diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs index 81fc265b73..0c4aa3b0e3 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs @@ -2,19 +2,101 @@ using NUnit.Framework; +using System.Collections.Generic; + namespace Ryujinx.Tests.Cpu { [Category("Alu")] public sealed class CpuTestAlu : CpuTest { #if Alu + +#region "Helper methods" + private static uint GenLeadingSignsMinus32(int cnt) // 0 <= cnt <= 31 + { + return ~GenLeadingZeros32(cnt + 1); + } + + private static ulong GenLeadingSignsMinus64(int cnt) // 0 <= cnt <= 63 + { + return ~GenLeadingZeros64(cnt + 1); + } + + private static uint GenLeadingSignsPlus32(int cnt) // 0 <= cnt <= 31 + { + return GenLeadingZeros32(cnt + 1); + } + + private static ulong GenLeadingSignsPlus64(int cnt) // 0 <= cnt <= 63 + { + return GenLeadingZeros64(cnt + 1); + } + + private static uint GenLeadingZeros32(int cnt) // 0 <= cnt <= 32 + { + if (cnt == 32) return 0u; + if (cnt == 31) return 1u; + + uint rnd = TestContext.CurrentContext.Random.NextUInt(); + int mask = int.MinValue; + + return (rnd >> (cnt + 1)) | ((uint)mask >> cnt); + } + + private static ulong GenLeadingZeros64(int cnt) // 0 <= cnt <= 64 + { + if (cnt == 64) return 0ul; + if (cnt == 63) return 1ul; + + ulong rnd = TestContext.CurrentContext.Random.NextULong(); + long mask = long.MinValue; + + return (rnd >> (cnt + 1)) | ((ulong)mask >> cnt); + } +#endregion + +#region "ValueSource (Types)" + private static IEnumerable _GenLeadingSignsX_() + { + for (int cnt = 0; cnt <= 63; cnt++) + { + yield return GenLeadingSignsMinus64(cnt); + yield return GenLeadingSignsPlus64(cnt); + } + } + + private static IEnumerable _GenLeadingSignsW_() + { + for (int cnt = 0; cnt <= 31; cnt++) + { + yield return GenLeadingSignsMinus32(cnt); + yield return GenLeadingSignsPlus32(cnt); + } + } + + private static IEnumerable _GenLeadingZerosX_() + { + for (int cnt = 0; cnt <= 64; cnt++) + { + yield return GenLeadingZeros64(cnt); + } + } + + private static IEnumerable _GenLeadingZerosW_() + { + for (int cnt = 0; cnt <= 32; cnt++) + { + yield return GenLeadingZeros32(cnt); + } + } +#endregion + private const int RndCnt = 2; [Test, Pairwise, Description("CLS , ")] public void Cls_64bit([Values(0u, 31u)] uint rd, [Values(1u, 31u)] uint rn, - [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, - 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn) + [ValueSource("_GenLeadingSignsX_")] [Random(RndCnt)] ulong xn) { uint opcode = 0xDAC01400; // CLS X0, X0 opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); @@ -29,8 +111,7 @@ namespace Ryujinx.Tests.Cpu [Test, Pairwise, Description("CLS , ")] public void Cls_32bit([Values(0u, 31u)] uint rd, [Values(1u, 31u)] uint rn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn) + [ValueSource("_GenLeadingSignsW_")] [Random(RndCnt)] uint wn) { uint opcode = 0x5AC01400; // CLS W0, W0 opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); @@ -45,8 +126,7 @@ namespace Ryujinx.Tests.Cpu [Test, Pairwise, Description("CLZ , ")] public void Clz_64bit([Values(0u, 31u)] uint rd, [Values(1u, 31u)] uint rn, - [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, - 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn) + [ValueSource("_GenLeadingZerosX_")] [Random(RndCnt)] ulong xn) { uint opcode = 0xDAC01000; // CLZ X0, X0 opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); @@ -61,8 +141,7 @@ namespace Ryujinx.Tests.Cpu [Test, Pairwise, Description("CLZ , ")] public void Clz_32bit([Values(0u, 31u)] uint rd, [Values(1u, 31u)] uint rn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn) + [ValueSource("_GenLeadingZerosW_")] [Random(RndCnt)] uint wn) { uint opcode = 0x5AC01000; // CLZ W0, W0 opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);