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.Input;
using Ryujinx.Input.HLE;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
@@ -692,7 +693,7 @@ namespace Ryujinx.Ava
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;
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,18 +18,16 @@ namespace Ryujinx.Cpu.AppleHv
private const ulong AllocationGranule = 1UL << 14;
private readonly ulong _asBase;
private readonly ulong _asSize;
private readonly ulong _backingSize;
private readonly HvAddressSpaceRange _userRange;
private readonly HvAddressSpaceRange _kernelRange;
private MemoryBlock _kernelCodeBlock;
private readonly MemoryBlock _kernelCodeBlock;
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
{
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
_asSize = asSize;
_backingSize = backingMemory.Size;
_userRange = new HvAddressSpaceRange(ipaAllocator);
@@ -58,20 +56,20 @@ namespace Ryujinx.Cpu.AppleHv
_kernelCodeBlock.Write(KernelRegionEretOffset, 0xD69F03E0u); // ERET
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);
}
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, hv_sys_reg_t.HV_SYS_REG_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, hv_sys_reg_t.HV_SYS_REG_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.TTBR0_EL1, _userRange.GetIpaBase());
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TTBR1_EL1, _kernelRange.GetIpaBase());
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.MAIR_EL1, 0xffUL);
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TCR_EL1, 0x00000011B5193519UL);
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.SCTLR_EL1, 0x0000000034D5D925UL);
}
public bool GetAndClearUserTlbInvalidationPending()
@@ -115,7 +113,7 @@ namespace Ryujinx.Cpu.AppleHv
MemoryPermission.ReadAndWrite => ApFlags.UserReadWriteKernelReadWrite,
MemoryPermission.ReadAndExecute => ApFlags.UserReadExecuteKernelRead,
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);
Allocation = blockAllocator.Allocate(size, PageSize);
AsSpan().Fill(0UL);
AsSpan().Clear();
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));
}
@@ -52,12 +52,10 @@ namespace Ryujinx.Cpu.AppleHv
private int _tlbInvalidationPending;
private readonly HvIpaAllocator _ipaAllocator;
private readonly HvMemoryBlockAllocator _blockAllocator;
public HvAddressSpaceRange(HvIpaAllocator ipaAllocator)
{
_ipaAllocator = ipaAllocator;
_blockAllocator = new HvMemoryBlockAllocator(ipaAllocator, (int)AllocationGranule);
}
@@ -129,7 +127,7 @@ namespace Ryujinx.Cpu.AppleHv
ulong endVa = (va + size + PageMask) & ~((ulong)PageMask);
va &= ~((ulong)PageMask);
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
(ulong blockSize, _) = GetBlockSizeAndShift(depth);
while (va < endVa)
{
@@ -138,7 +136,7 @@ namespace Ryujinx.Cpu.AppleHv
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)
{
@@ -190,7 +188,7 @@ namespace Ryujinx.Cpu.AppleHv
ulong endVa = (va + size + PageSize - 1) & ~((ulong)PageSize - 1);
va &= ~((ulong)PageSize - 1);
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
(ulong blockSize, _) = GetBlockSizeAndShift(depth);
while (va < endVa)
{
@@ -204,7 +202,7 @@ namespace Ryujinx.Cpu.AppleHv
// First check if the region is mapped.
if ((pte & 3) != 0)
{
PtLevel nextTable = level.Next != null ? level.Next[l] : null;
PtLevel nextTable = level.Next?[l];
if (nextTable != null)
{
@@ -240,10 +238,10 @@ namespace Ryujinx.Cpu.AppleHv
pte &= ~3UL;
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();
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
(_, int blockShift) = GetBlockSizeAndShift(depth);
// Fill in the blocks.
for (int i = 0; i < LevelCount; i++)
@@ -334,7 +332,7 @@ namespace Ryujinx.Cpu.AppleHv
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;
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();

View File

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

View File

@@ -125,17 +125,17 @@ namespace Ryujinx.Cpu.AppleHv
{
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)
{
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
uint reason = vcpu.ExitInfo->reason;
uint reason = vcpu.ExitInfo->Reason;
if (reason == 1)
{
uint hvEsr = (uint)vcpu.ExitInfo->exception.syndrome;
uint hvEsr = (uint)vcpu.ExitInfo->Exception.Syndrome;
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
if (hvEc != ExceptionClass.HvcAarch64)
@@ -144,7 +144,7 @@ namespace Ryujinx.Cpu.AppleHv
}
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)
{
@@ -168,8 +168,8 @@ namespace Ryujinx.Cpu.AppleHv
{
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, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError();
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
ExceptionClass ec = (ExceptionClass)((uint)esr >> 26);
@@ -180,7 +180,7 @@ namespace Ryujinx.Cpu.AppleHv
break;
case ExceptionClass.TrappedMsrMrsSystem:
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;
case ExceptionClass.SvcAarch64:
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 farValid = (esr & (1u << 10)) == 0;
@@ -212,7 +212,7 @@ namespace Ryujinx.Cpu.AppleHv
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;

View File

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

View File

@@ -8,10 +8,10 @@ namespace Ryujinx.Cpu.AppleHv
{
class HvExecutionContextVcpu : IHvExecutionContext
{
private static MemoryBlock _setSimdFpRegFuncMem;
private delegate hv_result_t SetSimdFpReg(ulong vcpu, hv_simd_fp_reg_t reg, in V128 value, IntPtr funcPtr);
private static SetSimdFpReg _setSimdFpReg;
private static IntPtr _setSimdFpRegNativePtr;
private static readonly MemoryBlock _setSimdFpRegFuncMem;
private delegate HvResult SetSimdFpReg(ulong vcpu, HvSimdFPReg reg, in V128 value, IntPtr funcPtr);
private static readonly SetSimdFpReg _setSimdFpReg;
private static readonly IntPtr _setSimdFpRegNativePtr;
static HvExecutionContextVcpu()
{
@@ -34,12 +34,12 @@ namespace Ryujinx.Cpu.AppleHv
{
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;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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;
public HvExecutionContextVcpu(ulong vcpu)
@@ -146,12 +146,12 @@ namespace Ryujinx.Cpu.AppleHv
{
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;
}
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;
}
}
@@ -160,23 +160,23 @@ namespace Ryujinx.Cpu.AppleHv
{
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
{
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)
{
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);
}
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()

View File

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

View File

@@ -1,12 +1,9 @@
using Ryujinx.Memory;
using System.Collections.Generic;
namespace Ryujinx.Cpu.AppleHv
{
class HvMemoryBlockAllocator : PrivateMemoryAllocatorImpl<HvMemoryBlockAllocator.Block>
{
private const ulong InvalidOffset = ulong.MaxValue;
public class Block : PrivateMemoryAllocator.Block
{
private readonly HvIpaAllocator _ipaAllocator;
@@ -21,7 +18,7 @@ namespace Ryujinx.Cpu.AppleHv
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()
@@ -44,7 +41,7 @@ namespace Ryujinx.Cpu.AppleHv
_ipaAllocator = ipaAllocator;
}
public unsafe HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
{
var allocation = Allocate(size, alignment, CreateBlock);

View File

@@ -32,7 +32,7 @@ namespace Ryujinx.Cpu.AppleHv
MappedReplicated = 0x5555555555555555,
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
ReadWriteTrackedReplicated = ulong.MaxValue
ReadWriteTrackedReplicated = ulong.MaxValue,
}
private readonly InvalidAccessHandler _invalidAccessHandler;
@@ -126,6 +126,7 @@ namespace Ryujinx.Cpu.AppleHv
}
}
#pragma warning disable IDE0051 // Remove unused private member
/// <summary>
/// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
/// </summary>
@@ -138,6 +139,7 @@ namespace Ryujinx.Cpu.AppleHv
throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
}
}
#pragma warning restore IDE0051
/// <inheritdoc/>
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));
data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size));
data[..size].CopyTo(_backingMemory.GetSpan(pa, size));
offset += size;
}
@@ -428,7 +430,7 @@ namespace Ryujinx.Cpu.AppleHv
}
[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);
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));
_backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size));
_backingMemory.GetSpan(pa, size).CopyTo(data[..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>
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
[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.
startVa = va & ~(ulong)PageMask;
@@ -814,7 +816,7 @@ namespace Ryujinx.Cpu.AppleHv
{
MemoryPermission.None => MemoryPermission.ReadAndWrite,
MemoryPermission.Write => MemoryPermission.Read,
_ => MemoryPermission.None
_ => MemoryPermission.None,
};
_addressSpace.ReprotectUser(va, size, protection);

View File

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

View File

@@ -17,10 +17,10 @@ namespace Ryujinx.Cpu.AppleHv
private const int MaxActiveVcpus = 4;
public static readonly HvVcpuPool Instance = new HvVcpuPool();
public static readonly HvVcpuPool Instance = new();
private int _totalVcpus;
private int _maxVcpus;
private readonly int _maxVcpus;
public HvVcpuPool()
{
@@ -69,17 +69,17 @@ namespace Ryujinx.Cpu.AppleHv
bool isEphemeral = newCount > _maxVcpus - MaxActiveVcpus;
// Create VCPU.
hv_vcpu_exit_t* exitInfo = null;
HvVcpuExit* exitInfo = null;
HvApi.hv_vcpu_create(out ulong vcpuHandle, ref exitInfo, IntPtr.Zero).ThrowOnError();
// 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);
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;
}

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Cpu.AppleHv
private static int _addressSpaces;
private static HvIpaAllocator _ipaAllocator;
private static object _lock = new object();
private static readonly object _lock = new();
public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block)
{
@@ -36,7 +36,7 @@ namespace Ryujinx.Cpu.AppleHv
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();

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Cpu.Jit
PtcLoadingState.Start => LoadState.Unloaded,
PtcLoadingState.Loading => LoadState.Loading,
PtcLoadingState.Loaded => LoadState.Loaded,
_ => throw new ArgumentException($"Invalid load state \"{newState}\".")
_ => throw new ArgumentException($"Invalid load state \"{newState}\"."),
};
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 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 oVa = va;
ulong oPa = pa;
while (remainingSize != 0)
{
_pageTable.Write((va / PageSize) * PteSize, PaToPte(pa));
@@ -246,7 +245,7 @@ namespace Ryujinx.Cpu.Jit
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;
}
@@ -298,7 +297,7 @@ namespace Ryujinx.Cpu.Jit
}
/// <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)
{
@@ -345,7 +344,7 @@ namespace Ryujinx.Cpu.Jit
/// <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>
[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.
startVa = va & ~(ulong)PageMask;
@@ -482,7 +481,7 @@ namespace Ryujinx.Cpu.Jit
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;
}
@@ -576,6 +575,7 @@ namespace Ryujinx.Cpu.Jit
}
}
#pragma warning disable IDE0051 // Remove unused private member
private ulong GetPhysicalAddress(ulong va)
{
// We return -1L if the virtual address is invalid or unmapped.
@@ -586,6 +586,7 @@ namespace Ryujinx.Cpu.Jit
return GetPhysicalAddressInternal(va);
}
#pragma warning restore IDE0051
private ulong GetPhysicalAddressInternal(ulong va)
{
@@ -604,7 +605,7 @@ namespace Ryujinx.Cpu.Jit
{
MemoryPermission.None => 0L,
MemoryPermission.Write => 2L << PointerTagBit,
_ => 3L << PointerTagBit
_ => 3L << PointerTagBit,
};
int pages = GetPagesCount(va, (uint)size, out va);
@@ -698,6 +699,8 @@ namespace Ryujinx.Cpu.Jit
/// </summary>
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,
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
ReadWriteTrackedReplicated = ulong.MaxValue
ReadWriteTrackedReplicated = ulong.MaxValue,
}
private readonly InvalidAccessHandler _invalidAccessHandler;
@@ -404,7 +404,7 @@ namespace Ryujinx.Cpu.Jit
}
[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);
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>
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
[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.
startVa = va & ~(ulong)PageMask;
@@ -697,7 +697,7 @@ namespace Ryujinx.Cpu.Jit
{
MemoryPermission.None => MemoryPermission.ReadAndWrite,
MemoryPermission.Write => MemoryPermission.Read,
_ => MemoryPermission.None
_ => MemoryPermission.None,
};
_addressSpace.Base.Reprotect(va, size, protection, false);

View File

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

View File

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

View File

@@ -2,7 +2,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Memory;
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
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];
}
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));
@@ -42,8 +41,8 @@ namespace Ryujinx.Cpu
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++)
{
byte value = memory.Read<byte>(position + (ulong)offs);
@@ -59,5 +58,4 @@ namespace Ryujinx.Cpu
return Encoding.ASCII.GetString(ms.GetReadOnlySequence());
}
}
}
}

