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,6 +489,8 @@ 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

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."),
}; };
} }

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();

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)
{ {

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;

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; }

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()

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);

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)

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;
} }

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();

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);

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,8 +41,8 @@ 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); byte value = memory.Read<byte>(position + (ulong)offs);
@@ -60,4 +59,3 @@ namespace Ryujinx.Cpu
} }
} }
} }
}

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; }

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

@@ -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);

View File

@@ -15,7 +15,7 @@ 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);
@@ -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,7 +45,7 @@ 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);
@@ -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

@@ -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;
@@ -208,12 +210,12 @@ namespace Ryujinx.Tests.Cpu
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
@@ -267,11 +269,12 @@ 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>
[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,7 +312,7 @@ namespace Ryujinx.Tests.Cpu
None, None,
UpToOneUlpsS, UpToOneUlpsS,
UpToOneUlpsD UpToOneUlpsD,
} }
protected void CompareAgainstUnicorn( protected void CompareAgainstUnicorn(
@@ -316,7 +320,7 @@ namespace Ryujinx.Tests.Cpu
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)
{ {
@@ -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,7 +537,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);
@@ -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,7 +560,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);
@@ -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,7 +583,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);
@@ -581,7 +595,8 @@ 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;
@@ -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,7 +635,8 @@ 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

@@ -33,8 +33,15 @@ 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;
}
if (cnt == 31)
{
return 1u;
}
uint rnd = TestContext.CurrentContext.Random.NextUInt(); uint rnd = TestContext.CurrentContext.Random.NextUInt();
int mask = int.MinValue; int mask = int.MinValue;
@@ -44,8 +51,15 @@ namespace Ryujinx.Tests.Cpu
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;
}
if (cnt == 63)
{
return 1ul;
}
ulong rnd = TestContext.CurrentContext.Random.NextULong(); ulong rnd = TestContext.CurrentContext.Random.NextULong();
long mask = long.MinValue; long mask = long.MinValue;
@@ -55,7 +69,7 @@ namespace Ryujinx.Tests.Cpu
#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,7 +95,7 @@ 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++)
{ {
@@ -93,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
[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);

View File

@@ -10,7 +10,7 @@ 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,14 +45,14 @@ 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
@@ -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,

View File

@@ -48,7 +48,7 @@ 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

View File

@@ -60,7 +60,7 @@ 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

View File

@@ -10,7 +10,7 @@ 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[]
{ {
@@ -35,7 +35,7 @@ namespace Ryujinx.Tests.Cpu
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,

View File

@@ -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,

View File

@@ -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)
@@ -58,9 +58,9 @@ namespace Ryujinx.Tests.Cpu
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]
@@ -164,8 +164,9 @@ namespace Ryujinx.Tests.Cpu
} }
#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,8 +197,9 @@ 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)]
@@ -242,8 +244,9 @@ 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)]
@@ -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;

View File

@@ -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)
@@ -57,9 +57,9 @@ namespace Ryujinx.Tests.Cpu
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

@@ -52,7 +52,7 @@ namespace Ryujinx.Tests.Cpu
#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,

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ namespace Ryujinx.Tests.Cpu
{ {
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,7 +27,7 @@ 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
@@ -35,10 +35,12 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 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)
@@ -177,9 +179,9 @@ namespace Ryujinx.Tests.Cpu
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,
@@ -223,8 +225,10 @@ 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);
@@ -252,8 +256,10 @@ 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);
@@ -303,7 +309,8 @@ 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

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
@@ -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(() =>
{ {
@@ -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
@@ -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(() =>
@@ -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

@@ -15,14 +15,18 @@ namespace Ryujinx.Tests.Cpu
#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)
@@ -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,18 +363,19 @@ 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,
@@ -387,7 +392,8 @@ 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,
@@ -403,7 +409,8 @@ 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,
@@ -420,7 +427,8 @@ 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,
@@ -436,7 +444,8 @@ 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,
@@ -457,7 +466,8 @@ 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,
@@ -477,7 +487,8 @@ 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,
@@ -498,7 +509,8 @@ 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,
@@ -518,7 +530,8 @@ 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,
@@ -535,7 +548,8 @@ 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,
@@ -552,7 +566,8 @@ 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,
@@ -569,7 +584,8 @@ 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,
@@ -586,7 +602,8 @@ 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,
@@ -607,7 +624,8 @@ 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,
@@ -628,7 +646,8 @@ 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,
@@ -649,7 +668,8 @@ 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,

View File

@@ -20,7 +20,7 @@ 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
@@ -28,8 +28,10 @@ namespace Ryujinx.Tests.Cpu
#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)
@@ -159,9 +161,9 @@ namespace Ryujinx.Tests.Cpu
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,8 +292,10 @@ 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);

View File

@@ -13,8 +13,10 @@ namespace Ryujinx.Tests.Cpu
#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

View File

@@ -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)
@@ -102,7 +102,7 @@ namespace Ryujinx.Tests.Cpu
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,7 +127,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x1E620C20u // FCSEL D0, D1, D2, EQ 0x1E620C20u, // FCSEL D0, D1, D2, EQ
}; };
} }
#endregion #endregion
@@ -135,11 +135,12 @@ namespace Ryujinx.Tests.Cpu
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

@@ -15,7 +15,7 @@ namespace Ryujinx.Tests.Cpu
{ {
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

@@ -48,14 +48,18 @@ namespace Ryujinx.Tests.Cpu
#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_()
@@ -95,7 +99,7 @@ namespace Ryujinx.Tests.Cpu
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,7 +183,7 @@ namespace Ryujinx.Tests.Cpu
{ {
return new[] return new[]
{ {
0x6F00E400u // MOVI V0.2D, #0 0x6F00E400u, // MOVI V0.2D, #0
}; };
} }
#endregion #endregion
@@ -229,7 +233,8 @@ 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)
{ {
@@ -246,7 +251,8 @@ 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)
{ {
@@ -260,7 +266,8 @@ 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)
{ {

View File

@@ -13,56 +13,72 @@ namespace Ryujinx.Tests.Cpu
#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[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static uint[] _W_() private static uint[] _W_()
{ {
return new[] { 0x00000000u, 0x0000007Fu, return new[] {
0x00000000u, 0x0000007Fu,
0x00000080u, 0x000000FFu, 0x00000080u, 0x000000FFu,
0x00007FFFu, 0x00008000u, 0x00007FFFu, 0x00008000u,
0x0000FFFFu, 0x7FFFFFFFu, 0x0000FFFFu, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu }; 0x80000000u, 0xFFFFFFFFu,
};
} }
private static ulong[] _X_() private static ulong[] _X_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion

View File

@@ -13,10 +13,12 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
#endregion #endregion
@@ -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,7 +45,7 @@ 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
@@ -62,9 +64,12 @@ 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);
@@ -97,7 +102,8 @@ 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;
@@ -129,9 +135,12 @@ 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);

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];

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,10 +468,10 @@ 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];
@@ -473,8 +482,8 @@ namespace Ryujinx.Tests.Cpu
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);

View File

