Ryujinx/Ryujinx.Tests/Cpu/CpuTestMisc32.cs
LDj3SNuD e36e97c64d
CPU: This PR fixes Fpscr, among other things. (#1433)
* CPU: This PR fixes Fpscr, among other things.

* Add Fpscr.Qc = 1 if sat. for Vqrshrn & Vqrshrun.

* Fix Vcmp & Vcmpe opcode table.

* Revert "Fix Vcmp & Vcmpe opcode table."

This reverts commit c117d9410d.

* Address PR feedbacks.
2020-08-08 17:18:51 +02:00

114 lines
4 KiB
C#

#define Misc32
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
{
[Category("Misc32")]
public sealed class CpuTestMisc32 : CpuTest32
{
#if Misc32
#region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_()
{
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
yield return 0x0000000080800000ul; // -Min Normal
yield return 0x00000000807FFFFFul; // -Max Subnormal
yield return 0x0000000080000001ul; // -Min Subnormal (-float.Epsilon)
yield return 0x000000007F7FFFFFul; // +Max Normal (float.MaxValue)
yield return 0x0000000000800000ul; // +Min Normal
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
yield return 0x000000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN)
yield return 0x000000007FBFFFFFul; // +SNaN (all ones payload)
}
for (int cnt = 1; cnt <= RndCnt; cnt++)
{
ulong grbg = TestContext.CurrentContext.Random.NextUInt();
ulong rnd1 = GenNormalS();
ulong rnd2 = GenSubnormalS();
yield return (grbg << 32) | rnd1;
yield return (grbg << 32) | rnd2;
}
}
#endregion
private const int RndCnt = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
[Test, Pairwise]
public void Vmsr_Vcmp_Vmrs([ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
[Values] bool mode1,
[Values] bool mode2,
[Values] bool mode3)
{
V128 v4 = MakeVectorE0(a);
V128 v5 = MakeVectorE0(b);
uint r0 = mode1
? TestContext.CurrentContext.Random.NextUInt(0xf) << 28
: TestContext.CurrentContext.Random.NextUInt();
bool v = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
bool c = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
bool z = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
bool n = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
int fpscr = mode1
? (int)TestContext.CurrentContext.Random.NextUInt()
: (int)TestContext.CurrentContext.Random.NextUInt(0xf) << 28;
SetContext(r0: r0, v4: v4, v5: v5, overflow: v, carry: c, zero: z, negative: n, fpscr: fpscr);
if (mode1)
{
Opcode(0xEEE10A10); // VMSR FPSCR, R0
}
Opcode(0xEEB48A4A); // VCMP.F32 S16, S20
if (mode2)
{
Opcode(0xEEF10A10); // VMRS R0, FPSCR
Opcode(0xE200020F); // AND R0, #0xF0000000 // R0 &= "Fpsr.Nzcv".
}
if (mode3)
{
Opcode(0xEEF1FA10); // VMRS APSR_NZCV, FPSCR
}
Opcode(0xE12FFF1E); // BX LR
ExecuteOpcodes();
CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv);
}
#endif
}
}