View File

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

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Cpu
public MemoryBlock Memory { get; private set; }
public ulong Size { get; }
private struct Range : IComparable<Range>
private readonly struct Range : IComparable<Range>
{
public ulong Offset { get; }
public ulong Size { get; }
@@ -40,7 +40,7 @@ namespace Ryujinx.Cpu
Size = size;
_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;
public struct Allocation
public readonly struct Allocation
{
public T Block { get; }
public ulong Offset { get; }

View File

@@ -1,14 +1,7 @@
using NUnit.Framework;
using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.Upsampler;
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
{
@@ -41,8 +34,8 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
/// <param name="quality">The resampler quality to use</param>
private static void DoResamplingTest(int inputRate, int outputRate, VoiceInParameter.SampleRateConversionQuality quality)
{
float inputSampleRate = (float)inputRate;
float outputSampleRate = (float)outputRate;
float inputSampleRate = inputRate;
float outputSampleRate = outputRate;
int inputSampleCount = inputRate;
int outputSampleCount = outputRate;
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++)
{
// 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;
@@ -70,14 +63,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
{
VoiceInParameter.SampleRateConversionQuality.High => 3,
VoiceInParameter.SampleRateConversionQuality.Default => 1,
_ => 0
_ => 0,
};
for (int sample = 0; sample < outputSampleCount; sample++)
{
outputBuffer[sample] /= 32767;
// 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]);
// Ensure no discontinuities
@@ -85,7 +78,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
sumDifference += thisDelta;
}
sumDifference = sumDifference / (float)outputSampleCount;
sumDifference /= outputSampleCount;
// Expect the output to be 99% similar to the expected resampled sine wave
Assert.IsTrue(sumDifference < 0.01f);
}

View File

@@ -1,14 +1,7 @@
using NUnit.Framework;
using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.Upsampler;
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
{
@@ -17,7 +10,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
[Test]
public void TestUpsamplerConsistency()
{
UpsamplerBufferState bufferState = new UpsamplerBufferState();
UpsamplerBufferState bufferState = new();
int inputBlockSize = 160;
int numInputSamples = 32000;
int numOutputSamples = 48000;
@@ -28,14 +21,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
for (int sample = 0; sample < inputBuffer.Length; sample++)
{
// 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 outputIdx = 0;
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(
outputBuffer.AsSpan(outputIdx),
inputBuffer.AsSpan(inputIdx),
@@ -52,11 +45,11 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
for (int sample = 0; sample < numOutputSamples; sample++)
{
// 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 = sumDifference / (float)expectedOutput.Length;
sumDifference /= expectedOutput.Length;
// Expect the output to be 98% similar to the expected resampled sine wave
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]
public void TestsMemoryPoolForceMappingEnabled()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision1()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision2()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision2);
@@ -88,7 +88,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision3()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision3);
@@ -114,7 +114,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision4()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision4);
@@ -140,7 +140,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision5()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision5);
@@ -166,7 +166,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision6()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision6);
@@ -192,7 +192,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision7()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision7);
@@ -218,7 +218,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision8()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision8);
@@ -244,7 +244,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision9()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision9);
@@ -270,7 +270,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestRevision10()
{
BehaviourContext behaviourContext = new BehaviourContext();
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision10);

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestInitializeSystemPool()
{
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
@@ -34,7 +34,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestGetProcessHandle()
{
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
@@ -45,7 +45,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
[Test]
public void TestMappings()
{
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
PoolMapper poolMapper = new(DummyProcessHandle, true);
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
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);
}
ErrorInfo errorInfo;
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(0, errorInfo.ExtraErrorInfo);
@@ -105,7 +104,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
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;

View File

@@ -14,13 +14,15 @@ namespace Ryujinx.Tests.Cpu
public class CpuTest
{
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 DataBaseAddress = CodeBaseAddress + Size;
#pragma warning restore CA2211
private static bool Ignore_FpcrFz = false;
private static bool Ignore_FpcrDn = false;
private static readonly bool _ignoreFpcrFz = false;
private static readonly bool _ignoreFpcrDn = false;
private static bool IgnoreAllExcept_FpsrQc = false;
private static readonly bool _ignoreAllExceptFpsrQc = false;
private ulong _currAddress;
@@ -208,12 +210,12 @@ namespace Ryujinx.Tests.Cpu
int fpsr = 0,
bool runUnicorn = true)
{
if (Ignore_FpcrFz)
if (_ignoreFpcrFz)
{
fpcr &= ~(1 << (int)Fpcr.Fz);
}
if (Ignore_FpcrDn)
if (_ignoreFpcrDn)
{
fpcr &= ~(1 << (int)Fpcr.Dn);
}
@@ -254,8 +256,8 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Round towards Minus Infinity mode.</summary>
Rm,
/// <summary>Round towards Zero mode.</summary>
Rz
};
Rz,
}
/// <summary>Floating-point Control Register.</summary>
protected enum Fpcr
@@ -267,11 +269,12 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Default NaN mode control bit.</summary>
Dn = 25,
/// <summary>Alternative half-precision control bit.</summary>
Ahp = 26
Ahp = 26,
}
/// <summary>Floating-point Status Register.</summary>
[Flags] protected enum Fpsr
[Flags]
protected enum Fpsr
{
None = 0,
@@ -289,10 +292,11 @@ namespace Ryujinx.Tests.Cpu
Idc = 1 << 7,
/// <summary>Cumulative saturation bit.</summary>
Qc = 1 << 27
Qc = 1 << 27,
}
[Flags] protected enum FpSkips
[Flags]
protected enum FpSkips
{
None = 0,
@@ -300,7 +304,7 @@ namespace Ryujinx.Tests.Cpu
IfNaND = 2,
IfUnderflow = 4,
IfOverflow = 8
IfOverflow = 8,
}
protected enum FpTolerances
@@ -308,7 +312,7 @@ namespace Ryujinx.Tests.Cpu
None,
UpToOneUlpsS,
UpToOneUlpsD
UpToOneUlpsD,
}
protected void CompareAgainstUnicorn(
@@ -316,7 +320,7 @@ namespace Ryujinx.Tests.Cpu
FpSkips fpSkips = FpSkips.None,
FpTolerances fpTolerances = FpTolerances.None)
{
if (IgnoreAllExcept_FpsrQc)
if (_ignoreAllExceptFpsrQc)
{
fpsrMask &= Fpsr.Qc;
}
@@ -326,6 +330,7 @@ namespace Ryujinx.Tests.Cpu
ManageFpSkips(fpSkips);
}
#pragma warning disable IDE0055 // Disable formatting
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(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(30), Is.EqualTo(_unicornEmu.X[30]));
Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31");
#pragma warning restore IDE0055
if (fpTolerances == FpTolerances.None)
{
@@ -367,6 +373,8 @@ namespace Ryujinx.Tests.Cpu
{
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(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2");
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.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr");
#pragma warning restore IDE0055
if (_usingMemory)
{
@@ -467,13 +476,13 @@ namespace Ryujinx.Tests.Cpu
{
Assert.Multiple(() =>
{
Assert.That (_context.GetV(0).Extract<float>(0),
Assert.That(_context.GetV(0).Extract<float>(0),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(0)).Within(1).Ulps, "V0[0]");
Assert.That (_context.GetV(0).Extract<float>(1),
Assert.That(_context.GetV(0).Extract<float>(1),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(1)).Within(1).Ulps, "V0[1]");
Assert.That (_context.GetV(0).Extract<float>(2),
Assert.That(_context.GetV(0).Extract<float>(2),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(2)).Within(1).Ulps, "V0[2]");
Assert.That (_context.GetV(0).Extract<float>(3),
Assert.That(_context.GetV(0).Extract<float>(3),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(3)).Within(1).Ulps, "V0[3]");
});
@@ -492,9 +501,9 @@ namespace Ryujinx.Tests.Cpu
{
Assert.Multiple(() =>
{
Assert.That (_context.GetV(0).Extract<double>(0),
Assert.That(_context.GetV(0).Extract<double>(0),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(0)).Within(1).Ulps, "V0[0]");
Assert.That (_context.GetV(0).Extract<double>(1),
Assert.That(_context.GetV(0).Extract<double>(1),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(1)).Within(1).Ulps, "V0[1]");
});
@@ -513,13 +522,13 @@ namespace Ryujinx.Tests.Cpu
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
}
protected static V128 MakeVectorScalar(float value) => new V128(value);
protected static V128 MakeVectorScalar(double value) => new V128(value);
protected static V128 MakeVectorScalar(float value) => new(value);
protected static V128 MakeVectorScalar(double value) => new(value);
protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0);
protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1);
protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
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 GetVectorE1(V128 vector) => vector.Extract<ulong>(1);
@@ -528,8 +537,9 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort();
while (( rnd & 0x7C00u) == 0u ||
do
rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x7C00u) == 0u ||
(~rnd & 0x7C00u) == 0u);
return (ushort)rnd;
@@ -539,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUShort();
do
rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x03FFu) == 0u);
return (ushort)(rnd & 0x83FFu);
@@ -549,8 +560,9 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt();
while (( rnd & 0x7F800000u) == 0u ||
do
rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x7F800000u) == 0u ||
(~rnd & 0x7F800000u) == 0u);
return rnd;
@@ -560,7 +572,8 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
do rnd = TestContext.CurrentContext.Random.NextUInt();
do
rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x007FFFFFu) == 0u);
return rnd & 0x807FFFFFu;
@@ -570,8 +583,9 @@ namespace Ryujinx.Tests.Cpu
{
ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong();
while (( rnd & 0x7FF0000000000000ul) == 0ul ||
do
rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
(~rnd & 0x7FF0000000000000ul) == 0ul);
return rnd;
@@ -581,7 +595,8 @@ namespace Ryujinx.Tests.Cpu
{
ulong rnd;
do rnd = TestContext.CurrentContext.Random.NextULong();
do
rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
return rnd & 0x800FFFFFFFFFFFFFul;

View File

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

View File

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

View File

@@ -9,8 +9,8 @@ namespace Ryujinx.Tests.Cpu
{
#if Alu32
#region "ValueSource (Opcodes)"
private static uint[] _SU_H_AddSub_8_()
#region "ValueSource (Opcodes)"
private static uint[] SuHAddSub8()
{
return new[]
{
@@ -21,22 +21,22 @@ namespace Ryujinx.Tests.Cpu
0xe6500f90u, // UADD8 R0, R0, R0
0xe6500ff0u, // USUB8 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[]
{
0xe6a00010u, // SSAT R0, #1, R0, LSL #0
0xe6a00050u, // SSAT R0, #1, R0, ASR #32
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[]
{
@@ -45,17 +45,17 @@ namespace Ryujinx.Tests.Cpu
};
}
private static uint[] _Lsr_Lsl_Asr_Ror_()
private static uint[] LsrLslAsrRor()
{
return new[]
{
0xe1b00030u, // LSRS R0, R0, R0
0xe1b00010u, // LSLS R0, R0, R0
0xe1b00050u, // ASRS R0, R0, R0
0xe1b00070u // RORS R0, R0, R0
0xe1b00070u, // RORS R0, R0, R0
};
}
#endregion
#endregion
private const int RndCnt = 2;
@@ -76,7 +76,7 @@ namespace Ryujinx.Tests.Cpu
}
[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,
0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
[Range(0, 31)] int shiftAmount)
@@ -130,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
@@ -148,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu)] uint sat,
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u)] uint rm,
[Values(2u)] uint rn,

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
{
#if AluRs32
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Add_Adds_Rsb_Rsbs_()
{
return new[]
@@ -17,7 +17,7 @@ namespace Ryujinx.Tests.Cpu
0xe0800000u, // ADD R0, R0, R0, LSL #0
0xe0900000u, // ADDS 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
0xe0f00000u, // RSCS R0, R0, R0
0xe0c00000u, // SBC R0, R0, R0
0xe0d00000u // SBCS R0, R0, R0
0xe0d00000u, // SBCS R0, R0, R0
};
}
#endregion
#endregion
[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(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
@@ -57,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
{
#if Misc
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_()
{
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -24,19 +24,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -54,15 +54,15 @@ namespace Ryujinx.Tests.Cpu
yield return (grbg << 32) | rnd2;
}
}
#endregion
#endregion
private const int RndCnt = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = false;
private static readonly bool _noNaNs = false;
#region "AluImm & Csel"
#region "AluImm & Csel"
[Test, Pairwise]
public void Adds_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
@@ -162,10 +162,11 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
#endregion
#endregion
// Roots.
[Explicit]
[TestCase(0xFFFFFFFDu)] // Roots.
[TestCase(0xFFFFFFFDu)]
[TestCase(0x00000005u)]
public void Misc1(uint a)
{
@@ -196,25 +197,26 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetX(0), Is.Zero);
}
// 18 integer solutions.
[Explicit]
[TestCase(-20f, -5f)] // 18 integer solutions.
[TestCase(-20f, -5f)]
[TestCase(-12f, -6f)]
[TestCase(-12f, 3f)]
[TestCase( -8f, -8f)]
[TestCase( -6f, -12f)]
[TestCase( -5f, -20f)]
[TestCase( -4f, 2f)]
[TestCase( -3f, 12f)]
[TestCase( -2f, 4f)]
[TestCase( 2f, -4f)]
[TestCase( 3f, -12f)]
[TestCase( 4f, -2f)]
[TestCase( 5f, 20f)]
[TestCase( 6f, 12f)]
[TestCase( 8f, 8f)]
[TestCase( 12f, -3f)]
[TestCase( 12f, 6f)]
[TestCase( 20f, 5f)]
[TestCase(-8f, -8f)]
[TestCase(-6f, -12f)]
[TestCase(-5f, -20f)]
[TestCase(-4f, 2f)]
[TestCase(-3f, 12f)]
[TestCase(-2f, 4f)]
[TestCase(2f, -4f)]
[TestCase(3f, -12f)]
[TestCase(4f, -2f)]
[TestCase(5f, 20f)]
[TestCase(6f, 12f)]
[TestCase(8f, 8f)]
[TestCase(12f, -3f)]
[TestCase(12f, 6f)]
[TestCase(20f, 5f)]
public void Misc2(float a, float b)
{
// 1 / ((1 / a + 1 / b) ^ 2) = 16
@@ -242,25 +244,26 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetV(0).As<float>(), Is.EqualTo(16f));
}
// 18 integer solutions.
[Explicit]
[TestCase(-20d, -5d)] // 18 integer solutions.
[TestCase(-20d, -5d)]
[TestCase(-12d, -6d)]
[TestCase(-12d, 3d)]
[TestCase( -8d, -8d)]
[TestCase( -6d, -12d)]
[TestCase( -5d, -20d)]
[TestCase( -4d, 2d)]
[TestCase( -3d, 12d)]
[TestCase( -2d, 4d)]
[TestCase( 2d, -4d)]
[TestCase( 3d, -12d)]
[TestCase( 4d, -2d)]
[TestCase( 5d, 20d)]
[TestCase( 6d, 12d)]
[TestCase( 8d, 8d)]
[TestCase( 12d, -3d)]
[TestCase( 12d, 6d)]
[TestCase( 20d, 5d)]
[TestCase(-8d, -8d)]
[TestCase(-6d, -12d)]
[TestCase(-5d, -20d)]
[TestCase(-4d, 2d)]
[TestCase(-3d, 12d)]
[TestCase(-2d, 4d)]
[TestCase(2d, -4d)]
[TestCase(3d, -12d)]
[TestCase(4d, -2d)]
[TestCase(5d, 20d)]
[TestCase(6d, 12d)]
[TestCase(8d, 8d)]
[TestCase(12d, -3d)]
[TestCase(12d, 6d)]
[TestCase(20d, 5d)]
public void Misc3(double a, double b)
{
// 1 / ((1 / a + 1 / b) ^ 2) = 16
@@ -291,7 +294,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Ignore("The Tester supports only one return point.")]
public void MiscF([Range(0u, 92u, 1u)] uint a)
{
ulong Fn(uint n)
static ulong Fn(uint n)
{
ulong x = 0, y = 1, z;
@@ -395,9 +398,9 @@ namespace Ryujinx.Tests.Cpu
}
[Explicit]
[TestCase( 0ul)]
[TestCase( 1ul)]
[TestCase( 2ul)]
[TestCase(0ul)]
[TestCase(1ul)]
[TestCase(2ul)]
[TestCase(42ul)]
public void SanityCheck(ulong a)
{

View File

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

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
{
#if Mul32
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Smlabb_Smlabt_Smlatb_Smlatt_()
{
return new[]
@@ -49,10 +49,10 @@ namespace Ryujinx.Tests.Cpu
0xe12000e0u, // SMULWT R0, R0, R0
};
}
#endregion
#endregion
[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(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint ra,
@@ -74,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint ra,
@@ -96,7 +96,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd,
@@ -115,7 +115,7 @@ namespace Ryujinx.Tests.Cpu
}
[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(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd,

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,14 @@ namespace Ryujinx.Tests.Cpu
{
#if Simd32
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Vabs_Vneg_Vpaddl_I_()
{
return new[]
{
0xf3b10300u, // VABS.S8 D0, D0
0xf3b10380u, // VNEG.S8 D0, D0
0xf3b00200u // VPADDL.S8 D0, D0
0xf3b00200u, // VPADDL.S8 D0, D0
};
}
@@ -27,18 +27,20 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0xf3b90700u, // VABS.F32 D0, D0
0xf3b90780u // VNEG.F32 D0, D0
0xf3b90780u, // VNEG.F32 D0, D0
};
}
#endregion
#endregion
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _8B4H2S_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _1S_F_()
@@ -52,19 +54,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -94,19 +96,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -135,19 +137,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -173,13 +175,13 @@ namespace Ryujinx.Tests.Cpu
(cnt << 24) | (cnt << 16) | (cnt << 08) | cnt;
}
}
#endregion
#endregion
private const int RndCnt = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = false;
private static readonly bool _noNaNs = false;
[Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")]
public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode,
@@ -223,8 +225,10 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rm >>= 1;
rm <<= 1;
}
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
@@ -252,8 +256,10 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rm >>= 1;
rm <<= 1;
}
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)] uint size) // <S8, S16, S32>
{
rm >>= 1; rm <<= 1;
rm >>= 1;
rm <<= 1;
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
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -87,8 +86,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode(
opcode,
v0: rn == 0u ? v : default(V128),
v1: rn == 1u ? v : default(V128));
v0: rn == 0u ? v : default,
v1: rn == 1u ? v : default);
Assert.Multiple(() =>
{
@@ -122,8 +121,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode(
opcode,
v0: rn == 0u ? v : default(V128),
v1: rn == 1u ? v : default(V128));
v0: rn == 0u ? v : default,
v1: rn == 1u ? v : default);
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
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -92,8 +91,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode(
opcode,
v0: rm == 0u ? v : default(V128),
v1: rm == 2u ? v : default(V128),
v0: rm == 0u ? v : default,
v1: rm == 2u ? v : default,
runUnicorn: false);
Assert.Multiple(() =>
@@ -130,8 +129,8 @@ namespace Ryujinx.Tests.Cpu
ExecutionContext context = SingleOpcode(
opcode,
v0: rm == 0u ? v : default(V128),
v1: rm == 2u ? v : default(V128),
v0: rm == 0u ? v : default,
v1: rm == 2u ? v : default,
runUnicorn: false);
Assert.Multiple(() =>

View File

@@ -12,17 +12,21 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdCvt
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static uint[] _W_()
{
return new[] { 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
return new[] {
0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu,
};
}
private static ulong[] _X_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _1S_F_WX_()
@@ -62,19 +66,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -145,19 +149,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -188,9 +192,9 @@ namespace Ryujinx.Tests.Cpu
yield return rnd6;
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_AMPZ_SU_Gp_SW_()
{
return new[]
@@ -203,7 +207,7 @@ namespace Ryujinx.Tests.Cpu
0x1E280000u, // FCVTPS W0, S0
0x1E290000u, // FCVTPU 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
0x9E290000u, // FCVTPU 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
0x1E690000u, // FCVTPU 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
0x9E690000u, // FCVTPU X0, D0
0x9E780000u, // FCVTZS X0, D0
0x9E790000u // FCVTZU X0, D0
0x9E790000u, // FCVTZU X0, D0
};
}
@@ -260,7 +264,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
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[]
{
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[]
{
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[]
{
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[]
{
0x1E220000u, // SCVTF S0, W0
0x1E230000u // UCVTF S0, W0
0x1E230000u, // UCVTF S0, W0
};
}
@@ -305,7 +309,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0x1E620000u, // SCVTF D0, W0
0x1E630000u // UCVTF D0, W0
0x1E630000u, // UCVTF D0, W0
};
}
@@ -314,7 +318,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0x9E220000u, // SCVTF S0, X0
0x9E230000u // UCVTF S0, X0
0x9E230000u, // UCVTF S0, X0
};
}
@@ -323,7 +327,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0x9E620000u, // SCVTF D0, X0
0x9E630000u // UCVTF D0, X0
0x9E630000u, // UCVTF D0, X0
};
}
@@ -332,7 +336,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
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[]
{
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[]
{
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[]
{
0x9E420000u, // SCVTF D0, X0, #64
0x9E430000u // UCVTF D0, X0, #64
0x9E430000u, // UCVTF D0, X0, #64
};
}
#endregion
#endregion
private const int RndCnt = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = 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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -387,7 +392,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -403,7 +409,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -420,7 +427,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -436,7 +444,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -457,7 +466,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -477,7 +487,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -498,7 +509,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
@@ -518,7 +530,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_WS([ValueSource(nameof(_SU_Cvt_F_Gp_WS_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -535,7 +548,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_WD([ValueSource(nameof(_SU_Cvt_F_Gp_WD_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -552,7 +566,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_XS([ValueSource(nameof(_SU_Cvt_F_Gp_XS_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -569,7 +584,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void SU_Cvt_F_Gp_XD([ValueSource(nameof(_SU_Cvt_F_Gp_XD_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -586,7 +602,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -607,7 +624,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -628,7 +646,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
@@ -649,7 +668,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,

View File

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

View File

@@ -10,13 +10,15 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdExt
#region "ValueSource"
#region "ValueSource"
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
#endregion
#endregion
[Test, Pairwise, Description("EXT <Vd>.8B, <Vn>.8B, <Vm>.8B, #<index>")]
public void Ext_V_8B([Values(0u)] uint rd,

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdImm
#region "Helper methods"
#region "Helper methods"
// abcdefgh -> aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
private static ulong ExpandImm8(byte imm8)
{
@@ -43,19 +43,23 @@ namespace Ryujinx.Tests.Cpu
return imm8;
}
#endregion
#endregion
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<byte> _8BIT_IMM_()
@@ -87,15 +91,15 @@ namespace Ryujinx.Tests.Cpu
yield return ExpandImm8(imm8);
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Bic_Orr_Vi_16bit_()
{
return new[]
{
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[]
{
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[]
{
0x0F00F400u // FMOV V0.2S, #2.0
0x0F00F400u, // FMOV V0.2S, #2.0
};
}
@@ -120,7 +124,7 @@ namespace Ryujinx.Tests.Cpu
{
return new[]
{
0x4F00F400u // FMOV V0.4S, #2.0
0x4F00F400u, // FMOV V0.4S, #2.0
};
}
@@ -128,7 +132,7 @@ namespace Ryujinx.Tests.Cpu
{
return new[]
{
0x6F00F400u // FMOV V0.2D, #2.0
0x6F00F400u, // FMOV V0.2D, #2.0
};
}
@@ -136,7 +140,7 @@ namespace Ryujinx.Tests.Cpu
{
return new[]
{
0x0F00E400u // MOVI V0.8B, #0
0x0F00E400u, // MOVI V0.8B, #0
};
}
@@ -145,7 +149,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
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[]
{
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[]
{
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[]
{
0x2F00E400u // MOVI D0, #0
0x2F00E400u, // MOVI D0, #0
};
}
@@ -179,10 +183,10 @@ namespace Ryujinx.Tests.Cpu
{
return new[]
{
0x6F00E400u // MOVI V0.2D, #0
0x6F00E400u, // MOVI V0.2D, #0
};
}
#endregion
#endregion
private const int RndCntImm8 = 2;
private const int RndCntImm64 = 2;
@@ -229,7 +233,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void F_Mov_Vi_2S([ValueSource(nameof(_F_Mov_Vi_2S_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh)
{
@@ -246,7 +251,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void F_Mov_Vi_4S([ValueSource(nameof(_F_Mov_Vi_4S_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh)
{
@@ -260,7 +266,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit]
[Test, Pairwise]
[Explicit]
public void F_Mov_Vi_2D([ValueSource(nameof(_F_Mov_Vi_2D_))] uint opcodes,
[Range(0u, 255u, 1u)] uint abcdefgh)
{

View File

@@ -10,61 +10,77 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdIns
#region "ValueSource"
#region "ValueSource"
private static ulong[] _1D_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B4H_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B4H2S_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static uint[] _W_()
{
return new[] { 0x00000000u, 0x0000007Fu,
return new[] {
0x00000000u, 0x0000007Fu,
0x00000080u, 0x000000FFu,
0x00007FFFu, 0x00008000u,
0x0000FFFFu, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
0x80000000u, 0xFFFFFFFFu,
};
}
private static ulong[] _X_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
#endregion
#endregion
[Test, Pairwise, Description("DUP <Vd>.<T>, W<n>")]
public void Dup_Gp_W([Values(0u)] uint rd,

View File

@@ -10,17 +10,19 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdLogical32
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _8B4H2S_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_()
{
return new[]
@@ -32,7 +34,7 @@ namespace Ryujinx.Tests.Cpu
0xf2000110u, // VAND D0, D0, D0
0xf2300110u, // VORN 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)
0xf2800930u, // VBIC.I16 D0, #0 (A2)
0xf2800110u, // VORR.I32 D0, #0 (A1)
0xf2800910u // VORR.I16 D0, #0 (A2)
0xf2800910u, // VORR.I16 D0, #0 (A2)
};
}
#endregion
@@ -62,9 +64,12 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
}
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
@@ -97,7 +102,8 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rd >>= 1;
rd <<= 1;
}
opcode |= ((uint)imm & 0xf) << 0;
@@ -129,9 +135,12 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
}
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);

View File

@@ -10,10 +10,10 @@ namespace Ryujinx.Tests.Cpu
[Category("SimdMemory32")]
public sealed class CpuTestSimdMemory32 : CpuTest32
{
private static readonly uint TestOffset = DataBaseAddress + 0x500;
private static readonly uint _testOffset = DataBaseAddress + 0x500;
#if SimdMemory32
private uint[] _ldStModes =
private readonly uint[] _ldStModes =
{
// LD1
0b0111,
@@ -32,7 +32,7 @@ namespace Ryujinx.Tests.Cpu
// LD4
0b0000,
0b0001
0b0001,
};
[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);
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 & 0xf) << 12);
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();
}
@@ -85,9 +85,12 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0xf) << 12);
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();
}
@@ -116,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
CompareAgainstUnicorn();
}
@@ -139,16 +142,16 @@ namespace Ryujinx.Tests.Cpu
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 & 0xf) << 12);
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();
}
@@ -179,7 +182,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18);
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();
}
@@ -201,7 +204,7 @@ namespace Ryujinx.Tests.Cpu
// Note: 3rd 0 leaves a space for "D".
0b0100, // Increment after.
0b0101, // Increment after. (!)
0b1001 // Decrement before. (!)
0b1001, // Decrement before. (!)
};
opcode |= ((vldmModes[mode] & 15) << 21);
@@ -212,7 +215,11 @@ namespace Ryujinx.Tests.Cpu
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;
if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31.
@@ -227,7 +234,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= regs & 0xff;
SingleOpcode(opcode, r0: TestOffset, sp: TestOffset);
SingleOpcode(opcode, r0: _testOffset, sp: _testOffset);
CompareAgainstUnicorn();
}
@@ -262,7 +269,7 @@ namespace Ryujinx.Tests.Cpu
}
opcode |= imm & 0xff;
SingleOpcode(opcode, r0: TestOffset);
SingleOpcode(opcode, r0: _testOffset);
CompareAgainstUnicorn();
}
@@ -299,12 +306,12 @@ namespace Ryujinx.Tests.Cpu
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2);
SingleOpcode(opcode, r0: _testOffset, v0: vec1, v1: vec2);
CompareAgainstUnicorn();
}
private (V128, V128, V128, V128) GenerateTestVectors()
private static (V128, V128, V128, V128) GenerateTestVectors()
{
return (
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;
float[] data = new float[floatLength];

View File

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

View File

@@ -11,75 +11,93 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdReg
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _1B1H1S1D_()
{
return new[] { 0x0000000000000000ul, 0x000000000000007Ful,
return new[] {
0x0000000000000000ul, 0x000000000000007Ful,
0x0000000000000080ul, 0x00000000000000FFul,
0x0000000000007FFFul, 0x0000000000008000ul,
0x000000000000FFFFul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul,
0x7FFFFFFFFFFFFFFFul, 0x8000000000000000ul,
0xFFFFFFFFFFFFFFFFul };
0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _1D_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _1H1S_()
{
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul,
return new[] {
0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul,
0x000000007FFFFFFFul, 0x0000000080000000ul,
0x00000000FFFFFFFFul };
0x00000000FFFFFFFFul,
};
}
private static ulong[] _4H2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H2S1D_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B1D_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B4H2S_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B4H2S1D_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _1S_F_()
@@ -93,19 +111,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -135,19 +153,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -176,19 +194,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -205,9 +223,9 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2;
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S_()
{
return new[]
@@ -218,7 +236,7 @@ namespace Ryujinx.Tests.Cpu
0x1E220820u, // FMUL S0, S1, S2
0x5E22DC20u, // FMULX 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
0x5E62DC20u, // FMULX 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
0x2E20DC00u, // FMUL 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
0x6E60DC00u, // FMUL 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
0x5E22E420u, // FCMEQ 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
0x5E62E420u, // FCMEQ 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
0x0E20E400u, // FCMEQ 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
0x4E60E400u, // FCMEQ 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[]
{
0x1E222020u, // FCMP S1, S2
0x1E222030u // FCMPE S1, S2
0x1E222030u, // FCMPE S1, S2
};
}
@@ -326,7 +344,7 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
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
0x1F028C20u, // FMSUB 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
0x1F428C20u, // FMSUB 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
0x1E226820u, // FMAXNM 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
0x1E626820u, // FMAXNM 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
0x0EA0C400u, // FMINNM 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
0x4EE0C400u, // FMINNM 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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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
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
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
0x5E002000u, // SHA1M 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
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
0x2E20A400u, // UMAXP 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
0x2E208000u, // UMLAL 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
0x6E208000u, // UMLAL2 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[]
{
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
0x2E204C00u, // UQSHL 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
0x6E204C00u, // UQSHL 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 static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = false;
private static readonly bool _noNaNs = false;
[Test, Pairwise, Description("ADD <V><d>, <V><n>, <V><m>")]
public void Add_S_D([Values(0u)] uint rd,
@@ -1362,7 +1380,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b)
@@ -1382,7 +1401,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b)
@@ -1402,7 +1422,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1429,7 +1450,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1454,7 +1476,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b)
@@ -1473,7 +1496,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b)
@@ -1492,7 +1516,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1518,7 +1543,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1542,7 +1568,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b)
@@ -1560,7 +1587,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b)
@@ -1578,7 +1606,9 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
@@ -1600,7 +1630,9 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
@@ -1622,7 +1654,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b)
@@ -1642,7 +1675,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b)
@@ -1662,7 +1696,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1689,7 +1724,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1714,7 +1750,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1741,7 +1779,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1766,7 +1806,9 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b)
@@ -1786,7 +1828,9 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b)
@@ -1806,7 +1850,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -1833,7 +1879,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -2322,8 +2370,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H8H, 4H4S4S, 2S2D2D>
{
uint opcode = 0x0E201000; // SADDW V0.8H, V0.8H, V0.8B
@@ -2344,8 +2392,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H8H, 8H4S4S, 4S2D2D>
{
uint opcode = 0x4E201000; // SADDW2 V0.8H, V0.8H, V0.16B
@@ -2978,8 +3026,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H8H, 4H4S4S, 2S2D2D>
{
uint opcode = 0x0E203000; // SSUBW V0.8H, V0.8H, V0.8B
@@ -3000,8 +3048,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H8H, 8H4S4S, 4S2D2D>
{
uint opcode = 0x4E203000; // SSUBW2 V0.8H, V0.8H, V0.16B
@@ -3438,8 +3486,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H8H, 4H4S4S, 2S2D2D>
{
uint opcode = 0x2E201000; // UADDW V0.8H, V0.8H, V0.8B
@@ -3460,8 +3508,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H8H, 8H4S4S, 4S2D2D>
{
uint opcode = 0x6E201000; // UADDW2 V0.8H, V0.8H, V0.16B
@@ -3790,8 +3838,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H8H, 4H4S4S, 2S2D2D>
{
uint opcode = 0x2E203000; // USUBW V0.8H, V0.8H, V0.8B
@@ -3812,8 +3860,8 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_4H2S1D_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_4H2S1D_))][Random(RndCnt)] ulong a,
[ValueSource(nameof(_8B4H2S_))][Random(RndCnt)] ulong b,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H8H, 8H4S4S, 4S2D2D>
{
uint opcode = 0x6E203000; // USUBW2 V0.8H, V0.8H, V0.16B

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdReg32
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _V_Add_Sub_Long_Wide_I_()
{
return new[]
@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Cpu
0xf2800000u, // VADDL.S8 Q0, D0, D0
0xf2800100u, // VADDW.S8 Q0, Q0, 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
0xEEA00A40u, // VFMS. 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
0xEEA00B40u, // VFMS. 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[]
{
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
0xEE000A40u, // VMLS. 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
0xEE000B40u, // VMLS. 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[]
{
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
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[]
{
0xf2000b10u // VPADD.I8 D0, D0, D0
0xf2000b10u, // VPADD.I8 D0, D0, D0
};
}
@@ -119,26 +119,30 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0xf2000050u, // VQADD.S8 Q0, Q0, Q0
0xf2000250u // VQSUB.S8 Q0, Q0, Q0
0xf2000250u, // VQSUB.S8 Q0, Q0, Q0
};
}
#endregion
#endregion
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _8B1D_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B4H2S1D_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _1S_F_()
@@ -152,19 +156,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -194,19 +198,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -235,19 +239,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -264,13 +268,13 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2;
}
}
#endregion
#endregion
private const int RndCnt = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = false;
private static readonly bool _noNaNs = false;
[Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")]
public void Sha256h_V([Values(0xF3000C40u)] uint opcode,
@@ -425,8 +429,10 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24;
}
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -480,7 +486,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rn,
@@ -501,7 +509,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rn,
@@ -520,7 +530,9 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise] [Explicit] // Fused.
// Fused.
[Test, Pairwise]
[Explicit]
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 rn,
@@ -535,9 +547,12 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
}
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
@@ -552,7 +567,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rn,
@@ -573,7 +589,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rn,
@@ -678,7 +695,8 @@ namespace Ryujinx.Tests.Cpu
uint opcode = 0xf2800e00u; // VMULL.P8 Q0, D0, D0
rd >>= 1; rd <<= 1;
rd >>= 1;
rd <<= 1;
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
@@ -836,9 +854,12 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24;
}
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -864,9 +885,12 @@ namespace Ryujinx.Tests.Cpu
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
[Values(1u, 2u)] uint size) // <S16, S32>
{
rd >>= 1; rd <<= 1;
rn >>= 1; rn <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rn >>= 1;
rn <<= 1;
rm >>= 1;
rm <<= 1;
uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0

View File

@@ -10,21 +10,25 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdRegElem
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_()
{
return new[]
@@ -33,7 +37,7 @@ namespace Ryujinx.Tests.Cpu
0x2F404000u, // MLS 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]
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]
0x0F808000u, // MUL 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]
0x2F402000u, // UMLAL 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,10 +75,10 @@ namespace Ryujinx.Tests.Cpu
0x0F80A000u, // SMULL 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]
0x2F80A000u // UMULL V0.2D, V0.2S, V0.S[0]
0x2F80A000u, // UMULL V0.2D, V0.2S, V0.S[0]
};
}
#endregion
#endregion
[Test, Pairwise]

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdRegElemF
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static IEnumerable<ulong> _1S_F_()
{
yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x00000000007FFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x0000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0x00000000FF800000ul; // -Infinity
yield return 0x000000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
@@ -65,19 +65,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -106,19 +106,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -135,15 +135,15 @@ namespace Ryujinx.Tests.Cpu
yield return rnd2;
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _F_Mla_Mls_Se_S_()
{
return new[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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 static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = 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,
[ValueSource(nameof(_1S_F_))] ulong z,
[ValueSource(nameof(_1S_F_))] ulong a,
@@ -243,7 +245,9 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong z,
[ValueSource(nameof(_1D_F_))] ulong a,
@@ -268,7 +272,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -300,7 +306,9 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -329,7 +337,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b,
@@ -355,7 +364,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
@@ -380,7 +390,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -412,7 +423,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,

View File

@@ -12,41 +12,53 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdShImm
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _1D_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _1H_()
{
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul };
return new[] {
0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul,
};
}
private static ulong[] _1S_()
{
return new[] { 0x0000000000000000ul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul,
};
}
private static ulong[] _2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _2S_F_W_()
@@ -73,19 +85,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000080000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFF800000FF800000ul; // -Infinity
yield return 0x7F8000007F800000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
@@ -133,19 +145,19 @@ namespace Ryujinx.Tests.Cpu
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
if (!NoZeros)
if (!_noZeros)
{
yield return 0x8000000000000000ul; // -Zero
yield return 0x0000000000000000ul; // +Zero
}
if (!NoInfs)
if (!_noInfs)
{
yield return 0xFFF0000000000000ul; // -Infinity
yield return 0x7FF0000000000000ul; // +Infinity
}
if (!NoNaNs)
if (!_noNaNs)
{
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
@@ -170,15 +182,15 @@ namespace Ryujinx.Tests.Cpu
yield return rnd4;
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_Z_SU_V_Fixed_2S_4S_()
{
return new[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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[]
{
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
0x7F403400u, // URSRA 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
0x2F083400u, // URSRA 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
0x2F103400u, // URSRA 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
0x2F203400u, // URSRA 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
0x6F403400u, // URSRA 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[]
{
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[]
{
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[]
{
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
0x5F089400u, // SQSHRN 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
0x5F109400u, // SQSHRN 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
0x5F209400u, // SQSHRN 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
0x0F089400u, // SQSHRN 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
0x0F109400u, // SQSHRN 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
0x0F209400u, // SQSHRN 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 static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
private static readonly bool _noZeros = false;
private static readonly bool _noInfs = 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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -514,7 +527,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -535,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1S_))] ulong a,
[Values(1u, 32u)] uint fBits)
@@ -553,7 +568,8 @@ namespace Ryujinx.Tests.Cpu
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,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint fBits)
@@ -571,7 +587,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
@@ -594,7 +611,8 @@ namespace Ryujinx.Tests.Cpu
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,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,

View File

@@ -10,30 +10,41 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdShImm32
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _1D_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _2S_()
{
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[]
{
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _4H_()
{
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[]
{
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[]
{
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _Vshr_Imm_SU8_()
{
return new[]
@@ -41,7 +52,7 @@ namespace Ryujinx.Tests.Cpu
0xf2880010u, // VSHR.S8 D0, D0, #8
0xf2880110u, // VSRA.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
0xf2900110u, // VSRA.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
0xf2a00110u, // VSRA.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
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)
0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
0xf2800850u // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
0xf2800850u, // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
};
}
@@ -92,10 +103,10 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
0xf3800850u, // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
};
}
#endregion
#endregion
private const int RndCnt = 2;
private const int RndCntShiftImm = 2;
@@ -171,8 +182,10 @@ namespace Ryujinx.Tests.Cpu
{
opcode |= 1 << 6;
rd >>= 1; rd <<= 1;
rm >>= 1; rm <<= 1;
rd >>= 1;
rd <<= 1;
rm >>= 1;
rm <<= 1;
}
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);

View File

@@ -11,12 +11,12 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdTbl
#region "Helper methods"
#region "Helper methods"
private static ulong GenIdxsForTbls(int regs)
{
const byte IdxInRngMin = 0;
byte idxInRngMax = (byte)((16 * regs) - 1);
byte idxOutRngMin = (byte) (16 * regs);
byte idxOutRngMin = (byte)(16 * regs);
const byte IdxOutRngMax = 255;
ulong idxs = 0ul;
@@ -33,13 +33,15 @@ namespace Ryujinx.Tests.Cpu
return idxs;
}
#endregion
#endregion
#region "ValueSource (Types)"
#region "ValueSource (Types)"
private static ulong[] _8B_()
{
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] {
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
};
}
private static IEnumerable<ulong> _GenIdxsForTbl1_()
@@ -93,15 +95,15 @@ namespace Ryujinx.Tests.Cpu
yield return GenIdxsForTbls(regs: 4);
}
}
#endregion
#endregion
#region "ValueSource (Opcodes)"
#region "ValueSource (Opcodes)"
private static uint[] _SingleRegisterTable_V_8B_16B_()
{
return new[]
{
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[]
{
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[]
{
0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
0x0E005000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
0x0E005000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
};
}
@@ -128,10 +130,10 @@ namespace Ryujinx.Tests.Cpu
return new[]
{
0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
0x0E006000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
0x0E006000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
};
}
#endregion
#endregion
private const int RndCntIdxs = 2;

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
using NUnit.Framework;
using System;
namespace Ryujinx.Tests.Cpu
{
@@ -14,70 +15,70 @@ namespace Ryujinx.Tests.Cpu
public static readonly PrecomputedMemoryThumbTestCase[] ImmTestCases =
{
// STRB (imm8)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -85,35 +86,35 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b86, Value: 0x2bac) },
},
// STRB (imm12)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c5a, Value: 0x005a) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -121,70 +122,70 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fe2, Value: 0x2f00) },
},
// STRH (imm8)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -192,35 +193,35 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2186, Value: 0xf886), (Address: 0x2188, Value: 0x2128) },
},
// STRH (imm12)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -228,70 +229,70 @@ namespace Ryujinx.Tests.Cpu
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22cc, Value: 0x2000) },
},
// STR (imm8)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -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) },
},
// STR (imm12)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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) },
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
@@ -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) },
},
// LDRB (imm8)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
// LDRB (imm12)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
// LDR (imm8)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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)
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
MemoryDelta = new (ulong Address, ushort Value)[] {},
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
},
new PrecomputedMemoryThumbTestCase()
new()
{
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 },
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 },
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 },
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
{
#pragma warning disable IDE0052 // Remove unread private member
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.
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private float GetDenormal()
private static float GetDenormal()
{
return BitConverter.Int32BitsToSingle(1);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private float GetZero()
private static float GetZero()
{
return BitConverter.Int32BitsToSingle(0);
}
@@ -53,7 +55,7 @@ namespace Ryujinx.Tests.Cpu
if (test < 4f)
{
throw new System.Exception("Sanity check.");
throw new Exception("Sanity check.");
}
isFz = GetDenormal() + GetZero() == 0f;
@@ -62,7 +64,7 @@ namespace Ryujinx.Tests.Cpu
{
if (test >= 4f)
{
throw new System.Exception("Always throws.");
throw new Exception("Always throws.");
}
}
catch

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Collections
[Test]
public void EnsureAddIntegrity()
{
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
TreeDictionary<int, int> dictionary = new();
Assert.AreEqual(dictionary.Count, 0);
@@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Collections
[Test]
public void EnsureRemoveIntegrity()
{
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
TreeDictionary<int, int> dictionary = new();
Assert.AreEqual(dictionary.Count, 0);
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Collections
[Test]
public void EnsureOverwriteIntegrity()
{
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
TreeDictionary<int, int> dictionary = new();
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();
NsoReader reader = new NsoReader();
NsoReader reader = new();
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
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.Threading;
using Path = System.IO.Path;
using TimeSpan = System.TimeSpan;
namespace Ryujinx.Ui.App.Common
{
@@ -44,8 +45,8 @@ namespace Ryujinx.Ui.App.Common
private Language _desiredTitleLanguage;
private CancellationTokenSource _cancellationToken;
private static readonly ApplicationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static readonly TitleUpdateMetadataJsonSerializerContext TitleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
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",
FileSizeBytes = fileSize,
Path = applicationPath,
ControlHolder = controlHolder
ControlHolder = controlHolder,
};
numApplicationsLoaded++;
OnApplicationAdded(new ApplicationAddedEventArgs()
OnApplicationAdded(new ApplicationAddedEventArgs
{
AppData = data
AppData = data,
});
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
{
NumAppsFound = numApplicationsFound,
NumAppsLoaded = numApplicationsLoaded
NumAppsLoaded = numApplicationsLoaded,
});
}
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
{
NumAppsFound = numApplicationsFound,
NumAppsLoaded = numApplicationsLoaded
NumAppsLoaded = numApplicationsLoaded,
});
}
finally
@@ -508,7 +509,7 @@ namespace Ryujinx.Ui.App.Common
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 metadataFile = Path.Combine(metadataFolder, "metadata.json");
@@ -521,12 +522,12 @@ namespace Ryujinx.Ui.App.Common
appMetadata = new ApplicationMetadata();
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata);
JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
}
try
{
appMetadata = JsonHelper.DeserializeFromFile(metadataFile, SerializerContext.ApplicationMetadata);
appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata);
}
catch (JsonException)
{
@@ -539,7 +540,7 @@ namespace Ryujinx.Ui.App.Common
{
modifyFunction(appMetadata);
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata);
JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
}
return appMetadata;
@@ -703,7 +704,7 @@ namespace Ryujinx.Ui.App.Common
}
}
}
catch(Exception)
catch (Exception)
{
Logger.Warning?.Print(LogClass.Application, $"Could not retrieve a valid icon for the app. Default icon will be used. Errored File: {applicationPath}");
}
@@ -713,7 +714,7 @@ namespace Ryujinx.Ui.App.Common
private static string ConvertSecondsToFormattedString(double seconds)
{
System.TimeSpan time = System.TimeSpan.FromSeconds(seconds);
TimeSpan time = TimeSpan.FromSeconds(seconds);
string timeString;
if (time.Days != 0)
@@ -840,7 +841,7 @@ namespace Ryujinx.Ui.App.Common
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);
@@ -884,7 +885,7 @@ namespace Ryujinx.Ui.App.Common
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);
@@ -925,12 +926,12 @@ namespace Ryujinx.Ui.App.Common
if (File.Exists(titleUpdateMetadataPath))
{
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, TitleSerializerContext.TitleUpdateMetadata).Selected;
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
if (File.Exists(updatePath))
{
FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
PartitionFileSystem nsp = new(file.AsStorage());
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,
OpenAl,
SoundIo,
SDL2
SDL2,
}
}