@@ -14,72 +14,90 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _1B1H1S1D_() private static ulong[] _1B1H1S1D_()
{ {
return new[] { 0x0000000000000000ul, 0x000000000000007Ful, return new[] {
0x0000000000000000ul, 0x000000000000007Ful,
0x0000000000000080ul, 0x00000000000000FFul, 0x0000000000000080ul, 0x00000000000000FFul,
0x0000000000007FFFul, 0x0000000000008000ul, 0x0000000000007FFFul, 0x0000000000008000ul,
0x000000000000FFFFul, 0x000000007FFFFFFFul, 0x000000000000FFFFul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul, 0x0000000080000000ul, 0x00000000FFFFFFFFul,
0x7FFFFFFFFFFFFFFFul, 0x8000000000000000ul, 0x7FFFFFFFFFFFFFFFul, 0x8000000000000000ul,
0xFFFFFFFFFFFFFFFFul }; 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _1D_() private static ulong[] _1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, return new[] {
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _1H1S_() private static ulong[] _1H1S_()
{ {
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul, return new[] {
0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul, 0x0000000000008000ul, 0x000000000000FFFFul,
0x000000007FFFFFFFul, 0x0000000080000000ul, 0x000000007FFFFFFFul, 0x0000000080000000ul,
0x00000000FFFFFFFFul }; 0x00000000FFFFFFFFul,
};
} }
private static ulong[] _4H2S_() private static ulong[] _4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _4H2S1D_() private static ulong[] _4H2S1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul, 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B_() private static ulong[] _8B_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul }; 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B1D_() private static ulong[] _8B1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul, 0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S_() private static ulong[] _8B4H2S_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S1D_() private static ulong[] _8B4H2S1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul, 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static IEnumerable<ulong> _1S_F_() private static IEnumerable<ulong> _1S_F_()
@@ -93,19 +111,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)
@@ -135,19 +153,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)
@@ -176,19 +194,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)
@@ -218,7 +236,7 @@ namespace Ryujinx.Tests.Cpu
0x1E220820u, // FMUL S0, S1, S2 0x1E220820u, // FMUL S0, S1, S2
0x5E22DC20u, // FMULX S0, S1, S2 0x5E22DC20u, // FMULX S0, S1, S2
0x1E228820u, // FNMUL S0, S1, S2 0x1E228820u, // FNMUL S0, S1, S2
0x1E223820u // FSUB S0, S1, S2 0x1E223820u, // FSUB S0, S1, S2
}; };
} }
@@ -232,7 +250,7 @@ namespace Ryujinx.Tests.Cpu
0x1E620820u, // FMUL D0, D1, D2 0x1E620820u, // FMUL D0, D1, D2
0x5E62DC20u, // FMULX D0, D1, D2 0x5E62DC20u, // FMULX D0, D1, D2
0x1E628820u, // FNMUL D0, D1, D2 0x1E628820u, // FNMUL D0, D1, D2
0x1E623820u // FSUB D0, D1, D2 0x1E623820u, // FSUB D0, D1, D2
}; };
} }
@@ -246,7 +264,7 @@ namespace Ryujinx.Tests.Cpu
0x2E20FC00u, // FDIV V0.2S, V0.2S, V0.2S 0x2E20FC00u, // FDIV V0.2S, V0.2S, V0.2S
0x2E20DC00u, // FMUL V0.2S, V0.2S, V0.2S 0x2E20DC00u, // FMUL V0.2S, V0.2S, V0.2S
0x0E20DC00u, // FMULX V0.2S, V0.2S, V0.2S 0x0E20DC00u, // FMULX V0.2S, V0.2S, V0.2S
0x0EA0D400u // FSUB V0.2S, V0.2S, V0.2S 0x0EA0D400u, // FSUB V0.2S, V0.2S, V0.2S
}; };
} }
@@ -260,7 +278,7 @@ namespace Ryujinx.Tests.Cpu
0x6E60FC00u, // FDIV V0.2D, V0.2D, V0.2D 0x6E60FC00u, // FDIV V0.2D, V0.2D, V0.2D
0x6E60DC00u, // FMUL V0.2D, V0.2D, V0.2D 0x6E60DC00u, // FMUL V0.2D, V0.2D, V0.2D
0x4E60DC00u, // FMULX V0.2D, V0.2D, V0.2D 0x4E60DC00u, // FMULX V0.2D, V0.2D, V0.2D
0x4EE0D400u // FSUB V0.2D, V0.2D, V0.2D 0x4EE0D400u, // FSUB V0.2D, V0.2D, V0.2D
}; };
} }
@@ -272,7 +290,7 @@ namespace Ryujinx.Tests.Cpu
0x7EA2EC20u, // FACGT S0, S1, S2 0x7EA2EC20u, // FACGT S0, S1, S2
0x5E22E420u, // FCMEQ S0, S1, S2 0x5E22E420u, // FCMEQ S0, S1, S2
0x7E22E420u, // FCMGE S0, S1, S2 0x7E22E420u, // FCMGE S0, S1, S2
0x7EA2E420u // FCMGT S0, S1, S2 0x7EA2E420u, // FCMGT S0, S1, S2
}; };
} }
@@ -284,7 +302,7 @@ namespace Ryujinx.Tests.Cpu
0x7EE2EC20u, // FACGT D0, D1, D2 0x7EE2EC20u, // FACGT D0, D1, D2
0x5E62E420u, // FCMEQ D0, D1, D2 0x5E62E420u, // FCMEQ D0, D1, D2
0x7E62E420u, // FCMGE D0, D1, D2 0x7E62E420u, // FCMGE D0, D1, D2
0x7EE2E420u // FCMGT D0, D1, D2 0x7EE2E420u, // FCMGT D0, D1, D2
}; };
} }
@@ -296,7 +314,7 @@ namespace Ryujinx.Tests.Cpu
0x2EA0EC00u, // FACGT V0.2S, V0.2S, V0.2S 0x2EA0EC00u, // FACGT V0.2S, V0.2S, V0.2S
0x0E20E400u, // FCMEQ V0.2S, V0.2S, V0.2S 0x0E20E400u, // FCMEQ V0.2S, V0.2S, V0.2S
0x2E20E400u, // FCMGE V0.2S, V0.2S, V0.2S 0x2E20E400u, // FCMGE V0.2S, V0.2S, V0.2S
0x2EA0E400u // FCMGT V0.2S, V0.2S, V0.2S 0x2EA0E400u, // FCMGT V0.2S, V0.2S, V0.2S
}; };
} }
@@ -308,7 +326,7 @@ namespace Ryujinx.Tests.Cpu
0x6EE0EC00u, // FACGT V0.2D, V0.2D, V0.2D 0x6EE0EC00u, // FACGT V0.2D, V0.2D, V0.2D
0x4E60E400u, // FCMEQ V0.2D, V0.2D, V0.2D 0x4E60E400u, // FCMEQ V0.2D, V0.2D, V0.2D
0x6E60E400u, // FCMGE V0.2D, V0.2D, V0.2D 0x6E60E400u, // FCMGE V0.2D, V0.2D, V0.2D
0x6EE0E400u // FCMGT V0.2D, V0.2D, V0.2D 0x6EE0E400u, // FCMGT V0.2D, V0.2D, V0.2D
}; };
} }
@@ -317,7 +335,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E222020u, // FCMP S1, S2 0x1E222020u, // FCMP S1, S2
0x1E222030u // FCMPE S1, S2 0x1E222030u, // FCMPE S1, S2
}; };
} }
@@ -326,7 +344,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x1E622020u, // FCMP D1, D2 0x1E622020u, // FCMP D1, D2
0x1E622030u // FCMPE D1, D2 0x1E622030u, // FCMPE D1, D2
}; };
} }
@@ -337,7 +355,7 @@ namespace Ryujinx.Tests.Cpu
0x1F020C20u, // FMADD S0, S1, S2, S3 0x1F020C20u, // FMADD S0, S1, S2, S3
0x1F028C20u, // FMSUB S0, S1, S2, S3 0x1F028C20u, // FMSUB S0, S1, S2, S3
0x1F220C20u, // FNMADD S0, S1, S2, S3 0x1F220C20u, // FNMADD S0, S1, S2, S3
0x1F228C20u // FNMSUB S0, S1, S2, S3 0x1F228C20u, // FNMSUB S0, S1, S2, S3
}; };
} }
@@ -348,7 +366,7 @@ namespace Ryujinx.Tests.Cpu
0x1F420C20u, // FMADD D0, D1, D2, D3 0x1F420C20u, // FMADD D0, D1, D2, D3
0x1F428C20u, // FMSUB D0, D1, D2, D3 0x1F428C20u, // FMSUB D0, D1, D2, D3
0x1F620C20u, // FNMADD D0, D1, D2, D3 0x1F620C20u, // FNMADD D0, D1, D2, D3
0x1F628C20u // FNMSUB D0, D1, D2, D3 0x1F628C20u, // FNMSUB D0, D1, D2, D3
}; };
} }
@@ -359,7 +377,7 @@ namespace Ryujinx.Tests.Cpu
0x1E224820u, // FMAX S0, S1, S2 0x1E224820u, // FMAX S0, S1, S2
0x1E226820u, // FMAXNM S0, S1, S2 0x1E226820u, // FMAXNM S0, S1, S2
0x1E225820u, // FMIN S0, S1, S2 0x1E225820u, // FMIN S0, S1, S2
0x1E227820u // FMINNM S0, S1, S2 0x1E227820u, // FMINNM S0, S1, S2
}; };
} }
@@ -370,7 +388,7 @@ namespace Ryujinx.Tests.Cpu
0x1E624820u, // FMAX D0, D1, D2 0x1E624820u, // FMAX D0, D1, D2
0x1E626820u, // FMAXNM D0, D1, D2 0x1E626820u, // FMAXNM D0, D1, D2
0x1E625820u, // FMIN D0, D1, D2 0x1E625820u, // FMIN D0, D1, D2
0x1E627820u // FMINNM D0, D1, D2 0x1E627820u, // FMINNM D0, D1, D2
}; };
} }
@@ -385,7 +403,7 @@ namespace Ryujinx.Tests.Cpu
0x0EA0F400u, // FMIN V0.2S, V0.2S, V0.2S 0x0EA0F400u, // FMIN V0.2S, V0.2S, V0.2S
0x0EA0C400u, // FMINNM V0.2S, V0.2S, V0.2S 0x0EA0C400u, // FMINNM V0.2S, V0.2S, V0.2S
0x2EA0C400u, // FMINNMP V0.2S, V0.2S, V0.2S 0x2EA0C400u, // FMINNMP V0.2S, V0.2S, V0.2S
0x2EA0F400u // FMINP V0.2S, V0.2S, V0.2S 0x2EA0F400u, // FMINP V0.2S, V0.2S, V0.2S
}; };
} }
@@ -400,7 +418,7 @@ namespace Ryujinx.Tests.Cpu
0x4EE0F400u, // FMIN V0.2D, V0.2D, V0.2D 0x4EE0F400u, // FMIN V0.2D, V0.2D, V0.2D
0x4EE0C400u, // FMINNM V0.2D, V0.2D, V0.2D 0x4EE0C400u, // FMINNM V0.2D, V0.2D, V0.2D
0x6EE0C400u, // FMINNMP V0.2D, V0.2D, V0.2D 0x6EE0C400u, // FMINNMP V0.2D, V0.2D, V0.2D
0x6EE0F400u // FMINP V0.2D, V0.2D, V0.2D 0x6EE0F400u, // FMINP V0.2D, V0.2D, V0.2D
}; };
} }
@@ -409,7 +427,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0E20CC00u, // FMLA V0.2S, V0.2S, V0.2S 0x0E20CC00u, // FMLA V0.2S, V0.2S, V0.2S
0x0EA0CC00u // FMLS V0.2S, V0.2S, V0.2S 0x0EA0CC00u, // FMLS V0.2S, V0.2S, V0.2S
}; };
} }
@@ -418,7 +436,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4E60CC00u, // FMLA V0.2D, V0.2D, V0.2D 0x4E60CC00u, // FMLA V0.2D, V0.2D, V0.2D
0x4EE0CC00u // FMLS V0.2D, V0.2D, V0.2D 0x4EE0CC00u, // FMLS V0.2D, V0.2D, V0.2D
}; };
} }
@@ -427,7 +445,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5E22FC20u, // FRECPS S0, S1, S2 0x5E22FC20u, // FRECPS S0, S1, S2
0x5EA2FC20u // FRSQRTS S0, S1, S2 0x5EA2FC20u, // FRSQRTS S0, S1, S2
}; };
} }
@@ -436,7 +454,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5E62FC20u, // FRECPS D0, D1, D2 0x5E62FC20u, // FRECPS D0, D1, D2
0x5EE2FC20u // FRSQRTS D0, D1, D2 0x5EE2FC20u, // FRSQRTS D0, D1, D2
}; };
} }
@@ -445,7 +463,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x0E20FC00u, // FRECPS V0.2S, V0.2S, V0.2S 0x0E20FC00u, // FRECPS V0.2S, V0.2S, V0.2S
0x0EA0FC00u // FRSQRTS V0.2S, V0.2S, V0.2S 0x0EA0FC00u, // FRSQRTS V0.2S, V0.2S, V0.2S
}; };
} }
@@ -454,7 +472,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x4E60FC00u, // FRECPS V0.2D, V0.2D, V0.2D 0x4E60FC00u, // FRECPS V0.2D, V0.2D, V0.2D
0x4EE0FC00u // FRSQRTS V0.2D, V0.2D, V0.2D 0x4EE0FC00u, // FRSQRTS V0.2D, V0.2D, V0.2D
}; };
} }
@@ -464,7 +482,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0x0E209400u, // MLA V0.8B, V0.8B, V0.8B 0x0E209400u, // MLA V0.8B, V0.8B, V0.8B
0x2E209400u, // MLS V0.8B, V0.8B, V0.8B 0x2E209400u, // MLS V0.8B, V0.8B, V0.8B
0x0E209C00u // MUL V0.8B, V0.8B, V0.8B 0x0E209C00u, // MUL V0.8B, V0.8B, V0.8B
}; };
} }
@@ -474,7 +492,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0x4E209400u, // MLA V0.16B, V0.16B, V0.16B 0x4E209400u, // MLA V0.16B, V0.16B, V0.16B
0x6E209400u, // MLS V0.16B, V0.16B, V0.16B 0x6E209400u, // MLS V0.16B, V0.16B, V0.16B
0x4E209C00u // MUL V0.16B, V0.16B, V0.16B 0x4E209C00u, // MUL V0.16B, V0.16B, V0.16B
}; };
} }
@@ -485,7 +503,7 @@ namespace Ryujinx.Tests.Cpu
0x5E000000u, // SHA1C Q0, S0, V0.4S 0x5E000000u, // SHA1C Q0, S0, V0.4S
0x5E002000u, // SHA1M Q0, S0, V0.4S 0x5E002000u, // SHA1M Q0, S0, V0.4S
0x5E001000u, // SHA1P Q0, S0, V0.4S 0x5E001000u, // SHA1P Q0, S0, V0.4S
0x5E003000u // SHA1SU0 V0.4S, V0.4S, V0.4S 0x5E003000u, // SHA1SU0 V0.4S, V0.4S, V0.4S
}; };
} }
@@ -495,7 +513,7 @@ namespace Ryujinx.Tests.Cpu
{ {
0x5E004000u, // SHA256H Q0, Q0, V0.4S 0x5E004000u, // SHA256H Q0, Q0, V0.4S
0x5E005000u, // SHA256H2 Q0, Q0, V0.4S 0x5E005000u, // SHA256H2 Q0, Q0, V0.4S
0x5E006000u // SHA256SU1 V0.4S, V0.4S, V0.4S 0x5E006000u, // SHA256SU1 V0.4S, V0.4S, V0.4S
}; };
} }
@@ -510,7 +528,7 @@ namespace Ryujinx.Tests.Cpu
0x2E206400u, // UMAX V0.8B, V0.8B, V0.8B 0x2E206400u, // UMAX V0.8B, V0.8B, V0.8B
0x2E20A400u, // UMAXP V0.8B, V0.8B, V0.8B 0x2E20A400u, // UMAXP V0.8B, V0.8B, V0.8B
0x2E206C00u, // UMIN V0.8B, V0.8B, V0.8B 0x2E206C00u, // UMIN V0.8B, V0.8B, V0.8B
0x2E20AC00u // UMINP V0.8B, V0.8B, V0.8B 0x2E20AC00u, // UMINP V0.8B, V0.8B, V0.8B
}; };
} }
@@ -523,7 +541,7 @@ namespace Ryujinx.Tests.Cpu
0x0E20C000u, // SMULL V0.8H, V0.8B, V0.8B 0x0E20C000u, // SMULL V0.8H, V0.8B, V0.8B
0x2E208000u, // UMLAL V0.8H, V0.8B, V0.8B 0x2E208000u, // UMLAL V0.8H, V0.8B, V0.8B
0x2E20A000u, // UMLSL V0.8H, V0.8B, V0.8B 0x2E20A000u, // UMLSL V0.8H, V0.8B, V0.8B
0x2E20C000u // UMULL V0.8H, V0.8B, V0.8B 0x2E20C000u, // UMULL V0.8H, V0.8B, V0.8B
}; };
} }
@@ -536,7 +554,7 @@ namespace Ryujinx.Tests.Cpu
0x4E20C000u, // SMULL2 V0.8H, V0.16B, V0.16B 0x4E20C000u, // SMULL2 V0.8H, V0.16B, V0.16B
0x6E208000u, // UMLAL2 V0.8H, V0.16B, V0.16B 0x6E208000u, // UMLAL2 V0.8H, V0.16B, V0.16B
0x6E20A000u, // UMLSL2 V0.8H, V0.16B, V0.16B 0x6E20A000u, // UMLSL2 V0.8H, V0.16B, V0.16B
0x6E20C000u // UMULL2 V0.8H, V0.16B, V0.16B 0x6E20C000u, // UMULL2 V0.8H, V0.16B, V0.16B
}; };
} }
@@ -545,7 +563,7 @@ namespace Ryujinx.Tests.Cpu
return new[] return new[]
{ {
0x5EE04400u, // SSHL D0, D0, D0 0x5EE04400u, // SSHL D0, D0, D0
0x7EE04400u // USHL D0, D0, D0 0x7EE04400u, // USHL D0, D0, D0
}; };
} }
@@ -560,7 +578,7 @@ namespace Ryujinx.Tests.Cpu
0x2E205C00u, // UQRSHL V0.8B, V0.8B, V0.8B 0x2E205C00u, // UQRSHL V0.8B, V0.8B, V0.8B
0x2E204C00u, // UQSHL V0.8B, V0.8B, V0.8B 0x2E204C00u, // UQSHL V0.8B, V0.8B, V0.8B
0x2E205400u, // URSHL V0.8B, V0.8B, V0.8B 0x2E205400u, // URSHL V0.8B, V0.8B, V0.8B
0x2E204400u // USHL V0.8B, V0.8B, V0.8B 0x2E204400u, // USHL V0.8B, V0.8B, V0.8B
}; };
} }
@@ -575,16 +593,16 @@ namespace Ryujinx.Tests.Cpu
0x6E205C00u, // UQRSHL V0.16B, V0.16B, V0.16B 0x6E205C00u, // UQRSHL V0.16B, V0.16B, V0.16B
0x6E204C00u, // UQSHL V0.16B, V0.16B, V0.16B 0x6E204C00u, // UQSHL V0.16B, V0.16B, V0.16B
0x6E205400u, // URSHL V0.16B, V0.16B, V0.16B 0x6E205400u, // URSHL V0.16B, V0.16B, V0.16B
0x6E204400u // USHL V0.16B, V0.16B, V0.16B 0x6E204400u, // USHL V0.16B, V0.16B, V0.16B
}; };
} }
#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("ADD <V><d>, <V><n>, <V><m>")] [Test, Pairwise, Description("ADD <V><d>, <V><n>, <V><m>")]
public void Add_S_D([Values(0u)] uint rd, public void Add_S_D([Values(0u)] uint rd,
@@ -1362,7 +1380,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S_))] uint opcodes, public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_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)
@@ -1382,7 +1401,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D_))] uint opcodes, public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_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)
@@ -1402,7 +1422,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S_))] uint opcodes, public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1429,7 +1450,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D_))] uint opcodes, public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1454,7 +1476,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_AcCm_EqGeGt_S_S([ValueSource(nameof(_F_AcCm_EqGeGt_S_S_))] uint opcodes, public void F_AcCm_EqGeGt_S_S([ValueSource(nameof(_F_AcCm_EqGeGt_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)
@@ -1473,7 +1496,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_AcCm_EqGeGt_S_D([ValueSource(nameof(_F_AcCm_EqGeGt_S_D_))] uint opcodes, public void F_AcCm_EqGeGt_S_D([ValueSource(nameof(_F_AcCm_EqGeGt_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)
@@ -1492,7 +1516,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_AcCm_EqGeGt_V_2S_4S([ValueSource(nameof(_F_AcCm_EqGeGt_V_2S_4S_))] uint opcodes, public void F_AcCm_EqGeGt_V_2S_4S([ValueSource(nameof(_F_AcCm_EqGeGt_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1518,7 +1543,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_AcCm_EqGeGt_V_2D([ValueSource(nameof(_F_AcCm_EqGeGt_V_2D_))] uint opcodes, public void F_AcCm_EqGeGt_V_2D([ValueSource(nameof(_F_AcCm_EqGeGt_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1542,7 +1568,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_Cmp_Cmpe_S_S([ValueSource(nameof(_F_Cmp_Cmpe_S_S_))] uint opcodes, public void F_Cmp_Cmpe_S_S([ValueSource(nameof(_F_Cmp_Cmpe_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)
@@ -1560,7 +1587,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
} }
[Test, Pairwise] [Explicit] [Test, Pairwise]
[Explicit]
public void F_Cmp_Cmpe_S_D([ValueSource(nameof(_F_Cmp_Cmpe_S_D_))] uint opcodes, public void F_Cmp_Cmpe_S_D([ValueSource(nameof(_F_Cmp_Cmpe_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)
@@ -1578,7 +1606,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Madd_Msub_Nmadd_Nmsub_S_S([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_S_))] uint opcodes, public void F_Madd_Msub_Nmadd_Nmsub_S_S([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_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,
@@ -1600,7 +1630,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_Madd_Msub_Nmadd_Nmsub_S_D([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_D_))] uint opcodes, public void F_Madd_Msub_Nmadd_Nmsub_S_D([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_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,
@@ -1622,7 +1654,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_Max_Min_Nm_S_S([ValueSource(nameof(_F_Max_Min_Nm_S_S_))] uint opcodes, public void F_Max_Min_Nm_S_S([ValueSource(nameof(_F_Max_Min_Nm_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)
@@ -1642,7 +1675,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_Max_Min_Nm_S_D([ValueSource(nameof(_F_Max_Min_Nm_S_D_))] uint opcodes, public void F_Max_Min_Nm_S_D([ValueSource(nameof(_F_Max_Min_Nm_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)
@@ -1662,7 +1696,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_Max_Min_Nm_P_V_2S_4S([ValueSource(nameof(_F_Max_Min_Nm_P_V_2S_4S_))] uint opcodes, public void F_Max_Min_Nm_P_V_2S_4S([ValueSource(nameof(_F_Max_Min_Nm_P_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1689,7 +1724,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_Max_Min_Nm_P_V_2D([ValueSource(nameof(_F_Max_Min_Nm_P_V_2D_))] uint opcodes, public void F_Max_Min_Nm_P_V_2D([ValueSource(nameof(_F_Max_Min_Nm_P_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1714,7 +1750,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc); CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
} }
[Test, Pairwise] [Explicit] // Fused. // Fused.
[Test, Pairwise]
[Explicit]
public void F_Mla_Mls_V_2S_4S([ValueSource(nameof(_F_Mla_Mls_V_2S_4S_))] uint opcodes, public void F_Mla_Mls_V_2S_4S([ValueSource(nameof(_F_Mla_Mls_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1741,7 +1779,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_V_2D([ValueSource(nameof(_F_Mla_Mls_V_2D_))] uint opcodes, public void F_Mla_Mls_V_2D([ValueSource(nameof(_F_Mla_Mls_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1766,7 +1806,9 @@ 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_Recps_Rsqrts_S_S([ValueSource(nameof(_F_Recps_Rsqrts_S_S_))] uint opcodes, public void F_Recps_Rsqrts_S_S([ValueSource(nameof(_F_Recps_Rsqrts_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)
@@ -1786,7 +1828,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_Recps_Rsqrts_S_D([ValueSource(nameof(_F_Recps_Rsqrts_S_D_))] uint opcodes, public void F_Recps_Rsqrts_S_D([ValueSource(nameof(_F_Recps_Rsqrts_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)
@@ -1806,7 +1850,9 @@ 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_Recps_Rsqrts_V_2S_4S([ValueSource(nameof(_F_Recps_Rsqrts_V_2S_4S_))] uint opcodes, public void F_Recps_Rsqrts_V_2S_4S([ValueSource(nameof(_F_Recps_Rsqrts_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,
@@ -1833,7 +1879,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_Recps_Rsqrts_V_2D([ValueSource(nameof(_F_Recps_Rsqrts_V_2D_))] uint opcodes, public void F_Recps_Rsqrts_V_2D([ValueSource(nameof(_F_Recps_Rsqrts_V_2D_))] uint opcodes,
[Values(0u)] uint rd, [Values(0u)] uint rd,
[Values(1u, 0u)] uint rn, [Values(1u, 0u)] uint rn,

View File

@@ -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,7 +119,7 @@ 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
@@ -127,18 +127,22 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)" #region "ValueSource (Types)"
private static ulong[] _8B1D_() private static ulong[] _8B1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul, 0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
} }
private static ulong[] _8B4H2S1D_() private static ulong[] _8B4H2S1D_()
{ {
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul, 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul, 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul }; 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)
@@ -268,9 +272,9 @@ namespace Ryujinx.Tests.Cpu
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,
@@ -425,8 +429,10 @@ 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);
@@ -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,
@@ -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,
@@ -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,9 +547,12 @@ 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);
@@ -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,
@@ -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,
@@ -678,7 +695,8 @@ 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);
@@ -836,9 +854,12 @@ 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);
@@ -864,9 +885,12 @@ 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

View File

@@ -13,14 +13,18 @@ namespace Ryujinx.Tests.Cpu
#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
@@ -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,7 +75,7 @@ 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

View File

@@ -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)
@@ -143,7 +143,7 @@ namespace Ryujinx.Tests.Cpu
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,7 +272,9 @@ 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,
@@ -300,7 +306,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_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,
@@ -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,7 +390,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_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,
@@ -412,7 +423,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_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,

View File

@@ -15,38 +15,50 @@ namespace Ryujinx.Tests.Cpu
#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)
@@ -178,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
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,18 +492,19 @@ 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,
@@ -514,7 +527,8 @@ 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,
@@ -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,7 +587,8 @@ 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,
@@ -594,7 +611,8 @@ 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,

View File

@@ -13,23 +13,34 @@ namespace Ryujinx.Tests.Cpu
#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
@@ -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,7 +103,7 @@ 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
@@ -171,8 +182,10 @@ 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);

View File

@@ -38,8 +38,10 @@ namespace Ryujinx.Tests.Cpu
#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_()
@@ -101,7 +103,7 @@ namespace Ryujinx.Tests.Cpu
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,7 +130,7 @@ 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

View File

@@ -41,15 +41,15 @@ namespace Ryujinx.Tests.Cpu
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;

File diff suppressed because it is too large Load Diff

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,185 +336,185 @@ 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

@@ -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);
}); });

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);
@@ -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

@@ -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];

View File

@@ -26,6 +26,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using Path = System.IO.Path; using Path = System.IO.Path;
using TimeSpan = System.TimeSpan;
namespace Ryujinx.Ui.App.Common namespace Ryujinx.Ui.App.Common
{ {
@@ -44,8 +45,8 @@ namespace Ryujinx.Ui.App.Common
private Language _desiredTitleLanguage; private Language _desiredTitleLanguage;
private CancellationTokenSource _cancellationToken; private CancellationTokenSource _cancellationToken;
private static readonly ApplicationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static readonly TitleUpdateMetadataJsonSerializerContext TitleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public ApplicationLibrary(VirtualFileSystem virtualFileSystem) public ApplicationLibrary(VirtualFileSystem virtualFileSystem)
{ {
@@ -459,27 +460,27 @@ namespace Ryujinx.Ui.App.Common
FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + " MiB" : fileSize.ToString("0.##") + " GiB", FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + " MiB" : fileSize.ToString("0.##") + " GiB",
FileSizeBytes = fileSize, FileSizeBytes = fileSize,
Path = applicationPath, Path = applicationPath,
ControlHolder = controlHolder ControlHolder = controlHolder,
}; };
numApplicationsLoaded++; numApplicationsLoaded++;
OnApplicationAdded(new ApplicationAddedEventArgs() OnApplicationAdded(new ApplicationAddedEventArgs
{ {
AppData = data AppData = data,
}); });
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs() OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
{ {
NumAppsFound = numApplicationsFound, NumAppsFound = numApplicationsFound,
NumAppsLoaded = numApplicationsLoaded NumAppsLoaded = numApplicationsLoaded,
}); });
} }
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs() OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
{ {
NumAppsFound = numApplicationsFound, NumAppsFound = numApplicationsFound,
NumAppsLoaded = numApplicationsLoaded NumAppsLoaded = numApplicationsLoaded,
}); });
} }
finally finally
@@ -508,7 +509,7 @@ namespace Ryujinx.Ui.App.Common
titleId = controlNca?.Header.TitleId.ToString("x16"); titleId = controlNca?.Header.TitleId.ToString("x16");
} }
public ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null) public static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
{ {
string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui"); string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui");
string metadataFile = Path.Combine(metadataFolder, "metadata.json"); string metadataFile = Path.Combine(metadataFolder, "metadata.json");
@@ -521,12 +522,12 @@ namespace Ryujinx.Ui.App.Common
appMetadata = new ApplicationMetadata(); appMetadata = new ApplicationMetadata();
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata); JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
} }
try try
{ {
appMetadata = JsonHelper.DeserializeFromFile(metadataFile, SerializerContext.ApplicationMetadata); appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata);
} }
catch (JsonException) catch (JsonException)
{ {
@@ -539,7 +540,7 @@ namespace Ryujinx.Ui.App.Common
{ {
modifyFunction(appMetadata); modifyFunction(appMetadata);
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata); JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
} }
return appMetadata; return appMetadata;
@@ -713,7 +714,7 @@ namespace Ryujinx.Ui.App.Common
private static string ConvertSecondsToFormattedString(double seconds) private static string ConvertSecondsToFormattedString(double seconds)
{ {
System.TimeSpan time = System.TimeSpan.FromSeconds(seconds); TimeSpan time = TimeSpan.FromSeconds(seconds);
string timeString; string timeString;
if (time.Days != 0) if (time.Days != 0)
@@ -840,7 +841,7 @@ namespace Ryujinx.Ui.App.Common
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage()); Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF); int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
@@ -884,7 +885,7 @@ namespace Ryujinx.Ui.App.Common
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage()); Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF); int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
@@ -925,12 +926,12 @@ namespace Ryujinx.Ui.App.Common
if (File.Exists(titleUpdateMetadataPath)) if (File.Exists(titleUpdateMetadataPath))
{ {
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, TitleSerializerContext.TitleUpdateMetadata).Selected; updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
if (File.Exists(updatePath)) if (File.Exists(updatePath))
{ {
FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read); FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); PartitionFileSystem nsp = new(file.AsStorage());
return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex); return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
} }
@@ -941,4 +942,3 @@ namespace Ryujinx.Ui.App.Common
} }
} }
} }

View File

@@ -9,6 +9,6 @@ namespace Ryujinx.Ui.Common.Configuration
Dummy, Dummy,
OpenAl, OpenAl,
SoundIo, SoundIo,
SDL2 SDL2,
} }
} }

View File

@@ -4,6 +4,6 @@ namespace Ryujinx.Ui.Common.Configuration
{ {
Success = 0, Success = 0,
NotLoaded = 1, NotLoaded = 1,
MigratedFromPreVulkan = 1 << 8 MigratedFromPreVulkan = 1 << 8,
} }
} }

View File

@@ -278,7 +278,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableFsAccessLog = new ReactiveObject<bool>(); EnableFsAccessLog = new ReactiveObject<bool>();
FilteredClasses = new ReactiveObject<LogClass[]>(); FilteredClasses = new ReactiveObject<LogClass[]>();
EnableFileLog = new ReactiveObject<bool>(); EnableFileLog = new ReactiveObject<bool>();
EnableFileLog.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFileLog)); EnableFileLog.Event += static (sender, e) => LogValueChange(e, nameof(EnableFileLog));
GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>(); GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
} }
} }
@@ -370,27 +370,27 @@ namespace Ryujinx.Ui.Common.Configuration
TimeZone = new ReactiveObject<string>(); TimeZone = new ReactiveObject<string>();
SystemTimeOffset = new ReactiveObject<long>(); SystemTimeOffset = new ReactiveObject<long>();
EnableDockedMode = new ReactiveObject<bool>(); EnableDockedMode = new ReactiveObject<bool>();
EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode)); EnableDockedMode.Event += static (sender, e) => LogValueChange(e, nameof(EnableDockedMode));
EnablePtc = new ReactiveObject<bool>(); EnablePtc = new ReactiveObject<bool>();
EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
EnableInternetAccess = new ReactiveObject<bool>(); EnableInternetAccess = new ReactiveObject<bool>();
EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess)); EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess));
EnableFsIntegrityChecks = new ReactiveObject<bool>(); EnableFsIntegrityChecks = new ReactiveObject<bool>();
EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks)); EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks));
FsGlobalAccessLogMode = new ReactiveObject<int>(); FsGlobalAccessLogMode = new ReactiveObject<int>();
FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(FsGlobalAccessLogMode)); FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(e, nameof(FsGlobalAccessLogMode));
AudioBackend = new ReactiveObject<AudioBackend>(); AudioBackend = new ReactiveObject<AudioBackend>();
AudioBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend)); AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend));
MemoryManagerMode = new ReactiveObject<MemoryManagerMode>(); MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
MemoryManagerMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(MemoryManagerMode)); MemoryManagerMode.Event += static (sender, e) => LogValueChange(e, nameof(MemoryManagerMode));
ExpandRam = new ReactiveObject<bool>(); ExpandRam = new ReactiveObject<bool>();
ExpandRam.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam)); ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam));
IgnoreMissingServices = new ReactiveObject<bool>(); IgnoreMissingServices = new ReactiveObject<bool>();
IgnoreMissingServices.Event += static (sender, e) => LogValueChange(sender, e, nameof(IgnoreMissingServices)); IgnoreMissingServices.Event += static (sender, e) => LogValueChange(e, nameof(IgnoreMissingServices));
AudioVolume = new ReactiveObject<float>(); AudioVolume = new ReactiveObject<float>();
AudioVolume.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioVolume)); AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume));
UseHypervisor = new ReactiveObject<bool>(); UseHypervisor = new ReactiveObject<bool>();
UseHypervisor.Event += static (sender, e) => LogValueChange(sender, e, nameof(UseHypervisor)); UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor));
} }
} }
@@ -513,34 +513,34 @@ namespace Ryujinx.Ui.Common.Configuration
public GraphicsSection() public GraphicsSection()
{ {
BackendThreading = new ReactiveObject<BackendThreading>(); BackendThreading = new ReactiveObject<BackendThreading>();
BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading)); BackendThreading.Event += static (sender, e) => LogValueChange(e, nameof(BackendThreading));
ResScale = new ReactiveObject<int>(); ResScale = new ReactiveObject<int>();
ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale));
ResScaleCustom = new ReactiveObject<float>(); ResScaleCustom = new ReactiveObject<float>();
ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); ResScaleCustom.Event += static (sender, e) => LogValueChange(e, nameof(ResScaleCustom));
MaxAnisotropy = new ReactiveObject<float>(); MaxAnisotropy = new ReactiveObject<float>();
MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy));
AspectRatio = new ReactiveObject<AspectRatio>(); AspectRatio = new ReactiveObject<AspectRatio>();
AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); AspectRatio.Event += static (sender, e) => LogValueChange(e, nameof(AspectRatio));
ShadersDumpPath = new ReactiveObject<string>(); ShadersDumpPath = new ReactiveObject<string>();
EnableVsync = new ReactiveObject<bool>(); EnableVsync = new ReactiveObject<bool>();
EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); EnableVsync.Event += static (sender, e) => LogValueChange(e, nameof(EnableVsync));
EnableShaderCache = new ReactiveObject<bool>(); EnableShaderCache = new ReactiveObject<bool>();
EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache));
EnableTextureRecompression = new ReactiveObject<bool>(); EnableTextureRecompression = new ReactiveObject<bool>();
EnableTextureRecompression.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableTextureRecompression)); EnableTextureRecompression.Event += static (sender, e) => LogValueChange(e, nameof(EnableTextureRecompression));
GraphicsBackend = new ReactiveObject<GraphicsBackend>(); GraphicsBackend = new ReactiveObject<GraphicsBackend>();
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend)); GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend));
PreferredGpu = new ReactiveObject<string>(); PreferredGpu = new ReactiveObject<string>();
PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu)); PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu));
EnableMacroHLE = new ReactiveObject<bool>(); EnableMacroHLE = new ReactiveObject<bool>();
EnableMacroHLE.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableMacroHLE)); EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
AntiAliasing = new ReactiveObject<AntiAliasing>(); AntiAliasing = new ReactiveObject<AntiAliasing>();
AntiAliasing.Event += static (sender, e) => LogValueChange(sender, e, nameof(AntiAliasing)); AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing));
ScalingFilter = new ReactiveObject<ScalingFilter>(); ScalingFilter = new ReactiveObject<ScalingFilter>();
ScalingFilter.Event += static (sender, e) => LogValueChange(sender, e, nameof(ScalingFilter)); ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter));
ScalingFilterLevel = new ReactiveObject<int>(); ScalingFilterLevel = new ReactiveObject<int>();
ScalingFilterLevel.Event += static (sender, e) => LogValueChange(sender, e, nameof(ScalingFilterLevel)); ScalingFilterLevel.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilterLevel));
} }
} }
@@ -631,7 +631,7 @@ namespace Ryujinx.Ui.Common.Configuration
public ConfigurationFileFormat ToFileFormat() public ConfigurationFileFormat ToFileFormat()
{ {
ConfigurationFileFormat configurationFile = new ConfigurationFileFormat ConfigurationFileFormat configurationFile = new()
{ {
Version = ConfigurationFileFormat.CurrentVersion, Version = ConfigurationFileFormat.CurrentVersion,
BackendThreading = Graphics.BackendThreading, BackendThreading = Graphics.BackendThreading,
@@ -688,12 +688,12 @@ namespace Ryujinx.Ui.Common.Configuration
LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn, LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
FileExtColumn = Ui.GuiColumns.FileExtColumn, FileExtColumn = Ui.GuiColumns.FileExtColumn,
FileSizeColumn = Ui.GuiColumns.FileSizeColumn, FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
PathColumn = Ui.GuiColumns.PathColumn PathColumn = Ui.GuiColumns.PathColumn,
}, },
ColumnSort = new ColumnSort ColumnSort = new ColumnSort
{ {
SortColumnId = Ui.ColumnSort.SortColumnId, SortColumnId = Ui.ColumnSort.SortColumnId,
SortAscending = Ui.ColumnSort.SortAscending SortAscending = Ui.ColumnSort.SortAscending,
}, },
GameDirs = Ui.GameDirs, GameDirs = Ui.GameDirs,
ShownFileTypes = new ShownFileTypes ShownFileTypes = new ShownFileTypes
@@ -732,7 +732,7 @@ namespace Ryujinx.Ui.Common.Configuration
InputConfig = Hid.InputConfig, InputConfig = Hid.InputConfig,
GraphicsBackend = Graphics.GraphicsBackend, GraphicsBackend = Graphics.GraphicsBackend,
PreferredGpu = Graphics.PreferredGpu, PreferredGpu = Graphics.PreferredGpu,
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
}; };
return configurationFile; return configurationFile;
@@ -767,7 +767,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration.Value = true; EnableDiscordIntegration.Value = true;
CheckUpdatesOnStart.Value = true; CheckUpdatesOnStart.Value = true;
ShowConfirmExit.Value = true; ShowConfirmExit.Value = true;
HideCursor.Value = Ryujinx.Common.Configuration.HideCursorMode.Never; HideCursor.Value = HideCursorMode.Never;
Graphics.EnableVsync.Value = true; Graphics.EnableVsync.Value = true;
Graphics.EnableShaderCache.Value = true; Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false; Graphics.EnableTextureRecompression.Value = false;
@@ -833,7 +833,7 @@ namespace Ryujinx.Ui.Common.Configuration
ResScaleUp = Key.Unbound, ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound, ResScaleDown = Key.Unbound,
VolumeUp = Key.Unbound, VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound VolumeDown = Key.Unbound,
}; };
Hid.InputConfig.Value = new List<InputConfig> Hid.InputConfig.Value = new List<InputConfig>
{ {
@@ -854,9 +854,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonL = Key.E, ButtonL = Key.E,
ButtonZl = Key.Q, ButtonZl = Key.Q,
ButtonSl = Key.Unbound, ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound ButtonSr = Key.Unbound,
}, },
LeftJoyconStick = new JoyconConfigKeyboardStick<Key> LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{ {
StickUp = Key.W, StickUp = Key.W,
@@ -865,7 +864,6 @@ namespace Ryujinx.Ui.Common.Configuration
StickRight = Key.D, StickRight = Key.D,
StickButton = Key.F, StickButton = Key.F,
}, },
RightJoycon = new RightJoyconCommonConfig<Key> RightJoycon = new RightJoyconCommonConfig<Key>
{ {
ButtonA = Key.Z, ButtonA = Key.Z,
@@ -876,9 +874,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonR = Key.U, ButtonR = Key.U,
ButtonZr = Key.O, ButtonZr = Key.O,
ButtonSl = Key.Unbound, ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound ButtonSr = Key.Unbound,
}, },
RightJoyconStick = new JoyconConfigKeyboardStick<Key> RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{ {
StickUp = Key.I, StickUp = Key.I,
@@ -886,8 +883,8 @@ namespace Ryujinx.Ui.Common.Configuration
StickLeft = Key.J, StickLeft = Key.J,
StickRight = Key.L, StickRight = Key.L,
StickButton = Key.H, StickButton = Key.H,
} },
} },
}; };
} }
@@ -958,12 +955,12 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.ColumnSort = new ColumnSort configurationFileFormat.ColumnSort = new ColumnSort
{ {
SortColumnId = 0, SortColumnId = 0,
SortAscending = false SortAscending = false,
}; };
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1 ToggleVsync = Key.F1,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1074,9 +1071,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonL = Key.E, ButtonL = Key.E,
ButtonZl = Key.Q, ButtonZl = Key.Q,
ButtonSl = Key.Unbound, ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound ButtonSr = Key.Unbound,
}, },
LeftJoyconStick = new JoyconConfigKeyboardStick<Key> LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{ {
StickUp = Key.W, StickUp = Key.W,
@@ -1085,7 +1081,6 @@ namespace Ryujinx.Ui.Common.Configuration
StickRight = Key.D, StickRight = Key.D,
StickButton = Key.F, StickButton = Key.F,
}, },
RightJoycon = new RightJoyconCommonConfig<Key> RightJoycon = new RightJoyconCommonConfig<Key>
{ {
ButtonA = Key.Z, ButtonA = Key.Z,
@@ -1096,9 +1091,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonR = Key.U, ButtonR = Key.U,
ButtonZr = Key.O, ButtonZr = Key.O,
ButtonSl = Key.Unbound, ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound ButtonSr = Key.Unbound,
}, },
RightJoyconStick = new JoyconConfigKeyboardStick<Key> RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{ {
StickUp = Key.I, StickUp = Key.I,
@@ -1106,8 +1100,8 @@ namespace Ryujinx.Ui.Common.Configuration
StickLeft = Key.J, StickLeft = Key.J,
StickRight = Key.L, StickRight = Key.L,
StickButton = Key.H, StickButton = Key.H,
} },
} },
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1145,7 +1139,7 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1, ToggleVsync = Key.F1,
Screenshot = Key.F8 Screenshot = Key.F8,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1159,7 +1153,7 @@ namespace Ryujinx.Ui.Common.Configuration
{ {
ToggleVsync = Key.F1, ToggleVsync = Key.F1,
Screenshot = Key.F8, Screenshot = Key.F8,
ShowUi = Key.F4 ShowUi = Key.F4,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1177,7 +1171,7 @@ namespace Ryujinx.Ui.Common.Configuration
{ {
EnableRumble = false, EnableRumble = false,
StrongRumble = 1f, StrongRumble = 1f,
WeakRumble = 1f WeakRumble = 1f,
}; };
} }
} }
@@ -1203,7 +1197,7 @@ namespace Ryujinx.Ui.Common.Configuration
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUi = configurationFileFormat.Hotkeys.ShowUi, ShowUi = configurationFileFormat.Hotkeys.ShowUi,
Pause = Key.F5 Pause = Key.F5,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1219,7 +1213,7 @@ namespace Ryujinx.Ui.Common.Configuration
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUi = configurationFileFormat.Hotkeys.ShowUi, ShowUi = configurationFileFormat.Hotkeys.ShowUi,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = Key.F2 ToggleMute = Key.F2,
}; };
configurationFileFormat.AudioVolume = 1; configurationFileFormat.AudioVolume = 1;
@@ -1295,7 +1289,7 @@ namespace Ryujinx.Ui.Common.Configuration
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute, ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = Key.Unbound, ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound ResScaleDown = Key.Unbound,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1326,7 +1320,7 @@ namespace Ryujinx.Ui.Common.Configuration
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp, ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown, ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = Key.Unbound, VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound VolumeDown = Key.Unbound,
}; };
} }
@@ -1366,7 +1360,7 @@ namespace Ryujinx.Ui.Common.Configuration
XCI = true, XCI = true,
NCA = true, NCA = true,
NRO = true, NRO = true,
NSO = true NSO = true,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -1499,7 +1493,7 @@ namespace Ryujinx.Ui.Common.Configuration
return result; return result;
} }
private static void LogValueChange<T>(object sender, ReactiveEventArgs<T> eventArgs, string valueName) private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName)
{ {
Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}"); Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
} }

