Compare commits

...

3 Commits

Author SHA1 Message Date
TSRBerry
79a1314ee4 [Ryujinx.Cpu] Address dotnet-format issues (#5365)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0052 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address most dotnet format whitespace warnings

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Remove a few unused parameters

* Adjust namespaces

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Start working on disabled warnings

* Fix and silence a few dotnet-format warnings again

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Address review feedback

* Remove redundant unsafe modifiers

* Fix build issues

* Add GC.SuppressFinalize() call

* Add trailing commas and fix naming rule violations

* Remove unused members and assignments
2023-07-01 02:18:52 +00:00
TSRBerry
e9848339dd [Ryujinx.Tests] Address dotnet-format issues (#5389)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Fix new dotnet-format issues after rebase

* Address review comments

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* cpu tests: Disable CA2211 for CodeBaseAddress and DataBaseAddress

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Apply suggestions from code review

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* First dotnet format pass

* Fix naming rule violations

* Remove naming rule violation exceptions

* Fix comment style

* Use targeted new

* Remove redundant code

* Remove comment alignment

* Remove naming rule exceptions

* Add trailing commas

* Use nameof expression

* Reformat to add remaining trailing commas

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-07-01 02:14:34 +00:00
TSRBerry
6e28a4dd13 [Ryujinx.Ui.Common] Address dotnet-format issues (#5392)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Silence dotnet format IDE0060 warnings

* Address dotnet format CA1401 warnings

* dotnet-format fixes after rebase

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Another rebase, another dotnet format run

* Run dotnet format style after rebase

* Add comments to disabled warnings

* Remove a few unused parameters

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Address IDE0251 warnings

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Small optimizations

* Remove alignment

* Apply formatting

* Fix build issues

* Final pass for dotnet format

* Add trailing commas

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Add trailing commas

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-06-29 02:39:22 +02:00
134 changed files with 3407 additions and 3019 deletions

View File

@@ -32,6 +32,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
@@ -692,7 +693,7 @@ namespace Ryujinx.Ava
DiscordIntegrationModule.SwitchToPlayingState(Device.Processes.ActiveApplication.ProgramIdText, Device.Processes.ActiveApplication.Name); DiscordIntegrationModule.SwitchToPlayingState(Device.Processes.ActiveApplication.ProgramIdText, Device.Processes.ActiveApplication.Name);
_viewModel.ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata => ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata =>
{ {
appMetadata.LastPlayed = DateTime.UtcNow; appMetadata.LastPlayed = DateTime.UtcNow;
}); });

View File

@@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Controls
{ {
viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite; viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite;
viewModel.ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.TitleId, appMetadata => ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.TitleId, appMetadata =>
{ {
appMetadata.Favorite = viewModel.SelectedApplication.Favorite; appMetadata.Favorite = viewModel.SelectedApplication.Favorite;
}); });

View File

@@ -3,6 +3,7 @@ using LibHac.Ncm;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.Ui.App.Common;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -74,7 +75,7 @@ namespace Ryujinx.Ava.UI.Models
} }
else else
{ {
var appMetadata = MainWindow.MainWindowViewModel.ApplicationLibrary.LoadAndSaveMetaData(TitleIdString); var appMetadata = ApplicationLibrary.LoadAndSaveMetaData(TitleIdString);
Title = appMetadata.Title ?? TitleIdString; Title = appMetadata.Title ?? TitleIdString;
} }

View File

@@ -239,28 +239,28 @@ namespace Ryujinx.Ava.UI.Renderer
IPlatformHandle CreateMacOS() IPlatformHandle CreateMacOS()
{ {
// Create a new CAMetalLayer. // Create a new CAMetalLayer.
IntPtr layerClass = ObjectiveC.objc_getClass("CAMetalLayer"); ObjectiveC.Object layerObject = new("CAMetalLayer");
IntPtr metalLayer = ObjectiveC.IntPtr_objc_msgSend(layerClass, "alloc"); ObjectiveC.Object metalLayer = layerObject.GetFromMessage("alloc");
ObjectiveC.objc_msgSend(metalLayer, "init"); metalLayer.SendMessage("init");
// Create a child NSView to render into. // Create a child NSView to render into.
IntPtr nsViewClass = ObjectiveC.objc_getClass("NSView"); ObjectiveC.Object nsViewObject = new("NSView");
IntPtr child = ObjectiveC.IntPtr_objc_msgSend(nsViewClass, "alloc"); ObjectiveC.Object child = nsViewObject.GetFromMessage("alloc");
ObjectiveC.objc_msgSend(child, "init", new ObjectiveC.NSRect(0, 0, 0, 0)); child.SendMessage("init", new ObjectiveC.NSRect(0, 0, 0, 0));
// Make its renderer our metal layer. // Make its renderer our metal layer.
ObjectiveC.objc_msgSend(child, "setWantsLayer:", 1); child.SendMessage("setWantsLayer:", 1);
ObjectiveC.objc_msgSend(child, "setLayer:", metalLayer); child.SendMessage("setLayer:", metalLayer);
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor); metalLayer.SendMessage("setContentsScale:", Program.DesktopScaleFactor);
// Ensure the scale factor is up to date. // Ensure the scale factor is up to date.
_updateBoundsCallback = rect => _updateBoundsCallback = rect =>
{ {
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor); metalLayer.SendMessage("setContentsScale:", Program.DesktopScaleFactor);
}; };
IntPtr nsView = child; IntPtr nsView = child.ObjPtr;
MetalLayer = metalLayer; MetalLayer = metalLayer.ObjPtr;
NsView = nsView; NsView = nsView;
return new PlatformHandle(nsView, "NSView"); return new PlatformHandle(nsView, "NSView");

View File

@@ -7,15 +7,13 @@ namespace Ryujinx.Cpu
{ {
public class AddressSpace : IDisposable public class AddressSpace : IDisposable
{ {
private const ulong PageSize = 0x1000;
private const int DefaultBlockAlignment = 1 << 20; private const int DefaultBlockAlignment = 1 << 20;
private enum MappingType : byte private enum MappingType : byte
{ {
None, None,
Private, Private,
Shared Shared,
} }
private class Mapping : IntrusiveRedBlackTreeNode<Mapping>, IComparable<Mapping> private class Mapping : IntrusiveRedBlackTreeNode<Mapping>, IComparable<Mapping>
@@ -37,7 +35,7 @@ namespace Ryujinx.Cpu
ulong leftSize = splitAddress - Address; ulong leftSize = splitAddress - Address;
ulong rightSize = EndAddress - splitAddress; ulong rightSize = EndAddress - splitAddress;
Mapping left = new Mapping(Address, leftSize, Type); Mapping left = new(Address, leftSize, Type);
Address = splitAddress; Address = splitAddress;
Size = rightSize; Size = rightSize;
@@ -93,7 +91,7 @@ namespace Ryujinx.Cpu
(var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize); (var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
PrivateMapping left = new PrivateMapping(Address, leftSize, leftAllocation); PrivateMapping left = new(Address, leftSize, leftAllocation);
Address = splitAddress; Address = splitAddress;
Size = rightSize; Size = rightSize;
@@ -181,7 +179,7 @@ namespace Ryujinx.Cpu
{ {
addressSpace = null; addressSpace = null;
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible; const MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36); ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
@@ -391,8 +389,6 @@ namespace Ryujinx.Cpu
ulong vaAligned = BitUtils.AlignDown(va, alignment); ulong vaAligned = BitUtils.AlignDown(va, alignment);
ulong endAddressAligned = BitUtils.AlignUp(endAddress, alignment); ulong endAddressAligned = BitUtils.AlignUp(endAddress, alignment);
ulong sizeAligned = endAddressAligned - vaAligned;
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default)); PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
for (; map != null; map = map.Successor) for (; map != null; map = map.Successor)
@@ -436,8 +432,6 @@ namespace Ryujinx.Cpu
return; return;
} }
ulong alignedSize = endAddressAligned - vaAligned;
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default)); PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
for (; map != null; map = map.Successor) for (; map != null; map = map.Successor)
@@ -495,9 +489,11 @@ namespace Ryujinx.Cpu
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
_privateMemoryAllocator?.Dispose(); _privateMemoryAllocator?.Dispose();
Base.Dispose(); Base.Dispose();
Mirror.Dispose(); Mirror.Dispose();
} }
} }
} }

View File

@@ -42,6 +42,6 @@ namespace Ryujinx.Cpu.AppleHv.Arm
WatchpointSameEl = 0b110101, WatchpointSameEl = 0b110101,
BkptAarch32 = 0b111000, BkptAarch32 = 0b111000,
VectorCatchAarch32 = 0b111010, VectorCatchAarch32 = 0b111010,
BrkAarch64 = 0b111100 BrkAarch64 = 0b111100,
} }
} }

View File

@@ -4,7 +4,7 @@ namespace Ryujinx.Cpu.AppleHv
{ {
public class DummyDiskCacheLoadState : IDiskCacheLoadState public class DummyDiskCacheLoadState : IDiskCacheLoadState
{ {
#pragma warning disable CS0067 #pragma warning disable CS0067 // The event is never used
/// <inheritdoc/> /// <inheritdoc/>
public event Action<LoadState, int, int> StateChanged; public event Action<LoadState, int, int> StateChanged;
#pragma warning restore CS0067 #pragma warning restore CS0067
@@ -14,4 +14,4 @@ namespace Ryujinx.Cpu.AppleHv
{ {
} }
} }
} }

View File

@@ -18,18 +18,16 @@ namespace Ryujinx.Cpu.AppleHv
private const ulong AllocationGranule = 1UL << 14; private const ulong AllocationGranule = 1UL << 14;
private readonly ulong _asBase; private readonly ulong _asBase;
private readonly ulong _asSize;
private readonly ulong _backingSize; private readonly ulong _backingSize;
private readonly HvAddressSpaceRange _userRange; private readonly HvAddressSpaceRange _userRange;
private readonly HvAddressSpaceRange _kernelRange; private readonly HvAddressSpaceRange _kernelRange;
private MemoryBlock _kernelCodeBlock; private readonly MemoryBlock _kernelCodeBlock;
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize) public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
{ {
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory); (_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
_asSize = asSize;
_backingSize = backingMemory.Size; _backingSize = backingMemory.Size;
_userRange = new HvAddressSpaceRange(ipaAllocator); _userRange = new HvAddressSpaceRange(ipaAllocator);
@@ -58,20 +56,20 @@ namespace Ryujinx.Cpu.AppleHv
_kernelCodeBlock.Write(KernelRegionEretOffset, 0xD69F03E0u); // ERET _kernelCodeBlock.Write(KernelRegionEretOffset, 0xD69F03E0u); // ERET
ulong kernelCodePa = ipaAllocator.Allocate(AllocationGranule); ulong kernelCodePa = ipaAllocator.Allocate(AllocationGranule);
HvApi.hv_vm_map((ulong)_kernelCodeBlock.Pointer, kernelCodePa, AllocationGranule, hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_EXEC).ThrowOnError(); HvApi.hv_vm_map((ulong)_kernelCodeBlock.Pointer, kernelCodePa, AllocationGranule, HvMemoryFlags.Read | HvMemoryFlags.Exec).ThrowOnError();
_kernelRange.Map(KernelRegionCodeOffset, kernelCodePa, KernelRegionCodeSize, ApFlags.UserNoneKernelReadExecute); _kernelRange.Map(KernelRegionCodeOffset, kernelCodePa, KernelRegionCodeSize, ApFlags.UserNoneKernelReadExecute);
} }
public void InitializeMmu(ulong vcpu) public void InitializeMmu(ulong vcpu)
{ {
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_VBAR_EL1, KernelRegionBase + KernelRegionCodeOffset); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.VBAR_EL1, KernelRegionBase + KernelRegionCodeOffset);
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TTBR0_EL1, _userRange.GetIpaBase()); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TTBR0_EL1, _userRange.GetIpaBase());
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TTBR1_EL1, _kernelRange.GetIpaBase()); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TTBR1_EL1, _kernelRange.GetIpaBase());
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_MAIR_EL1, 0xffUL); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.MAIR_EL1, 0xffUL);
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TCR_EL1, 0x00000011B5193519UL); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TCR_EL1, 0x00000011B5193519UL);
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_SCTLR_EL1, 0x0000000034D5D925UL); HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.SCTLR_EL1, 0x0000000034D5D925UL);
} }
public bool GetAndClearUserTlbInvalidationPending() public bool GetAndClearUserTlbInvalidationPending()
@@ -115,7 +113,7 @@ namespace Ryujinx.Cpu.AppleHv
MemoryPermission.ReadAndWrite => ApFlags.UserReadWriteKernelReadWrite, MemoryPermission.ReadAndWrite => ApFlags.UserReadWriteKernelReadWrite,
MemoryPermission.ReadAndExecute => ApFlags.UserReadExecuteKernelRead, MemoryPermission.ReadAndExecute => ApFlags.UserReadExecuteKernelRead,
MemoryPermission.ReadWriteExecute => ApFlags.UserReadWriteExecuteKernelReadWrite, MemoryPermission.ReadWriteExecute => ApFlags.UserReadWriteExecuteKernelReadWrite,
_ => throw new ArgumentException($"Permission \"{permission}\" is invalid.") _ => throw new ArgumentException($"Permission \"{permission}\" is invalid."),
}; };
} }
@@ -126,4 +124,4 @@ namespace Ryujinx.Cpu.AppleHv
HvVm.DestroyAddressSpace(_asBase, _backingSize); HvVm.DestroyAddressSpace(_asBase, _backingSize);
} }
} }
} }

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Cpu.AppleHv
ulong size = (ulong)count * sizeof(ulong); ulong size = (ulong)count * sizeof(ulong);
Allocation = blockAllocator.Allocate(size, PageSize); Allocation = blockAllocator.Allocate(size, PageSize);
AsSpan().Fill(0UL); AsSpan().Clear();
if (hasNext) if (hasNext)
{ {
@@ -42,7 +42,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
public unsafe Span<ulong> AsSpan() public Span<ulong> AsSpan()
{ {
return MemoryMarshal.Cast<byte, ulong>(Allocation.Memory.GetSpan(Allocation.Offset, (int)Allocation.Size)); return MemoryMarshal.Cast<byte, ulong>(Allocation.Memory.GetSpan(Allocation.Offset, (int)Allocation.Size));
} }
@@ -52,12 +52,10 @@ namespace Ryujinx.Cpu.AppleHv
private int _tlbInvalidationPending; private int _tlbInvalidationPending;
private readonly HvIpaAllocator _ipaAllocator;
private readonly HvMemoryBlockAllocator _blockAllocator; private readonly HvMemoryBlockAllocator _blockAllocator;
public HvAddressSpaceRange(HvIpaAllocator ipaAllocator) public HvAddressSpaceRange(HvIpaAllocator ipaAllocator)
{ {
_ipaAllocator = ipaAllocator;
_blockAllocator = new HvMemoryBlockAllocator(ipaAllocator, (int)AllocationGranule); _blockAllocator = new HvMemoryBlockAllocator(ipaAllocator, (int)AllocationGranule);
} }
@@ -129,7 +127,7 @@ namespace Ryujinx.Cpu.AppleHv
ulong endVa = (va + size + PageMask) & ~((ulong)PageMask); ulong endVa = (va + size + PageMask) & ~((ulong)PageMask);
va &= ~((ulong)PageMask); va &= ~((ulong)PageMask);
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth); (ulong blockSize, _) = GetBlockSizeAndShift(depth);
while (va < endVa) while (va < endVa)
{ {
@@ -138,7 +136,7 @@ namespace Ryujinx.Cpu.AppleHv
int l = (int)(va >> (PageBits + (2 - depth) * LevelBits)) & LevelMask; int l = (int)(va >> (PageBits + (2 - depth) * LevelBits)) & LevelMask;
PtLevel nextTable = level.Next != null ? level.Next[l] : null; PtLevel nextTable = level.Next?[l];
if (nextTable != null) if (nextTable != null)
{ {
@@ -190,7 +188,7 @@ namespace Ryujinx.Cpu.AppleHv
ulong endVa = (va + size + PageSize - 1) & ~((ulong)PageSize - 1); ulong endVa = (va + size + PageSize - 1) & ~((ulong)PageSize - 1);
va &= ~((ulong)PageSize - 1); va &= ~((ulong)PageSize - 1);
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth); (ulong blockSize, _) = GetBlockSizeAndShift(depth);
while (va < endVa) while (va < endVa)
{ {
@@ -204,7 +202,7 @@ namespace Ryujinx.Cpu.AppleHv
// First check if the region is mapped. // First check if the region is mapped.
if ((pte & 3) != 0) if ((pte & 3) != 0)
{ {
PtLevel nextTable = level.Next != null ? level.Next[l] : null; PtLevel nextTable = level.Next?[l];
if (nextTable != null) if (nextTable != null)
{ {
@@ -240,10 +238,10 @@ namespace Ryujinx.Cpu.AppleHv
pte &= ~3UL; pte &= ~3UL;
pte |= (depth == 2 ? 3UL : 1UL); pte |= (depth == 2 ? 3UL : 1UL);
PtLevel level = new PtLevel(_blockAllocator, LevelCount, depth < 2); PtLevel level = new(_blockAllocator, LevelCount, depth < 2);
Span<ulong> currentLevel = level.AsSpan(); Span<ulong> currentLevel = level.AsSpan();
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth); (_, int blockShift) = GetBlockSizeAndShift(depth);
// Fill in the blocks. // Fill in the blocks.
for (int i = 0; i < LevelCount; i++) for (int i = 0; i < LevelCount; i++)
@@ -334,7 +332,7 @@ namespace Ryujinx.Cpu.AppleHv
if ((currentTable[index] & 1) == 0) if ((currentTable[index] & 1) == 0)
{ {
PtLevel nextLevel = new PtLevel(_blockAllocator, LevelCount, hasNext); PtLevel nextLevel = new(_blockAllocator, LevelCount, hasNext);
currentTable[index] = (nextLevel.Address & ~(ulong)PageMask) | 3UL; currentTable[index] = (nextLevel.Address & ~(ulong)PageMask) | 3UL;
level.Next[index] = nextLevel; level.Next[index] = nextLevel;
@@ -347,7 +345,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
private void WriteBlock(PtLevel level, int index, int depth, ulong pa, ulong attr) private static void WriteBlock(PtLevel level, int index, int depth, ulong pa, ulong attr)
{ {
Span<ulong> currentTable = level.AsSpan(); Span<ulong> currentTable = level.AsSpan();
@@ -367,4 +365,4 @@ namespace Ryujinx.Cpu.AppleHv
_blockAllocator.Dispose(); _blockAllocator.Dispose();
} }
} }
} }

View File

@@ -1,245 +1,244 @@
using ARMeilleure.State;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
struct hv_vcpu_exit_exception_t struct HvVcpuExitException
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649 // Field is never assigned to
public ulong syndrome; public ulong Syndrome;
public ulong virtual_address; public ulong VirtualAddress;
public ulong physical_address; public ulong PhysicalAddress;
#pragma warning restore CS0649 #pragma warning restore CS0649
} }
struct hv_vcpu_exit_t struct HvVcpuExit
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649 // Field is never assigned to
public uint reason; public uint Reason;
public hv_vcpu_exit_exception_t exception; public HvVcpuExitException Exception;
#pragma warning restore CS0649 #pragma warning restore CS0649
} }
enum hv_reg_t : uint enum HvReg : uint
{ {
HV_REG_X0, X0,
HV_REG_X1, X1,
HV_REG_X2, X2,
HV_REG_X3, X3,
HV_REG_X4, X4,
HV_REG_X5, X5,
HV_REG_X6, X6,
HV_REG_X7, X7,
HV_REG_X8, X8,
HV_REG_X9, X9,
HV_REG_X10, X10,
HV_REG_X11, X11,
HV_REG_X12, X12,
HV_REG_X13, X13,
HV_REG_X14, X14,
HV_REG_X15, X15,
HV_REG_X16, X16,
HV_REG_X17, X17,
HV_REG_X18, X18,
HV_REG_X19, X19,
HV_REG_X20, X20,
HV_REG_X21, X21,
HV_REG_X22, X22,
HV_REG_X23, X23,
HV_REG_X24, X24,
HV_REG_X25, X25,
HV_REG_X26, X26,
HV_REG_X27, X27,
HV_REG_X28, X28,
HV_REG_X29, X29,
HV_REG_FP = HV_REG_X29, FP = X29,
HV_REG_X30, X30,
HV_REG_LR = HV_REG_X30, LR = X30,
HV_REG_PC, PC,
HV_REG_FPCR, FPCR,
HV_REG_FPSR, FPSR,
HV_REG_CPSR, CPSR,
} }
enum hv_simd_fp_reg_t : uint enum HvSimdFPReg : uint
{ {
HV_SIMD_FP_REG_Q0, Q0,
HV_SIMD_FP_REG_Q1, Q1,
HV_SIMD_FP_REG_Q2, Q2,
HV_SIMD_FP_REG_Q3, Q3,
HV_SIMD_FP_REG_Q4, Q4,
HV_SIMD_FP_REG_Q5, Q5,
HV_SIMD_FP_REG_Q6, Q6,
HV_SIMD_FP_REG_Q7, Q7,
HV_SIMD_FP_REG_Q8, Q8,
HV_SIMD_FP_REG_Q9, Q9,
HV_SIMD_FP_REG_Q10, Q10,
HV_SIMD_FP_REG_Q11, Q11,
HV_SIMD_FP_REG_Q12, Q12,
HV_SIMD_FP_REG_Q13, Q13,
HV_SIMD_FP_REG_Q14, Q14,
HV_SIMD_FP_REG_Q15, Q15,
HV_SIMD_FP_REG_Q16, Q16,
HV_SIMD_FP_REG_Q17, Q17,
HV_SIMD_FP_REG_Q18, Q18,
HV_SIMD_FP_REG_Q19, Q19,
HV_SIMD_FP_REG_Q20, Q20,
HV_SIMD_FP_REG_Q21, Q21,
HV_SIMD_FP_REG_Q22, Q22,
HV_SIMD_FP_REG_Q23, Q23,
HV_SIMD_FP_REG_Q24, Q24,
HV_SIMD_FP_REG_Q25, Q25,
HV_SIMD_FP_REG_Q26, Q26,
HV_SIMD_FP_REG_Q27, Q27,
HV_SIMD_FP_REG_Q28, Q28,
HV_SIMD_FP_REG_Q29, Q29,
HV_SIMD_FP_REG_Q30, Q30,
HV_SIMD_FP_REG_Q31, Q31,
} }
enum hv_sys_reg_t : ushort enum HvSysReg : ushort
{ {
HV_SYS_REG_DBGBVR0_EL1 = 0x8004, DBGBVR0_EL1 = 0x8004,
HV_SYS_REG_DBGBCR0_EL1 = 0x8005, DBGBCR0_EL1 = 0x8005,
HV_SYS_REG_DBGWVR0_EL1 = 0x8006, DBGWVR0_EL1 = 0x8006,
HV_SYS_REG_DBGWCR0_EL1 = 0x8007, DBGWCR0_EL1 = 0x8007,
HV_SYS_REG_DBGBVR1_EL1 = 0x800c, DBGBVR1_EL1 = 0x800c,
HV_SYS_REG_DBGBCR1_EL1 = 0x800d, DBGBCR1_EL1 = 0x800d,
HV_SYS_REG_DBGWVR1_EL1 = 0x800e, DBGWVR1_EL1 = 0x800e,
HV_SYS_REG_DBGWCR1_EL1 = 0x800f, DBGWCR1_EL1 = 0x800f,
HV_SYS_REG_MDCCINT_EL1 = 0x8010, MDCCINT_EL1 = 0x8010,
HV_SYS_REG_MDSCR_EL1 = 0x8012, MDSCR_EL1 = 0x8012,
HV_SYS_REG_DBGBVR2_EL1 = 0x8014, DBGBVR2_EL1 = 0x8014,
HV_SYS_REG_DBGBCR2_EL1 = 0x8015, DBGBCR2_EL1 = 0x8015,
HV_SYS_REG_DBGWVR2_EL1 = 0x8016, DBGWVR2_EL1 = 0x8016,
HV_SYS_REG_DBGWCR2_EL1 = 0x8017, DBGWCR2_EL1 = 0x8017,
HV_SYS_REG_DBGBVR3_EL1 = 0x801c, DBGBVR3_EL1 = 0x801c,
HV_SYS_REG_DBGBCR3_EL1 = 0x801d, DBGBCR3_EL1 = 0x801d,
HV_SYS_REG_DBGWVR3_EL1 = 0x801e, DBGWVR3_EL1 = 0x801e,
HV_SYS_REG_DBGWCR3_EL1 = 0x801f, DBGWCR3_EL1 = 0x801f,
HV_SYS_REG_DBGBVR4_EL1 = 0x8024, DBGBVR4_EL1 = 0x8024,
HV_SYS_REG_DBGBCR4_EL1 = 0x8025, DBGBCR4_EL1 = 0x8025,
HV_SYS_REG_DBGWVR4_EL1 = 0x8026, DBGWVR4_EL1 = 0x8026,
HV_SYS_REG_DBGWCR4_EL1 = 0x8027, DBGWCR4_EL1 = 0x8027,
HV_SYS_REG_DBGBVR5_EL1 = 0x802c, DBGBVR5_EL1 = 0x802c,
HV_SYS_REG_DBGBCR5_EL1 = 0x802d, DBGBCR5_EL1 = 0x802d,
HV_SYS_REG_DBGWVR5_EL1 = 0x802e, DBGWVR5_EL1 = 0x802e,
HV_SYS_REG_DBGWCR5_EL1 = 0x802f, DBGWCR5_EL1 = 0x802f,
HV_SYS_REG_DBGBVR6_EL1 = 0x8034, DBGBVR6_EL1 = 0x8034,
HV_SYS_REG_DBGBCR6_EL1 = 0x8035, DBGBCR6_EL1 = 0x8035,
HV_SYS_REG_DBGWVR6_EL1 = 0x8036, DBGWVR6_EL1 = 0x8036,
HV_SYS_REG_DBGWCR6_EL1 = 0x8037, DBGWCR6_EL1 = 0x8037,
HV_SYS_REG_DBGBVR7_EL1 = 0x803c, DBGBVR7_EL1 = 0x803c,
HV_SYS_REG_DBGBCR7_EL1 = 0x803d, DBGBCR7_EL1 = 0x803d,
HV_SYS_REG_DBGWVR7_EL1 = 0x803e, DBGWVR7_EL1 = 0x803e,
HV_SYS_REG_DBGWCR7_EL1 = 0x803f, DBGWCR7_EL1 = 0x803f,
HV_SYS_REG_DBGBVR8_EL1 = 0x8044, DBGBVR8_EL1 = 0x8044,
HV_SYS_REG_DBGBCR8_EL1 = 0x8045, DBGBCR8_EL1 = 0x8045,
HV_SYS_REG_DBGWVR8_EL1 = 0x8046, DBGWVR8_EL1 = 0x8046,
HV_SYS_REG_DBGWCR8_EL1 = 0x8047, DBGWCR8_EL1 = 0x8047,
HV_SYS_REG_DBGBVR9_EL1 = 0x804c, DBGBVR9_EL1 = 0x804c,
HV_SYS_REG_DBGBCR9_EL1 = 0x804d, DBGBCR9_EL1 = 0x804d,
HV_SYS_REG_DBGWVR9_EL1 = 0x804e, DBGWVR9_EL1 = 0x804e,
HV_SYS_REG_DBGWCR9_EL1 = 0x804f, DBGWCR9_EL1 = 0x804f,
HV_SYS_REG_DBGBVR10_EL1 = 0x8054, DBGBVR10_EL1 = 0x8054,
HV_SYS_REG_DBGBCR10_EL1 = 0x8055, DBGBCR10_EL1 = 0x8055,
HV_SYS_REG_DBGWVR10_EL1 = 0x8056, DBGWVR10_EL1 = 0x8056,
HV_SYS_REG_DBGWCR10_EL1 = 0x8057, DBGWCR10_EL1 = 0x8057,
HV_SYS_REG_DBGBVR11_EL1 = 0x805c, DBGBVR11_EL1 = 0x805c,
HV_SYS_REG_DBGBCR11_EL1 = 0x805d, DBGBCR11_EL1 = 0x805d,
HV_SYS_REG_DBGWVR11_EL1 = 0x805e, DBGWVR11_EL1 = 0x805e,
HV_SYS_REG_DBGWCR11_EL1 = 0x805f, DBGWCR11_EL1 = 0x805f,
HV_SYS_REG_DBGBVR12_EL1 = 0x8064, DBGBVR12_EL1 = 0x8064,
HV_SYS_REG_DBGBCR12_EL1 = 0x8065, DBGBCR12_EL1 = 0x8065,
HV_SYS_REG_DBGWVR12_EL1 = 0x8066, DBGWVR12_EL1 = 0x8066,
HV_SYS_REG_DBGWCR12_EL1 = 0x8067, DBGWCR12_EL1 = 0x8067,
HV_SYS_REG_DBGBVR13_EL1 = 0x806c, DBGBVR13_EL1 = 0x806c,
HV_SYS_REG_DBGBCR13_EL1 = 0x806d, DBGBCR13_EL1 = 0x806d,
HV_SYS_REG_DBGWVR13_EL1 = 0x806e, DBGWVR13_EL1 = 0x806e,
HV_SYS_REG_DBGWCR13_EL1 = 0x806f, DBGWCR13_EL1 = 0x806f,
HV_SYS_REG_DBGBVR14_EL1 = 0x8074, DBGBVR14_EL1 = 0x8074,
HV_SYS_REG_DBGBCR14_EL1 = 0x8075, DBGBCR14_EL1 = 0x8075,
HV_SYS_REG_DBGWVR14_EL1 = 0x8076, DBGWVR14_EL1 = 0x8076,
HV_SYS_REG_DBGWCR14_EL1 = 0x8077, DBGWCR14_EL1 = 0x8077,
HV_SYS_REG_DBGBVR15_EL1 = 0x807c, DBGBVR15_EL1 = 0x807c,
HV_SYS_REG_DBGBCR15_EL1 = 0x807d, DBGBCR15_EL1 = 0x807d,
HV_SYS_REG_DBGWVR15_EL1 = 0x807e, DBGWVR15_EL1 = 0x807e,
HV_SYS_REG_DBGWCR15_EL1 = 0x807f, DBGWCR15_EL1 = 0x807f,
HV_SYS_REG_MIDR_EL1 = 0xc000, MIDR_EL1 = 0xc000,
HV_SYS_REG_MPIDR_EL1 = 0xc005, MPIDR_EL1 = 0xc005,
HV_SYS_REG_ID_AA64PFR0_EL1 = 0xc020, ID_AA64PFR0_EL1 = 0xc020,
HV_SYS_REG_ID_AA64PFR1_EL1 = 0xc021, ID_AA64PFR1_EL1 = 0xc021,
HV_SYS_REG_ID_AA64DFR0_EL1 = 0xc028, ID_AA64DFR0_EL1 = 0xc028,
HV_SYS_REG_ID_AA64DFR1_EL1 = 0xc029, ID_AA64DFR1_EL1 = 0xc029,
HV_SYS_REG_ID_AA64ISAR0_EL1 = 0xc030, ID_AA64ISAR0_EL1 = 0xc030,
HV_SYS_REG_ID_AA64ISAR1_EL1 = 0xc031, ID_AA64ISAR1_EL1 = 0xc031,
HV_SYS_REG_ID_AA64MMFR0_EL1 = 0xc038, ID_AA64MMFR0_EL1 = 0xc038,
HV_SYS_REG_ID_AA64MMFR1_EL1 = 0xc039, ID_AA64MMFR1_EL1 = 0xc039,
HV_SYS_REG_ID_AA64MMFR2_EL1 = 0xc03a, ID_AA64MMFR2_EL1 = 0xc03a,
HV_SYS_REG_SCTLR_EL1 = 0xc080, SCTLR_EL1 = 0xc080,
HV_SYS_REG_CPACR_EL1 = 0xc082, CPACR_EL1 = 0xc082,
HV_SYS_REG_TTBR0_EL1 = 0xc100, TTBR0_EL1 = 0xc100,
HV_SYS_REG_TTBR1_EL1 = 0xc101, TTBR1_EL1 = 0xc101,
HV_SYS_REG_TCR_EL1 = 0xc102, TCR_EL1 = 0xc102,
HV_SYS_REG_APIAKEYLO_EL1 = 0xc108, APIAKEYLO_EL1 = 0xc108,
HV_SYS_REG_APIAKEYHI_EL1 = 0xc109, APIAKEYHI_EL1 = 0xc109,
HV_SYS_REG_APIBKEYLO_EL1 = 0xc10a, APIBKEYLO_EL1 = 0xc10a,
HV_SYS_REG_APIBKEYHI_EL1 = 0xc10b, APIBKEYHI_EL1 = 0xc10b,
HV_SYS_REG_APDAKEYLO_EL1 = 0xc110, APDAKEYLO_EL1 = 0xc110,
HV_SYS_REG_APDAKEYHI_EL1 = 0xc111, APDAKEYHI_EL1 = 0xc111,
HV_SYS_REG_APDBKEYLO_EL1 = 0xc112, APDBKEYLO_EL1 = 0xc112,
HV_SYS_REG_APDBKEYHI_EL1 = 0xc113, APDBKEYHI_EL1 = 0xc113,
HV_SYS_REG_APGAKEYLO_EL1 = 0xc118, APGAKEYLO_EL1 = 0xc118,
HV_SYS_REG_APGAKEYHI_EL1 = 0xc119, APGAKEYHI_EL1 = 0xc119,
HV_SYS_REG_SPSR_EL1 = 0xc200, SPSR_EL1 = 0xc200,
HV_SYS_REG_ELR_EL1 = 0xc201, ELR_EL1 = 0xc201,
HV_SYS_REG_SP_EL0 = 0xc208, SP_EL0 = 0xc208,
HV_SYS_REG_AFSR0_EL1 = 0xc288, AFSR0_EL1 = 0xc288,
HV_SYS_REG_AFSR1_EL1 = 0xc289, AFSR1_EL1 = 0xc289,
HV_SYS_REG_ESR_EL1 = 0xc290, ESR_EL1 = 0xc290,
HV_SYS_REG_FAR_EL1 = 0xc300, FAR_EL1 = 0xc300,
HV_SYS_REG_PAR_EL1 = 0xc3a0, PAR_EL1 = 0xc3a0,
HV_SYS_REG_MAIR_EL1 = 0xc510, MAIR_EL1 = 0xc510,
HV_SYS_REG_AMAIR_EL1 = 0xc518, AMAIR_EL1 = 0xc518,
HV_SYS_REG_VBAR_EL1 = 0xc600, VBAR_EL1 = 0xc600,
HV_SYS_REG_CONTEXTIDR_EL1 = 0xc681, CONTEXTIDR_EL1 = 0xc681,
HV_SYS_REG_TPIDR_EL1 = 0xc684, TPIDR_EL1 = 0xc684,
HV_SYS_REG_CNTKCTL_EL1 = 0xc708, CNTKCTL_EL1 = 0xc708,
HV_SYS_REG_CSSELR_EL1 = 0xd000, CSSELR_EL1 = 0xd000,
HV_SYS_REG_TPIDR_EL0 = 0xde82, TPIDR_EL0 = 0xde82,
HV_SYS_REG_TPIDRRO_EL0 = 0xde83, TPIDRRO_EL0 = 0xde83,
HV_SYS_REG_CNTV_CTL_EL0 = 0xdf19, CNTV_CTL_EL0 = 0xdf19,
HV_SYS_REG_CNTV_CVAL_EL0 = 0xdf1a, CNTV_CVAL_EL0 = 0xdf1a,
HV_SYS_REG_SP_EL1 = 0xe208, SP_EL1 = 0xe208,
} }
enum hv_memory_flags_t : ulong enum HvMemoryFlags : ulong
{ {
HV_MEMORY_READ = 1UL << 0, Read = 1UL << 0,
HV_MEMORY_WRITE = 1UL << 1, Write = 1UL << 1,
HV_MEMORY_EXEC = 1UL << 2 Exec = 1UL << 2,
} }
enum hv_result_t : uint enum HvResult : uint
{ {
HV_SUCCESS = 0, Success = 0,
HV_ERROR = 0xfae94001, Error = 0xfae94001,
HV_BUSY = 0xfae94002, Busy = 0xfae94002,
HV_BAD_ARGUMENT = 0xfae94003, BadArgument = 0xfae94003,
HV_NO_RESOURCES = 0xfae94005, NoResources = 0xfae94005,
HV_NO_DEVICE = 0xfae94006, NoDevice = 0xfae94006,
HV_DENIED = 0xfae94007, Denied = 0xfae94007,
HV_UNSUPPORTED = 0xfae9400f Unsupported = 0xfae9400f,
} }
enum hv_interrupt_type_t : uint enum HvInterruptType : uint
{ {
HV_INTERRUPT_TYPE_IRQ, IRQ,
HV_INTERRUPT_TYPE_FIQ FIQ,
} }
struct hv_simd_fp_uchar16_t struct HvSimdFPUchar16
{ {
public ulong Low; public ulong Low;
public ulong High; public ulong High;
@@ -247,9 +246,9 @@ namespace Ryujinx.Cpu.AppleHv
static class HvResultExtensions static class HvResultExtensions
{ {
public static void ThrowOnError(this hv_result_t result) public static void ThrowOnError(this HvResult result)
{ {
if (result != hv_result_t.HV_SUCCESS) if (result != HvResult.Success)
{ {
throw new Exception($"Unexpected result \"{result}\"."); throw new Exception($"Unexpected result \"{result}\".");
} }
@@ -261,60 +260,60 @@ namespace Ryujinx.Cpu.AppleHv
public const string LibraryName = "/System/Library/Frameworks/Hypervisor.framework/Hypervisor"; public const string LibraryName = "/System/Library/Frameworks/Hypervisor.framework/Hypervisor";
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_get_max_vcpu_count(out uint max_vcpu_count); public static partial HvResult hv_vm_get_max_vcpu_count(out uint max_vcpu_count);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_create(IntPtr config); public static partial HvResult hv_vm_create(IntPtr config);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_destroy(); public static partial HvResult hv_vm_destroy();
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_map(ulong addr, ulong ipa, ulong size, hv_memory_flags_t flags); public static partial HvResult hv_vm_map(ulong addr, ulong ipa, ulong size, HvMemoryFlags flags);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_unmap(ulong ipa, ulong size); public static partial HvResult hv_vm_unmap(ulong ipa, ulong size);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vm_protect(ulong ipa, ulong size, hv_memory_flags_t flags); public static partial HvResult hv_vm_protect(ulong ipa, ulong size, HvMemoryFlags flags);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public unsafe static partial hv_result_t hv_vcpu_create(out ulong vcpu, ref hv_vcpu_exit_t* exit, IntPtr config); public unsafe static partial HvResult hv_vcpu_create(out ulong vcpu, ref HvVcpuExit* exit, IntPtr config);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public unsafe static partial hv_result_t hv_vcpu_destroy(ulong vcpu); public unsafe static partial HvResult hv_vcpu_destroy(ulong vcpu);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_run(ulong vcpu); public static partial HvResult hv_vcpu_run(ulong vcpu);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpus_exit(ref ulong vcpus, uint vcpu_count); public static partial HvResult hv_vcpus_exit(ref ulong vcpus, uint vcpu_count);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_set_vtimer_mask(ulong vcpu, [MarshalAs(UnmanagedType.Bool)] bool vtimer_is_masked); public static partial HvResult hv_vcpu_set_vtimer_mask(ulong vcpu, [MarshalAs(UnmanagedType.Bool)] bool vtimer_is_masked);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_get_reg(ulong vcpu, hv_reg_t reg, out ulong value); public static partial HvResult hv_vcpu_get_reg(ulong vcpu, HvReg reg, out ulong value);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_set_reg(ulong vcpu, hv_reg_t reg, ulong value); public static partial HvResult hv_vcpu_set_reg(ulong vcpu, HvReg reg, ulong value);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_get_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, out hv_simd_fp_uchar16_t value); public static partial HvResult hv_vcpu_get_simd_fp_reg(ulong vcpu, HvSimdFPReg reg, out HvSimdFPUchar16 value);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_set_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, hv_simd_fp_uchar16_t value); // DO NOT USE DIRECTLY! public static partial HvResult hv_vcpu_set_simd_fp_reg(ulong vcpu, HvSimdFPReg reg, HvSimdFPUchar16 value); // DO NOT USE DIRECTLY!
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_get_sys_reg(ulong vcpu, hv_sys_reg_t reg, out ulong value); public static partial HvResult hv_vcpu_get_sys_reg(ulong vcpu, HvSysReg reg, out ulong value);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_set_sys_reg(ulong vcpu, hv_sys_reg_t reg, ulong value); public static partial HvResult hv_vcpu_set_sys_reg(ulong vcpu, HvSysReg reg, ulong value);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_get_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] out bool pending); public static partial HvResult hv_vcpu_get_pending_interrupt(ulong vcpu, HvInterruptType type, [MarshalAs(UnmanagedType.Bool)] out bool pending);
[LibraryImport(LibraryName, SetLastError = true)] [LibraryImport(LibraryName, SetLastError = true)]
public static partial hv_result_t hv_vcpu_set_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] bool pending); public static partial HvResult hv_vcpu_set_pending_interrupt(ulong vcpu, HvInterruptType type, [MarshalAs(UnmanagedType.Bool)] bool pending);
} }
} }

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
@@ -14,10 +13,6 @@ namespace Ryujinx.Cpu.AppleHv
_memoryManager = (HvMemoryManager)memory; _memoryManager = (HvMemoryManager)memory;
} }
private void UnmapHandler(ulong address, ulong size)
{
}
/// <inheritdoc/> /// <inheritdoc/>
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks) public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
{ {
@@ -44,4 +39,4 @@ namespace Ryujinx.Cpu.AppleHv
{ {
} }
} }
} }