View File

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

View File

@@ -278,7 +278,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableFsAccessLog = new ReactiveObject<bool>();
FilteredClasses = new ReactiveObject<LogClass[]>();
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>();
}
}
@@ -370,27 +370,27 @@ namespace Ryujinx.Ui.Common.Configuration
TimeZone = new ReactiveObject<string>();
SystemTimeOffset = new ReactiveObject<long>();
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc));
EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks));
EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend));
AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam));
ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioVolume));
AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume));
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()
{
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale));
ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy));
MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy));
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>();
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache));
EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend));
GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableMacroHLE));
EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
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.Event += static (sender, e) => LogValueChange(sender, e, nameof(ScalingFilter));
ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter));
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()
{
ConfigurationFileFormat configurationFile = new ConfigurationFileFormat
ConfigurationFileFormat configurationFile = new()
{
Version = ConfigurationFileFormat.CurrentVersion,
BackendThreading = Graphics.BackendThreading,
@@ -688,12 +688,12 @@ namespace Ryujinx.Ui.Common.Configuration
LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
FileExtColumn = Ui.GuiColumns.FileExtColumn,
FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
PathColumn = Ui.GuiColumns.PathColumn
PathColumn = Ui.GuiColumns.PathColumn,
},
ColumnSort = new ColumnSort
{
SortColumnId = Ui.ColumnSort.SortColumnId,
SortAscending = Ui.ColumnSort.SortAscending
SortAscending = Ui.ColumnSort.SortAscending,
},
GameDirs = Ui.GameDirs,
ShownFileTypes = new ShownFileTypes
@@ -732,7 +732,7 @@ namespace Ryujinx.Ui.Common.Configuration
InputConfig = Hid.InputConfig,
GraphicsBackend = Graphics.GraphicsBackend,
PreferredGpu = Graphics.PreferredGpu,
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
};
return configurationFile;
@@ -767,7 +767,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration.Value = true;
CheckUpdatesOnStart.Value = true;
ShowConfirmExit.Value = true;
HideCursor.Value = Ryujinx.Common.Configuration.HideCursorMode.Never;
HideCursor.Value = HideCursorMode.Never;
Graphics.EnableVsync.Value = true;
Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false;
@@ -833,7 +833,7 @@ namespace Ryujinx.Ui.Common.Configuration
ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound,
VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound
VolumeDown = Key.Unbound,
};
Hid.InputConfig.Value = new List<InputConfig>
{
@@ -854,9 +854,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonL = Key.E,
ButtonZl = Key.Q,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound
ButtonSr = Key.Unbound,
},
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.W,
@@ -865,7 +864,6 @@ namespace Ryujinx.Ui.Common.Configuration
StickRight = Key.D,
StickButton = Key.F,
},
RightJoycon = new RightJoyconCommonConfig<Key>
{
ButtonA = Key.Z,
@@ -876,9 +874,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonR = Key.U,
ButtonZr = Key.O,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound
ButtonSr = Key.Unbound,
},
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.I,
@@ -886,8 +883,8 @@ namespace Ryujinx.Ui.Common.Configuration
StickLeft = Key.J,
StickRight = Key.L,
StickButton = Key.H,
}
}
},
},
};
}
@@ -958,12 +955,12 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.ColumnSort = new ColumnSort
{
SortColumnId = 0,
SortAscending = false
SortAscending = false,
};
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVsync = Key.F1
ToggleVsync = Key.F1,
};
configurationFileUpdated = true;
@@ -1074,9 +1071,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonL = Key.E,
ButtonZl = Key.Q,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound
ButtonSr = Key.Unbound,
},
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.W,
@@ -1085,7 +1081,6 @@ namespace Ryujinx.Ui.Common.Configuration
StickRight = Key.D,
StickButton = Key.F,
},
RightJoycon = new RightJoyconCommonConfig<Key>
{
ButtonA = Key.Z,
@@ -1096,9 +1091,8 @@ namespace Ryujinx.Ui.Common.Configuration
ButtonR = Key.U,
ButtonZr = Key.O,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound
ButtonSr = Key.Unbound,
},
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.I,
@@ -1106,8 +1100,8 @@ namespace Ryujinx.Ui.Common.Configuration
StickLeft = Key.J,
StickRight = Key.L,
StickButton = Key.H,
}
}
},
},
};
configurationFileUpdated = true;
@@ -1145,7 +1139,7 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVsync = Key.F1,
Screenshot = Key.F8
Screenshot = Key.F8,
};
configurationFileUpdated = true;
@@ -1159,7 +1153,7 @@ namespace Ryujinx.Ui.Common.Configuration
{
ToggleVsync = Key.F1,
Screenshot = Key.F8,
ShowUi = Key.F4
ShowUi = Key.F4,
};
configurationFileUpdated = true;
@@ -1169,7 +1163,7 @@ namespace Ryujinx.Ui.Common.Configuration
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
foreach(InputConfig config in configurationFileFormat.InputConfig)
foreach (InputConfig config in configurationFileFormat.InputConfig)
{
if (config is StandardControllerInputConfig controllerConfig)
{
@@ -1177,7 +1171,7 @@ namespace Ryujinx.Ui.Common.Configuration
{
EnableRumble = false,
StrongRumble = 1f,
WeakRumble = 1f
WeakRumble = 1f,
};
}
}
@@ -1203,7 +1197,7 @@ namespace Ryujinx.Ui.Common.Configuration
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
Pause = Key.F5
Pause = Key.F5,
};
configurationFileUpdated = true;
@@ -1219,7 +1213,7 @@ namespace Ryujinx.Ui.Common.Configuration
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = Key.F2
ToggleMute = Key.F2,
};
configurationFileFormat.AudioVolume = 1;
@@ -1295,7 +1289,7 @@ namespace Ryujinx.Ui.Common.Configuration
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound
ResScaleDown = Key.Unbound,
};
configurationFileUpdated = true;
@@ -1326,7 +1320,7 @@ namespace Ryujinx.Ui.Common.Configuration
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound
VolumeDown = Key.Unbound,
};
}
@@ -1366,7 +1360,7 @@ namespace Ryujinx.Ui.Common.Configuration
XCI = true,
NCA = true,
NRO = true,
NSO = true
NSO = true,
};
configurationFileUpdated = true;
@@ -1499,7 +1493,7 @@ namespace Ryujinx.Ui.Common.Configuration
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}");
}