View File

@@ -23,6 +23,6 @@ namespace Ryujinx.Ui.Common.Configuration.System
LatinAmericanSpanish, LatinAmericanSpanish,
SimplifiedChinese, SimplifiedChinese,
TraditionalChinese, TraditionalChinese,
BrazilianPortuguese BrazilianPortuguese,
} }
} }

View File

@@ -12,6 +12,6 @@ namespace Ryujinx.Ui.Common.Configuration.System
Australia, Australia,
China, China,
Korea, Korea,
Taiwan Taiwan,
} }
} }

View File

@@ -19,19 +19,19 @@ namespace Ryujinx.Ui.Common
Assets = new Assets Assets = new Assets
{ {
LargeImageKey = "ryujinx", LargeImageKey = "ryujinx",
LargeImageText = Description LargeImageText = Description,
}, },
Details = "Main Menu", Details = "Main Menu",
State = "Idling", State = "Idling",
Timestamps = Timestamps.Now, Timestamps = Timestamps.Now,
Buttons = new Button[] Buttons = new[]
{ {
new Button() new Button
{ {
Label = "Website", Label = "Website",
Url = "https://ryujinx.org/" Url = "https://ryujinx.org/",
} },
} },
}; };
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update; ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
@@ -74,14 +74,14 @@ namespace Ryujinx.Ui.Common
Details = $"Playing {titleName}", Details = $"Playing {titleName}",
State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(), State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
Timestamps = Timestamps.Now, Timestamps = Timestamps.Now,
Buttons = new Button[] Buttons = new[]
{ {
new Button() new Button
{ {
Label = "Website", Label = "Website",
Url = "https://ryujinx.org/" Url = "https://ryujinx.org/",
} },
} },
}); });
} }

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.Ui.Common
FileTypes.NCA => config.NCA.Value, FileTypes.NCA => config.NCA.Value,
FileTypes.NRO => config.NRO.Value, FileTypes.NRO => config.NRO.Value,
FileTypes.NSO => config.NSO.Value, FileTypes.NSO => config.NSO.Value,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null) _ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
}; };
} }
} }