View File

@@ -17,4 +17,4 @@ namespace Ryujinx.Cpu.AppleHv
return new HvCpuContext(_tickSource, memoryManager, for64Bit); return new HvCpuContext(_tickSource, memoryManager, for64Bit);
} }
} }
} }

View File

@@ -125,17 +125,17 @@ namespace Ryujinx.Cpu.AppleHv
{ {
HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext); HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext);
HvApi.hv_vcpu_set_reg(vcpu.Handle, hv_reg_t.HV_REG_PC, address).ThrowOnError(); HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
while (Running) while (Running)
{ {
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError(); HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
uint reason = vcpu.ExitInfo->reason; uint reason = vcpu.ExitInfo->Reason;
if (reason == 1) if (reason == 1)
{ {
uint hvEsr = (uint)vcpu.ExitInfo->exception.syndrome; uint hvEsr = (uint)vcpu.ExitInfo->Exception.Syndrome;
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26); ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
if (hvEc != ExceptionClass.HvcAarch64) if (hvEc != ExceptionClass.HvcAarch64)
@@ -144,7 +144,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
address = SynchronousException(memoryManager, ref vcpu); address = SynchronousException(memoryManager, ref vcpu);
HvApi.hv_vcpu_set_reg(vcpu.Handle, hv_reg_t.HV_REG_PC, address).ThrowOnError(); HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
} }
else if (reason == 0) else if (reason == 0)
{ {
@@ -168,8 +168,8 @@ namespace Ryujinx.Cpu.AppleHv
{ {
ulong vcpuHandle = vcpu.Handle; ulong vcpuHandle = vcpu.Handle;
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, out ulong elr).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
ExceptionClass ec = (ExceptionClass)((uint)esr >> 26); ExceptionClass ec = (ExceptionClass)((uint)esr >> 26);
@@ -180,7 +180,7 @@ namespace Ryujinx.Cpu.AppleHv
break; break;
case ExceptionClass.TrappedMsrMrsSystem: case ExceptionClass.TrappedMsrMrsSystem:
InstructionTrap((uint)esr); InstructionTrap((uint)esr);
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, elr + 4UL).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, elr + 4UL).ThrowOnError();
break; break;
case ExceptionClass.SvcAarch64: case ExceptionClass.SvcAarch64:
ReturnToPool(vcpu); ReturnToPool(vcpu);
@@ -204,7 +204,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
private void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr) private static void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr)
{ {
bool write = (esr & (1u << 6)) != 0; bool write = (esr & (1u << 6)) != 0;
bool farValid = (esr & (1u << 10)) == 0; bool farValid = (esr & (1u << 10)) == 0;
@@ -212,7 +212,7 @@ namespace Ryujinx.Cpu.AppleHv
if (farValid) if (farValid)
{ {
HvApi.hv_vcpu_get_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_FAR_EL1, out ulong far).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(vcpu, HvSysReg.FAR_EL1, out ulong far).ThrowOnError();
ulong size = 1UL << accessSizeLog2; ulong size = 1UL << accessSizeLog2;
@@ -281,4 +281,4 @@ namespace Ryujinx.Cpu.AppleHv
{ {
} }
} }
} }

View File

@@ -2,7 +2,7 @@ using ARMeilleure.State;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
unsafe class HvExecutionContextShadow : IHvExecutionContext class HvExecutionContextShadow : IHvExecutionContext
{ {
public ulong Pc { get; set; } public ulong Pc { get; set; }
public ulong ElrEl1 { get; set; } public ulong ElrEl1 { get; set; }
@@ -56,4 +56,4 @@ namespace Ryujinx.Cpu.AppleHv
return false; return false;
} }
} }
} }

View File

@@ -8,10 +8,10 @@ namespace Ryujinx.Cpu.AppleHv
{ {
class HvExecutionContextVcpu : IHvExecutionContext class HvExecutionContextVcpu : IHvExecutionContext
{ {
private static MemoryBlock _setSimdFpRegFuncMem; private static readonly MemoryBlock _setSimdFpRegFuncMem;
private delegate hv_result_t SetSimdFpReg(ulong vcpu, hv_simd_fp_reg_t reg, in V128 value, IntPtr funcPtr); private delegate HvResult SetSimdFpReg(ulong vcpu, HvSimdFPReg reg, in V128 value, IntPtr funcPtr);
private static SetSimdFpReg _setSimdFpReg; private static readonly SetSimdFpReg _setSimdFpReg;
private static IntPtr _setSimdFpRegNativePtr; private static readonly IntPtr _setSimdFpRegNativePtr;
static HvExecutionContextVcpu() static HvExecutionContextVcpu()
{ {
@@ -34,12 +34,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_PC, out ulong pc).ThrowOnError(); HvApi.hv_vcpu_get_reg(_vcpu, HvReg.PC, out ulong pc).ThrowOnError();
return pc; return pc;
} }
set set
{ {
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_PC, value).ThrowOnError(); HvApi.hv_vcpu_set_reg(_vcpu, HvReg.PC, value).ThrowOnError();
} }
} }
@@ -47,12 +47,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, out ulong elr).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
return elr; return elr;
} }
set set
{ {
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, value).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ELR_EL1, value).ThrowOnError();
} }
} }
@@ -60,12 +60,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
return esr; return esr;
} }
set set
{ {
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, value).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ESR_EL1, value).ThrowOnError();
} }
} }
@@ -73,12 +73,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, out ulong tpidrEl0).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, out ulong tpidrEl0).ThrowOnError();
return (long)tpidrEl0; return (long)tpidrEl0;
} }
set set
{ {
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, (ulong)value).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, (ulong)value).ThrowOnError();
} }
} }
@@ -86,12 +86,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError();
return (long)tpidrroEl0; return (long)tpidrroEl0;
} }
set set
{ {
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, (ulong)value).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, (ulong)value).ThrowOnError();
} }
} }
@@ -99,12 +99,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_CPSR, out ulong cpsr).ThrowOnError(); HvApi.hv_vcpu_get_reg(_vcpu, HvReg.CPSR, out ulong cpsr).ThrowOnError();
return (uint)cpsr; return (uint)cpsr;
} }
set set
{ {
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_CPSR, (ulong)value).ThrowOnError(); HvApi.hv_vcpu_set_reg(_vcpu, HvReg.CPSR, (ulong)value).ThrowOnError();
} }
} }
@@ -112,12 +112,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPCR, out ulong fpcr).ThrowOnError(); HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPCR, out ulong fpcr).ThrowOnError();
return (uint)fpcr; return (uint)fpcr;
} }
set set
{ {
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPCR, (ulong)value).ThrowOnError(); HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPCR, (ulong)value).ThrowOnError();
} }
} }
@@ -125,16 +125,16 @@ namespace Ryujinx.Cpu.AppleHv
{ {
get get
{ {
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPSR, out ulong fpsr).ThrowOnError(); HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPSR, out ulong fpsr).ThrowOnError();
return (uint)fpsr; return (uint)fpsr;
} }
set set
{ {
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPSR, (ulong)value).ThrowOnError(); HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPSR, (ulong)value).ThrowOnError();
} }
} }
private ulong _vcpu; private readonly ulong _vcpu;
private int _interruptRequested; private int _interruptRequested;
public HvExecutionContextVcpu(ulong vcpu) public HvExecutionContextVcpu(ulong vcpu)
@@ -146,12 +146,12 @@ namespace Ryujinx.Cpu.AppleHv
{ {
if (index == 31) if (index == 31)
{ {
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, out ulong value).ThrowOnError(); HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.SP_EL0, out ulong value).ThrowOnError();
return value; return value;
} }
else else
{ {
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, out ulong value).ThrowOnError(); HvApi.hv_vcpu_get_reg(_vcpu, HvReg.X0 + (uint)index, out ulong value).ThrowOnError();
return value; return value;
} }
} }
@@ -160,23 +160,23 @@ namespace Ryujinx.Cpu.AppleHv
{ {
if (index == 31) if (index == 31)
{ {
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, value).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.SP_EL0, value).ThrowOnError();
} }
else else
{ {
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, value).ThrowOnError(); HvApi.hv_vcpu_set_reg(_vcpu, HvReg.X0 + (uint)index, value).ThrowOnError();
} }
} }
public V128 GetV(int index) public V128 GetV(int index)
{ {
HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, out hv_simd_fp_uchar16_t value).ThrowOnError(); HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, HvSimdFPReg.Q0 + (uint)index, out HvSimdFPUchar16 value).ThrowOnError();
return new V128(value.Low, value.High); return new V128(value.Low, value.High);
} }
public void SetV(int index, V128 value) public void SetV(int index, V128 value)
{ {
_setSimdFpReg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError(); _setSimdFpReg(_vcpu, HvSimdFPReg.Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError();
} }
public void RequestInterrupt() public void RequestInterrupt()
@@ -193,4 +193,4 @@ namespace Ryujinx.Cpu.AppleHv
return Interlocked.Exchange(ref _interruptRequested, 0) != 0; return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
} }
} }
} }

View File

@@ -31,4 +31,4 @@ namespace Ryujinx.Cpu.AppleHv
_block.Free(offset, size); _block.Free(offset, size);
} }
} }
} }

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
struct HvMemoryBlockAllocation : IDisposable readonly struct HvMemoryBlockAllocation : IDisposable
{ {
private readonly HvMemoryBlockAllocator _owner; private readonly HvMemoryBlockAllocator _owner;
private readonly HvMemoryBlockAllocator.Block _block; private readonly HvMemoryBlockAllocator.Block _block;

View File

@@ -1,12 +1,9 @@
using Ryujinx.Memory; using Ryujinx.Memory;
using System.Collections.Generic;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
class HvMemoryBlockAllocator : PrivateMemoryAllocatorImpl<HvMemoryBlockAllocator.Block> class HvMemoryBlockAllocator : PrivateMemoryAllocatorImpl<HvMemoryBlockAllocator.Block>
{ {
private const ulong InvalidOffset = ulong.MaxValue;
public class Block : PrivateMemoryAllocator.Block public class Block : PrivateMemoryAllocator.Block
{ {
private readonly HvIpaAllocator _ipaAllocator; private readonly HvIpaAllocator _ipaAllocator;
@@ -21,7 +18,7 @@ namespace Ryujinx.Cpu.AppleHv
Ipa = ipaAllocator.Allocate(size); Ipa = ipaAllocator.Allocate(size);
} }
HvApi.hv_vm_map((ulong)Memory.Pointer, Ipa, size, hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_WRITE).ThrowOnError(); HvApi.hv_vm_map((ulong)Memory.Pointer, Ipa, size, HvMemoryFlags.Read | HvMemoryFlags.Write).ThrowOnError();
} }
public override void Destroy() public override void Destroy()
@@ -44,7 +41,7 @@ namespace Ryujinx.Cpu.AppleHv
_ipaAllocator = ipaAllocator; _ipaAllocator = ipaAllocator;
} }
public unsafe HvMemoryBlockAllocation Allocate(ulong size, ulong alignment) public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
{ {
var allocation = Allocate(size, alignment, CreateBlock); var allocation = Allocate(size, alignment, CreateBlock);

View File

@@ -32,7 +32,7 @@ namespace Ryujinx.Cpu.AppleHv
MappedReplicated = 0x5555555555555555, MappedReplicated = 0x5555555555555555,
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa, WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
ReadWriteTrackedReplicated = ulong.MaxValue ReadWriteTrackedReplicated = ulong.MaxValue,
} }
private readonly InvalidAccessHandler _invalidAccessHandler; private readonly InvalidAccessHandler _invalidAccessHandler;
@@ -126,6 +126,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
#pragma warning disable IDE0051 // Remove unused private member
/// <summary> /// <summary>
/// Ensures the combination of virtual address and size is part of the addressable space and fully mapped. /// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
/// </summary> /// </summary>
@@ -138,6 +139,7 @@ namespace Ryujinx.Cpu.AppleHv
throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}"); throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
} }
} }
#pragma warning restore IDE0051
/// <inheritdoc/> /// <inheritdoc/>
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags) public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
@@ -306,7 +308,7 @@ namespace Ryujinx.Cpu.AppleHv
size = Math.Min(data.Length, PageSize - (int)(va & PageMask)); size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size)); data[..size].CopyTo(_backingMemory.GetSpan(pa, size));
offset += size; offset += size;
} }
@@ -428,7 +430,7 @@ namespace Ryujinx.Cpu.AppleHv
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex) private static void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
{ {
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1); startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1)); endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
@@ -606,7 +608,7 @@ namespace Ryujinx.Cpu.AppleHv
size = Math.Min(data.Length, PageSize - (int)(va & PageMask)); size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
_backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size)); _backingMemory.GetSpan(pa, size).CopyTo(data[..size]);
offset += size; offset += size;
} }
@@ -723,7 +725,7 @@ namespace Ryujinx.Cpu.AppleHv
/// <param name="startVa">The virtual address of the beginning of the first page</param> /// <param name="startVa">The virtual address of the beginning of the first page</param>
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks> /// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetPagesCount(ulong va, ulong size, out ulong startVa) private static int GetPagesCount(ulong va, ulong size, out ulong startVa)
{ {
// WARNING: Always check if ulong does not overflow during the operations. // WARNING: Always check if ulong does not overflow during the operations.
startVa = va & ~(ulong)PageMask; startVa = va & ~(ulong)PageMask;
@@ -814,7 +816,7 @@ namespace Ryujinx.Cpu.AppleHv
{ {
MemoryPermission.None => MemoryPermission.ReadAndWrite, MemoryPermission.None => MemoryPermission.ReadAndWrite,
MemoryPermission.Write => MemoryPermission.Read, MemoryPermission.Write => MemoryPermission.Read,
_ => MemoryPermission.None _ => MemoryPermission.None,
}; };
_addressSpace.ReprotectUser(va, size, protection); _addressSpace.ReprotectUser(va, size, protection);
@@ -943,4 +945,4 @@ namespace Ryujinx.Cpu.AppleHv
private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message); private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
} }
} }

View File

@@ -3,14 +3,14 @@ namespace Ryujinx.Cpu.AppleHv
unsafe class HvVcpu unsafe class HvVcpu
{ {
public readonly ulong Handle; public readonly ulong Handle;
public readonly hv_vcpu_exit_t* ExitInfo; public readonly HvVcpuExit* ExitInfo;
public readonly IHvExecutionContext ShadowContext; public readonly IHvExecutionContext ShadowContext;
public readonly IHvExecutionContext NativeContext; public readonly IHvExecutionContext NativeContext;
public readonly bool IsEphemeral; public readonly bool IsEphemeral;
public HvVcpu( public HvVcpu(
ulong handle, ulong handle,
hv_vcpu_exit_t* exitInfo, HvVcpuExit* exitInfo,
IHvExecutionContext shadowContext, IHvExecutionContext shadowContext,
IHvExecutionContext nativeContext, IHvExecutionContext nativeContext,
bool isEphemeral) bool isEphemeral)
@@ -22,4 +22,4 @@ namespace Ryujinx.Cpu.AppleHv
IsEphemeral = isEphemeral; IsEphemeral = isEphemeral;
} }
} }
} }

View File

@@ -17,10 +17,10 @@ namespace Ryujinx.Cpu.AppleHv
private const int MaxActiveVcpus = 4; private const int MaxActiveVcpus = 4;
public static readonly HvVcpuPool Instance = new HvVcpuPool(); public static readonly HvVcpuPool Instance = new();
private int _totalVcpus; private int _totalVcpus;
private int _maxVcpus; private readonly int _maxVcpus;
public HvVcpuPool() public HvVcpuPool()
{ {
@@ -69,17 +69,17 @@ namespace Ryujinx.Cpu.AppleHv
bool isEphemeral = newCount > _maxVcpus - MaxActiveVcpus; bool isEphemeral = newCount > _maxVcpus - MaxActiveVcpus;
// Create VCPU. // Create VCPU.
hv_vcpu_exit_t* exitInfo = null; HvVcpuExit* exitInfo = null;
HvApi.hv_vcpu_create(out ulong vcpuHandle, ref exitInfo, IntPtr.Zero).ThrowOnError(); HvApi.hv_vcpu_create(out ulong vcpuHandle, ref exitInfo, IntPtr.Zero).ThrowOnError();
// Enable FP and SIMD instructions. // Enable FP and SIMD instructions.
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_CPACR_EL1, 0b11 << 20).ThrowOnError(); HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.CPACR_EL1, 0b11 << 20).ThrowOnError();
addressSpace.InitializeMmu(vcpuHandle); addressSpace.InitializeMmu(vcpuHandle);
HvExecutionContextVcpu nativeContext = new HvExecutionContextVcpu(vcpuHandle); HvExecutionContextVcpu nativeContext = new(vcpuHandle);
HvVcpu vcpu = new HvVcpu(vcpuHandle, exitInfo, shadowContext, nativeContext, isEphemeral); HvVcpu vcpu = new(vcpuHandle, exitInfo, shadowContext, nativeContext, isEphemeral);
return vcpu; return vcpu;
} }
@@ -100,4 +100,4 @@ namespace Ryujinx.Cpu.AppleHv
Interlocked.Decrement(ref _totalVcpus); Interlocked.Decrement(ref _totalVcpus);
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Cpu.AppleHv
private static int _addressSpaces; private static int _addressSpaces;
private static HvIpaAllocator _ipaAllocator; private static HvIpaAllocator _ipaAllocator;
private static object _lock = new object(); private static readonly object _lock = new();
public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block) public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block)
{ {
@@ -36,7 +36,7 @@ namespace Ryujinx.Cpu.AppleHv
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment); baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
} }
var rwx = hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_WRITE | hv_memory_flags_t.HV_MEMORY_EXEC; var rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec;
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError(); HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();
@@ -65,4 +65,4 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
} }
} }

View File

@@ -43,4 +43,4 @@ namespace Ryujinx.Cpu.AppleHv
void RequestInterrupt(); void RequestInterrupt();
bool GetAndClearInterruptRequested(); bool GetAndClearInterruptRequested();
} }
} }

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Cpu.Jit
PtcLoadingState.Start => LoadState.Unloaded, PtcLoadingState.Start => LoadState.Unloaded,
PtcLoadingState.Loading => LoadState.Loading, PtcLoadingState.Loading => LoadState.Loading,
PtcLoadingState.Loaded => LoadState.Loaded, PtcLoadingState.Loaded => LoadState.Loaded,
_ => throw new ArgumentException($"Invalid load state \"{newState}\".") _ => throw new ArgumentException($"Invalid load state \"{newState}\"."),
}; };
StateChanged?.Invoke(state, current, total); StateChanged?.Invoke(state, current, total);
@@ -35,4 +35,4 @@ namespace Ryujinx.Cpu.Jit
_loadState.Continue(); _loadState.Continue();
} }
} }
} }

View File

@@ -17,4 +17,4 @@ namespace Ryujinx.Cpu.Jit
return new JitCpuContext(_tickSource, memoryManager, for64Bit); return new JitCpuContext(_tickSource, memoryManager, for64Bit);
} }
} }
} }

View File

@@ -120,4 +120,4 @@ namespace Ryujinx.Cpu.Jit
_impl.Dispose(); _impl.Dispose();
} }
} }
} }

View File

@@ -19,6 +19,10 @@ namespace Ryujinx.Cpu.Jit
public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute); public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute);
public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute); public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute);
public void Dispose() => _impl.Dispose(); public void Dispose()
{
GC.SuppressFinalize(this);
_impl.Dispose();
}
} }
} }

View File

@@ -84,7 +84,6 @@ namespace Ryujinx.Cpu.Jit
ulong remainingSize = size; ulong remainingSize = size;
ulong oVa = va; ulong oVa = va;
ulong oPa = pa;
while (remainingSize != 0) while (remainingSize != 0)
{ {
_pageTable.Write((va / PageSize) * PteSize, PaToPte(pa)); _pageTable.Write((va / PageSize) * PteSize, PaToPte(pa));
@@ -246,7 +245,7 @@ namespace Ryujinx.Cpu.Jit
size = Math.Min(data.Length, PageSize - (int)(va & PageMask)); size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size)); data[..size].CopyTo(_backingMemory.GetSpan(pa, size));
offset += size; offset += size;
} }
@@ -298,7 +297,7 @@ namespace Ryujinx.Cpu.Jit
} }
/// <inheritdoc/> /// <inheritdoc/>
public unsafe WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false) public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
{ {
if (size == 0) if (size == 0)
{ {
@@ -345,7 +344,7 @@ namespace Ryujinx.Cpu.Jit
/// <param name="startVa">The virtual address of the beginning of the first page</param> /// <param name="startVa">The virtual address of the beginning of the first page</param>
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks> /// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetPagesCount(ulong va, uint size, out ulong startVa) private static int GetPagesCount(ulong va, uint size, out ulong startVa)
{ {
// WARNING: Always check if ulong does not overflow during the operations. // WARNING: Always check if ulong does not overflow during the operations.
startVa = va & ~(ulong)PageMask; startVa = va & ~(ulong)PageMask;
@@ -482,7 +481,7 @@ namespace Ryujinx.Cpu.Jit
size = Math.Min(data.Length, PageSize - (int)(va & PageMask)); size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
_backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size)); _backingMemory.GetSpan(pa, size).CopyTo(data[..size]);
offset += size; offset += size;
} }
@@ -576,6 +575,7 @@ namespace Ryujinx.Cpu.Jit
} }
} }
#pragma warning disable IDE0051 // Remove unused private member
private ulong GetPhysicalAddress(ulong va) private ulong GetPhysicalAddress(ulong va)
{ {
// We return -1L if the virtual address is invalid or unmapped. // We return -1L if the virtual address is invalid or unmapped.
@@ -586,6 +586,7 @@ namespace Ryujinx.Cpu.Jit
return GetPhysicalAddressInternal(va); return GetPhysicalAddressInternal(va);
} }
#pragma warning restore IDE0051
private ulong GetPhysicalAddressInternal(ulong va) private ulong GetPhysicalAddressInternal(ulong va)
{ {
@@ -604,7 +605,7 @@ namespace Ryujinx.Cpu.Jit
{ {
MemoryPermission.None => 0L, MemoryPermission.None => 0L,
MemoryPermission.Write => 2L << PointerTagBit, MemoryPermission.Write => 2L << PointerTagBit,
_ => 3L << PointerTagBit _ => 3L << PointerTagBit,
}; };
int pages = GetPagesCount(va, (uint)size, out va); int pages = GetPagesCount(va, (uint)size, out va);
@@ -698,6 +699,8 @@ namespace Ryujinx.Cpu.Jit
/// </summary> /// </summary>
protected override void Destroy() => _pageTable.Dispose(); protected override void Destroy() => _pageTable.Dispose();
private void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message); #pragma warning disable IDE0051 // Remove unused private member
private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
#pragma warning restore IDE0051
} }
} }

View File

@@ -31,7 +31,7 @@ namespace Ryujinx.Cpu.Jit
MappedReplicated = 0x5555555555555555, MappedReplicated = 0x5555555555555555,
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa, WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
ReadWriteTrackedReplicated = ulong.MaxValue ReadWriteTrackedReplicated = ulong.MaxValue,
} }
private readonly InvalidAccessHandler _invalidAccessHandler; private readonly InvalidAccessHandler _invalidAccessHandler;
@@ -404,7 +404,7 @@ namespace Ryujinx.Cpu.Jit
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex) private static void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
{ {
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1); startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1)); endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
@@ -606,7 +606,7 @@ namespace Ryujinx.Cpu.Jit
/// <param name="startVa">The virtual address of the beginning of the first page</param> /// <param name="startVa">The virtual address of the beginning of the first page</param>
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks> /// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetPagesCount(ulong va, ulong size, out ulong startVa) private static int GetPagesCount(ulong va, ulong size, out ulong startVa)
{ {
// WARNING: Always check if ulong does not overflow during the operations. // WARNING: Always check if ulong does not overflow during the operations.
startVa = va & ~(ulong)PageMask; startVa = va & ~(ulong)PageMask;
@@ -697,7 +697,7 @@ namespace Ryujinx.Cpu.Jit
{ {
MemoryPermission.None => MemoryPermission.ReadAndWrite, MemoryPermission.None => MemoryPermission.ReadAndWrite,
MemoryPermission.Write => MemoryPermission.Read, MemoryPermission.Write => MemoryPermission.Read,
_ => MemoryPermission.None _ => MemoryPermission.None,
}; };
_addressSpace.Base.Reprotect(va, size, protection, false); _addressSpace.Base.Reprotect(va, size, protection, false);

View File

@@ -7,6 +7,6 @@ namespace Ryujinx.Cpu
{ {
Unloaded, Unloaded,
Loading, Loading,
Loaded Loaded,
} }
} }

View File

@@ -10,7 +10,6 @@ namespace Ryujinx.Cpu
{ {
private delegate bool TrackingEventDelegate(ulong address, ulong size, bool write); private delegate bool TrackingEventDelegate(ulong address, ulong size, bool write);
private readonly MemoryTracking _tracking;
private readonly TrackingEventDelegate _trackingEvent; private readonly TrackingEventDelegate _trackingEvent;
private readonly ulong _baseAddress; private readonly ulong _baseAddress;
@@ -18,12 +17,10 @@ namespace Ryujinx.Cpu
public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking) public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking)
{ {
_tracking = tracking;
_baseAddress = (ulong)addressSpace.Pointer; _baseAddress = (ulong)addressSpace.Pointer;
ulong endAddress = _baseAddress + addressSpace.Size; ulong endAddress = _baseAddress + addressSpace.Size;
_trackingEvent = new TrackingEventDelegate(tracking.VirtualMemoryEvent); _trackingEvent = tracking.VirtualMemoryEvent;
bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent)); bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent));
if (!added) if (!added)
@@ -51,6 +48,8 @@ namespace Ryujinx.Cpu
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress); NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress);
if (_mirrorAddress != 0) if (_mirrorAddress != 0)

View File

