Update CpuTest.cs

This commit is contained in:
LDj3SNuD 2018-09-28 20:16:13 +02:00 committed by GitHub
parent 0254a84f90
commit 9e0214aee0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -178,8 +178,30 @@ namespace Ryujinx.Tests.Cpu
return GetThreadState();
}
[Flags]
protected enum FPSR
/// <summary>Rounding Mode control field.</summary>
public enum RMode
{
/// <summary>Round to Nearest (RN) mode.</summary>
RN,
/// <summary>Round towards Plus Infinity (RP) mode.</summary>
RP,
/// <summary>Round towards Minus Infinity (RM) mode.</summary>
RM,
/// <summary>Round towards Zero (RZ) mode.</summary>
RZ
};
/// <summary>Floating-point Control Register.</summary>
protected enum FPCR
{
/// <summary>Rounding Mode control field.</summary>
RMode = 22,
/// <summary>Default NaN mode control bit.</summary>
DN = 25
}
/// <summary>Floating-point Status Register.</summary>
[Flags] protected enum FPSR
{
None = 0,
@ -199,28 +221,23 @@ namespace Ryujinx.Tests.Cpu
QC = 1 << 27
}
protected enum FpSkips { None, IfNaN_S, IfNaN_D };
[Flags] protected enum FpSkips { None = 0, IfNaN_S = 1, IfNaN_D = 2, IfUnderflow = 4, IfOverflow = 8 };
protected enum FpUseTolerance { None, OneUlps_S, OneUlps_D };
protected enum FpTolerances { None, UpToOneUlps_S, UpToOneUlps_D };
protected void CompareAgainstUnicorn(
FPSR FpsrMask = FPSR.None,
FpSkips FpSkips = FpSkips.None,
FpUseTolerance FpUseTolerance = FpUseTolerance.None)
FPSR FpsrMask = FPSR.None,
FpSkips FpSkips = FpSkips.None,
FpTolerances FpTolerances = FpTolerances.None)
{
if (!UnicornAvailable)
{
return;
}
if (FpSkips == FpSkips.IfNaN_S && float.IsNaN(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)))
if (FpSkips != FpSkips.None)
{
Assert.Ignore("NaN test.");
}
if (FpSkips == FpSkips.IfNaN_D && double.IsNaN(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)))
{
Assert.Ignore("NaN test.");
ManageFpSkips(FpSkips);
}
Assert.That(Thread.ThreadState.X0, Is.EqualTo(UnicornEmu.X[0]));
@ -257,50 +274,13 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Thread.ThreadState.X31, Is.EqualTo(UnicornEmu.SP));
if (FpUseTolerance == FpUseTolerance.None)
if (FpTolerances == FpTolerances.None)
{
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
}
else
{
if (!Is.EqualTo(UnicornEmu.Q[0]).ApplyTo(Thread.ThreadState.V0).IsSuccess)
{
if (FpUseTolerance == FpUseTolerance.OneUlps_S)
{
if (float.IsNormal (VectorExtractSingle(UnicornEmu.Q[0], (byte)0)) ||
float.IsSubnormal(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)))
{
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)0),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)1),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)1)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)2),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)2)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)3),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)3)).Within(1).Ulps);
}
else
{
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
}
}
if (FpUseTolerance == FpUseTolerance.OneUlps_D)
{
if (double.IsNormal (VectorExtractDouble(UnicornEmu.Q[0], (byte)0)) ||
double.IsSubnormal(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)))
{
Assert.That (VectorExtractDouble(Thread.ThreadState.V0, (byte)0),
Is.EqualTo(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)).Within(1).Ulps);
Assert.That (VectorExtractDouble(Thread.ThreadState.V0, (byte)1),
Is.EqualTo(VectorExtractDouble(UnicornEmu.Q[0], (byte)1)).Within(1).Ulps);
}
else
{
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
}
}
}
ManageFpTolerances(FpTolerances);
}
Assert.That(Thread.ThreadState.V1, Is.EqualTo(UnicornEmu.Q[1]));
Assert.That(Thread.ThreadState.V2, Is.EqualTo(UnicornEmu.Q[2]));
@ -344,6 +324,90 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Thread.ThreadState.Negative, Is.EqualTo(UnicornEmu.NegativeFlag));
}
private void ManageFpSkips(FpSkips FpSkips)
{
if (FpSkips.HasFlag(FpSkips.IfNaN_S))
{
if (float.IsNaN(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)))
{
Assert.Ignore("NaN test.");
}
}
else if (FpSkips.HasFlag(FpSkips.IfNaN_D))
{
if (double.IsNaN(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)))
{
Assert.Ignore("NaN test.");
}
}
if (FpSkips.HasFlag(FpSkips.IfUnderflow))
{
if ((UnicornEmu.Fpsr & (int)FPSR.UFC) != 0)
{
Assert.Ignore("Underflow test.");
}
}
if (FpSkips.HasFlag(FpSkips.IfOverflow))
{
if ((UnicornEmu.Fpsr & (int)FPSR.OFC) != 0)
{
Assert.Ignore("Overflow test.");
}
}
}
private void ManageFpTolerances(FpTolerances FpTolerances)
{
if (!Is.EqualTo(UnicornEmu.Q[0]).ApplyTo(Thread.ThreadState.V0).IsSuccess)
{
if (FpTolerances == FpTolerances.UpToOneUlps_S)
{
if (IsNormalOrSubnormal_S(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)) &&
IsNormalOrSubnormal_S(VectorExtractSingle(Thread.ThreadState.V0, (byte)0)))
{
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)0),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)0)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)1),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)1)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)2),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)2)).Within(1).Ulps);
Assert.That (VectorExtractSingle(Thread.ThreadState.V0, (byte)3),
Is.EqualTo(VectorExtractSingle(UnicornEmu.Q[0], (byte)3)).Within(1).Ulps);
Console.WriteLine(FpTolerances);
}
else
{
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
}
}
if (FpTolerances == FpTolerances.UpToOneUlps_D)
{
if (IsNormalOrSubnormal_D(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)) &&
IsNormalOrSubnormal_D(VectorExtractDouble(Thread.ThreadState.V0, (byte)0)))
{
Assert.That (VectorExtractDouble(Thread.ThreadState.V0, (byte)0),
Is.EqualTo(VectorExtractDouble(UnicornEmu.Q[0], (byte)0)).Within(1).Ulps);
Assert.That (VectorExtractDouble(Thread.ThreadState.V0, (byte)1),
Is.EqualTo(VectorExtractDouble(UnicornEmu.Q[0], (byte)1)).Within(1).Ulps);
Console.WriteLine(FpTolerances);
}
else
{
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
}
}
}
bool IsNormalOrSubnormal_S(float f) => float.IsNormal(f) || float.IsSubnormal(f);
bool IsNormalOrSubnormal_D(double d) => double.IsNormal(d) || double.IsSubnormal(d);
}
protected static Vector128<float> MakeVectorE0(double E0)
{
if (!Sse2.IsSupported)
@ -453,14 +517,14 @@ namespace Ryujinx.Tests.Cpu
{
uint Rnd;
do Rnd = TestContext.CurrentContext.Random.NextUInt();
while ((Rnd & 0x7F800000u) == 0u ||
(Rnd & 0x7F800000u) == 0x7F800000u);
do Rnd = TestContext.CurrentContext.Random.NextUInt();
while (( Rnd & 0x7F800000u) == 0u ||
(~Rnd & 0x7F800000u) == 0u);
return Rnd;
}
protected static uint GenSubNormal_S()
protected static uint GenSubnormal_S()
{
uint Rnd;
@ -474,14 +538,14 @@ namespace Ryujinx.Tests.Cpu
{
ulong Rnd;
do Rnd = TestContext.CurrentContext.Random.NextULong();
while ((Rnd & 0x7FF0000000000000ul) == 0ul ||
(Rnd & 0x7FF0000000000000ul) == 0x7FF0000000000000ul);
do Rnd = TestContext.CurrentContext.Random.NextULong();
while (( Rnd & 0x7FF0000000000000ul) == 0ul ||
(~Rnd & 0x7FF0000000000000ul) == 0ul);
return Rnd;
}
protected static ulong GenSubNormal_D()
protected static ulong GenSubnormal_D()
{
ulong Rnd;