View File

@@ -49,8 +49,8 @@ namespace Ryujinx.Ui.Common.Helper
StartInfo = StartInfo =
{ {
FileName = PkExecPath, FileName = PkExecPath,
ArgumentList = { "sh", "-c", command } ArgumentList = { "sh", "-c", command },
} },
}; };
process.Start(); process.Start();

View File

@@ -1,8 +1,6 @@
using System; using System;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Text;
namespace Ryujinx.Ui.Common.Helper namespace Ryujinx.Ui.Common.Helper
{ {
@@ -12,44 +10,109 @@ namespace Ryujinx.Ui.Common.Helper
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)] [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
private static unsafe partial IntPtr sel_getUid(string name); private static partial IntPtr sel_getUid(string name);
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)] [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
public static partial IntPtr objc_getClass(string name); private static partial IntPtr objc_getClass(string name);
[LibraryImport(ObjCRuntime)] [LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector); private static partial void objc_msgSend(IntPtr receiver, Selector selector);
[LibraryImport(ObjCRuntime)] [LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value); private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
[LibraryImport(ObjCRuntime)] [LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value); private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
[LibraryImport(ObjCRuntime)] [LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point); private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
[LibraryImport(ObjCRuntime)] [LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, double value); private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector); private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param); private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)] [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param); private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param); private static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
public struct Selector public readonly struct Object
{
public readonly IntPtr ObjPtr;
private Object(IntPtr pointer)
{
ObjPtr = pointer;
}
public Object(string name)
{
ObjPtr = objc_getClass(name);
}
public void SendMessage(Selector selector)
{
objc_msgSend(ObjPtr, selector);
}
public void SendMessage(Selector selector, byte value)
{
objc_msgSend(ObjPtr, selector, value);
}
public void SendMessage(Selector selector, Object obj)
{
objc_msgSend(ObjPtr, selector, obj.ObjPtr);
}
public void SendMessage(Selector selector, NSRect point)
{
objc_msgSend(ObjPtr, selector, point);
}
public void SendMessage(Selector selector, double value)
{
objc_msgSend(ObjPtr, selector, value);
}
public Object GetFromMessage(Selector selector)
{
return new Object(IntPtr_objc_msgSend(ObjPtr, selector));
}
public Object GetFromMessage(Selector selector, Object obj)
{
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, obj.ObjPtr));
}
public Object GetFromMessage(Selector selector, NSString nsString)
{
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, nsString.StrPtr));
}
public Object GetFromMessage(Selector selector, string param)
{
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, param));
}
public bool GetBoolFromMessage(Selector selector, Object obj)
{
return bool_objc_msgSend(ObjPtr, selector, obj.ObjPtr);
}
}
public readonly struct Selector
{ {
public readonly IntPtr SelPtr; public readonly IntPtr SelPtr;
public unsafe Selector(string name) private Selector(string name)
{ {
SelPtr = sel_getUid(name); SelPtr = sel_getUid(name);
} }
@@ -57,7 +120,7 @@ namespace Ryujinx.Ui.Common.Helper
public static implicit operator Selector(string value) => new(value); public static implicit operator Selector(string value) => new(value);
} }
public struct NSString public readonly struct NSString
{ {
public readonly IntPtr StrPtr; public readonly IntPtr StrPtr;

View File

@@ -9,13 +9,13 @@ namespace Ryujinx.Ui.Common.Helper
public static partial class OpenHelper public static partial class OpenHelper
{ {
[LibraryImport("shell32.dll", SetLastError = true)] [LibraryImport("shell32.dll", SetLastError = true)]
public static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags); private static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
[LibraryImport("shell32.dll", SetLastError = true)] [LibraryImport("shell32.dll", SetLastError = true)]
public static partial void ILFree(IntPtr pidlList); private static partial void ILFree(IntPtr pidlList);
[LibraryImport("shell32.dll", SetLastError = true)] [LibraryImport("shell32.dll", SetLastError = true)]
public static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath); private static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath);
public static void OpenFolder(string path) public static void OpenFolder(string path)
{ {
@@ -25,7 +25,7 @@ namespace Ryujinx.Ui.Common.Helper
{ {
FileName = path, FileName = path,
UseShellExecute = true, UseShellExecute = true,
Verb = "open" Verb = "open",
}); });
} }
else else
@@ -56,16 +56,16 @@ namespace Ryujinx.Ui.Common.Helper
else if (OperatingSystem.IsMacOS()) else if (OperatingSystem.IsMacOS())
{ {
ObjectiveC.NSString nsStringPath = new(path); ObjectiveC.NSString nsStringPath = new(path);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL"); ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "fileURLWithPath:", nsStringPath); var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
IntPtr nsArray = ObjectiveC.objc_getClass("NSArray"); ObjectiveC.Object nsArray = new("NSArray");
IntPtr urlArray = ObjectiveC.IntPtr_objc_msgSend(nsArray, "arrayWithObject:", urlPtr); ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace"); ObjectiveC.Object nsWorkspace = new("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace"); ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
ObjectiveC.objc_msgSend(sharedWorkspace, "activateFileViewerSelectingURLs:", urlArray); sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray);
} }
else if (OperatingSystem.IsLinux()) else if (OperatingSystem.IsLinux())
{ {
@@ -95,13 +95,13 @@ namespace Ryujinx.Ui.Common.Helper
else if (OperatingSystem.IsMacOS()) else if (OperatingSystem.IsMacOS())
{ {
ObjectiveC.NSString nsStringPath = new(url); ObjectiveC.NSString nsStringPath = new(url);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL"); ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "URLWithString:", nsStringPath); var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace"); ObjectiveC.Object nsWorkspace = new("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace"); ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
ObjectiveC.bool_objc_msgSend(sharedWorkspace, "openURL:", urlPtr); sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr);
} }
else else
{ {

View File

@@ -20,13 +20,11 @@ namespace Ryujinx.Ui.Common.Helper
return true; return true;
} }
else
{
error = UserError.NoFirmware; error = UserError.NoFirmware;
return false; return false;
} }
}
public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion) public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion)
{ {
@@ -107,12 +105,10 @@ namespace Ryujinx.Ui.Common.Helper
return IsFirmwareValid(contentManager, out error); return IsFirmwareValid(contentManager, out error);
} }
else
{
error = UserError.ApplicationNotFound; error = UserError.ApplicationNotFound;
return false; return false;
} }
} }
} }
}