@@ -2,7 +2,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -26,12 +25,12 @@ namespace Ryujinx.Cpu
} }
} }
public unsafe static T Read<T>(IVirtualMemoryManager memory, ulong position) where T : unmanaged public static T Read<T>(IVirtualMemoryManager memory, ulong position) where T : unmanaged
{ {
return MemoryMarshal.Cast<byte, T>(memory.GetSpan(position, Unsafe.SizeOf<T>()))[0]; return MemoryMarshal.Cast<byte, T>(memory.GetSpan(position, Unsafe.SizeOf<T>()))[0];
} }
public unsafe static ulong Write<T>(IVirtualMemoryManager memory, ulong position, T value) where T : unmanaged public static ulong Write<T>(IVirtualMemoryManager memory, ulong position, T value) where T : unmanaged
{ {
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1)); ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
@@ -42,22 +41,21 @@ namespace Ryujinx.Cpu
public static string ReadAsciiString(IVirtualMemoryManager memory, ulong position, long maxSize = -1) public static string ReadAsciiString(IVirtualMemoryManager memory, ulong position, long maxSize = -1)
{ {
using (RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream()) using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream();
for (long offs = 0; offs < maxSize || maxSize == -1; offs++)
{ {
for (long offs = 0; offs < maxSize || maxSize == -1; offs++) byte value = memory.Read<byte>(position + (ulong)offs);
if (value == 0)
{ {
byte value = memory.Read<byte>(position + (ulong)offs); break;
if (value == 0)
{
break;
}
ms.WriteByte(value);
} }
return Encoding.ASCII.GetString(ms.GetReadOnlySequence()); ms.WriteByte(value);
} }
return Encoding.ASCII.GetString(ms.GetReadOnlySequence());
} }
} }
} }

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Cpu namespace Ryujinx.Cpu
{ {
struct PrivateMemoryAllocation : IDisposable readonly struct PrivateMemoryAllocation : IDisposable
{ {
private readonly PrivateMemoryAllocator _owner; private readonly PrivateMemoryAllocator _owner;
private readonly PrivateMemoryAllocator.Block _block; private readonly PrivateMemoryAllocator.Block _block;
@@ -27,8 +27,8 @@ namespace Ryujinx.Cpu
public (PrivateMemoryAllocation, PrivateMemoryAllocation) Split(ulong splitOffset) public (PrivateMemoryAllocation, PrivateMemoryAllocation) Split(ulong splitOffset)
{ {
PrivateMemoryAllocation left = new PrivateMemoryAllocation(_owner, _block, Offset, splitOffset); PrivateMemoryAllocation left = new(_owner, _block, Offset, splitOffset);
PrivateMemoryAllocation right = new PrivateMemoryAllocation(_owner, _block, Offset + splitOffset, Size - splitOffset); PrivateMemoryAllocation right = new(_owner, _block, Offset + splitOffset, Size - splitOffset);
return (left, right); return (left, right);
} }

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Cpu
public MemoryBlock Memory { get; private set; } public MemoryBlock Memory { get; private set; }
public ulong Size { get; } public ulong Size { get; }
private struct Range : IComparable<Range> private readonly struct Range : IComparable<Range>
{ {
public ulong Offset { get; } public ulong Offset { get; }
public ulong Size { get; } public ulong Size { get; }
@@ -40,7 +40,7 @@ namespace Ryujinx.Cpu
Size = size; Size = size;
_freeRanges = new List<Range> _freeRanges = new List<Range>
{ {
new Range(0, size) new Range(0, size),
}; };
} }
@@ -164,7 +164,7 @@ namespace Ryujinx.Cpu
{ {
private const ulong InvalidOffset = ulong.MaxValue; private const ulong InvalidOffset = ulong.MaxValue;
public struct Allocation public readonly struct Allocation
{ {
public T Block { get; } public T Block { get; }
public ulong Offset { get; } public ulong Offset { get; }
@@ -265,4 +265,4 @@ namespace Ryujinx.Cpu
_blocks.Clear(); _blocks.Clear();
} }
} }
} }

View File

@@ -42,4 +42,4 @@ namespace Ryujinx.Cpu
_tickCounter.Start(); _tickCounter.Start();
} }
} }
} }

View File

@@ -1,14 +1,7 @@
using NUnit.Framework; using NUnit.Framework;
using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.Upsampler;
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Ryujinx.Tests.Audio.Renderer.Dsp namespace Ryujinx.Tests.Audio.Renderer.Dsp
{ {
@@ -41,8 +34,8 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
/// <param name="quality">The resampler quality to use</param> /// <param name="quality">The resampler quality to use</param>
private static void DoResamplingTest(int inputRate, int outputRate, VoiceInParameter.SampleRateConversionQuality quality) private static void DoResamplingTest(int inputRate, int outputRate, VoiceInParameter.SampleRateConversionQuality quality)
{ {
float inputSampleRate = (float)inputRate; float inputSampleRate = inputRate;
float outputSampleRate = (float)outputRate; float outputSampleRate = outputRate;
int inputSampleCount = inputRate; int inputSampleCount = inputRate;
int outputSampleCount = outputRate; int outputSampleCount = outputRate;
short[] inputBuffer = new short[inputSampleCount + 100]; // add some safety buffer at the end short[] inputBuffer = new short[inputSampleCount + 100]; // add some safety buffer at the end
@@ -50,7 +43,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
for (int sample = 0; sample < inputBuffer.Length; sample++) for (int sample = 0; sample < inputBuffer.Length; sample++)
{ {
// 440 hz sine wave with amplitude = 0.5f at input sample rate // 440 hz sine wave with amplitude = 0.5f at input sample rate
inputBuffer[sample] = (short)(32767 * MathF.Sin((440 / inputSampleRate) * (float)sample * MathF.PI * 2f) * 0.5f); inputBuffer[sample] = (short)(32767 * MathF.Sin((440 / inputSampleRate) * sample * MathF.PI * 2f) * 0.5f);
} }
float fraction = 0; float fraction = 0;
@@ -70,14 +63,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
{ {
VoiceInParameter.SampleRateConversionQuality.High => 3, VoiceInParameter.SampleRateConversionQuality.High => 3,
VoiceInParameter.SampleRateConversionQuality.Default => 1, VoiceInParameter.SampleRateConversionQuality.Default => 1,
_ => 0 _ => 0,
}; };
for (int sample = 0; sample < outputSampleCount; sample++) for (int sample = 0; sample < outputSampleCount; sample++)
{ {
outputBuffer[sample] /= 32767; outputBuffer[sample] /= 32767;
// 440 hz sine wave with amplitude = 0.5f at output sample rate // 440 hz sine wave with amplitude = 0.5f at output sample rate
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (float)(sample + delay) * MathF.PI * 2f) * 0.5f; expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (sample + delay) * MathF.PI * 2f) * 0.5f;
float thisDelta = Math.Abs(expectedOutput[sample] - outputBuffer[sample]); float thisDelta = Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
// Ensure no discontinuities // Ensure no discontinuities
@@ -85,7 +78,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
sumDifference += thisDelta; sumDifference += thisDelta;
} }
sumDifference = sumDifference / (float)outputSampleCount; sumDifference /= outputSampleCount;
// Expect the output to be 99% similar to the expected resampled sine wave // Expect the output to be 99% similar to the expected resampled sine wave
Assert.IsTrue(sumDifference < 0.01f); Assert.IsTrue(sumDifference < 0.01f);
} }

View File

@@ -1,14 +1,7 @@
using NUnit.Framework; using NUnit.Framework;
using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.Upsampler; using Ryujinx.Audio.Renderer.Server.Upsampler;
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Ryujinx.Tests.Audio.Renderer.Dsp namespace Ryujinx.Tests.Audio.Renderer.Dsp
{ {
@@ -17,7 +10,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
[Test] [Test]
public void TestUpsamplerConsistency() public void TestUpsamplerConsistency()
{ {
UpsamplerBufferState bufferState = new UpsamplerBufferState(); UpsamplerBufferState bufferState = new();
int inputBlockSize = 160; int inputBlockSize = 160;
int numInputSamples = 32000; int numInputSamples = 32000;
int numOutputSamples = 48000; int numOutputSamples = 48000;
@@ -28,14 +21,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
for (int sample = 0; sample < inputBuffer.Length; sample++) for (int sample = 0; sample < inputBuffer.Length; sample++)
{ {
// 440 hz sine wave with amplitude = 0.5f at input sample rate // 440 hz sine wave with amplitude = 0.5f at input sample rate
inputBuffer[sample] = MathF.Sin((440 / inputSampleRate) * (float)sample * MathF.PI * 2f) * 0.5f; inputBuffer[sample] = MathF.Sin((440 / inputSampleRate) * sample * MathF.PI * 2f) * 0.5f;
} }
int inputIdx = 0; int inputIdx = 0;
int outputIdx = 0; int outputIdx = 0;
while (inputIdx + inputBlockSize < numInputSamples) while (inputIdx + inputBlockSize < numInputSamples)
{ {
int outputBufLength = (int)Math.Round((float)(inputIdx + inputBlockSize) * outputSampleRate / inputSampleRate) - outputIdx; int outputBufLength = (int)Math.Round((inputIdx + inputBlockSize) * outputSampleRate / inputSampleRate) - outputIdx;
UpsamplerHelper.Upsample( UpsamplerHelper.Upsample(
outputBuffer.AsSpan(outputIdx), outputBuffer.AsSpan(outputIdx),
inputBuffer.AsSpan(inputIdx), inputBuffer.AsSpan(inputIdx),
@@ -52,11 +45,11 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
for (int sample = 0; sample < numOutputSamples; sample++) for (int sample = 0; sample < numOutputSamples; sample++)
{ {
// 440 hz sine wave with amplitude = 0.5f at output sample rate with an offset of 15 // 440 hz sine wave with amplitude = 0.5f at output sample rate with an offset of 15
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (float)(sample - 15) * MathF.PI * 2f) * 0.5f; expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (sample - 15) * MathF.PI * 2f) * 0.5f;
sumDifference += Math.Abs(expectedOutput[sample] - outputBuffer[sample]); sumDifference += Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
} }
sumDifference = sumDifference / (float)expectedOutput.Length; sumDifference /= expectedOutput.Length;
// Expect the output to be 98% similar to the expected resampled sine wave // Expect the output to be 98% similar to the expected resampled sine wave
Assert.IsTrue(sumDifference < 0.02f); Assert.IsTrue(sumDifference < 0.02f);
} }

View File

@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
} }
} }
} }

View File

@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
} }
} }
} }

View File

@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
} }
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestCheckFeature() public void TestCheckFeature()
{ {
int latestRevision = BehaviourContext.BaseRevisionMagic + BehaviourContext.LastRevision; int latestRevision = BehaviourContext.BaseRevisionMagic + BehaviourContext.LastRevision;
int previousRevision = BehaviourContext.BaseRevisionMagic + (BehaviourContext.LastRevision - 1); int previousRevision = BehaviourContext.BaseRevisionMagic + (BehaviourContext.LastRevision - 1);
int invalidRevision = BehaviourContext.BaseRevisionMagic + (BehaviourContext.LastRevision + 1); int invalidRevision = BehaviourContext.BaseRevisionMagic + (BehaviourContext.LastRevision + 1);
@@ -22,7 +22,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestsMemoryPoolForceMappingEnabled() public void TestsMemoryPoolForceMappingEnabled()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision1() public void TestRevision1()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision2() public void TestRevision2()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision2); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision2);
@@ -88,7 +88,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision3() public void TestRevision3()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision3); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision3);
@@ -114,7 +114,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision4() public void TestRevision4()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision4); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision4);
@@ -140,7 +140,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision5() public void TestRevision5()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision5); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision5);
@@ -166,7 +166,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision6() public void TestRevision6()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision6); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision6);
@@ -192,7 +192,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision7() public void TestRevision7()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision7); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision7);
@@ -218,7 +218,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision8() public void TestRevision8()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision8); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision8);
@@ -244,7 +244,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision9() public void TestRevision9()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision9); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision9);
@@ -270,7 +270,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestRevision10() public void TestRevision10()
{ {
BehaviourContext behaviourContext = new BehaviourContext(); BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision10); behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision10);
@@ -293,4 +293,4 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
Assert.AreEqual(2, behaviourContext.GetPerformanceMetricsDataFormat()); Assert.AreEqual(2, behaviourContext.GetPerformanceMetricsDataFormat());
} }
} }
} }

View File

@@ -15,13 +15,13 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestInitializeSystemPool() public void TestInitializeSystemPool()
{ {
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true); PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp); MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu); MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
const CpuAddress CpuAddress = 0x20000; const CpuAddress CpuAddress = 0x20000;
const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
const ulong CpuSize = 0x1000; const ulong CpuSize = 0x1000;
Assert.IsFalse(poolMapper.InitializeSystemPool(ref memoryPoolCpu, CpuAddress, CpuSize)); Assert.IsFalse(poolMapper.InitializeSystemPool(ref memoryPoolCpu, CpuAddress, CpuSize));
Assert.IsTrue(poolMapper.InitializeSystemPool(ref memoryPoolDsp, CpuAddress, CpuSize)); Assert.IsTrue(poolMapper.InitializeSystemPool(ref memoryPoolDsp, CpuAddress, CpuSize));
@@ -34,7 +34,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestGetProcessHandle() public void TestGetProcessHandle()
{ {
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true); PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp); MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu); MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
@@ -45,13 +45,13 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test] [Test]
public void TestMappings() public void TestMappings()
{ {
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true); PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp); MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu); MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
const CpuAddress CpuAddress = 0x20000; const CpuAddress CpuAddress = 0x20000;
const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
const ulong CpuSize = 0x1000; const ulong CpuSize = 0x1000;
memoryPoolDsp.SetCpuAddress(CpuAddress, CpuSize); memoryPoolDsp.SetCpuAddress(CpuAddress, CpuSize);
memoryPoolCpu.SetCpuAddress(CpuAddress, CpuSize); memoryPoolCpu.SetCpuAddress(CpuAddress, CpuSize);
@@ -72,10 +72,10 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
{ {
const CpuAddress CpuAddress = 0x20000; const CpuAddress CpuAddress = 0x20000;
const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
const ulong CpuSize = 0x1000; const ulong CpuSize = 0x1000;
const int MemoryPoolStateArraySize = 0x10; const int MemoryPoolStateArraySize = 0x10;
const CpuAddress CpuAddressRegionEnding = CpuAddress * MemoryPoolStateArraySize; const CpuAddress CpuAddressRegionEnding = CpuAddress * MemoryPoolStateArraySize;
MemoryPoolState[] memoryPoolStateArray = new MemoryPoolState[MemoryPoolStateArraySize]; MemoryPoolState[] memoryPoolStateArray = new MemoryPoolState[MemoryPoolStateArraySize];
@@ -85,13 +85,12 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize); memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize);
} }
ErrorInfo errorInfo;
AddressInfo addressInfo = AddressInfo.Create(); AddressInfo addressInfo = AddressInfo.Create();
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true); PoolMapper poolMapper = new(DummyProcessHandle, true);
Assert.IsTrue(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0)); Assert.IsTrue(poolMapper.TryAttachBuffer(out ErrorInfo errorInfo, ref addressInfo, 0, 0));
Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode); Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
Assert.AreEqual(0, errorInfo.ExtraErrorInfo); Assert.AreEqual(0, errorInfo.ExtraErrorInfo);
@@ -105,7 +104,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
poolMapper = new PoolMapper(DummyProcessHandle, false); poolMapper = new PoolMapper(DummyProcessHandle, false);
Assert.IsFalse(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0)); Assert.IsFalse(poolMapper.TryAttachBuffer(out _, ref addressInfo, 0, 0));
addressInfo.ForceMappedDspAddress = 0; addressInfo.ForceMappedDspAddress = 0;

View File

@@ -31,7 +31,7 @@ namespace Ryujinx.Tests.Cpu
new() { Value = 0xffff8fffffff8fff, Valid = true, ImmN = 0, ImmS = 0x1c, ImmR = 17 }, new() { Value = 0xffff8fffffff8fff, Valid = true, ImmN = 0, ImmS = 0x1c, ImmR = 17 },
new() { Value = 0x000000000ffff800, Valid = true, ImmN = 1, ImmS = 0x10, ImmR = 53 }, new() { Value = 0x000000000ffff800, Valid = true, ImmN = 1, ImmS = 0x10, ImmR = 53 },
}; };
[Test] [Test]
public void BitImmTests([ValueSource(nameof(TestCases))] TestCase test) public void BitImmTests([ValueSource(nameof(TestCases))] TestCase test)
{ {
@@ -43,4 +43,4 @@ namespace Ryujinx.Tests.Cpu
Assert.That(immR, Is.EqualTo(test.ImmR)); Assert.That(immR, Is.EqualTo(test.ImmR));
} }
} }
} }

View File

@@ -14,13 +14,15 @@ namespace Ryujinx.Tests.Cpu
public class CpuTest public class CpuTest
{ {
protected static readonly ulong Size = MemoryBlock.GetPageSize(); protected static readonly ulong Size = MemoryBlock.GetPageSize();
#pragma warning disable CA2211 // Non-constant fields should not be visible
protected static ulong CodeBaseAddress = Size; protected static ulong CodeBaseAddress = Size;
protected static ulong DataBaseAddress = CodeBaseAddress + Size; protected static ulong DataBaseAddress = CodeBaseAddress + Size;
#pragma warning restore CA2211
private static bool Ignore_FpcrFz = false; private static readonly bool _ignoreFpcrFz = false;
private static bool Ignore_FpcrDn = false; private static readonly bool _ignoreFpcrDn = false;
private static bool IgnoreAllExcept_FpsrQc = false; private static readonly bool _ignoreAllExceptFpsrQc = false;
private ulong _currAddress; private ulong _currAddress;
@@ -84,8 +86,8 @@ namespace Ryujinx.Tests.Cpu
_context.Dispose(); _context.Dispose();
_ram.Dispose(); _ram.Dispose();
_memory = null; _memory = null;
_context = null; _context = null;
_cpuContext = null; _cpuContext = null;
_unicornEmu = null; _unicornEmu = null;
@@ -109,38 +111,38 @@ namespace Ryujinx.Tests.Cpu
protected ExecutionContext GetContext() => _context; protected ExecutionContext GetContext() => _context;
protected void SetContext(ulong x0 = 0, protected void SetContext(ulong x0 = 0,
ulong x1 = 0, ulong x1 = 0,
ulong x2 = 0, ulong x2 = 0,
ulong x3 = 0, ulong x3 = 0,
ulong x31 = 0, ulong x31 = 0,
V128 v0 = default, V128 v0 = default,
V128 v1 = default, V128 v1 = default,
V128 v2 = default, V128 v2 = default,
V128 v3 = default, V128 v3 = default,
V128 v4 = default, V128 v4 = default,
V128 v5 = default, V128 v5 = default,
V128 v30 = default, V128 v30 = default,
V128 v31 = default, V128 v31 = default,
bool overflow = false, bool overflow = false,
bool carry = false, bool carry = false,
bool zero = false, bool zero = false,
bool negative = false, bool negative = false,
int fpcr = 0, int fpcr = 0,
int fpsr = 0) int fpsr = 0)
{ {
_context.SetX(0, x0); _context.SetX(0, x0);
_context.SetX(1, x1); _context.SetX(1, x1);
_context.SetX(2, x2); _context.SetX(2, x2);
_context.SetX(3, x3); _context.SetX(3, x3);
_context.SetX(31, x31); _context.SetX(31, x31);
_context.SetV(0, v0); _context.SetV(0, v0);
_context.SetV(1, v1); _context.SetV(1, v1);
_context.SetV(2, v2); _context.SetV(2, v2);
_context.SetV(3, v3); _context.SetV(3, v3);
_context.SetV(4, v4); _context.SetV(4, v4);
_context.SetV(5, v5); _context.SetV(5, v5);
_context.SetV(30, v30); _context.SetV(30, v30);
_context.SetV(31, v31); _context.SetV(31, v31);
@@ -156,20 +158,20 @@ namespace Ryujinx.Tests.Cpu
_unicornEmu.X[1] = x1; _unicornEmu.X[1] = x1;
_unicornEmu.X[2] = x2; _unicornEmu.X[2] = x2;
_unicornEmu.X[3] = x3; _unicornEmu.X[3] = x3;
_unicornEmu.SP = x31; _unicornEmu.SP = x31;
_unicornEmu.Q[0] = V128ToSimdValue(v0); _unicornEmu.Q[0] = V128ToSimdValue(v0);
_unicornEmu.Q[1] = V128ToSimdValue(v1); _unicornEmu.Q[1] = V128ToSimdValue(v1);
_unicornEmu.Q[2] = V128ToSimdValue(v2); _unicornEmu.Q[2] = V128ToSimdValue(v2);
_unicornEmu.Q[3] = V128ToSimdValue(v3); _unicornEmu.Q[3] = V128ToSimdValue(v3);
_unicornEmu.Q[4] = V128ToSimdValue(v4); _unicornEmu.Q[4] = V128ToSimdValue(v4);
_unicornEmu.Q[5] = V128ToSimdValue(v5); _unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[30] = V128ToSimdValue(v30); _unicornEmu.Q[30] = V128ToSimdValue(v30);
_unicornEmu.Q[31] = V128ToSimdValue(v31); _unicornEmu.Q[31] = V128ToSimdValue(v31);
_unicornEmu.OverflowFlag = overflow; _unicornEmu.OverflowFlag = overflow;
_unicornEmu.CarryFlag = carry; _unicornEmu.CarryFlag = carry;
_unicornEmu.ZeroFlag = zero; _unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative; _unicornEmu.NegativeFlag = negative;
_unicornEmu.Fpcr = fpcr; _unicornEmu.Fpcr = fpcr;
@@ -186,34 +188,34 @@ namespace Ryujinx.Tests.Cpu
} }
} }
protected ExecutionContext SingleOpcode(uint opcode, protected ExecutionContext SingleOpcode(uint opcode,
ulong x0 = 0, ulong x0 = 0,
ulong x1 = 0, ulong x1 = 0,
ulong x2 = 0, ulong x2 = 0,
ulong x3 = 0, ulong x3 = 0,
ulong x31 = 0, ulong x31 = 0,
V128 v0 = default, V128 v0 = default,
V128 v1 = default, V128 v1 = default,
V128 v2 = default, V128 v2 = default,
V128 v3 = default, V128 v3 = default,
V128 v4 = default, V128 v4 = default,
V128 v5 = default, V128 v5 = default,
V128 v30 = default, V128 v30 = default,
V128 v31 = default, V128 v31 = default,
bool overflow = false, bool overflow = false,
bool carry = false, bool carry = false,
bool zero = false, bool zero = false,
bool negative = false, bool negative = false,
int fpcr = 0, int fpcr = 0,
int fpsr = 0, int fpsr = 0,
bool runUnicorn = true) bool runUnicorn = true)
{ {
if (Ignore_FpcrFz) if (_ignoreFpcrFz)
{ {
fpcr &= ~(1 << (int)Fpcr.Fz); fpcr &= ~(1 << (int)Fpcr.Fz);
} }
if (Ignore_FpcrDn) if (_ignoreFpcrDn)
{ {
fpcr &= ~(1 << (int)Fpcr.Dn); fpcr &= ~(1 << (int)Fpcr.Dn);
} }
@@ -254,8 +256,8 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Round towards Minus Infinity mode.</summary> /// <summary>Round towards Minus Infinity mode.</summary>
Rm, Rm,
/// <summary>Round towards Zero mode.</summary> /// <summary>Round towards Zero mode.</summary>
Rz Rz,
}; }
/// <summary>Floating-point Control Register.</summary> /// <summary>Floating-point Control Register.</summary>
protected enum Fpcr protected enum Fpcr
@@ -263,15 +265,16 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Rounding Mode control field.</summary> /// <summary>Rounding Mode control field.</summary>
RMode = 22, RMode = 22,
/// <summary>Flush-to-zero mode control bit.</summary> /// <summary>Flush-to-zero mode control bit.</summary>
Fz = 24, Fz = 24,
/// <summary>Default NaN mode control bit.</summary> /// <summary>Default NaN mode control bit.</summary>
Dn = 25, Dn = 25,
/// <summary>Alternative half-precision control bit.</summary> /// <summary>Alternative half-precision control bit.</summary>
Ahp = 26 Ahp = 26,
} }
/// <summary>Floating-point Status Register.</summary> /// <summary>Floating-point Status Register.</summary>
[Flags] protected enum Fpsr [Flags]
protected enum Fpsr
{ {
None = 0, None = 0,
@@ -289,10 +292,11 @@ namespace Ryujinx.Tests.Cpu
Idc = 1 << 7, Idc = 1 << 7,
/// <summary>Cumulative saturation bit.</summary> /// <summary>Cumulative saturation bit.</summary>
Qc = 1 << 27 Qc = 1 << 27,
} }
[Flags] protected enum FpSkips [Flags]
protected enum FpSkips
{ {
None = 0, None = 0,
@@ -300,7 +304,7 @@ namespace Ryujinx.Tests.Cpu
IfNaND = 2, IfNaND = 2,
IfUnderflow = 4, IfUnderflow = 4,
IfOverflow = 8 IfOverflow = 8,
} }
protected enum FpTolerances protected enum FpTolerances
@@ -308,15 +312,15 @@ namespace Ryujinx.Tests.Cpu
None, None,
UpToOneUlpsS, UpToOneUlpsS,
UpToOneUlpsD UpToOneUlpsD,
} }
protected void CompareAgainstUnicorn( protected void CompareAgainstUnicorn(
Fpsr fpsrMask = Fpsr.None, Fpsr fpsrMask = Fpsr.None,
FpSkips fpSkips = FpSkips.None, FpSkips fpSkips = FpSkips.None,
FpTolerances fpTolerances = FpTolerances.None) FpTolerances fpTolerances = FpTolerances.None)
{ {
if (IgnoreAllExcept_FpsrQc) if (_ignoreAllExceptFpsrQc)
{ {
fpsrMask &= Fpsr.Qc; fpsrMask &= Fpsr.Qc;
} }
@@ -326,6 +330,7 @@ namespace Ryujinx.Tests.Cpu
ManageFpSkips(fpSkips); ManageFpSkips(fpSkips);
} }
#pragma warning disable IDE0055 // Disable formatting
Assert.That(_context.GetX(0), Is.EqualTo(_unicornEmu.X[0]), "X0"); Assert.That(_context.GetX(0), Is.EqualTo(_unicornEmu.X[0]), "X0");
Assert.That(_context.GetX(1), Is.EqualTo(_unicornEmu.X[1]), "X1"); Assert.That(_context.GetX(1), Is.EqualTo(_unicornEmu.X[1]), "X1");
Assert.That(_context.GetX(2), Is.EqualTo(_unicornEmu.X[2]), "X2"); Assert.That(_context.GetX(2), Is.EqualTo(_unicornEmu.X[2]), "X2");
@@ -358,6 +363,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(_context.GetX(29), Is.EqualTo(_unicornEmu.X[29])); Assert.That(_context.GetX(29), Is.EqualTo(_unicornEmu.X[29]));
Assert.That(_context.GetX(30), Is.EqualTo(_unicornEmu.X[30])); Assert.That(_context.GetX(30), Is.EqualTo(_unicornEmu.X[30]));
Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31"); Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31");
#pragma warning restore IDE0055
if (fpTolerances == FpTolerances.None) if (fpTolerances == FpTolerances.None)
{ {
@@ -367,6 +373,8 @@ namespace Ryujinx.Tests.Cpu
{ {
ManageFpTolerances(fpTolerances); ManageFpTolerances(fpTolerances);
} }
#pragma warning disable IDE0055 // Disable formatting
Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1"); Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1");
Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2"); Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2");
Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3"); Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3");
@@ -409,6 +417,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr), "Fpcr"); Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr), "Fpcr");
Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr"); Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr");
#pragma warning restore IDE0055
if (_usingMemory) if (_usingMemory)
{ {
@@ -455,7 +464,7 @@ namespace Ryujinx.Tests.Cpu
private void ManageFpTolerances(FpTolerances fpTolerances) private void ManageFpTolerances(FpTolerances fpTolerances)
{ {
bool IsNormalOrSubnormalS(float f) => float.IsNormal(f) || float.IsSubnormal(f); bool IsNormalOrSubnormalS(float f) => float.IsNormal(f) || float.IsSubnormal(f);
bool IsNormalOrSubnormalD(double d) => double.IsNormal(d) || double.IsSubnormal(d); bool IsNormalOrSubnormalD(double d) => double.IsNormal(d) || double.IsSubnormal(d);
if (!Is.EqualTo(_unicornEmu.Q[0]).ApplyTo(V128ToSimdValue(_context.GetV(0))).IsSuccess) if (!Is.EqualTo(_unicornEmu.Q[0]).ApplyTo(V128ToSimdValue(_context.GetV(0))).IsSuccess)
@@ -467,13 +476,13 @@ namespace Ryujinx.Tests.Cpu
{ {
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.That (_context.GetV(0).Extract<float>(0), Assert.That(_context.GetV(0).Extract<float>(0),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(0)).Within(1).Ulps, "V0[0]"); Is.EqualTo(_unicornEmu.Q[0].GetFloat(0)).Within(1).Ulps, "V0[0]");
Assert.That (_context.GetV(0).Extract<float>(1), Assert.That(_context.GetV(0).Extract<float>(1),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(1)).Within(1).Ulps, "V0[1]"); Is.EqualTo(_unicornEmu.Q[0].GetFloat(1)).Within(1).Ulps, "V0[1]");
Assert.That (_context.GetV(0).Extract<float>(2), Assert.That(_context.GetV(0).Extract<float>(2),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(2)).Within(1).Ulps, "V0[2]"); Is.EqualTo(_unicornEmu.Q[0].GetFloat(2)).Within(1).Ulps, "V0[2]");
Assert.That (_context.GetV(0).Extract<float>(3), Assert.That(_context.GetV(0).Extract<float>(3),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(3)).Within(1).Ulps, "V0[3]"); Is.EqualTo(_unicornEmu.Q[0].GetFloat(3)).Within(1).Ulps, "V0[3]");
}); });
@@ -492,9 +501,9 @@ namespace Ryujinx.Tests.Cpu
{ {
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.That (_context.GetV(0).Extract<double>(0), Assert.That(_context.GetV(0).Extract<double>(0),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(0)).Within(1).Ulps, "V0[0]"); Is.EqualTo(_unicornEmu.Q[0].GetDouble(0)).Within(1).Ulps, "V0[0]");
Assert.That (_context.GetV(0).Extract<double>(1), Assert.That(_context.GetV(0).Extract<double>(1),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(1)).Within(1).Ulps, "V0[1]"); Is.EqualTo(_unicornEmu.Q[0].GetDouble(1)).Within(1).Ulps, "V0[1]");
}); });
@@ -513,13 +522,13 @@ namespace Ryujinx.Tests.Cpu
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1)); return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
} }
protected static V128 MakeVectorScalar(float value) => new V128(value); protected static V128 MakeVectorScalar(float value) => new(value);
protected static V128 MakeVectorScalar(double value) => new V128(value); protected static V128 MakeVectorScalar(double value) => new(value);
protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0); protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1); protected static V128 MakeVectorE1(ulong e1) => new(0, e1);
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new V128(e0, e1); protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new(e0, e1);
protected static ulong GetVectorE0(V128 vector) => vector.Extract<ulong>(0); protected static ulong GetVectorE0(V128 vector) => vector.Extract<ulong>(0);
protected static ulong GetVectorE1(V128 vector) => vector.Extract<ulong>(1); protected static ulong GetVectorE1(V128 vector) => vector.Extract<ulong>(1);
@@ -528,8 +537,9 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort(); do
while (( rnd & 0x7C00u) == 0u || rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x7C00u) == 0u ||
(~rnd & 0x7C00u) == 0u); (~rnd & 0x7C00u) == 0u);
return (ushort)rnd; return (ushort)rnd;
@@ -539,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort(); do
rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x03FFu) == 0u); while ((rnd & 0x03FFu) == 0u);
return (ushort)(rnd & 0x83FFu); return (ushort)(rnd & 0x83FFu);
@@ -549,8 +560,9 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt(); do
while (( rnd & 0x7F800000u) == 0u || rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x7F800000u) == 0u ||
(~rnd & 0x7F800000u) == 0u); (~rnd & 0x7F800000u) == 0u);
return rnd; return rnd;
@@ -560,7 +572,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt(); do
rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x007FFFFFu) == 0u); while ((rnd & 0x007FFFFFu) == 0u);
return rnd & 0x807FFFFFu; return rnd & 0x807FFFFFu;
@@ -570,8 +583,9 @@ namespace Ryujinx.Tests.Cpu
{ {
ulong rnd; ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong(); do
while (( rnd & 0x7FF0000000000000ul) == 0ul || rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
(~rnd & 0x7FF0000000000000ul) == 0ul); (~rnd & 0x7FF0000000000000ul) == 0ul);
return rnd; return rnd;
@@ -581,10 +595,11 @@ namespace Ryujinx.Tests.Cpu
{ {
ulong rnd; ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong(); do
rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul); while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
return rnd & 0x800FFFFFFFFFFFFFul; return rnd & 0x800FFFFFFFFFFFFFul;
} }
} }
} }

View File

