mirror of
https://github.com/GreemDev/Ryujinx
synced 2024-11-26 19:52:31 +01:00
e36e97c64d
* 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 c117d9410d693185ff5f8ee8e457ffbfb2027dd5. * Address PR feedbacks.
113 lines
4 KiB
C#
113 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
|
|
}
|
|
}
|