View File

@@ -29,29 +29,39 @@ namespace Ryujinx.Ui.Common.Models.Amiibo
[JsonPropertyName("gamesSwitch")] [JsonPropertyName("gamesSwitch")]
public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; } public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
public override string ToString() public readonly override string ToString()
{ {
return Name; return Name;
} }
public string GetId() public readonly string GetId()
{ {
return Head + Tail; return Head + Tail;
} }
public bool Equals(AmiiboApi other) public readonly bool Equals(AmiiboApi other)
{ {
return Head + Tail == other.Head + other.Tail; return Head + Tail == other.Head + other.Tail;
} }
public override bool Equals(object obj) public readonly override bool Equals(object obj)
{ {
return obj is AmiiboApi other && Equals(other); return obj is AmiiboApi other && Equals(other);
} }
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return HashCode.Combine(Head, Tail); return HashCode.Combine(Head, Tail);
} }
public static bool operator ==(AmiiboApi left, AmiiboApi right)
{
return left.Equals(right);
}
public static bool operator !=(AmiiboApi left, AmiiboApi right)
{
return !(left == right);
}
} }
} }

View File

@@ -34,6 +34,6 @@
/// <summary> /// <summary>
/// An unknown error. /// An unknown error.
/// </summary> /// </summary>
Unknown = 0xDEAD Unknown = 0xDEAD,
} }
} }

View File

@@ -874,7 +874,7 @@ namespace Ryujinx.Ui
DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText, DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
_emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString()); _emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString());
_applicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata => ApplicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata =>
{ {
appMetadata.LastPlayed = DateTime.UtcNow; appMetadata.LastPlayed = DateTime.UtcNow;
}); });
@@ -1017,7 +1017,7 @@ namespace Ryujinx.Ui
{ {
if (_gameLoaded) if (_gameLoaded)
{ {
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
{ {
if (appMetadata.LastPlayed.HasValue) if (appMetadata.LastPlayed.HasValue)
{ {
@@ -1156,7 +1156,7 @@ namespace Ryujinx.Ui
_tableStore.SetValue(treeIter, 0, newToggleValue); _tableStore.SetValue(treeIter, 0, newToggleValue);
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
{ {
appMetadata.Favorite = newToggleValue; appMetadata.Favorite = newToggleValue;
}); });