@@ -14,8 +14,10 @@ namespace Ryujinx.Tests.Cpu
public class CpuTest32 public class CpuTest32
{ {
protected static readonly uint Size = (uint)MemoryBlock.GetPageSize(); protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
#pragma warning disable CA2211 // Non-constant fields should not be visible
protected static uint CodeBaseAddress = Size; protected static uint CodeBaseAddress = Size;
protected static uint DataBaseAddress = CodeBaseAddress + Size; protected static uint DataBaseAddress = CodeBaseAddress + Size;
#pragma warning restore CA2211
private uint _currAddress; private uint _currAddress;
@@ -79,8 +81,8 @@ namespace Ryujinx.Tests.Cpu
_context.Dispose(); _context.Dispose();
_ram.Dispose(); _ram.Dispose();
_memory = null; _memory = null;
_context = null; _context = null;
_cpuContext = null; _cpuContext = null;
_unicornEmu = null; _unicornEmu = null;
@@ -288,16 +290,17 @@ namespace Ryujinx.Tests.Cpu
SetWorkingMemory(0, testMem); SetWorkingMemory(0, testMem);
RunPrecomputedTestCase(new PrecomputedThumbTestCase(){ RunPrecomputedTestCase(new PrecomputedThumbTestCase
{
Instructions = test.Instructions, Instructions = test.Instructions,
StartRegs = test.StartRegs, StartRegs = test.StartRegs,
FinalRegs = test.FinalRegs, FinalRegs = test.FinalRegs,
}); });
foreach (var delta in test.MemoryDelta) foreach (var (address, value) in test.MemoryDelta)
{ {
testMem[delta.Address - DataBaseAddress + 0] = (byte)(delta.Value >> 0); testMem[address - DataBaseAddress + 0] = (byte)(value >> 0);
testMem[delta.Address - DataBaseAddress + 1] = (byte)(delta.Value >> 8); testMem[address - DataBaseAddress + 1] = (byte)(value >> 8);
} }
byte[] mem = _memory.GetSpan(DataBaseAddress, (int)Size).ToArray(); byte[] mem = _memory.GetSpan(DataBaseAddress, (int)Size).ToArray();
@@ -324,8 +327,8 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Round towards Minus Infinity mode.</summary> /// <summary>Round towards Minus Infinity mode.</summary>
Rm, Rm,
/// <summary>Round towards Zero mode.</summary> /// <summary>Round towards Zero mode.</summary>
Rz Rz,
}; }
/// <summary>Floating-point Control Register.</summary> /// <summary>Floating-point Control Register.</summary>
protected enum Fpcr protected enum Fpcr
@@ -337,7 +340,7 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Default NaN mode control bit.</summary> /// <summary>Default NaN mode control bit.</summary>
Dn = 25, Dn = 25,
/// <summary>Alternative half-precision control bit.</summary> /// <summary>Alternative half-precision control bit.</summary>
Ahp = 26 Ahp = 26,
} }
/// <summary>Floating-point Status Register.</summary> /// <summary>Floating-point Status Register.</summary>
@@ -363,7 +366,7 @@ namespace Ryujinx.Tests.Cpu
Qc = 1 << 27, Qc = 1 << 27,
/// <summary>NZCV flags.</summary> /// <summary>NZCV flags.</summary>
Nzcv = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) Nzcv = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28),
} }
[Flags] [Flags]
@@ -375,7 +378,7 @@ namespace Ryujinx.Tests.Cpu
IfNaND = 2, IfNaND = 2,
IfUnderflow = 4, IfUnderflow = 4,
IfOverflow = 8 IfOverflow = 8,
} }
protected enum FpTolerances protected enum FpTolerances
@@ -383,7 +386,7 @@ namespace Ryujinx.Tests.Cpu
None, None,
UpToOneUlpsS, UpToOneUlpsS,
UpToOneUlpsD UpToOneUlpsD,
} }
protected void CompareAgainstUnicorn( protected void CompareAgainstUnicorn(
@@ -554,13 +557,13 @@ namespace Ryujinx.Tests.Cpu
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1)); return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
} }
protected static V128 MakeVectorScalar(float value) => new V128(value); protected static V128 MakeVectorScalar(float value) => new(value);
protected static V128 MakeVectorScalar(double value) => new V128(value); protected static V128 MakeVectorScalar(double value) => new(value);
protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0); protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1); protected static V128 MakeVectorE1(ulong e1) => new(0, e1);
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new V128(e0, e1); protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new(e0, e1);
protected static V128 MakeVectorE0E1E2E3(uint e0, uint e1, uint e2, uint e3) protected static V128 MakeVectorE0E1E2E3(uint e0, uint e1, uint e2, uint e3)
{ {
@@ -574,7 +577,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort(); do
rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x7C00u) == 0u || while ((rnd & 0x7C00u) == 0u ||
(~rnd & 0x7C00u) == 0u); (~rnd & 0x7C00u) == 0u);
@@ -585,7 +589,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort(); do
rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x03FFu) == 0u); while ((rnd & 0x03FFu) == 0u);
return (ushort)(rnd & 0x83FFu); return (ushort)(rnd & 0x83FFu);
@@ -595,7 +600,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt(); do
rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x7F800000u) == 0u || while ((rnd & 0x7F800000u) == 0u ||
(~rnd & 0x7F800000u) == 0u); (~rnd & 0x7F800000u) == 0u);
@@ -606,7 +612,8 @@ namespace Ryujinx.Tests.Cpu
{ {
uint rnd; uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt(); do
rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x007FFFFFu) == 0u); while ((rnd & 0x007FFFFFu) == 0u);
return rnd & 0x807FFFFFu; return rnd & 0x807FFFFFu;
@@ -616,7 +623,8 @@ namespace Ryujinx.Tests.Cpu
{ {
ulong rnd; ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong(); do
rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x7FF0000000000000ul) == 0ul || while ((rnd & 0x7FF0000000000000ul) == 0ul ||
(~rnd & 0x7FF0000000000000ul) == 0ul); (~rnd & 0x7FF0000000000000ul) == 0ul);
@@ -627,10 +635,11 @@ namespace Ryujinx.Tests.Cpu
{ {
ulong rnd; ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong(); do
rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul); while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
return rnd & 0x800FFFFFFFFFFFFFul; return rnd & 0x800FFFFFFFFFFFFFul;
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Alu #if Alu
#region "Helper methods" #region "Helper methods"
private static uint GenLeadingSignsMinus32(int cnt) // 0 <= cnt <= 31 private static uint GenLeadingSignsMinus32(int cnt) // 0 <= cnt <= 31
{ {
return ~GenLeadingZeros32(cnt + 1); return ~GenLeadingZeros32(cnt + 1);
@@ -33,29 +33,43 @@ namespace Ryujinx.Tests.Cpu
private static uint GenLeadingZeros32(int cnt) // 0 <= cnt <= 32 private static uint GenLeadingZeros32(int cnt) // 0 <= cnt <= 32
{ {
if (cnt == 32) return 0u; if (cnt == 32)
if (cnt == 31) return 1u; {
return 0u;
}
uint rnd = TestContext.CurrentContext.Random.NextUInt(); if (cnt == 31)
int mask = int.MinValue; {
return 1u;
}
uint rnd = TestContext.CurrentContext.Random.NextUInt();
int mask = int.MinValue;
return (rnd >> (cnt + 1)) | ((uint)mask >> cnt); return (rnd >> (cnt + 1)) | ((uint)mask >> cnt);
} }
private static ulong GenLeadingZeros64(int cnt) // 0 <= cnt <= 64 private static ulong GenLeadingZeros64(int cnt) // 0 <= cnt <= 64
{ {
if (cnt == 64) return 0ul; if (cnt == 64)
if (cnt == 63) return 1ul; {
return 0ul;
}
ulong rnd = TestContext.CurrentContext.Random.NextULong(); if (cnt == 63)
long mask = long.MinValue; {
return 1ul;
}
ulong rnd = TestContext.CurrentContext.Random.NextULong();
long mask = long.MinValue;
return (rnd >> (cnt + 1)) | ((ulong)mask >> cnt); return (rnd >> (cnt + 1)) | ((ulong)mask >> cnt);
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _GenLeadingSignsX_() private static IEnumerable<ulong> GenLeadingSignsX()
{ {
for (int cnt = 0; cnt <= 63; cnt++) for (int cnt = 0; cnt <= 63; cnt++)
{ {
@@ -64,7 +78,7 @@ namespace Ryujinx.Tests.Cpu
} }
} }
private static IEnumerable<uint> _GenLeadingSignsW_() private static IEnumerable<uint> GenLeadingSignsW()
{ {
for (int cnt = 0; cnt <= 31; cnt++) for (int cnt = 0; cnt <= 31; cnt++)
{ {
@@ -73,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
} }
} }
private static IEnumerable<ulong> _GenLeadingZerosX_() private static IEnumerable<ulong> GenLeadingZerosX()
{ {
for (int cnt = 0; cnt <= 64; cnt++) for (int cnt = 0; cnt <= 64; cnt++)
{ {
@@ -81,19 +95,19 @@ namespace Ryujinx.Tests.Cpu
} }
} }
private static IEnumerable<uint> _GenLeadingZerosW_() private static IEnumerable<uint> GenLeadingZerosW()
{ {
for (int cnt = 0; cnt <= 32; cnt++) for (int cnt = 0; cnt <= 32; cnt++)
{ {
yield return GenLeadingZeros32(cnt); yield return GenLeadingZeros32(cnt);
} }
} }
#endregion #endregion
[Test, Pairwise, Description("CLS <Xd>, <Xn>")] [Test, Pairwise, Description("CLS <Xd>, <Xn>")]
public void Cls_64bit([Values(0u, 31u)] uint rd, public void Cls_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_GenLeadingSignsX_))] ulong xn) [ValueSource(nameof(GenLeadingSignsX))] ulong xn)
{ {
uint opcode = 0xDAC01400; // CLS X0, X0 uint opcode = 0xDAC01400; // CLS X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -108,7 +122,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLS <Wd>, <Wn>")] [Test, Pairwise, Description("CLS <Wd>, <Wn>")]
public void Cls_32bit([Values(0u, 31u)] uint rd, public void Cls_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_GenLeadingSignsW_))] uint wn) [ValueSource(nameof(GenLeadingSignsW))] uint wn)
{ {
uint opcode = 0x5AC01400; // CLS W0, W0 uint opcode = 0x5AC01400; // CLS W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -123,7 +137,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLZ <Xd>, <Xn>")] [Test, Pairwise, Description("CLZ <Xd>, <Xn>")]
public void Clz_64bit([Values(0u, 31u)] uint rd, public void Clz_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_GenLeadingZerosX_))] ulong xn) [ValueSource(nameof(GenLeadingZerosX))] ulong xn)
{ {
uint opcode = 0xDAC01000; // CLZ X0, X0 uint opcode = 0xDAC01000; // CLZ X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -138,7 +152,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLZ <Wd>, <Wn>")] [Test, Pairwise, Description("CLZ <Wd>, <Wn>")]
public void Clz_32bit([Values(0u, 31u)] uint rd, public void Clz_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_GenLeadingZerosW_))] uint wn) [ValueSource(nameof(GenLeadingZerosW))] uint wn)
{ {
uint opcode = 0x5AC01000; // CLZ W0, W0 uint opcode = 0x5AC01000; // CLZ W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -263,4 +277,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -9,8 +9,8 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Alu32 #if Alu32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _SU_H_AddSub_8_() private static uint[] SuHAddSub8()
{ {
return new[] return new[]
{ {
@@ -21,22 +21,22 @@ namespace Ryujinx.Tests.Cpu
0xe6500f90u, // UADD8 R0, R0, R0 0xe6500f90u, // UADD8 R0, R0, R0
0xe6500ff0u, // USUB8 R0, R0, R0 0xe6500ff0u, // USUB8 R0, R0, R0
0xe6700f90u, // UHADD8 R0, R0, R0 0xe6700f90u, // UHADD8 R0, R0, R0
0xe6700ff0u // UHSUB8 R0, R0, R0 0xe6700ff0u, // UHSUB8 R0, R0, R0
}; };
} }
private static uint[] _Ssat_Usat_() private static uint[] SsatUsat()
{ {
return new[] return new[]
{ {
0xe6a00010u, // SSAT R0, #1, R0, LSL #0 0xe6a00010u, // SSAT R0, #1, R0, LSL #0
0xe6a00050u, // SSAT R0, #1, R0, ASR #32 0xe6a00050u, // SSAT R0, #1, R0, ASR #32
0xe6e00010u, // USAT R0, #0, R0, LSL #0 0xe6e00010u, // USAT R0, #0, R0, LSL #0
0xe6e00050u // USAT R0, #0, R0, ASR #32 0xe6e00050u, // USAT R0, #0, R0, ASR #32
}; };
} }
private static uint[] _Ssat16_Usat16_() private static uint[] Ssat16Usat16()
{ {
return new[] return new[]
{ {
@@ -45,17 +45,17 @@ namespace Ryujinx.Tests.Cpu
}; };
} }
private static uint[] _Lsr_Lsl_Asr_Ror_() private static uint[] LsrLslAsrRor()
{ {
return new[] return new[]
{ {
0xe1b00030u, // LSRS R0, R0, R0 0xe1b00030u, // LSRS R0, R0, R0
0xe1b00010u, // LSLS R0, R0, R0 0xe1b00010u, // LSLS R0, R0, R0
0xe1b00050u, // ASRS R0, R0, R0 0xe1b00050u, // ASRS R0, R0, R0
0xe1b00070u // RORS R0, R0, R0 0xe1b00070u, // RORS R0, R0, R0
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
@@ -76,7 +76,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Test, Pairwise]
public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(_Lsr_Lsl_Asr_Ror_))] uint opcode, public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(LsrLslAsrRor))] uint opcode,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] uint shiftValue, 0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
[Range(0, 31)] int shiftAmount) [Range(0, 31)] int shiftAmount)
@@ -130,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Test, Pairwise]
public void Ssat_Usat([ValueSource(nameof(_Ssat_Usat_))] uint opcode, public void Ssat_Usat([ValueSource(nameof(SsatUsat))] uint opcode,
[Values(0u, 0xdu)] uint rd, [Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn, [Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat, [Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
@@ -148,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Test, Pairwise]
public void Ssat16_Usat16([ValueSource(nameof(_Ssat16_Usat16_))] uint opcode, public void Ssat16_Usat16([ValueSource(nameof(Ssat16Usat16))] uint opcode,
[Values(0u, 0xdu)] uint rd, [Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn, [Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu)] uint sat, [Values(0u, 7u, 8u, 0xfu)] uint sat,
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Test, Pairwise]
public void SU_H_AddSub_8([ValueSource(nameof(_SU_H_AddSub_8_))] uint opcode, public void SU_H_AddSub_8([ValueSource(nameof(SuHAddSub8))] uint opcode,
[Values(0u, 0xdu)] uint rd, [Values(0u, 0xdu)] uint rd,
[Values(1u)] uint rm, [Values(1u)] uint rm,
[Values(2u)] uint rn, [Values(2u)] uint rn,
@@ -191,9 +191,9 @@ namespace Ryujinx.Tests.Cpu
[Random(RndCnt)] uint w2) [Random(RndCnt)] uint w2)
{ {
uint opUadd8 = 0xE6500F90; // UADD8 R0, R0, R0 uint opUadd8 = 0xE6500F90; // UADD8 R0, R0, R0
uint opSel = 0xE6800FB0; // SEL R0, R0, R0 uint opSel = 0xE6800FB0; // SEL R0, R0, R0
opUadd8 |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); opUadd8 |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
opSel |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); opSel |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
SetContext(r0: w0, r1: w1, r2: w2); SetContext(r0: w0, r1: w1, r2: w2);
@@ -206,4 +206,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.Tests.Cpu
} }
} }
#region "ValueSource (CRC32)" #region "ValueSource (CRC32)"
private static CrcTest[] _CRC32_Test_Values_() private static CrcTest[] _CRC32_Test_Values_()
{ {
// Created with http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, with: // Created with http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, with:
@@ -48,10 +48,10 @@ namespace Ryujinx.Tests.Cpu
new CrcTest(0xffffffffu, 0x7f_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0x3303a3c3), new CrcTest(0xffffffffu, 0x7f_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0x3303a3c3),
new CrcTest(0xffffffffu, 0x80_00_00_00_00_00_00_00u, false, 0x2dfd1072, 0xbe26ed00, 0xdebb20e3, 0x7765a3b6), new CrcTest(0xffffffffu, 0x80_00_00_00_00_00_00_00u, false, 0x2dfd1072, 0xbe26ed00, 0xdebb20e3, 0x7765a3b6),
new CrcTest(0xffffffffu, 0xff_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0xdebb20e3), new CrcTest(0xffffffffu, 0xff_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0xdebb20e3),
new CrcTest(0xffffffffu, 0xa0_02_f1_ca_52_78_8c_1cu, false, 0x39fc4c3d, 0xbc5f7f56, 0x4ed8e906, 0x12cb419c) new CrcTest(0xffffffffu, 0xa0_02_f1_ca_52_78_8c_1cu, false, 0x39fc4c3d, 0xbc5f7f56, 0x4ed8e906, 0x12cb419c),
}; };
} }
#endregion #endregion
[Test, Combinatorial] [Test, Combinatorial]
public void Crc32_b_h_w_x([Values(0u)] uint rd, public void Crc32_b_h_w_x([Values(0u)] uint rd,
@@ -304,4 +304,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
} }
} }
#region "ValueSource (CRC32/CRC32C)" #region "ValueSource (CRC32/CRC32C)"
private static CrcTest32[] _CRC32_Test_Values_() private static CrcTest32[] _CRC32_Test_Values_()
{ {
// Created with http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, with: // Created with http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, with:
@@ -60,10 +60,10 @@ namespace Ryujinx.Tests.Cpu
new CrcTest32(0xffffffffu, 0x7f_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x82f63b78), new CrcTest32(0xffffffffu, 0x7f_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x82f63b78),
new CrcTest32(0xffffffffu, 0x80_00_00_00u, true, 0xad82acae, 0x0e9e882d, 0x356e8f40), new CrcTest32(0xffffffffu, 0x80_00_00_00u, true, 0xad82acae, 0x0e9e882d, 0x356e8f40),
new CrcTest32(0xffffffffu, 0xff_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x00000000), new CrcTest32(0xffffffffu, 0xff_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x00000000),
new CrcTest32(0xffffffffu, 0x9d_cb_12_f0u, true, 0x5eecc3db, 0xbb6111cb, 0xcfb54fc9) new CrcTest32(0xffffffffu, 0x9d_cb_12_f0u, true, 0x5eecc3db, 0xbb6111cb, 0xcfb54fc9),
}; };
} }
#endregion #endregion
[Test, Combinatorial] [Test, Combinatorial]
public void Crc32_Crc32c_b_h_w([Values(0u)] uint rd, public void Crc32_Crc32c_b_h_w([Values(0u)] uint rd,

View File

@@ -430,4 +430,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -9,8 +9,8 @@ namespace Ryujinx.Tests.Cpu
{ {
#if AluRs32 #if AluRs32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _opcodes() private static uint[] Opcodes()
{ {
return new[] return new[]
{ {
@@ -30,12 +30,12 @@ namespace Ryujinx.Tests.Cpu
0xe2500000u, // SUBS R0, R0, #0 0xe2500000u, // SUBS R0, R0, #0
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
[Test, Pairwise] [Test, Pairwise]
public void TestCpuTestAluImm32([ValueSource(nameof(_opcodes))] uint opcode, public void TestCpuTestAluImm32([ValueSource(nameof(Opcodes))] uint opcode,
[Values(0u, 13u)] uint rd, [Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn, [Values(1u, 13u)] uint rn,
[Random(RndCnt)] uint imm, [Random(RndCnt)] uint imm,
@@ -52,4 +52,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -892,4 +892,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if AluRs32 #if AluRs32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Add_Adds_Rsb_Rsbs_() private static uint[] _Add_Adds_Rsb_Rsbs_()
{ {
return new[] return new[]
@@ -17,7 +17,7 @@ namespace Ryujinx.Tests.Cpu
0xe0800000u, // ADD R0, R0, R0, LSL #0 0xe0800000u, // ADD R0, R0, R0, LSL #0
0xe0900000u, // ADDS R0, R0, R0, LSL #0 0xe0900000u, // ADDS R0, R0, R0, LSL #0
0xe0600000u, // RSB R0, R0, R0, LSL #0 0xe0600000u, // RSB R0, R0, R0, LSL #0
0xe0700000u // RSBS R0, R0, R0, LSL #0 0xe0700000u, // RSBS R0, R0, R0, LSL #0
}; };
} }
@@ -30,14 +30,14 @@ namespace Ryujinx.Tests.Cpu
0xe0e00000u, // RSC R0, R0, R0 0xe0e00000u, // RSC R0, R0, R0
0xe0f00000u, // RSCS R0, R0, R0 0xe0f00000u, // RSCS R0, R0, R0
0xe0c00000u, // SBC R0, R0, R0 0xe0c00000u, // SBC R0, R0, R0
0xe0d00000u // SBCS R0, R0, R0 0xe0d00000u, // SBCS R0, R0, R0
}; };
} }
#endregion #endregion
[Test, Pairwise] [Test, Pairwise]
public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource("_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_")] uint opcode, public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource(nameof(_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_))] uint opcode,
[Values(0u, 13u)] uint rd, [Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn, [Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm, [Values(2u, 13u)] uint rm,
@@ -57,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Test, Pairwise]
public void Add_Adds_Rsb_Rsbs([ValueSource("_Add_Adds_Rsb_Rsbs_")] uint opcode, public void Add_Adds_Rsb_Rsbs([ValueSource(nameof(_Add_Adds_Rsb_Rsbs_))] uint opcode,
[Values(0u, 13u)] uint rd, [Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn, [Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm, [Values(2u, 13u)] uint rm,
@@ -79,4 +79,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -720,4 +720,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -103,4 +103,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestBfm : CpuTest public sealed class CpuTestBfm : CpuTest
{ {
#if Bfm #if Bfm
private const int RndCnt = 2; private const int RndCnt = 2;
[Test, Pairwise, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")] [Test, Pairwise, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Bfm_64bit([Values(0u, 31u)] uint rd, public void Bfm_64bit([Values(0u, 31u)] uint rd,
@@ -127,4 +127,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -99,4 +99,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -107,4 +107,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -202,4 +202,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Misc #if Misc
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
{ {
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue) yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -24,19 +24,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -54,15 +54,15 @@ namespace Ryujinx.Tests.Cpu
yield return (grbg << 32) | rnd2; yield return (grbg << 32) | rnd2;
} }
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
#region "AluImm & Csel" #region "AluImm & Csel"
[Test, Pairwise] [Test, Pairwise]
public void Adds_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, public void Adds_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
@@ -73,10 +73,10 @@ namespace Ryujinx.Tests.Cpu
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
0b1100u, 0b1101u)] uint cond) // GT, LE> 0b1100u, 0b1101u)] uint cond) // GT, LE>
{ {
uint opCmn = 0xB100001F; // ADDS X31, X0, #0, LSL #0 -> CMN X0, #0, LSL #0 uint opCmn = 0xB100001F; // ADDS X31, X0, #0, LSL #0 -> CMN X0, #0, LSL #0
uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE
opCmn |= ((shift & 3) << 22) | ((imm & 4095) << 10); opCmn |= ((shift & 3) << 22) | ((imm & 4095) << 10);
opCset |= ((cond & 15) << 12); opCset |= ((cond & 15) << 12);
SetContext(x0: xn); SetContext(x0: xn);
@@ -98,10 +98,10 @@ namespace Ryujinx.Tests.Cpu
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
0b1100u, 0b1101u)] uint cond) // GT, LE> 0b1100u, 0b1101u)] uint cond) // GT, LE>
{ {
uint opCmn = 0x3100001F; // ADDS W31, W0, #0, LSL #0 -> CMN W0, #0, LSL #0 uint opCmn = 0x3100001F; // ADDS W31, W0, #0, LSL #0 -> CMN W0, #0, LSL #0
uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE
opCmn |= ((shift & 3) << 22) | ((imm & 4095) << 10); opCmn |= ((shift & 3) << 22) | ((imm & 4095) << 10);
opCset |= ((cond & 15) << 12); opCset |= ((cond & 15) << 12);
SetContext(x0: wn); SetContext(x0: wn);
@@ -123,10 +123,10 @@ namespace Ryujinx.Tests.Cpu
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
0b1100u, 0b1101u)] uint cond) // GT, LE> 0b1100u, 0b1101u)] uint cond) // GT, LE>
{ {
uint opCmp = 0xF100001F; // SUBS X31, X0, #0, LSL #0 -> CMP X0, #0, LSL #0 uint opCmp = 0xF100001F; // SUBS X31, X0, #0, LSL #0 -> CMP X0, #0, LSL #0
uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE
opCmp |= ((shift & 3) << 22) | ((imm & 4095) << 10); opCmp |= ((shift & 3) << 22) | ((imm & 4095) << 10);
opCset |= ((cond & 15) << 12); opCset |= ((cond & 15) << 12);
SetContext(x0: xn); SetContext(x0: xn);
@@ -148,10 +148,10 @@ namespace Ryujinx.Tests.Cpu
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
0b1100u, 0b1101u)] uint cond) // GT, LE> 0b1100u, 0b1101u)] uint cond) // GT, LE>
{ {
uint opCmp = 0x7100001F; // SUBS W31, W0, #0, LSL #0 -> CMP W0, #0, LSL #0 uint opCmp = 0x7100001F; // SUBS W31, W0, #0, LSL #0 -> CMP W0, #0, LSL #0
uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE
opCmp |= ((shift & 3) << 22) | ((imm & 4095) << 10); opCmp |= ((shift & 3) << 22) | ((imm & 4095) << 10);
opCset |= ((cond & 15) << 12); opCset |= ((cond & 15) << 12);
SetContext(x0: wn); SetContext(x0: wn);
@@ -162,10 +162,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endregion #endregion
// Roots.
[Explicit] [Explicit]
[TestCase(0xFFFFFFFDu)] // Roots. [TestCase(0xFFFFFFFDu)]
[TestCase(0x00000005u)] [TestCase(0x00000005u)]
public void Misc1(uint a) public void Misc1(uint a)
{ {
@@ -196,25 +197,26 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetX(0), Is.Zero); Assert.That(GetContext().GetX(0), Is.Zero);
} }
// 18 integer solutions.
[Explicit] [Explicit]
[TestCase(-20f, -5f)] // 18 integer solutions. [TestCase(-20f, -5f)]
[TestCase(-12f, -6f)] [TestCase(-12f, -6f)]
[TestCase(-12f, 3f)] [TestCase(-12f, 3f)]
[TestCase( -8f, -8f)] [TestCase(-8f, -8f)]
[TestCase( -6f, -12f)] [TestCase(-6f, -12f)]
[TestCase( -5f, -20f)] [TestCase(-5f, -20f)]
[TestCase( -4f, 2f)] [TestCase(-4f, 2f)]
[TestCase( -3f, 12f)] [TestCase(-3f, 12f)]
[TestCase( -2f, 4f)] [TestCase(-2f, 4f)]
[TestCase( 2f, -4f)] [TestCase(2f, -4f)]
[TestCase( 3f, -12f)] [TestCase(3f, -12f)]
[TestCase( 4f, -2f)] [TestCase(4f, -2f)]
[TestCase( 5f, 20f)] [TestCase(5f, 20f)]
[TestCase( 6f, 12f)] [TestCase(6f, 12f)]
[TestCase( 8f, 8f)] [TestCase(8f, 8f)]
[TestCase( 12f, -3f)] [TestCase(12f, -3f)]
[TestCase( 12f, 6f)] [TestCase(12f, 6f)]
[TestCase( 20f, 5f)] [TestCase(20f, 5f)]
public void Misc2(float a, float b) public void Misc2(float a, float b)
{ {
// 1 / ((1 / a + 1 / b) ^ 2) = 16 // 1 / ((1 / a + 1 / b) ^ 2) = 16
@@ -242,25 +244,26 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetV(0).As<float>(), Is.EqualTo(16f)); Assert.That(GetContext().GetV(0).As<float>(), Is.EqualTo(16f));
} }
// 18 integer solutions.
[Explicit] [Explicit]
[TestCase(-20d, -5d)] // 18 integer solutions. [TestCase(-20d, -5d)]
[TestCase(-12d, -6d)] [TestCase(-12d, -6d)]
[TestCase(-12d, 3d)] [TestCase(-12d, 3d)]
[TestCase( -8d, -8d)] [TestCase(-8d, -8d)]
[TestCase( -6d, -12d)] [TestCase(-6d, -12d)]
[TestCase( -5d, -20d)] [TestCase(-5d, -20d)]
[TestCase( -4d, 2d)] [TestCase(-4d, 2d)]
[TestCase( -3d, 12d)] [TestCase(-3d, 12d)]
[TestCase( -2d, 4d)] [TestCase(-2d, 4d)]
[TestCase( 2d, -4d)] [TestCase(2d, -4d)]
[TestCase( 3d, -12d)] [TestCase(3d, -12d)]
[TestCase( 4d, -2d)] [TestCase(4d, -2d)]
[TestCase( 5d, 20d)] [TestCase(5d, 20d)]
[TestCase( 6d, 12d)] [TestCase(6d, 12d)]
[TestCase( 8d, 8d)] [TestCase(8d, 8d)]
[TestCase( 12d, -3d)] [TestCase(12d, -3d)]
[TestCase( 12d, 6d)] [TestCase(12d, 6d)]
[TestCase( 20d, 5d)] [TestCase(20d, 5d)]
public void Misc3(double a, double b) public void Misc3(double a, double b)
{ {
// 1 / ((1 / a + 1 / b) ^ 2) = 16 // 1 / ((1 / a + 1 / b) ^ 2) = 16
@@ -291,7 +294,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Ignore("The Tester supports only one return point.")] [Test, Ignore("The Tester supports only one return point.")]
public void MiscF([Range(0u, 92u, 1u)] uint a) public void MiscF([Range(0u, 92u, 1u)] uint a)
{ {
ulong Fn(uint n) static ulong Fn(uint n)
{ {
ulong x = 0, y = 1, z; ulong x = 0, y = 1, z;
@@ -395,9 +398,9 @@ namespace Ryujinx.Tests.Cpu
} }
[Explicit] [Explicit]
[TestCase( 0ul)] [TestCase(0ul)]
[TestCase( 1ul)] [TestCase(1ul)]
[TestCase( 2ul)] [TestCase(2ul)]
[TestCase(42ul)] [TestCase(42ul)]
public void SanityCheck(ulong a) public void SanityCheck(ulong a)
{ {
@@ -439,8 +442,8 @@ namespace Ryujinx.Tests.Cpu
v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()),
v2: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), v2: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()),
overflow: TestContext.CurrentContext.Random.NextBool(), overflow: TestContext.CurrentContext.Random.NextBool(),
carry: TestContext.CurrentContext.Random.NextBool(), carry: TestContext.CurrentContext.Random.NextBool(),
zero: TestContext.CurrentContext.Random.NextBool(), zero: TestContext.CurrentContext.Random.NextBool(),
negative: TestContext.CurrentContext.Random.NextBool()); negative: TestContext.CurrentContext.Random.NextBool());
Opcode(0xBD400001); // LDR S1, [X0,#0] Opcode(0xBD400001); // LDR S1, [X0,#0]
@@ -463,8 +466,8 @@ namespace Ryujinx.Tests.Cpu
v0: MakeVectorE0E1(a, TestContext.CurrentContext.Random.NextULong()), v0: MakeVectorE0E1(a, TestContext.CurrentContext.Random.NextULong()),
v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()),
overflow: TestContext.CurrentContext.Random.NextBool(), overflow: TestContext.CurrentContext.Random.NextBool(),
carry: TestContext.CurrentContext.Random.NextBool(), carry: TestContext.CurrentContext.Random.NextBool(),
zero: TestContext.CurrentContext.Random.NextBool(), zero: TestContext.CurrentContext.Random.NextBool(),
negative: TestContext.CurrentContext.Random.NextBool()); negative: TestContext.CurrentContext.Random.NextBool());
Opcode(0x1E202008); // FCMP S0, #0.0 Opcode(0x1E202008); // FCMP S0, #0.0

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Misc32 #if Misc32
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
{ {
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue) yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -53,13 +53,13 @@ namespace Ryujinx.Tests.Cpu
yield return (grbg << 32) | rnd2; yield return (grbg << 32) | rnd2;
} }
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise] [Test, Pairwise]
public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a, public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a,
@@ -75,10 +75,10 @@ namespace Ryujinx.Tests.Cpu
? TestContext.CurrentContext.Random.NextUInt(0xf) << 28 ? TestContext.CurrentContext.Random.NextUInt(0xf) << 28
: TestContext.CurrentContext.Random.NextUInt(); : TestContext.CurrentContext.Random.NextUInt();
bool v = mode3 ? TestContext.CurrentContext.Random.NextBool() : false; bool v = mode3 && TestContext.CurrentContext.Random.NextBool();
bool c = mode3 ? TestContext.CurrentContext.Random.NextBool() : false; bool c = mode3 && TestContext.CurrentContext.Random.NextBool();
bool z = mode3 ? TestContext.CurrentContext.Random.NextBool() : false; bool z = mode3 && TestContext.CurrentContext.Random.NextBool();
bool n = mode3 ? TestContext.CurrentContext.Random.NextBool() : false; bool n = mode3 && TestContext.CurrentContext.Random.NextBool();
int fpscr = mode1 int fpscr = mode1
? (int)TestContext.CurrentContext.Random.NextUInt() ? (int)TestContext.CurrentContext.Random.NextUInt()

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestMov : CpuTest public sealed class CpuTestMov : CpuTest
{ {
#if Mov #if Mov
private const int RndCnt = 2; private const int RndCnt = 2;
[Test, Pairwise, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")]
public void Movk_64bit([Values(0u, 31u)] uint rd, public void Movk_64bit([Values(0u, 31u)] uint rd,
@@ -109,4 +109,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -223,4 +223,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Mul32 #if Mul32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Smlabb_Smlabt_Smlatb_Smlatt_() private static uint[] _Smlabb_Smlabt_Smlatb_Smlatt_()
{ {
return new[] return new[]
@@ -49,10 +49,10 @@ namespace Ryujinx.Tests.Cpu
0xe12000e0u, // SMULWT R0, R0, R0 0xe12000e0u, // SMULWT R0, R0, R0
}; };
} }
#endregion #endregion
[Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")] [Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")]
public void Smla___32bit([ValueSource("_Smlabb_Smlabt_Smlatb_Smlatt_")] uint opcode, public void Smla___32bit([ValueSource(nameof(_Smlabb_Smlabt_Smlatb_Smlatt_))] uint opcode,
[Values(0u, 0xdu)] uint rn, [Values(0u, 0xdu)] uint rn,
[Values(1u, 0xdu)] uint rm, [Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint ra, [Values(2u, 0xdu)] uint ra,
@@ -74,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("SMLAW<x> <Rd>, <Rn>, <Rm>, <Ra>")] [Test, Pairwise, Description("SMLAW<x> <Rd>, <Rn>, <Rm>, <Ra>")]
public void Smlaw__32bit([ValueSource("_Smlawb_Smlawt_")] uint opcode, public void Smlaw__32bit([ValueSource(nameof(_Smlawb_Smlawt_))] uint opcode,
[Values(0u, 0xdu)] uint rn, [Values(0u, 0xdu)] uint rn,
[Values(1u, 0xdu)] uint rm, [Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint ra, [Values(2u, 0xdu)] uint ra,
@@ -96,7 +96,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("SMUL<x><y> <Rd>, <Rn>, <Rm>")] [Test, Pairwise, Description("SMUL<x><y> <Rd>, <Rn>, <Rm>")]
public void Smul___32bit([ValueSource("_Smulbb_Smulbt_Smultb_Smultt_")] uint opcode, public void Smul___32bit([ValueSource(nameof(_Smulbb_Smulbt_Smultb_Smultt_))] uint opcode,
[Values(0u, 0xdu)] uint rn, [Values(0u, 0xdu)] uint rn,
[Values(1u, 0xdu)] uint rm, [Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd, [Values(2u, 0xdu)] uint rd,
@@ -115,7 +115,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("SMULW<x> <Rd>, <Rn>, <Rm>")] [Test, Pairwise, Description("SMULW<x> <Rd>, <Rn>, <Rm>")]
public void Smulw__32bit([ValueSource("_Smulwb_Smulwt_")] uint opcode, public void Smulw__32bit([ValueSource(nameof(_Smulwb_Smulwt_))] uint opcode,
[Values(0u, 0xdu)] uint rn, [Values(0u, 0xdu)] uint rn,
[Values(1u, 0xdu)] uint rm, [Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd, [Values(2u, 0xdu)] uint rd,
@@ -134,4 +134,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,14 @@ namespace Ryujinx.Tests.Cpu
{ {
#if Simd32 #if Simd32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Vabs_Vneg_Vpaddl_I_() private static uint[] _Vabs_Vneg_Vpaddl_I_()
{ {
return new[] return new[]
{ {
0xf3b10300u, // VABS.S8 D0, D0 0xf3b10300u, // VABS.S8 D0, D0
0xf3b10380u, // VNEG.S8 D0, D0 0xf3b10380u, // VNEG.S8 D0, D0
0xf3b00200u // VPADDL.S8 D0, D0 0xf3b00200u, // VPADDL.S8 D0, D0
}; };
} }
@@ -27,18 +27,20 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0xf3b90700u, // VABS.F32 D0, D0 0xf3b90700u, // VABS.F32 D0, D0
0xf3b90780u // VNEG.F32 D0, D0 0xf3b90780u, // VNEG.F32 D0, D0
}; };
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
@@ -52,19 +54,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -94,19 +96,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000080000000ul; // -Zero yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFF800000FF800000ul; // -Infinity yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity yield return 0x7F8000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -135,19 +137,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -173,13 +175,13 @@ namespace Ryujinx.Tests.Cpu
(cnt << 24) | (cnt << 16) | (cnt << 08) | cnt; (cnt << 24) | (cnt << 16) | (cnt << 08) | cnt;
} }
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")] [Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")]
public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode, public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode,
@@ -193,7 +195,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x74CED221E2793F07ul)] ulong resultH) [Values(0x74CED221E2793F07ul)] ulong resultH)
{ {
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1); V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1); V128 v1 = MakeVectorE0E1(a0, a1);
@@ -223,12 +225,14 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rm >>= 1; rm <<= 1; rd <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (size & 0x3) << 18; opcode |= (size & 0x3) << 18;
@@ -252,12 +256,14 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rm >>= 1; rm <<= 1; rd <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z, ~z); V128 v0 = MakeVectorE0E1(z, ~z);
V128 v1 = MakeVectorE0E1(b, ~b); V128 v1 = MakeVectorE0E1(b, ~b);
@@ -286,7 +292,7 @@ namespace Ryujinx.Tests.Cpu
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(d0, d1); V128 v0 = MakeVectorE0E1(d0, d1);
@@ -303,12 +309,13 @@ namespace Ryujinx.Tests.Cpu
[Values(0u, 1u, 2u, 3u)] uint op, [Values(0u, 1u, 2u, 3u)] uint op,
[Values(0u, 1u, 2u)] uint size) // <S8, S16, S32> [Values(0u, 1u, 2u)] uint size) // <S8, S16, S32>
{ {
rm >>= 1; rm <<= 1; rm >>= 1;
rm <<= 1;
uint opcode = 0xf3b20200u; // VMOVN.S16 D0, Q0 uint opcode = 0xf3b20200u; // VMOVN.S16 D0, Q0
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (op & 0x3) << 6; opcode |= (op & 0x3) << 6;
opcode |= (size & 0x3) << 18; opcode |= (size & 0x3) << 18;
@@ -322,4 +329,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -1,7 +1,6 @@
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf // https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
@@ -13,8 +12,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u)] uint rn, [Values(1u)] uint rn,
[Values(0x7B5B546573745665ul)] ulong valueH, [Values(0x7B5B546573745665ul)] ulong valueH,
[Values(0x63746F725D53475Dul)] ulong valueL, [Values(0x63746F725D53475Dul)] ulong valueL,
[Random(2)] ulong roundKeyH, [Random(2)] ulong roundKeyH,
[Random(2)] ulong roundKeyL, [Random(2)] ulong roundKeyL,
[Values(0x8DCAB9BC035006BCul)] ulong resultH, [Values(0x8DCAB9BC035006BCul)] ulong resultH,
[Values(0x8F57161E00CAFD8Dul)] ulong resultL) [Values(0x8F57161E00CAFD8Dul)] ulong resultL)
{ {
@@ -22,7 +21,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
V128 v0 = MakeVectorE0E1(roundKeyL ^ valueL, roundKeyH ^ valueH); V128 v0 = MakeVectorE0E1(roundKeyL ^ valueL, roundKeyH ^ valueH);
V128 v1 = MakeVectorE0E1(roundKeyL, roundKeyH); V128 v1 = MakeVectorE0E1(roundKeyL, roundKeyH);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1); ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1);
@@ -45,8 +44,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u)] uint rn, [Values(1u)] uint rn,
[Values(0x7B5B546573745665ul)] ulong valueH, [Values(0x7B5B546573745665ul)] ulong valueH,
[Values(0x63746F725D53475Dul)] ulong valueL, [Values(0x63746F725D53475Dul)] ulong valueL,
[Random(2)] ulong roundKeyH, [Random(2)] ulong roundKeyH,
[Random(2)] ulong roundKeyL, [Random(2)] ulong roundKeyL,
[Values(0x8F92A04DFBED204Dul)] ulong resultH, [Values(0x8F92A04DFBED204Dul)] ulong resultH,
[Values(0x4C39B1402192A84Cul)] ulong resultL) [Values(0x4C39B1402192A84Cul)] ulong resultL)
{ {
@@ -54,7 +53,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
V128 v0 = MakeVectorE0E1(roundKeyL ^ valueL, roundKeyH ^ valueH); V128 v0 = MakeVectorE0E1(roundKeyL ^ valueL, roundKeyH ^ valueH);
V128 v1 = MakeVectorE0E1(roundKeyL, roundKeyH); V128 v1 = MakeVectorE0E1(roundKeyL, roundKeyH);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1); ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1);
@@ -73,7 +72,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Description("AESIMC <Vd>.16B, <Vn>.16B")] [Test, Description("AESIMC <Vd>.16B, <Vn>.16B")]
public void Aesimc_V([Values(0u)] uint rd, public void Aesimc_V([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(0x8DCAB9DC035006BCul)] ulong valueH, [Values(0x8DCAB9DC035006BCul)] ulong valueH,
[Values(0x8F57161E00CAFD8Dul)] ulong valueL, [Values(0x8F57161E00CAFD8Dul)] ulong valueL,
@@ -87,8 +86,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode( ExecutionContext context = SingleOpcode(
opcode, opcode,
v0: rn == 0u ? v : default(V128), v0: rn == 0u ? v : default,
v1: rn == 1u ? v : default(V128)); v1: rn == 1u ? v : default);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
@@ -108,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Description("AESMC <Vd>.16B, <Vn>.16B")] [Test, Description("AESMC <Vd>.16B, <Vn>.16B")]
public void Aesmc_V([Values(0u)] uint rd, public void Aesmc_V([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(0x627A6F6644B109C8ul)] ulong valueH, [Values(0x627A6F6644B109C8ul)] ulong valueH,
[Values(0x2B18330A81C3B3E5ul)] ulong valueL, [Values(0x2B18330A81C3B3E5ul)] ulong valueL,
@@ -122,8 +121,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode( ExecutionContext context = SingleOpcode(
opcode, opcode,
v0: rn == 0u ? v : default(V128), v0: rn == 0u ? v : default,
v1: rn == 1u ? v : default(V128)); v1: rn == 1u ? v : default);
Assert.Multiple(() => Assert.Multiple(() =>
{ {

View File

@@ -1,7 +1,6 @@
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf // https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
@@ -13,8 +12,8 @@ namespace Ryujinx.Tests.Cpu
[Values(2u)] uint rm, [Values(2u)] uint rm,
[Values(0x7B5B546573745665ul)] ulong valueH, [Values(0x7B5B546573745665ul)] ulong valueH,
[Values(0x63746F725D53475Dul)] ulong valueL, [Values(0x63746F725D53475Dul)] ulong valueL,
[Random(2)] ulong roundKeyH, [Random(2)] ulong roundKeyH,
[Random(2)] ulong roundKeyL, [Random(2)] ulong roundKeyL,
[Values(0x8DCAB9BC035006BCul)] ulong resultH, [Values(0x8DCAB9BC035006BCul)] ulong resultH,
[Values(0x8F57161E00CAFD8Dul)] ulong resultL) [Values(0x8F57161E00CAFD8Dul)] ulong resultL)
{ {
@@ -47,8 +46,8 @@ namespace Ryujinx.Tests.Cpu
[Values(2u)] uint rm, [Values(2u)] uint rm,
[Values(0x7B5B546573745665ul)] ulong valueH, [Values(0x7B5B546573745665ul)] ulong valueH,
[Values(0x63746F725D53475Dul)] ulong valueL, [Values(0x63746F725D53475Dul)] ulong valueL,
[Random(2)] ulong roundKeyH, [Random(2)] ulong roundKeyH,
[Random(2)] ulong roundKeyL, [Random(2)] ulong roundKeyL,
[Values(0x8F92A04DFBED204Dul)] ulong resultH, [Values(0x8F92A04DFBED204Dul)] ulong resultH,
[Values(0x4C39B1402192A84Cul)] ulong resultL) [Values(0x4C39B1402192A84Cul)] ulong resultL)
{ {
@@ -77,7 +76,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Description("AESIMC.8 <Qd>, <Qm>")] [Test, Description("AESIMC.8 <Qd>, <Qm>")]
public void Aesimc_V([Values(0u)] uint rd, public void Aesimc_V([Values(0u)] uint rd,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[Values(0x8DCAB9DC035006BCul)] ulong valueH, [Values(0x8DCAB9DC035006BCul)] ulong valueH,
[Values(0x8F57161E00CAFD8Dul)] ulong valueL, [Values(0x8F57161E00CAFD8Dul)] ulong valueL,
@@ -92,8 +91,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode( ExecutionContext context = SingleOpcode(
opcode, opcode,
v0: rm == 0u ? v : default(V128), v0: rm == 0u ? v : default,
v1: rm == 2u ? v : default(V128), v1: rm == 2u ? v : default,
runUnicorn: false); runUnicorn: false);
Assert.Multiple(() => Assert.Multiple(() =>
@@ -115,7 +114,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Description("AESMC.8 <Qd>, <Qm>")] [Test, Description("AESMC.8 <Qd>, <Qm>")]
public void Aesmc_V([Values(0u)] uint rd, public void Aesmc_V([Values(0u)] uint rd,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[Values(0x627A6F6644B109C8ul)] ulong valueH, [Values(0x627A6F6644B109C8ul)] ulong valueH,
[Values(0x2B18330A81C3B3E5ul)] ulong valueL, [Values(0x2B18330A81C3B3E5ul)] ulong valueL,
@@ -130,8 +129,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode( ExecutionContext context = SingleOpcode(
opcode, opcode,
v0: rm == 0u ? v : default(V128), v0: rm == 0u ? v : default,
v1: rm == 2u ? v : default(V128), v1: rm == 2u ? v : default,
runUnicorn: false); runUnicorn: false);
Assert.Multiple(() => Assert.Multiple(() =>

View File

@@ -12,17 +12,21 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdCvt #if SimdCvt
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static uint[] _W_() private static uint[] _W_()
{ {
return new[] { 0x00000000u, 0x7FFFFFFFu, return new[] {
0x80000000u, 0xFFFFFFFFu }; 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu,
};
} }
private static ulong[] _X_() private static ulong[] _X_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _1S_F_WX_() private static IEnumerable<ulong> _1S_F_WX_()
@@ -62,19 +66,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -145,19 +149,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -188,9 +192,9 @@ namespace Ryujinx.Tests.Cpu
yield return rnd6; yield return rnd6;
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_AMPZ_SU_Gp_SW_() private static uint[] _F_Cvt_AMPZ_SU_Gp_SW_()
{ {
return new[] return new[]
@@ -203,7 +207,7 @@ namespace Ryujinx.Tests.Cpu
0x1E280000u, // FCVTPS W0, S0 0x1E280000u, // FCVTPS W0, S0
0x1E290000u, // FCVTPU W0, S0 0x1E290000u, // FCVTPU W0, S0
0x1E380000u, // FCVTZS W0, S0 0x1E380000u, // FCVTZS W0, S0
0x1E390000u // FCVTZU W0, S0 0x1E390000u, // FCVTZU W0, S0
}; };
} }
@@ -219,7 +223,7 @@ namespace Ryujinx.Tests.Cpu
0x9E280000u, // FCVTPS X0, S0 0x9E280000u, // FCVTPS X0, S0
0x9E290000u, // FCVTPU X0, S0 0x9E290000u, // FCVTPU X0, S0
0x9E380000u, // FCVTZS X0, S0 0x9E380000u, // FCVTZS X0, S0
0x9E390000u // FCVTZU X0, S0 0x9E390000u, // FCVTZU X0, S0
}; };
} }
@@ -235,7 +239,7 @@ namespace Ryujinx.Tests.Cpu
0x1E680000u, // FCVTPS W0, D0 0x1E680000u, // FCVTPS W0, D0
0x1E690000u, // FCVTPU W0, D0 0x1E690000u, // FCVTPU W0, D0
0x1E780000u, // FCVTZS W0, D0 0x1E780000u, // FCVTZS W0, D0
0x1E790000u // FCVTZU W0, D0 0x1E790000u, // FCVTZU W0, D0
}; };
} }
@@ -251,7 +255,7 @@ namespace Ryujinx.Tests.Cpu
0x9E680000u, // FCVTPS X0, D0 0x9E680000u, // FCVTPS X0, D0
0x9E690000u, // FCVTPU X0, D0 0x9E690000u, // FCVTPU X0, D0
0x9E780000u, // FCVTZS X0, D0 0x9E780000u, // FCVTZS X0, D0
0x9E790000u // FCVTZU X0, D0 0x9E790000u, // FCVTZU X0, D0
}; };
} }
@@ -260,7 +264,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E188000u, // FCVTZS W0, S0, #32 0x1E188000u, // FCVTZS W0, S0, #32
0x1E198000u // FCVTZU W0, S0, #32 0x1E198000u, // FCVTZU W0, S0, #32
}; };
} }
@@ -269,7 +273,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E180000u, // FCVTZS X0, S0, #64 0x9E180000u, // FCVTZS X0, S0, #64
0x9E190000u // FCVTZU X0, S0, #64 0x9E190000u, // FCVTZU X0, S0, #64
}; };
} }
@@ -278,7 +282,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E588000u, // FCVTZS W0, D0, #32 0x1E588000u, // FCVTZS W0, D0, #32
0x1E598000u // FCVTZU W0, D0, #32 0x1E598000u, // FCVTZU W0, D0, #32
}; };
} }
@@ -287,7 +291,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E580000u, // FCVTZS X0, D0, #64 0x9E580000u, // FCVTZS X0, D0, #64
0x9E590000u // FCVTZU X0, D0, #64 0x9E590000u, // FCVTZU X0, D0, #64
}; };
} }
@@ -296,7 +300,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E220000u, // SCVTF S0, W0 0x1E220000u, // SCVTF S0, W0
0x1E230000u // UCVTF S0, W0 0x1E230000u, // UCVTF S0, W0
}; };
} }
@@ -305,7 +309,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E620000u, // SCVTF D0, W0 0x1E620000u, // SCVTF D0, W0
0x1E630000u // UCVTF D0, W0 0x1E630000u, // UCVTF D0, W0
}; };
} }
@@ -314,7 +318,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E220000u, // SCVTF S0, X0 0x9E220000u, // SCVTF S0, X0
0x9E230000u // UCVTF S0, X0 0x9E230000u, // UCVTF S0, X0
}; };
} }
@@ -323,7 +327,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E620000u, // SCVTF D0, X0 0x9E620000u, // SCVTF D0, X0
0x9E630000u // UCVTF D0, X0 0x9E630000u, // UCVTF D0, X0
}; };
} }
@@ -332,7 +336,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E028000u, // SCVTF S0, W0, #32 0x1E028000u, // SCVTF S0, W0, #32
0x1E038000u // UCVTF S0, W0, #32 0x1E038000u, // UCVTF S0, W0, #32
}; };
} }
@@ -341,7 +345,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E428000u, // SCVTF D0, W0, #32 0x1E428000u, // SCVTF D0, W0, #32
0x1E438000u // UCVTF D0, W0, #32 0x1E438000u, // UCVTF D0, W0, #32
}; };
} }
@@ -350,7 +354,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E020000u, // SCVTF S0, X0, #64 0x9E020000u, // SCVTF S0, X0, #64
0x9E030000u // UCVTF S0, X0, #64 0x9E030000u, // UCVTF S0, X0, #64
}; };
} }
@@ -359,21 +363,22 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x9E420000u, // SCVTF D0, X0, #64 0x9E420000u, // SCVTF D0, X0, #64
0x9E430000u // UCVTF D0, X0, #64 0x9E430000u, // UCVTF D0, X0, #64
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_AMPZ_SU_Gp_SW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SW_))] uint opcodes, public void F_Cvt_AMPZ_SU_Gp_SW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SW_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1S_F_WX_))] ulong a) [ValueSource(nameof(_1S_F_WX_))] ulong a)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -387,10 +392,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_AMPZ_SU_Gp_SX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SX_))] uint opcodes, public void F_Cvt_AMPZ_SU_Gp_SX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SX_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1S_F_WX_))] ulong a) [ValueSource(nameof(_1S_F_WX_))] ulong a)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -403,10 +409,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_AMPZ_SU_Gp_DW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DW_))] uint opcodes, public void F_Cvt_AMPZ_SU_Gp_DW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DW_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1D_F_WX_))] ulong a) [ValueSource(nameof(_1D_F_WX_))] ulong a)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -420,10 +427,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_AMPZ_SU_Gp_DX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DX_))] uint opcodes, public void F_Cvt_AMPZ_SU_Gp_DX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DX_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1D_F_WX_))] ulong a) [ValueSource(nameof(_1D_F_WX_))] ulong a)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -436,10 +444,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_SW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SW_))] uint opcodes, public void F_Cvt_Z_SU_Gp_Fixed_SW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SW_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1S_F_WX_))] ulong a, [ValueSource(nameof(_1S_F_WX_))] ulong a,
[Values(1u, 32u)] uint fBits) [Values(1u, 32u)] uint fBits)
{ {
@@ -457,10 +466,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_SX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SX_))] uint opcodes, public void F_Cvt_Z_SU_Gp_Fixed_SX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SX_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1S_F_WX_))] ulong a, [ValueSource(nameof(_1S_F_WX_))] ulong a,
[Values(1u, 64u)] uint fBits) [Values(1u, 64u)] uint fBits)
{ {
@@ -477,10 +487,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_DW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DW_))] uint opcodes, public void F_Cvt_Z_SU_Gp_Fixed_DW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DW_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1D_F_WX_))] ulong a, [ValueSource(nameof(_1D_F_WX_))] ulong a,
[Values(1u, 32u)] uint fBits) [Values(1u, 32u)] uint fBits)
{ {
@@ -498,10 +509,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_DX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DX_))] uint opcodes, public void F_Cvt_Z_SU_Gp_Fixed_DX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DX_))] uint opcodes,
[Values(0u, 31u)] uint rd, [Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1D_F_WX_))] ulong a, [ValueSource(nameof(_1D_F_WX_))] ulong a,
[Values(1u, 64u)] uint fBits) [Values(1u, 64u)] uint fBits)
{ {
@@ -518,16 +530,17 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_WS([ValueSource(nameof(_SU_Cvt_F_Gp_WS_))] uint opcodes, public void SU_Cvt_F_Gp_WS([ValueSource(nameof(_SU_Cvt_F_Gp_WS_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_W_))] uint wn) [ValueSource(nameof(_W_))] uint wn)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
uint w31 = TestContext.CurrentContext.Random.NextUInt(); uint w31 = TestContext.CurrentContext.Random.NextUInt();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0); SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0);
@@ -535,16 +548,17 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_WD([ValueSource(nameof(_SU_Cvt_F_Gp_WD_))] uint opcodes, public void SU_Cvt_F_Gp_WD([ValueSource(nameof(_SU_Cvt_F_Gp_WD_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_W_))] uint wn) [ValueSource(nameof(_W_))] uint wn)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
uint w31 = TestContext.CurrentContext.Random.NextUInt(); uint w31 = TestContext.CurrentContext.Random.NextUInt();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z); V128 v0 = MakeVectorE1(z);
SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0); SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0);
@@ -552,16 +566,17 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_XS([ValueSource(nameof(_SU_Cvt_F_Gp_XS_))] uint opcodes, public void SU_Cvt_F_Gp_XS([ValueSource(nameof(_SU_Cvt_F_Gp_XS_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_X_))] ulong xn) [ValueSource(nameof(_X_))] ulong xn)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
ulong x31 = TestContext.CurrentContext.Random.NextULong(); ulong x31 = TestContext.CurrentContext.Random.NextULong();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0); SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0);
@@ -569,16 +584,17 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_XD([ValueSource(nameof(_SU_Cvt_F_Gp_XD_))] uint opcodes, public void SU_Cvt_F_Gp_XD([ValueSource(nameof(_SU_Cvt_F_Gp_XD_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_X_))] ulong xn) [ValueSource(nameof(_X_))] ulong xn)
{ {
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
ulong x31 = TestContext.CurrentContext.Random.NextULong(); ulong x31 = TestContext.CurrentContext.Random.NextULong();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z); V128 v0 = MakeVectorE1(z);
SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0); SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0);
@@ -586,9 +602,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_Fixed_WS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WS_))] uint opcodes, public void SU_Cvt_F_Gp_Fixed_WS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WS_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
[Values(1u, 32u)] uint fBits) [Values(1u, 32u)] uint fBits)
@@ -598,8 +615,8 @@ namespace Ryujinx.Tests.Cpu
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
opcodes |= (scale << 10); opcodes |= (scale << 10);
uint w31 = TestContext.CurrentContext.Random.NextUInt(); uint w31 = TestContext.CurrentContext.Random.NextUInt();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0); SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0);
@@ -607,9 +624,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_Fixed_WD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WD_))] uint opcodes, public void SU_Cvt_F_Gp_Fixed_WD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WD_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
[Values(1u, 32u)] uint fBits) [Values(1u, 32u)] uint fBits)
@@ -619,8 +637,8 @@ namespace Ryujinx.Tests.Cpu
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
opcodes |= (scale << 10); opcodes |= (scale << 10);
uint w31 = TestContext.CurrentContext.Random.NextUInt(); uint w31 = TestContext.CurrentContext.Random.NextUInt();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z); V128 v0 = MakeVectorE1(z);
SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0); SingleOpcode(opcodes, x1: wn, x31: w31, v0: v0);
@@ -628,9 +646,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_Fixed_XS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XS_))] uint opcodes, public void SU_Cvt_F_Gp_Fixed_XS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XS_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_X_))] ulong xn, [ValueSource(nameof(_X_))] ulong xn,
[Values(1u, 64u)] uint fBits) [Values(1u, 64u)] uint fBits)
@@ -641,7 +660,7 @@ namespace Ryujinx.Tests.Cpu
opcodes |= (scale << 10); opcodes |= (scale << 10);
ulong x31 = TestContext.CurrentContext.Random.NextULong(); ulong x31 = TestContext.CurrentContext.Random.NextULong();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0); SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0);
@@ -649,9 +668,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_Fixed_XD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XD_))] uint opcodes, public void SU_Cvt_F_Gp_Fixed_XD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XD_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_X_))] ulong xn, [ValueSource(nameof(_X_))] ulong xn,
[Values(1u, 64u)] uint fBits) [Values(1u, 64u)] uint fBits)
@@ -662,7 +682,7 @@ namespace Ryujinx.Tests.Cpu
opcodes |= (scale << 10); opcodes |= (scale << 10);
ulong x31 = TestContext.CurrentContext.Random.NextULong(); ulong x31 = TestContext.CurrentContext.Random.NextULong();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z); V128 v0 = MakeVectorE1(z);
SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0); SingleOpcode(opcodes, x1: xn, x31: x31, v0: v0);
@@ -671,4 +691,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdCvt32 #if SimdCvt32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Vrint_AMNP_V_F32_() private static uint[] _Vrint_AMNP_V_F32_()
{ {
return new[] return new[]
@@ -20,16 +20,18 @@ namespace Ryujinx.Tests.Cpu
0xf3ba0500u, // VRINTA.F32 Q0, Q0 0xf3ba0500u, // VRINTA.F32 Q0, Q0
0xf3ba0680u, // VRINTM.F32 Q0, Q0 0xf3ba0680u, // VRINTM.F32 Q0, Q0
0xf3ba0400u, // VRINTN.F32 Q0, Q0 0xf3ba0400u, // VRINTN.F32 Q0, Q0
0xf3ba0780u // VRINTP.F32 Q0, Q0 0xf3ba0780u, // VRINTP.F32 Q0, Q0
}; };
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static uint[] _1S_() private static uint[] _1S_()
{ {
return new[] { 0x00000000u, 0x7FFFFFFFu, return new[] {
0x80000000u, 0xFFFFFFFFu }; 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu,
};
} }
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
@@ -43,19 +45,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -85,19 +87,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000080000000ul; // -Zero yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFF800000FF800000ul; // -Infinity yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity yield return 0x7F8000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -126,19 +128,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -155,13 +157,13 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2; yield return rnd2;
} }
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Explicit] [Explicit]
[Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")] [Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")]
@@ -275,7 +277,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode, public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode,
[Values(0u, 1u, 2u, 3u)] uint rd, [Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rm, [Values(0u, 1u, 2u, 3u)] uint rm,
@@ -289,12 +292,14 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rm >>= 1; rm <<= 1; rd <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(d0, d1); V128 v0 = MakeVectorE0E1(d0, d1);
V128 v1 = MakeVectorE0E1(d2, d3); V128 v1 = MakeVectorE0E1(d2, d3);
@@ -508,4 +513,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -10,16 +10,18 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdExt #if SimdExt
#region "ValueSource" #region "ValueSource"
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
[Test, Pairwise, Description("EXT <Vd>.8B, <Vn>.8B, <Vm>.8B, #<index>")] [Test, Pairwise, Description("EXT <Vd>.8B, <Vn>.8B, <Vm>.8B, #<index>")]
public void Ext_V_8B([Values(0u)] uint rd, public void Ext_V_8B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
@@ -43,7 +45,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("EXT <Vd>.16B, <Vn>.16B, <Vm>.16B, #<index>")] [Test, Pairwise, Description("EXT <Vd>.16B, <Vn>.16B, <Vm>.16B, #<index>")]
public void Ext_V_16B([Values(0u)] uint rd, public void Ext_V_16B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
@@ -67,4 +69,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdFcond #if SimdFcond
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
{ {
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue) yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -65,19 +65,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -94,15 +94,15 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2; yield return rnd2;
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _F_Ccmp_Ccmpe_S_S_() private static uint[] _F_Ccmp_Ccmpe_S_S_()
{ {
return new[] return new[]
{ {
0x1E220420u, // FCCMP S1, S2, #0, EQ 0x1E220420u, // FCCMP S1, S2, #0, EQ
0x1E220430u // FCCMPE S1, S2, #0, EQ 0x1E220430u, // FCCMPE S1, S2, #0, EQ
}; };
} }
@@ -111,7 +111,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E620420u, // FCCMP D1, D2, #0, EQ 0x1E620420u, // FCCMP D1, D2, #0, EQ
0x1E620430u // FCCMPE D1, D2, #0, EQ 0x1E620430u, // FCCMPE D1, D2, #0, EQ
}; };
} }
@@ -119,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x1E220C20u // FCSEL S0, S1, S2, EQ 0x1E220C20u, // FCSEL S0, S1, S2, EQ
}; };
} }
@@ -127,19 +127,20 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x1E620C20u // FCSEL D0, D1, D2, EQ 0x1E620C20u, // FCSEL D0, D1, D2, EQ
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private const int RndCntNzcv = 2; private const int RndCntNzcv = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Ccmp_Ccmpe_S_S([ValueSource(nameof(_F_Ccmp_Ccmpe_S_S_))] uint opcodes, public void F_Ccmp_Ccmpe_S_S([ValueSource(nameof(_F_Ccmp_Ccmpe_S_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a, [ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b, [ValueSource(nameof(_1S_F_))] ulong b,
@@ -164,7 +165,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Ccmp_Ccmpe_S_D([ValueSource(nameof(_F_Ccmp_Ccmpe_S_D_))] uint opcodes, public void F_Ccmp_Ccmpe_S_D([ValueSource(nameof(_F_Ccmp_Ccmpe_S_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a, [ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b, [ValueSource(nameof(_1D_F_))] ulong b,
@@ -189,7 +191,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Csel_S_S([ValueSource(nameof(_F_Csel_S_S_))] uint opcodes, public void F_Csel_S_S([ValueSource(nameof(_F_Csel_S_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a, [ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b, [ValueSource(nameof(_1S_F_))] ulong b,
@@ -210,7 +213,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Csel_S_D([ValueSource(nameof(_F_Csel_S_D_))] uint opcodes, public void F_Csel_S_D([ValueSource(nameof(_F_Csel_S_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a, [ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b, [ValueSource(nameof(_1D_F_))] ulong b,

View File

@@ -10,12 +10,12 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdFmov #if SimdFmov
#region "ValueSource" #region "ValueSource"
private static uint[] _F_Mov_Si_S_() private static uint[] _F_Mov_Si_S_()
{ {
return new[] return new[]
{ {
0x1E201000u // FMOV S0, #2.0 0x1E201000u, // FMOV S0, #2.0
}; };
} }
@@ -23,12 +23,13 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x1E601000u // FMOV D0, #2.0 0x1E601000u, // FMOV D0, #2.0
}; };
} }
#endregion #endregion
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mov_Si_S([ValueSource(nameof(_F_Mov_Si_S_))] uint opcodes, public void F_Mov_Si_S([ValueSource(nameof(_F_Mov_Si_S_))] uint opcodes,
[Range(0u, 255u, 1u)] uint imm8) [Range(0u, 255u, 1u)] uint imm8)
{ {
@@ -42,7 +43,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mov_Si_D([ValueSource(nameof(_F_Mov_Si_D_))] uint opcodes, public void F_Mov_Si_D([ValueSource(nameof(_F_Mov_Si_D_))] uint opcodes,
[Range(0u, 255u, 1u)] uint imm8) [Range(0u, 255u, 1u)] uint imm8)
{ {

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdImm #if SimdImm
#region "Helper methods" #region "Helper methods"
// abcdefgh -> aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh // abcdefgh -> aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
private static ulong ExpandImm8(byte imm8) private static ulong ExpandImm8(byte imm8)
{ {
@@ -43,19 +43,23 @@ namespace Ryujinx.Tests.Cpu
return imm8; return imm8;
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _2S_() private static ulong[] _2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, return new[] {
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H_() private static ulong[] _4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<byte> _8BIT_IMM_() private static IEnumerable<byte> _8BIT_IMM_()
@@ -87,15 +91,15 @@ namespace Ryujinx.Tests.Cpu
yield return ExpandImm8(imm8); yield return ExpandImm8(imm8);
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Bic_Orr_Vi_16bit_() private static uint[] _Bic_Orr_Vi_16bit_()
{ {
return new[] return new[]
{ {
0x2F009400u, // BIC V0.4H, #0 0x2F009400u, // BIC V0.4H, #0
0x0F009400u // ORR V0.4H, #0 0x0F009400u, // ORR V0.4H, #0
}; };
} }
@@ -104,7 +108,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x2F001400u, // BIC V0.2S, #0 0x2F001400u, // BIC V0.2S, #0
0x0F001400u // ORR V0.2S, #0 0x0F001400u, // ORR V0.2S, #0
}; };
} }
@@ -112,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x0F00F400u // FMOV V0.2S, #2.0 0x0F00F400u, // FMOV V0.2S, #2.0
}; };
} }
@@ -120,7 +124,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x4F00F400u // FMOV V0.4S, #2.0 0x4F00F400u, // FMOV V0.4S, #2.0
}; };
} }
@@ -128,7 +132,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x6F00F400u // FMOV V0.2D, #2.0 0x6F00F400u, // FMOV V0.2D, #2.0
}; };
} }
@@ -136,7 +140,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x0F00E400u // MOVI V0.8B, #0 0x0F00E400u, // MOVI V0.8B, #0
}; };
} }
@@ -145,7 +149,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F008400u, // MOVI V0.4H, #0 0x0F008400u, // MOVI V0.4H, #0
0x2F008400u // MVNI V0.4H, #0 0x2F008400u, // MVNI V0.4H, #0
}; };
} }
@@ -154,7 +158,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F000400u, // MOVI V0.2S, #0 0x0F000400u, // MOVI V0.2S, #0
0x2F000400u // MVNI V0.2S, #0 0x2F000400u, // MVNI V0.2S, #0
}; };
} }
@@ -163,7 +167,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F00C400u, // MOVI V0.2S, #0, MSL #8 0x0F00C400u, // MOVI V0.2S, #0, MSL #8
0x2F00C400u // MVNI V0.2S, #0, MSL #8 0x2F00C400u, // MVNI V0.2S, #0, MSL #8
}; };
} }
@@ -171,7 +175,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x2F00E400u // MOVI D0, #0 0x2F00E400u, // MOVI D0, #0
}; };
} }
@@ -179,12 +183,12 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x6F00E400u // MOVI V0.2D, #0 0x6F00E400u, // MOVI V0.2D, #0
}; };
} }
#endregion #endregion
private const int RndCntImm8 = 2; private const int RndCntImm8 = 2;
private const int RndCntImm64 = 2; private const int RndCntImm64 = 2;
[Test, Pairwise] [Test, Pairwise]
@@ -194,7 +198,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0b0u, 0b1u)] uint amount, // <0, 8> [Values(0b0u, 0b1u)] uint amount, // <0, 8>
[Values(0b0u, 0b1u)] uint q) // <4H, 8H> [Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -215,7 +219,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24> [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S> [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -229,11 +233,12 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mov_Vi_2S([ValueSource(nameof(_F_Mov_Vi_2S_))] uint opcodes, public void F_Mov_Vi_2S([ValueSource(nameof(_F_Mov_Vi_2S_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh) [Range(0u, 255u, 1u)] uint abcdefgh)
{ {
uint abc = (abcdefgh & 0xE0u) >> 5; uint abc = (abcdefgh & 0xE0u) >> 5;
uint defgh = (abcdefgh & 0x1Fu); uint defgh = (abcdefgh & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -246,11 +251,12 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mov_Vi_4S([ValueSource(nameof(_F_Mov_Vi_4S_))] uint opcodes, public void F_Mov_Vi_4S([ValueSource(nameof(_F_Mov_Vi_4S_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh) [Range(0u, 255u, 1u)] uint abcdefgh)
{ {
uint abc = (abcdefgh & 0xE0u) >> 5; uint abc = (abcdefgh & 0xE0u) >> 5;
uint defgh = (abcdefgh & 0x1Fu); uint defgh = (abcdefgh & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -260,11 +266,12 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mov_Vi_2D([ValueSource(nameof(_F_Mov_Vi_2D_))] uint opcodes, public void F_Mov_Vi_2D([ValueSource(nameof(_F_Mov_Vi_2D_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh) [Range(0u, 255u, 1u)] uint abcdefgh)
{ {
uint abc = (abcdefgh & 0xE0u) >> 5; uint abc = (abcdefgh & 0xE0u) >> 5;
uint defgh = (abcdefgh & 0x1Fu); uint defgh = (abcdefgh & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -279,7 +286,7 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_8BIT_IMM_))] byte imm8, [ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B> [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -299,7 +306,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0b0u, 0b1u)] uint amount, // <0, 8> [Values(0b0u, 0b1u)] uint amount, // <0, 8>
[Values(0b0u, 0b1u)] uint q) // <4H, 8H> [Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -320,7 +327,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24> [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S> [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -341,7 +348,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0b0u, 0b1u)] uint amount, // <8, 16> [Values(0b0u, 0b1u)] uint amount, // <8, 16>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S> [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{ {
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -362,7 +369,7 @@ namespace Ryujinx.Tests.Cpu
{ {
byte imm8 = ShrinkImm64(imm); byte imm8 = ShrinkImm64(imm);
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -381,7 +388,7 @@ namespace Ryujinx.Tests.Cpu
{ {
byte imm8 = ShrinkImm64(imm); byte imm8 = ShrinkImm64(imm);
uint abc = (imm8 & 0xE0u) >> 5; uint abc = (imm8 & 0xE0u) >> 5;
uint defgh = (imm8 & 0x1Fu); uint defgh = (imm8 & 0x1Fu);
opcodes |= (abc << 16) | (defgh << 5); opcodes |= (abc << 16) | (defgh << 5);
@@ -392,4 +399,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -10,64 +10,80 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdIns #if SimdIns
#region "ValueSource" #region "ValueSource"
private static ulong[] _1D_() private static ulong[] _1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _2S_() private static ulong[] _2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, return new[] {
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H_() private static ulong[] _4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H_() private static ulong[] _8B4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static uint[] _W_() private static uint[] _W_()
{ {
return new[] { 0x00000000u, 0x0000007Fu, return new[] {
0x00000080u, 0x000000FFu, 0x00000000u, 0x0000007Fu,
0x00007FFFu, 0x00008000u, 0x00000080u, 0x000000FFu,
0x0000FFFFu, 0x7FFFFFFFu, 0x00007FFFu, 0x00008000u,
0x80000000u, 0xFFFFFFFFu }; 0x0000FFFFu, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu,
};
} }
private static ulong[] _X_() private static ulong[] _X_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
[Test, Pairwise, Description("DUP <Vd>.<T>, W<n>")] [Test, Pairwise, Description("DUP <Vd>.<T>, W<n>")]
public void Dup_Gp_W([Values(0u)] uint rd, public void Dup_Gp_W([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
[Values(0, 1, 2)] int size, // Q0: <8B, 4H, 2S> [Values(0, 1, 2)] int size, // Q0: <8B, 4H, 2S>
@@ -80,8 +96,8 @@ namespace Ryujinx.Tests.Cpu
opcode |= (imm5 << 16); opcode |= (imm5 << 16);
opcode |= ((q & 1) << 30); opcode |= ((q & 1) << 30);
uint w31 = TestContext.CurrentContext.Random.NextUInt(); uint w31 = TestContext.CurrentContext.Random.NextUInt();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcode, x1: wn, x31: w31, v0: v0); SingleOpcode(opcode, x1: wn, x31: w31, v0: v0);
@@ -90,7 +106,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("DUP <Vd>.<T>, X<n>")] [Test, Pairwise, Description("DUP <Vd>.<T>, X<n>")]
public void Dup_Gp_X([Values(0u)] uint rd, public void Dup_Gp_X([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_X_))] ulong xn) [ValueSource(nameof(_X_))] ulong xn)
{ {
@@ -98,7 +114,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0); opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
ulong x31 = TestContext.CurrentContext.Random.NextULong(); ulong x31 = TestContext.CurrentContext.Random.NextULong();
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
SingleOpcode(opcode, x1: xn, x31: x31, v0: v0); SingleOpcode(opcode, x1: xn, x31: x31, v0: v0);
@@ -187,7 +203,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.B[<index>]")] [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.B[<index>]")]
public void Dup_V_8B_16B([Values(0u)] uint rd, public void Dup_V_8B_16B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
@@ -212,7 +228,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.H[<index>]")] [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.H[<index>]")]
public void Dup_V_4H_8H([Values(0u)] uint rd, public void Dup_V_4H_8H([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -237,7 +253,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.S[<index>]")] [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.S[<index>]")]
public void Dup_V_2S_4S([Values(0u)] uint rd, public void Dup_V_2S_4S([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -262,7 +278,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.D[<index>]")] [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.D[<index>]")]
public void Dup_V_2D([Values(0u)] uint rd, public void Dup_V_2D([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -287,7 +303,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.B[<index>], W<n>")] [Test, Pairwise, Description("INS <Vd>.B[<index>], W<n>")]
public void Ins_Gp_WB([Values(0u)] uint rd, public void Ins_Gp_WB([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
@@ -310,7 +326,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.H[<index>], W<n>")] [Test, Pairwise, Description("INS <Vd>.H[<index>], W<n>")]
public void Ins_Gp_WH([Values(0u)] uint rd, public void Ins_Gp_WH([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
@@ -333,7 +349,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.S[<index>], W<n>")] [Test, Pairwise, Description("INS <Vd>.S[<index>], W<n>")]
public void Ins_Gp_WS([Values(0u)] uint rd, public void Ins_Gp_WS([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_W_))] uint wn, [ValueSource(nameof(_W_))] uint wn,
@@ -356,7 +372,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.D[<index>], X<n>")] [Test, Pairwise, Description("INS <Vd>.D[<index>], X<n>")]
public void Ins_Gp_XD([Values(0u)] uint rd, public void Ins_Gp_XD([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn, [Values(1u, 31u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_X_))] ulong xn, [ValueSource(nameof(_X_))] ulong xn,
@@ -379,7 +395,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.B[<index1>], <Vn>.B[<index2>]")] [Test, Pairwise, Description("INS <Vd>.B[<index1>], <Vn>.B[<index2>]")]
public void Ins_V_BB([Values(0u)] uint rd, public void Ins_V_BB([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
@@ -405,7 +421,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.H[<index1>], <Vn>.H[<index2>]")] [Test, Pairwise, Description("INS <Vd>.H[<index1>], <Vn>.H[<index2>]")]
public void Ins_V_HH([Values(0u)] uint rd, public void Ins_V_HH([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -431,7 +447,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.S[<index1>], <Vn>.S[<index2>]")] [Test, Pairwise, Description("INS <Vd>.S[<index1>], <Vn>.S[<index2>]")]
public void Ins_V_SS([Values(0u)] uint rd, public void Ins_V_SS([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -457,7 +473,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("INS <Vd>.D[<index1>], <Vn>.D[<index2>]")] [Test, Pairwise, Description("INS <Vd>.D[<index1>], <Vn>.D[<index2>]")]
public void Ins_V_DD([Values(0u)] uint rd, public void Ins_V_DD([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -484,7 +500,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Wd>, <Vn>.B[<index>]")] [Test, Pairwise, Description("SMOV <Wd>, <Vn>.B[<index>]")]
public void Smov_S_BW([Values(0u, 31u)] uint rd, public void Smov_S_BW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index) [Values(0u, 15u)] uint index)
{ {
@@ -507,7 +523,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Wd>, <Vn>.H[<index>]")] [Test, Pairwise, Description("SMOV <Wd>, <Vn>.H[<index>]")]
public void Smov_S_HW([Values(0u, 31u)] uint rd, public void Smov_S_HW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index) [Values(0u, 7u)] uint index)
{ {
@@ -530,7 +546,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.B[<index>]")] [Test, Pairwise, Description("SMOV <Xd>, <Vn>.B[<index>]")]
public void Smov_S_BX([Values(0u, 31u)] uint rd, public void Smov_S_BX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index) [Values(0u, 15u)] uint index)
{ {
@@ -552,7 +568,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.H[<index>]")] [Test, Pairwise, Description("SMOV <Xd>, <Vn>.H[<index>]")]
public void Smov_S_HX([Values(0u, 31u)] uint rd, public void Smov_S_HX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index) [Values(0u, 7u)] uint index)
{ {
@@ -574,7 +590,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.S[<index>]")] [Test, Pairwise, Description("SMOV <Xd>, <Vn>.S[<index>]")]
public void Smov_S_SX([Values(0u, 31u)] uint rd, public void Smov_S_SX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index) [Values(0u, 1u, 2u, 3u)] uint index)
{ {
@@ -596,7 +612,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.B[<index>]")] [Test, Pairwise, Description("UMOV <Wd>, <Vn>.B[<index>]")]
public void Umov_S_BW([Values(0u, 31u)] uint rd, public void Umov_S_BW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index) [Values(0u, 15u)] uint index)
{ {
@@ -619,7 +635,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.H[<index>]")] [Test, Pairwise, Description("UMOV <Wd>, <Vn>.H[<index>]")]
public void Umov_S_HW([Values(0u, 31u)] uint rd, public void Umov_S_HW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index) [Values(0u, 7u)] uint index)
{ {
@@ -642,7 +658,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.S[<index>]")] [Test, Pairwise, Description("UMOV <Wd>, <Vn>.S[<index>]")]
public void Umov_S_SW([Values(0u, 31u)] uint rd, public void Umov_S_SW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index) [Values(0u, 1u, 2u, 3u)] uint index)
{ {
@@ -665,7 +681,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Xd>, <Vn>.D[<index>]")] [Test, Pairwise, Description("UMOV <Xd>, <Vn>.D[<index>]")]
public void Umov_S_DX([Values(0u, 31u)] uint rd, public void Umov_S_DX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn, [Values(1u)] uint rn,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 1u)] uint index) [Values(0u, 1u)] uint index)
{ {

View File

@@ -10,17 +10,19 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdLogical32 #if SimdLogical32
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_() private static uint[] _Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_()
{ {
return new[] return new[]
@@ -32,7 +34,7 @@ namespace Ryujinx.Tests.Cpu
0xf2000110u, // VAND D0, D0, D0 0xf2000110u, // VAND D0, D0, D0
0xf2300110u, // VORN D0, D0, D0 0xf2300110u, // VORN D0, D0, D0
0xf2200110u, // VORR D0, D0, D0 0xf2200110u, // VORR D0, D0, D0
0xf3000110u // VEOR D0, D0, D0 0xf3000110u, // VEOR D0, D0, D0
}; };
} }
@@ -43,10 +45,10 @@ namespace Ryujinx.Tests.Cpu
0xf2800130u, // VBIC.I32 D0, #0 (A1) 0xf2800130u, // VBIC.I32 D0, #0 (A1)
0xf2800930u, // VBIC.I16 D0, #0 (A2) 0xf2800930u, // VBIC.I16 D0, #0 (A2)
0xf2800110u, // VORR.I32 D0, #0 (A1) 0xf2800110u, // VORR.I32 D0, #0 (A1)
0xf2800910u // VORR.I16 D0, #0 (A2) 0xf2800910u, // VORR.I16 D0, #0 (A2)
}; };
} }
#endregion #endregion
[Test, Pairwise] [Test, Pairwise]
public void Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I([ValueSource(nameof(_Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_))] uint opcode, public void Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I([ValueSource(nameof(_Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_))] uint opcode,
@@ -62,14 +64,17 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rm >>= 1; rm <<= 1; rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z, ~z); V128 v0 = MakeVectorE0E1(z, ~z);
V128 v1 = MakeVectorE0E1(a, ~a); V128 v1 = MakeVectorE0E1(a, ~a);
@@ -97,10 +102,11 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rd <<= 1;
} }
opcode |= ((uint)imm & 0xf) << 0; opcode |= ((uint)imm & 0xf) << 0;
opcode |= ((uint)imm & 0x70) << 12; opcode |= ((uint)imm & 0x70) << 12;
opcode |= ((uint)imm & 0x80) << 17; opcode |= ((uint)imm & 0x80) << 17;
opcode |= (cMode & 0x3) << 9; opcode |= (cMode & 0x3) << 9;
@@ -129,14 +135,17 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rm >>= 1; rm <<= 1; rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (size & 0x3) << 20; opcode |= (size & 0x3) << 20;
@@ -150,4 +159,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -10,10 +10,10 @@ namespace Ryujinx.Tests.Cpu
[Category("SimdMemory32")] [Category("SimdMemory32")]
public sealed class CpuTestSimdMemory32 : CpuTest32 public sealed class CpuTestSimdMemory32 : CpuTest32
{ {
private static readonly uint TestOffset = DataBaseAddress + 0x500; private static readonly uint _testOffset = DataBaseAddress + 0x500;
#if SimdMemory32 #if SimdMemory32
private uint[] _ldStModes = private readonly uint[] _ldStModes =
{ {
// LD1 // LD1
0b0111, 0b0111,
@@ -32,7 +32,7 @@ namespace Ryujinx.Tests.Cpu
// LD4 // LD4
0b0000, 0b0000,
0b0001 0b0001,
}; };
[Test, Pairwise, Description("VLDn.<size> <list>, [<Rn> {:<align>}]{ /!/, <Rm>} (single n element structure)")] [Test, Pairwise, Description("VLDn.<size> <list>, [<Rn> {:<align>}]{ /!/, <Rm>} (single n element structure)")]
@@ -51,16 +51,16 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15); opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
uint index_align = (index << (int)(1 + size)) & 15; uint indexAlign = (index << (int)(1 + size)) & 15;
opcode |= (index_align) << 4; opcode |= (indexAlign) << 4;
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -85,9 +85,12 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
if (t) opcode |= 1 << 5; if (t)
{
opcode |= 1 << 5;
}
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -116,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -139,16 +142,16 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15); opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
uint index_align = (index << (int)(1 + size)) & 15; uint indexAlign = (index << (int)(1 + size)) & 15;
opcode |= (index_align) << 4; opcode |= (indexAlign) << 4;
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc. opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -179,7 +182,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -201,7 +204,7 @@ namespace Ryujinx.Tests.Cpu
// Note: 3rd 0 leaves a space for "D". // Note: 3rd 0 leaves a space for "D".
0b0100, // Increment after. 0b0100, // Increment after.
0b0101, // Increment after. (!) 0b0101, // Increment after. (!)
0b1001 // Decrement before. (!) 0b1001, // Decrement before. (!)
}; };
opcode |= ((vldmModes[mode] & 15) << 21); opcode |= ((vldmModes[mode] & 15) << 21);
@@ -212,7 +215,11 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((uint)(single ? 0 : 1) << 8); opcode |= ((uint)(single ? 0 : 1) << 8);
if (!single) regs = (regs << 1); // Low bit must be 0 - must be even number of registers. if (!single)
{
regs <<= 1; // Low bit must be 0 - must be even number of registers.
}
uint regSize = single ? 1u : 2u; uint regSize = single ? 1u : 2u;
if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31. if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31.
@@ -227,7 +234,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= regs & 0xff; opcode |= regs & 0xff;
SingleOpcode(opcode, r0: TestOffset, sp: TestOffset); SingleOpcode(opcode, r0: _testOffset, sp: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -262,7 +269,7 @@ namespace Ryujinx.Tests.Cpu
} }
opcode |= imm & 0xff; opcode |= imm & 0xff;
SingleOpcode(opcode, r0: TestOffset); SingleOpcode(opcode, r0: _testOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -299,12 +306,12 @@ namespace Ryujinx.Tests.Cpu
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); (V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2); SingleOpcode(opcode, r0: _testOffset, v0: vec1, v1: vec2);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
private (V128, V128, V128, V128) GenerateTestVectors() private static (V128, V128, V128, V128) GenerateTestVectors()
{ {
return ( return (
new V128(-12.43f, 1872.23f, 4456.23f, -5622.2f), new V128(-12.43f, 1872.23f, 4456.23f, -5622.2f),
@@ -314,7 +321,7 @@ namespace Ryujinx.Tests.Cpu
); );
} }
private byte[] GenerateVectorSequence(int length) private static byte[] GenerateVectorSequence(int length)
{ {
int floatLength = length >> 2; int floatLength = length >> 2;
float[] data = new float[floatLength]; float[] data = new float[floatLength];
@@ -330,4 +337,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -35,7 +35,7 @@ namespace Ryujinx.Tests.Cpu
0b1110_0, 0b1110_0,
0b1111_0, 0b1111_0,
0b1110_1 0b1110_1,
}; };
uint opcode = 0xf2800010u; // VMOV.I32 D0, #0 uint opcode = 0xf2800010u; // VMOV.I32 D0, #0
@@ -97,7 +97,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= (vn & 0x1e) << 15; opcode |= (vn & 0x1e) << 15;
opcode |= (rt & 0xf) << 12; opcode |= (rt & 0xf) << 12;
if (op) opcode |= 1 << 20; if (op)
{
opcode |= 1 << 20;
}
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2)); SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2));
@@ -217,10 +220,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -247,10 +250,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24; opcode |= 1 << 24;
} }
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -279,10 +282,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= (vd & 0x10) << 18; opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12; opcode |= (vd & 0xf) << 12;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -348,18 +351,20 @@ namespace Ryujinx.Tests.Cpu
if (q) if (q)
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
vd <<= 1; vm <<= 1; vd <<= 1;
vm <<= 1;
} }
opcode |= (vm & 0x10) << 1; opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf); opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18; opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12; opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18; opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -381,18 +386,20 @@ namespace Ryujinx.Tests.Cpu
if (q) if (q)
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
vd <<= 1; vm <<= 1; vd <<= 1;
vm <<= 1;
} }
opcode |= (vm & 0x10) << 1; opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf); opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18; opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12; opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18; opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -414,18 +421,20 @@ namespace Ryujinx.Tests.Cpu
if (q) if (q)
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
vd <<= 1; vm <<= 1; vd <<= 1;
vm <<= 1;
} }
opcode |= (vm & 0x10) << 1; opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf); opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18; opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12; opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18; opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -459,22 +468,22 @@ namespace Ryujinx.Tests.Cpu
opcode |= (length & 0x3) << 8; opcode |= (length & 0x3) << 8;
var rnd = TestContext.CurrentContext.Random; var rnd = TestContext.CurrentContext.Random;
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v4 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v4 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v5 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v5 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
byte maxIndex = (byte)(length * 8 - 1); byte maxIndex = (byte)(length * 8 - 1);
byte[] b0 = new byte[16]; byte[] b0 = new byte[16];
byte[] b1 = new byte[16]; byte[] b1 = new byte[16];
for (int i=0; i<16; i++) for (int i = 0; i < 16; i++)
{ {
b0[i] = rnd.NextByte(maxIndex); b0[i] = rnd.NextByte(maxIndex);
b1[i] = rnd.NextByte(maxIndex); b1[i] = rnd.NextByte(maxIndex);
} }
V128 v0 = new V128(b0); V128 v0 = new(b0);
V128 v1 = new V128(b1); V128 v1 = new(b1);
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
@@ -493,7 +502,9 @@ namespace Ryujinx.Tests.Cpu
if (q) if (q)
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
vd <<= 1; vm <<= 1; vn <<= 1; vd <<= 1;
vm <<= 1;
vn <<= 1;
} }
else if (imm4 > 7) else if (imm4 > 7)
{ {
@@ -507,10 +518,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= (vn & 0xf) << 16; opcode |= (vn & 0xf) << 16;
opcode |= (imm4 & 0xf) << 8; opcode |= (imm4 & 0xf) << 8;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
@@ -541,7 +552,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (size & 1) << 5; // E opcode |= (size & 1) << 5; // E
opcode |= (size & 2) << 21; // B opcode |= (size & 2) << 21; // B
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1); SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1);
@@ -586,9 +597,9 @@ namespace Ryujinx.Tests.Cpu
opcode |= imm4 << 16; opcode |= imm4 << 16;
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3); SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3);
@@ -596,4 +607,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdReg32 #if SimdReg32
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _V_Add_Sub_Long_Wide_I_() private static uint[] _V_Add_Sub_Long_Wide_I_()
{ {
return new[] return new[]
@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Cpu
0xf2800000u, // VADDL.S8 Q0, D0, D0 0xf2800000u, // VADDL.S8 Q0, D0, D0
0xf2800100u, // VADDW.S8 Q0, Q0, D0 0xf2800100u, // VADDW.S8 Q0, Q0, D0
0xf2800200u, // VSUBL.S8 Q0, D0, D0 0xf2800200u, // VSUBL.S8 Q0, D0, D0
0xf2800300u // VSUBW.S8 Q0, Q0, D0 0xf2800300u, // VSUBW.S8 Q0, Q0, D0
}; };
} }
@@ -31,7 +31,7 @@ namespace Ryujinx.Tests.Cpu
0xEEA00A00u, // VFMA. F32 S0, S0, S0 0xEEA00A00u, // VFMA. F32 S0, S0, S0
0xEEA00A40u, // VFMS. F32 S0, S0, S0 0xEEA00A40u, // VFMS. F32 S0, S0, S0
0xEE900A40u, // VFNMA.F32 S0, S0, S0 0xEE900A40u, // VFNMA.F32 S0, S0, S0
0xEE900A00u // VFNMS.F32 S0, S0, S0 0xEE900A00u, // VFNMS.F32 S0, S0, S0
}; };
} }
@@ -42,7 +42,7 @@ namespace Ryujinx.Tests.Cpu
0xEEA00B00u, // VFMA. F64 D0, D0, D0 0xEEA00B00u, // VFMA. F64 D0, D0, D0
0xEEA00B40u, // VFMS. F64 D0, D0, D0 0xEEA00B40u, // VFMS. F64 D0, D0, D0
0xEE900B40u, // VFNMA.F64 D0, D0, D0 0xEE900B40u, // VFNMA.F64 D0, D0, D0
0xEE900B00u // VFNMS.F64 D0, D0, D0 0xEE900B00u, // VFNMS.F64 D0, D0, D0
}; };
} }
@@ -51,7 +51,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0xF2000C10u, // VFMA.F32 D0, D0, D0 0xF2000C10u, // VFMA.F32 D0, D0, D0
0xF2200C10u // VFMS.F32 D0, D0, D0 0xF2200C10u, // VFMS.F32 D0, D0, D0
}; };
} }
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
0xEE000A00u, // VMLA. F32 S0, S0, S0 0xEE000A00u, // VMLA. F32 S0, S0, S0
0xEE000A40u, // VMLS. F32 S0, S0, S0 0xEE000A40u, // VMLS. F32 S0, S0, S0
0xEE100A40u, // VNMLA.F32 S0, S0, S0 0xEE100A40u, // VNMLA.F32 S0, S0, S0
0xEE100A00u // VNMLS.F32 S0, S0, S0 0xEE100A00u, // VNMLS.F32 S0, S0, S0
}; };
} }
@@ -73,7 +73,7 @@ namespace Ryujinx.Tests.Cpu
0xEE000B00u, // VMLA. F64 D0, D0, D0 0xEE000B00u, // VMLA. F64 D0, D0, D0
0xEE000B40u, // VMLS. F64 D0, D0, D0 0xEE000B40u, // VMLS. F64 D0, D0, D0
0xEE100B40u, // VNMLA.F64 D0, D0, D0 0xEE100B40u, // VNMLA.F64 D0, D0, D0
0xEE100B00u // VNMLS.F64 D0, D0, D0 0xEE100B00u, // VNMLS.F64 D0, D0, D0
}; };
} }
@@ -82,7 +82,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0xf2800800u, // VMLAL.S8 Q0, D0, D0 0xf2800800u, // VMLAL.S8 Q0, D0, D0
0xf2800a00u // VMLSL.S8 Q0, D0, D0 0xf2800a00u, // VMLSL.S8 Q0, D0, D0
}; };
} }
@@ -92,7 +92,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0xf3000d00u, // VPADD.F32 D0, D0, D0 0xf3000d00u, // VPADD.F32 D0, D0, D0
0xf3000f00u, // VPMAX.F32 D0, D0, D0 0xf3000f00u, // VPMAX.F32 D0, D0, D0
0xf3200f00u // VPMIN.F32 D0, D0, D0 0xf3200f00u, // VPMIN.F32 D0, D0, D0
}; };
} }
@@ -100,7 +100,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0xf2000b10u // VPADD.I8 D0, D0, D0 0xf2000b10u, // VPADD.I8 D0, D0, D0
}; };
} }
@@ -119,26 +119,30 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0xf2000050u, // VQADD.S8 Q0, Q0, Q0 0xf2000050u, // VQADD.S8 Q0, Q0, Q0
0xf2000250u // VQSUB.S8 Q0, Q0, Q0 0xf2000250u, // VQSUB.S8 Q0, Q0, Q0
}; };
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B1D_() private static ulong[] _8B1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S1D_() private static ulong[] _8B4H2S1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
@@ -152,19 +156,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -194,19 +198,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000080000000ul; // -Zero yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFF800000FF800000ul; // -Infinity yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity yield return 0x7F8000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -235,19 +239,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -264,13 +268,13 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2; yield return rnd2;
} }
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")] [Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")]
public void Sha256h_V([Values(0xF3000C40u)] uint opcode, public void Sha256h_V([Values(0xF3000C40u)] uint opcode,
@@ -288,7 +292,7 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1); V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1); V128 v1 = MakeVectorE0E1(a0, a1);
@@ -322,7 +326,7 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1); V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1); V128 v1 = MakeVectorE0E1(a0, a1);
@@ -356,7 +360,7 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1); V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1); V128 v1 = MakeVectorE0E1(a0, a1);
@@ -396,7 +400,7 @@ namespace Ryujinx.Tests.Cpu
rd <<= 1; rd <<= 1;
} }
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -425,12 +429,14 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24; opcode |= 1 << 24;
} }
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rn >>= 1;
rn <<= 1;
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (size & 0x3) << 20; opcode |= (size & 0x3) << 20;
@@ -455,12 +461,12 @@ namespace Ryujinx.Tests.Cpu
if (size == 3) if (size == 3)
{ {
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
} }
else else
{ {
opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
} }
@@ -480,7 +486,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv); CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void Vfma_Vfms_Vfnma_Vfnms_S_F32([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F32_))] uint opcode, public void Vfma_Vfms_Vfnma_Vfnms_S_F32([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F32_))] uint opcode,
[Values(0u, 1u, 2u, 3u)] uint rd, [Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rn, [Values(0u, 1u, 2u, 3u)] uint rn,
@@ -491,8 +499,8 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_1S_F_))] ulong s3) [ValueSource(nameof(_1S_F_))] ulong s3)
{ {
opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11); opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11);
opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) << 15); opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) << 15);
opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1); opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1);
V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3); V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3);
@@ -501,7 +509,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void Vfma_Vfms_Vfnma_Vfnms_S_F64([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F64_))] uint opcode, public void Vfma_Vfms_Vfnma_Vfnms_S_F64([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F64_))] uint opcode,
[Values(0u, 1u)] uint rd, [Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rn, [Values(0u, 1u)] uint rn,
@@ -510,8 +520,8 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_1D_F_))] ulong d1) [ValueSource(nameof(_1D_F_))] ulong d1)
{ {
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12); opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16); opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0); opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
V128 v0 = MakeVectorE0E1(d0, d1); V128 v0 = MakeVectorE0E1(d0, d1);
@@ -520,7 +530,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void Vfma_Vfms_V_F32([ValueSource(nameof(_Vfma_Vfms_V_F32_))] uint opcode, public void Vfma_Vfms_V_F32([ValueSource(nameof(_Vfma_Vfms_V_F32_))] uint opcode,
[Values(0u, 1u, 2u, 3u)] uint rd, [Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rn, [Values(0u, 1u, 2u, 3u)] uint rn,
@@ -535,14 +547,17 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rm >>= 1; rm <<= 1; rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(d0, d1); V128 v0 = MakeVectorE0E1(d0, d1);
V128 v1 = MakeVectorE0E1(d2, d3); V128 v1 = MakeVectorE0E1(d2, d3);
@@ -552,7 +567,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void Vmla_Vmls_Vnmla_Vnmls_S_F32([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F32_))] uint opcode, public void Vmla_Vmls_Vnmla_Vnmls_S_F32([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F32_))] uint opcode,
[Values(0u, 1u, 2u, 3u)] uint rd, [Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rn, [Values(0u, 1u, 2u, 3u)] uint rn,
@@ -563,8 +579,8 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_1S_F_))] ulong s3) [ValueSource(nameof(_1S_F_))] ulong s3)
{ {
opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11); opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11);
opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) << 15); opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) << 15);
opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1); opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1);
V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3); V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3);
@@ -573,7 +589,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void Vmla_Vmls_Vnmla_Vnmls_S_F64([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F64_))] uint opcode, public void Vmla_Vmls_Vnmla_Vnmls_S_F64([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F64_))] uint opcode,
[Values(0u, 1u)] uint rd, [Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rn, [Values(0u, 1u)] uint rn,
@@ -582,8 +599,8 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_1D_F_))] ulong d1) [ValueSource(nameof(_1D_F_))] ulong d1)
{ {
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12); opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16); opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0); opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
V128 v0 = MakeVectorE0E1(d0, d1); V128 v0 = MakeVectorE0E1(d0, d1);
@@ -603,7 +620,7 @@ namespace Ryujinx.Tests.Cpu
[Random(RndCnt)] ulong b, [Random(RndCnt)] ulong b,
[Values] bool u) [Values] bool u)
{ {
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -636,7 +653,7 @@ namespace Ryujinx.Tests.Cpu
{ {
uint opcode = 0xf2800c00u; // VMULL.S8 Q0, D0, D0 uint opcode = 0xf2800c00u; // VMULL.S8 Q0, D0, D0
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -678,11 +695,12 @@ namespace Ryujinx.Tests.Cpu
uint opcode = 0xf2800e00u; // VMULL.P8 Q0, D0, D0 uint opcode = 0xf2800e00u; // VMULL.P8 Q0, D0, D0
rd >>= 1; rd <<= 1; rd >>= 1;
rd <<= 1;
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12); opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16); opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0); opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
opcode |= (size & 0x3) << 20; opcode |= (size & 0x3) << 20;
@@ -723,7 +741,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24; opcode |= 1 << 24;
} }
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -751,7 +769,7 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_2S_F_))] ulong b0, [ValueSource(nameof(_2S_F_))] ulong b0,
[ValueSource(nameof(_2S_F_))] ulong b1) [ValueSource(nameof(_2S_F_))] ulong b1)
{ {
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -774,7 +792,7 @@ namespace Ryujinx.Tests.Cpu
[Random(RndCnt)] ulong a, [Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b) [Random(RndCnt)] ulong b)
{ {
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -805,7 +823,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24; opcode |= 1 << 24;
} }
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -836,13 +854,16 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24; opcode |= 1 << 24;
} }
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rm >>= 1; rm <<= 1; rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (size & 0x3) << 20; opcode |= (size & 0x3) << 20;
@@ -864,15 +885,18 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_8B4H2S1D_))] ulong b, [ValueSource(nameof(_8B4H2S1D_))] ulong b,
[Values(1u, 2u)] uint size) // <S16, S32> [Values(1u, 2u)] uint size) // <S16, S32>
{ {
rd >>= 1; rd <<= 1; rd >>= 1;
rn >>= 1; rn <<= 1; rd <<= 1;
rm >>= 1; rm <<= 1; rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0 uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (size & 0x3) << 20; opcode |= (size & 0x3) << 20;
@@ -886,4 +910,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -10,21 +10,25 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdRegElem #if SimdRegElem
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _2S_() private static ulong[] _2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, return new[] {
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H_() private static ulong[] _4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_() private static uint[] _Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_()
{ {
return new[] return new[]
@@ -33,7 +37,7 @@ namespace Ryujinx.Tests.Cpu
0x2F404000u, // MLS V0.4H, V0.4H, V0.H[0] 0x2F404000u, // MLS V0.4H, V0.4H, V0.H[0]
0x0F408000u, // MUL V0.4H, V0.4H, V0.H[0] 0x0F408000u, // MUL V0.4H, V0.4H, V0.H[0]
0x0F40C000u, // SQDMULH V0.4H, V0.4H, V0.H[0] 0x0F40C000u, // SQDMULH V0.4H, V0.4H, V0.H[0]
0x0F40D000u // SQRDMULH V0.4H, V0.4H, V0.H[0] 0x0F40D000u, // SQRDMULH V0.4H, V0.4H, V0.H[0]
}; };
} }
@@ -45,7 +49,7 @@ namespace Ryujinx.Tests.Cpu
0x2F804000u, // MLS V0.2S, V0.2S, V0.S[0] 0x2F804000u, // MLS V0.2S, V0.2S, V0.S[0]
0x0F808000u, // MUL V0.2S, V0.2S, V0.S[0] 0x0F808000u, // MUL V0.2S, V0.2S, V0.S[0]
0x0F80C000u, // SQDMULH V0.2S, V0.2S, V0.S[0] 0x0F80C000u, // SQDMULH V0.2S, V0.2S, V0.S[0]
0x0F80D000u // SQRDMULH V0.2S, V0.2S, V0.S[0] 0x0F80D000u, // SQRDMULH V0.2S, V0.2S, V0.S[0]
}; };
} }
@@ -58,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
0x0F40A000u, // SMULL V0.4S, V0.4H, V0.H[0] 0x0F40A000u, // SMULL V0.4S, V0.4H, V0.H[0]
0x2F402000u, // UMLAL V0.4S, V0.4H, V0.H[0] 0x2F402000u, // UMLAL V0.4S, V0.4H, V0.H[0]
0x2F406000u, // UMLSL V0.4S, V0.4H, V0.H[0] 0x2F406000u, // UMLSL V0.4S, V0.4H, V0.H[0]
0x2F40A000u // UMULL V0.4S, V0.4H, V0.H[0] 0x2F40A000u, // UMULL V0.4S, V0.4H, V0.H[0]
}; };
} }
@@ -71,15 +75,15 @@ namespace Ryujinx.Tests.Cpu
0x0F80A000u, // SMULL V0.2D, V0.2S, V0.S[0] 0x0F80A000u, // SMULL V0.2D, V0.2S, V0.S[0]
0x2F802000u, // UMLAL V0.2D, V0.2S, V0.S[0] 0x2F802000u, // UMLAL V0.2D, V0.2S, V0.S[0]
0x2F806000u, // UMLSL V0.2D, V0.2S, V0.S[0] 0x2F806000u, // UMLSL V0.2D, V0.2S, V0.S[0]
0x2F80A000u // UMULL V0.2D, V0.2S, V0.S[0] 0x2F80A000u, // UMULL V0.2D, V0.2S, V0.S[0]
}; };
} }
#endregion #endregion
[Test, Pairwise] [Test, Pairwise]
public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_))] uint opcodes, public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
@@ -134,7 +138,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S_))] uint opcodes, public void SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
@@ -162,7 +166,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D_))] uint opcodes, public void SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
@@ -188,4 +192,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdRegElemF #if SimdRegElemF
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
{ {
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue) yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x0000000080000000ul; // -Zero yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0x00000000FF800000ul; // -Infinity yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity yield return 0x000000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -65,19 +65,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000080000000ul; // -Zero yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFF800000FF800000ul; // -Infinity yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity yield return 0x7F8000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -106,19 +106,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -135,15 +135,15 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2; yield return rnd2;
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _F_Mla_Mls_Se_S_() private static uint[] _F_Mla_Mls_Se_S_()
{ {
return new[] return new[]
{ {
0x5F821020u, // FMLA S0, S1, V2.S[0] 0x5F821020u, // FMLA S0, S1, V2.S[0]
0x5F825020u // FMLS S0, S1, V2.S[0] 0x5F825020u, // FMLS S0, S1, V2.S[0]
}; };
} }
@@ -152,7 +152,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5FC21020u, // FMLA D0, D1, V2.D[0] 0x5FC21020u, // FMLA D0, D1, V2.D[0]
0x5FC25020u // FMLS D0, D1, V2.D[0] 0x5FC25020u, // FMLS D0, D1, V2.D[0]
}; };
} }
@@ -161,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F801000u, // FMLA V0.2S, V0.2S, V0.S[0] 0x0F801000u, // FMLA V0.2S, V0.2S, V0.S[0]
0x0F805000u // FMLS V0.2S, V0.2S, V0.S[0] 0x0F805000u, // FMLS V0.2S, V0.2S, V0.S[0]
}; };
} }
@@ -170,7 +170,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4FC01000u, // FMLA V0.2D, V0.2D, V0.D[0] 0x4FC01000u, // FMLA V0.2D, V0.2D, V0.D[0]
0x4FC05000u // FMLS V0.2D, V0.2D, V0.D[0] 0x4FC05000u, // FMLS V0.2D, V0.2D, V0.D[0]
}; };
} }
@@ -179,7 +179,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5F829020u, // FMUL S0, S1, V2.S[0] 0x5F829020u, // FMUL S0, S1, V2.S[0]
0x7F829020u // FMULX S0, S1, V2.S[0] 0x7F829020u, // FMULX S0, S1, V2.S[0]
}; };
} }
@@ -188,7 +188,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5FC29020u, // FMUL D0, D1, V2.D[0] 0x5FC29020u, // FMUL D0, D1, V2.D[0]
0x7FC29020u // FMULX D0, D1, V2.D[0] 0x7FC29020u, // FMULX D0, D1, V2.D[0]
}; };
} }
@@ -197,7 +197,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F809000u, // FMUL V0.2S, V0.2S, V0.S[0] 0x0F809000u, // FMUL V0.2S, V0.2S, V0.S[0]
0x2F809000u // FMULX V0.2S, V0.2S, V0.S[0] 0x2F809000u, // FMULX V0.2S, V0.2S, V0.S[0]
}; };
} }
@@ -206,18 +206,20 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4FC09000u, // FMUL V0.2D, V0.2D, V0.D[0] 0x4FC09000u, // FMUL V0.2D, V0.2D, V0.D[0]
0x6FC09000u // FMULX V0.2D, V0.2D, V0.D[0] 0x6FC09000u, // FMULX V0.2D, V0.2D, V0.D[0]
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Mla_Mls_Se_S([ValueSource(nameof(_F_Mla_Mls_Se_S_))] uint opcodes, public void F_Mla_Mls_Se_S([ValueSource(nameof(_F_Mla_Mls_Se_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong z, [ValueSource(nameof(_1S_F_))] ulong z,
[ValueSource(nameof(_1S_F_))] ulong a, [ValueSource(nameof(_1S_F_))] ulong a,
@@ -243,7 +245,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS); CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Mla_Mls_Se_D([ValueSource(nameof(_F_Mla_Mls_Se_D_))] uint opcodes, public void F_Mla_Mls_Se_D([ValueSource(nameof(_F_Mla_Mls_Se_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong z, [ValueSource(nameof(_1D_F_))] ulong z,
[ValueSource(nameof(_1D_F_))] ulong a, [ValueSource(nameof(_1D_F_))] ulong a,
@@ -268,9 +272,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD); CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Mla_Mls_Ve_2S_4S([ValueSource(nameof(_F_Mla_Mls_Ve_2S_4S_))] uint opcodes, public void F_Mla_Mls_Ve_2S_4S([ValueSource(nameof(_F_Mla_Mls_Ve_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_2S_F_))] ulong z, [ValueSource(nameof(_2S_F_))] ulong z,
@@ -300,9 +306,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS); CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Mla_Mls_Ve_2D([ValueSource(nameof(_F_Mla_Mls_Ve_2D_))] uint opcodes, public void F_Mla_Mls_Ve_2D([ValueSource(nameof(_F_Mla_Mls_Ve_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_1D_F_))] ulong z, [ValueSource(nameof(_1D_F_))] ulong z,
@@ -329,7 +337,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD); CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mul_Mulx_Se_S([ValueSource(nameof(_F_Mul_Mulx_Se_S_))] uint opcodes, public void F_Mul_Mulx_Se_S([ValueSource(nameof(_F_Mul_Mulx_Se_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a, [ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b, [ValueSource(nameof(_2S_F_))] ulong b,
@@ -355,7 +364,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mul_Mulx_Se_D([ValueSource(nameof(_F_Mul_Mulx_Se_D_))] uint opcodes, public void F_Mul_Mulx_Se_D([ValueSource(nameof(_F_Mul_Mulx_Se_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a, [ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b, [ValueSource(nameof(_1D_F_))] ulong b,
@@ -380,9 +390,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mul_Mulx_Ve_2S_4S([ValueSource(nameof(_F_Mul_Mulx_Ve_2S_4S_))] uint opcodes, public void F_Mul_Mulx_Ve_2S_4S([ValueSource(nameof(_F_Mul_Mulx_Ve_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_2S_F_))] ulong z, [ValueSource(nameof(_2S_F_))] ulong z,
@@ -412,9 +423,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Mul_Mulx_Ve_2D([ValueSource(nameof(_F_Mul_Mulx_Ve_2D_))] uint opcodes, public void F_Mul_Mulx_Ve_2D([ValueSource(nameof(_F_Mul_Mulx_Ve_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm, [Values(2u, 0u)] uint rm,
[ValueSource(nameof(_1D_F_))] ulong z, [ValueSource(nameof(_1D_F_))] ulong z,

View File

@@ -12,41 +12,53 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdShImm #if SimdShImm
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _1D_() private static ulong[] _1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _1H_() private static ulong[] _1H_()
{ {
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul, return new[] {
0x0000000000008000ul, 0x000000000000FFFFul }; 0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul,
};
} }
private static ulong[] _1S_() private static ulong[] _1S_()
{ {
return new[] { 0x0000000000000000ul, 0x000000007FFFFFFFul, return new[] {
0x0000000080000000ul, 0x00000000FFFFFFFFul }; 0x0000000000000000ul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul,
};
} }
private static ulong[] _2S_() private static ulong[] _2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, return new[] {
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H_() private static ulong[] _4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _2S_F_W_() private static IEnumerable<ulong> _2S_F_W_()
@@ -73,19 +85,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000080000000ul; // -Zero yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFF800000FF800000ul; // -Infinity yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity yield return 0x7F8000007F800000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -133,19 +145,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros) if (!_noZeros)
{ {
yield return 0x8000000000000000ul; // -Zero yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero yield return 0x0000000000000000ul; // +Zero
} }
if (!NoInfs) if (!_noInfs)
{ {
yield return 0xFFF0000000000000ul; // -Infinity yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity yield return 0x7FF0000000000000ul; // +Infinity
} }
if (!NoNaNs) if (!_noNaNs)
{ {
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -170,15 +182,15 @@ namespace Ryujinx.Tests.Cpu
yield return rnd4; yield return rnd4;
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_Z_SU_V_Fixed_2S_4S_() private static uint[] _F_Cvt_Z_SU_V_Fixed_2S_4S_()
{ {
return new[] return new[]
{ {
0x0F20FC00u, // FCVTZS V0.2S, V0.2S, #32 0x0F20FC00u, // FCVTZS V0.2S, V0.2S, #32
0x2F20FC00u // FCVTZU V0.2S, V0.2S, #32 0x2F20FC00u, // FCVTZU V0.2S, V0.2S, #32
}; };
} }
@@ -187,7 +199,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4F40FC00u, // FCVTZS V0.2D, V0.2D, #64 0x4F40FC00u, // FCVTZS V0.2D, V0.2D, #64
0x6F40FC00u // FCVTZU V0.2D, V0.2D, #64 0x6F40FC00u, // FCVTZU V0.2D, V0.2D, #64
}; };
} }
@@ -196,7 +208,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5F20E420u, // SCVTF S0, S1, #32 0x5F20E420u, // SCVTF S0, S1, #32
0x7F20E420u // UCVTF S0, S1, #32 0x7F20E420u, // UCVTF S0, S1, #32
}; };
} }
@@ -205,7 +217,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5F40E420u, // SCVTF D0, D1, #64 0x5F40E420u, // SCVTF D0, D1, #64
0x7F40E420u // UCVTF D0, D1, #64 0x7F40E420u, // UCVTF D0, D1, #64
}; };
} }
@@ -214,7 +226,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F20E400u, // SCVTF V0.2S, V0.2S, #32 0x0F20E400u, // SCVTF V0.2S, V0.2S, #32
0x2F20E400u // UCVTF V0.2S, V0.2S, #32 0x2F20E400u, // UCVTF V0.2S, V0.2S, #32
}; };
} }
@@ -223,7 +235,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4F40E400u, // SCVTF V0.2D, V0.2D, #64 0x4F40E400u, // SCVTF V0.2D, V0.2D, #64
0x6F40E400u // UCVTF V0.2D, V0.2D, #64 0x6F40E400u, // UCVTF V0.2D, V0.2D, #64
}; };
} }
@@ -232,7 +244,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5F405400u, // SHL D0, D0, #0 0x5F405400u, // SHL D0, D0, #0
0x7F405400u // SLI D0, D0, #0 0x7F405400u, // SLI D0, D0, #0
}; };
} }
@@ -241,7 +253,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F085400u, // SHL V0.8B, V0.8B, #0 0x0F085400u, // SHL V0.8B, V0.8B, #0
0x2F085400u // SLI V0.8B, V0.8B, #0 0x2F085400u, // SLI V0.8B, V0.8B, #0
}; };
} }
@@ -250,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F105400u, // SHL V0.4H, V0.4H, #0 0x0F105400u, // SHL V0.4H, V0.4H, #0
0x2F105400u // SLI V0.4H, V0.4H, #0 0x2F105400u, // SLI V0.4H, V0.4H, #0
}; };
} }
@@ -259,7 +271,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F205400u, // SHL V0.2S, V0.2S, #0 0x0F205400u, // SHL V0.2S, V0.2S, #0
0x2F205400u // SLI V0.2S, V0.2S, #0 0x2F205400u, // SLI V0.2S, V0.2S, #0
}; };
} }
@@ -268,7 +280,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4F405400u, // SHL V0.2D, V0.2D, #0 0x4F405400u, // SHL V0.2D, V0.2D, #0
0x6F405400u // SLI V0.2D, V0.2D, #0 0x6F405400u, // SLI V0.2D, V0.2D, #0
}; };
} }
@@ -277,7 +289,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F08A400u, // SSHLL V0.8H, V0.8B, #0 0x0F08A400u, // SSHLL V0.8H, V0.8B, #0
0x2F08A400u // USHLL V0.8H, V0.8B, #0 0x2F08A400u, // USHLL V0.8H, V0.8B, #0
}; };
} }
@@ -286,7 +298,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F10A400u, // SSHLL V0.4S, V0.4H, #0 0x0F10A400u, // SSHLL V0.4S, V0.4H, #0
0x2F10A400u // USHLL V0.4S, V0.4H, #0 0x2F10A400u, // USHLL V0.4S, V0.4H, #0
}; };
} }
@@ -295,7 +307,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F20A400u, // SSHLL V0.2D, V0.2S, #0 0x0F20A400u, // SSHLL V0.2D, V0.2S, #0
0x2F20A400u // USHLL V0.2D, V0.2S, #0 0x2F20A400u, // USHLL V0.2D, V0.2S, #0
}; };
} }
@@ -311,7 +323,7 @@ namespace Ryujinx.Tests.Cpu
0x7F402400u, // URSHR D0, D0, #64 0x7F402400u, // URSHR D0, D0, #64
0x7F403400u, // URSRA D0, D0, #64 0x7F403400u, // URSRA D0, D0, #64
0x7F400400u, // USHR D0, D0, #64 0x7F400400u, // USHR D0, D0, #64
0x7F401400u // USRA D0, D0, #64 0x7F401400u, // USRA D0, D0, #64
}; };
} }
@@ -327,7 +339,7 @@ namespace Ryujinx.Tests.Cpu
0x2F082400u, // URSHR V0.8B, V0.8B, #8 0x2F082400u, // URSHR V0.8B, V0.8B, #8
0x2F083400u, // URSRA V0.8B, V0.8B, #8 0x2F083400u, // URSRA V0.8B, V0.8B, #8
0x2F080400u, // USHR V0.8B, V0.8B, #8 0x2F080400u, // USHR V0.8B, V0.8B, #8
0x2F081400u // USRA V0.8B, V0.8B, #8 0x2F081400u, // USRA V0.8B, V0.8B, #8
}; };
} }
@@ -343,7 +355,7 @@ namespace Ryujinx.Tests.Cpu
0x2F102400u, // URSHR V0.4H, V0.4H, #16 0x2F102400u, // URSHR V0.4H, V0.4H, #16
0x2F103400u, // URSRA V0.4H, V0.4H, #16 0x2F103400u, // URSRA V0.4H, V0.4H, #16
0x2F100400u, // USHR V0.4H, V0.4H, #16 0x2F100400u, // USHR V0.4H, V0.4H, #16
0x2F101400u // USRA V0.4H, V0.4H, #16 0x2F101400u, // USRA V0.4H, V0.4H, #16
}; };
} }
@@ -359,7 +371,7 @@ namespace Ryujinx.Tests.Cpu
0x2F202400u, // URSHR V0.2S, V0.2S, #32 0x2F202400u, // URSHR V0.2S, V0.2S, #32
0x2F203400u, // URSRA V0.2S, V0.2S, #32 0x2F203400u, // URSRA V0.2S, V0.2S, #32
0x2F200400u, // USHR V0.2S, V0.2S, #32 0x2F200400u, // USHR V0.2S, V0.2S, #32
0x2F201400u // USRA V0.2S, V0.2S, #32 0x2F201400u, // USRA V0.2S, V0.2S, #32
}; };
} }
@@ -375,7 +387,7 @@ namespace Ryujinx.Tests.Cpu
0x6F402400u, // URSHR V0.2D, V0.2D, #64 0x6F402400u, // URSHR V0.2D, V0.2D, #64
0x6F403400u, // URSRA V0.2D, V0.2D, #64 0x6F403400u, // URSRA V0.2D, V0.2D, #64
0x6F400400u, // USHR V0.2D, V0.2D, #64 0x6F400400u, // USHR V0.2D, V0.2D, #64
0x6F401400u // USRA V0.2D, V0.2D, #64 0x6F401400u, // USRA V0.2D, V0.2D, #64
}; };
} }
@@ -384,7 +396,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F088C00u, // RSHRN V0.8B, V0.8H, #8 0x0F088C00u, // RSHRN V0.8B, V0.8H, #8
0x0F088400u // SHRN V0.8B, V0.8H, #8 0x0F088400u, // SHRN V0.8B, V0.8H, #8
}; };
} }
@@ -393,7 +405,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F108C00u, // RSHRN V0.4H, V0.4S, #16 0x0F108C00u, // RSHRN V0.4H, V0.4S, #16
0x0F108400u // SHRN V0.4H, V0.4S, #16 0x0F108400u, // SHRN V0.4H, V0.4S, #16
}; };
} }
@@ -402,7 +414,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0F208C00u, // RSHRN V0.2S, V0.2D, #32 0x0F208C00u, // RSHRN V0.2S, V0.2D, #32
0x0F208400u // SHRN V0.2S, V0.2D, #32 0x0F208400u, // SHRN V0.2S, V0.2D, #32
}; };
} }
@@ -415,7 +427,7 @@ namespace Ryujinx.Tests.Cpu
0x7F088C00u, // SQRSHRUN B0, H0, #8 0x7F088C00u, // SQRSHRUN B0, H0, #8
0x5F089400u, // SQSHRN B0, H0, #8 0x5F089400u, // SQSHRN B0, H0, #8
0x7F089400u, // UQSHRN B0, H0, #8 0x7F089400u, // UQSHRN B0, H0, #8
0x7F088400u // SQSHRUN B0, H0, #8 0x7F088400u, // SQSHRUN B0, H0, #8
}; };
} }
@@ -428,7 +440,7 @@ namespace Ryujinx.Tests.Cpu
0x7F108C00u, // SQRSHRUN H0, S0, #16 0x7F108C00u, // SQRSHRUN H0, S0, #16
0x5F109400u, // SQSHRN H0, S0, #16 0x5F109400u, // SQSHRN H0, S0, #16
0x7F109400u, // UQSHRN H0, S0, #16 0x7F109400u, // UQSHRN H0, S0, #16
0x7F108400u // SQSHRUN H0, S0, #16 0x7F108400u, // SQSHRUN H0, S0, #16
}; };
} }
@@ -441,7 +453,7 @@ namespace Ryujinx.Tests.Cpu
0x7F208C00u, // SQRSHRUN S0, D0, #32 0x7F208C00u, // SQRSHRUN S0, D0, #32
0x5F209400u, // SQSHRN S0, D0, #32 0x5F209400u, // SQSHRN S0, D0, #32
0x7F209400u, // UQSHRN S0, D0, #32 0x7F209400u, // UQSHRN S0, D0, #32
0x7F208400u // SQSHRUN S0, D0, #32 0x7F208400u, // SQSHRUN S0, D0, #32
}; };
} }
@@ -454,7 +466,7 @@ namespace Ryujinx.Tests.Cpu
0x2F088C00u, // SQRSHRUN V0.8B, V0.8H, #8 0x2F088C00u, // SQRSHRUN V0.8B, V0.8H, #8
0x0F089400u, // SQSHRN V0.8B, V0.8H, #8 0x0F089400u, // SQSHRN V0.8B, V0.8H, #8
0x2F089400u, // UQSHRN V0.8B, V0.8H, #8 0x2F089400u, // UQSHRN V0.8B, V0.8H, #8
0x2F088400u // SQSHRUN V0.8B, V0.8H, #8 0x2F088400u, // SQSHRUN V0.8B, V0.8H, #8
}; };
} }
@@ -467,7 +479,7 @@ namespace Ryujinx.Tests.Cpu
0x2F108C00u, // SQRSHRUN V0.4H, V0.4S, #16 0x2F108C00u, // SQRSHRUN V0.4H, V0.4S, #16
0x0F109400u, // SQSHRN V0.4H, V0.4S, #16 0x0F109400u, // SQSHRN V0.4H, V0.4S, #16
0x2F109400u, // UQSHRN V0.4H, V0.4S, #16 0x2F109400u, // UQSHRN V0.4H, V0.4S, #16
0x2F108400u // SQSHRUN V0.4H, V0.4S, #16 0x2F108400u, // SQSHRUN V0.4H, V0.4S, #16
}; };
} }
@@ -480,20 +492,21 @@ namespace Ryujinx.Tests.Cpu
0x2F208C00u, // SQRSHRUN V0.2S, V0.2D, #32 0x2F208C00u, // SQRSHRUN V0.2S, V0.2D, #32
0x0F209400u, // SQSHRN V0.2S, V0.2D, #32 0x0F209400u, // SQSHRN V0.2S, V0.2D, #32
0x2F209400u, // UQSHRN V0.2S, V0.2D, #32 0x2F209400u, // UQSHRN V0.2S, V0.2D, #32
0x2F208400u // SQSHRUN V0.2S, V0.2D, #32 0x2F208400u, // SQSHRUN V0.2S, V0.2D, #32
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private static readonly bool NoZeros = false; private static readonly bool _noZeros = false;
private static readonly bool NoInfs = false; private static readonly bool _noInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool _noNaNs = false;
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_V_Fixed_2S_4S([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2S_4S_))] uint opcodes, public void F_Cvt_Z_SU_V_Fixed_2S_4S([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_F_W_))] ulong z, [ValueSource(nameof(_2S_F_W_))] ulong z,
[ValueSource(nameof(_2S_F_W_))] ulong a, [ValueSource(nameof(_2S_F_W_))] ulong a,
@@ -514,9 +527,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cvt_Z_SU_V_Fixed_2D([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2D_))] uint opcodes, public void F_Cvt_Z_SU_V_Fixed_2D([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_F_X_))] ulong z, [ValueSource(nameof(_1D_F_X_))] ulong z,
[ValueSource(nameof(_1D_F_X_))] ulong a, [ValueSource(nameof(_1D_F_X_))] ulong a,
@@ -535,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_S_Fixed_S([ValueSource(nameof(_SU_Cvt_F_S_Fixed_S_))] uint opcodes, public void SU_Cvt_F_S_Fixed_S([ValueSource(nameof(_SU_Cvt_F_S_Fixed_S_))] uint opcodes,
[ValueSource(nameof(_1S_))] ulong a, [ValueSource(nameof(_1S_))] ulong a,
[Values(1u, 32u)] uint fBits) [Values(1u, 32u)] uint fBits)
@@ -553,7 +568,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_S_Fixed_D([ValueSource(nameof(_SU_Cvt_F_S_Fixed_D_))] uint opcodes, public void SU_Cvt_F_S_Fixed_D([ValueSource(nameof(_SU_Cvt_F_S_Fixed_D_))] uint opcodes,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint fBits) [Values(1u, 64u)] uint fBits)
@@ -571,9 +587,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2S_4S_))] uint opcodes, public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -594,9 +611,10 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void SU_Cvt_F_V_Fixed_2D([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2D_))] uint opcodes, public void SU_Cvt_F_V_Fixed_2D([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -617,7 +635,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Shl_Sli_S_D([ValueSource(nameof(_Shl_Sli_S_D_))] uint opcodes, public void Shl_Sli_S_D([ValueSource(nameof(_Shl_Sli_S_D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -638,7 +656,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Shl_Sli_V_8B_16B([ValueSource(nameof(_Shl_Sli_V_8B_16B_))] uint opcodes, public void Shl_Sli_V_8B_16B([ValueSource(nameof(_Shl_Sli_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
@@ -661,7 +679,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Shl_Sli_V_4H_8H([ValueSource(nameof(_Shl_Sli_V_4H_8H_))] uint opcodes, public void Shl_Sli_V_4H_8H([ValueSource(nameof(_Shl_Sli_V_4H_8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -684,7 +702,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Shl_Sli_V_2S_4S([ValueSource(nameof(_Shl_Sli_V_2S_4S_))] uint opcodes, public void Shl_Sli_V_2S_4S([ValueSource(nameof(_Shl_Sli_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -707,7 +725,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Shl_Sli_V_2D([ValueSource(nameof(_Shl_Sli_V_2D_))] uint opcodes, public void Shl_Sli_V_2D([ValueSource(nameof(_Shl_Sli_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -728,7 +746,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void SU_Shll_V_8B8H_16B8H([ValueSource(nameof(_SU_Shll_V_8B8H_16B8H_))] uint opcodes, public void SU_Shll_V_8B8H_16B8H([ValueSource(nameof(_SU_Shll_V_8B8H_16B8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
@@ -751,7 +769,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void SU_Shll_V_4H4S_8H4S([ValueSource(nameof(_SU_Shll_V_4H4S_8H4S_))] uint opcodes, public void SU_Shll_V_4H4S_8H4S([ValueSource(nameof(_SU_Shll_V_4H4S_8H4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -774,7 +792,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void SU_Shll_V_2S2D_4S2D([ValueSource(nameof(_SU_Shll_V_2S2D_4S2D_))] uint opcodes, public void SU_Shll_V_2S2D_4S2D([ValueSource(nameof(_SU_Shll_V_2S2D_4S2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -797,7 +815,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImm_Sri_S_D([ValueSource(nameof(_ShrImm_Sri_S_D_))] uint opcodes, public void ShrImm_Sri_S_D([ValueSource(nameof(_ShrImm_Sri_S_D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -818,7 +836,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImm_Sri_V_8B_16B([ValueSource(nameof(_ShrImm_Sri_V_8B_16B_))] uint opcodes, public void ShrImm_Sri_V_8B_16B([ValueSource(nameof(_ShrImm_Sri_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a, [ValueSource(nameof(_8B_))] ulong a,
@@ -841,7 +859,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImm_Sri_V_4H_8H([ValueSource(nameof(_ShrImm_Sri_V_4H_8H_))] uint opcodes, public void ShrImm_Sri_V_4H_8H([ValueSource(nameof(_ShrImm_Sri_V_4H_8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -864,7 +882,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImm_Sri_V_2S_4S([ValueSource(nameof(_ShrImm_Sri_V_2S_4S_))] uint opcodes, public void ShrImm_Sri_V_2S_4S([ValueSource(nameof(_ShrImm_Sri_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -887,7 +905,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImm_Sri_V_2D([ValueSource(nameof(_ShrImm_Sri_V_2D_))] uint opcodes, public void ShrImm_Sri_V_2D([ValueSource(nameof(_ShrImm_Sri_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -908,7 +926,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmNarrow_V_8H8B_8H16B_))] uint opcodes, public void ShrImmNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmNarrow_V_8H8B_8H16B_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -931,7 +949,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmNarrow_V_4S4H_4S8H_))] uint opcodes, public void ShrImmNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmNarrow_V_4S4H_4S8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -954,7 +972,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmNarrow_V_2D2S_2D4S_))] uint opcodes, public void ShrImmNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmNarrow_V_2D2S_2D4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -977,7 +995,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_S_HB([ValueSource(nameof(_ShrImmSaturatingNarrow_S_HB_))] uint opcodes, public void ShrImmSaturatingNarrow_S_HB([ValueSource(nameof(_ShrImmSaturatingNarrow_S_HB_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1H_))] ulong z, [ValueSource(nameof(_1H_))] ulong z,
[ValueSource(nameof(_1H_))] ulong a, [ValueSource(nameof(_1H_))] ulong a,
@@ -998,7 +1016,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_S_SH([ValueSource(nameof(_ShrImmSaturatingNarrow_S_SH_))] uint opcodes, public void ShrImmSaturatingNarrow_S_SH([ValueSource(nameof(_ShrImmSaturatingNarrow_S_SH_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1S_))] ulong z, [ValueSource(nameof(_1S_))] ulong z,
[ValueSource(nameof(_1S_))] ulong a, [ValueSource(nameof(_1S_))] ulong a,
@@ -1019,7 +1037,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_S_DS([ValueSource(nameof(_ShrImmSaturatingNarrow_S_DS_))] uint opcodes, public void ShrImmSaturatingNarrow_S_DS([ValueSource(nameof(_ShrImmSaturatingNarrow_S_DS_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -1040,7 +1058,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmSaturatingNarrow_V_8H8B_8H16B_))] uint opcodes, public void ShrImmSaturatingNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmSaturatingNarrow_V_8H8B_8H16B_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_4H_))] ulong z, [ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a, [ValueSource(nameof(_4H_))] ulong a,
@@ -1063,7 +1081,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmSaturatingNarrow_V_4S4H_4S8H_))] uint opcodes, public void ShrImmSaturatingNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmSaturatingNarrow_V_4S4H_4S8H_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_2S_))] ulong z, [ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a, [ValueSource(nameof(_2S_))] ulong a,
@@ -1086,7 +1104,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void ShrImmSaturatingNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmSaturatingNarrow_V_2D2S_2D4S_))] uint opcodes, public void ShrImmSaturatingNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmSaturatingNarrow_V_2D2S_2D4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
[ValueSource(nameof(_1D_))] ulong z, [ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a, [ValueSource(nameof(_1D_))] ulong a,
@@ -1108,4 +1126,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -10,30 +10,41 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdShImm32 #if SimdShImm32
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _1D_() private static ulong[] _1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _2S_() private static ulong[] _2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; return new[]
{
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H_() private static ulong[] _4H_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; return new[]
{
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; return new[]
{
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _Vshr_Imm_SU8_() private static uint[] _Vshr_Imm_SU8_()
{ {
return new[] return new[]
@@ -41,7 +52,7 @@ namespace Ryujinx.Tests.Cpu
0xf2880010u, // VSHR.S8 D0, D0, #8 0xf2880010u, // VSHR.S8 D0, D0, #8
0xf2880110u, // VSRA.S8 D0, D0, #8 0xf2880110u, // VSRA.S8 D0, D0, #8
0xf2880210u, // VRSHR.S8 D0, D0, #8 0xf2880210u, // VRSHR.S8 D0, D0, #8
0xf2880310u // VRSRA.S8 D0, D0, #8 0xf2880310u, // VRSRA.S8 D0, D0, #8
}; };
} }
@@ -52,7 +63,7 @@ namespace Ryujinx.Tests.Cpu
0xf2900010u, // VSHR.S16 D0, D0, #16 0xf2900010u, // VSHR.S16 D0, D0, #16
0xf2900110u, // VSRA.S16 D0, D0, #16 0xf2900110u, // VSRA.S16 D0, D0, #16
0xf2900210u, // VRSHR.S16 D0, D0, #16 0xf2900210u, // VRSHR.S16 D0, D0, #16
0xf2900310u // VRSRA.S16 D0, D0, #16 0xf2900310u, // VRSRA.S16 D0, D0, #16
}; };
} }
@@ -63,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
0xf2a00010u, // VSHR.S32 D0, D0, #32 0xf2a00010u, // VSHR.S32 D0, D0, #32
0xf2a00110u, // VSRA.S32 D0, D0, #32 0xf2a00110u, // VSRA.S32 D0, D0, #32
0xf2a00210u, // VRSHR.S32 D0, D0, #32 0xf2a00210u, // VRSHR.S32 D0, D0, #32
0xf2a00310u // VRSRA.S32 D0, D0, #32 0xf2a00310u, // VRSRA.S32 D0, D0, #32
}; };
} }
@@ -73,7 +84,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0xf2800190u, // VSRA.S64 D0, D0, #64 0xf2800190u, // VSRA.S64 D0, D0, #64
0xf2800290u, // VRSHR.S64 D0, D0, #64 0xf2800290u, // VRSHR.S64 D0, D0, #64
0xf2800090u // VSHR.S64 D0, D0, #64 0xf2800090u, // VSHR.S64 D0, D0, #64
}; };
} }
@@ -83,7 +94,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN) 0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN)
0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN) 0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
0xf2800850u // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN) 0xf2800850u, // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
}; };
} }
@@ -92,10 +103,10 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN) 0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN) 0xf3800850u, // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
}; };
} }
#endregion #endregion
private const int RndCnt = 2; private const int RndCnt = 2;
private const int RndCntShiftImm = 2; private const int RndCntShiftImm = 2;
@@ -171,12 +182,14 @@ namespace Ryujinx.Tests.Cpu
{ {
opcode |= 1 << 6; opcode |= 1 << 6;
rd >>= 1; rd <<= 1; rd >>= 1;
rm >>= 1; rm <<= 1; rd <<= 1;
rm >>= 1;
rm <<= 1;
} }
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= (imm6 & 0x3f) << 16; opcode |= (imm6 & 0x3f) << 16;
@@ -312,4 +325,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

View File

@@ -11,19 +11,19 @@ namespace Ryujinx.Tests.Cpu
{ {
#if SimdTbl #if SimdTbl
#region "Helper methods" #region "Helper methods"
private static ulong GenIdxsForTbls(int regs) private static ulong GenIdxsForTbls(int regs)
{ {
const byte IdxInRngMin = 0; const byte IdxInRngMin = 0;
byte idxInRngMax = (byte)((16 * regs) - 1); byte idxInRngMax = (byte)((16 * regs) - 1);
byte idxOutRngMin = (byte) (16 * regs); byte idxOutRngMin = (byte)(16 * regs);
const byte IdxOutRngMax = 255; const byte IdxOutRngMax = 255;
ulong idxs = 0ul; ulong idxs = 0ul;
for (int cnt = 1; cnt <= 8; cnt++) for (int cnt = 1; cnt <= 8; cnt++)
{ {
ulong idxInRng = TestContext.CurrentContext.Random.NextByte(IdxInRngMin, idxInRngMax); ulong idxInRng = TestContext.CurrentContext.Random.NextByte(IdxInRngMin, idxInRngMax);
ulong idxOutRng = TestContext.CurrentContext.Random.NextByte(idxOutRngMin, IdxOutRngMax); ulong idxOutRng = TestContext.CurrentContext.Random.NextByte(idxOutRngMin, IdxOutRngMax);
ulong idx = TestContext.CurrentContext.Random.NextBool() ? idxInRng : idxOutRng; ulong idx = TestContext.CurrentContext.Random.NextBool() ? idxInRng : idxOutRng;
@@ -33,13 +33,15 @@ namespace Ryujinx.Tests.Cpu
return idxs; return idxs;
} }
#endregion #endregion
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _GenIdxsForTbl1_() private static IEnumerable<ulong> _GenIdxsForTbl1_()
@@ -93,15 +95,15 @@ namespace Ryujinx.Tests.Cpu
yield return GenIdxsForTbls(regs: 4); yield return GenIdxsForTbls(regs: 4);
} }
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _SingleRegisterTable_V_8B_16B_() private static uint[] _SingleRegisterTable_V_8B_16B_()
{ {
return new[] return new[]
{ {
0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B 0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B
0x0E001000u // TBX V0.8B, { V0.16B }, V0.8B 0x0E001000u, // TBX V0.8B, { V0.16B }, V0.8B
}; };
} }
@@ -110,7 +112,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B 0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B
0x0E003000u // TBX V0.8B, { V0.16B, V1.16B }, V0.8B 0x0E003000u, // TBX V0.8B, { V0.16B, V1.16B }, V0.8B
}; };
} }
@@ -119,7 +121,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B 0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
0x0E005000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B 0x0E005000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
}; };
} }
@@ -128,10 +130,10 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B 0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
0x0E006000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B 0x0E006000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
}; };
} }
#endregion #endregion
private const int RndCntIdxs = 2; private const int RndCntIdxs = 2;
@@ -184,7 +186,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Mod_TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes, public void Mod_TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 1u)] uint rd, [Values(30u, 1u)] uint rd,
[Values(31u)] uint rn, [Values(31u)] uint rn,
[Values(1u, 30u)] uint rm, [Values(1u, 30u)] uint rm,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0, [ValueSource(nameof(_8B_))] ulong table0,
@@ -197,8 +199,8 @@ namespace Ryujinx.Tests.Cpu
V128 v30 = MakeVectorE0E1(z, z); V128 v30 = MakeVectorE0E1(z, z);
V128 v31 = MakeVectorE0E1(table0, table0); V128 v31 = MakeVectorE0E1(table0, table0);
V128 v0 = MakeVectorE0E1(table1, table1); V128 v0 = MakeVectorE0E1(table1, table1);
V128 v1 = MakeVectorE0E1(indexes, indexes); V128 v1 = MakeVectorE0E1(indexes, indexes);
SingleOpcode(opcodes, v0: v0, v1: v1, v30: v30, v31: v31); SingleOpcode(opcodes, v0: v0, v1: v1, v30: v30, v31: v31);
@@ -234,7 +236,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes, public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 2u)] uint rd, [Values(30u, 2u)] uint rd,
[Values(31u)] uint rn, [Values(31u)] uint rn,
[Values(2u, 30u)] uint rm, [Values(2u, 30u)] uint rm,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0, [ValueSource(nameof(_8B_))] ulong table0,
@@ -248,9 +250,9 @@ namespace Ryujinx.Tests.Cpu
V128 v30 = MakeVectorE0E1(z, z); V128 v30 = MakeVectorE0E1(z, z);
V128 v31 = MakeVectorE0E1(table0, table0); V128 v31 = MakeVectorE0E1(table0, table0);
V128 v0 = MakeVectorE0E1(table1, table1); V128 v0 = MakeVectorE0E1(table1, table1);
V128 v1 = MakeVectorE0E1(table2, table2); V128 v1 = MakeVectorE0E1(table2, table2);
V128 v2 = MakeVectorE0E1(indexes, indexes); V128 v2 = MakeVectorE0E1(indexes, indexes);
SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v30: v30, v31: v31); SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v30: v30, v31: v31);
@@ -288,7 +290,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise] [Test, Pairwise]
public void Mod_FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes, public void Mod_FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 3u)] uint rd, [Values(30u, 3u)] uint rd,
[Values(31u)] uint rn, [Values(31u)] uint rn,
[Values(3u, 30u)] uint rm, [Values(3u, 30u)] uint rm,
[ValueSource(nameof(_8B_))] ulong z, [ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0, [ValueSource(nameof(_8B_))] ulong table0,
@@ -303,10 +305,10 @@ namespace Ryujinx.Tests.Cpu
V128 v30 = MakeVectorE0E1(z, z); V128 v30 = MakeVectorE0E1(z, z);
V128 v31 = MakeVectorE0E1(table0, table0); V128 v31 = MakeVectorE0E1(table0, table0);
V128 v0 = MakeVectorE0E1(table1, table1); V128 v0 = MakeVectorE0E1(table1, table1);
V128 v1 = MakeVectorE0E1(table2, table2); V128 v1 = MakeVectorE0E1(table2, table2);
V128 v2 = MakeVectorE0E1(table3, table3); V128 v2 = MakeVectorE0E1(table3, table3);
V128 v3 = MakeVectorE0E1(indexes, indexes); V128 v3 = MakeVectorE0E1(indexes, indexes);
SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3, v30: v30, v31: v31); SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3, v30: v30, v31: v31);

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{ {
#if System #if System
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static IEnumerable<ulong> _GenNzcv_() private static IEnumerable<ulong> _GenNzcv_()
{ {
yield return 0x0000000000000000ul; yield return 0x0000000000000000ul;
@@ -33,23 +33,23 @@ namespace Ryujinx.Tests.Cpu
yield return rnd; yield return rnd;
} }
#endregion #endregion
#region "ValueSource (Opcodes)" #region "ValueSource (Opcodes)"
private static uint[] _MrsMsr_Nzcv_() private static uint[] _MrsMsr_Nzcv_()
{ {
return new[] return new[]
{ {
0xD53B4200u, // MRS X0, NZCV 0xD53B4200u, // MRS X0, NZCV
0xD51B4200u // MSR NZCV, X0 0xD51B4200u, // MSR NZCV, X0
}; };
} }
#endregion #endregion
[Test, Pairwise] [Test, Pairwise]
public void MrsMsr_Nzcv([ValueSource("_MrsMsr_Nzcv_")] uint opcodes, public void MrsMsr_Nzcv([ValueSource(nameof(_MrsMsr_Nzcv_))] uint opcodes,
[Values(0u, 1u, 31u)] uint rt, [Values(0u, 1u, 31u)] uint rt,
[ValueSource("_GenNzcv_")] ulong xt) [ValueSource(nameof(_GenNzcv_))] ulong xt)
{ {
opcodes |= (rt & 31) << 0; opcodes |= (rt & 31) << 0;
@@ -66,4 +66,4 @@ namespace Ryujinx.Tests.Cpu
} }
#endif #endif
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -164,4 +164,4 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false)); Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false));
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using NUnit.Framework; using NUnit.Framework;
using System;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
@@ -14,70 +15,70 @@ namespace Ryujinx.Tests.Cpu
public static readonly PrecomputedMemoryThumbTestCase[] ImmTestCases = public static readonly PrecomputedMemoryThumbTestCase[] ImmTestCases =
{ {
// STRB (imm8) // STRB (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf80c, 0x1b2f, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf80c, 0x1b2f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x000021ff, 0x000026e3, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x000021ff, 0x000026e3, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x0000222e, 0x000026e3, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x0000222e, 0x000026e3, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21fe, Value: 0xbbfe) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21fe, Value: 0xbbfe) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf80a, 0x2f81, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf80a, 0x2f81, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x0000266f, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 }, StartRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x0000266f, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x000026f0, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 }, FinalRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x000026f0, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x26f0, Value: 0x2600) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x26f0, Value: 0x2600) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf803, 0x6968, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf803, 0x6968, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002dac, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 }, StartRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002dac, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002d44, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 }, FinalRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002d44, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2dac, Value: 0x2dc9) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2dac, Value: 0x2dc9) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf804, 0x89ad, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf804, 0x89ad, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002413, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 }, StartRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002413, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002366, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 }, FinalRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002366, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2412, Value: 0xca12) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2412, Value: 0xca12) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf80d, 0xa9fe, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf80d, 0xa9fe, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002d9d, 0x00000001, 0x900001f0 }, StartRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002d9d, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002c9f, 0x00000001, 0x900001f0 }, FinalRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002c9f, 0x00000001, 0x900001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2d9c, Value: 0x0a9c) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2d9c, Value: 0x0a9c) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf80d, 0x3c46, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf80d, 0x3c46, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 }, StartRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 }, FinalRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b76, Value: 0xcc76) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b76, Value: 0xcc76) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf801, 0x6c56, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf801, 0x6c56, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x24da, Value: 0x2473) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x24da, Value: 0x2473) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf809, 0xcc76, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf809, 0xcc76, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c8c, Value: 0xee8c) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c8c, Value: 0xee8c) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf808, 0x1c8d, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf808, 0x1c8d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2e40, Value: 0x2e78) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2e40, Value: 0x2e78) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf80b, 0xbc26, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf80b, 0xbc26, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002244, 0x000025ad, 0x00002434, 0x00002b06, 0x00002ebd, 0x0000292b, 0x00002431, 0x00002e12, 0x0000289b, 0x0000265a, 0x00002747, 0x00002bac, 0x00002dae, 0x00002582, 0x00000001, 0xf00001f0 }, StartRegs = new uint[] { 0x00002244, 0x000025ad, 0x00002434, 0x00002b06, 0x00002ebd, 0x0000292b, 0x00002431, 0x00002e12, 0x0000289b, 0x0000265a, 0x00002747, 0x00002bac, 0x00002dae, 0x00002582, 0x00000001, 0xf00001f0 },
@@ -85,35 +86,35 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b86, Value: 0x2bac) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b86, Value: 0x2bac) },
}, },
// STRB (imm12) // STRB (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf887, 0x67c2, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf887, 0x67c2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27c2, Value: 0x2700) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27c2, Value: 0x2700) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf883, 0x9fda, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf883, 0x9fda, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fda, Value: 0x2f00) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fda, Value: 0x2f00) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf889, 0xd200, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf889, 0xd200, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf88c, 0x1c5b, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf88c, 0x1c5b, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c5a, Value: 0x005a) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c5a, Value: 0x005a) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf887, 0x9fe2, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf887, 0x9fe2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
@@ -121,70 +122,70 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fe2, Value: 0x2f00) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fe2, Value: 0x2f00) },
}, },
// STRH (imm8) // STRH (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf826, 0x0b0a, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf826, 0x0b0a, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x00002620, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x00002620, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x0000262a, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x0000262a, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2620, Value: 0x25a2) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2620, Value: 0x25a2) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf827, 0xcf61, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf827, 0xcf61, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x000029eb, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x000029eb, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x00002a4c, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x00002a4c, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a4c, Value: 0x2e29) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a4c, Value: 0x2e29) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf821, 0x9b00, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf821, 0x9b00, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2514, Value: 0x2398) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2514, Value: 0x2398) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf82c, 0xa927, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf82c, 0xa927, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x000029a1, 0x00002976, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x000029a1, 0x00002976, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x0000297a, 0x00002976, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x0000297a, 0x00002976, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29a0, Value: 0x4aa0), (Address: 0x29a2, Value: 0x2927) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29a0, Value: 0x4aa0), (Address: 0x29a2, Value: 0x2927) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf824, 0xcfe4, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf824, 0xcfe4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002442, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002442, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002526, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002526, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2526, Value: 0x2d1c) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2526, Value: 0x2d1c) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf820, 0x1c3d, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf820, 0x1c3d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21ea, Value: 0x2b29) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21ea, Value: 0x2b29) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf826, 0x1cdf, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf826, 0x1cdf, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x265a, Value: 0xa15a), (Address: 0x265c, Value: 0x2629) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x265a, Value: 0xa15a), (Address: 0x265c, Value: 0x2629) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf82b, 0x3c66, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf82b, 0x3c66, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 }, StartRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 }, FinalRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2798, Value: 0xdf98), (Address: 0x279a, Value: 0x2721) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2798, Value: 0xdf98), (Address: 0x279a, Value: 0x2721) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf822, 0x3c06, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf822, 0x3c06, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 }, StartRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 }, FinalRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2afa, Value: 0x2207) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2afa, Value: 0x2207) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf824, 0xac84, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf824, 0xac84, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002796, 0x000027c8, 0x0000241b, 0x0000214d, 0x0000220b, 0x00002587, 0x00002130, 0x00002910, 0x00002ac2, 0x00002e74, 0x000028f8, 0x000024bf, 0x0000263a, 0x00002625, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002796, 0x000027c8, 0x0000241b, 0x0000214d, 0x0000220b, 0x00002587, 0x00002130, 0x00002910, 0x00002ac2, 0x00002e74, 0x000028f8, 0x000024bf, 0x0000263a, 0x00002625, 0x00000001, 0x600001f0 },
@@ -192,35 +193,35 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2186, Value: 0xf886), (Address: 0x2188, Value: 0x2128) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2186, Value: 0xf886), (Address: 0x2188, Value: 0x2128) },
}, },
// STRH (imm12) // STRH (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8a5, 0x59d4, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8a5, 0x59d4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29d4, Value: 0x2000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29d4, Value: 0x2000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8ac, 0xc533, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8ac, 0xc533, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2532, Value: 0x0032), (Address: 0x2534, Value: 0x2520) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2532, Value: 0x0032), (Address: 0x2534, Value: 0x2520) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8a3, 0xb559, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8a3, 0xb559, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2558, Value: 0x0058), (Address: 0x255a, Value: 0x2520) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2558, Value: 0x0058), (Address: 0x255a, Value: 0x2520) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8a5, 0xdb3a, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8a5, 0xdb3a, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b3a, Value: 0x2000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b3a, Value: 0x2000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8a9, 0x02cc, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8a9, 0x02cc, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
@@ -228,70 +229,70 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22cc, Value: 0x2000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22cc, Value: 0x2000) },
}, },
// STR (imm8) // STR (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf846, 0x1fb4, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf846, 0x1fb4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x0000222d, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 }, StartRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x0000222d, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x000022e1, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 }, FinalRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x000022e1, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22e0, Value: 0x2fe0), (Address: 0x22e2, Value: 0x0027), (Address: 0x22e4, Value: 0x2200) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22e0, Value: 0x2fe0), (Address: 0x22e2, Value: 0x0027), (Address: 0x22e4, Value: 0x2200) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf844, 0x3f11, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf844, 0x3f11, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027bb, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 }, StartRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027bb, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027cc, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 }, FinalRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027cc, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27cc, Value: 0x23ac), (Address: 0x27ce, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27cc, Value: 0x23ac), (Address: 0x27ce, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf847, 0x09c2, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf847, 0x09c2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000211c, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000211c, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000205a, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000205a, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x211c, Value: 0x248b), (Address: 0x211e, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x211c, Value: 0x248b), (Address: 0x211e, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf84d, 0x7f23, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf84d, 0x7f23, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c33, 0x00000001, 0x200001f0 }, StartRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c33, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c56, 0x00000001, 0x200001f0 }, FinalRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c56, 0x00000001, 0x200001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c56, Value: 0x2b63), (Address: 0x2c58, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c56, Value: 0x2b63), (Address: 0x2c58, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf843, 0x9d24, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf843, 0x9d24, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025fb, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025fb, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025d7, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025d7, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25d6, Value: 0xdcd6), (Address: 0x25d8, Value: 0x0027), (Address: 0x25da, Value: 0x2500) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25d6, Value: 0xdcd6), (Address: 0x25d8, Value: 0x0027), (Address: 0x25da, Value: 0x2500) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf849, 0xdc1a, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf849, 0xdc1a, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 }, StartRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 }, FinalRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2666, Value: 0x2d81), (Address: 0x2668, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2666, Value: 0x2d81), (Address: 0x2668, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf849, 0x0cd1, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf849, 0x0cd1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 }, StartRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 }, FinalRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2cec, Value: 0x255a), (Address: 0x2cee, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2cec, Value: 0x255a), (Address: 0x2cee, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf847, 0x7c96, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf847, 0x7c96, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 }, StartRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 }, FinalRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29bc, Value: 0x53bc), (Address: 0x29be, Value: 0x002a), (Address: 0x29c0, Value: 0x2900) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29bc, Value: 0x53bc), (Address: 0x29be, Value: 0x002a), (Address: 0x29c0, Value: 0x2900) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf84d, 0x8cbd, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf84d, 0x8cbd, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x229a, Value: 0x23d7), (Address: 0x229c, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x229a, Value: 0x23d7), (Address: 0x229c, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf846, 0xacaf, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf846, 0xacaf, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000284f, 0x00002def, 0x0000292f, 0x000021e8, 0x0000274e, 0x00002518, 0x00002538, 0x00002375, 0x00002d28, 0x0000229a, 0x0000255f, 0x00002eca, 0x00002e15, 0x000021aa, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x0000284f, 0x00002def, 0x0000292f, 0x000021e8, 0x0000274e, 0x00002518, 0x00002538, 0x00002375, 0x00002d28, 0x0000229a, 0x0000255f, 0x00002eca, 0x00002e15, 0x000021aa, 0x00000001, 0x100001f0 },
@@ -299,35 +300,35 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2488, Value: 0x5f88), (Address: 0x248a, Value: 0x0025), (Address: 0x248c, Value: 0x2400) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2488, Value: 0x5f88), (Address: 0x248a, Value: 0x0025), (Address: 0x248c, Value: 0x2400) },
}, },
// STR (imm12) // STR (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8cc, 0x1a6e, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8cc, 0x1a6e, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a6e, Value: 0x2000), (Address: 0x2a70, Value: 0x0000) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a6e, Value: 0x2000), (Address: 0x2a70, Value: 0x0000) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8c9, 0xcfc1, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8c9, 0xcfc1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fc0, Value: 0x00c0), (Address: 0x2fc2, Value: 0x0020), (Address: 0x2fc4, Value: 0x2f00) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fc0, Value: 0x00c0), (Address: 0x2fc2, Value: 0x0020), (Address: 0x2fc4, Value: 0x2f00) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8c3, 0xb5dd, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8c3, 0xb5dd, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25dc, Value: 0x00dc), (Address: 0x25de, Value: 0x0020), (Address: 0x25e0, Value: 0x2500) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25dc, Value: 0x00dc), (Address: 0x25de, Value: 0x0020), (Address: 0x25e0, Value: 0x2500) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8c0, 0x69e9, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8c0, 0x69e9, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29e8, Value: 0x00e8), (Address: 0x29ea, Value: 0x0020), (Address: 0x29ec, Value: 0x2900) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29e8, Value: 0x00e8), (Address: 0x29ea, Value: 0x0020), (Address: 0x29ec, Value: 0x2900) },
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8cd, 0x028f, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8cd, 0x028f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
@@ -335,186 +336,186 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x228e, Value: 0x008e), (Address: 0x2290, Value: 0x0020), (Address: 0x2292, Value: 0x2200) }, MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x228e, Value: 0x008e), (Address: 0x2290, Value: 0x0020), (Address: 0x2292, Value: 0x2200) },
}, },
// LDRB (imm8) // LDRB (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf816, 0x1c48, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf816, 0x1c48, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002cb8, 0x00002345, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002cb8, 0x00002345, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x00002cb8, 0x00000010, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x00002cb8, 0x00000010, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf815, 0x2d6e, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf815, 0x2d6e, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000021e4, 0x00002425, 0x00002e42, 0x00002a58, 0x00002708, 0x00002965, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x000021e4, 0x00002425, 0x00002e42, 0x00002a58, 0x00002708, 0x00002965, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x000021e4, 0x00002425, 0x00000028, 0x00002a58, 0x00002708, 0x000028f7, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x000021e4, 0x00002425, 0x00000028, 0x00002a58, 0x00002708, 0x000028f7, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf818, 0x0d33, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf818, 0x0d33, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002492, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x0000297b, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x00002492, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x0000297b, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x00000048, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x00002948, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x00000048, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x00002948, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf810, 0xbff3, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf810, 0xbff3, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002ea6, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x000022e7, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002ea6, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x000022e7, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x00002f99, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x0000002f, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x00002f99, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x0000002f, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
// LDRB (imm12) // LDRB (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf892, 0xcc8f, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf892, 0xcc8f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002c, 0x00002000, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002c, 0x00002000, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf89a, 0x7fdc, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf89a, 0x7fdc, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000000dc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000000dc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf890, 0x5f9f, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf890, 0x5f9f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002f, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002f, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf894, 0xdda1, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf894, 0xdda1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002d, 0x00000001, 0x900001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002d, 0x00000001, 0x900001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf890, 0xc281, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf890, 0xc281, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000022, 0x00002000, 0x00000001, 0x100001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000022, 0x00002000, 0x00000001, 0x100001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
// LDRH (imm8) // LDRH (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf834, 0x89d8, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf834, 0x89d8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000024a2, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x00002dff, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000024a2, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x00002dff, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000023ca, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x000024a2, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000023ca, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x000024a2, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf833, 0x6be4, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf833, 0x6be4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002a83, 0x00002293, 0x00002c7c, 0x00002bfe, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002a83, 0x00002293, 0x00002c7c, 0x00002bfe, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002b67, 0x00002293, 0x00002c7c, 0x0000842a, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002b67, 0x00002293, 0x00002c7c, 0x0000842a, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf83d, 0x1bca, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf83d, 0x1bca, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000250e, 0x00002776, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002e97, 0x00000001, 0x200001f0 }, StartRegs = new uint[] { 0x0000250e, 0x00002776, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002e97, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x0000250e, 0x0000982e, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002f61, 0x00000001, 0x200001f0 }, FinalRegs = new uint[] { 0x0000250e, 0x0000982e, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002f61, 0x00000001, 0x200001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
// LDRH (imm12) // LDRH (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8b7, 0x92fc, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8b7, 0x92fc, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000022fc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000022fc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8ba, 0xadd9, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8ba, 0xadd9, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000da2d, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000da2d, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8bb, 0x0bb0, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8bb, 0x0bb0, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x00002bb0, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x00002bb0, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8b8, 0xc3f8, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8b8, 0xc3f8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000023f8, 0x00002000, 0x00000001, 0x600001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000023f8, 0x00002000, 0x00000001, 0x600001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
// LDR (imm8) // LDR (imm8)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf85b, 0x3fd1, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf85b, 0x3fd1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x000021fa, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002735, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 }, StartRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x000021fa, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002735, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x28082806, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002806, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 }, FinalRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x28082806, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002806, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf854, 0xab9e, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf854, 0xab9e, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002ebb, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0x00002373, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 }, StartRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002ebb, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0x00002373, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002f59, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0xbe2ebc2e, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 }, FinalRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002f59, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0xbe2ebc2e, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf852, 0x6d2d, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf852, 0x6d2d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bde, 0x000022d9, 0x00002362, 0x00002d4b, 0x00002dab, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 }, StartRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bde, 0x000022d9, 0x00002362, 0x00002d4b, 0x00002dab, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bb1, 0x000022d9, 0x00002362, 0x00002d4b, 0xb42bb22b, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 }, FinalRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bb1, 0x000022d9, 0x00002362, 0x00002d4b, 0xb42bb22b, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf850, 0x8da5, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf850, 0x8da5, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002559, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x00002124, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 }, StartRegs = new uint[] { 0x00002559, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x00002124, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x000024b4, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x24b624b4, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 }, FinalRegs = new uint[] { 0x000024b4, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x24b624b4, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf857, 0x19f6, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf857, 0x19f6, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x000027f5, 0x0000285e, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000024cf, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 }, StartRegs = new uint[] { 0x000027f5, 0x0000285e, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000024cf, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x000027f5, 0xd224d024, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000023d9, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 }, FinalRegs = new uint[] { 0x000027f5, 0xd224d024, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000023d9, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
// LDR (imm12) // LDR (imm12)
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8d1, 0xc65e, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8d1, 0xc65e, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2660265e, 0x00002000, 0x00000001, 0x000001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2660265e, 0x00002000, 0x00000001, 0x000001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8db, 0xd09b, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8db, 0xd09b, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x9e209c20, 0x00000001, 0x800001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x9e209c20, 0x00000001, 0x800001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8d2, 0x6fde, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8d2, 0x6fde, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2fe02fde, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2fe02fde, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
new PrecomputedMemoryThumbTestCase() new()
{ {
Instructions = new ushort[] { 0xf8dc, 0x3de5, 0x4770, 0xe7fe }, Instructions = new ushort[] { 0xf8dc, 0x3de5, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0xe82de62d, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 }, FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0xe82de62d, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
MemoryDelta = new (ulong Address, ushort Value)[] {}, MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
}, },
}; };
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -10,22 +10,24 @@ namespace Ryujinx.Tests.Cpu
{ {
internal class EnvironmentTests internal class EnvironmentTests
{ {
#pragma warning disable IDE0052 // Remove unread private member
private static Translator _translator; private static Translator _translator;
#pragma warning restore IDE0052
private void EnsureTranslator() private static void EnsureTranslator()
{ {
// Create a translator, as one is needed to register the signal handler or emit methods. // Create a translator, as one is needed to register the signal handler or emit methods.
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true); _translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
} }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private float GetDenormal() private static float GetDenormal()
{ {
return BitConverter.Int32BitsToSingle(1); return BitConverter.Int32BitsToSingle(1);
} }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private float GetZero() private static float GetZero()
{ {
return BitConverter.Int32BitsToSingle(0); return BitConverter.Int32BitsToSingle(0);
} }
@@ -53,7 +55,7 @@ namespace Ryujinx.Tests.Cpu
if (test < 4f) if (test < 4f)
{ {
throw new System.Exception("Sanity check."); throw new Exception("Sanity check.");
} }
isFz = GetDenormal() + GetZero() == 0f; isFz = GetDenormal() + GetZero() == 0f;
@@ -62,7 +64,7 @@ namespace Ryujinx.Tests.Cpu
{ {
if (test >= 4f) if (test >= 4f)
{ {
throw new System.Exception("Always throws."); throw new Exception("Always throws.");
} }
} }
catch catch

View File

@@ -6,5 +6,5 @@ namespace Ryujinx.Tests.Cpu
public uint[] StartRegs; public uint[] StartRegs;
public uint[] FinalRegs; public uint[] FinalRegs;
public (ulong Address, ushort Value)[] MemoryDelta; public (ulong Address, ushort Value)[] MemoryDelta;
}; }
} }