View File

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

View File

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

View File

@@ -19,19 +19,19 @@ namespace Ryujinx.Ui.Common
Assets = new Assets
{
LargeImageKey = "ryujinx",
LargeImageText = Description
LargeImageText = Description,
},
Details = "Main Menu",
State = "Idling",
Timestamps = Timestamps.Now,
Buttons = new Button[]
Buttons = new[]
{
new Button()
new Button
{
Label = "Website",
Url = "https://ryujinx.org/"
}
}
Url = "https://ryujinx.org/",
},
},
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
@@ -74,14 +74,14 @@ namespace Ryujinx.Ui.Common
Details = $"Playing {titleName}",
State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
Timestamps = Timestamps.Now,
Buttons = new Button[]
Buttons = new[]
{
new Button()
new Button
{
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.NRO => config.NRO.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 =
{
FileName = PkExecPath,
ArgumentList = { "sh", "-c", command }
}
ArgumentList = { "sh", "-c", command },
},
};
process.Start();

View File

@@ -1,8 +1,6 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
namespace Ryujinx.Ui.Common.Helper
{
@@ -12,44 +10,109 @@ namespace Ryujinx.Ui.Common.Helper
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
[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)]
public static partial IntPtr objc_getClass(string name);
private static partial IntPtr objc_getClass(string name);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector);
private static partial void objc_msgSend(IntPtr receiver, Selector selector);
[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)]
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)]
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)]
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")]
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")]
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)]
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")]
[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 unsafe Selector(string name)
private Selector(string name)
{
SelPtr = sel_getUid(name);
}
@@ -57,7 +120,7 @@ namespace Ryujinx.Ui.Common.Helper
public static implicit operator Selector(string value) => new(value);
}
public struct NSString
public readonly struct NSString
{
public readonly IntPtr StrPtr;

View File

@@ -9,13 +9,13 @@ namespace Ryujinx.Ui.Common.Helper
public static partial class OpenHelper
{
[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)]
public static partial void ILFree(IntPtr pidlList);
private static partial void ILFree(IntPtr pidlList);
[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)
{
@@ -25,7 +25,7 @@ namespace Ryujinx.Ui.Common.Helper
{
FileName = path,
UseShellExecute = true,
Verb = "open"
Verb = "open",
});
}
else
@@ -56,16 +56,16 @@ namespace Ryujinx.Ui.Common.Helper
else if (OperatingSystem.IsMacOS())
{
ObjectiveC.NSString nsStringPath = new(path);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "fileURLWithPath:", nsStringPath);
ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
IntPtr nsArray = ObjectiveC.objc_getClass("NSArray");
IntPtr urlArray = ObjectiveC.IntPtr_objc_msgSend(nsArray, "arrayWithObject:", urlPtr);
ObjectiveC.Object nsArray = new("NSArray");
ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
ObjectiveC.Object nsWorkspace = new("NSWorkspace");
ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
ObjectiveC.objc_msgSend(sharedWorkspace, "activateFileViewerSelectingURLs:", urlArray);
sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray);
}
else if (OperatingSystem.IsLinux())
{
@@ -95,13 +95,13 @@ namespace Ryujinx.Ui.Common.Helper
else if (OperatingSystem.IsMacOS())
{
ObjectiveC.NSString nsStringPath = new(url);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "URLWithString:", nsStringPath);
ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
ObjectiveC.Object nsWorkspace = new("NSWorkspace");
ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
ObjectiveC.bool_objc_msgSend(sharedWorkspace, "openURL:", urlPtr);
sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr);
}
else
{

View File

@@ -20,13 +20,11 @@ namespace Ryujinx.Ui.Common.Helper
return true;
}
else
{
error = UserError.NoFirmware;
return false;
}
}
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);
}
else
{
error = UserError.ApplicationNotFound;
return false;
}
}
}
}

View File

@@ -29,29 +29,39 @@ namespace Ryujinx.Ui.Common.Models.Amiibo
[JsonPropertyName("gamesSwitch")]
public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
public override string ToString()
public readonly override string ToString()
{
return Name;
}
public string GetId()
public readonly string GetId()
{
return Head + Tail;
}
public bool Equals(AmiiboApi other)
public readonly bool Equals(AmiiboApi other)
{
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);
}
public override int GetHashCode()
public readonly override int GetHashCode()
{
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>
/// An unknown error.
/// </summary>
Unknown = 0xDEAD
Unknown = 0xDEAD,
}
}

View File

@@ -874,7 +874,7 @@ namespace Ryujinx.Ui
DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
_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;
});
@@ -1017,7 +1017,7 @@ namespace Ryujinx.Ui
{
if (_gameLoaded)
{
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
{
if (appMetadata.LastPlayed.HasValue)
{
@@ -1156,7 +1156,7 @@ namespace Ryujinx.Ui
_tableStore.SetValue(treeIter, 0, newToggleValue);
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
{
appMetadata.Favorite = newToggleValue;
});