View File

@@ -6,4 +6,4 @@
public uint[] StartRegs; public uint[] StartRegs;
public uint[] FinalRegs; public uint[] FinalRegs;
} }
} }

View File

@@ -21,8 +21,7 @@ namespace Ryujinx.Tests.HLE
[Test] [Test]
public void StripUnicodeControlCodes_Passthrough() public void StripUnicodeControlCodes_Passthrough()
{ {
string[] prompts = new string[] string[] prompts = {
{
"Please name him.", "Please name him.",
"Name her, too.", "Name her, too.",
"Name your friend.", "Name your friend.",

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Memory
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe; public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
#pragma warning disable CS0067 #pragma warning disable CS0067 // The event is never used
public event Action<ulong, ulong> UnmapEvent; public event Action<ulong, ulong> UnmapEvent;
#pragma warning restore CS0067 #pragma warning restore CS0067

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Memory
{ {
private static Translator _translator; private static Translator _translator;
private (MemoryBlock virt, MemoryBlock mirror, MemoryEhMeilleure exceptionHandler) GetVirtual(ulong asSize) private static (MemoryBlock virt, MemoryBlock mirror, MemoryEhMeilleure exceptionHandler) GetVirtual(ulong asSize)
{ {
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible; MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
@@ -33,7 +33,7 @@ namespace Ryujinx.Tests.Memory
return (addressSpace, addressSpaceMirror, exceptionHandler); return (addressSpace, addressSpaceMirror, exceptionHandler);
} }
private int CountThreads(ref PartialUnmapState state) private static int CountThreads(ref PartialUnmapState state)
{ {
int count = 0; int count = 0;
@@ -50,7 +50,7 @@ namespace Ryujinx.Tests.Memory
return count; return count;
} }
private void EnsureTranslator() private static void EnsureTranslator()
{ {
// Create a translator, as one is needed to register the signal handler or emit methods. // Create a translator, as one is needed to register the signal handler or emit methods.
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true); _translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
@@ -239,7 +239,7 @@ namespace Ryujinx.Tests.Memory
var writeFunc = TestMethods.GenerateDebugNativeWriteLoop(); var writeFunc = TestMethods.GenerateDebugNativeWriteLoop();
IntPtr writePtr = mainMemory.GetPointer(vaSize - 0x1000, 4); IntPtr writePtr = mainMemory.GetPointer(vaSize - 0x1000, 4);
Thread testThread = new Thread(() => Thread testThread = new(() =>
{ {
writeFunc(statePtr, writePtr); writeFunc(statePtr, writePtr);
}); });
@@ -283,7 +283,7 @@ namespace Ryujinx.Tests.Memory
[Test] [Test]
// Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming. // Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming.
[Platform("Win")] [Platform("Win")]
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")] [SuppressMessage("Interoperability", "CA1416: Validate platform compatibility")]
public void ThreadLocalMap() public void ThreadLocalMap()
{ {
PartialUnmapState.Reset(); PartialUnmapState.Reset();
@@ -465,4 +465,4 @@ namespace Ryujinx.Tests.Memory
Assert.False(error); Assert.False(error);
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Collections
[Test] [Test]
public void EnsureAddIntegrity() public void EnsureAddIntegrity()
{ {
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>(); TreeDictionary<int, int> dictionary = new();
Assert.AreEqual(dictionary.Count, 0); Assert.AreEqual(dictionary.Count, 0);
@@ -35,7 +35,7 @@ namespace Ryujinx.Tests.Collections
* 5 11 * 5 11
* *
*/ */
Assert.AreEqual(list.Count, dictionary.Count); Assert.AreEqual(list.Count, dictionary.Count);
Assert.AreEqual(list[0].Key, 2); Assert.AreEqual(list[0].Key, 2);
Assert.AreEqual(list[1].Key, 1); Assert.AreEqual(list[1].Key, 1);
@@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Collections
[Test] [Test]
public void EnsureRemoveIntegrity() public void EnsureRemoveIntegrity()
{ {
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>(); TreeDictionary<int, int> dictionary = new();
Assert.AreEqual(dictionary.Count, 0); Assert.AreEqual(dictionary.Count, 0);
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Collections
[Test] [Test]
public void EnsureOverwriteIntegrity() public void EnsureOverwriteIntegrity()
{ {
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>(); TreeDictionary<int, int> dictionary = new();
Assert.AreEqual(dictionary.Count, 0); Assert.AreEqual(dictionary.Count, 0);

View File

@@ -6,4 +6,4 @@ namespace Ryujinx.Ui.App.Common
{ {
public ApplicationData AppData { get; set; } public ApplicationData AppData { get; set; }
} }
} }

View File

@@ -4,7 +4,7 @@ namespace Ryujinx.Ui.App.Common
{ {
public class ApplicationCountUpdatedEventArgs : EventArgs public class ApplicationCountUpdatedEventArgs : EventArgs
{ {
public int NumAppsFound { get; set; } public int NumAppsFound { get; set; }
public int NumAppsLoaded { get; set; } public int NumAppsLoaded { get; set; }
} }
} }

View File

@@ -18,19 +18,19 @@ namespace Ryujinx.Ui.App.Common
{ {
public class ApplicationData public class ApplicationData
{ {
public bool Favorite { get; set; } public bool Favorite { get; set; }
public byte[] Icon { get; set; } public byte[] Icon { get; set; }
public string TitleName { get; set; } public string TitleName { get; set; }
public string TitleId { get; set; } public string TitleId { get; set; }
public string Developer { get; set; } public string Developer { get; set; }
public string Version { get; set; } public string Version { get; set; }
public string TimePlayed { get; set; } public string TimePlayed { get; set; }
public double TimePlayedNum { get; set; } public double TimePlayedNum { get; set; }
public DateTime? LastPlayed { get; set; } public DateTime? LastPlayed { get; set; }
public string FileExtension { get; set; } public string FileExtension { get; set; }
public string FileSize { get; set; } public string FileSize { get; set; }
public double FileSizeBytes { get; set; } public double FileSizeBytes { get; set; }
public string Path { get; set; } public string Path { get; set; }
public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; } public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
[JsonIgnore] [JsonIgnore]
@@ -159,7 +159,7 @@ namespace Ryujinx.Ui.App.Common
codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure(); codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
NsoReader reader = new NsoReader(); NsoReader reader = new();
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure(); reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16]; return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];

Some files were not shown because too many files have changed in this diff Show More