Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
79a1314ee4 | ||
|
e9848339dd | ||
|
6e28a4dd13 |
@@ -32,6 +32,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
|
using Ryujinx.Ui.App.Common;
|
||||||
using Ryujinx.Ui.Common;
|
using Ryujinx.Ui.Common;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
using Ryujinx.Ui.Common.Helper;
|
using Ryujinx.Ui.Common.Helper;
|
||||||
@@ -692,7 +693,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
DiscordIntegrationModule.SwitchToPlayingState(Device.Processes.ActiveApplication.ProgramIdText, Device.Processes.ActiveApplication.Name);
|
DiscordIntegrationModule.SwitchToPlayingState(Device.Processes.ActiveApplication.ProgramIdText, Device.Processes.ActiveApplication.Name);
|
||||||
|
|
||||||
_viewModel.ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata =>
|
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata =>
|
||||||
{
|
{
|
||||||
appMetadata.LastPlayed = DateTime.UtcNow;
|
appMetadata.LastPlayed = DateTime.UtcNow;
|
||||||
});
|
});
|
||||||
|
@@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
{
|
{
|
||||||
viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite;
|
viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite;
|
||||||
|
|
||||||
viewModel.ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.TitleId, appMetadata =>
|
ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.TitleId, appMetadata =>
|
||||||
{
|
{
|
||||||
appMetadata.Favorite = viewModel.SelectedApplication.Favorite;
|
appMetadata.Favorite = viewModel.SelectedApplication.Favorite;
|
||||||
});
|
});
|
||||||
|
@@ -3,6 +3,7 @@ using LibHac.Ncm;
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
using Ryujinx.Ui.App.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -74,7 +75,7 @@ namespace Ryujinx.Ava.UI.Models
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var appMetadata = MainWindow.MainWindowViewModel.ApplicationLibrary.LoadAndSaveMetaData(TitleIdString);
|
var appMetadata = ApplicationLibrary.LoadAndSaveMetaData(TitleIdString);
|
||||||
Title = appMetadata.Title ?? TitleIdString;
|
Title = appMetadata.Title ?? TitleIdString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -239,28 +239,28 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
IPlatformHandle CreateMacOS()
|
IPlatformHandle CreateMacOS()
|
||||||
{
|
{
|
||||||
// Create a new CAMetalLayer.
|
// Create a new CAMetalLayer.
|
||||||
IntPtr layerClass = ObjectiveC.objc_getClass("CAMetalLayer");
|
ObjectiveC.Object layerObject = new("CAMetalLayer");
|
||||||
IntPtr metalLayer = ObjectiveC.IntPtr_objc_msgSend(layerClass, "alloc");
|
ObjectiveC.Object metalLayer = layerObject.GetFromMessage("alloc");
|
||||||
ObjectiveC.objc_msgSend(metalLayer, "init");
|
metalLayer.SendMessage("init");
|
||||||
|
|
||||||
// Create a child NSView to render into.
|
// Create a child NSView to render into.
|
||||||
IntPtr nsViewClass = ObjectiveC.objc_getClass("NSView");
|
ObjectiveC.Object nsViewObject = new("NSView");
|
||||||
IntPtr child = ObjectiveC.IntPtr_objc_msgSend(nsViewClass, "alloc");
|
ObjectiveC.Object child = nsViewObject.GetFromMessage("alloc");
|
||||||
ObjectiveC.objc_msgSend(child, "init", new ObjectiveC.NSRect(0, 0, 0, 0));
|
child.SendMessage("init", new ObjectiveC.NSRect(0, 0, 0, 0));
|
||||||
|
|
||||||
// Make its renderer our metal layer.
|
// Make its renderer our metal layer.
|
||||||
ObjectiveC.objc_msgSend(child, "setWantsLayer:", 1);
|
child.SendMessage("setWantsLayer:", 1);
|
||||||
ObjectiveC.objc_msgSend(child, "setLayer:", metalLayer);
|
child.SendMessage("setLayer:", metalLayer);
|
||||||
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
|
metalLayer.SendMessage("setContentsScale:", Program.DesktopScaleFactor);
|
||||||
|
|
||||||
// Ensure the scale factor is up to date.
|
// Ensure the scale factor is up to date.
|
||||||
_updateBoundsCallback = rect =>
|
_updateBoundsCallback = rect =>
|
||||||
{
|
{
|
||||||
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
|
metalLayer.SendMessage("setContentsScale:", Program.DesktopScaleFactor);
|
||||||
};
|
};
|
||||||
|
|
||||||
IntPtr nsView = child;
|
IntPtr nsView = child.ObjPtr;
|
||||||
MetalLayer = metalLayer;
|
MetalLayer = metalLayer.ObjPtr;
|
||||||
NsView = nsView;
|
NsView = nsView;
|
||||||
|
|
||||||
return new PlatformHandle(nsView, "NSView");
|
return new PlatformHandle(nsView, "NSView");
|
||||||
|
@@ -7,15 +7,13 @@ namespace Ryujinx.Cpu
|
|||||||
{
|
{
|
||||||
public class AddressSpace : IDisposable
|
public class AddressSpace : IDisposable
|
||||||
{
|
{
|
||||||
private const ulong PageSize = 0x1000;
|
|
||||||
|
|
||||||
private const int DefaultBlockAlignment = 1 << 20;
|
private const int DefaultBlockAlignment = 1 << 20;
|
||||||
|
|
||||||
private enum MappingType : byte
|
private enum MappingType : byte
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Private,
|
Private,
|
||||||
Shared
|
Shared,
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Mapping : IntrusiveRedBlackTreeNode<Mapping>, IComparable<Mapping>
|
private class Mapping : IntrusiveRedBlackTreeNode<Mapping>, IComparable<Mapping>
|
||||||
@@ -37,7 +35,7 @@ namespace Ryujinx.Cpu
|
|||||||
ulong leftSize = splitAddress - Address;
|
ulong leftSize = splitAddress - Address;
|
||||||
ulong rightSize = EndAddress - splitAddress;
|
ulong rightSize = EndAddress - splitAddress;
|
||||||
|
|
||||||
Mapping left = new Mapping(Address, leftSize, Type);
|
Mapping left = new(Address, leftSize, Type);
|
||||||
|
|
||||||
Address = splitAddress;
|
Address = splitAddress;
|
||||||
Size = rightSize;
|
Size = rightSize;
|
||||||
@@ -93,7 +91,7 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
(var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
|
(var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
|
||||||
|
|
||||||
PrivateMapping left = new PrivateMapping(Address, leftSize, leftAllocation);
|
PrivateMapping left = new(Address, leftSize, leftAllocation);
|
||||||
|
|
||||||
Address = splitAddress;
|
Address = splitAddress;
|
||||||
Size = rightSize;
|
Size = rightSize;
|
||||||
@@ -181,7 +179,7 @@ namespace Ryujinx.Cpu
|
|||||||
{
|
{
|
||||||
addressSpace = null;
|
addressSpace = null;
|
||||||
|
|
||||||
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
const MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
||||||
|
|
||||||
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
|
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
|
||||||
|
|
||||||
@@ -391,8 +389,6 @@ namespace Ryujinx.Cpu
|
|||||||
ulong vaAligned = BitUtils.AlignDown(va, alignment);
|
ulong vaAligned = BitUtils.AlignDown(va, alignment);
|
||||||
ulong endAddressAligned = BitUtils.AlignUp(endAddress, alignment);
|
ulong endAddressAligned = BitUtils.AlignUp(endAddress, alignment);
|
||||||
|
|
||||||
ulong sizeAligned = endAddressAligned - vaAligned;
|
|
||||||
|
|
||||||
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
|
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
|
||||||
|
|
||||||
for (; map != null; map = map.Successor)
|
for (; map != null; map = map.Successor)
|
||||||
@@ -436,8 +432,6 @@ namespace Ryujinx.Cpu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong alignedSize = endAddressAligned - vaAligned;
|
|
||||||
|
|
||||||
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
|
PrivateMapping map = _privateTree.GetNode(new PrivateMapping(va, 1UL, default));
|
||||||
|
|
||||||
for (; map != null; map = map.Successor)
|
for (; map != null; map = map.Successor)
|
||||||
@@ -495,6 +489,8 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
_privateMemoryAllocator?.Dispose();
|
_privateMemoryAllocator?.Dispose();
|
||||||
Base.Dispose();
|
Base.Dispose();
|
||||||
Mirror.Dispose();
|
Mirror.Dispose();
|
||||||
|
@@ -42,6 +42,6 @@ namespace Ryujinx.Cpu.AppleHv.Arm
|
|||||||
WatchpointSameEl = 0b110101,
|
WatchpointSameEl = 0b110101,
|
||||||
BkptAarch32 = 0b111000,
|
BkptAarch32 = 0b111000,
|
||||||
VectorCatchAarch32 = 0b111010,
|
VectorCatchAarch32 = 0b111010,
|
||||||
BrkAarch64 = 0b111100
|
BrkAarch64 = 0b111100,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -4,7 +4,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
public class DummyDiskCacheLoadState : IDiskCacheLoadState
|
public class DummyDiskCacheLoadState : IDiskCacheLoadState
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0067
|
#pragma warning disable CS0067 // The event is never used
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public event Action<LoadState, int, int> StateChanged;
|
public event Action<LoadState, int, int> StateChanged;
|
||||||
#pragma warning restore CS0067
|
#pragma warning restore CS0067
|
||||||
|
@@ -18,18 +18,16 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
private const ulong AllocationGranule = 1UL << 14;
|
private const ulong AllocationGranule = 1UL << 14;
|
||||||
|
|
||||||
private readonly ulong _asBase;
|
private readonly ulong _asBase;
|
||||||
private readonly ulong _asSize;
|
|
||||||
private readonly ulong _backingSize;
|
private readonly ulong _backingSize;
|
||||||
|
|
||||||
private readonly HvAddressSpaceRange _userRange;
|
private readonly HvAddressSpaceRange _userRange;
|
||||||
private readonly HvAddressSpaceRange _kernelRange;
|
private readonly HvAddressSpaceRange _kernelRange;
|
||||||
|
|
||||||
private MemoryBlock _kernelCodeBlock;
|
private readonly MemoryBlock _kernelCodeBlock;
|
||||||
|
|
||||||
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
|
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
|
||||||
{
|
{
|
||||||
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
|
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
|
||||||
_asSize = asSize;
|
|
||||||
_backingSize = backingMemory.Size;
|
_backingSize = backingMemory.Size;
|
||||||
|
|
||||||
_userRange = new HvAddressSpaceRange(ipaAllocator);
|
_userRange = new HvAddressSpaceRange(ipaAllocator);
|
||||||
@@ -58,20 +56,20 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
_kernelCodeBlock.Write(KernelRegionEretOffset, 0xD69F03E0u); // ERET
|
_kernelCodeBlock.Write(KernelRegionEretOffset, 0xD69F03E0u); // ERET
|
||||||
|
|
||||||
ulong kernelCodePa = ipaAllocator.Allocate(AllocationGranule);
|
ulong kernelCodePa = ipaAllocator.Allocate(AllocationGranule);
|
||||||
HvApi.hv_vm_map((ulong)_kernelCodeBlock.Pointer, kernelCodePa, AllocationGranule, hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_EXEC).ThrowOnError();
|
HvApi.hv_vm_map((ulong)_kernelCodeBlock.Pointer, kernelCodePa, AllocationGranule, HvMemoryFlags.Read | HvMemoryFlags.Exec).ThrowOnError();
|
||||||
|
|
||||||
_kernelRange.Map(KernelRegionCodeOffset, kernelCodePa, KernelRegionCodeSize, ApFlags.UserNoneKernelReadExecute);
|
_kernelRange.Map(KernelRegionCodeOffset, kernelCodePa, KernelRegionCodeSize, ApFlags.UserNoneKernelReadExecute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitializeMmu(ulong vcpu)
|
public void InitializeMmu(ulong vcpu)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_VBAR_EL1, KernelRegionBase + KernelRegionCodeOffset);
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.VBAR_EL1, KernelRegionBase + KernelRegionCodeOffset);
|
||||||
|
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TTBR0_EL1, _userRange.GetIpaBase());
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TTBR0_EL1, _userRange.GetIpaBase());
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TTBR1_EL1, _kernelRange.GetIpaBase());
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TTBR1_EL1, _kernelRange.GetIpaBase());
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_MAIR_EL1, 0xffUL);
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.MAIR_EL1, 0xffUL);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_TCR_EL1, 0x00000011B5193519UL);
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.TCR_EL1, 0x00000011B5193519UL);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_SCTLR_EL1, 0x0000000034D5D925UL);
|
HvApi.hv_vcpu_set_sys_reg(vcpu, HvSysReg.SCTLR_EL1, 0x0000000034D5D925UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetAndClearUserTlbInvalidationPending()
|
public bool GetAndClearUserTlbInvalidationPending()
|
||||||
@@ -115,7 +113,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
MemoryPermission.ReadAndWrite => ApFlags.UserReadWriteKernelReadWrite,
|
MemoryPermission.ReadAndWrite => ApFlags.UserReadWriteKernelReadWrite,
|
||||||
MemoryPermission.ReadAndExecute => ApFlags.UserReadExecuteKernelRead,
|
MemoryPermission.ReadAndExecute => ApFlags.UserReadExecuteKernelRead,
|
||||||
MemoryPermission.ReadWriteExecute => ApFlags.UserReadWriteExecuteKernelReadWrite,
|
MemoryPermission.ReadWriteExecute => ApFlags.UserReadWriteExecuteKernelReadWrite,
|
||||||
_ => throw new ArgumentException($"Permission \"{permission}\" is invalid.")
|
_ => throw new ArgumentException($"Permission \"{permission}\" is invalid."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
ulong size = (ulong)count * sizeof(ulong);
|
ulong size = (ulong)count * sizeof(ulong);
|
||||||
Allocation = blockAllocator.Allocate(size, PageSize);
|
Allocation = blockAllocator.Allocate(size, PageSize);
|
||||||
|
|
||||||
AsSpan().Fill(0UL);
|
AsSpan().Clear();
|
||||||
|
|
||||||
if (hasNext)
|
if (hasNext)
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe Span<ulong> AsSpan()
|
public Span<ulong> AsSpan()
|
||||||
{
|
{
|
||||||
return MemoryMarshal.Cast<byte, ulong>(Allocation.Memory.GetSpan(Allocation.Offset, (int)Allocation.Size));
|
return MemoryMarshal.Cast<byte, ulong>(Allocation.Memory.GetSpan(Allocation.Offset, (int)Allocation.Size));
|
||||||
}
|
}
|
||||||
@@ -52,12 +52,10 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
private int _tlbInvalidationPending;
|
private int _tlbInvalidationPending;
|
||||||
|
|
||||||
private readonly HvIpaAllocator _ipaAllocator;
|
|
||||||
private readonly HvMemoryBlockAllocator _blockAllocator;
|
private readonly HvMemoryBlockAllocator _blockAllocator;
|
||||||
|
|
||||||
public HvAddressSpaceRange(HvIpaAllocator ipaAllocator)
|
public HvAddressSpaceRange(HvIpaAllocator ipaAllocator)
|
||||||
{
|
{
|
||||||
_ipaAllocator = ipaAllocator;
|
|
||||||
_blockAllocator = new HvMemoryBlockAllocator(ipaAllocator, (int)AllocationGranule);
|
_blockAllocator = new HvMemoryBlockAllocator(ipaAllocator, (int)AllocationGranule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +127,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
ulong endVa = (va + size + PageMask) & ~((ulong)PageMask);
|
ulong endVa = (va + size + PageMask) & ~((ulong)PageMask);
|
||||||
va &= ~((ulong)PageMask);
|
va &= ~((ulong)PageMask);
|
||||||
|
|
||||||
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
|
(ulong blockSize, _) = GetBlockSizeAndShift(depth);
|
||||||
|
|
||||||
while (va < endVa)
|
while (va < endVa)
|
||||||
{
|
{
|
||||||
@@ -138,7 +136,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
int l = (int)(va >> (PageBits + (2 - depth) * LevelBits)) & LevelMask;
|
int l = (int)(va >> (PageBits + (2 - depth) * LevelBits)) & LevelMask;
|
||||||
|
|
||||||
PtLevel nextTable = level.Next != null ? level.Next[l] : null;
|
PtLevel nextTable = level.Next?[l];
|
||||||
|
|
||||||
if (nextTable != null)
|
if (nextTable != null)
|
||||||
{
|
{
|
||||||
@@ -190,7 +188,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
ulong endVa = (va + size + PageSize - 1) & ~((ulong)PageSize - 1);
|
ulong endVa = (va + size + PageSize - 1) & ~((ulong)PageSize - 1);
|
||||||
va &= ~((ulong)PageSize - 1);
|
va &= ~((ulong)PageSize - 1);
|
||||||
|
|
||||||
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
|
(ulong blockSize, _) = GetBlockSizeAndShift(depth);
|
||||||
|
|
||||||
while (va < endVa)
|
while (va < endVa)
|
||||||
{
|
{
|
||||||
@@ -204,7 +202,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
// First check if the region is mapped.
|
// First check if the region is mapped.
|
||||||
if ((pte & 3) != 0)
|
if ((pte & 3) != 0)
|
||||||
{
|
{
|
||||||
PtLevel nextTable = level.Next != null ? level.Next[l] : null;
|
PtLevel nextTable = level.Next?[l];
|
||||||
|
|
||||||
if (nextTable != null)
|
if (nextTable != null)
|
||||||
{
|
{
|
||||||
@@ -240,10 +238,10 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
pte &= ~3UL;
|
pte &= ~3UL;
|
||||||
pte |= (depth == 2 ? 3UL : 1UL);
|
pte |= (depth == 2 ? 3UL : 1UL);
|
||||||
|
|
||||||
PtLevel level = new PtLevel(_blockAllocator, LevelCount, depth < 2);
|
PtLevel level = new(_blockAllocator, LevelCount, depth < 2);
|
||||||
Span<ulong> currentLevel = level.AsSpan();
|
Span<ulong> currentLevel = level.AsSpan();
|
||||||
|
|
||||||
(ulong blockSize, int blockShift) = GetBlockSizeAndShift(depth);
|
(_, int blockShift) = GetBlockSizeAndShift(depth);
|
||||||
|
|
||||||
// Fill in the blocks.
|
// Fill in the blocks.
|
||||||
for (int i = 0; i < LevelCount; i++)
|
for (int i = 0; i < LevelCount; i++)
|
||||||
@@ -334,7 +332,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
if ((currentTable[index] & 1) == 0)
|
if ((currentTable[index] & 1) == 0)
|
||||||
{
|
{
|
||||||
PtLevel nextLevel = new PtLevel(_blockAllocator, LevelCount, hasNext);
|
PtLevel nextLevel = new(_blockAllocator, LevelCount, hasNext);
|
||||||
|
|
||||||
currentTable[index] = (nextLevel.Address & ~(ulong)PageMask) | 3UL;
|
currentTable[index] = (nextLevel.Address & ~(ulong)PageMask) | 3UL;
|
||||||
level.Next[index] = nextLevel;
|
level.Next[index] = nextLevel;
|
||||||
@@ -347,7 +345,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteBlock(PtLevel level, int index, int depth, ulong pa, ulong attr)
|
private static void WriteBlock(PtLevel level, int index, int depth, ulong pa, ulong attr)
|
||||||
{
|
{
|
||||||
Span<ulong> currentTable = level.AsSpan();
|
Span<ulong> currentTable = level.AsSpan();
|
||||||
|
|
||||||
|
@@ -1,245 +1,244 @@
|
|||||||
using ARMeilleure.State;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
struct hv_vcpu_exit_exception_t
|
struct HvVcpuExitException
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public ulong syndrome;
|
public ulong Syndrome;
|
||||||
public ulong virtual_address;
|
public ulong VirtualAddress;
|
||||||
public ulong physical_address;
|
public ulong PhysicalAddress;
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hv_vcpu_exit_t
|
struct HvVcpuExit
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public uint reason;
|
public uint Reason;
|
||||||
public hv_vcpu_exit_exception_t exception;
|
public HvVcpuExitException Exception;
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_reg_t : uint
|
enum HvReg : uint
|
||||||
{
|
{
|
||||||
HV_REG_X0,
|
X0,
|
||||||
HV_REG_X1,
|
X1,
|
||||||
HV_REG_X2,
|
X2,
|
||||||
HV_REG_X3,
|
X3,
|
||||||
HV_REG_X4,
|
X4,
|
||||||
HV_REG_X5,
|
X5,
|
||||||
HV_REG_X6,
|
X6,
|
||||||
HV_REG_X7,
|
X7,
|
||||||
HV_REG_X8,
|
X8,
|
||||||
HV_REG_X9,
|
X9,
|
||||||
HV_REG_X10,
|
X10,
|
||||||
HV_REG_X11,
|
X11,
|
||||||
HV_REG_X12,
|
X12,
|
||||||
HV_REG_X13,
|
X13,
|
||||||
HV_REG_X14,
|
X14,
|
||||||
HV_REG_X15,
|
X15,
|
||||||
HV_REG_X16,
|
X16,
|
||||||
HV_REG_X17,
|
X17,
|
||||||
HV_REG_X18,
|
X18,
|
||||||
HV_REG_X19,
|
X19,
|
||||||
HV_REG_X20,
|
X20,
|
||||||
HV_REG_X21,
|
X21,
|
||||||
HV_REG_X22,
|
X22,
|
||||||
HV_REG_X23,
|
X23,
|
||||||
HV_REG_X24,
|
X24,
|
||||||
HV_REG_X25,
|
X25,
|
||||||
HV_REG_X26,
|
X26,
|
||||||
HV_REG_X27,
|
X27,
|
||||||
HV_REG_X28,
|
X28,
|
||||||
HV_REG_X29,
|
X29,
|
||||||
HV_REG_FP = HV_REG_X29,
|
FP = X29,
|
||||||
HV_REG_X30,
|
X30,
|
||||||
HV_REG_LR = HV_REG_X30,
|
LR = X30,
|
||||||
HV_REG_PC,
|
PC,
|
||||||
HV_REG_FPCR,
|
FPCR,
|
||||||
HV_REG_FPSR,
|
FPSR,
|
||||||
HV_REG_CPSR,
|
CPSR,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_simd_fp_reg_t : uint
|
enum HvSimdFPReg : uint
|
||||||
{
|
{
|
||||||
HV_SIMD_FP_REG_Q0,
|
Q0,
|
||||||
HV_SIMD_FP_REG_Q1,
|
Q1,
|
||||||
HV_SIMD_FP_REG_Q2,
|
Q2,
|
||||||
HV_SIMD_FP_REG_Q3,
|
Q3,
|
||||||
HV_SIMD_FP_REG_Q4,
|
Q4,
|
||||||
HV_SIMD_FP_REG_Q5,
|
Q5,
|
||||||
HV_SIMD_FP_REG_Q6,
|
Q6,
|
||||||
HV_SIMD_FP_REG_Q7,
|
Q7,
|
||||||
HV_SIMD_FP_REG_Q8,
|
Q8,
|
||||||
HV_SIMD_FP_REG_Q9,
|
Q9,
|
||||||
HV_SIMD_FP_REG_Q10,
|
Q10,
|
||||||
HV_SIMD_FP_REG_Q11,
|
Q11,
|
||||||
HV_SIMD_FP_REG_Q12,
|
Q12,
|
||||||
HV_SIMD_FP_REG_Q13,
|
Q13,
|
||||||
HV_SIMD_FP_REG_Q14,
|
Q14,
|
||||||
HV_SIMD_FP_REG_Q15,
|
Q15,
|
||||||
HV_SIMD_FP_REG_Q16,
|
Q16,
|
||||||
HV_SIMD_FP_REG_Q17,
|
Q17,
|
||||||
HV_SIMD_FP_REG_Q18,
|
Q18,
|
||||||
HV_SIMD_FP_REG_Q19,
|
Q19,
|
||||||
HV_SIMD_FP_REG_Q20,
|
Q20,
|
||||||
HV_SIMD_FP_REG_Q21,
|
Q21,
|
||||||
HV_SIMD_FP_REG_Q22,
|
Q22,
|
||||||
HV_SIMD_FP_REG_Q23,
|
Q23,
|
||||||
HV_SIMD_FP_REG_Q24,
|
Q24,
|
||||||
HV_SIMD_FP_REG_Q25,
|
Q25,
|
||||||
HV_SIMD_FP_REG_Q26,
|
Q26,
|
||||||
HV_SIMD_FP_REG_Q27,
|
Q27,
|
||||||
HV_SIMD_FP_REG_Q28,
|
Q28,
|
||||||
HV_SIMD_FP_REG_Q29,
|
Q29,
|
||||||
HV_SIMD_FP_REG_Q30,
|
Q30,
|
||||||
HV_SIMD_FP_REG_Q31,
|
Q31,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_sys_reg_t : ushort
|
enum HvSysReg : ushort
|
||||||
{
|
{
|
||||||
HV_SYS_REG_DBGBVR0_EL1 = 0x8004,
|
DBGBVR0_EL1 = 0x8004,
|
||||||
HV_SYS_REG_DBGBCR0_EL1 = 0x8005,
|
DBGBCR0_EL1 = 0x8005,
|
||||||
HV_SYS_REG_DBGWVR0_EL1 = 0x8006,
|
DBGWVR0_EL1 = 0x8006,
|
||||||
HV_SYS_REG_DBGWCR0_EL1 = 0x8007,
|
DBGWCR0_EL1 = 0x8007,
|
||||||
HV_SYS_REG_DBGBVR1_EL1 = 0x800c,
|
DBGBVR1_EL1 = 0x800c,
|
||||||
HV_SYS_REG_DBGBCR1_EL1 = 0x800d,
|
DBGBCR1_EL1 = 0x800d,
|
||||||
HV_SYS_REG_DBGWVR1_EL1 = 0x800e,
|
DBGWVR1_EL1 = 0x800e,
|
||||||
HV_SYS_REG_DBGWCR1_EL1 = 0x800f,
|
DBGWCR1_EL1 = 0x800f,
|
||||||
HV_SYS_REG_MDCCINT_EL1 = 0x8010,
|
MDCCINT_EL1 = 0x8010,
|
||||||
HV_SYS_REG_MDSCR_EL1 = 0x8012,
|
MDSCR_EL1 = 0x8012,
|
||||||
HV_SYS_REG_DBGBVR2_EL1 = 0x8014,
|
DBGBVR2_EL1 = 0x8014,
|
||||||
HV_SYS_REG_DBGBCR2_EL1 = 0x8015,
|
DBGBCR2_EL1 = 0x8015,
|
||||||
HV_SYS_REG_DBGWVR2_EL1 = 0x8016,
|
DBGWVR2_EL1 = 0x8016,
|
||||||
HV_SYS_REG_DBGWCR2_EL1 = 0x8017,
|
DBGWCR2_EL1 = 0x8017,
|
||||||
HV_SYS_REG_DBGBVR3_EL1 = 0x801c,
|
DBGBVR3_EL1 = 0x801c,
|
||||||
HV_SYS_REG_DBGBCR3_EL1 = 0x801d,
|
DBGBCR3_EL1 = 0x801d,
|
||||||
HV_SYS_REG_DBGWVR3_EL1 = 0x801e,
|
DBGWVR3_EL1 = 0x801e,
|
||||||
HV_SYS_REG_DBGWCR3_EL1 = 0x801f,
|
DBGWCR3_EL1 = 0x801f,
|
||||||
HV_SYS_REG_DBGBVR4_EL1 = 0x8024,
|
DBGBVR4_EL1 = 0x8024,
|
||||||
HV_SYS_REG_DBGBCR4_EL1 = 0x8025,
|
DBGBCR4_EL1 = 0x8025,
|
||||||
HV_SYS_REG_DBGWVR4_EL1 = 0x8026,
|
DBGWVR4_EL1 = 0x8026,
|
||||||
HV_SYS_REG_DBGWCR4_EL1 = 0x8027,
|
DBGWCR4_EL1 = 0x8027,
|
||||||
HV_SYS_REG_DBGBVR5_EL1 = 0x802c,
|
DBGBVR5_EL1 = 0x802c,
|
||||||
HV_SYS_REG_DBGBCR5_EL1 = 0x802d,
|
DBGBCR5_EL1 = 0x802d,
|
||||||
HV_SYS_REG_DBGWVR5_EL1 = 0x802e,
|
DBGWVR5_EL1 = 0x802e,
|
||||||
HV_SYS_REG_DBGWCR5_EL1 = 0x802f,
|
DBGWCR5_EL1 = 0x802f,
|
||||||
HV_SYS_REG_DBGBVR6_EL1 = 0x8034,
|
DBGBVR6_EL1 = 0x8034,
|
||||||
HV_SYS_REG_DBGBCR6_EL1 = 0x8035,
|
DBGBCR6_EL1 = 0x8035,
|
||||||
HV_SYS_REG_DBGWVR6_EL1 = 0x8036,
|
DBGWVR6_EL1 = 0x8036,
|
||||||
HV_SYS_REG_DBGWCR6_EL1 = 0x8037,
|
DBGWCR6_EL1 = 0x8037,
|
||||||
HV_SYS_REG_DBGBVR7_EL1 = 0x803c,
|
DBGBVR7_EL1 = 0x803c,
|
||||||
HV_SYS_REG_DBGBCR7_EL1 = 0x803d,
|
DBGBCR7_EL1 = 0x803d,
|
||||||
HV_SYS_REG_DBGWVR7_EL1 = 0x803e,
|
DBGWVR7_EL1 = 0x803e,
|
||||||
HV_SYS_REG_DBGWCR7_EL1 = 0x803f,
|
DBGWCR7_EL1 = 0x803f,
|
||||||
HV_SYS_REG_DBGBVR8_EL1 = 0x8044,
|
DBGBVR8_EL1 = 0x8044,
|
||||||
HV_SYS_REG_DBGBCR8_EL1 = 0x8045,
|
DBGBCR8_EL1 = 0x8045,
|
||||||
HV_SYS_REG_DBGWVR8_EL1 = 0x8046,
|
DBGWVR8_EL1 = 0x8046,
|
||||||
HV_SYS_REG_DBGWCR8_EL1 = 0x8047,
|
DBGWCR8_EL1 = 0x8047,
|
||||||
HV_SYS_REG_DBGBVR9_EL1 = 0x804c,
|
DBGBVR9_EL1 = 0x804c,
|
||||||
HV_SYS_REG_DBGBCR9_EL1 = 0x804d,
|
DBGBCR9_EL1 = 0x804d,
|
||||||
HV_SYS_REG_DBGWVR9_EL1 = 0x804e,
|
DBGWVR9_EL1 = 0x804e,
|
||||||
HV_SYS_REG_DBGWCR9_EL1 = 0x804f,
|
DBGWCR9_EL1 = 0x804f,
|
||||||
HV_SYS_REG_DBGBVR10_EL1 = 0x8054,
|
DBGBVR10_EL1 = 0x8054,
|
||||||
HV_SYS_REG_DBGBCR10_EL1 = 0x8055,
|
DBGBCR10_EL1 = 0x8055,
|
||||||
HV_SYS_REG_DBGWVR10_EL1 = 0x8056,
|
DBGWVR10_EL1 = 0x8056,
|
||||||
HV_SYS_REG_DBGWCR10_EL1 = 0x8057,
|
DBGWCR10_EL1 = 0x8057,
|
||||||
HV_SYS_REG_DBGBVR11_EL1 = 0x805c,
|
DBGBVR11_EL1 = 0x805c,
|
||||||
HV_SYS_REG_DBGBCR11_EL1 = 0x805d,
|
DBGBCR11_EL1 = 0x805d,
|
||||||
HV_SYS_REG_DBGWVR11_EL1 = 0x805e,
|
DBGWVR11_EL1 = 0x805e,
|
||||||
HV_SYS_REG_DBGWCR11_EL1 = 0x805f,
|
DBGWCR11_EL1 = 0x805f,
|
||||||
HV_SYS_REG_DBGBVR12_EL1 = 0x8064,
|
DBGBVR12_EL1 = 0x8064,
|
||||||
HV_SYS_REG_DBGBCR12_EL1 = 0x8065,
|
DBGBCR12_EL1 = 0x8065,
|
||||||
HV_SYS_REG_DBGWVR12_EL1 = 0x8066,
|
DBGWVR12_EL1 = 0x8066,
|
||||||
HV_SYS_REG_DBGWCR12_EL1 = 0x8067,
|
DBGWCR12_EL1 = 0x8067,
|
||||||
HV_SYS_REG_DBGBVR13_EL1 = 0x806c,
|
DBGBVR13_EL1 = 0x806c,
|
||||||
HV_SYS_REG_DBGBCR13_EL1 = 0x806d,
|
DBGBCR13_EL1 = 0x806d,
|
||||||
HV_SYS_REG_DBGWVR13_EL1 = 0x806e,
|
DBGWVR13_EL1 = 0x806e,
|
||||||
HV_SYS_REG_DBGWCR13_EL1 = 0x806f,
|
DBGWCR13_EL1 = 0x806f,
|
||||||
HV_SYS_REG_DBGBVR14_EL1 = 0x8074,
|
DBGBVR14_EL1 = 0x8074,
|
||||||
HV_SYS_REG_DBGBCR14_EL1 = 0x8075,
|
DBGBCR14_EL1 = 0x8075,
|
||||||
HV_SYS_REG_DBGWVR14_EL1 = 0x8076,
|
DBGWVR14_EL1 = 0x8076,
|
||||||
HV_SYS_REG_DBGWCR14_EL1 = 0x8077,
|
DBGWCR14_EL1 = 0x8077,
|
||||||
HV_SYS_REG_DBGBVR15_EL1 = 0x807c,
|
DBGBVR15_EL1 = 0x807c,
|
||||||
HV_SYS_REG_DBGBCR15_EL1 = 0x807d,
|
DBGBCR15_EL1 = 0x807d,
|
||||||
HV_SYS_REG_DBGWVR15_EL1 = 0x807e,
|
DBGWVR15_EL1 = 0x807e,
|
||||||
HV_SYS_REG_DBGWCR15_EL1 = 0x807f,
|
DBGWCR15_EL1 = 0x807f,
|
||||||
HV_SYS_REG_MIDR_EL1 = 0xc000,
|
MIDR_EL1 = 0xc000,
|
||||||
HV_SYS_REG_MPIDR_EL1 = 0xc005,
|
MPIDR_EL1 = 0xc005,
|
||||||
HV_SYS_REG_ID_AA64PFR0_EL1 = 0xc020,
|
ID_AA64PFR0_EL1 = 0xc020,
|
||||||
HV_SYS_REG_ID_AA64PFR1_EL1 = 0xc021,
|
ID_AA64PFR1_EL1 = 0xc021,
|
||||||
HV_SYS_REG_ID_AA64DFR0_EL1 = 0xc028,
|
ID_AA64DFR0_EL1 = 0xc028,
|
||||||
HV_SYS_REG_ID_AA64DFR1_EL1 = 0xc029,
|
ID_AA64DFR1_EL1 = 0xc029,
|
||||||
HV_SYS_REG_ID_AA64ISAR0_EL1 = 0xc030,
|
ID_AA64ISAR0_EL1 = 0xc030,
|
||||||
HV_SYS_REG_ID_AA64ISAR1_EL1 = 0xc031,
|
ID_AA64ISAR1_EL1 = 0xc031,
|
||||||
HV_SYS_REG_ID_AA64MMFR0_EL1 = 0xc038,
|
ID_AA64MMFR0_EL1 = 0xc038,
|
||||||
HV_SYS_REG_ID_AA64MMFR1_EL1 = 0xc039,
|
ID_AA64MMFR1_EL1 = 0xc039,
|
||||||
HV_SYS_REG_ID_AA64MMFR2_EL1 = 0xc03a,
|
ID_AA64MMFR2_EL1 = 0xc03a,
|
||||||
HV_SYS_REG_SCTLR_EL1 = 0xc080,
|
SCTLR_EL1 = 0xc080,
|
||||||
HV_SYS_REG_CPACR_EL1 = 0xc082,
|
CPACR_EL1 = 0xc082,
|
||||||
HV_SYS_REG_TTBR0_EL1 = 0xc100,
|
TTBR0_EL1 = 0xc100,
|
||||||
HV_SYS_REG_TTBR1_EL1 = 0xc101,
|
TTBR1_EL1 = 0xc101,
|
||||||
HV_SYS_REG_TCR_EL1 = 0xc102,
|
TCR_EL1 = 0xc102,
|
||||||
HV_SYS_REG_APIAKEYLO_EL1 = 0xc108,
|
APIAKEYLO_EL1 = 0xc108,
|
||||||
HV_SYS_REG_APIAKEYHI_EL1 = 0xc109,
|
APIAKEYHI_EL1 = 0xc109,
|
||||||
HV_SYS_REG_APIBKEYLO_EL1 = 0xc10a,
|
APIBKEYLO_EL1 = 0xc10a,
|
||||||
HV_SYS_REG_APIBKEYHI_EL1 = 0xc10b,
|
APIBKEYHI_EL1 = 0xc10b,
|
||||||
HV_SYS_REG_APDAKEYLO_EL1 = 0xc110,
|
APDAKEYLO_EL1 = 0xc110,
|
||||||
HV_SYS_REG_APDAKEYHI_EL1 = 0xc111,
|
APDAKEYHI_EL1 = 0xc111,
|
||||||
HV_SYS_REG_APDBKEYLO_EL1 = 0xc112,
|
APDBKEYLO_EL1 = 0xc112,
|
||||||
HV_SYS_REG_APDBKEYHI_EL1 = 0xc113,
|
APDBKEYHI_EL1 = 0xc113,
|
||||||
HV_SYS_REG_APGAKEYLO_EL1 = 0xc118,
|
APGAKEYLO_EL1 = 0xc118,
|
||||||
HV_SYS_REG_APGAKEYHI_EL1 = 0xc119,
|
APGAKEYHI_EL1 = 0xc119,
|
||||||
HV_SYS_REG_SPSR_EL1 = 0xc200,
|
SPSR_EL1 = 0xc200,
|
||||||
HV_SYS_REG_ELR_EL1 = 0xc201,
|
ELR_EL1 = 0xc201,
|
||||||
HV_SYS_REG_SP_EL0 = 0xc208,
|
SP_EL0 = 0xc208,
|
||||||
HV_SYS_REG_AFSR0_EL1 = 0xc288,
|
AFSR0_EL1 = 0xc288,
|
||||||
HV_SYS_REG_AFSR1_EL1 = 0xc289,
|
AFSR1_EL1 = 0xc289,
|
||||||
HV_SYS_REG_ESR_EL1 = 0xc290,
|
ESR_EL1 = 0xc290,
|
||||||
HV_SYS_REG_FAR_EL1 = 0xc300,
|
FAR_EL1 = 0xc300,
|
||||||
HV_SYS_REG_PAR_EL1 = 0xc3a0,
|
PAR_EL1 = 0xc3a0,
|
||||||
HV_SYS_REG_MAIR_EL1 = 0xc510,
|
MAIR_EL1 = 0xc510,
|
||||||
HV_SYS_REG_AMAIR_EL1 = 0xc518,
|
AMAIR_EL1 = 0xc518,
|
||||||
HV_SYS_REG_VBAR_EL1 = 0xc600,
|
VBAR_EL1 = 0xc600,
|
||||||
HV_SYS_REG_CONTEXTIDR_EL1 = 0xc681,
|
CONTEXTIDR_EL1 = 0xc681,
|
||||||
HV_SYS_REG_TPIDR_EL1 = 0xc684,
|
TPIDR_EL1 = 0xc684,
|
||||||
HV_SYS_REG_CNTKCTL_EL1 = 0xc708,
|
CNTKCTL_EL1 = 0xc708,
|
||||||
HV_SYS_REG_CSSELR_EL1 = 0xd000,
|
CSSELR_EL1 = 0xd000,
|
||||||
HV_SYS_REG_TPIDR_EL0 = 0xde82,
|
TPIDR_EL0 = 0xde82,
|
||||||
HV_SYS_REG_TPIDRRO_EL0 = 0xde83,
|
TPIDRRO_EL0 = 0xde83,
|
||||||
HV_SYS_REG_CNTV_CTL_EL0 = 0xdf19,
|
CNTV_CTL_EL0 = 0xdf19,
|
||||||
HV_SYS_REG_CNTV_CVAL_EL0 = 0xdf1a,
|
CNTV_CVAL_EL0 = 0xdf1a,
|
||||||
HV_SYS_REG_SP_EL1 = 0xe208,
|
SP_EL1 = 0xe208,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_memory_flags_t : ulong
|
enum HvMemoryFlags : ulong
|
||||||
{
|
{
|
||||||
HV_MEMORY_READ = 1UL << 0,
|
Read = 1UL << 0,
|
||||||
HV_MEMORY_WRITE = 1UL << 1,
|
Write = 1UL << 1,
|
||||||
HV_MEMORY_EXEC = 1UL << 2
|
Exec = 1UL << 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_result_t : uint
|
enum HvResult : uint
|
||||||
{
|
{
|
||||||
HV_SUCCESS = 0,
|
Success = 0,
|
||||||
HV_ERROR = 0xfae94001,
|
Error = 0xfae94001,
|
||||||
HV_BUSY = 0xfae94002,
|
Busy = 0xfae94002,
|
||||||
HV_BAD_ARGUMENT = 0xfae94003,
|
BadArgument = 0xfae94003,
|
||||||
HV_NO_RESOURCES = 0xfae94005,
|
NoResources = 0xfae94005,
|
||||||
HV_NO_DEVICE = 0xfae94006,
|
NoDevice = 0xfae94006,
|
||||||
HV_DENIED = 0xfae94007,
|
Denied = 0xfae94007,
|
||||||
HV_UNSUPPORTED = 0xfae9400f
|
Unsupported = 0xfae9400f,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hv_interrupt_type_t : uint
|
enum HvInterruptType : uint
|
||||||
{
|
{
|
||||||
HV_INTERRUPT_TYPE_IRQ,
|
IRQ,
|
||||||
HV_INTERRUPT_TYPE_FIQ
|
FIQ,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hv_simd_fp_uchar16_t
|
struct HvSimdFPUchar16
|
||||||
{
|
{
|
||||||
public ulong Low;
|
public ulong Low;
|
||||||
public ulong High;
|
public ulong High;
|
||||||
@@ -247,9 +246,9 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
static class HvResultExtensions
|
static class HvResultExtensions
|
||||||
{
|
{
|
||||||
public static void ThrowOnError(this hv_result_t result)
|
public static void ThrowOnError(this HvResult result)
|
||||||
{
|
{
|
||||||
if (result != hv_result_t.HV_SUCCESS)
|
if (result != HvResult.Success)
|
||||||
{
|
{
|
||||||
throw new Exception($"Unexpected result \"{result}\".");
|
throw new Exception($"Unexpected result \"{result}\".");
|
||||||
}
|
}
|
||||||
@@ -261,60 +260,60 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
public const string LibraryName = "/System/Library/Frameworks/Hypervisor.framework/Hypervisor";
|
public const string LibraryName = "/System/Library/Frameworks/Hypervisor.framework/Hypervisor";
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_get_max_vcpu_count(out uint max_vcpu_count);
|
public static partial HvResult hv_vm_get_max_vcpu_count(out uint max_vcpu_count);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_create(IntPtr config);
|
public static partial HvResult hv_vm_create(IntPtr config);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_destroy();
|
public static partial HvResult hv_vm_destroy();
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_map(ulong addr, ulong ipa, ulong size, hv_memory_flags_t flags);
|
public static partial HvResult hv_vm_map(ulong addr, ulong ipa, ulong size, HvMemoryFlags flags);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_unmap(ulong ipa, ulong size);
|
public static partial HvResult hv_vm_unmap(ulong ipa, ulong size);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vm_protect(ulong ipa, ulong size, hv_memory_flags_t flags);
|
public static partial HvResult hv_vm_protect(ulong ipa, ulong size, HvMemoryFlags flags);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public unsafe static partial hv_result_t hv_vcpu_create(out ulong vcpu, ref hv_vcpu_exit_t* exit, IntPtr config);
|
public unsafe static partial HvResult hv_vcpu_create(out ulong vcpu, ref HvVcpuExit* exit, IntPtr config);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public unsafe static partial hv_result_t hv_vcpu_destroy(ulong vcpu);
|
public unsafe static partial HvResult hv_vcpu_destroy(ulong vcpu);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_run(ulong vcpu);
|
public static partial HvResult hv_vcpu_run(ulong vcpu);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpus_exit(ref ulong vcpus, uint vcpu_count);
|
public static partial HvResult hv_vcpus_exit(ref ulong vcpus, uint vcpu_count);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_set_vtimer_mask(ulong vcpu, [MarshalAs(UnmanagedType.Bool)] bool vtimer_is_masked);
|
public static partial HvResult hv_vcpu_set_vtimer_mask(ulong vcpu, [MarshalAs(UnmanagedType.Bool)] bool vtimer_is_masked);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_get_reg(ulong vcpu, hv_reg_t reg, out ulong value);
|
public static partial HvResult hv_vcpu_get_reg(ulong vcpu, HvReg reg, out ulong value);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_set_reg(ulong vcpu, hv_reg_t reg, ulong value);
|
public static partial HvResult hv_vcpu_set_reg(ulong vcpu, HvReg reg, ulong value);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_get_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, out hv_simd_fp_uchar16_t value);
|
public static partial HvResult hv_vcpu_get_simd_fp_reg(ulong vcpu, HvSimdFPReg reg, out HvSimdFPUchar16 value);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_set_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, hv_simd_fp_uchar16_t value); // DO NOT USE DIRECTLY!
|
public static partial HvResult hv_vcpu_set_simd_fp_reg(ulong vcpu, HvSimdFPReg reg, HvSimdFPUchar16 value); // DO NOT USE DIRECTLY!
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_get_sys_reg(ulong vcpu, hv_sys_reg_t reg, out ulong value);
|
public static partial HvResult hv_vcpu_get_sys_reg(ulong vcpu, HvSysReg reg, out ulong value);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_set_sys_reg(ulong vcpu, hv_sys_reg_t reg, ulong value);
|
public static partial HvResult hv_vcpu_set_sys_reg(ulong vcpu, HvSysReg reg, ulong value);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_get_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] out bool pending);
|
public static partial HvResult hv_vcpu_get_pending_interrupt(ulong vcpu, HvInterruptType type, [MarshalAs(UnmanagedType.Bool)] out bool pending);
|
||||||
|
|
||||||
[LibraryImport(LibraryName, SetLastError = true)]
|
[LibraryImport(LibraryName, SetLastError = true)]
|
||||||
public static partial hv_result_t hv_vcpu_set_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] bool pending);
|
public static partial HvResult hv_vcpu_set_pending_interrupt(ulong vcpu, HvInterruptType type, [MarshalAs(UnmanagedType.Bool)] bool pending);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,4 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
@@ -14,10 +13,6 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
_memoryManager = (HvMemoryManager)memory;
|
_memoryManager = (HvMemoryManager)memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UnmapHandler(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
||||||
{
|
{
|
||||||
|
@@ -125,17 +125,17 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext);
|
HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext);
|
||||||
|
|
||||||
HvApi.hv_vcpu_set_reg(vcpu.Handle, hv_reg_t.HV_REG_PC, address).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
||||||
|
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
|
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
|
||||||
|
|
||||||
uint reason = vcpu.ExitInfo->reason;
|
uint reason = vcpu.ExitInfo->Reason;
|
||||||
|
|
||||||
if (reason == 1)
|
if (reason == 1)
|
||||||
{
|
{
|
||||||
uint hvEsr = (uint)vcpu.ExitInfo->exception.syndrome;
|
uint hvEsr = (uint)vcpu.ExitInfo->Exception.Syndrome;
|
||||||
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
|
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
|
||||||
|
|
||||||
if (hvEc != ExceptionClass.HvcAarch64)
|
if (hvEc != ExceptionClass.HvcAarch64)
|
||||||
@@ -144,7 +144,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
|
|
||||||
address = SynchronousException(memoryManager, ref vcpu);
|
address = SynchronousException(memoryManager, ref vcpu);
|
||||||
HvApi.hv_vcpu_set_reg(vcpu.Handle, hv_reg_t.HV_REG_PC, address).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
||||||
}
|
}
|
||||||
else if (reason == 0)
|
else if (reason == 0)
|
||||||
{
|
{
|
||||||
@@ -168,8 +168,8 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
ulong vcpuHandle = vcpu.Handle;
|
ulong vcpuHandle = vcpu.Handle;
|
||||||
|
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, out ulong elr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
|
||||||
|
|
||||||
ExceptionClass ec = (ExceptionClass)((uint)esr >> 26);
|
ExceptionClass ec = (ExceptionClass)((uint)esr >> 26);
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
break;
|
break;
|
||||||
case ExceptionClass.TrappedMsrMrsSystem:
|
case ExceptionClass.TrappedMsrMrsSystem:
|
||||||
InstructionTrap((uint)esr);
|
InstructionTrap((uint)esr);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, elr + 4UL).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, elr + 4UL).ThrowOnError();
|
||||||
break;
|
break;
|
||||||
case ExceptionClass.SvcAarch64:
|
case ExceptionClass.SvcAarch64:
|
||||||
ReturnToPool(vcpu);
|
ReturnToPool(vcpu);
|
||||||
@@ -204,7 +204,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr)
|
private static void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr)
|
||||||
{
|
{
|
||||||
bool write = (esr & (1u << 6)) != 0;
|
bool write = (esr & (1u << 6)) != 0;
|
||||||
bool farValid = (esr & (1u << 10)) == 0;
|
bool farValid = (esr & (1u << 10)) == 0;
|
||||||
@@ -212,7 +212,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
if (farValid)
|
if (farValid)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpu, hv_sys_reg_t.HV_SYS_REG_FAR_EL1, out ulong far).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpu, HvSysReg.FAR_EL1, out ulong far).ThrowOnError();
|
||||||
|
|
||||||
ulong size = 1UL << accessSizeLog2;
|
ulong size = 1UL << accessSizeLog2;
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ using ARMeilleure.State;
|
|||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
unsafe class HvExecutionContextShadow : IHvExecutionContext
|
class HvExecutionContextShadow : IHvExecutionContext
|
||||||
{
|
{
|
||||||
public ulong Pc { get; set; }
|
public ulong Pc { get; set; }
|
||||||
public ulong ElrEl1 { get; set; }
|
public ulong ElrEl1 { get; set; }
|
||||||
|
@@ -8,10 +8,10 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
class HvExecutionContextVcpu : IHvExecutionContext
|
class HvExecutionContextVcpu : IHvExecutionContext
|
||||||
{
|
{
|
||||||
private static MemoryBlock _setSimdFpRegFuncMem;
|
private static readonly MemoryBlock _setSimdFpRegFuncMem;
|
||||||
private delegate hv_result_t SetSimdFpReg(ulong vcpu, hv_simd_fp_reg_t reg, in V128 value, IntPtr funcPtr);
|
private delegate HvResult SetSimdFpReg(ulong vcpu, HvSimdFPReg reg, in V128 value, IntPtr funcPtr);
|
||||||
private static SetSimdFpReg _setSimdFpReg;
|
private static readonly SetSimdFpReg _setSimdFpReg;
|
||||||
private static IntPtr _setSimdFpRegNativePtr;
|
private static readonly IntPtr _setSimdFpRegNativePtr;
|
||||||
|
|
||||||
static HvExecutionContextVcpu()
|
static HvExecutionContextVcpu()
|
||||||
{
|
{
|
||||||
@@ -34,12 +34,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_PC, out ulong pc).ThrowOnError();
|
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.PC, out ulong pc).ThrowOnError();
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_PC, value).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.PC, value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, out ulong elr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
|
||||||
return elr;
|
return elr;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, value).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ELR_EL1, value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,12 +60,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
|
||||||
return esr;
|
return esr;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, value).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ESR_EL1, value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +73,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, out ulong tpidrEl0).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, out ulong tpidrEl0).ThrowOnError();
|
||||||
return (long)tpidrEl0;
|
return (long)tpidrEl0;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, (ulong)value).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, (ulong)value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,12 +86,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError();
|
||||||
return (long)tpidrroEl0;
|
return (long)tpidrroEl0;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, (ulong)value).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, (ulong)value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +99,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_CPSR, out ulong cpsr).ThrowOnError();
|
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.CPSR, out ulong cpsr).ThrowOnError();
|
||||||
return (uint)cpsr;
|
return (uint)cpsr;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_CPSR, (ulong)value).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.CPSR, (ulong)value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +112,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPCR, out ulong fpcr).ThrowOnError();
|
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPCR, out ulong fpcr).ThrowOnError();
|
||||||
return (uint)fpcr;
|
return (uint)fpcr;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPCR, (ulong)value).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPCR, (ulong)value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,16 +125,16 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPSR, out ulong fpsr).ThrowOnError();
|
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPSR, out ulong fpsr).ThrowOnError();
|
||||||
return (uint)fpsr;
|
return (uint)fpsr;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPSR, (ulong)value).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPSR, (ulong)value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong _vcpu;
|
private readonly ulong _vcpu;
|
||||||
private int _interruptRequested;
|
private int _interruptRequested;
|
||||||
|
|
||||||
public HvExecutionContextVcpu(ulong vcpu)
|
public HvExecutionContextVcpu(ulong vcpu)
|
||||||
@@ -146,12 +146,12 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (index == 31)
|
if (index == 31)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, out ulong value).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.SP_EL0, out ulong value).ThrowOnError();
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, out ulong value).ThrowOnError();
|
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.X0 + (uint)index, out ulong value).ThrowOnError();
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,23 +160,23 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (index == 31)
|
if (index == 31)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, value).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.SP_EL0, value).ThrowOnError();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, value).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.X0 + (uint)index, value).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public V128 GetV(int index)
|
public V128 GetV(int index)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, out hv_simd_fp_uchar16_t value).ThrowOnError();
|
HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, HvSimdFPReg.Q0 + (uint)index, out HvSimdFPUchar16 value).ThrowOnError();
|
||||||
return new V128(value.Low, value.High);
|
return new V128(value.Low, value.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetV(int index, V128 value)
|
public void SetV(int index, V128 value)
|
||||||
{
|
{
|
||||||
_setSimdFpReg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError();
|
_setSimdFpReg(_vcpu, HvSimdFPReg.Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RequestInterrupt()
|
public void RequestInterrupt()
|
||||||
|
@@ -3,7 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
struct HvMemoryBlockAllocation : IDisposable
|
readonly struct HvMemoryBlockAllocation : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HvMemoryBlockAllocator _owner;
|
private readonly HvMemoryBlockAllocator _owner;
|
||||||
private readonly HvMemoryBlockAllocator.Block _block;
|
private readonly HvMemoryBlockAllocator.Block _block;
|
||||||
|
@@ -1,12 +1,9 @@
|
|||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
class HvMemoryBlockAllocator : PrivateMemoryAllocatorImpl<HvMemoryBlockAllocator.Block>
|
class HvMemoryBlockAllocator : PrivateMemoryAllocatorImpl<HvMemoryBlockAllocator.Block>
|
||||||
{
|
{
|
||||||
private const ulong InvalidOffset = ulong.MaxValue;
|
|
||||||
|
|
||||||
public class Block : PrivateMemoryAllocator.Block
|
public class Block : PrivateMemoryAllocator.Block
|
||||||
{
|
{
|
||||||
private readonly HvIpaAllocator _ipaAllocator;
|
private readonly HvIpaAllocator _ipaAllocator;
|
||||||
@@ -21,7 +18,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
Ipa = ipaAllocator.Allocate(size);
|
Ipa = ipaAllocator.Allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
HvApi.hv_vm_map((ulong)Memory.Pointer, Ipa, size, hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_WRITE).ThrowOnError();
|
HvApi.hv_vm_map((ulong)Memory.Pointer, Ipa, size, HvMemoryFlags.Read | HvMemoryFlags.Write).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Destroy()
|
public override void Destroy()
|
||||||
@@ -44,7 +41,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
_ipaAllocator = ipaAllocator;
|
_ipaAllocator = ipaAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
|
public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
|
||||||
{
|
{
|
||||||
var allocation = Allocate(size, alignment, CreateBlock);
|
var allocation = Allocate(size, alignment, CreateBlock);
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
MappedReplicated = 0x5555555555555555,
|
MappedReplicated = 0x5555555555555555,
|
||||||
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
|
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
|
||||||
ReadWriteTrackedReplicated = ulong.MaxValue
|
ReadWriteTrackedReplicated = ulong.MaxValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly InvalidAccessHandler _invalidAccessHandler;
|
private readonly InvalidAccessHandler _invalidAccessHandler;
|
||||||
@@ -126,6 +126,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
|
/// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -138,6 +139,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
|
throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
||||||
@@ -306,7 +308,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size));
|
data[..size].CopyTo(_backingMemory.GetSpan(pa, size));
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
@@ -428,7 +430,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
|
private static void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
|
||||||
{
|
{
|
||||||
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
|
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
|
||||||
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
|
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
|
||||||
@@ -606,7 +608,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
_backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size));
|
_backingMemory.GetSpan(pa, size).CopyTo(data[..size]);
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
@@ -723,7 +725,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
||||||
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetPagesCount(ulong va, ulong size, out ulong startVa)
|
private static int GetPagesCount(ulong va, ulong size, out ulong startVa)
|
||||||
{
|
{
|
||||||
// WARNING: Always check if ulong does not overflow during the operations.
|
// WARNING: Always check if ulong does not overflow during the operations.
|
||||||
startVa = va & ~(ulong)PageMask;
|
startVa = va & ~(ulong)PageMask;
|
||||||
@@ -814,7 +816,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
MemoryPermission.None => MemoryPermission.ReadAndWrite,
|
MemoryPermission.None => MemoryPermission.ReadAndWrite,
|
||||||
MemoryPermission.Write => MemoryPermission.Read,
|
MemoryPermission.Write => MemoryPermission.Read,
|
||||||
_ => MemoryPermission.None
|
_ => MemoryPermission.None,
|
||||||
};
|
};
|
||||||
|
|
||||||
_addressSpace.ReprotectUser(va, size, protection);
|
_addressSpace.ReprotectUser(va, size, protection);
|
||||||
|
@@ -3,14 +3,14 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
unsafe class HvVcpu
|
unsafe class HvVcpu
|
||||||
{
|
{
|
||||||
public readonly ulong Handle;
|
public readonly ulong Handle;
|
||||||
public readonly hv_vcpu_exit_t* ExitInfo;
|
public readonly HvVcpuExit* ExitInfo;
|
||||||
public readonly IHvExecutionContext ShadowContext;
|
public readonly IHvExecutionContext ShadowContext;
|
||||||
public readonly IHvExecutionContext NativeContext;
|
public readonly IHvExecutionContext NativeContext;
|
||||||
public readonly bool IsEphemeral;
|
public readonly bool IsEphemeral;
|
||||||
|
|
||||||
public HvVcpu(
|
public HvVcpu(
|
||||||
ulong handle,
|
ulong handle,
|
||||||
hv_vcpu_exit_t* exitInfo,
|
HvVcpuExit* exitInfo,
|
||||||
IHvExecutionContext shadowContext,
|
IHvExecutionContext shadowContext,
|
||||||
IHvExecutionContext nativeContext,
|
IHvExecutionContext nativeContext,
|
||||||
bool isEphemeral)
|
bool isEphemeral)
|
||||||
|
@@ -17,10 +17,10 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
private const int MaxActiveVcpus = 4;
|
private const int MaxActiveVcpus = 4;
|
||||||
|
|
||||||
public static readonly HvVcpuPool Instance = new HvVcpuPool();
|
public static readonly HvVcpuPool Instance = new();
|
||||||
|
|
||||||
private int _totalVcpus;
|
private int _totalVcpus;
|
||||||
private int _maxVcpus;
|
private readonly int _maxVcpus;
|
||||||
|
|
||||||
public HvVcpuPool()
|
public HvVcpuPool()
|
||||||
{
|
{
|
||||||
@@ -69,17 +69,17 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
bool isEphemeral = newCount > _maxVcpus - MaxActiveVcpus;
|
bool isEphemeral = newCount > _maxVcpus - MaxActiveVcpus;
|
||||||
|
|
||||||
// Create VCPU.
|
// Create VCPU.
|
||||||
hv_vcpu_exit_t* exitInfo = null;
|
HvVcpuExit* exitInfo = null;
|
||||||
HvApi.hv_vcpu_create(out ulong vcpuHandle, ref exitInfo, IntPtr.Zero).ThrowOnError();
|
HvApi.hv_vcpu_create(out ulong vcpuHandle, ref exitInfo, IntPtr.Zero).ThrowOnError();
|
||||||
|
|
||||||
// Enable FP and SIMD instructions.
|
// Enable FP and SIMD instructions.
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, hv_sys_reg_t.HV_SYS_REG_CPACR_EL1, 0b11 << 20).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.CPACR_EL1, 0b11 << 20).ThrowOnError();
|
||||||
|
|
||||||
addressSpace.InitializeMmu(vcpuHandle);
|
addressSpace.InitializeMmu(vcpuHandle);
|
||||||
|
|
||||||
HvExecutionContextVcpu nativeContext = new HvExecutionContextVcpu(vcpuHandle);
|
HvExecutionContextVcpu nativeContext = new(vcpuHandle);
|
||||||
|
|
||||||
HvVcpu vcpu = new HvVcpu(vcpuHandle, exitInfo, shadowContext, nativeContext, isEphemeral);
|
HvVcpu vcpu = new(vcpuHandle, exitInfo, shadowContext, nativeContext, isEphemeral);
|
||||||
|
|
||||||
return vcpu;
|
return vcpu;
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
private static int _addressSpaces;
|
private static int _addressSpaces;
|
||||||
private static HvIpaAllocator _ipaAllocator;
|
private static HvIpaAllocator _ipaAllocator;
|
||||||
private static object _lock = new object();
|
private static readonly object _lock = new();
|
||||||
|
|
||||||
public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block)
|
public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block)
|
||||||
{
|
{
|
||||||
@@ -36,7 +36,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
|
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rwx = hv_memory_flags_t.HV_MEMORY_READ | hv_memory_flags_t.HV_MEMORY_WRITE | hv_memory_flags_t.HV_MEMORY_EXEC;
|
var rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec;
|
||||||
|
|
||||||
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();
|
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
PtcLoadingState.Start => LoadState.Unloaded,
|
PtcLoadingState.Start => LoadState.Unloaded,
|
||||||
PtcLoadingState.Loading => LoadState.Loading,
|
PtcLoadingState.Loading => LoadState.Loading,
|
||||||
PtcLoadingState.Loaded => LoadState.Loaded,
|
PtcLoadingState.Loaded => LoadState.Loaded,
|
||||||
_ => throw new ArgumentException($"Invalid load state \"{newState}\".")
|
_ => throw new ArgumentException($"Invalid load state \"{newState}\"."),
|
||||||
};
|
};
|
||||||
|
|
||||||
StateChanged?.Invoke(state, current, total);
|
StateChanged?.Invoke(state, current, total);
|
||||||
|
@@ -19,6 +19,10 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute);
|
public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute);
|
||||||
public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute);
|
public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute);
|
||||||
|
|
||||||
public void Dispose() => _impl.Dispose();
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
_impl.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -84,7 +84,6 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
|
|
||||||
ulong remainingSize = size;
|
ulong remainingSize = size;
|
||||||
ulong oVa = va;
|
ulong oVa = va;
|
||||||
ulong oPa = pa;
|
|
||||||
while (remainingSize != 0)
|
while (remainingSize != 0)
|
||||||
{
|
{
|
||||||
_pageTable.Write((va / PageSize) * PteSize, PaToPte(pa));
|
_pageTable.Write((va / PageSize) * PteSize, PaToPte(pa));
|
||||||
@@ -246,7 +245,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
|
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size));
|
data[..size].CopyTo(_backingMemory.GetSpan(pa, size));
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
@@ -298,7 +297,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
|
public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@@ -345,7 +344,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
||||||
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetPagesCount(ulong va, uint size, out ulong startVa)
|
private static int GetPagesCount(ulong va, uint size, out ulong startVa)
|
||||||
{
|
{
|
||||||
// WARNING: Always check if ulong does not overflow during the operations.
|
// WARNING: Always check if ulong does not overflow during the operations.
|
||||||
startVa = va & ~(ulong)PageMask;
|
startVa = va & ~(ulong)PageMask;
|
||||||
@@ -482,7 +481,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
|
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
_backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size));
|
_backingMemory.GetSpan(pa, size).CopyTo(data[..size]);
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
@@ -576,6 +575,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private ulong GetPhysicalAddress(ulong va)
|
private ulong GetPhysicalAddress(ulong va)
|
||||||
{
|
{
|
||||||
// We return -1L if the virtual address is invalid or unmapped.
|
// We return -1L if the virtual address is invalid or unmapped.
|
||||||
@@ -586,6 +586,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
|
|
||||||
return GetPhysicalAddressInternal(va);
|
return GetPhysicalAddressInternal(va);
|
||||||
}
|
}
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
private ulong GetPhysicalAddressInternal(ulong va)
|
private ulong GetPhysicalAddressInternal(ulong va)
|
||||||
{
|
{
|
||||||
@@ -604,7 +605,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
MemoryPermission.None => 0L,
|
MemoryPermission.None => 0L,
|
||||||
MemoryPermission.Write => 2L << PointerTagBit,
|
MemoryPermission.Write => 2L << PointerTagBit,
|
||||||
_ => 3L << PointerTagBit
|
_ => 3L << PointerTagBit,
|
||||||
};
|
};
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
@@ -698,6 +699,8 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void Destroy() => _pageTable.Dispose();
|
protected override void Destroy() => _pageTable.Dispose();
|
||||||
|
|
||||||
private void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
|
private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
|
||||||
|
#pragma warning restore IDE0051
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
|
|
||||||
MappedReplicated = 0x5555555555555555,
|
MappedReplicated = 0x5555555555555555,
|
||||||
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
|
WriteTrackedReplicated = 0xaaaaaaaaaaaaaaaa,
|
||||||
ReadWriteTrackedReplicated = ulong.MaxValue
|
ReadWriteTrackedReplicated = ulong.MaxValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly InvalidAccessHandler _invalidAccessHandler;
|
private readonly InvalidAccessHandler _invalidAccessHandler;
|
||||||
@@ -404,7 +404,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
|
private static void GetPageBlockRange(ulong pageStart, ulong pageEnd, out ulong startMask, out ulong endMask, out int pageIndex, out int pageEndIndex)
|
||||||
{
|
{
|
||||||
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
|
startMask = ulong.MaxValue << ((int)(pageStart & 31) << 1);
|
||||||
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
|
endMask = ulong.MaxValue >> (64 - ((int)(pageEnd & 31) << 1));
|
||||||
@@ -606,7 +606,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
/// <param name="startVa">The virtual address of the beginning of the first page</param>
|
||||||
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
/// <remarks>This function does not differentiate between allocated and unallocated pages.</remarks>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetPagesCount(ulong va, ulong size, out ulong startVa)
|
private static int GetPagesCount(ulong va, ulong size, out ulong startVa)
|
||||||
{
|
{
|
||||||
// WARNING: Always check if ulong does not overflow during the operations.
|
// WARNING: Always check if ulong does not overflow during the operations.
|
||||||
startVa = va & ~(ulong)PageMask;
|
startVa = va & ~(ulong)PageMask;
|
||||||
@@ -697,7 +697,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
MemoryPermission.None => MemoryPermission.ReadAndWrite,
|
MemoryPermission.None => MemoryPermission.ReadAndWrite,
|
||||||
MemoryPermission.Write => MemoryPermission.Read,
|
MemoryPermission.Write => MemoryPermission.Read,
|
||||||
_ => MemoryPermission.None
|
_ => MemoryPermission.None,
|
||||||
};
|
};
|
||||||
|
|
||||||
_addressSpace.Base.Reprotect(va, size, protection, false);
|
_addressSpace.Base.Reprotect(va, size, protection, false);
|
||||||
|
@@ -7,6 +7,6 @@ namespace Ryujinx.Cpu
|
|||||||
{
|
{
|
||||||
Unloaded,
|
Unloaded,
|
||||||
Loading,
|
Loading,
|
||||||
Loaded
|
Loaded,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -10,7 +10,6 @@ namespace Ryujinx.Cpu
|
|||||||
{
|
{
|
||||||
private delegate bool TrackingEventDelegate(ulong address, ulong size, bool write);
|
private delegate bool TrackingEventDelegate(ulong address, ulong size, bool write);
|
||||||
|
|
||||||
private readonly MemoryTracking _tracking;
|
|
||||||
private readonly TrackingEventDelegate _trackingEvent;
|
private readonly TrackingEventDelegate _trackingEvent;
|
||||||
|
|
||||||
private readonly ulong _baseAddress;
|
private readonly ulong _baseAddress;
|
||||||
@@ -18,12 +17,10 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking)
|
public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking)
|
||||||
{
|
{
|
||||||
_tracking = tracking;
|
|
||||||
|
|
||||||
_baseAddress = (ulong)addressSpace.Pointer;
|
_baseAddress = (ulong)addressSpace.Pointer;
|
||||||
ulong endAddress = _baseAddress + addressSpace.Size;
|
ulong endAddress = _baseAddress + addressSpace.Size;
|
||||||
|
|
||||||
_trackingEvent = new TrackingEventDelegate(tracking.VirtualMemoryEvent);
|
_trackingEvent = tracking.VirtualMemoryEvent;
|
||||||
bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
||||||
|
|
||||||
if (!added)
|
if (!added)
|
||||||
@@ -51,6 +48,8 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress);
|
NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress);
|
||||||
|
|
||||||
if (_mirrorAddress != 0)
|
if (_mirrorAddress != 0)
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -26,12 +25,12 @@ namespace Ryujinx.Cpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe static T Read<T>(IVirtualMemoryManager memory, ulong position) where T : unmanaged
|
public static T Read<T>(IVirtualMemoryManager memory, ulong position) where T : unmanaged
|
||||||
{
|
{
|
||||||
return MemoryMarshal.Cast<byte, T>(memory.GetSpan(position, Unsafe.SizeOf<T>()))[0];
|
return MemoryMarshal.Cast<byte, T>(memory.GetSpan(position, Unsafe.SizeOf<T>()))[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe static ulong Write<T>(IVirtualMemoryManager memory, ulong position, T value) where T : unmanaged
|
public static ulong Write<T>(IVirtualMemoryManager memory, ulong position, T value) where T : unmanaged
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
|
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
|
||||||
|
|
||||||
@@ -42,8 +41,8 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
public static string ReadAsciiString(IVirtualMemoryManager memory, ulong position, long maxSize = -1)
|
public static string ReadAsciiString(IVirtualMemoryManager memory, ulong position, long maxSize = -1)
|
||||||
{
|
{
|
||||||
using (RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream())
|
using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream();
|
||||||
{
|
|
||||||
for (long offs = 0; offs < maxSize || maxSize == -1; offs++)
|
for (long offs = 0; offs < maxSize || maxSize == -1; offs++)
|
||||||
{
|
{
|
||||||
byte value = memory.Read<byte>(position + (ulong)offs);
|
byte value = memory.Read<byte>(position + (ulong)offs);
|
||||||
@@ -60,4 +59,3 @@ namespace Ryujinx.Cpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@@ -3,7 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Cpu
|
namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
struct PrivateMemoryAllocation : IDisposable
|
readonly struct PrivateMemoryAllocation : IDisposable
|
||||||
{
|
{
|
||||||
private readonly PrivateMemoryAllocator _owner;
|
private readonly PrivateMemoryAllocator _owner;
|
||||||
private readonly PrivateMemoryAllocator.Block _block;
|
private readonly PrivateMemoryAllocator.Block _block;
|
||||||
@@ -27,8 +27,8 @@ namespace Ryujinx.Cpu
|
|||||||
|
|
||||||
public (PrivateMemoryAllocation, PrivateMemoryAllocation) Split(ulong splitOffset)
|
public (PrivateMemoryAllocation, PrivateMemoryAllocation) Split(ulong splitOffset)
|
||||||
{
|
{
|
||||||
PrivateMemoryAllocation left = new PrivateMemoryAllocation(_owner, _block, Offset, splitOffset);
|
PrivateMemoryAllocation left = new(_owner, _block, Offset, splitOffset);
|
||||||
PrivateMemoryAllocation right = new PrivateMemoryAllocation(_owner, _block, Offset + splitOffset, Size - splitOffset);
|
PrivateMemoryAllocation right = new(_owner, _block, Offset + splitOffset, Size - splitOffset);
|
||||||
|
|
||||||
return (left, right);
|
return (left, right);
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Cpu
|
|||||||
public MemoryBlock Memory { get; private set; }
|
public MemoryBlock Memory { get; private set; }
|
||||||
public ulong Size { get; }
|
public ulong Size { get; }
|
||||||
|
|
||||||
private struct Range : IComparable<Range>
|
private readonly struct Range : IComparable<Range>
|
||||||
{
|
{
|
||||||
public ulong Offset { get; }
|
public ulong Offset { get; }
|
||||||
public ulong Size { get; }
|
public ulong Size { get; }
|
||||||
@@ -40,7 +40,7 @@ namespace Ryujinx.Cpu
|
|||||||
Size = size;
|
Size = size;
|
||||||
_freeRanges = new List<Range>
|
_freeRanges = new List<Range>
|
||||||
{
|
{
|
||||||
new Range(0, size)
|
new Range(0, size),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ namespace Ryujinx.Cpu
|
|||||||
{
|
{
|
||||||
private const ulong InvalidOffset = ulong.MaxValue;
|
private const ulong InvalidOffset = ulong.MaxValue;
|
||||||
|
|
||||||
public struct Allocation
|
public readonly struct Allocation
|
||||||
{
|
{
|
||||||
public T Block { get; }
|
public T Block { get; }
|
||||||
public ulong Offset { get; }
|
public ulong Offset { get; }
|
||||||
|
@@ -1,14 +1,7 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Ryujinx.Audio.Renderer.Dsp;
|
using Ryujinx.Audio.Renderer.Dsp;
|
||||||
using Ryujinx.Audio.Renderer.Parameter;
|
using Ryujinx.Audio.Renderer.Parameter;
|
||||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
||||||
{
|
{
|
||||||
@@ -41,8 +34,8 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
/// <param name="quality">The resampler quality to use</param>
|
/// <param name="quality">The resampler quality to use</param>
|
||||||
private static void DoResamplingTest(int inputRate, int outputRate, VoiceInParameter.SampleRateConversionQuality quality)
|
private static void DoResamplingTest(int inputRate, int outputRate, VoiceInParameter.SampleRateConversionQuality quality)
|
||||||
{
|
{
|
||||||
float inputSampleRate = (float)inputRate;
|
float inputSampleRate = inputRate;
|
||||||
float outputSampleRate = (float)outputRate;
|
float outputSampleRate = outputRate;
|
||||||
int inputSampleCount = inputRate;
|
int inputSampleCount = inputRate;
|
||||||
int outputSampleCount = outputRate;
|
int outputSampleCount = outputRate;
|
||||||
short[] inputBuffer = new short[inputSampleCount + 100]; // add some safety buffer at the end
|
short[] inputBuffer = new short[inputSampleCount + 100]; // add some safety buffer at the end
|
||||||
@@ -50,7 +43,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
for (int sample = 0; sample < inputBuffer.Length; sample++)
|
for (int sample = 0; sample < inputBuffer.Length; sample++)
|
||||||
{
|
{
|
||||||
// 440 hz sine wave with amplitude = 0.5f at input sample rate
|
// 440 hz sine wave with amplitude = 0.5f at input sample rate
|
||||||
inputBuffer[sample] = (short)(32767 * MathF.Sin((440 / inputSampleRate) * (float)sample * MathF.PI * 2f) * 0.5f);
|
inputBuffer[sample] = (short)(32767 * MathF.Sin((440 / inputSampleRate) * sample * MathF.PI * 2f) * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float fraction = 0;
|
float fraction = 0;
|
||||||
@@ -70,14 +63,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
{
|
{
|
||||||
VoiceInParameter.SampleRateConversionQuality.High => 3,
|
VoiceInParameter.SampleRateConversionQuality.High => 3,
|
||||||
VoiceInParameter.SampleRateConversionQuality.Default => 1,
|
VoiceInParameter.SampleRateConversionQuality.Default => 1,
|
||||||
_ => 0
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int sample = 0; sample < outputSampleCount; sample++)
|
for (int sample = 0; sample < outputSampleCount; sample++)
|
||||||
{
|
{
|
||||||
outputBuffer[sample] /= 32767;
|
outputBuffer[sample] /= 32767;
|
||||||
// 440 hz sine wave with amplitude = 0.5f at output sample rate
|
// 440 hz sine wave with amplitude = 0.5f at output sample rate
|
||||||
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (float)(sample + delay) * MathF.PI * 2f) * 0.5f;
|
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (sample + delay) * MathF.PI * 2f) * 0.5f;
|
||||||
float thisDelta = Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
|
float thisDelta = Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
|
||||||
|
|
||||||
// Ensure no discontinuities
|
// Ensure no discontinuities
|
||||||
@@ -85,7 +78,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
sumDifference += thisDelta;
|
sumDifference += thisDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
sumDifference = sumDifference / (float)outputSampleCount;
|
sumDifference /= outputSampleCount;
|
||||||
// Expect the output to be 99% similar to the expected resampled sine wave
|
// Expect the output to be 99% similar to the expected resampled sine wave
|
||||||
Assert.IsTrue(sumDifference < 0.01f);
|
Assert.IsTrue(sumDifference < 0.01f);
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,7 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Ryujinx.Audio.Renderer.Dsp;
|
using Ryujinx.Audio.Renderer.Dsp;
|
||||||
using Ryujinx.Audio.Renderer.Parameter;
|
|
||||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
||||||
{
|
{
|
||||||
@@ -17,7 +10,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestUpsamplerConsistency()
|
public void TestUpsamplerConsistency()
|
||||||
{
|
{
|
||||||
UpsamplerBufferState bufferState = new UpsamplerBufferState();
|
UpsamplerBufferState bufferState = new();
|
||||||
int inputBlockSize = 160;
|
int inputBlockSize = 160;
|
||||||
int numInputSamples = 32000;
|
int numInputSamples = 32000;
|
||||||
int numOutputSamples = 48000;
|
int numOutputSamples = 48000;
|
||||||
@@ -28,14 +21,14 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
for (int sample = 0; sample < inputBuffer.Length; sample++)
|
for (int sample = 0; sample < inputBuffer.Length; sample++)
|
||||||
{
|
{
|
||||||
// 440 hz sine wave with amplitude = 0.5f at input sample rate
|
// 440 hz sine wave with amplitude = 0.5f at input sample rate
|
||||||
inputBuffer[sample] = MathF.Sin((440 / inputSampleRate) * (float)sample * MathF.PI * 2f) * 0.5f;
|
inputBuffer[sample] = MathF.Sin((440 / inputSampleRate) * sample * MathF.PI * 2f) * 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int inputIdx = 0;
|
int inputIdx = 0;
|
||||||
int outputIdx = 0;
|
int outputIdx = 0;
|
||||||
while (inputIdx + inputBlockSize < numInputSamples)
|
while (inputIdx + inputBlockSize < numInputSamples)
|
||||||
{
|
{
|
||||||
int outputBufLength = (int)Math.Round((float)(inputIdx + inputBlockSize) * outputSampleRate / inputSampleRate) - outputIdx;
|
int outputBufLength = (int)Math.Round((inputIdx + inputBlockSize) * outputSampleRate / inputSampleRate) - outputIdx;
|
||||||
UpsamplerHelper.Upsample(
|
UpsamplerHelper.Upsample(
|
||||||
outputBuffer.AsSpan(outputIdx),
|
outputBuffer.AsSpan(outputIdx),
|
||||||
inputBuffer.AsSpan(inputIdx),
|
inputBuffer.AsSpan(inputIdx),
|
||||||
@@ -52,11 +45,11 @@ namespace Ryujinx.Tests.Audio.Renderer.Dsp
|
|||||||
for (int sample = 0; sample < numOutputSamples; sample++)
|
for (int sample = 0; sample < numOutputSamples; sample++)
|
||||||
{
|
{
|
||||||
// 440 hz sine wave with amplitude = 0.5f at output sample rate with an offset of 15
|
// 440 hz sine wave with amplitude = 0.5f at output sample rate with an offset of 15
|
||||||
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (float)(sample - 15) * MathF.PI * 2f) * 0.5f;
|
expectedOutput[sample] = MathF.Sin((440 / outputSampleRate) * (sample - 15) * MathF.PI * 2f) * 0.5f;
|
||||||
sumDifference += Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
|
sumDifference += Math.Abs(expectedOutput[sample] - outputBuffer[sample]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sumDifference = sumDifference / (float)expectedOutput.Length;
|
sumDifference /= expectedOutput.Length;
|
||||||
// Expect the output to be 98% similar to the expected resampled sine wave
|
// Expect the output to be 98% similar to the expected resampled sine wave
|
||||||
Assert.IsTrue(sumDifference < 0.02f);
|
Assert.IsTrue(sumDifference < 0.02f);
|
||||||
}
|
}
|
||||||
|
@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,4 +13,3 @@ namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestsMemoryPoolForceMappingEnabled()
|
public void TestsMemoryPoolForceMappingEnabled()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision1()
|
public void TestRevision1()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision1);
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision2()
|
public void TestRevision2()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision2);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision2);
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision3()
|
public void TestRevision3()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision3);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision3);
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision4()
|
public void TestRevision4()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision4);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision4);
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision5()
|
public void TestRevision5()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision5);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision5);
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision6()
|
public void TestRevision6()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision6);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision6);
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision7()
|
public void TestRevision7()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision7);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision7);
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision8()
|
public void TestRevision8()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision8);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision8);
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision9()
|
public void TestRevision9()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision9);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision9);
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRevision10()
|
public void TestRevision10()
|
||||||
{
|
{
|
||||||
BehaviourContext behaviourContext = new BehaviourContext();
|
BehaviourContext behaviourContext = new();
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision10);
|
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision10);
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestInitializeSystemPool()
|
public void TestInitializeSystemPool()
|
||||||
{
|
{
|
||||||
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
|
PoolMapper poolMapper = new(DummyProcessHandle, true);
|
||||||
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
||||||
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestGetProcessHandle()
|
public void TestGetProcessHandle()
|
||||||
{
|
{
|
||||||
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
|
PoolMapper poolMapper = new(DummyProcessHandle, true);
|
||||||
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
||||||
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestMappings()
|
public void TestMappings()
|
||||||
{
|
{
|
||||||
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
|
PoolMapper poolMapper = new(DummyProcessHandle, true);
|
||||||
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
||||||
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
|
||||||
|
|
||||||
@@ -85,13 +85,12 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize);
|
memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorInfo errorInfo;
|
|
||||||
|
|
||||||
AddressInfo addressInfo = AddressInfo.Create();
|
AddressInfo addressInfo = AddressInfo.Create();
|
||||||
|
|
||||||
PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);
|
PoolMapper poolMapper = new(DummyProcessHandle, true);
|
||||||
|
|
||||||
Assert.IsTrue(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0));
|
Assert.IsTrue(poolMapper.TryAttachBuffer(out ErrorInfo errorInfo, ref addressInfo, 0, 0));
|
||||||
|
|
||||||
Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
|
Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
|
||||||
Assert.AreEqual(0, errorInfo.ExtraErrorInfo);
|
Assert.AreEqual(0, errorInfo.ExtraErrorInfo);
|
||||||
@@ -105,7 +104,7 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
|||||||
|
|
||||||
poolMapper = new PoolMapper(DummyProcessHandle, false);
|
poolMapper = new PoolMapper(DummyProcessHandle, false);
|
||||||
|
|
||||||
Assert.IsFalse(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0));
|
Assert.IsFalse(poolMapper.TryAttachBuffer(out _, ref addressInfo, 0, 0));
|
||||||
|
|
||||||
addressInfo.ForceMappedDspAddress = 0;
|
addressInfo.ForceMappedDspAddress = 0;
|
||||||
|
|
||||||
|
@@ -14,13 +14,15 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
public class CpuTest
|
public class CpuTest
|
||||||
{
|
{
|
||||||
protected static readonly ulong Size = MemoryBlock.GetPageSize();
|
protected static readonly ulong Size = MemoryBlock.GetPageSize();
|
||||||
|
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||||
protected static ulong CodeBaseAddress = Size;
|
protected static ulong CodeBaseAddress = Size;
|
||||||
protected static ulong DataBaseAddress = CodeBaseAddress + Size;
|
protected static ulong DataBaseAddress = CodeBaseAddress + Size;
|
||||||
|
#pragma warning restore CA2211
|
||||||
|
|
||||||
private static bool Ignore_FpcrFz = false;
|
private static readonly bool _ignoreFpcrFz = false;
|
||||||
private static bool Ignore_FpcrDn = false;
|
private static readonly bool _ignoreFpcrDn = false;
|
||||||
|
|
||||||
private static bool IgnoreAllExcept_FpsrQc = false;
|
private static readonly bool _ignoreAllExceptFpsrQc = false;
|
||||||
|
|
||||||
private ulong _currAddress;
|
private ulong _currAddress;
|
||||||
|
|
||||||
@@ -208,12 +210,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
int fpsr = 0,
|
int fpsr = 0,
|
||||||
bool runUnicorn = true)
|
bool runUnicorn = true)
|
||||||
{
|
{
|
||||||
if (Ignore_FpcrFz)
|
if (_ignoreFpcrFz)
|
||||||
{
|
{
|
||||||
fpcr &= ~(1 << (int)Fpcr.Fz);
|
fpcr &= ~(1 << (int)Fpcr.Fz);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ignore_FpcrDn)
|
if (_ignoreFpcrDn)
|
||||||
{
|
{
|
||||||
fpcr &= ~(1 << (int)Fpcr.Dn);
|
fpcr &= ~(1 << (int)Fpcr.Dn);
|
||||||
}
|
}
|
||||||
@@ -254,8 +256,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
/// <summary>Round towards Minus Infinity mode.</summary>
|
/// <summary>Round towards Minus Infinity mode.</summary>
|
||||||
Rm,
|
Rm,
|
||||||
/// <summary>Round towards Zero mode.</summary>
|
/// <summary>Round towards Zero mode.</summary>
|
||||||
Rz
|
Rz,
|
||||||
};
|
}
|
||||||
|
|
||||||
/// <summary>Floating-point Control Register.</summary>
|
/// <summary>Floating-point Control Register.</summary>
|
||||||
protected enum Fpcr
|
protected enum Fpcr
|
||||||
@@ -267,11 +269,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
/// <summary>Default NaN mode control bit.</summary>
|
/// <summary>Default NaN mode control bit.</summary>
|
||||||
Dn = 25,
|
Dn = 25,
|
||||||
/// <summary>Alternative half-precision control bit.</summary>
|
/// <summary>Alternative half-precision control bit.</summary>
|
||||||
Ahp = 26
|
Ahp = 26,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Floating-point Status Register.</summary>
|
/// <summary>Floating-point Status Register.</summary>
|
||||||
[Flags] protected enum Fpsr
|
[Flags]
|
||||||
|
protected enum Fpsr
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
@@ -289,10 +292,11 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Idc = 1 << 7,
|
Idc = 1 << 7,
|
||||||
|
|
||||||
/// <summary>Cumulative saturation bit.</summary>
|
/// <summary>Cumulative saturation bit.</summary>
|
||||||
Qc = 1 << 27
|
Qc = 1 << 27,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags] protected enum FpSkips
|
[Flags]
|
||||||
|
protected enum FpSkips
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
@@ -300,7 +304,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
IfNaND = 2,
|
IfNaND = 2,
|
||||||
|
|
||||||
IfUnderflow = 4,
|
IfUnderflow = 4,
|
||||||
IfOverflow = 8
|
IfOverflow = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected enum FpTolerances
|
protected enum FpTolerances
|
||||||
@@ -308,7 +312,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
None,
|
None,
|
||||||
|
|
||||||
UpToOneUlpsS,
|
UpToOneUlpsS,
|
||||||
UpToOneUlpsD
|
UpToOneUlpsD,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void CompareAgainstUnicorn(
|
protected void CompareAgainstUnicorn(
|
||||||
@@ -316,7 +320,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
FpSkips fpSkips = FpSkips.None,
|
FpSkips fpSkips = FpSkips.None,
|
||||||
FpTolerances fpTolerances = FpTolerances.None)
|
FpTolerances fpTolerances = FpTolerances.None)
|
||||||
{
|
{
|
||||||
if (IgnoreAllExcept_FpsrQc)
|
if (_ignoreAllExceptFpsrQc)
|
||||||
{
|
{
|
||||||
fpsrMask &= Fpsr.Qc;
|
fpsrMask &= Fpsr.Qc;
|
||||||
}
|
}
|
||||||
@@ -326,6 +330,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
ManageFpSkips(fpSkips);
|
ManageFpSkips(fpSkips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Assert.That(_context.GetX(0), Is.EqualTo(_unicornEmu.X[0]), "X0");
|
Assert.That(_context.GetX(0), Is.EqualTo(_unicornEmu.X[0]), "X0");
|
||||||
Assert.That(_context.GetX(1), Is.EqualTo(_unicornEmu.X[1]), "X1");
|
Assert.That(_context.GetX(1), Is.EqualTo(_unicornEmu.X[1]), "X1");
|
||||||
Assert.That(_context.GetX(2), Is.EqualTo(_unicornEmu.X[2]), "X2");
|
Assert.That(_context.GetX(2), Is.EqualTo(_unicornEmu.X[2]), "X2");
|
||||||
@@ -358,6 +363,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Assert.That(_context.GetX(29), Is.EqualTo(_unicornEmu.X[29]));
|
Assert.That(_context.GetX(29), Is.EqualTo(_unicornEmu.X[29]));
|
||||||
Assert.That(_context.GetX(30), Is.EqualTo(_unicornEmu.X[30]));
|
Assert.That(_context.GetX(30), Is.EqualTo(_unicornEmu.X[30]));
|
||||||
Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31");
|
Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31");
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
|
||||||
if (fpTolerances == FpTolerances.None)
|
if (fpTolerances == FpTolerances.None)
|
||||||
{
|
{
|
||||||
@@ -367,6 +373,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
ManageFpTolerances(fpTolerances);
|
ManageFpTolerances(fpTolerances);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1");
|
Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1");
|
||||||
Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2");
|
Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2");
|
||||||
Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3");
|
Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3");
|
||||||
@@ -409,6 +417,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr), "Fpcr");
|
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr), "Fpcr");
|
||||||
Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr");
|
Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr");
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
|
||||||
if (_usingMemory)
|
if (_usingMemory)
|
||||||
{
|
{
|
||||||
@@ -513,13 +522,13 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
|
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static V128 MakeVectorScalar(float value) => new V128(value);
|
protected static V128 MakeVectorScalar(float value) => new(value);
|
||||||
protected static V128 MakeVectorScalar(double value) => new V128(value);
|
protected static V128 MakeVectorScalar(double value) => new(value);
|
||||||
|
|
||||||
protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0);
|
protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
|
||||||
protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1);
|
protected static V128 MakeVectorE1(ulong e1) => new(0, e1);
|
||||||
|
|
||||||
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new V128(e0, e1);
|
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new(e0, e1);
|
||||||
|
|
||||||
protected static ulong GetVectorE0(V128 vector) => vector.Extract<ulong>(0);
|
protected static ulong GetVectorE0(V128 vector) => vector.Extract<ulong>(0);
|
||||||
protected static ulong GetVectorE1(V128 vector) => vector.Extract<ulong>(1);
|
protected static ulong GetVectorE1(V128 vector) => vector.Extract<ulong>(1);
|
||||||
@@ -528,7 +537,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUShort();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUShort();
|
||||||
while ((rnd & 0x7C00u) == 0u ||
|
while ((rnd & 0x7C00u) == 0u ||
|
||||||
(~rnd & 0x7C00u) == 0u);
|
(~rnd & 0x7C00u) == 0u);
|
||||||
|
|
||||||
@@ -539,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUShort();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUShort();
|
||||||
while ((rnd & 0x03FFu) == 0u);
|
while ((rnd & 0x03FFu) == 0u);
|
||||||
|
|
||||||
return (ushort)(rnd & 0x83FFu);
|
return (ushort)(rnd & 0x83FFu);
|
||||||
@@ -549,7 +560,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUInt();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUInt();
|
||||||
while ((rnd & 0x7F800000u) == 0u ||
|
while ((rnd & 0x7F800000u) == 0u ||
|
||||||
(~rnd & 0x7F800000u) == 0u);
|
(~rnd & 0x7F800000u) == 0u);
|
||||||
|
|
||||||
@@ -560,7 +572,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUInt();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUInt();
|
||||||
while ((rnd & 0x007FFFFFu) == 0u);
|
while ((rnd & 0x007FFFFFu) == 0u);
|
||||||
|
|
||||||
return rnd & 0x807FFFFFu;
|
return rnd & 0x807FFFFFu;
|
||||||
@@ -570,7 +583,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
ulong rnd;
|
ulong rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextULong();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextULong();
|
||||||
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
|
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
|
||||||
(~rnd & 0x7FF0000000000000ul) == 0ul);
|
(~rnd & 0x7FF0000000000000ul) == 0ul);
|
||||||
|
|
||||||
@@ -581,7 +595,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
ulong rnd;
|
ulong rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextULong();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextULong();
|
||||||
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
|
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
|
||||||
|
|
||||||
return rnd & 0x800FFFFFFFFFFFFFul;
|
return rnd & 0x800FFFFFFFFFFFFFul;
|
||||||
|
@@ -14,8 +14,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
public class CpuTest32
|
public class CpuTest32
|
||||||
{
|
{
|
||||||
protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
|
protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
|
||||||
|
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||||
protected static uint CodeBaseAddress = Size;
|
protected static uint CodeBaseAddress = Size;
|
||||||
protected static uint DataBaseAddress = CodeBaseAddress + Size;
|
protected static uint DataBaseAddress = CodeBaseAddress + Size;
|
||||||
|
#pragma warning restore CA2211
|
||||||
|
|
||||||
private uint _currAddress;
|
private uint _currAddress;
|
||||||
|
|
||||||
@@ -288,16 +290,17 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
SetWorkingMemory(0, testMem);
|
SetWorkingMemory(0, testMem);
|
||||||
|
|
||||||
RunPrecomputedTestCase(new PrecomputedThumbTestCase(){
|
RunPrecomputedTestCase(new PrecomputedThumbTestCase
|
||||||
|
{
|
||||||
Instructions = test.Instructions,
|
Instructions = test.Instructions,
|
||||||
StartRegs = test.StartRegs,
|
StartRegs = test.StartRegs,
|
||||||
FinalRegs = test.FinalRegs,
|
FinalRegs = test.FinalRegs,
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var delta in test.MemoryDelta)
|
foreach (var (address, value) in test.MemoryDelta)
|
||||||
{
|
{
|
||||||
testMem[delta.Address - DataBaseAddress + 0] = (byte)(delta.Value >> 0);
|
testMem[address - DataBaseAddress + 0] = (byte)(value >> 0);
|
||||||
testMem[delta.Address - DataBaseAddress + 1] = (byte)(delta.Value >> 8);
|
testMem[address - DataBaseAddress + 1] = (byte)(value >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] mem = _memory.GetSpan(DataBaseAddress, (int)Size).ToArray();
|
byte[] mem = _memory.GetSpan(DataBaseAddress, (int)Size).ToArray();
|
||||||
@@ -324,8 +327,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
/// <summary>Round towards Minus Infinity mode.</summary>
|
/// <summary>Round towards Minus Infinity mode.</summary>
|
||||||
Rm,
|
Rm,
|
||||||
/// <summary>Round towards Zero mode.</summary>
|
/// <summary>Round towards Zero mode.</summary>
|
||||||
Rz
|
Rz,
|
||||||
};
|
}
|
||||||
|
|
||||||
/// <summary>Floating-point Control Register.</summary>
|
/// <summary>Floating-point Control Register.</summary>
|
||||||
protected enum Fpcr
|
protected enum Fpcr
|
||||||
@@ -337,7 +340,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
/// <summary>Default NaN mode control bit.</summary>
|
/// <summary>Default NaN mode control bit.</summary>
|
||||||
Dn = 25,
|
Dn = 25,
|
||||||
/// <summary>Alternative half-precision control bit.</summary>
|
/// <summary>Alternative half-precision control bit.</summary>
|
||||||
Ahp = 26
|
Ahp = 26,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Floating-point Status Register.</summary>
|
/// <summary>Floating-point Status Register.</summary>
|
||||||
@@ -363,7 +366,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Qc = 1 << 27,
|
Qc = 1 << 27,
|
||||||
|
|
||||||
/// <summary>NZCV flags.</summary>
|
/// <summary>NZCV flags.</summary>
|
||||||
Nzcv = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28)
|
Nzcv = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28),
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -375,7 +378,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
IfNaND = 2,
|
IfNaND = 2,
|
||||||
|
|
||||||
IfUnderflow = 4,
|
IfUnderflow = 4,
|
||||||
IfOverflow = 8
|
IfOverflow = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected enum FpTolerances
|
protected enum FpTolerances
|
||||||
@@ -383,7 +386,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
None,
|
None,
|
||||||
|
|
||||||
UpToOneUlpsS,
|
UpToOneUlpsS,
|
||||||
UpToOneUlpsD
|
UpToOneUlpsD,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void CompareAgainstUnicorn(
|
protected void CompareAgainstUnicorn(
|
||||||
@@ -554,13 +557,13 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
|
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static V128 MakeVectorScalar(float value) => new V128(value);
|
protected static V128 MakeVectorScalar(float value) => new(value);
|
||||||
protected static V128 MakeVectorScalar(double value) => new V128(value);
|
protected static V128 MakeVectorScalar(double value) => new(value);
|
||||||
|
|
||||||
protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0);
|
protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
|
||||||
protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1);
|
protected static V128 MakeVectorE1(ulong e1) => new(0, e1);
|
||||||
|
|
||||||
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new V128(e0, e1);
|
protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new(e0, e1);
|
||||||
|
|
||||||
protected static V128 MakeVectorE0E1E2E3(uint e0, uint e1, uint e2, uint e3)
|
protected static V128 MakeVectorE0E1E2E3(uint e0, uint e1, uint e2, uint e3)
|
||||||
{
|
{
|
||||||
@@ -574,7 +577,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUShort();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUShort();
|
||||||
while ((rnd & 0x7C00u) == 0u ||
|
while ((rnd & 0x7C00u) == 0u ||
|
||||||
(~rnd & 0x7C00u) == 0u);
|
(~rnd & 0x7C00u) == 0u);
|
||||||
|
|
||||||
@@ -585,7 +589,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUShort();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUShort();
|
||||||
while ((rnd & 0x03FFu) == 0u);
|
while ((rnd & 0x03FFu) == 0u);
|
||||||
|
|
||||||
return (ushort)(rnd & 0x83FFu);
|
return (ushort)(rnd & 0x83FFu);
|
||||||
@@ -595,7 +600,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUInt();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUInt();
|
||||||
while ((rnd & 0x7F800000u) == 0u ||
|
while ((rnd & 0x7F800000u) == 0u ||
|
||||||
(~rnd & 0x7F800000u) == 0u);
|
(~rnd & 0x7F800000u) == 0u);
|
||||||
|
|
||||||
@@ -606,7 +612,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
uint rnd;
|
uint rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextUInt();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextUInt();
|
||||||
while ((rnd & 0x007FFFFFu) == 0u);
|
while ((rnd & 0x007FFFFFu) == 0u);
|
||||||
|
|
||||||
return rnd & 0x807FFFFFu;
|
return rnd & 0x807FFFFFu;
|
||||||
@@ -616,7 +623,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
ulong rnd;
|
ulong rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextULong();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextULong();
|
||||||
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
|
while ((rnd & 0x7FF0000000000000ul) == 0ul ||
|
||||||
(~rnd & 0x7FF0000000000000ul) == 0ul);
|
(~rnd & 0x7FF0000000000000ul) == 0ul);
|
||||||
|
|
||||||
@@ -627,7 +635,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
ulong rnd;
|
ulong rnd;
|
||||||
|
|
||||||
do rnd = TestContext.CurrentContext.Random.NextULong();
|
do
|
||||||
|
rnd = TestContext.CurrentContext.Random.NextULong();
|
||||||
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
|
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
|
||||||
|
|
||||||
return rnd & 0x800FFFFFFFFFFFFFul;
|
return rnd & 0x800FFFFFFFFFFFFFul;
|
||||||
|
@@ -33,8 +33,15 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private static uint GenLeadingZeros32(int cnt) // 0 <= cnt <= 32
|
private static uint GenLeadingZeros32(int cnt) // 0 <= cnt <= 32
|
||||||
{
|
{
|
||||||
if (cnt == 32) return 0u;
|
if (cnt == 32)
|
||||||
if (cnt == 31) return 1u;
|
{
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt == 31)
|
||||||
|
{
|
||||||
|
return 1u;
|
||||||
|
}
|
||||||
|
|
||||||
uint rnd = TestContext.CurrentContext.Random.NextUInt();
|
uint rnd = TestContext.CurrentContext.Random.NextUInt();
|
||||||
int mask = int.MinValue;
|
int mask = int.MinValue;
|
||||||
@@ -44,8 +51,15 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private static ulong GenLeadingZeros64(int cnt) // 0 <= cnt <= 64
|
private static ulong GenLeadingZeros64(int cnt) // 0 <= cnt <= 64
|
||||||
{
|
{
|
||||||
if (cnt == 64) return 0ul;
|
if (cnt == 64)
|
||||||
if (cnt == 63) return 1ul;
|
{
|
||||||
|
return 0ul;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt == 63)
|
||||||
|
{
|
||||||
|
return 1ul;
|
||||||
|
}
|
||||||
|
|
||||||
ulong rnd = TestContext.CurrentContext.Random.NextULong();
|
ulong rnd = TestContext.CurrentContext.Random.NextULong();
|
||||||
long mask = long.MinValue;
|
long mask = long.MinValue;
|
||||||
@@ -55,7 +69,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static IEnumerable<ulong> _GenLeadingSignsX_()
|
private static IEnumerable<ulong> GenLeadingSignsX()
|
||||||
{
|
{
|
||||||
for (int cnt = 0; cnt <= 63; cnt++)
|
for (int cnt = 0; cnt <= 63; cnt++)
|
||||||
{
|
{
|
||||||
@@ -64,7 +78,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<uint> _GenLeadingSignsW_()
|
private static IEnumerable<uint> GenLeadingSignsW()
|
||||||
{
|
{
|
||||||
for (int cnt = 0; cnt <= 31; cnt++)
|
for (int cnt = 0; cnt <= 31; cnt++)
|
||||||
{
|
{
|
||||||
@@ -73,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _GenLeadingZerosX_()
|
private static IEnumerable<ulong> GenLeadingZerosX()
|
||||||
{
|
{
|
||||||
for (int cnt = 0; cnt <= 64; cnt++)
|
for (int cnt = 0; cnt <= 64; cnt++)
|
||||||
{
|
{
|
||||||
@@ -81,7 +95,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<uint> _GenLeadingZerosW_()
|
private static IEnumerable<uint> GenLeadingZerosW()
|
||||||
{
|
{
|
||||||
for (int cnt = 0; cnt <= 32; cnt++)
|
for (int cnt = 0; cnt <= 32; cnt++)
|
||||||
{
|
{
|
||||||
@@ -93,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Test, Pairwise, Description("CLS <Xd>, <Xn>")]
|
[Test, Pairwise, Description("CLS <Xd>, <Xn>")]
|
||||||
public void Cls_64bit([Values(0u, 31u)] uint rd,
|
public void Cls_64bit([Values(0u, 31u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
[ValueSource(nameof(_GenLeadingSignsX_))] ulong xn)
|
[ValueSource(nameof(GenLeadingSignsX))] ulong xn)
|
||||||
{
|
{
|
||||||
uint opcode = 0xDAC01400; // CLS X0, X0
|
uint opcode = 0xDAC01400; // CLS X0, X0
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
@@ -108,7 +122,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Test, Pairwise, Description("CLS <Wd>, <Wn>")]
|
[Test, Pairwise, Description("CLS <Wd>, <Wn>")]
|
||||||
public void Cls_32bit([Values(0u, 31u)] uint rd,
|
public void Cls_32bit([Values(0u, 31u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
[ValueSource(nameof(_GenLeadingSignsW_))] uint wn)
|
[ValueSource(nameof(GenLeadingSignsW))] uint wn)
|
||||||
{
|
{
|
||||||
uint opcode = 0x5AC01400; // CLS W0, W0
|
uint opcode = 0x5AC01400; // CLS W0, W0
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
@@ -123,7 +137,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Test, Pairwise, Description("CLZ <Xd>, <Xn>")]
|
[Test, Pairwise, Description("CLZ <Xd>, <Xn>")]
|
||||||
public void Clz_64bit([Values(0u, 31u)] uint rd,
|
public void Clz_64bit([Values(0u, 31u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
[ValueSource(nameof(_GenLeadingZerosX_))] ulong xn)
|
[ValueSource(nameof(GenLeadingZerosX))] ulong xn)
|
||||||
{
|
{
|
||||||
uint opcode = 0xDAC01000; // CLZ X0, X0
|
uint opcode = 0xDAC01000; // CLZ X0, X0
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
@@ -138,7 +152,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Test, Pairwise, Description("CLZ <Wd>, <Wn>")]
|
[Test, Pairwise, Description("CLZ <Wd>, <Wn>")]
|
||||||
public void Clz_32bit([Values(0u, 31u)] uint rd,
|
public void Clz_32bit([Values(0u, 31u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
[ValueSource(nameof(_GenLeadingZerosW_))] uint wn)
|
[ValueSource(nameof(GenLeadingZerosW))] uint wn)
|
||||||
{
|
{
|
||||||
uint opcode = 0x5AC01000; // CLZ W0, W0
|
uint opcode = 0x5AC01000; // CLZ W0, W0
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#if Alu32
|
#if Alu32
|
||||||
|
|
||||||
#region "ValueSource (Opcodes)"
|
#region "ValueSource (Opcodes)"
|
||||||
private static uint[] _SU_H_AddSub_8_()
|
private static uint[] SuHAddSub8()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
@@ -21,22 +21,22 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xe6500f90u, // UADD8 R0, R0, R0
|
0xe6500f90u, // UADD8 R0, R0, R0
|
||||||
0xe6500ff0u, // USUB8 R0, R0, R0
|
0xe6500ff0u, // USUB8 R0, R0, R0
|
||||||
0xe6700f90u, // UHADD8 R0, R0, R0
|
0xe6700f90u, // UHADD8 R0, R0, R0
|
||||||
0xe6700ff0u // UHSUB8 R0, R0, R0
|
0xe6700ff0u, // UHSUB8 R0, R0, R0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] _Ssat_Usat_()
|
private static uint[] SsatUsat()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xe6a00010u, // SSAT R0, #1, R0, LSL #0
|
0xe6a00010u, // SSAT R0, #1, R0, LSL #0
|
||||||
0xe6a00050u, // SSAT R0, #1, R0, ASR #32
|
0xe6a00050u, // SSAT R0, #1, R0, ASR #32
|
||||||
0xe6e00010u, // USAT R0, #0, R0, LSL #0
|
0xe6e00010u, // USAT R0, #0, R0, LSL #0
|
||||||
0xe6e00050u // USAT R0, #0, R0, ASR #32
|
0xe6e00050u, // USAT R0, #0, R0, ASR #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] _Ssat16_Usat16_()
|
private static uint[] Ssat16Usat16()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
@@ -45,14 +45,14 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] _Lsr_Lsl_Asr_Ror_()
|
private static uint[] LsrLslAsrRor()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xe1b00030u, // LSRS R0, R0, R0
|
0xe1b00030u, // LSRS R0, R0, R0
|
||||||
0xe1b00010u, // LSLS R0, R0, R0
|
0xe1b00010u, // LSLS R0, R0, R0
|
||||||
0xe1b00050u, // ASRS R0, R0, R0
|
0xe1b00050u, // ASRS R0, R0, R0
|
||||||
0xe1b00070u // RORS R0, R0, R0
|
0xe1b00070u, // RORS R0, R0, R0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -76,7 +76,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(_Lsr_Lsl_Asr_Ror_))] uint opcode,
|
public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(LsrLslAsrRor))] uint opcode,
|
||||||
[Values(0x00000000u, 0x7FFFFFFFu,
|
[Values(0x00000000u, 0x7FFFFFFFu,
|
||||||
0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
|
0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
|
||||||
[Range(0, 31)] int shiftAmount)
|
[Range(0, 31)] int shiftAmount)
|
||||||
@@ -130,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Ssat_Usat([ValueSource(nameof(_Ssat_Usat_))] uint opcode,
|
public void Ssat_Usat([ValueSource(nameof(SsatUsat))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rd,
|
[Values(0u, 0xdu)] uint rd,
|
||||||
[Values(1u, 0xdu)] uint rn,
|
[Values(1u, 0xdu)] uint rn,
|
||||||
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
|
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
|
||||||
@@ -148,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Ssat16_Usat16([ValueSource(nameof(_Ssat16_Usat16_))] uint opcode,
|
public void Ssat16_Usat16([ValueSource(nameof(Ssat16Usat16))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rd,
|
[Values(0u, 0xdu)] uint rd,
|
||||||
[Values(1u, 0xdu)] uint rn,
|
[Values(1u, 0xdu)] uint rn,
|
||||||
[Values(0u, 7u, 8u, 0xfu)] uint sat,
|
[Values(0u, 7u, 8u, 0xfu)] uint sat,
|
||||||
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void SU_H_AddSub_8([ValueSource(nameof(_SU_H_AddSub_8_))] uint opcode,
|
public void SU_H_AddSub_8([ValueSource(nameof(SuHAddSub8))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rd,
|
[Values(0u, 0xdu)] uint rd,
|
||||||
[Values(1u)] uint rm,
|
[Values(1u)] uint rm,
|
||||||
[Values(2u)] uint rn,
|
[Values(2u)] uint rn,
|
||||||
|
@@ -48,7 +48,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
new CrcTest(0xffffffffu, 0x7f_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0x3303a3c3),
|
new CrcTest(0xffffffffu, 0x7f_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0x3303a3c3),
|
||||||
new CrcTest(0xffffffffu, 0x80_00_00_00_00_00_00_00u, false, 0x2dfd1072, 0xbe26ed00, 0xdebb20e3, 0x7765a3b6),
|
new CrcTest(0xffffffffu, 0x80_00_00_00_00_00_00_00u, false, 0x2dfd1072, 0xbe26ed00, 0xdebb20e3, 0x7765a3b6),
|
||||||
new CrcTest(0xffffffffu, 0xff_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0xdebb20e3),
|
new CrcTest(0xffffffffu, 0xff_ff_ff_ff_ff_ff_ff_ffu, false, 0x00ffffff, 0x0000ffff, 0x00000000, 0xdebb20e3),
|
||||||
new CrcTest(0xffffffffu, 0xa0_02_f1_ca_52_78_8c_1cu, false, 0x39fc4c3d, 0xbc5f7f56, 0x4ed8e906, 0x12cb419c)
|
new CrcTest(0xffffffffu, 0xa0_02_f1_ca_52_78_8c_1cu, false, 0x39fc4c3d, 0xbc5f7f56, 0x4ed8e906, 0x12cb419c),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -60,7 +60,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
new CrcTest32(0xffffffffu, 0x7f_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x82f63b78),
|
new CrcTest32(0xffffffffu, 0x7f_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x82f63b78),
|
||||||
new CrcTest32(0xffffffffu, 0x80_00_00_00u, true, 0xad82acae, 0x0e9e882d, 0x356e8f40),
|
new CrcTest32(0xffffffffu, 0x80_00_00_00u, true, 0xad82acae, 0x0e9e882d, 0x356e8f40),
|
||||||
new CrcTest32(0xffffffffu, 0xff_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x00000000),
|
new CrcTest32(0xffffffffu, 0xff_ff_ff_ffu, true, 0x00ffffff, 0x0000ffff, 0x00000000),
|
||||||
new CrcTest32(0xffffffffu, 0x9d_cb_12_f0u, true, 0x5eecc3db, 0xbb6111cb, 0xcfb54fc9)
|
new CrcTest32(0xffffffffu, 0x9d_cb_12_f0u, true, 0x5eecc3db, 0xbb6111cb, 0xcfb54fc9),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#if AluRs32
|
#if AluRs32
|
||||||
|
|
||||||
#region "ValueSource (Opcodes)"
|
#region "ValueSource (Opcodes)"
|
||||||
private static uint[] _opcodes()
|
private static uint[] Opcodes()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void TestCpuTestAluImm32([ValueSource(nameof(_opcodes))] uint opcode,
|
public void TestCpuTestAluImm32([ValueSource(nameof(Opcodes))] uint opcode,
|
||||||
[Values(0u, 13u)] uint rd,
|
[Values(0u, 13u)] uint rd,
|
||||||
[Values(1u, 13u)] uint rn,
|
[Values(1u, 13u)] uint rn,
|
||||||
[Random(RndCnt)] uint imm,
|
[Random(RndCnt)] uint imm,
|
||||||
|
@@ -17,7 +17,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xe0800000u, // ADD R0, R0, R0, LSL #0
|
0xe0800000u, // ADD R0, R0, R0, LSL #0
|
||||||
0xe0900000u, // ADDS R0, R0, R0, LSL #0
|
0xe0900000u, // ADDS R0, R0, R0, LSL #0
|
||||||
0xe0600000u, // RSB R0, R0, R0, LSL #0
|
0xe0600000u, // RSB R0, R0, R0, LSL #0
|
||||||
0xe0700000u // RSBS R0, R0, R0, LSL #0
|
0xe0700000u, // RSBS R0, R0, R0, LSL #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,14 +30,14 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xe0e00000u, // RSC R0, R0, R0
|
0xe0e00000u, // RSC R0, R0, R0
|
||||||
0xe0f00000u, // RSCS R0, R0, R0
|
0xe0f00000u, // RSCS R0, R0, R0
|
||||||
0xe0c00000u, // SBC R0, R0, R0
|
0xe0c00000u, // SBC R0, R0, R0
|
||||||
0xe0d00000u // SBCS R0, R0, R0
|
0xe0d00000u, // SBCS R0, R0, R0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource("_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_")] uint opcode,
|
public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource(nameof(_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_))] uint opcode,
|
||||||
[Values(0u, 13u)] uint rd,
|
[Values(0u, 13u)] uint rd,
|
||||||
[Values(1u, 13u)] uint rn,
|
[Values(1u, 13u)] uint rn,
|
||||||
[Values(2u, 13u)] uint rm,
|
[Values(2u, 13u)] uint rm,
|
||||||
@@ -57,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Add_Adds_Rsb_Rsbs([ValueSource("_Add_Adds_Rsb_Rsbs_")] uint opcode,
|
public void Add_Adds_Rsb_Rsbs([ValueSource(nameof(_Add_Adds_Rsb_Rsbs_))] uint opcode,
|
||||||
[Values(0u, 13u)] uint rd,
|
[Values(0u, 13u)] uint rd,
|
||||||
[Values(1u, 13u)] uint rn,
|
[Values(1u, 13u)] uint rn,
|
||||||
[Values(2u, 13u)] uint rm,
|
[Values(2u, 13u)] uint rm,
|
||||||
|
@@ -24,19 +24,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -58,9 +58,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
#region "AluImm & Csel"
|
#region "AluImm & Csel"
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
@@ -164,8 +164,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
// Roots.
|
||||||
[Explicit]
|
[Explicit]
|
||||||
[TestCase(0xFFFFFFFDu)] // Roots.
|
[TestCase(0xFFFFFFFDu)]
|
||||||
[TestCase(0x00000005u)]
|
[TestCase(0x00000005u)]
|
||||||
public void Misc1(uint a)
|
public void Misc1(uint a)
|
||||||
{
|
{
|
||||||
@@ -196,8 +197,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Assert.That(GetContext().GetX(0), Is.Zero);
|
Assert.That(GetContext().GetX(0), Is.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 18 integer solutions.
|
||||||
[Explicit]
|
[Explicit]
|
||||||
[TestCase(-20f, -5f)] // 18 integer solutions.
|
[TestCase(-20f, -5f)]
|
||||||
[TestCase(-12f, -6f)]
|
[TestCase(-12f, -6f)]
|
||||||
[TestCase(-12f, 3f)]
|
[TestCase(-12f, 3f)]
|
||||||
[TestCase(-8f, -8f)]
|
[TestCase(-8f, -8f)]
|
||||||
@@ -242,8 +244,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Assert.That(GetContext().GetV(0).As<float>(), Is.EqualTo(16f));
|
Assert.That(GetContext().GetV(0).As<float>(), Is.EqualTo(16f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 18 integer solutions.
|
||||||
[Explicit]
|
[Explicit]
|
||||||
[TestCase(-20d, -5d)] // 18 integer solutions.
|
[TestCase(-20d, -5d)]
|
||||||
[TestCase(-12d, -6d)]
|
[TestCase(-12d, -6d)]
|
||||||
[TestCase(-12d, 3d)]
|
[TestCase(-12d, 3d)]
|
||||||
[TestCase(-8d, -8d)]
|
[TestCase(-8d, -8d)]
|
||||||
@@ -291,7 +294,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Test, Ignore("The Tester supports only one return point.")]
|
[Test, Ignore("The Tester supports only one return point.")]
|
||||||
public void MiscF([Range(0u, 92u, 1u)] uint a)
|
public void MiscF([Range(0u, 92u, 1u)] uint a)
|
||||||
{
|
{
|
||||||
ulong Fn(uint n)
|
static ulong Fn(uint n)
|
||||||
{
|
{
|
||||||
ulong x = 0, y = 1, z;
|
ulong x = 0, y = 1, z;
|
||||||
|
|
||||||
|
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -57,9 +57,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a,
|
public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
@@ -75,10 +75,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
? TestContext.CurrentContext.Random.NextUInt(0xf) << 28
|
? TestContext.CurrentContext.Random.NextUInt(0xf) << 28
|
||||||
: TestContext.CurrentContext.Random.NextUInt();
|
: TestContext.CurrentContext.Random.NextUInt();
|
||||||
|
|
||||||
bool v = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
|
bool v = mode3 && TestContext.CurrentContext.Random.NextBool();
|
||||||
bool c = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
|
bool c = mode3 && TestContext.CurrentContext.Random.NextBool();
|
||||||
bool z = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
|
bool z = mode3 && TestContext.CurrentContext.Random.NextBool();
|
||||||
bool n = mode3 ? TestContext.CurrentContext.Random.NextBool() : false;
|
bool n = mode3 && TestContext.CurrentContext.Random.NextBool();
|
||||||
|
|
||||||
int fpscr = mode1
|
int fpscr = mode1
|
||||||
? (int)TestContext.CurrentContext.Random.NextUInt()
|
? (int)TestContext.CurrentContext.Random.NextUInt()
|
||||||
|
@@ -52,7 +52,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")]
|
[Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")]
|
||||||
public void Smla___32bit([ValueSource("_Smlabb_Smlabt_Smlatb_Smlatt_")] uint opcode,
|
public void Smla___32bit([ValueSource(nameof(_Smlabb_Smlabt_Smlatb_Smlatt_))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rn,
|
[Values(0u, 0xdu)] uint rn,
|
||||||
[Values(1u, 0xdu)] uint rm,
|
[Values(1u, 0xdu)] uint rm,
|
||||||
[Values(2u, 0xdu)] uint ra,
|
[Values(2u, 0xdu)] uint ra,
|
||||||
@@ -74,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("SMLAW<x> <Rd>, <Rn>, <Rm>, <Ra>")]
|
[Test, Pairwise, Description("SMLAW<x> <Rd>, <Rn>, <Rm>, <Ra>")]
|
||||||
public void Smlaw__32bit([ValueSource("_Smlawb_Smlawt_")] uint opcode,
|
public void Smlaw__32bit([ValueSource(nameof(_Smlawb_Smlawt_))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rn,
|
[Values(0u, 0xdu)] uint rn,
|
||||||
[Values(1u, 0xdu)] uint rm,
|
[Values(1u, 0xdu)] uint rm,
|
||||||
[Values(2u, 0xdu)] uint ra,
|
[Values(2u, 0xdu)] uint ra,
|
||||||
@@ -96,7 +96,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("SMUL<x><y> <Rd>, <Rn>, <Rm>")]
|
[Test, Pairwise, Description("SMUL<x><y> <Rd>, <Rn>, <Rm>")]
|
||||||
public void Smul___32bit([ValueSource("_Smulbb_Smulbt_Smultb_Smultt_")] uint opcode,
|
public void Smul___32bit([ValueSource(nameof(_Smulbb_Smulbt_Smultb_Smultt_))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rn,
|
[Values(0u, 0xdu)] uint rn,
|
||||||
[Values(1u, 0xdu)] uint rm,
|
[Values(1u, 0xdu)] uint rm,
|
||||||
[Values(2u, 0xdu)] uint rd,
|
[Values(2u, 0xdu)] uint rd,
|
||||||
@@ -115,7 +115,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("SMULW<x> <Rd>, <Rn>, <Rm>")]
|
[Test, Pairwise, Description("SMULW<x> <Rd>, <Rn>, <Rm>")]
|
||||||
public void Smulw__32bit([ValueSource("_Smulwb_Smulwt_")] uint opcode,
|
public void Smulw__32bit([ValueSource(nameof(_Smulwb_Smulwt_))] uint opcode,
|
||||||
[Values(0u, 0xdu)] uint rn,
|
[Values(0u, 0xdu)] uint rn,
|
||||||
[Values(1u, 0xdu)] uint rm,
|
[Values(1u, 0xdu)] uint rm,
|
||||||
[Values(2u, 0xdu)] uint rd,
|
[Values(2u, 0xdu)] uint rd,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0xf3b10300u, // VABS.S8 D0, D0
|
0xf3b10300u, // VABS.S8 D0, D0
|
||||||
0xf3b10380u, // VNEG.S8 D0, D0
|
0xf3b10380u, // VNEG.S8 D0, D0
|
||||||
0xf3b00200u // VPADDL.S8 D0, D0
|
0xf3b00200u, // VPADDL.S8 D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xf3b90700u, // VABS.F32 D0, D0
|
0xf3b90700u, // VABS.F32 D0, D0
|
||||||
0xf3b90780u // VNEG.F32 D0, D0
|
0xf3b90780u, // VNEG.F32 D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -35,10 +35,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _8B4H2S_()
|
private static ulong[] _8B4H2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _1S_F_()
|
private static IEnumerable<ulong> _1S_F_()
|
||||||
@@ -52,19 +54,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -94,19 +96,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -135,19 +137,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -177,9 +179,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")]
|
[Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")]
|
||||||
public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode,
|
public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode,
|
||||||
@@ -223,8 +225,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rd <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
@@ -252,8 +256,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rd <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
@@ -303,7 +309,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Values(0u, 1u, 2u, 3u)] uint op,
|
[Values(0u, 1u, 2u, 3u)] uint op,
|
||||||
[Values(0u, 1u, 2u)] uint size) // <S8, S16, S32>
|
[Values(0u, 1u, 2u)] uint size) // <S8, S16, S32>
|
||||||
{
|
{
|
||||||
rm >>= 1; rm <<= 1;
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
|
|
||||||
uint opcode = 0xf3b20200u; // VMOVN.S16 D0, Q0
|
uint opcode = 0xf3b20200u; // VMOVN.S16 D0, Q0
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
|
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
|
||||||
|
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
@@ -87,8 +86,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
ExecutionContext context = SingleOpcode(
|
ExecutionContext context = SingleOpcode(
|
||||||
opcode,
|
opcode,
|
||||||
v0: rn == 0u ? v : default(V128),
|
v0: rn == 0u ? v : default,
|
||||||
v1: rn == 1u ? v : default(V128));
|
v1: rn == 1u ? v : default);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
@@ -122,8 +121,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
ExecutionContext context = SingleOpcode(
|
ExecutionContext context = SingleOpcode(
|
||||||
opcode,
|
opcode,
|
||||||
v0: rn == 0u ? v : default(V128),
|
v0: rn == 0u ? v : default,
|
||||||
v1: rn == 1u ? v : default(V128));
|
v1: rn == 1u ? v : default);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
|
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
|
||||||
|
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
@@ -92,8 +91,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
ExecutionContext context = SingleOpcode(
|
ExecutionContext context = SingleOpcode(
|
||||||
opcode,
|
opcode,
|
||||||
v0: rm == 0u ? v : default(V128),
|
v0: rm == 0u ? v : default,
|
||||||
v1: rm == 2u ? v : default(V128),
|
v1: rm == 2u ? v : default,
|
||||||
runUnicorn: false);
|
runUnicorn: false);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
@@ -130,8 +129,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
ExecutionContext context = SingleOpcode(
|
ExecutionContext context = SingleOpcode(
|
||||||
opcode,
|
opcode,
|
||||||
v0: rm == 0u ? v : default(V128),
|
v0: rm == 0u ? v : default,
|
||||||
v1: rm == 2u ? v : default(V128),
|
v1: rm == 2u ? v : default,
|
||||||
runUnicorn: false);
|
runUnicorn: false);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
|
@@ -15,14 +15,18 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static uint[] _W_()
|
private static uint[] _W_()
|
||||||
{
|
{
|
||||||
return new[] { 0x00000000u, 0x7FFFFFFFu,
|
return new[] {
|
||||||
0x80000000u, 0xFFFFFFFFu };
|
0x00000000u, 0x7FFFFFFFu,
|
||||||
|
0x80000000u, 0xFFFFFFFFu,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _X_()
|
private static ulong[] _X_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _1S_F_WX_()
|
private static IEnumerable<ulong> _1S_F_WX_()
|
||||||
@@ -62,19 +66,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -145,19 +149,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -203,7 +207,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E280000u, // FCVTPS W0, S0
|
0x1E280000u, // FCVTPS W0, S0
|
||||||
0x1E290000u, // FCVTPU W0, S0
|
0x1E290000u, // FCVTPU W0, S0
|
||||||
0x1E380000u, // FCVTZS W0, S0
|
0x1E380000u, // FCVTZS W0, S0
|
||||||
0x1E390000u // FCVTZU W0, S0
|
0x1E390000u, // FCVTZU W0, S0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +223,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x9E280000u, // FCVTPS X0, S0
|
0x9E280000u, // FCVTPS X0, S0
|
||||||
0x9E290000u, // FCVTPU X0, S0
|
0x9E290000u, // FCVTPU X0, S0
|
||||||
0x9E380000u, // FCVTZS X0, S0
|
0x9E380000u, // FCVTZS X0, S0
|
||||||
0x9E390000u // FCVTZU X0, S0
|
0x9E390000u, // FCVTZU X0, S0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +239,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E680000u, // FCVTPS W0, D0
|
0x1E680000u, // FCVTPS W0, D0
|
||||||
0x1E690000u, // FCVTPU W0, D0
|
0x1E690000u, // FCVTPU W0, D0
|
||||||
0x1E780000u, // FCVTZS W0, D0
|
0x1E780000u, // FCVTZS W0, D0
|
||||||
0x1E790000u // FCVTZU W0, D0
|
0x1E790000u, // FCVTZU W0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +255,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x9E680000u, // FCVTPS X0, D0
|
0x9E680000u, // FCVTPS X0, D0
|
||||||
0x9E690000u, // FCVTPU X0, D0
|
0x9E690000u, // FCVTPU X0, D0
|
||||||
0x9E780000u, // FCVTZS X0, D0
|
0x9E780000u, // FCVTZS X0, D0
|
||||||
0x9E790000u // FCVTZU X0, D0
|
0x9E790000u, // FCVTZU X0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +264,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E188000u, // FCVTZS W0, S0, #32
|
0x1E188000u, // FCVTZS W0, S0, #32
|
||||||
0x1E198000u // FCVTZU W0, S0, #32
|
0x1E198000u, // FCVTZU W0, S0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +273,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E180000u, // FCVTZS X0, S0, #64
|
0x9E180000u, // FCVTZS X0, S0, #64
|
||||||
0x9E190000u // FCVTZU X0, S0, #64
|
0x9E190000u, // FCVTZU X0, S0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +282,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E588000u, // FCVTZS W0, D0, #32
|
0x1E588000u, // FCVTZS W0, D0, #32
|
||||||
0x1E598000u // FCVTZU W0, D0, #32
|
0x1E598000u, // FCVTZU W0, D0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +291,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E580000u, // FCVTZS X0, D0, #64
|
0x9E580000u, // FCVTZS X0, D0, #64
|
||||||
0x9E590000u // FCVTZU X0, D0, #64
|
0x9E590000u, // FCVTZU X0, D0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +300,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E220000u, // SCVTF S0, W0
|
0x1E220000u, // SCVTF S0, W0
|
||||||
0x1E230000u // UCVTF S0, W0
|
0x1E230000u, // UCVTF S0, W0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +309,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E620000u, // SCVTF D0, W0
|
0x1E620000u, // SCVTF D0, W0
|
||||||
0x1E630000u // UCVTF D0, W0
|
0x1E630000u, // UCVTF D0, W0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +318,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E220000u, // SCVTF S0, X0
|
0x9E220000u, // SCVTF S0, X0
|
||||||
0x9E230000u // UCVTF S0, X0
|
0x9E230000u, // UCVTF S0, X0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +327,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E620000u, // SCVTF D0, X0
|
0x9E620000u, // SCVTF D0, X0
|
||||||
0x9E630000u // UCVTF D0, X0
|
0x9E630000u, // UCVTF D0, X0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +336,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E028000u, // SCVTF S0, W0, #32
|
0x1E028000u, // SCVTF S0, W0, #32
|
||||||
0x1E038000u // UCVTF S0, W0, #32
|
0x1E038000u, // UCVTF S0, W0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +345,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E428000u, // SCVTF D0, W0, #32
|
0x1E428000u, // SCVTF D0, W0, #32
|
||||||
0x1E438000u // UCVTF D0, W0, #32
|
0x1E438000u, // UCVTF D0, W0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +354,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E020000u, // SCVTF S0, X0, #64
|
0x9E020000u, // SCVTF S0, X0, #64
|
||||||
0x9E030000u // UCVTF S0, X0, #64
|
0x9E030000u, // UCVTF S0, X0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,18 +363,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x9E420000u, // SCVTF D0, X0, #64
|
0x9E420000u, // SCVTF D0, X0, #64
|
||||||
0x9E430000u // UCVTF D0, X0, #64
|
0x9E430000u, // UCVTF D0, X0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_AMPZ_SU_Gp_SW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SW_))] uint opcodes,
|
public void F_Cvt_AMPZ_SU_Gp_SW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SW_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -387,7 +392,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_AMPZ_SU_Gp_SX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SX_))] uint opcodes,
|
public void F_Cvt_AMPZ_SU_Gp_SX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_SX_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -403,7 +409,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_AMPZ_SU_Gp_DW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DW_))] uint opcodes,
|
public void F_Cvt_AMPZ_SU_Gp_DW([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DW_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -420,7 +427,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_AMPZ_SU_Gp_DX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DX_))] uint opcodes,
|
public void F_Cvt_AMPZ_SU_Gp_DX([ValueSource(nameof(_F_Cvt_AMPZ_SU_Gp_DX_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -436,7 +444,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_Gp_Fixed_SW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SW_))] uint opcodes,
|
public void F_Cvt_Z_SU_Gp_Fixed_SW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SW_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -457,7 +466,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_Gp_Fixed_SX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SX_))] uint opcodes,
|
public void F_Cvt_Z_SU_Gp_Fixed_SX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_SX_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -477,7 +487,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_Gp_Fixed_DW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DW_))] uint opcodes,
|
public void F_Cvt_Z_SU_Gp_Fixed_DW([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DW_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -498,7 +509,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_Gp_Fixed_DX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DX_))] uint opcodes,
|
public void F_Cvt_Z_SU_Gp_Fixed_DX([ValueSource(nameof(_F_Cvt_Z_SU_Gp_Fixed_DX_))] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
[Values(1u)] uint rn,
|
[Values(1u)] uint rn,
|
||||||
@@ -518,7 +530,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_WS([ValueSource(nameof(_SU_Cvt_F_Gp_WS_))] uint opcodes,
|
public void SU_Cvt_F_Gp_WS([ValueSource(nameof(_SU_Cvt_F_Gp_WS_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -535,7 +548,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_WD([ValueSource(nameof(_SU_Cvt_F_Gp_WD_))] uint opcodes,
|
public void SU_Cvt_F_Gp_WD([ValueSource(nameof(_SU_Cvt_F_Gp_WD_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -552,7 +566,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_XS([ValueSource(nameof(_SU_Cvt_F_Gp_XS_))] uint opcodes,
|
public void SU_Cvt_F_Gp_XS([ValueSource(nameof(_SU_Cvt_F_Gp_XS_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -569,7 +584,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_XD([ValueSource(nameof(_SU_Cvt_F_Gp_XD_))] uint opcodes,
|
public void SU_Cvt_F_Gp_XD([ValueSource(nameof(_SU_Cvt_F_Gp_XD_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -586,7 +602,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_Fixed_WS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WS_))] uint opcodes,
|
public void SU_Cvt_F_Gp_Fixed_WS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WS_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -607,7 +624,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_Fixed_WD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WD_))] uint opcodes,
|
public void SU_Cvt_F_Gp_Fixed_WD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_WD_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -628,7 +646,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_Fixed_XS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XS_))] uint opcodes,
|
public void SU_Cvt_F_Gp_Fixed_XS([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XS_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
@@ -649,7 +668,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_Gp_Fixed_XD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XD_))] uint opcodes,
|
public void SU_Cvt_F_Gp_Fixed_XD([ValueSource(nameof(_SU_Cvt_F_Gp_Fixed_XD_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 31u)] uint rn,
|
[Values(1u, 31u)] uint rn,
|
||||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf3ba0500u, // VRINTA.F32 Q0, Q0
|
0xf3ba0500u, // VRINTA.F32 Q0, Q0
|
||||||
0xf3ba0680u, // VRINTM.F32 Q0, Q0
|
0xf3ba0680u, // VRINTM.F32 Q0, Q0
|
||||||
0xf3ba0400u, // VRINTN.F32 Q0, Q0
|
0xf3ba0400u, // VRINTN.F32 Q0, Q0
|
||||||
0xf3ba0780u // VRINTP.F32 Q0, Q0
|
0xf3ba0780u, // VRINTP.F32 Q0, Q0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -28,8 +28,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static uint[] _1S_()
|
private static uint[] _1S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x00000000u, 0x7FFFFFFFu,
|
return new[] {
|
||||||
0x80000000u, 0xFFFFFFFFu };
|
0x00000000u, 0x7FFFFFFFu,
|
||||||
|
0x80000000u, 0xFFFFFFFFu,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _1S_F_()
|
private static IEnumerable<ulong> _1S_F_()
|
||||||
@@ -43,19 +45,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -85,19 +87,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -126,19 +128,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -159,9 +161,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Explicit]
|
[Explicit]
|
||||||
[Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")]
|
[Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")]
|
||||||
@@ -275,7 +277,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode,
|
public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rd,
|
[Values(0u, 1u, 2u, 3u)] uint rd,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rm,
|
[Values(0u, 1u, 2u, 3u)] uint rm,
|
||||||
@@ -289,8 +292,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rd <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
|
@@ -13,8 +13,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource"
|
#region "ValueSource"
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -65,19 +65,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -102,7 +102,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E220420u, // FCCMP S1, S2, #0, EQ
|
0x1E220420u, // FCCMP S1, S2, #0, EQ
|
||||||
0x1E220430u // FCCMPE S1, S2, #0, EQ
|
0x1E220430u, // FCCMPE S1, S2, #0, EQ
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E620420u, // FCCMP D1, D2, #0, EQ
|
0x1E620420u, // FCCMP D1, D2, #0, EQ
|
||||||
0x1E620430u // FCCMPE D1, D2, #0, EQ
|
0x1E620430u, // FCCMPE D1, D2, #0, EQ
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E220C20u // FCSEL S0, S1, S2, EQ
|
0x1E220C20u, // FCSEL S0, S1, S2, EQ
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E620C20u // FCSEL D0, D1, D2, EQ
|
0x1E620C20u, // FCSEL D0, D1, D2, EQ
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -135,11 +135,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
private const int RndCntNzcv = 2;
|
private const int RndCntNzcv = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Ccmp_Ccmpe_S_S([ValueSource(nameof(_F_Ccmp_Ccmpe_S_S_))] uint opcodes,
|
public void F_Ccmp_Ccmpe_S_S([ValueSource(nameof(_F_Ccmp_Ccmpe_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b,
|
[ValueSource(nameof(_1S_F_))] ulong b,
|
||||||
@@ -164,7 +165,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Ccmp_Ccmpe_S_D([ValueSource(nameof(_F_Ccmp_Ccmpe_S_D_))] uint opcodes,
|
public void F_Ccmp_Ccmpe_S_D([ValueSource(nameof(_F_Ccmp_Ccmpe_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b,
|
[ValueSource(nameof(_1D_F_))] ulong b,
|
||||||
@@ -189,7 +191,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Csel_S_S([ValueSource(nameof(_F_Csel_S_S_))] uint opcodes,
|
public void F_Csel_S_S([ValueSource(nameof(_F_Csel_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b,
|
[ValueSource(nameof(_1S_F_))] ulong b,
|
||||||
@@ -210,7 +213,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Csel_S_D([ValueSource(nameof(_F_Csel_S_D_))] uint opcodes,
|
public void F_Csel_S_D([ValueSource(nameof(_F_Csel_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b,
|
[ValueSource(nameof(_1D_F_))] ulong b,
|
||||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E201000u // FMOV S0, #2.0
|
0x1E201000u, // FMOV S0, #2.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,12 +23,13 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E601000u // FMOV D0, #2.0
|
0x1E601000u, // FMOV D0, #2.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mov_Si_S([ValueSource(nameof(_F_Mov_Si_S_))] uint opcodes,
|
public void F_Mov_Si_S([ValueSource(nameof(_F_Mov_Si_S_))] uint opcodes,
|
||||||
[Range(0u, 255u, 1u)] uint imm8)
|
[Range(0u, 255u, 1u)] uint imm8)
|
||||||
{
|
{
|
||||||
@@ -42,7 +43,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mov_Si_D([ValueSource(nameof(_F_Mov_Si_D_))] uint opcodes,
|
public void F_Mov_Si_D([ValueSource(nameof(_F_Mov_Si_D_))] uint opcodes,
|
||||||
[Range(0u, 255u, 1u)] uint imm8)
|
[Range(0u, 255u, 1u)] uint imm8)
|
||||||
{
|
{
|
||||||
|
@@ -48,14 +48,18 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _2S_()
|
private static ulong[] _2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
return new[] {
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H_()
|
private static ulong[] _4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
|
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<byte> _8BIT_IMM_()
|
private static IEnumerable<byte> _8BIT_IMM_()
|
||||||
@@ -95,7 +99,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x2F009400u, // BIC V0.4H, #0
|
0x2F009400u, // BIC V0.4H, #0
|
||||||
0x0F009400u // ORR V0.4H, #0
|
0x0F009400u, // ORR V0.4H, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x2F001400u, // BIC V0.2S, #0
|
0x2F001400u, // BIC V0.2S, #0
|
||||||
0x0F001400u // ORR V0.2S, #0
|
0x0F001400u, // ORR V0.2S, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F00F400u // FMOV V0.2S, #2.0
|
0x0F00F400u, // FMOV V0.2S, #2.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +124,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4F00F400u // FMOV V0.4S, #2.0
|
0x4F00F400u, // FMOV V0.4S, #2.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +132,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x6F00F400u // FMOV V0.2D, #2.0
|
0x6F00F400u, // FMOV V0.2D, #2.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +140,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F00E400u // MOVI V0.8B, #0
|
0x0F00E400u, // MOVI V0.8B, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +149,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F008400u, // MOVI V0.4H, #0
|
0x0F008400u, // MOVI V0.4H, #0
|
||||||
0x2F008400u // MVNI V0.4H, #0
|
0x2F008400u, // MVNI V0.4H, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +158,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F000400u, // MOVI V0.2S, #0
|
0x0F000400u, // MOVI V0.2S, #0
|
||||||
0x2F000400u // MVNI V0.2S, #0
|
0x2F000400u, // MVNI V0.2S, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +167,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F00C400u, // MOVI V0.2S, #0, MSL #8
|
0x0F00C400u, // MOVI V0.2S, #0, MSL #8
|
||||||
0x2F00C400u // MVNI V0.2S, #0, MSL #8
|
0x2F00C400u, // MVNI V0.2S, #0, MSL #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +175,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x2F00E400u // MOVI D0, #0
|
0x2F00E400u, // MOVI D0, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +183,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x6F00E400u // MOVI V0.2D, #0
|
0x6F00E400u, // MOVI V0.2D, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -229,7 +233,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mov_Vi_2S([ValueSource(nameof(_F_Mov_Vi_2S_))] uint opcodes,
|
public void F_Mov_Vi_2S([ValueSource(nameof(_F_Mov_Vi_2S_))] uint opcodes,
|
||||||
[Range(0u, 255u, 1u)] uint abcdefgh)
|
[Range(0u, 255u, 1u)] uint abcdefgh)
|
||||||
{
|
{
|
||||||
@@ -246,7 +251,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mov_Vi_4S([ValueSource(nameof(_F_Mov_Vi_4S_))] uint opcodes,
|
public void F_Mov_Vi_4S([ValueSource(nameof(_F_Mov_Vi_4S_))] uint opcodes,
|
||||||
[Range(0u, 255u, 1u)] uint abcdefgh)
|
[Range(0u, 255u, 1u)] uint abcdefgh)
|
||||||
{
|
{
|
||||||
@@ -260,7 +266,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mov_Vi_2D([ValueSource(nameof(_F_Mov_Vi_2D_))] uint opcodes,
|
public void F_Mov_Vi_2D([ValueSource(nameof(_F_Mov_Vi_2D_))] uint opcodes,
|
||||||
[Range(0u, 255u, 1u)] uint abcdefgh)
|
[Range(0u, 255u, 1u)] uint abcdefgh)
|
||||||
{
|
{
|
||||||
|
@@ -13,56 +13,72 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource"
|
#region "ValueSource"
|
||||||
private static ulong[] _1D_()
|
private static ulong[] _1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _2S_()
|
private static ulong[] _2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
return new[] {
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H_()
|
private static ulong[] _4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
|
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H_()
|
private static ulong[] _8B4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H2S_()
|
private static ulong[] _8B4H2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] _W_()
|
private static uint[] _W_()
|
||||||
{
|
{
|
||||||
return new[] { 0x00000000u, 0x0000007Fu,
|
return new[] {
|
||||||
|
0x00000000u, 0x0000007Fu,
|
||||||
0x00000080u, 0x000000FFu,
|
0x00000080u, 0x000000FFu,
|
||||||
0x00007FFFu, 0x00008000u,
|
0x00007FFFu, 0x00008000u,
|
||||||
0x0000FFFFu, 0x7FFFFFFFu,
|
0x0000FFFFu, 0x7FFFFFFFu,
|
||||||
0x80000000u, 0xFFFFFFFFu };
|
0x80000000u, 0xFFFFFFFFu,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _X_()
|
private static ulong[] _X_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@@ -13,10 +13,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _8B4H2S_()
|
private static ulong[] _8B4H2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2000110u, // VAND D0, D0, D0
|
0xf2000110u, // VAND D0, D0, D0
|
||||||
0xf2300110u, // VORN D0, D0, D0
|
0xf2300110u, // VORN D0, D0, D0
|
||||||
0xf2200110u, // VORR D0, D0, D0
|
0xf2200110u, // VORR D0, D0, D0
|
||||||
0xf3000110u // VEOR D0, D0, D0
|
0xf3000110u, // VEOR D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2800130u, // VBIC.I32 D0, #0 (A1)
|
0xf2800130u, // VBIC.I32 D0, #0 (A1)
|
||||||
0xf2800930u, // VBIC.I16 D0, #0 (A2)
|
0xf2800930u, // VBIC.I16 D0, #0 (A2)
|
||||||
0xf2800110u, // VORR.I32 D0, #0 (A1)
|
0xf2800110u, // VORR.I32 D0, #0 (A1)
|
||||||
0xf2800910u // VORR.I16 D0, #0 (A2)
|
0xf2800910u, // VORR.I16 D0, #0 (A2)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -62,9 +64,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
@@ -97,7 +102,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
|
rd <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((uint)imm & 0xf) << 0;
|
opcode |= ((uint)imm & 0xf) << 0;
|
||||||
@@ -129,9 +135,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
|
@@ -10,10 +10,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[Category("SimdMemory32")]
|
[Category("SimdMemory32")]
|
||||||
public sealed class CpuTestSimdMemory32 : CpuTest32
|
public sealed class CpuTestSimdMemory32 : CpuTest32
|
||||||
{
|
{
|
||||||
private static readonly uint TestOffset = DataBaseAddress + 0x500;
|
private static readonly uint _testOffset = DataBaseAddress + 0x500;
|
||||||
#if SimdMemory32
|
#if SimdMemory32
|
||||||
|
|
||||||
private uint[] _ldStModes =
|
private readonly uint[] _ldStModes =
|
||||||
{
|
{
|
||||||
// LD1
|
// LD1
|
||||||
0b0111,
|
0b0111,
|
||||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
// LD4
|
// LD4
|
||||||
0b0000,
|
0b0000,
|
||||||
0b0001
|
0b0001,
|
||||||
};
|
};
|
||||||
|
|
||||||
[Test, Pairwise, Description("VLDn.<size> <list>, [<Rn> {:<align>}]{ /!/, <Rm>} (single n element structure)")]
|
[Test, Pairwise, Description("VLDn.<size> <list>, [<Rn> {:<align>}]{ /!/, <Rm>} (single n element structure)")]
|
||||||
@@ -51,16 +51,16 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
|
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
|
||||||
|
|
||||||
uint index_align = (index << (int)(1 + size)) & 15;
|
uint indexAlign = (index << (int)(1 + size)) & 15;
|
||||||
|
|
||||||
opcode |= (index_align) << 4;
|
opcode |= (indexAlign) << 4;
|
||||||
|
|
||||||
opcode |= ((vd & 0x10) << 18);
|
opcode |= ((vd & 0x10) << 18);
|
||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -85,9 +85,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
||||||
if (t) opcode |= 1 << 5;
|
if (t)
|
||||||
|
{
|
||||||
|
opcode |= 1 << 5;
|
||||||
|
}
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -116,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= ((vd & 0x10) << 18);
|
opcode |= ((vd & 0x10) << 18);
|
||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, r1: offset, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -139,16 +142,16 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
|
opcode |= ((size & 3) << 10) | ((rn & 15) << 16) | (rm & 15);
|
||||||
|
|
||||||
uint index_align = (index << (int)(1 + size)) & 15;
|
uint indexAlign = (index << (int)(1 + size)) & 15;
|
||||||
|
|
||||||
opcode |= (index_align) << 4;
|
opcode |= (indexAlign) << 4;
|
||||||
|
|
||||||
opcode |= ((vd & 0x10) << 18);
|
opcode |= ((vd & 0x10) << 18);
|
||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
|
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -179,7 +182,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= ((vd & 0x10) << 18);
|
opcode |= ((vd & 0x10) << 18);
|
||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -201,7 +204,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
// Note: 3rd 0 leaves a space for "D".
|
// Note: 3rd 0 leaves a space for "D".
|
||||||
0b0100, // Increment after.
|
0b0100, // Increment after.
|
||||||
0b0101, // Increment after. (!)
|
0b0101, // Increment after. (!)
|
||||||
0b1001 // Decrement before. (!)
|
0b1001, // Decrement before. (!)
|
||||||
};
|
};
|
||||||
|
|
||||||
opcode |= ((vldmModes[mode] & 15) << 21);
|
opcode |= ((vldmModes[mode] & 15) << 21);
|
||||||
@@ -212,7 +215,11 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
opcode |= ((uint)(single ? 0 : 1) << 8);
|
opcode |= ((uint)(single ? 0 : 1) << 8);
|
||||||
|
|
||||||
if (!single) regs = (regs << 1); // Low bit must be 0 - must be even number of registers.
|
if (!single)
|
||||||
|
{
|
||||||
|
regs <<= 1; // Low bit must be 0 - must be even number of registers.
|
||||||
|
}
|
||||||
|
|
||||||
uint regSize = single ? 1u : 2u;
|
uint regSize = single ? 1u : 2u;
|
||||||
|
|
||||||
if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31.
|
if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31.
|
||||||
@@ -227,7 +234,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
opcode |= regs & 0xff;
|
opcode |= regs & 0xff;
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, sp: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset, sp: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -262,7 +269,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
}
|
}
|
||||||
opcode |= imm & 0xff;
|
opcode |= imm & 0xff;
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset);
|
SingleOpcode(opcode, r0: _testOffset);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
@@ -299,12 +306,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
|
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2);
|
SingleOpcode(opcode, r0: _testOffset, v0: vec1, v1: vec2);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
private (V128, V128, V128, V128) GenerateTestVectors()
|
private static (V128, V128, V128, V128) GenerateTestVectors()
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
new V128(-12.43f, 1872.23f, 4456.23f, -5622.2f),
|
new V128(-12.43f, 1872.23f, 4456.23f, -5622.2f),
|
||||||
@@ -314,7 +321,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] GenerateVectorSequence(int length)
|
private static byte[] GenerateVectorSequence(int length)
|
||||||
{
|
{
|
||||||
int floatLength = length >> 2;
|
int floatLength = length >> 2;
|
||||||
float[] data = new float[floatLength];
|
float[] data = new float[floatLength];
|
||||||
|
@@ -35,7 +35,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0b1110_0,
|
0b1110_0,
|
||||||
0b1111_0,
|
0b1111_0,
|
||||||
|
|
||||||
0b1110_1
|
0b1110_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint opcode = 0xf2800010u; // VMOV.I32 D0, #0
|
uint opcode = 0xf2800010u; // VMOV.I32 D0, #0
|
||||||
@@ -97,7 +97,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= (vn & 0x1e) << 15;
|
opcode |= (vn & 0x1e) << 15;
|
||||||
opcode |= (rt & 0xf) << 12;
|
opcode |= (rt & 0xf) << 12;
|
||||||
|
|
||||||
if (op) opcode |= 1 << 20;
|
if (op)
|
||||||
|
{
|
||||||
|
opcode |= 1 << 20;
|
||||||
|
}
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2));
|
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2));
|
||||||
|
|
||||||
@@ -217,10 +220,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= ((vd & 0x10) << 18);
|
opcode |= ((vd & 0x10) << 18);
|
||||||
opcode |= ((vd & 0xf) << 12);
|
opcode |= ((vd & 0xf) << 12);
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -247,10 +250,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= 1 << 24;
|
opcode |= 1 << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -279,10 +282,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= (vd & 0x10) << 18;
|
opcode |= (vd & 0x10) << 18;
|
||||||
opcode |= (vd & 0xf) << 12;
|
opcode |= (vd & 0xf) << 12;
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -348,18 +351,20 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
vd <<= 1; vm <<= 1;
|
vd <<= 1;
|
||||||
|
vm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= (vm & 0x10) << 1;
|
opcode |= (vm & 0x10) << 1;
|
||||||
opcode |= (vm & 0xf);
|
opcode |= (vm & 0xf);
|
||||||
opcode |= (vd & 0x10) << 18;
|
opcode |= (vd & 0x10) << 18;
|
||||||
opcode |= (vd & 0xf) << 12;
|
opcode |= (vd & 0xf) << 12;
|
||||||
opcode |= (size & 0x3) << 18;
|
opcode |= (size & 0x3) << 18;
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -381,18 +386,20 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
vd <<= 1; vm <<= 1;
|
vd <<= 1;
|
||||||
|
vm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= (vm & 0x10) << 1;
|
opcode |= (vm & 0x10) << 1;
|
||||||
opcode |= (vm & 0xf);
|
opcode |= (vm & 0xf);
|
||||||
opcode |= (vd & 0x10) << 18;
|
opcode |= (vd & 0x10) << 18;
|
||||||
opcode |= (vd & 0xf) << 12;
|
opcode |= (vd & 0xf) << 12;
|
||||||
opcode |= (size & 0x3) << 18;
|
opcode |= (size & 0x3) << 18;
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -414,18 +421,20 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
vd <<= 1; vm <<= 1;
|
vd <<= 1;
|
||||||
|
vm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= (vm & 0x10) << 1;
|
opcode |= (vm & 0x10) << 1;
|
||||||
opcode |= (vm & 0xf);
|
opcode |= (vm & 0xf);
|
||||||
opcode |= (vd & 0x10) << 18;
|
opcode |= (vd & 0x10) << 18;
|
||||||
opcode |= (vd & 0xf) << 12;
|
opcode |= (vd & 0xf) << 12;
|
||||||
opcode |= (size & 0x3) << 18;
|
opcode |= (size & 0x3) << 18;
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -459,10 +468,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= (length & 0x3) << 8;
|
opcode |= (length & 0x3) << 8;
|
||||||
|
|
||||||
var rnd = TestContext.CurrentContext.Random;
|
var rnd = TestContext.CurrentContext.Random;
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v4 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v4 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v5 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v5 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
byte maxIndex = (byte)(length * 8 - 1);
|
byte maxIndex = (byte)(length * 8 - 1);
|
||||||
byte[] b0 = new byte[16];
|
byte[] b0 = new byte[16];
|
||||||
@@ -473,8 +482,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
b1[i] = rnd.NextByte(maxIndex);
|
b1[i] = rnd.NextByte(maxIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
V128 v0 = new V128(b0);
|
V128 v0 = new(b0);
|
||||||
V128 v1 = new V128(b1);
|
V128 v1 = new(b1);
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
|
||||||
|
|
||||||
@@ -493,7 +502,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
vd <<= 1; vm <<= 1; vn <<= 1;
|
vd <<= 1;
|
||||||
|
vm <<= 1;
|
||||||
|
vn <<= 1;
|
||||||
}
|
}
|
||||||
else if (imm4 > 7)
|
else if (imm4 > 7)
|
||||||
{
|
{
|
||||||
@@ -507,10 +518,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= (vn & 0xf) << 16;
|
opcode |= (vn & 0xf) << 16;
|
||||||
opcode |= (imm4 & 0xf) << 8;
|
opcode |= (imm4 & 0xf) << 8;
|
||||||
|
|
||||||
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v0 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
@@ -541,7 +552,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= (size & 1) << 5; // E
|
opcode |= (size & 1) << 5; // E
|
||||||
opcode |= (size & 2) << 21; // B
|
opcode |= (size & 2) << 21; // B
|
||||||
|
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1);
|
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1);
|
||||||
|
|
||||||
@@ -586,9 +597,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
opcode |= imm4 << 16;
|
opcode |= imm4 << 16;
|
||||||
|
|
||||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v1 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v2 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
V128 v3 = new(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3);
|
SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3);
|
||||||
|
|
||||||
|
@@ -14,72 +14,90 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _1B1H1S1D_()
|
private static ulong[] _1B1H1S1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x000000000000007Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x000000000000007Ful,
|
||||||
0x0000000000000080ul, 0x00000000000000FFul,
|
0x0000000000000080ul, 0x00000000000000FFul,
|
||||||
0x0000000000007FFFul, 0x0000000000008000ul,
|
0x0000000000007FFFul, 0x0000000000008000ul,
|
||||||
0x000000000000FFFFul, 0x000000007FFFFFFFul,
|
0x000000000000FFFFul, 0x000000007FFFFFFFul,
|
||||||
0x0000000080000000ul, 0x00000000FFFFFFFFul,
|
0x0000000080000000ul, 0x00000000FFFFFFFFul,
|
||||||
0x7FFFFFFFFFFFFFFFul, 0x8000000000000000ul,
|
0x7FFFFFFFFFFFFFFFul, 0x8000000000000000ul,
|
||||||
0xFFFFFFFFFFFFFFFFul };
|
0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _1D_()
|
private static ulong[] _1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _1H1S_()
|
private static ulong[] _1H1S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x0000000000007FFFul,
|
||||||
0x0000000000008000ul, 0x000000000000FFFFul,
|
0x0000000000008000ul, 0x000000000000FFFFul,
|
||||||
0x000000007FFFFFFFul, 0x0000000080000000ul,
|
0x000000007FFFFFFFul, 0x0000000080000000ul,
|
||||||
0x00000000FFFFFFFFul };
|
0x00000000FFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H2S_()
|
private static ulong[] _4H2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H2S1D_()
|
private static ulong[] _4H2S1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B1D_()
|
private static ulong[] _8B1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
|
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H2S_()
|
private static ulong[] _8B4H2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H2S1D_()
|
private static ulong[] _8B4H2S1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _1S_F_()
|
private static IEnumerable<ulong> _1S_F_()
|
||||||
@@ -93,19 +111,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -135,19 +153,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -176,19 +194,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -218,7 +236,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E220820u, // FMUL S0, S1, S2
|
0x1E220820u, // FMUL S0, S1, S2
|
||||||
0x5E22DC20u, // FMULX S0, S1, S2
|
0x5E22DC20u, // FMULX S0, S1, S2
|
||||||
0x1E228820u, // FNMUL S0, S1, S2
|
0x1E228820u, // FNMUL S0, S1, S2
|
||||||
0x1E223820u // FSUB S0, S1, S2
|
0x1E223820u, // FSUB S0, S1, S2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +250,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E620820u, // FMUL D0, D1, D2
|
0x1E620820u, // FMUL D0, D1, D2
|
||||||
0x5E62DC20u, // FMULX D0, D1, D2
|
0x5E62DC20u, // FMULX D0, D1, D2
|
||||||
0x1E628820u, // FNMUL D0, D1, D2
|
0x1E628820u, // FNMUL D0, D1, D2
|
||||||
0x1E623820u // FSUB D0, D1, D2
|
0x1E623820u, // FSUB D0, D1, D2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +264,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2E20FC00u, // FDIV V0.2S, V0.2S, V0.2S
|
0x2E20FC00u, // FDIV V0.2S, V0.2S, V0.2S
|
||||||
0x2E20DC00u, // FMUL V0.2S, V0.2S, V0.2S
|
0x2E20DC00u, // FMUL V0.2S, V0.2S, V0.2S
|
||||||
0x0E20DC00u, // FMULX V0.2S, V0.2S, V0.2S
|
0x0E20DC00u, // FMULX V0.2S, V0.2S, V0.2S
|
||||||
0x0EA0D400u // FSUB V0.2S, V0.2S, V0.2S
|
0x0EA0D400u, // FSUB V0.2S, V0.2S, V0.2S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +278,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x6E60FC00u, // FDIV V0.2D, V0.2D, V0.2D
|
0x6E60FC00u, // FDIV V0.2D, V0.2D, V0.2D
|
||||||
0x6E60DC00u, // FMUL V0.2D, V0.2D, V0.2D
|
0x6E60DC00u, // FMUL V0.2D, V0.2D, V0.2D
|
||||||
0x4E60DC00u, // FMULX V0.2D, V0.2D, V0.2D
|
0x4E60DC00u, // FMULX V0.2D, V0.2D, V0.2D
|
||||||
0x4EE0D400u // FSUB V0.2D, V0.2D, V0.2D
|
0x4EE0D400u, // FSUB V0.2D, V0.2D, V0.2D
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +290,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7EA2EC20u, // FACGT S0, S1, S2
|
0x7EA2EC20u, // FACGT S0, S1, S2
|
||||||
0x5E22E420u, // FCMEQ S0, S1, S2
|
0x5E22E420u, // FCMEQ S0, S1, S2
|
||||||
0x7E22E420u, // FCMGE S0, S1, S2
|
0x7E22E420u, // FCMGE S0, S1, S2
|
||||||
0x7EA2E420u // FCMGT S0, S1, S2
|
0x7EA2E420u, // FCMGT S0, S1, S2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +302,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7EE2EC20u, // FACGT D0, D1, D2
|
0x7EE2EC20u, // FACGT D0, D1, D2
|
||||||
0x5E62E420u, // FCMEQ D0, D1, D2
|
0x5E62E420u, // FCMEQ D0, D1, D2
|
||||||
0x7E62E420u, // FCMGE D0, D1, D2
|
0x7E62E420u, // FCMGE D0, D1, D2
|
||||||
0x7EE2E420u // FCMGT D0, D1, D2
|
0x7EE2E420u, // FCMGT D0, D1, D2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +314,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2EA0EC00u, // FACGT V0.2S, V0.2S, V0.2S
|
0x2EA0EC00u, // FACGT V0.2S, V0.2S, V0.2S
|
||||||
0x0E20E400u, // FCMEQ V0.2S, V0.2S, V0.2S
|
0x0E20E400u, // FCMEQ V0.2S, V0.2S, V0.2S
|
||||||
0x2E20E400u, // FCMGE V0.2S, V0.2S, V0.2S
|
0x2E20E400u, // FCMGE V0.2S, V0.2S, V0.2S
|
||||||
0x2EA0E400u // FCMGT V0.2S, V0.2S, V0.2S
|
0x2EA0E400u, // FCMGT V0.2S, V0.2S, V0.2S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +326,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x6EE0EC00u, // FACGT V0.2D, V0.2D, V0.2D
|
0x6EE0EC00u, // FACGT V0.2D, V0.2D, V0.2D
|
||||||
0x4E60E400u, // FCMEQ V0.2D, V0.2D, V0.2D
|
0x4E60E400u, // FCMEQ V0.2D, V0.2D, V0.2D
|
||||||
0x6E60E400u, // FCMGE V0.2D, V0.2D, V0.2D
|
0x6E60E400u, // FCMGE V0.2D, V0.2D, V0.2D
|
||||||
0x6EE0E400u // FCMGT V0.2D, V0.2D, V0.2D
|
0x6EE0E400u, // FCMGT V0.2D, V0.2D, V0.2D
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +335,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E222020u, // FCMP S1, S2
|
0x1E222020u, // FCMP S1, S2
|
||||||
0x1E222030u // FCMPE S1, S2
|
0x1E222030u, // FCMPE S1, S2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +344,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x1E622020u, // FCMP D1, D2
|
0x1E622020u, // FCMP D1, D2
|
||||||
0x1E622030u // FCMPE D1, D2
|
0x1E622030u, // FCMPE D1, D2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +355,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1F020C20u, // FMADD S0, S1, S2, S3
|
0x1F020C20u, // FMADD S0, S1, S2, S3
|
||||||
0x1F028C20u, // FMSUB S0, S1, S2, S3
|
0x1F028C20u, // FMSUB S0, S1, S2, S3
|
||||||
0x1F220C20u, // FNMADD S0, S1, S2, S3
|
0x1F220C20u, // FNMADD S0, S1, S2, S3
|
||||||
0x1F228C20u // FNMSUB S0, S1, S2, S3
|
0x1F228C20u, // FNMSUB S0, S1, S2, S3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +366,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1F420C20u, // FMADD D0, D1, D2, D3
|
0x1F420C20u, // FMADD D0, D1, D2, D3
|
||||||
0x1F428C20u, // FMSUB D0, D1, D2, D3
|
0x1F428C20u, // FMSUB D0, D1, D2, D3
|
||||||
0x1F620C20u, // FNMADD D0, D1, D2, D3
|
0x1F620C20u, // FNMADD D0, D1, D2, D3
|
||||||
0x1F628C20u // FNMSUB D0, D1, D2, D3
|
0x1F628C20u, // FNMSUB D0, D1, D2, D3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +377,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E224820u, // FMAX S0, S1, S2
|
0x1E224820u, // FMAX S0, S1, S2
|
||||||
0x1E226820u, // FMAXNM S0, S1, S2
|
0x1E226820u, // FMAXNM S0, S1, S2
|
||||||
0x1E225820u, // FMIN S0, S1, S2
|
0x1E225820u, // FMIN S0, S1, S2
|
||||||
0x1E227820u // FMINNM S0, S1, S2
|
0x1E227820u, // FMINNM S0, S1, S2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +388,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x1E624820u, // FMAX D0, D1, D2
|
0x1E624820u, // FMAX D0, D1, D2
|
||||||
0x1E626820u, // FMAXNM D0, D1, D2
|
0x1E626820u, // FMAXNM D0, D1, D2
|
||||||
0x1E625820u, // FMIN D0, D1, D2
|
0x1E625820u, // FMIN D0, D1, D2
|
||||||
0x1E627820u // FMINNM D0, D1, D2
|
0x1E627820u, // FMINNM D0, D1, D2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +403,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x0EA0F400u, // FMIN V0.2S, V0.2S, V0.2S
|
0x0EA0F400u, // FMIN V0.2S, V0.2S, V0.2S
|
||||||
0x0EA0C400u, // FMINNM V0.2S, V0.2S, V0.2S
|
0x0EA0C400u, // FMINNM V0.2S, V0.2S, V0.2S
|
||||||
0x2EA0C400u, // FMINNMP V0.2S, V0.2S, V0.2S
|
0x2EA0C400u, // FMINNMP V0.2S, V0.2S, V0.2S
|
||||||
0x2EA0F400u // FMINP V0.2S, V0.2S, V0.2S
|
0x2EA0F400u, // FMINP V0.2S, V0.2S, V0.2S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +418,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x4EE0F400u, // FMIN V0.2D, V0.2D, V0.2D
|
0x4EE0F400u, // FMIN V0.2D, V0.2D, V0.2D
|
||||||
0x4EE0C400u, // FMINNM V0.2D, V0.2D, V0.2D
|
0x4EE0C400u, // FMINNM V0.2D, V0.2D, V0.2D
|
||||||
0x6EE0C400u, // FMINNMP V0.2D, V0.2D, V0.2D
|
0x6EE0C400u, // FMINNMP V0.2D, V0.2D, V0.2D
|
||||||
0x6EE0F400u // FMINP V0.2D, V0.2D, V0.2D
|
0x6EE0F400u, // FMINP V0.2D, V0.2D, V0.2D
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +427,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E20CC00u, // FMLA V0.2S, V0.2S, V0.2S
|
0x0E20CC00u, // FMLA V0.2S, V0.2S, V0.2S
|
||||||
0x0EA0CC00u // FMLS V0.2S, V0.2S, V0.2S
|
0x0EA0CC00u, // FMLS V0.2S, V0.2S, V0.2S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +436,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4E60CC00u, // FMLA V0.2D, V0.2D, V0.2D
|
0x4E60CC00u, // FMLA V0.2D, V0.2D, V0.2D
|
||||||
0x4EE0CC00u // FMLS V0.2D, V0.2D, V0.2D
|
0x4EE0CC00u, // FMLS V0.2D, V0.2D, V0.2D
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +445,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5E22FC20u, // FRECPS S0, S1, S2
|
0x5E22FC20u, // FRECPS S0, S1, S2
|
||||||
0x5EA2FC20u // FRSQRTS S0, S1, S2
|
0x5EA2FC20u, // FRSQRTS S0, S1, S2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,7 +454,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5E62FC20u, // FRECPS D0, D1, D2
|
0x5E62FC20u, // FRECPS D0, D1, D2
|
||||||
0x5EE2FC20u // FRSQRTS D0, D1, D2
|
0x5EE2FC20u, // FRSQRTS D0, D1, D2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +463,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E20FC00u, // FRECPS V0.2S, V0.2S, V0.2S
|
0x0E20FC00u, // FRECPS V0.2S, V0.2S, V0.2S
|
||||||
0x0EA0FC00u // FRSQRTS V0.2S, V0.2S, V0.2S
|
0x0EA0FC00u, // FRSQRTS V0.2S, V0.2S, V0.2S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +472,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4E60FC00u, // FRECPS V0.2D, V0.2D, V0.2D
|
0x4E60FC00u, // FRECPS V0.2D, V0.2D, V0.2D
|
||||||
0x4EE0FC00u // FRSQRTS V0.2D, V0.2D, V0.2D
|
0x4EE0FC00u, // FRSQRTS V0.2D, V0.2D, V0.2D
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +482,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0x0E209400u, // MLA V0.8B, V0.8B, V0.8B
|
0x0E209400u, // MLA V0.8B, V0.8B, V0.8B
|
||||||
0x2E209400u, // MLS V0.8B, V0.8B, V0.8B
|
0x2E209400u, // MLS V0.8B, V0.8B, V0.8B
|
||||||
0x0E209C00u // MUL V0.8B, V0.8B, V0.8B
|
0x0E209C00u, // MUL V0.8B, V0.8B, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +492,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0x4E209400u, // MLA V0.16B, V0.16B, V0.16B
|
0x4E209400u, // MLA V0.16B, V0.16B, V0.16B
|
||||||
0x6E209400u, // MLS V0.16B, V0.16B, V0.16B
|
0x6E209400u, // MLS V0.16B, V0.16B, V0.16B
|
||||||
0x4E209C00u // MUL V0.16B, V0.16B, V0.16B
|
0x4E209C00u, // MUL V0.16B, V0.16B, V0.16B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +503,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x5E000000u, // SHA1C Q0, S0, V0.4S
|
0x5E000000u, // SHA1C Q0, S0, V0.4S
|
||||||
0x5E002000u, // SHA1M Q0, S0, V0.4S
|
0x5E002000u, // SHA1M Q0, S0, V0.4S
|
||||||
0x5E001000u, // SHA1P Q0, S0, V0.4S
|
0x5E001000u, // SHA1P Q0, S0, V0.4S
|
||||||
0x5E003000u // SHA1SU0 V0.4S, V0.4S, V0.4S
|
0x5E003000u, // SHA1SU0 V0.4S, V0.4S, V0.4S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +513,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0x5E004000u, // SHA256H Q0, Q0, V0.4S
|
0x5E004000u, // SHA256H Q0, Q0, V0.4S
|
||||||
0x5E005000u, // SHA256H2 Q0, Q0, V0.4S
|
0x5E005000u, // SHA256H2 Q0, Q0, V0.4S
|
||||||
0x5E006000u // SHA256SU1 V0.4S, V0.4S, V0.4S
|
0x5E006000u, // SHA256SU1 V0.4S, V0.4S, V0.4S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +528,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2E206400u, // UMAX V0.8B, V0.8B, V0.8B
|
0x2E206400u, // UMAX V0.8B, V0.8B, V0.8B
|
||||||
0x2E20A400u, // UMAXP V0.8B, V0.8B, V0.8B
|
0x2E20A400u, // UMAXP V0.8B, V0.8B, V0.8B
|
||||||
0x2E206C00u, // UMIN V0.8B, V0.8B, V0.8B
|
0x2E206C00u, // UMIN V0.8B, V0.8B, V0.8B
|
||||||
0x2E20AC00u // UMINP V0.8B, V0.8B, V0.8B
|
0x2E20AC00u, // UMINP V0.8B, V0.8B, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +541,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x0E20C000u, // SMULL V0.8H, V0.8B, V0.8B
|
0x0E20C000u, // SMULL V0.8H, V0.8B, V0.8B
|
||||||
0x2E208000u, // UMLAL V0.8H, V0.8B, V0.8B
|
0x2E208000u, // UMLAL V0.8H, V0.8B, V0.8B
|
||||||
0x2E20A000u, // UMLSL V0.8H, V0.8B, V0.8B
|
0x2E20A000u, // UMLSL V0.8H, V0.8B, V0.8B
|
||||||
0x2E20C000u // UMULL V0.8H, V0.8B, V0.8B
|
0x2E20C000u, // UMULL V0.8H, V0.8B, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +554,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x4E20C000u, // SMULL2 V0.8H, V0.16B, V0.16B
|
0x4E20C000u, // SMULL2 V0.8H, V0.16B, V0.16B
|
||||||
0x6E208000u, // UMLAL2 V0.8H, V0.16B, V0.16B
|
0x6E208000u, // UMLAL2 V0.8H, V0.16B, V0.16B
|
||||||
0x6E20A000u, // UMLSL2 V0.8H, V0.16B, V0.16B
|
0x6E20A000u, // UMLSL2 V0.8H, V0.16B, V0.16B
|
||||||
0x6E20C000u // UMULL2 V0.8H, V0.16B, V0.16B
|
0x6E20C000u, // UMULL2 V0.8H, V0.16B, V0.16B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,7 +563,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5EE04400u, // SSHL D0, D0, D0
|
0x5EE04400u, // SSHL D0, D0, D0
|
||||||
0x7EE04400u // USHL D0, D0, D0
|
0x7EE04400u, // USHL D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +578,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2E205C00u, // UQRSHL V0.8B, V0.8B, V0.8B
|
0x2E205C00u, // UQRSHL V0.8B, V0.8B, V0.8B
|
||||||
0x2E204C00u, // UQSHL V0.8B, V0.8B, V0.8B
|
0x2E204C00u, // UQSHL V0.8B, V0.8B, V0.8B
|
||||||
0x2E205400u, // URSHL V0.8B, V0.8B, V0.8B
|
0x2E205400u, // URSHL V0.8B, V0.8B, V0.8B
|
||||||
0x2E204400u // USHL V0.8B, V0.8B, V0.8B
|
0x2E204400u, // USHL V0.8B, V0.8B, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,16 +593,16 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x6E205C00u, // UQRSHL V0.16B, V0.16B, V0.16B
|
0x6E205C00u, // UQRSHL V0.16B, V0.16B, V0.16B
|
||||||
0x6E204C00u, // UQSHL V0.16B, V0.16B, V0.16B
|
0x6E204C00u, // UQSHL V0.16B, V0.16B, V0.16B
|
||||||
0x6E205400u, // URSHL V0.16B, V0.16B, V0.16B
|
0x6E205400u, // URSHL V0.16B, V0.16B, V0.16B
|
||||||
0x6E204400u // USHL V0.16B, V0.16B, V0.16B
|
0x6E204400u, // USHL V0.16B, V0.16B, V0.16B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise, Description("ADD <V><d>, <V><n>, <V><m>")]
|
[Test, Pairwise, Description("ADD <V><d>, <V><n>, <V><m>")]
|
||||||
public void Add_S_D([Values(0u)] uint rd,
|
public void Add_S_D([Values(0u)] uint rd,
|
||||||
@@ -1362,7 +1380,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S_))] uint opcodes,
|
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b)
|
[ValueSource(nameof(_1S_F_))] ulong b)
|
||||||
@@ -1382,7 +1401,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D_))] uint opcodes,
|
public void F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Nmul_Sub_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b)
|
[ValueSource(nameof(_1D_F_))] ulong b)
|
||||||
@@ -1402,7 +1422,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S_))] uint opcodes,
|
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1429,7 +1450,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D_))] uint opcodes,
|
public void F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D([ValueSource(nameof(_F_Abd_Add_Div_Mul_Mulx_Sub_P_V_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1454,7 +1476,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Dzc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_AcCm_EqGeGt_S_S([ValueSource(nameof(_F_AcCm_EqGeGt_S_S_))] uint opcodes,
|
public void F_AcCm_EqGeGt_S_S([ValueSource(nameof(_F_AcCm_EqGeGt_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b)
|
[ValueSource(nameof(_1S_F_))] ulong b)
|
||||||
@@ -1473,7 +1496,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_AcCm_EqGeGt_S_D([ValueSource(nameof(_F_AcCm_EqGeGt_S_D_))] uint opcodes,
|
public void F_AcCm_EqGeGt_S_D([ValueSource(nameof(_F_AcCm_EqGeGt_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b)
|
[ValueSource(nameof(_1D_F_))] ulong b)
|
||||||
@@ -1492,7 +1516,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_AcCm_EqGeGt_V_2S_4S([ValueSource(nameof(_F_AcCm_EqGeGt_V_2S_4S_))] uint opcodes,
|
public void F_AcCm_EqGeGt_V_2S_4S([ValueSource(nameof(_F_AcCm_EqGeGt_V_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1518,7 +1543,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_AcCm_EqGeGt_V_2D([ValueSource(nameof(_F_AcCm_EqGeGt_V_2D_))] uint opcodes,
|
public void F_AcCm_EqGeGt_V_2D([ValueSource(nameof(_F_AcCm_EqGeGt_V_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1542,7 +1568,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cmp_Cmpe_S_S([ValueSource(nameof(_F_Cmp_Cmpe_S_S_))] uint opcodes,
|
public void F_Cmp_Cmpe_S_S([ValueSource(nameof(_F_Cmp_Cmpe_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b)
|
[ValueSource(nameof(_1S_F_))] ulong b)
|
||||||
@@ -1560,7 +1587,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cmp_Cmpe_S_D([ValueSource(nameof(_F_Cmp_Cmpe_S_D_))] uint opcodes,
|
public void F_Cmp_Cmpe_S_D([ValueSource(nameof(_F_Cmp_Cmpe_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b)
|
[ValueSource(nameof(_1D_F_))] ulong b)
|
||||||
@@ -1578,7 +1606,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Madd_Msub_Nmadd_Nmsub_S_S([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_S_))] uint opcodes,
|
public void F_Madd_Msub_Nmadd_Nmsub_S_S([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b,
|
[ValueSource(nameof(_1S_F_))] ulong b,
|
||||||
@@ -1600,7 +1630,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Madd_Msub_Nmadd_Nmsub_S_D([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_D_))] uint opcodes,
|
public void F_Madd_Msub_Nmadd_Nmsub_S_D([ValueSource(nameof(_F_Madd_Msub_Nmadd_Nmsub_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b,
|
[ValueSource(nameof(_1D_F_))] ulong b,
|
||||||
@@ -1622,7 +1654,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Max_Min_Nm_S_S([ValueSource(nameof(_F_Max_Min_Nm_S_S_))] uint opcodes,
|
public void F_Max_Min_Nm_S_S([ValueSource(nameof(_F_Max_Min_Nm_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b)
|
[ValueSource(nameof(_1S_F_))] ulong b)
|
||||||
@@ -1642,7 +1675,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Max_Min_Nm_S_D([ValueSource(nameof(_F_Max_Min_Nm_S_D_))] uint opcodes,
|
public void F_Max_Min_Nm_S_D([ValueSource(nameof(_F_Max_Min_Nm_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b)
|
[ValueSource(nameof(_1D_F_))] ulong b)
|
||||||
@@ -1662,7 +1696,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Max_Min_Nm_P_V_2S_4S([ValueSource(nameof(_F_Max_Min_Nm_P_V_2S_4S_))] uint opcodes,
|
public void F_Max_Min_Nm_P_V_2S_4S([ValueSource(nameof(_F_Max_Min_Nm_P_V_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1689,7 +1724,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Max_Min_Nm_P_V_2D([ValueSource(nameof(_F_Max_Min_Nm_P_V_2D_))] uint opcodes,
|
public void F_Max_Min_Nm_P_V_2D([ValueSource(nameof(_F_Max_Min_Nm_P_V_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1714,7 +1750,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_V_2S_4S([ValueSource(nameof(_F_Mla_Mls_V_2S_4S_))] uint opcodes,
|
public void F_Mla_Mls_V_2S_4S([ValueSource(nameof(_F_Mla_Mls_V_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1741,7 +1779,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_V_2D([ValueSource(nameof(_F_Mla_Mls_V_2D_))] uint opcodes,
|
public void F_Mla_Mls_V_2D([ValueSource(nameof(_F_Mla_Mls_V_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1766,7 +1806,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Recps_Rsqrts_S_S([ValueSource(nameof(_F_Recps_Rsqrts_S_S_))] uint opcodes,
|
public void F_Recps_Rsqrts_S_S([ValueSource(nameof(_F_Recps_Rsqrts_S_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong b)
|
[ValueSource(nameof(_1S_F_))] ulong b)
|
||||||
@@ -1786,7 +1828,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Recps_Rsqrts_S_D([ValueSource(nameof(_F_Recps_Rsqrts_S_D_))] uint opcodes,
|
public void F_Recps_Rsqrts_S_D([ValueSource(nameof(_F_Recps_Rsqrts_S_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b)
|
[ValueSource(nameof(_1D_F_))] ulong b)
|
||||||
@@ -1806,7 +1850,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Recps_Rsqrts_V_2S_4S([ValueSource(nameof(_F_Recps_Rsqrts_V_2S_4S_))] uint opcodes,
|
public void F_Recps_Rsqrts_V_2S_4S([ValueSource(nameof(_F_Recps_Rsqrts_V_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -1833,7 +1879,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Recps_Rsqrts_V_2D([ValueSource(nameof(_F_Recps_Rsqrts_V_2D_))] uint opcodes,
|
public void F_Recps_Rsqrts_V_2D([ValueSource(nameof(_F_Recps_Rsqrts_V_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2800000u, // VADDL.S8 Q0, D0, D0
|
0xf2800000u, // VADDL.S8 Q0, D0, D0
|
||||||
0xf2800100u, // VADDW.S8 Q0, Q0, D0
|
0xf2800100u, // VADDW.S8 Q0, Q0, D0
|
||||||
0xf2800200u, // VSUBL.S8 Q0, D0, D0
|
0xf2800200u, // VSUBL.S8 Q0, D0, D0
|
||||||
0xf2800300u // VSUBW.S8 Q0, Q0, D0
|
0xf2800300u, // VSUBW.S8 Q0, Q0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xEEA00A00u, // VFMA. F32 S0, S0, S0
|
0xEEA00A00u, // VFMA. F32 S0, S0, S0
|
||||||
0xEEA00A40u, // VFMS. F32 S0, S0, S0
|
0xEEA00A40u, // VFMS. F32 S0, S0, S0
|
||||||
0xEE900A40u, // VFNMA.F32 S0, S0, S0
|
0xEE900A40u, // VFNMA.F32 S0, S0, S0
|
||||||
0xEE900A00u // VFNMS.F32 S0, S0, S0
|
0xEE900A00u, // VFNMS.F32 S0, S0, S0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xEEA00B00u, // VFMA. F64 D0, D0, D0
|
0xEEA00B00u, // VFMA. F64 D0, D0, D0
|
||||||
0xEEA00B40u, // VFMS. F64 D0, D0, D0
|
0xEEA00B40u, // VFMS. F64 D0, D0, D0
|
||||||
0xEE900B40u, // VFNMA.F64 D0, D0, D0
|
0xEE900B40u, // VFNMA.F64 D0, D0, D0
|
||||||
0xEE900B00u // VFNMS.F64 D0, D0, D0
|
0xEE900B00u, // VFNMS.F64 D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xF2000C10u, // VFMA.F32 D0, D0, D0
|
0xF2000C10u, // VFMA.F32 D0, D0, D0
|
||||||
0xF2200C10u // VFMS.F32 D0, D0, D0
|
0xF2200C10u, // VFMS.F32 D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xEE000A00u, // VMLA. F32 S0, S0, S0
|
0xEE000A00u, // VMLA. F32 S0, S0, S0
|
||||||
0xEE000A40u, // VMLS. F32 S0, S0, S0
|
0xEE000A40u, // VMLS. F32 S0, S0, S0
|
||||||
0xEE100A40u, // VNMLA.F32 S0, S0, S0
|
0xEE100A40u, // VNMLA.F32 S0, S0, S0
|
||||||
0xEE100A00u // VNMLS.F32 S0, S0, S0
|
0xEE100A00u, // VNMLS.F32 S0, S0, S0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xEE000B00u, // VMLA. F64 D0, D0, D0
|
0xEE000B00u, // VMLA. F64 D0, D0, D0
|
||||||
0xEE000B40u, // VMLS. F64 D0, D0, D0
|
0xEE000B40u, // VMLS. F64 D0, D0, D0
|
||||||
0xEE100B40u, // VNMLA.F64 D0, D0, D0
|
0xEE100B40u, // VNMLA.F64 D0, D0, D0
|
||||||
0xEE100B00u // VNMLS.F64 D0, D0, D0
|
0xEE100B00u, // VNMLS.F64 D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xf2800800u, // VMLAL.S8 Q0, D0, D0
|
0xf2800800u, // VMLAL.S8 Q0, D0, D0
|
||||||
0xf2800a00u // VMLSL.S8 Q0, D0, D0
|
0xf2800a00u, // VMLSL.S8 Q0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0xf3000d00u, // VPADD.F32 D0, D0, D0
|
0xf3000d00u, // VPADD.F32 D0, D0, D0
|
||||||
0xf3000f00u, // VPMAX.F32 D0, D0, D0
|
0xf3000f00u, // VPMAX.F32 D0, D0, D0
|
||||||
0xf3200f00u // VPMIN.F32 D0, D0, D0
|
0xf3200f00u, // VPMIN.F32 D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xf2000b10u // VPADD.I8 D0, D0, D0
|
0xf2000b10u, // VPADD.I8 D0, D0, D0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xf2000050u, // VQADD.S8 Q0, Q0, Q0
|
0xf2000050u, // VQADD.S8 Q0, Q0, Q0
|
||||||
0xf2000250u // VQSUB.S8 Q0, Q0, Q0
|
0xf2000250u, // VQSUB.S8 Q0, Q0, Q0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -127,18 +127,22 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _8B1D_()
|
private static ulong[] _8B1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
|
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H2S1D_()
|
private static ulong[] _8B4H2S1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _1S_F_()
|
private static IEnumerable<ulong> _1S_F_()
|
||||||
@@ -152,19 +156,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -194,19 +198,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -235,19 +239,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -268,9 +272,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")]
|
[Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")]
|
||||||
public void Sha256h_V([Values(0xF3000C40u)] uint opcode,
|
public void Sha256h_V([Values(0xF3000C40u)] uint opcode,
|
||||||
@@ -425,8 +429,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= 1 << 24;
|
opcode |= 1 << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
|
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
|
||||||
@@ -480,7 +486,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vfma_Vfms_Vfnma_Vfnms_S_F32([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F32_))] uint opcode,
|
public void Vfma_Vfms_Vfnma_Vfnms_S_F32([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F32_))] uint opcode,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rd,
|
[Values(0u, 1u, 2u, 3u)] uint rd,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rn,
|
[Values(0u, 1u, 2u, 3u)] uint rn,
|
||||||
@@ -501,7 +509,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vfma_Vfms_Vfnma_Vfnms_S_F64([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F64_))] uint opcode,
|
public void Vfma_Vfms_Vfnma_Vfnms_S_F64([ValueSource(nameof(_Vfma_Vfms_Vfnma_Vfnms_S_F64_))] uint opcode,
|
||||||
[Values(0u, 1u)] uint rd,
|
[Values(0u, 1u)] uint rd,
|
||||||
[Values(0u, 1u)] uint rn,
|
[Values(0u, 1u)] uint rn,
|
||||||
@@ -520,7 +530,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vfma_Vfms_V_F32([ValueSource(nameof(_Vfma_Vfms_V_F32_))] uint opcode,
|
public void Vfma_Vfms_V_F32([ValueSource(nameof(_Vfma_Vfms_V_F32_))] uint opcode,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rd,
|
[Values(0u, 1u, 2u, 3u)] uint rd,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rn,
|
[Values(0u, 1u, 2u, 3u)] uint rn,
|
||||||
@@ -535,9 +547,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
@@ -552,7 +567,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vmla_Vmls_Vnmla_Vnmls_S_F32([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F32_))] uint opcode,
|
public void Vmla_Vmls_Vnmla_Vnmls_S_F32([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F32_))] uint opcode,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rd,
|
[Values(0u, 1u, 2u, 3u)] uint rd,
|
||||||
[Values(0u, 1u, 2u, 3u)] uint rn,
|
[Values(0u, 1u, 2u, 3u)] uint rn,
|
||||||
@@ -573,7 +589,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void Vmla_Vmls_Vnmla_Vnmls_S_F64([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F64_))] uint opcode,
|
public void Vmla_Vmls_Vnmla_Vnmls_S_F64([ValueSource(nameof(_Vmla_Vmls_Vnmla_Vnmls_S_F64_))] uint opcode,
|
||||||
[Values(0u, 1u)] uint rd,
|
[Values(0u, 1u)] uint rd,
|
||||||
[Values(0u, 1u)] uint rn,
|
[Values(0u, 1u)] uint rn,
|
||||||
@@ -678,7 +695,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
uint opcode = 0xf2800e00u; // VMULL.P8 Q0, D0, D0
|
uint opcode = 0xf2800e00u; // VMULL.P8 Q0, D0, D0
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
|
rd <<= 1;
|
||||||
|
|
||||||
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
|
opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
|
||||||
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
|
opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
|
||||||
@@ -836,9 +854,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
opcode |= 1 << 24;
|
opcode |= 1 << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
|
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
|
||||||
@@ -864,9 +885,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
|
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
|
||||||
[Values(1u, 2u)] uint size) // <S16, S32>
|
[Values(1u, 2u)] uint size) // <S16, S32>
|
||||||
{
|
{
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rn >>= 1; rn <<= 1;
|
rd <<= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rn >>= 1;
|
||||||
|
rn <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
|
|
||||||
uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0
|
uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0
|
||||||
|
|
||||||
|
@@ -13,14 +13,18 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _2S_()
|
private static ulong[] _2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
return new[] {
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H_()
|
private static ulong[] _4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
|
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -33,7 +37,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F404000u, // MLS V0.4H, V0.4H, V0.H[0]
|
0x2F404000u, // MLS V0.4H, V0.4H, V0.H[0]
|
||||||
0x0F408000u, // MUL V0.4H, V0.4H, V0.H[0]
|
0x0F408000u, // MUL V0.4H, V0.4H, V0.H[0]
|
||||||
0x0F40C000u, // SQDMULH V0.4H, V0.4H, V0.H[0]
|
0x0F40C000u, // SQDMULH V0.4H, V0.4H, V0.H[0]
|
||||||
0x0F40D000u // SQRDMULH V0.4H, V0.4H, V0.H[0]
|
0x0F40D000u, // SQRDMULH V0.4H, V0.4H, V0.H[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +49,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F804000u, // MLS V0.2S, V0.2S, V0.S[0]
|
0x2F804000u, // MLS V0.2S, V0.2S, V0.S[0]
|
||||||
0x0F808000u, // MUL V0.2S, V0.2S, V0.S[0]
|
0x0F808000u, // MUL V0.2S, V0.2S, V0.S[0]
|
||||||
0x0F80C000u, // SQDMULH V0.2S, V0.2S, V0.S[0]
|
0x0F80C000u, // SQDMULH V0.2S, V0.2S, V0.S[0]
|
||||||
0x0F80D000u // SQRDMULH V0.2S, V0.2S, V0.S[0]
|
0x0F80D000u, // SQRDMULH V0.2S, V0.2S, V0.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x0F40A000u, // SMULL V0.4S, V0.4H, V0.H[0]
|
0x0F40A000u, // SMULL V0.4S, V0.4H, V0.H[0]
|
||||||
0x2F402000u, // UMLAL V0.4S, V0.4H, V0.H[0]
|
0x2F402000u, // UMLAL V0.4S, V0.4H, V0.H[0]
|
||||||
0x2F406000u, // UMLSL V0.4S, V0.4H, V0.H[0]
|
0x2F406000u, // UMLSL V0.4S, V0.4H, V0.H[0]
|
||||||
0x2F40A000u // UMULL V0.4S, V0.4H, V0.H[0]
|
0x2F40A000u, // UMULL V0.4S, V0.4H, V0.H[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +75,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x0F80A000u, // SMULL V0.2D, V0.2S, V0.S[0]
|
0x0F80A000u, // SMULL V0.2D, V0.2S, V0.S[0]
|
||||||
0x2F802000u, // UMLAL V0.2D, V0.2S, V0.S[0]
|
0x2F802000u, // UMLAL V0.2D, V0.2S, V0.S[0]
|
||||||
0x2F806000u, // UMLSL V0.2D, V0.2S, V0.S[0]
|
0x2F806000u, // UMLSL V0.2D, V0.2S, V0.S[0]
|
||||||
0x2F80A000u // UMULL V0.2D, V0.2S, V0.S[0]
|
0x2F80A000u, // UMULL V0.2D, V0.2S, V0.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -23,19 +23,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
yield return 0x00000000007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x0000000080000000ul; // -Zero
|
yield return 0x0000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FF800000ul; // -Infinity
|
yield return 0x00000000FF800000ul; // -Infinity
|
||||||
yield return 0x000000007F800000ul; // +Infinity
|
yield return 0x000000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -65,19 +65,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -106,19 +106,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -143,7 +143,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5F821020u, // FMLA S0, S1, V2.S[0]
|
0x5F821020u, // FMLA S0, S1, V2.S[0]
|
||||||
0x5F825020u // FMLS S0, S1, V2.S[0]
|
0x5F825020u, // FMLS S0, S1, V2.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5FC21020u, // FMLA D0, D1, V2.D[0]
|
0x5FC21020u, // FMLA D0, D1, V2.D[0]
|
||||||
0x5FC25020u // FMLS D0, D1, V2.D[0]
|
0x5FC25020u, // FMLS D0, D1, V2.D[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F801000u, // FMLA V0.2S, V0.2S, V0.S[0]
|
0x0F801000u, // FMLA V0.2S, V0.2S, V0.S[0]
|
||||||
0x0F805000u // FMLS V0.2S, V0.2S, V0.S[0]
|
0x0F805000u, // FMLS V0.2S, V0.2S, V0.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4FC01000u, // FMLA V0.2D, V0.2D, V0.D[0]
|
0x4FC01000u, // FMLA V0.2D, V0.2D, V0.D[0]
|
||||||
0x4FC05000u // FMLS V0.2D, V0.2D, V0.D[0]
|
0x4FC05000u, // FMLS V0.2D, V0.2D, V0.D[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5F829020u, // FMUL S0, S1, V2.S[0]
|
0x5F829020u, // FMUL S0, S1, V2.S[0]
|
||||||
0x7F829020u // FMULX S0, S1, V2.S[0]
|
0x7F829020u, // FMULX S0, S1, V2.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5FC29020u, // FMUL D0, D1, V2.D[0]
|
0x5FC29020u, // FMUL D0, D1, V2.D[0]
|
||||||
0x7FC29020u // FMULX D0, D1, V2.D[0]
|
0x7FC29020u, // FMULX D0, D1, V2.D[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F809000u, // FMUL V0.2S, V0.2S, V0.S[0]
|
0x0F809000u, // FMUL V0.2S, V0.2S, V0.S[0]
|
||||||
0x2F809000u // FMULX V0.2S, V0.2S, V0.S[0]
|
0x2F809000u, // FMULX V0.2S, V0.2S, V0.S[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,18 +206,20 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4FC09000u, // FMUL V0.2D, V0.2D, V0.D[0]
|
0x4FC09000u, // FMUL V0.2D, V0.2D, V0.D[0]
|
||||||
0x6FC09000u // FMULX V0.2D, V0.2D, V0.D[0]
|
0x6FC09000u, // FMULX V0.2D, V0.2D, V0.D[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_Se_S([ValueSource(nameof(_F_Mla_Mls_Se_S_))] uint opcodes,
|
public void F_Mla_Mls_Se_S([ValueSource(nameof(_F_Mla_Mls_Se_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong z,
|
[ValueSource(nameof(_1S_F_))] ulong z,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
@@ -243,7 +245,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_Se_D([ValueSource(nameof(_F_Mla_Mls_Se_D_))] uint opcodes,
|
public void F_Mla_Mls_Se_D([ValueSource(nameof(_F_Mla_Mls_Se_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong z,
|
[ValueSource(nameof(_1D_F_))] ulong z,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
@@ -268,7 +272,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_Ve_2S_4S([ValueSource(nameof(_F_Mla_Mls_Ve_2S_4S_))] uint opcodes,
|
public void F_Mla_Mls_Ve_2S_4S([ValueSource(nameof(_F_Mla_Mls_Ve_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -300,7 +306,9 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsS);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit] // Fused.
|
// Fused.
|
||||||
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mla_Mls_Ve_2D([ValueSource(nameof(_F_Mla_Mls_Ve_2D_))] uint opcodes,
|
public void F_Mla_Mls_Ve_2D([ValueSource(nameof(_F_Mla_Mls_Ve_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -329,7 +337,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
CompareAgainstUnicorn(Fpsr.Ioc | Fpsr.Idc, FpSkips.IfUnderflow, FpTolerances.UpToOneUlpsD);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mul_Mulx_Se_S([ValueSource(nameof(_F_Mul_Mulx_Se_S_))] uint opcodes,
|
public void F_Mul_Mulx_Se_S([ValueSource(nameof(_F_Mul_Mulx_Se_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_F_))] ulong a,
|
[ValueSource(nameof(_1S_F_))] ulong a,
|
||||||
[ValueSource(nameof(_2S_F_))] ulong b,
|
[ValueSource(nameof(_2S_F_))] ulong b,
|
||||||
@@ -355,7 +364,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mul_Mulx_Se_D([ValueSource(nameof(_F_Mul_Mulx_Se_D_))] uint opcodes,
|
public void F_Mul_Mulx_Se_D([ValueSource(nameof(_F_Mul_Mulx_Se_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong a,
|
[ValueSource(nameof(_1D_F_))] ulong a,
|
||||||
[ValueSource(nameof(_1D_F_))] ulong b,
|
[ValueSource(nameof(_1D_F_))] ulong b,
|
||||||
@@ -380,7 +390,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mul_Mulx_Ve_2S_4S([ValueSource(nameof(_F_Mul_Mulx_Ve_2S_4S_))] uint opcodes,
|
public void F_Mul_Mulx_Ve_2S_4S([ValueSource(nameof(_F_Mul_Mulx_Ve_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -412,7 +423,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Mul_Mulx_Ve_2D([ValueSource(nameof(_F_Mul_Mulx_Ve_2D_))] uint opcodes,
|
public void F_Mul_Mulx_Ve_2D([ValueSource(nameof(_F_Mul_Mulx_Ve_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
|
@@ -15,38 +15,50 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _1D_()
|
private static ulong[] _1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _1H_()
|
private static ulong[] _1H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul,
|
return new[] {
|
||||||
0x0000000000008000ul, 0x000000000000FFFFul };
|
0x0000000000000000ul, 0x0000000000007FFFul,
|
||||||
|
0x0000000000008000ul, 0x000000000000FFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _1S_()
|
private static ulong[] _1S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x000000007FFFFFFFul,
|
return new[] {
|
||||||
0x0000000080000000ul, 0x00000000FFFFFFFFul };
|
0x0000000000000000ul, 0x000000007FFFFFFFul,
|
||||||
|
0x0000000080000000ul, 0x00000000FFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _2S_()
|
private static ulong[] _2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
return new[] {
|
||||||
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
|
||||||
|
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H_()
|
private static ulong[] _4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
return new[] {
|
||||||
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
|
||||||
|
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _2S_F_W_()
|
private static IEnumerable<ulong> _2S_F_W_()
|
||||||
@@ -73,19 +85,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000080000000ul; // -Zero
|
yield return 0x8000000080000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFF800000FF800000ul; // -Infinity
|
yield return 0xFF800000FF800000ul; // -Infinity
|
||||||
yield return 0x7F8000007F800000ul; // +Infinity
|
yield return 0x7F8000007F800000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
|
||||||
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -133,19 +145,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
|
||||||
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
|
||||||
|
|
||||||
if (!NoZeros)
|
if (!_noZeros)
|
||||||
{
|
{
|
||||||
yield return 0x8000000000000000ul; // -Zero
|
yield return 0x8000000000000000ul; // -Zero
|
||||||
yield return 0x0000000000000000ul; // +Zero
|
yield return 0x0000000000000000ul; // +Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoInfs)
|
if (!_noInfs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF0000000000000ul; // -Infinity
|
yield return 0xFFF0000000000000ul; // -Infinity
|
||||||
yield return 0x7FF0000000000000ul; // +Infinity
|
yield return 0x7FF0000000000000ul; // +Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NoNaNs)
|
if (!_noNaNs)
|
||||||
{
|
{
|
||||||
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
|
||||||
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
|
||||||
@@ -178,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F20FC00u, // FCVTZS V0.2S, V0.2S, #32
|
0x0F20FC00u, // FCVTZS V0.2S, V0.2S, #32
|
||||||
0x2F20FC00u // FCVTZU V0.2S, V0.2S, #32
|
0x2F20FC00u, // FCVTZU V0.2S, V0.2S, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +199,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4F40FC00u, // FCVTZS V0.2D, V0.2D, #64
|
0x4F40FC00u, // FCVTZS V0.2D, V0.2D, #64
|
||||||
0x6F40FC00u // FCVTZU V0.2D, V0.2D, #64
|
0x6F40FC00u, // FCVTZU V0.2D, V0.2D, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +208,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5F20E420u, // SCVTF S0, S1, #32
|
0x5F20E420u, // SCVTF S0, S1, #32
|
||||||
0x7F20E420u // UCVTF S0, S1, #32
|
0x7F20E420u, // UCVTF S0, S1, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +217,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5F40E420u, // SCVTF D0, D1, #64
|
0x5F40E420u, // SCVTF D0, D1, #64
|
||||||
0x7F40E420u // UCVTF D0, D1, #64
|
0x7F40E420u, // UCVTF D0, D1, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +226,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F20E400u, // SCVTF V0.2S, V0.2S, #32
|
0x0F20E400u, // SCVTF V0.2S, V0.2S, #32
|
||||||
0x2F20E400u // UCVTF V0.2S, V0.2S, #32
|
0x2F20E400u, // UCVTF V0.2S, V0.2S, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +235,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4F40E400u, // SCVTF V0.2D, V0.2D, #64
|
0x4F40E400u, // SCVTF V0.2D, V0.2D, #64
|
||||||
0x6F40E400u // UCVTF V0.2D, V0.2D, #64
|
0x6F40E400u, // UCVTF V0.2D, V0.2D, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +244,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x5F405400u, // SHL D0, D0, #0
|
0x5F405400u, // SHL D0, D0, #0
|
||||||
0x7F405400u // SLI D0, D0, #0
|
0x7F405400u, // SLI D0, D0, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +253,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F085400u, // SHL V0.8B, V0.8B, #0
|
0x0F085400u, // SHL V0.8B, V0.8B, #0
|
||||||
0x2F085400u // SLI V0.8B, V0.8B, #0
|
0x2F085400u, // SLI V0.8B, V0.8B, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F105400u, // SHL V0.4H, V0.4H, #0
|
0x0F105400u, // SHL V0.4H, V0.4H, #0
|
||||||
0x2F105400u // SLI V0.4H, V0.4H, #0
|
0x2F105400u, // SLI V0.4H, V0.4H, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +271,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F205400u, // SHL V0.2S, V0.2S, #0
|
0x0F205400u, // SHL V0.2S, V0.2S, #0
|
||||||
0x2F205400u // SLI V0.2S, V0.2S, #0
|
0x2F205400u, // SLI V0.2S, V0.2S, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +280,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x4F405400u, // SHL V0.2D, V0.2D, #0
|
0x4F405400u, // SHL V0.2D, V0.2D, #0
|
||||||
0x6F405400u // SLI V0.2D, V0.2D, #0
|
0x6F405400u, // SLI V0.2D, V0.2D, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +289,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F08A400u, // SSHLL V0.8H, V0.8B, #0
|
0x0F08A400u, // SSHLL V0.8H, V0.8B, #0
|
||||||
0x2F08A400u // USHLL V0.8H, V0.8B, #0
|
0x2F08A400u, // USHLL V0.8H, V0.8B, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +298,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F10A400u, // SSHLL V0.4S, V0.4H, #0
|
0x0F10A400u, // SSHLL V0.4S, V0.4H, #0
|
||||||
0x2F10A400u // USHLL V0.4S, V0.4H, #0
|
0x2F10A400u, // USHLL V0.4S, V0.4H, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +307,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F20A400u, // SSHLL V0.2D, V0.2S, #0
|
0x0F20A400u, // SSHLL V0.2D, V0.2S, #0
|
||||||
0x2F20A400u // USHLL V0.2D, V0.2S, #0
|
0x2F20A400u, // USHLL V0.2D, V0.2S, #0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +323,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7F402400u, // URSHR D0, D0, #64
|
0x7F402400u, // URSHR D0, D0, #64
|
||||||
0x7F403400u, // URSRA D0, D0, #64
|
0x7F403400u, // URSRA D0, D0, #64
|
||||||
0x7F400400u, // USHR D0, D0, #64
|
0x7F400400u, // USHR D0, D0, #64
|
||||||
0x7F401400u // USRA D0, D0, #64
|
0x7F401400u, // USRA D0, D0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +339,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F082400u, // URSHR V0.8B, V0.8B, #8
|
0x2F082400u, // URSHR V0.8B, V0.8B, #8
|
||||||
0x2F083400u, // URSRA V0.8B, V0.8B, #8
|
0x2F083400u, // URSRA V0.8B, V0.8B, #8
|
||||||
0x2F080400u, // USHR V0.8B, V0.8B, #8
|
0x2F080400u, // USHR V0.8B, V0.8B, #8
|
||||||
0x2F081400u // USRA V0.8B, V0.8B, #8
|
0x2F081400u, // USRA V0.8B, V0.8B, #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +355,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F102400u, // URSHR V0.4H, V0.4H, #16
|
0x2F102400u, // URSHR V0.4H, V0.4H, #16
|
||||||
0x2F103400u, // URSRA V0.4H, V0.4H, #16
|
0x2F103400u, // URSRA V0.4H, V0.4H, #16
|
||||||
0x2F100400u, // USHR V0.4H, V0.4H, #16
|
0x2F100400u, // USHR V0.4H, V0.4H, #16
|
||||||
0x2F101400u // USRA V0.4H, V0.4H, #16
|
0x2F101400u, // USRA V0.4H, V0.4H, #16
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +371,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F202400u, // URSHR V0.2S, V0.2S, #32
|
0x2F202400u, // URSHR V0.2S, V0.2S, #32
|
||||||
0x2F203400u, // URSRA V0.2S, V0.2S, #32
|
0x2F203400u, // URSRA V0.2S, V0.2S, #32
|
||||||
0x2F200400u, // USHR V0.2S, V0.2S, #32
|
0x2F200400u, // USHR V0.2S, V0.2S, #32
|
||||||
0x2F201400u // USRA V0.2S, V0.2S, #32
|
0x2F201400u, // USRA V0.2S, V0.2S, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +387,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x6F402400u, // URSHR V0.2D, V0.2D, #64
|
0x6F402400u, // URSHR V0.2D, V0.2D, #64
|
||||||
0x6F403400u, // URSRA V0.2D, V0.2D, #64
|
0x6F403400u, // URSRA V0.2D, V0.2D, #64
|
||||||
0x6F400400u, // USHR V0.2D, V0.2D, #64
|
0x6F400400u, // USHR V0.2D, V0.2D, #64
|
||||||
0x6F401400u // USRA V0.2D, V0.2D, #64
|
0x6F401400u, // USRA V0.2D, V0.2D, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +396,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F088C00u, // RSHRN V0.8B, V0.8H, #8
|
0x0F088C00u, // RSHRN V0.8B, V0.8H, #8
|
||||||
0x0F088400u // SHRN V0.8B, V0.8H, #8
|
0x0F088400u, // SHRN V0.8B, V0.8H, #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +405,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F108C00u, // RSHRN V0.4H, V0.4S, #16
|
0x0F108C00u, // RSHRN V0.4H, V0.4S, #16
|
||||||
0x0F108400u // SHRN V0.4H, V0.4S, #16
|
0x0F108400u, // SHRN V0.4H, V0.4S, #16
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +414,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0F208C00u, // RSHRN V0.2S, V0.2D, #32
|
0x0F208C00u, // RSHRN V0.2S, V0.2D, #32
|
||||||
0x0F208400u // SHRN V0.2S, V0.2D, #32
|
0x0F208400u, // SHRN V0.2S, V0.2D, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +427,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7F088C00u, // SQRSHRUN B0, H0, #8
|
0x7F088C00u, // SQRSHRUN B0, H0, #8
|
||||||
0x5F089400u, // SQSHRN B0, H0, #8
|
0x5F089400u, // SQSHRN B0, H0, #8
|
||||||
0x7F089400u, // UQSHRN B0, H0, #8
|
0x7F089400u, // UQSHRN B0, H0, #8
|
||||||
0x7F088400u // SQSHRUN B0, H0, #8
|
0x7F088400u, // SQSHRUN B0, H0, #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +440,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7F108C00u, // SQRSHRUN H0, S0, #16
|
0x7F108C00u, // SQRSHRUN H0, S0, #16
|
||||||
0x5F109400u, // SQSHRN H0, S0, #16
|
0x5F109400u, // SQSHRN H0, S0, #16
|
||||||
0x7F109400u, // UQSHRN H0, S0, #16
|
0x7F109400u, // UQSHRN H0, S0, #16
|
||||||
0x7F108400u // SQSHRUN H0, S0, #16
|
0x7F108400u, // SQSHRUN H0, S0, #16
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +453,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x7F208C00u, // SQRSHRUN S0, D0, #32
|
0x7F208C00u, // SQRSHRUN S0, D0, #32
|
||||||
0x5F209400u, // SQSHRN S0, D0, #32
|
0x5F209400u, // SQSHRN S0, D0, #32
|
||||||
0x7F209400u, // UQSHRN S0, D0, #32
|
0x7F209400u, // UQSHRN S0, D0, #32
|
||||||
0x7F208400u // SQSHRUN S0, D0, #32
|
0x7F208400u, // SQSHRUN S0, D0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +466,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F088C00u, // SQRSHRUN V0.8B, V0.8H, #8
|
0x2F088C00u, // SQRSHRUN V0.8B, V0.8H, #8
|
||||||
0x0F089400u, // SQSHRN V0.8B, V0.8H, #8
|
0x0F089400u, // SQSHRN V0.8B, V0.8H, #8
|
||||||
0x2F089400u, // UQSHRN V0.8B, V0.8H, #8
|
0x2F089400u, // UQSHRN V0.8B, V0.8H, #8
|
||||||
0x2F088400u // SQSHRUN V0.8B, V0.8H, #8
|
0x2F088400u, // SQSHRUN V0.8B, V0.8H, #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +479,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F108C00u, // SQRSHRUN V0.4H, V0.4S, #16
|
0x2F108C00u, // SQRSHRUN V0.4H, V0.4S, #16
|
||||||
0x0F109400u, // SQSHRN V0.4H, V0.4S, #16
|
0x0F109400u, // SQSHRN V0.4H, V0.4S, #16
|
||||||
0x2F109400u, // UQSHRN V0.4H, V0.4S, #16
|
0x2F109400u, // UQSHRN V0.4H, V0.4S, #16
|
||||||
0x2F108400u // SQSHRUN V0.4H, V0.4S, #16
|
0x2F108400u, // SQSHRUN V0.4H, V0.4S, #16
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,18 +492,19 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0x2F208C00u, // SQRSHRUN V0.2S, V0.2D, #32
|
0x2F208C00u, // SQRSHRUN V0.2S, V0.2D, #32
|
||||||
0x0F209400u, // SQSHRN V0.2S, V0.2D, #32
|
0x0F209400u, // SQSHRN V0.2S, V0.2D, #32
|
||||||
0x2F209400u, // UQSHRN V0.2S, V0.2D, #32
|
0x2F209400u, // UQSHRN V0.2S, V0.2D, #32
|
||||||
0x2F208400u // SQSHRUN V0.2S, V0.2D, #32
|
0x2F208400u, // SQSHRUN V0.2S, V0.2D, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private const int RndCnt = 2;
|
private const int RndCnt = 2;
|
||||||
|
|
||||||
private static readonly bool NoZeros = false;
|
private static readonly bool _noZeros = false;
|
||||||
private static readonly bool NoInfs = false;
|
private static readonly bool _noInfs = false;
|
||||||
private static readonly bool NoNaNs = false;
|
private static readonly bool _noNaNs = false;
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_V_Fixed_2S_4S([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2S_4S_))] uint opcodes,
|
public void F_Cvt_Z_SU_V_Fixed_2S_4S([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -514,7 +527,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void F_Cvt_Z_SU_V_Fixed_2D([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2D_))] uint opcodes,
|
public void F_Cvt_Z_SU_V_Fixed_2D([ValueSource(nameof(_F_Cvt_Z_SU_V_Fixed_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -535,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_S_Fixed_S([ValueSource(nameof(_SU_Cvt_F_S_Fixed_S_))] uint opcodes,
|
public void SU_Cvt_F_S_Fixed_S([ValueSource(nameof(_SU_Cvt_F_S_Fixed_S_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1S_))] ulong a,
|
[ValueSource(nameof(_1S_))] ulong a,
|
||||||
[Values(1u, 32u)] uint fBits)
|
[Values(1u, 32u)] uint fBits)
|
||||||
@@ -553,7 +568,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_S_Fixed_D([ValueSource(nameof(_SU_Cvt_F_S_Fixed_D_))] uint opcodes,
|
public void SU_Cvt_F_S_Fixed_D([ValueSource(nameof(_SU_Cvt_F_S_Fixed_D_))] uint opcodes,
|
||||||
[ValueSource(nameof(_1D_))] ulong a,
|
[ValueSource(nameof(_1D_))] ulong a,
|
||||||
[Values(1u, 64u)] uint fBits)
|
[Values(1u, 64u)] uint fBits)
|
||||||
@@ -571,7 +587,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2S_4S_))] uint opcodes,
|
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2S_4S_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
@@ -594,7 +611,8 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise]
|
||||||
|
[Explicit]
|
||||||
public void SU_Cvt_F_V_Fixed_2D([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2D_))] uint opcodes,
|
public void SU_Cvt_F_V_Fixed_2D([ValueSource(nameof(_SU_Cvt_F_V_Fixed_2D_))] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(1u, 0u)] uint rn,
|
||||||
|
@@ -13,23 +13,34 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _1D_()
|
private static ulong[] _1D_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
return new[] {
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
|
||||||
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _2S_()
|
private static ulong[] _2S_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
|
return new[]
|
||||||
|
{
|
||||||
|
0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _4H_()
|
private static ulong[] _4H_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
|
return new[]
|
||||||
|
{
|
||||||
|
0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
return new[]
|
||||||
|
{
|
||||||
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -41,7 +52,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2880010u, // VSHR.S8 D0, D0, #8
|
0xf2880010u, // VSHR.S8 D0, D0, #8
|
||||||
0xf2880110u, // VSRA.S8 D0, D0, #8
|
0xf2880110u, // VSRA.S8 D0, D0, #8
|
||||||
0xf2880210u, // VRSHR.S8 D0, D0, #8
|
0xf2880210u, // VRSHR.S8 D0, D0, #8
|
||||||
0xf2880310u // VRSRA.S8 D0, D0, #8
|
0xf2880310u, // VRSRA.S8 D0, D0, #8
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +63,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2900010u, // VSHR.S16 D0, D0, #16
|
0xf2900010u, // VSHR.S16 D0, D0, #16
|
||||||
0xf2900110u, // VSRA.S16 D0, D0, #16
|
0xf2900110u, // VSRA.S16 D0, D0, #16
|
||||||
0xf2900210u, // VRSHR.S16 D0, D0, #16
|
0xf2900210u, // VRSHR.S16 D0, D0, #16
|
||||||
0xf2900310u // VRSRA.S16 D0, D0, #16
|
0xf2900310u, // VRSRA.S16 D0, D0, #16
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
0xf2a00010u, // VSHR.S32 D0, D0, #32
|
0xf2a00010u, // VSHR.S32 D0, D0, #32
|
||||||
0xf2a00110u, // VSRA.S32 D0, D0, #32
|
0xf2a00110u, // VSRA.S32 D0, D0, #32
|
||||||
0xf2a00210u, // VRSHR.S32 D0, D0, #32
|
0xf2a00210u, // VRSHR.S32 D0, D0, #32
|
||||||
0xf2a00310u // VRSRA.S32 D0, D0, #32
|
0xf2a00310u, // VRSRA.S32 D0, D0, #32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +84,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0xf2800190u, // VSRA.S64 D0, D0, #64
|
0xf2800190u, // VSRA.S64 D0, D0, #64
|
||||||
0xf2800290u, // VRSHR.S64 D0, D0, #64
|
0xf2800290u, // VRSHR.S64 D0, D0, #64
|
||||||
0xf2800090u // VSHR.S64 D0, D0, #64
|
0xf2800090u, // VSHR.S64 D0, D0, #64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +94,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN)
|
0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN)
|
||||||
0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
|
0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
|
||||||
0xf2800850u // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
|
0xf2800850u, // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +103,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
|
0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
|
||||||
0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
|
0xf3800850u, // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -171,8 +182,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
opcode |= 1 << 6;
|
opcode |= 1 << 6;
|
||||||
|
|
||||||
rd >>= 1; rd <<= 1;
|
rd >>= 1;
|
||||||
rm >>= 1; rm <<= 1;
|
rd <<= 1;
|
||||||
|
rm >>= 1;
|
||||||
|
rm <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
|
@@ -38,8 +38,10 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
#region "ValueSource (Types)"
|
#region "ValueSource (Types)"
|
||||||
private static ulong[] _8B_()
|
private static ulong[] _8B_()
|
||||||
{
|
{
|
||||||
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new[] {
|
||||||
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ulong> _GenIdxsForTbl1_()
|
private static IEnumerable<ulong> _GenIdxsForTbl1_()
|
||||||
@@ -101,7 +103,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B
|
0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B
|
||||||
0x0E001000u // TBX V0.8B, { V0.16B }, V0.8B
|
0x0E001000u, // TBX V0.8B, { V0.16B }, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +112,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B
|
0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B
|
||||||
0x0E003000u // TBX V0.8B, { V0.16B, V1.16B }, V0.8B
|
0x0E003000u, // TBX V0.8B, { V0.16B, V1.16B }, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
|
0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
|
||||||
0x0E005000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
|
0x0E005000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
|
0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
|
||||||
0x0E006000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
|
0x0E006000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -41,15 +41,15 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
0xD53B4200u, // MRS X0, NZCV
|
0xD53B4200u, // MRS X0, NZCV
|
||||||
0xD51B4200u // MSR NZCV, X0
|
0xD51B4200u, // MSR NZCV, X0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[Test, Pairwise]
|
[Test, Pairwise]
|
||||||
public void MrsMsr_Nzcv([ValueSource("_MrsMsr_Nzcv_")] uint opcodes,
|
public void MrsMsr_Nzcv([ValueSource(nameof(_MrsMsr_Nzcv_))] uint opcodes,
|
||||||
[Values(0u, 1u, 31u)] uint rt,
|
[Values(0u, 1u, 31u)] uint rt,
|
||||||
[ValueSource("_GenNzcv_")] ulong xt)
|
[ValueSource(nameof(_GenNzcv_))] ulong xt)
|
||||||
{
|
{
|
||||||
opcodes |= (rt & 31) << 0;
|
opcodes |= (rt & 31) << 0;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
@@ -14,70 +15,70 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
public static readonly PrecomputedMemoryThumbTestCase[] ImmTestCases =
|
public static readonly PrecomputedMemoryThumbTestCase[] ImmTestCases =
|
||||||
{
|
{
|
||||||
// STRB (imm8)
|
// STRB (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf80c, 0x1b2f, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf80c, 0x1b2f, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x000021ff, 0x000026e3, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x000021ff, 0x000026e3, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x0000222e, 0x000026e3, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x000023bd, 0x000027bb, 0x00002715, 0x000028f5, 0x0000233f, 0x0000213b, 0x00002eea, 0x0000282b, 0x000021e1, 0x0000264c, 0x000029e0, 0x00002ae7, 0x0000222e, 0x000026e3, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21fe, Value: 0xbbfe) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21fe, Value: 0xbbfe) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf80a, 0x2f81, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf80a, 0x2f81, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x0000266f, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
|
StartRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x0000266f, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x000026f0, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
|
FinalRegs = new uint[] { 0x0000223c, 0x00002db9, 0x00002900, 0x0000247c, 0x00002b0a, 0x0000266b, 0x000026df, 0x00002447, 0x000024bb, 0x00002687, 0x000026f0, 0x00002a80, 0x000025ff, 0x00002881, 0x00000001, 0xa00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x26f0, Value: 0x2600) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x26f0, Value: 0x2600) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf803, 0x6968, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf803, 0x6968, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002dac, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
|
StartRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002dac, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
|
||||||
FinalRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002d44, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
|
FinalRegs = new uint[] { 0x000026ed, 0x00002685, 0x00002cd1, 0x00002d44, 0x00002a23, 0x00002626, 0x00002ec9, 0x0000245c, 0x000024ef, 0x00002319, 0x000026ce, 0x0000214d, 0x00002401, 0x000028b4, 0x00000001, 0x300001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2dac, Value: 0x2dc9) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2dac, Value: 0x2dc9) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf804, 0x89ad, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf804, 0x89ad, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002413, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
|
StartRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002413, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002366, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
|
FinalRegs = new uint[] { 0x0000265d, 0x00002b9c, 0x00002360, 0x000029ec, 0x00002366, 0x00002d8e, 0x00002aad, 0x00002d29, 0x00002bca, 0x00002a44, 0x00002980, 0x00002710, 0x000022fa, 0x0000222e, 0x00000001, 0xc00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2412, Value: 0xca12) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2412, Value: 0xca12) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf80d, 0xa9fe, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf80d, 0xa9fe, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002d9d, 0x00000001, 0x900001f0 },
|
StartRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002d9d, 0x00000001, 0x900001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002c9f, 0x00000001, 0x900001f0 },
|
FinalRegs = new uint[] { 0x0000298d, 0x00002e6c, 0x00002986, 0x00002ebb, 0x0000213e, 0x00002e39, 0x0000246f, 0x00002b6c, 0x00002ee2, 0x0000259e, 0x0000250a, 0x000029f6, 0x000021e7, 0x00002c9f, 0x00000001, 0x900001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2d9c, Value: 0x0a9c) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2d9c, Value: 0x0a9c) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf80d, 0x3c46, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf80d, 0x3c46, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
|
StartRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
|
FinalRegs = new uint[] { 0x00002c6f, 0x000028cc, 0x000025f0, 0x000022cc, 0x00002de3, 0x0000243c, 0x000025fb, 0x00002e88, 0x00002985, 0x000023ee, 0x00002120, 0x00002d50, 0x0000270a, 0x00002bbd, 0x00000001, 0xa00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b76, Value: 0xcc76) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b76, Value: 0xcc76) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf801, 0x6c56, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf801, 0x6c56, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x00002d6e, 0x00002530, 0x00002e6d, 0x00002942, 0x00002985, 0x00002d64, 0x00002a73, 0x00002ac6, 0x00002955, 0x00002881, 0x0000221d, 0x00002cb0, 0x0000225f, 0x00002534, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x24da, Value: 0x2473) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x24da, Value: 0x2473) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf809, 0xcc76, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf809, 0xcc76, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x00002d50, 0x000025f2, 0x0000250a, 0x0000214c, 0x000023d1, 0x00002115, 0x00002c27, 0x00002540, 0x0000222b, 0x00002d03, 0x00002679, 0x00002b52, 0x00002eee, 0x00002b2a, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c8c, Value: 0xee8c) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c8c, Value: 0xee8c) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf808, 0x1c8d, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf808, 0x1c8d, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x00002844, 0x00002b78, 0x000028b0, 0x000026ff, 0x0000280b, 0x00002e0b, 0x00002de4, 0x00002b53, 0x00002ecd, 0x000021b5, 0x000026bc, 0x00002e9d, 0x00002d33, 0x000027f0, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2e40, Value: 0x2e78) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2e40, Value: 0x2e78) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf80b, 0xbc26, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf80b, 0xbc26, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002244, 0x000025ad, 0x00002434, 0x00002b06, 0x00002ebd, 0x0000292b, 0x00002431, 0x00002e12, 0x0000289b, 0x0000265a, 0x00002747, 0x00002bac, 0x00002dae, 0x00002582, 0x00000001, 0xf00001f0 },
|
StartRegs = new uint[] { 0x00002244, 0x000025ad, 0x00002434, 0x00002b06, 0x00002ebd, 0x0000292b, 0x00002431, 0x00002e12, 0x0000289b, 0x0000265a, 0x00002747, 0x00002bac, 0x00002dae, 0x00002582, 0x00000001, 0xf00001f0 },
|
||||||
@@ -85,35 +86,35 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b86, Value: 0x2bac) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b86, Value: 0x2bac) },
|
||||||
},
|
},
|
||||||
// STRB (imm12)
|
// STRB (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf887, 0x67c2, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf887, 0x67c2, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x700001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27c2, Value: 0x2700) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27c2, Value: 0x2700) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf883, 0x9fda, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf883, 0x9fda, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fda, Value: 0x2f00) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fda, Value: 0x2f00) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf889, 0xd200, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf889, 0xd200, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x400001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf88c, 0x1c5b, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf88c, 0x1c5b, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c5a, Value: 0x005a) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c5a, Value: 0x005a) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf887, 0x9fe2, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf887, 0x9fe2, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
@@ -121,70 +122,70 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fe2, Value: 0x2f00) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fe2, Value: 0x2f00) },
|
||||||
},
|
},
|
||||||
// STRH (imm8)
|
// STRH (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf826, 0x0b0a, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf826, 0x0b0a, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x00002620, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x00002620, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x0000262a, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x000025a2, 0x000024d5, 0x00002ca1, 0x0000238a, 0x0000279c, 0x0000244c, 0x0000262a, 0x00002c0e, 0x0000233e, 0x0000285f, 0x000021ab, 0x00002bd0, 0x0000281f, 0x00002be7, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2620, Value: 0x25a2) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2620, Value: 0x25a2) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf827, 0xcf61, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf827, 0xcf61, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x000029eb, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x000029eb, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x00002a4c, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x00002555, 0x0000238f, 0x00002829, 0x000028c8, 0x00002399, 0x00002aab, 0x00002d6f, 0x00002a4c, 0x000029e0, 0x00002d33, 0x0000292a, 0x00002b33, 0x00002e29, 0x00002ca4, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a4c, Value: 0x2e29) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a4c, Value: 0x2e29) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf821, 0x9b00, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf821, 0x9b00, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x000027ba, 0x00002514, 0x00002b07, 0x00002daf, 0x00002790, 0x0000274b, 0x00002379, 0x00002a98, 0x000024c8, 0x00002398, 0x000021ba, 0x00002959, 0x00002821, 0x00002d09, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2514, Value: 0x2398) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2514, Value: 0x2398) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf82c, 0xa927, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf82c, 0xa927, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x000029a1, 0x00002976, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x000029a1, 0x00002976, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x0000297a, 0x00002976, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x0000226a, 0x00002792, 0x00002870, 0x00002918, 0x00002757, 0x00002679, 0x00002546, 0x000027f5, 0x00002edc, 0x00002cd3, 0x0000274a, 0x00002562, 0x0000297a, 0x00002976, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29a0, Value: 0x4aa0), (Address: 0x29a2, Value: 0x2927) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29a0, Value: 0x4aa0), (Address: 0x29a2, Value: 0x2927) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf824, 0xcfe4, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf824, 0xcfe4, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002442, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002442, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002526, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x0000238b, 0x00002d22, 0x00002476, 0x000028ae, 0x00002526, 0x0000212b, 0x000026de, 0x00002a1a, 0x00002a02, 0x00002e47, 0x00002b2d, 0x00002427, 0x00002d1c, 0x000026d4, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2526, Value: 0x2d1c) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2526, Value: 0x2d1c) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf820, 0x1c3d, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf820, 0x1c3d, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x00002227, 0x00002b29, 0x0000232a, 0x0000214e, 0x000029ef, 0x00002522, 0x000029d3, 0x0000286c, 0x000029b2, 0x00002147, 0x00002c65, 0x00002891, 0x000029c2, 0x000028a5, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21ea, Value: 0x2b29) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x21ea, Value: 0x2b29) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf826, 0x1cdf, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf826, 0x1cdf, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x00002232, 0x000029a1, 0x00002938, 0x00002ae7, 0x000029a4, 0x00002366, 0x0000273a, 0x000023f6, 0x00002601, 0x00002919, 0x000028e3, 0x00002907, 0x000023c1, 0x00002138, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x265a, Value: 0xa15a), (Address: 0x265c, Value: 0x2629) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x265a, Value: 0xa15a), (Address: 0x265c, Value: 0x2629) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf82b, 0x3c66, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf82b, 0x3c66, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
|
StartRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
|
FinalRegs = new uint[] { 0x00002974, 0x00002372, 0x0000276c, 0x000021df, 0x00002272, 0x00002928, 0x00002c50, 0x0000290e, 0x00002319, 0x000021d1, 0x00002a82, 0x000027ff, 0x00002730, 0x000027b2, 0x00000001, 0x700001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2798, Value: 0xdf98), (Address: 0x279a, Value: 0x2721) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2798, Value: 0xdf98), (Address: 0x279a, Value: 0x2721) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf822, 0x3c06, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf822, 0x3c06, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
|
StartRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
|
||||||
FinalRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
|
FinalRegs = new uint[] { 0x000021b8, 0x00002357, 0x00002b00, 0x00002207, 0x00002648, 0x0000219c, 0x000021d2, 0x000023b0, 0x00002368, 0x00002a41, 0x000026ac, 0x00002a86, 0x00002879, 0x00002c1d, 0x00000001, 0x700001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2afa, Value: 0x2207) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2afa, Value: 0x2207) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf824, 0xac84, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf824, 0xac84, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002796, 0x000027c8, 0x0000241b, 0x0000214d, 0x0000220b, 0x00002587, 0x00002130, 0x00002910, 0x00002ac2, 0x00002e74, 0x000028f8, 0x000024bf, 0x0000263a, 0x00002625, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002796, 0x000027c8, 0x0000241b, 0x0000214d, 0x0000220b, 0x00002587, 0x00002130, 0x00002910, 0x00002ac2, 0x00002e74, 0x000028f8, 0x000024bf, 0x0000263a, 0x00002625, 0x00000001, 0x600001f0 },
|
||||||
@@ -192,35 +193,35 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2186, Value: 0xf886), (Address: 0x2188, Value: 0x2128) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2186, Value: 0xf886), (Address: 0x2188, Value: 0x2128) },
|
||||||
},
|
},
|
||||||
// STRH (imm12)
|
// STRH (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8a5, 0x59d4, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8a5, 0x59d4, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29d4, Value: 0x2000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29d4, Value: 0x2000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8ac, 0xc533, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8ac, 0xc533, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2532, Value: 0x0032), (Address: 0x2534, Value: 0x2520) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2532, Value: 0x0032), (Address: 0x2534, Value: 0x2520) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8a3, 0xb559, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8a3, 0xb559, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2558, Value: 0x0058), (Address: 0x255a, Value: 0x2520) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2558, Value: 0x0058), (Address: 0x255a, Value: 0x2520) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8a5, 0xdb3a, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8a5, 0xdb3a, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xb00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b3a, Value: 0x2000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2b3a, Value: 0x2000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8a9, 0x02cc, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8a9, 0x02cc, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xc00001f0 },
|
||||||
@@ -228,70 +229,70 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22cc, Value: 0x2000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22cc, Value: 0x2000) },
|
||||||
},
|
},
|
||||||
// STR (imm8)
|
// STR (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf846, 0x1fb4, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf846, 0x1fb4, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x0000222d, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
|
StartRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x0000222d, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x000022e1, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
|
FinalRegs = new uint[] { 0x00002b17, 0x0000272f, 0x00002483, 0x0000284c, 0x0000287f, 0x0000238f, 0x000022e1, 0x00002259, 0x0000249d, 0x00002e3f, 0x00002323, 0x00002729, 0x000025c1, 0x00002866, 0x00000001, 0x900001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22e0, Value: 0x2fe0), (Address: 0x22e2, Value: 0x0027), (Address: 0x22e4, Value: 0x2200) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x22e0, Value: 0x2fe0), (Address: 0x22e2, Value: 0x0027), (Address: 0x22e4, Value: 0x2200) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf844, 0x3f11, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf844, 0x3f11, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027bb, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
|
StartRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027bb, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
|
||||||
FinalRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027cc, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
|
FinalRegs = new uint[] { 0x000028e1, 0x00002d48, 0x000027d6, 0x000023ac, 0x000027cc, 0x000026cf, 0x000023c1, 0x00002633, 0x0000214b, 0x00002434, 0x0000239a, 0x000025c6, 0x00002148, 0x00002d1f, 0x00000001, 0x300001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27cc, Value: 0x23ac), (Address: 0x27ce, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x27cc, Value: 0x23ac), (Address: 0x27ce, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf847, 0x09c2, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf847, 0x09c2, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000211c, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000211c, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000205a, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x0000248b, 0x00002396, 0x000023c5, 0x00002be0, 0x0000237d, 0x00002191, 0x00002da0, 0x0000205a, 0x00002d24, 0x000021e6, 0x000024ff, 0x00002268, 0x00002968, 0x0000244d, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x211c, Value: 0x248b), (Address: 0x211e, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x211c, Value: 0x248b), (Address: 0x211e, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf84d, 0x7f23, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf84d, 0x7f23, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c33, 0x00000001, 0x200001f0 },
|
StartRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c33, 0x00000001, 0x200001f0 },
|
||||||
FinalRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c56, 0x00000001, 0x200001f0 },
|
FinalRegs = new uint[] { 0x000025b0, 0x0000260e, 0x00002343, 0x00002e36, 0x000024c5, 0x000029bc, 0x0000278e, 0x00002b63, 0x00002ce7, 0x000029af, 0x000023bf, 0x00002475, 0x00002197, 0x00002c56, 0x00000001, 0x200001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c56, Value: 0x2b63), (Address: 0x2c58, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2c56, Value: 0x2b63), (Address: 0x2c58, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf843, 0x9d24, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf843, 0x9d24, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025fb, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025fb, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025d7, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x00002ce4, 0x00002e0e, 0x000026d5, 0x000025d7, 0x00002b78, 0x0000215a, 0x00002af7, 0x0000259c, 0x00002645, 0x000027dc, 0x00002163, 0x000028f5, 0x000029df, 0x0000230b, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25d6, Value: 0xdcd6), (Address: 0x25d8, Value: 0x0027), (Address: 0x25da, Value: 0x2500) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25d6, Value: 0xdcd6), (Address: 0x25d8, Value: 0x0027), (Address: 0x25da, Value: 0x2500) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf849, 0xdc1a, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf849, 0xdc1a, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
|
StartRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
|
FinalRegs = new uint[] { 0x00002d98, 0x0000254a, 0x00002540, 0x00002324, 0x0000264e, 0x00002523, 0x0000271f, 0x00002875, 0x000023b3, 0x00002680, 0x00002223, 0x000022bf, 0x000025f4, 0x00002d81, 0x00000001, 0x700001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2666, Value: 0x2d81), (Address: 0x2668, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2666, Value: 0x2d81), (Address: 0x2668, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf849, 0x0cd1, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf849, 0x0cd1, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
|
StartRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
|
FinalRegs = new uint[] { 0x0000255a, 0x00002655, 0x00002276, 0x000022e4, 0x00002eef, 0x00002e99, 0x00002b55, 0x00002a40, 0x00002661, 0x00002dbd, 0x00002687, 0x000024e1, 0x000023ea, 0x00002b88, 0x00000001, 0xc00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2cec, Value: 0x255a), (Address: 0x2cee, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2cec, Value: 0x255a), (Address: 0x2cee, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf847, 0x7c96, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf847, 0x7c96, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
|
StartRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
|
||||||
FinalRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
|
FinalRegs = new uint[] { 0x000027f6, 0x0000222a, 0x000024e1, 0x00002a2d, 0x00002ee8, 0x000023f2, 0x000029de, 0x00002a53, 0x000029da, 0x00002d2c, 0x00002d6f, 0x000026b8, 0x00002777, 0x00002e3a, 0x00000001, 0xf00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29bc, Value: 0x53bc), (Address: 0x29be, Value: 0x002a), (Address: 0x29c0, Value: 0x2900) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29bc, Value: 0x53bc), (Address: 0x29be, Value: 0x002a), (Address: 0x29c0, Value: 0x2900) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf84d, 0x8cbd, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf84d, 0x8cbd, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x00002a58, 0x00002a59, 0x00002dfd, 0x00002ba8, 0x00002929, 0x00002146, 0x00002706, 0x000025f3, 0x000023d7, 0x0000221f, 0x000027ae, 0x00002a6e, 0x00002824, 0x00002357, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x229a, Value: 0x23d7), (Address: 0x229c, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x229a, Value: 0x23d7), (Address: 0x229c, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf846, 0xacaf, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf846, 0xacaf, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000284f, 0x00002def, 0x0000292f, 0x000021e8, 0x0000274e, 0x00002518, 0x00002538, 0x00002375, 0x00002d28, 0x0000229a, 0x0000255f, 0x00002eca, 0x00002e15, 0x000021aa, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x0000284f, 0x00002def, 0x0000292f, 0x000021e8, 0x0000274e, 0x00002518, 0x00002538, 0x00002375, 0x00002d28, 0x0000229a, 0x0000255f, 0x00002eca, 0x00002e15, 0x000021aa, 0x00000001, 0x100001f0 },
|
||||||
@@ -299,35 +300,35 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2488, Value: 0x5f88), (Address: 0x248a, Value: 0x0025), (Address: 0x248c, Value: 0x2400) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2488, Value: 0x5f88), (Address: 0x248a, Value: 0x0025), (Address: 0x248c, Value: 0x2400) },
|
||||||
},
|
},
|
||||||
// STR (imm12)
|
// STR (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8cc, 0x1a6e, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8cc, 0x1a6e, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a6e, Value: 0x2000), (Address: 0x2a70, Value: 0x0000) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2a6e, Value: 0x2000), (Address: 0x2a70, Value: 0x0000) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8c9, 0xcfc1, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8c9, 0xcfc1, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fc0, Value: 0x00c0), (Address: 0x2fc2, Value: 0x0020), (Address: 0x2fc4, Value: 0x2f00) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x2fc0, Value: 0x00c0), (Address: 0x2fc2, Value: 0x0020), (Address: 0x2fc4, Value: 0x2f00) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8c3, 0xb5dd, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8c3, 0xb5dd, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25dc, Value: 0x00dc), (Address: 0x25de, Value: 0x0020), (Address: 0x25e0, Value: 0x2500) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x25dc, Value: 0x00dc), (Address: 0x25de, Value: 0x0020), (Address: 0x25e0, Value: 0x2500) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8c0, 0x69e9, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8c0, 0x69e9, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xe00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29e8, Value: 0x00e8), (Address: 0x29ea, Value: 0x0020), (Address: 0x29ec, Value: 0x2900) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x29e8, Value: 0x00e8), (Address: 0x29ea, Value: 0x0020), (Address: 0x29ec, Value: 0x2900) },
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8cd, 0x028f, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8cd, 0x028f, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
||||||
@@ -335,185 +336,185 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x228e, Value: 0x008e), (Address: 0x2290, Value: 0x0020), (Address: 0x2292, Value: 0x2200) },
|
MemoryDelta = new (ulong Address, ushort Value)[] { (Address: 0x228e, Value: 0x008e), (Address: 0x2290, Value: 0x0020), (Address: 0x2292, Value: 0x2200) },
|
||||||
},
|
},
|
||||||
// LDRB (imm8)
|
// LDRB (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf816, 0x1c48, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf816, 0x1c48, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002cb8, 0x00002345, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002cb8, 0x00002345, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002cb8, 0x00000010, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x00002cb8, 0x00000010, 0x00002ebc, 0x00002db8, 0x000021d4, 0x000026e4, 0x00002458, 0x000029e3, 0x000028d2, 0x000027f4, 0x000023d6, 0x00002def, 0x0000285c, 0x00002d06, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf815, 0x2d6e, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf815, 0x2d6e, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000021e4, 0x00002425, 0x00002e42, 0x00002a58, 0x00002708, 0x00002965, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x000021e4, 0x00002425, 0x00002e42, 0x00002a58, 0x00002708, 0x00002965, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x000021e4, 0x00002425, 0x00000028, 0x00002a58, 0x00002708, 0x000028f7, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x000021e4, 0x00002425, 0x00000028, 0x00002a58, 0x00002708, 0x000028f7, 0x00002a1d, 0x00002ed5, 0x00002cc4, 0x000026e1, 0x00002b4b, 0x00002ade, 0x00002824, 0x00002975, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf818, 0x0d33, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf818, 0x0d33, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002492, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x0000297b, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x00002492, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x0000297b, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00000048, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x00002948, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x00000048, 0x0000214d, 0x00002827, 0x000021af, 0x0000215e, 0x000028d6, 0x000024ec, 0x00002984, 0x00002948, 0x000024b5, 0x000024ca, 0x0000298f, 0x00002339, 0x00002b7e, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf810, 0xbff3, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf810, 0xbff3, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002ea6, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x000022e7, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002ea6, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x000022e7, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002f99, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x0000002f, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x00002f99, 0x000024fa, 0x00002346, 0x00002748, 0x0000283f, 0x00002770, 0x000023e3, 0x000021aa, 0x0000214a, 0x00002d58, 0x00002159, 0x0000002f, 0x00002242, 0x00002728, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
// LDRB (imm12)
|
// LDRB (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf892, 0xcc8f, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf892, 0xcc8f, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002c, 0x00002000, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002c, 0x00002000, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf89a, 0x7fdc, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf89a, 0x7fdc, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000000dc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000000dc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x200001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf890, 0x5f9f, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf890, 0x5f9f, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002f, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002f, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf894, 0xdda1, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf894, 0xdda1, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002d, 0x00000001, 0x900001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000002d, 0x00000001, 0x900001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf890, 0xc281, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf890, 0xc281, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x100001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000022, 0x00002000, 0x00000001, 0x100001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000022, 0x00002000, 0x00000001, 0x100001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
// LDRH (imm8)
|
// LDRH (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf834, 0x89d8, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf834, 0x89d8, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000024a2, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x00002dff, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000024a2, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x00002dff, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000023ca, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x000024a2, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x00002a9e, 0x00002d84, 0x00002e9b, 0x00002e7f, 0x000023ca, 0x00002b7b, 0x00002e3b, 0x0000299a, 0x000024a2, 0x00002a9e, 0x000027b2, 0x00002a90, 0x00002883, 0x0000288d, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf833, 0x6be4, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf833, 0x6be4, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002a83, 0x00002293, 0x00002c7c, 0x00002bfe, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002a83, 0x00002293, 0x00002c7c, 0x00002bfe, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002b67, 0x00002293, 0x00002c7c, 0x0000842a, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x000028bd, 0x00002b0e, 0x00002bc1, 0x00002b67, 0x00002293, 0x00002c7c, 0x0000842a, 0x00002eb7, 0x0000299b, 0x000026e6, 0x0000219c, 0x00002d5e, 0x00002cd4, 0x000026cf, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf83d, 0x1bca, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf83d, 0x1bca, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000250e, 0x00002776, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002e97, 0x00000001, 0x200001f0 },
|
StartRegs = new uint[] { 0x0000250e, 0x00002776, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002e97, 0x00000001, 0x200001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000250e, 0x0000982e, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002f61, 0x00000001, 0x200001f0 },
|
FinalRegs = new uint[] { 0x0000250e, 0x0000982e, 0x000029e5, 0x0000276e, 0x00002c6b, 0x00002712, 0x00002a85, 0x00002d56, 0x000024c0, 0x00002d86, 0x0000254a, 0x00002549, 0x00002795, 0x00002f61, 0x00000001, 0x200001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
// LDRH (imm12)
|
// LDRH (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8b7, 0x92fc, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8b7, 0x92fc, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000022fc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000022fc, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8ba, 0xadd9, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8ba, 0xadd9, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000da2d, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x0000da2d, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xa00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8bb, 0x0bb0, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8bb, 0x0bb0, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002bb0, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x00002bb0, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8b8, 0xc3f8, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8b8, 0xc3f8, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x600001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000023f8, 0x00002000, 0x00000001, 0x600001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x000023f8, 0x00002000, 0x00000001, 0x600001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
// LDR (imm8)
|
// LDR (imm8)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf85b, 0x3fd1, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf85b, 0x3fd1, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x000021fa, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002735, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
|
StartRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x000021fa, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002735, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x28082806, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002806, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
|
FinalRegs = new uint[] { 0x00002a19, 0x00002e5b, 0x0000231b, 0x28082806, 0x00002e95, 0x00002bd5, 0x00002e9c, 0x00002dfa, 0x000021d8, 0x00002ce1, 0x00002318, 0x00002806, 0x0000247d, 0x00002436, 0x00000001, 0xf00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf854, 0xab9e, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf854, 0xab9e, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002ebb, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0x00002373, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
|
StartRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002ebb, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0x00002373, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
|
||||||
FinalRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002f59, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0xbe2ebc2e, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
|
FinalRegs = new uint[] { 0x0000214f, 0x00002578, 0x00002a98, 0x000021b0, 0x00002f59, 0x0000284a, 0x00002319, 0x00002581, 0x00002179, 0x00002594, 0xbe2ebc2e, 0x000028f4, 0x00002ec5, 0x00002e0a, 0x00000001, 0xb00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf852, 0x6d2d, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf852, 0x6d2d, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bde, 0x000022d9, 0x00002362, 0x00002d4b, 0x00002dab, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
|
StartRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bde, 0x000022d9, 0x00002362, 0x00002d4b, 0x00002dab, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bb1, 0x000022d9, 0x00002362, 0x00002d4b, 0xb42bb22b, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
|
FinalRegs = new uint[] { 0x00002e27, 0x00002676, 0x00002bb1, 0x000022d9, 0x00002362, 0x00002d4b, 0xb42bb22b, 0x000022b6, 0x0000229c, 0x00002507, 0x00002848, 0x0000225f, 0x00002ac2, 0x000023c3, 0x00000001, 0xf00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf850, 0x8da5, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf850, 0x8da5, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002559, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x00002124, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
|
StartRegs = new uint[] { 0x00002559, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x00002124, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
|
||||||
FinalRegs = new uint[] { 0x000024b4, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x24b624b4, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
|
FinalRegs = new uint[] { 0x000024b4, 0x0000285e, 0x000021de, 0x00002223, 0x000023ff, 0x00002e05, 0x00002bf3, 0x000024a5, 0x24b624b4, 0x00002768, 0x00002a14, 0x0000219e, 0x00002739, 0x00002e3c, 0x00000001, 0xd00001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf857, 0x19f6, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf857, 0x19f6, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x000027f5, 0x0000285e, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000024cf, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
|
StartRegs = new uint[] { 0x000027f5, 0x0000285e, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000024cf, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
|
||||||
FinalRegs = new uint[] { 0x000027f5, 0xd224d024, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000023d9, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
|
FinalRegs = new uint[] { 0x000027f5, 0xd224d024, 0x000025f6, 0x00002e22, 0x00002224, 0x00002870, 0x00002ecc, 0x000023d9, 0x00002711, 0x0000241b, 0x00002ddf, 0x00002545, 0x000028ca, 0x000023c5, 0x00000001, 0x400001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
// LDR (imm12)
|
// LDR (imm12)
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8d1, 0xc65e, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8d1, 0xc65e, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2660265e, 0x00002000, 0x00000001, 0x000001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2660265e, 0x00002000, 0x00000001, 0x000001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8db, 0xd09b, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8db, 0xd09b, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x800001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x9e209c20, 0x00000001, 0x800001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x9e209c20, 0x00000001, 0x800001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8d2, 0x6fde, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8d2, 0x6fde, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2fe02fde, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x2fe02fde, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x900001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
new PrecomputedMemoryThumbTestCase()
|
new()
|
||||||
{
|
{
|
||||||
Instructions = new ushort[] { 0xf8dc, 0x3de5, 0x4770, 0xe7fe },
|
Instructions = new ushort[] { 0xf8dc, 0x3de5, 0x4770, 0xe7fe },
|
||||||
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
StartRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0xe82de62d, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
FinalRegs = new uint[] { 0x00002000, 0x00002000, 0x00002000, 0xe82de62d, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00000001, 0x500001f0 },
|
||||||
MemoryDelta = new (ulong Address, ushort Value)[] {},
|
MemoryDelta = Array.Empty<(ulong Address, ushort Value)>(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -10,22 +10,24 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
internal class EnvironmentTests
|
internal class EnvironmentTests
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0052 // Remove unread private member
|
||||||
private static Translator _translator;
|
private static Translator _translator;
|
||||||
|
#pragma warning restore IDE0052
|
||||||
|
|
||||||
private void EnsureTranslator()
|
private static void EnsureTranslator()
|
||||||
{
|
{
|
||||||
// Create a translator, as one is needed to register the signal handler or emit methods.
|
// Create a translator, as one is needed to register the signal handler or emit methods.
|
||||||
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
|
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
|
||||||
private float GetDenormal()
|
private static float GetDenormal()
|
||||||
{
|
{
|
||||||
return BitConverter.Int32BitsToSingle(1);
|
return BitConverter.Int32BitsToSingle(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
|
||||||
private float GetZero()
|
private static float GetZero()
|
||||||
{
|
{
|
||||||
return BitConverter.Int32BitsToSingle(0);
|
return BitConverter.Int32BitsToSingle(0);
|
||||||
}
|
}
|
||||||
@@ -53,7 +55,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
if (test < 4f)
|
if (test < 4f)
|
||||||
{
|
{
|
||||||
throw new System.Exception("Sanity check.");
|
throw new Exception("Sanity check.");
|
||||||
}
|
}
|
||||||
|
|
||||||
isFz = GetDenormal() + GetZero() == 0f;
|
isFz = GetDenormal() + GetZero() == 0f;
|
||||||
@@ -62,7 +64,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
if (test >= 4f)
|
if (test >= 4f)
|
||||||
{
|
{
|
||||||
throw new System.Exception("Always throws.");
|
throw new Exception("Always throws.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@@ -6,5 +6,5 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
public uint[] StartRegs;
|
public uint[] StartRegs;
|
||||||
public uint[] FinalRegs;
|
public uint[] FinalRegs;
|
||||||
public (ulong Address, ushort Value)[] MemoryDelta;
|
public (ulong Address, ushort Value)[] MemoryDelta;
|
||||||
};
|
}
|
||||||
}
|
}
|
@@ -21,8 +21,7 @@ namespace Ryujinx.Tests.HLE
|
|||||||
[Test]
|
[Test]
|
||||||
public void StripUnicodeControlCodes_Passthrough()
|
public void StripUnicodeControlCodes_Passthrough()
|
||||||
{
|
{
|
||||||
string[] prompts = new string[]
|
string[] prompts = {
|
||||||
{
|
|
||||||
"Please name him.",
|
"Please name him.",
|
||||||
"Name her, too.",
|
"Name her, too.",
|
||||||
"Name your friend.",
|
"Name your friend.",
|
||||||
|
@@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Memory
|
|||||||
|
|
||||||
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
|
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
|
||||||
|
|
||||||
#pragma warning disable CS0067
|
#pragma warning disable CS0067 // The event is never used
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
public event Action<ulong, ulong> UnmapEvent;
|
||||||
#pragma warning restore CS0067
|
#pragma warning restore CS0067
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Tests.Memory
|
|||||||
{
|
{
|
||||||
private static Translator _translator;
|
private static Translator _translator;
|
||||||
|
|
||||||
private (MemoryBlock virt, MemoryBlock mirror, MemoryEhMeilleure exceptionHandler) GetVirtual(ulong asSize)
|
private static (MemoryBlock virt, MemoryBlock mirror, MemoryEhMeilleure exceptionHandler) GetVirtual(ulong asSize)
|
||||||
{
|
{
|
||||||
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Tests.Memory
|
|||||||
return (addressSpace, addressSpaceMirror, exceptionHandler);
|
return (addressSpace, addressSpaceMirror, exceptionHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CountThreads(ref PartialUnmapState state)
|
private static int CountThreads(ref PartialUnmapState state)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ namespace Ryujinx.Tests.Memory
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureTranslator()
|
private static void EnsureTranslator()
|
||||||
{
|
{
|
||||||
// Create a translator, as one is needed to register the signal handler or emit methods.
|
// Create a translator, as one is needed to register the signal handler or emit methods.
|
||||||
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
|
_translator ??= new Translator(new JitMemoryAllocator(), new MockMemoryManager(), true);
|
||||||
@@ -239,7 +239,7 @@ namespace Ryujinx.Tests.Memory
|
|||||||
var writeFunc = TestMethods.GenerateDebugNativeWriteLoop();
|
var writeFunc = TestMethods.GenerateDebugNativeWriteLoop();
|
||||||
IntPtr writePtr = mainMemory.GetPointer(vaSize - 0x1000, 4);
|
IntPtr writePtr = mainMemory.GetPointer(vaSize - 0x1000, 4);
|
||||||
|
|
||||||
Thread testThread = new Thread(() =>
|
Thread testThread = new(() =>
|
||||||
{
|
{
|
||||||
writeFunc(statePtr, writePtr);
|
writeFunc(statePtr, writePtr);
|
||||||
});
|
});
|
||||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Tests.Collections
|
|||||||
[Test]
|
[Test]
|
||||||
public void EnsureAddIntegrity()
|
public void EnsureAddIntegrity()
|
||||||
{
|
{
|
||||||
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
|
TreeDictionary<int, int> dictionary = new();
|
||||||
|
|
||||||
Assert.AreEqual(dictionary.Count, 0);
|
Assert.AreEqual(dictionary.Count, 0);
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Collections
|
|||||||
[Test]
|
[Test]
|
||||||
public void EnsureRemoveIntegrity()
|
public void EnsureRemoveIntegrity()
|
||||||
{
|
{
|
||||||
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
|
TreeDictionary<int, int> dictionary = new();
|
||||||
|
|
||||||
Assert.AreEqual(dictionary.Count, 0);
|
Assert.AreEqual(dictionary.Count, 0);
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Collections
|
|||||||
[Test]
|
[Test]
|
||||||
public void EnsureOverwriteIntegrity()
|
public void EnsureOverwriteIntegrity()
|
||||||
{
|
{
|
||||||
TreeDictionary<int, int> dictionary = new TreeDictionary<int, int>();
|
TreeDictionary<int, int> dictionary = new();
|
||||||
|
|
||||||
Assert.AreEqual(dictionary.Count, 0);
|
Assert.AreEqual(dictionary.Count, 0);
|
||||||
|
|
||||||
|
@@ -159,7 +159,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
|
|
||||||
NsoReader reader = new NsoReader();
|
NsoReader reader = new();
|
||||||
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
|
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
|
||||||
|
|
||||||
return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];
|
return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];
|
||||||
|
@@ -26,6 +26,7 @@ using System.Text;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
|
using TimeSpan = System.TimeSpan;
|
||||||
|
|
||||||
namespace Ryujinx.Ui.App.Common
|
namespace Ryujinx.Ui.App.Common
|
||||||
{
|
{
|
||||||
@@ -44,8 +45,8 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
private Language _desiredTitleLanguage;
|
private Language _desiredTitleLanguage;
|
||||||
private CancellationTokenSource _cancellationToken;
|
private CancellationTokenSource _cancellationToken;
|
||||||
|
|
||||||
private static readonly ApplicationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
private static readonly TitleUpdateMetadataJsonSerializerContext TitleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
public ApplicationLibrary(VirtualFileSystem virtualFileSystem)
|
public ApplicationLibrary(VirtualFileSystem virtualFileSystem)
|
||||||
{
|
{
|
||||||
@@ -459,27 +460,27 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + " MiB" : fileSize.ToString("0.##") + " GiB",
|
FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + " MiB" : fileSize.ToString("0.##") + " GiB",
|
||||||
FileSizeBytes = fileSize,
|
FileSizeBytes = fileSize,
|
||||||
Path = applicationPath,
|
Path = applicationPath,
|
||||||
ControlHolder = controlHolder
|
ControlHolder = controlHolder,
|
||||||
};
|
};
|
||||||
|
|
||||||
numApplicationsLoaded++;
|
numApplicationsLoaded++;
|
||||||
|
|
||||||
OnApplicationAdded(new ApplicationAddedEventArgs()
|
OnApplicationAdded(new ApplicationAddedEventArgs
|
||||||
{
|
{
|
||||||
AppData = data
|
AppData = data,
|
||||||
});
|
});
|
||||||
|
|
||||||
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
|
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
|
||||||
{
|
{
|
||||||
NumAppsFound = numApplicationsFound,
|
NumAppsFound = numApplicationsFound,
|
||||||
NumAppsLoaded = numApplicationsLoaded
|
NumAppsLoaded = numApplicationsLoaded,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
|
OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
|
||||||
{
|
{
|
||||||
NumAppsFound = numApplicationsFound,
|
NumAppsFound = numApplicationsFound,
|
||||||
NumAppsLoaded = numApplicationsLoaded
|
NumAppsLoaded = numApplicationsLoaded,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -508,7 +509,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
titleId = controlNca?.Header.TitleId.ToString("x16");
|
titleId = controlNca?.Header.TitleId.ToString("x16");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
|
public static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
|
||||||
{
|
{
|
||||||
string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui");
|
string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui");
|
||||||
string metadataFile = Path.Combine(metadataFolder, "metadata.json");
|
string metadataFile = Path.Combine(metadataFolder, "metadata.json");
|
||||||
@@ -521,12 +522,12 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
appMetadata = new ApplicationMetadata();
|
appMetadata = new ApplicationMetadata();
|
||||||
|
|
||||||
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata);
|
JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
appMetadata = JsonHelper.DeserializeFromFile(metadataFile, SerializerContext.ApplicationMetadata);
|
appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata);
|
||||||
}
|
}
|
||||||
catch (JsonException)
|
catch (JsonException)
|
||||||
{
|
{
|
||||||
@@ -539,7 +540,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
{
|
{
|
||||||
modifyFunction(appMetadata);
|
modifyFunction(appMetadata);
|
||||||
|
|
||||||
JsonHelper.SerializeToFile(metadataFile, appMetadata, SerializerContext.ApplicationMetadata);
|
JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return appMetadata;
|
return appMetadata;
|
||||||
@@ -713,7 +714,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
private static string ConvertSecondsToFormattedString(double seconds)
|
private static string ConvertSecondsToFormattedString(double seconds)
|
||||||
{
|
{
|
||||||
System.TimeSpan time = System.TimeSpan.FromSeconds(seconds);
|
TimeSpan time = TimeSpan.FromSeconds(seconds);
|
||||||
|
|
||||||
string timeString;
|
string timeString;
|
||||||
if (time.Days != 0)
|
if (time.Days != 0)
|
||||||
@@ -840,7 +841,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
|
|
||||||
Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
||||||
|
|
||||||
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
||||||
|
|
||||||
@@ -884,7 +885,7 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
|
|
||||||
Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
||||||
|
|
||||||
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
||||||
|
|
||||||
@@ -925,12 +926,12 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
|
|
||||||
if (File.Exists(titleUpdateMetadataPath))
|
if (File.Exists(titleUpdateMetadataPath))
|
||||||
{
|
{
|
||||||
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, TitleSerializerContext.TitleUpdateMetadata).Selected;
|
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
|
||||||
|
|
||||||
if (File.Exists(updatePath))
|
if (File.Exists(updatePath))
|
||||||
{
|
{
|
||||||
FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
|
FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
|
||||||
PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
|
PartitionFileSystem nsp = new(file.AsStorage());
|
||||||
|
|
||||||
return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
|
return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
|
||||||
}
|
}
|
||||||
@@ -941,4 +942,3 @@ namespace Ryujinx.Ui.App.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,6 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
Dummy,
|
Dummy,
|
||||||
OpenAl,
|
OpenAl,
|
||||||
SoundIo,
|
SoundIo,
|
||||||
SDL2
|
SDL2,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -4,6 +4,6 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
{
|
{
|
||||||
Success = 0,
|
Success = 0,
|
||||||
NotLoaded = 1,
|
NotLoaded = 1,
|
||||||
MigratedFromPreVulkan = 1 << 8
|
MigratedFromPreVulkan = 1 << 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -278,7 +278,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
EnableFsAccessLog = new ReactiveObject<bool>();
|
EnableFsAccessLog = new ReactiveObject<bool>();
|
||||||
FilteredClasses = new ReactiveObject<LogClass[]>();
|
FilteredClasses = new ReactiveObject<LogClass[]>();
|
||||||
EnableFileLog = new ReactiveObject<bool>();
|
EnableFileLog = new ReactiveObject<bool>();
|
||||||
EnableFileLog.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFileLog));
|
EnableFileLog.Event += static (sender, e) => LogValueChange(e, nameof(EnableFileLog));
|
||||||
GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
|
GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,27 +370,27 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
TimeZone = new ReactiveObject<string>();
|
TimeZone = new ReactiveObject<string>();
|
||||||
SystemTimeOffset = new ReactiveObject<long>();
|
SystemTimeOffset = new ReactiveObject<long>();
|
||||||
EnableDockedMode = new ReactiveObject<bool>();
|
EnableDockedMode = new ReactiveObject<bool>();
|
||||||
EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode));
|
EnableDockedMode.Event += static (sender, e) => LogValueChange(e, nameof(EnableDockedMode));
|
||||||
EnablePtc = new ReactiveObject<bool>();
|
EnablePtc = new ReactiveObject<bool>();
|
||||||
EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc));
|
EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
|
||||||
EnableInternetAccess = new ReactiveObject<bool>();
|
EnableInternetAccess = new ReactiveObject<bool>();
|
||||||
EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess));
|
EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess));
|
||||||
EnableFsIntegrityChecks = new ReactiveObject<bool>();
|
EnableFsIntegrityChecks = new ReactiveObject<bool>();
|
||||||
EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks));
|
EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks));
|
||||||
FsGlobalAccessLogMode = new ReactiveObject<int>();
|
FsGlobalAccessLogMode = new ReactiveObject<int>();
|
||||||
FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(FsGlobalAccessLogMode));
|
FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(e, nameof(FsGlobalAccessLogMode));
|
||||||
AudioBackend = new ReactiveObject<AudioBackend>();
|
AudioBackend = new ReactiveObject<AudioBackend>();
|
||||||
AudioBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend));
|
AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend));
|
||||||
MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
|
MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
|
||||||
MemoryManagerMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(MemoryManagerMode));
|
MemoryManagerMode.Event += static (sender, e) => LogValueChange(e, nameof(MemoryManagerMode));
|
||||||
ExpandRam = new ReactiveObject<bool>();
|
ExpandRam = new ReactiveObject<bool>();
|
||||||
ExpandRam.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam));
|
ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam));
|
||||||
IgnoreMissingServices = new ReactiveObject<bool>();
|
IgnoreMissingServices = new ReactiveObject<bool>();
|
||||||
IgnoreMissingServices.Event += static (sender, e) => LogValueChange(sender, e, nameof(IgnoreMissingServices));
|
IgnoreMissingServices.Event += static (sender, e) => LogValueChange(e, nameof(IgnoreMissingServices));
|
||||||
AudioVolume = new ReactiveObject<float>();
|
AudioVolume = new ReactiveObject<float>();
|
||||||
AudioVolume.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioVolume));
|
AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume));
|
||||||
UseHypervisor = new ReactiveObject<bool>();
|
UseHypervisor = new ReactiveObject<bool>();
|
||||||
UseHypervisor.Event += static (sender, e) => LogValueChange(sender, e, nameof(UseHypervisor));
|
UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,34 +513,34 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
public GraphicsSection()
|
public GraphicsSection()
|
||||||
{
|
{
|
||||||
BackendThreading = new ReactiveObject<BackendThreading>();
|
BackendThreading = new ReactiveObject<BackendThreading>();
|
||||||
BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading));
|
BackendThreading.Event += static (sender, e) => LogValueChange(e, nameof(BackendThreading));
|
||||||
ResScale = new ReactiveObject<int>();
|
ResScale = new ReactiveObject<int>();
|
||||||
ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale));
|
ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale));
|
||||||
ResScaleCustom = new ReactiveObject<float>();
|
ResScaleCustom = new ReactiveObject<float>();
|
||||||
ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom));
|
ResScaleCustom.Event += static (sender, e) => LogValueChange(e, nameof(ResScaleCustom));
|
||||||
MaxAnisotropy = new ReactiveObject<float>();
|
MaxAnisotropy = new ReactiveObject<float>();
|
||||||
MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy));
|
MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy));
|
||||||
AspectRatio = new ReactiveObject<AspectRatio>();
|
AspectRatio = new ReactiveObject<AspectRatio>();
|
||||||
AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio));
|
AspectRatio.Event += static (sender, e) => LogValueChange(e, nameof(AspectRatio));
|
||||||
ShadersDumpPath = new ReactiveObject<string>();
|
ShadersDumpPath = new ReactiveObject<string>();
|
||||||
EnableVsync = new ReactiveObject<bool>();
|
EnableVsync = new ReactiveObject<bool>();
|
||||||
EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync));
|
EnableVsync.Event += static (sender, e) => LogValueChange(e, nameof(EnableVsync));
|
||||||
EnableShaderCache = new ReactiveObject<bool>();
|
EnableShaderCache = new ReactiveObject<bool>();
|
||||||
EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache));
|
EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache));
|
||||||
EnableTextureRecompression = new ReactiveObject<bool>();
|
EnableTextureRecompression = new ReactiveObject<bool>();
|
||||||
EnableTextureRecompression.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableTextureRecompression));
|
EnableTextureRecompression.Event += static (sender, e) => LogValueChange(e, nameof(EnableTextureRecompression));
|
||||||
GraphicsBackend = new ReactiveObject<GraphicsBackend>();
|
GraphicsBackend = new ReactiveObject<GraphicsBackend>();
|
||||||
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend));
|
GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend));
|
||||||
PreferredGpu = new ReactiveObject<string>();
|
PreferredGpu = new ReactiveObject<string>();
|
||||||
PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu));
|
PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu));
|
||||||
EnableMacroHLE = new ReactiveObject<bool>();
|
EnableMacroHLE = new ReactiveObject<bool>();
|
||||||
EnableMacroHLE.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableMacroHLE));
|
EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
|
||||||
AntiAliasing = new ReactiveObject<AntiAliasing>();
|
AntiAliasing = new ReactiveObject<AntiAliasing>();
|
||||||
AntiAliasing.Event += static (sender, e) => LogValueChange(sender, e, nameof(AntiAliasing));
|
AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing));
|
||||||
ScalingFilter = new ReactiveObject<ScalingFilter>();
|
ScalingFilter = new ReactiveObject<ScalingFilter>();
|
||||||
ScalingFilter.Event += static (sender, e) => LogValueChange(sender, e, nameof(ScalingFilter));
|
ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter));
|
||||||
ScalingFilterLevel = new ReactiveObject<int>();
|
ScalingFilterLevel = new ReactiveObject<int>();
|
||||||
ScalingFilterLevel.Event += static (sender, e) => LogValueChange(sender, e, nameof(ScalingFilterLevel));
|
ScalingFilterLevel.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilterLevel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
|
|
||||||
public ConfigurationFileFormat ToFileFormat()
|
public ConfigurationFileFormat ToFileFormat()
|
||||||
{
|
{
|
||||||
ConfigurationFileFormat configurationFile = new ConfigurationFileFormat
|
ConfigurationFileFormat configurationFile = new()
|
||||||
{
|
{
|
||||||
Version = ConfigurationFileFormat.CurrentVersion,
|
Version = ConfigurationFileFormat.CurrentVersion,
|
||||||
BackendThreading = Graphics.BackendThreading,
|
BackendThreading = Graphics.BackendThreading,
|
||||||
@@ -688,12 +688,12 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
|
LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
|
||||||
FileExtColumn = Ui.GuiColumns.FileExtColumn,
|
FileExtColumn = Ui.GuiColumns.FileExtColumn,
|
||||||
FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
|
FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
|
||||||
PathColumn = Ui.GuiColumns.PathColumn
|
PathColumn = Ui.GuiColumns.PathColumn,
|
||||||
},
|
},
|
||||||
ColumnSort = new ColumnSort
|
ColumnSort = new ColumnSort
|
||||||
{
|
{
|
||||||
SortColumnId = Ui.ColumnSort.SortColumnId,
|
SortColumnId = Ui.ColumnSort.SortColumnId,
|
||||||
SortAscending = Ui.ColumnSort.SortAscending
|
SortAscending = Ui.ColumnSort.SortAscending,
|
||||||
},
|
},
|
||||||
GameDirs = Ui.GameDirs,
|
GameDirs = Ui.GameDirs,
|
||||||
ShownFileTypes = new ShownFileTypes
|
ShownFileTypes = new ShownFileTypes
|
||||||
@@ -732,7 +732,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
InputConfig = Hid.InputConfig,
|
InputConfig = Hid.InputConfig,
|
||||||
GraphicsBackend = Graphics.GraphicsBackend,
|
GraphicsBackend = Graphics.GraphicsBackend,
|
||||||
PreferredGpu = Graphics.PreferredGpu,
|
PreferredGpu = Graphics.PreferredGpu,
|
||||||
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId
|
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return configurationFile;
|
return configurationFile;
|
||||||
@@ -767,7 +767,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
EnableDiscordIntegration.Value = true;
|
EnableDiscordIntegration.Value = true;
|
||||||
CheckUpdatesOnStart.Value = true;
|
CheckUpdatesOnStart.Value = true;
|
||||||
ShowConfirmExit.Value = true;
|
ShowConfirmExit.Value = true;
|
||||||
HideCursor.Value = Ryujinx.Common.Configuration.HideCursorMode.Never;
|
HideCursor.Value = HideCursorMode.Never;
|
||||||
Graphics.EnableVsync.Value = true;
|
Graphics.EnableVsync.Value = true;
|
||||||
Graphics.EnableShaderCache.Value = true;
|
Graphics.EnableShaderCache.Value = true;
|
||||||
Graphics.EnableTextureRecompression.Value = false;
|
Graphics.EnableTextureRecompression.Value = false;
|
||||||
@@ -833,7 +833,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ResScaleUp = Key.Unbound,
|
ResScaleUp = Key.Unbound,
|
||||||
ResScaleDown = Key.Unbound,
|
ResScaleDown = Key.Unbound,
|
||||||
VolumeUp = Key.Unbound,
|
VolumeUp = Key.Unbound,
|
||||||
VolumeDown = Key.Unbound
|
VolumeDown = Key.Unbound,
|
||||||
};
|
};
|
||||||
Hid.InputConfig.Value = new List<InputConfig>
|
Hid.InputConfig.Value = new List<InputConfig>
|
||||||
{
|
{
|
||||||
@@ -854,9 +854,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ButtonL = Key.E,
|
ButtonL = Key.E,
|
||||||
ButtonZl = Key.Q,
|
ButtonZl = Key.Q,
|
||||||
ButtonSl = Key.Unbound,
|
ButtonSl = Key.Unbound,
|
||||||
ButtonSr = Key.Unbound
|
ButtonSr = Key.Unbound,
|
||||||
},
|
},
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
{
|
{
|
||||||
StickUp = Key.W,
|
StickUp = Key.W,
|
||||||
@@ -865,7 +864,6 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
StickRight = Key.D,
|
StickRight = Key.D,
|
||||||
StickButton = Key.F,
|
StickButton = Key.F,
|
||||||
},
|
},
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||||
{
|
{
|
||||||
ButtonA = Key.Z,
|
ButtonA = Key.Z,
|
||||||
@@ -876,9 +874,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ButtonR = Key.U,
|
ButtonR = Key.U,
|
||||||
ButtonZr = Key.O,
|
ButtonZr = Key.O,
|
||||||
ButtonSl = Key.Unbound,
|
ButtonSl = Key.Unbound,
|
||||||
ButtonSr = Key.Unbound
|
ButtonSr = Key.Unbound,
|
||||||
},
|
},
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
{
|
{
|
||||||
StickUp = Key.I,
|
StickUp = Key.I,
|
||||||
@@ -886,8 +883,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
StickLeft = Key.J,
|
StickLeft = Key.J,
|
||||||
StickRight = Key.L,
|
StickRight = Key.L,
|
||||||
StickButton = Key.H,
|
StickButton = Key.H,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -958,12 +955,12 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
configurationFileFormat.ColumnSort = new ColumnSort
|
configurationFileFormat.ColumnSort = new ColumnSort
|
||||||
{
|
{
|
||||||
SortColumnId = 0,
|
SortColumnId = 0,
|
||||||
SortAscending = false
|
SortAscending = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||||
{
|
{
|
||||||
ToggleVsync = Key.F1
|
ToggleVsync = Key.F1,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1074,9 +1071,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ButtonL = Key.E,
|
ButtonL = Key.E,
|
||||||
ButtonZl = Key.Q,
|
ButtonZl = Key.Q,
|
||||||
ButtonSl = Key.Unbound,
|
ButtonSl = Key.Unbound,
|
||||||
ButtonSr = Key.Unbound
|
ButtonSr = Key.Unbound,
|
||||||
},
|
},
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
{
|
{
|
||||||
StickUp = Key.W,
|
StickUp = Key.W,
|
||||||
@@ -1085,7 +1081,6 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
StickRight = Key.D,
|
StickRight = Key.D,
|
||||||
StickButton = Key.F,
|
StickButton = Key.F,
|
||||||
},
|
},
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||||
{
|
{
|
||||||
ButtonA = Key.Z,
|
ButtonA = Key.Z,
|
||||||
@@ -1096,9 +1091,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ButtonR = Key.U,
|
ButtonR = Key.U,
|
||||||
ButtonZr = Key.O,
|
ButtonZr = Key.O,
|
||||||
ButtonSl = Key.Unbound,
|
ButtonSl = Key.Unbound,
|
||||||
ButtonSr = Key.Unbound
|
ButtonSr = Key.Unbound,
|
||||||
},
|
},
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
{
|
{
|
||||||
StickUp = Key.I,
|
StickUp = Key.I,
|
||||||
@@ -1106,8 +1100,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
StickLeft = Key.J,
|
StickLeft = Key.J,
|
||||||
StickRight = Key.L,
|
StickRight = Key.L,
|
||||||
StickButton = Key.H,
|
StickButton = Key.H,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1145,7 +1139,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||||
{
|
{
|
||||||
ToggleVsync = Key.F1,
|
ToggleVsync = Key.F1,
|
||||||
Screenshot = Key.F8
|
Screenshot = Key.F8,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1159,7 +1153,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
{
|
{
|
||||||
ToggleVsync = Key.F1,
|
ToggleVsync = Key.F1,
|
||||||
Screenshot = Key.F8,
|
Screenshot = Key.F8,
|
||||||
ShowUi = Key.F4
|
ShowUi = Key.F4,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1177,7 +1171,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
{
|
{
|
||||||
EnableRumble = false,
|
EnableRumble = false,
|
||||||
StrongRumble = 1f,
|
StrongRumble = 1f,
|
||||||
WeakRumble = 1f
|
WeakRumble = 1f,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1203,7 +1197,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||||
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
||||||
Pause = Key.F5
|
Pause = Key.F5,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1219,7 +1213,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||||
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||||
ToggleMute = Key.F2
|
ToggleMute = Key.F2,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileFormat.AudioVolume = 1;
|
configurationFileFormat.AudioVolume = 1;
|
||||||
@@ -1295,7 +1289,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
||||||
ResScaleUp = Key.Unbound,
|
ResScaleUp = Key.Unbound,
|
||||||
ResScaleDown = Key.Unbound
|
ResScaleDown = Key.Unbound,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1326,7 +1320,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
||||||
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
||||||
VolumeUp = Key.Unbound,
|
VolumeUp = Key.Unbound,
|
||||||
VolumeDown = Key.Unbound
|
VolumeDown = Key.Unbound,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1366,7 +1360,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
XCI = true,
|
XCI = true,
|
||||||
NCA = true,
|
NCA = true,
|
||||||
NRO = true,
|
NRO = true,
|
||||||
NSO = true
|
NSO = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
@@ -1499,7 +1493,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LogValueChange<T>(object sender, ReactiveEventArgs<T> eventArgs, string valueName)
|
private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName)
|
||||||
{
|
{
|
||||||
Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
|
Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,6 @@ namespace Ryujinx.Ui.Common.Configuration.System
|
|||||||
LatinAmericanSpanish,
|
LatinAmericanSpanish,
|
||||||
SimplifiedChinese,
|
SimplifiedChinese,
|
||||||
TraditionalChinese,
|
TraditionalChinese,
|
||||||
BrazilianPortuguese
|
BrazilianPortuguese,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,6 @@ namespace Ryujinx.Ui.Common.Configuration.System
|
|||||||
Australia,
|
Australia,
|
||||||
China,
|
China,
|
||||||
Korea,
|
Korea,
|
||||||
Taiwan
|
Taiwan,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,19 +19,19 @@ namespace Ryujinx.Ui.Common
|
|||||||
Assets = new Assets
|
Assets = new Assets
|
||||||
{
|
{
|
||||||
LargeImageKey = "ryujinx",
|
LargeImageKey = "ryujinx",
|
||||||
LargeImageText = Description
|
LargeImageText = Description,
|
||||||
},
|
},
|
||||||
Details = "Main Menu",
|
Details = "Main Menu",
|
||||||
State = "Idling",
|
State = "Idling",
|
||||||
Timestamps = Timestamps.Now,
|
Timestamps = Timestamps.Now,
|
||||||
Buttons = new Button[]
|
Buttons = new[]
|
||||||
{
|
{
|
||||||
new Button()
|
new Button
|
||||||
{
|
{
|
||||||
Label = "Website",
|
Label = "Website",
|
||||||
Url = "https://ryujinx.org/"
|
Url = "https://ryujinx.org/",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
||||||
@@ -74,14 +74,14 @@ namespace Ryujinx.Ui.Common
|
|||||||
Details = $"Playing {titleName}",
|
Details = $"Playing {titleName}",
|
||||||
State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
|
State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
|
||||||
Timestamps = Timestamps.Now,
|
Timestamps = Timestamps.Now,
|
||||||
Buttons = new Button[]
|
Buttons = new[]
|
||||||
{
|
{
|
||||||
new Button()
|
new Button
|
||||||
{
|
{
|
||||||
Label = "Website",
|
Label = "Website",
|
||||||
Url = "https://ryujinx.org/"
|
Url = "https://ryujinx.org/",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ namespace Ryujinx.Ui.Common
|
|||||||
FileTypes.NCA => config.NCA.Value,
|
FileTypes.NCA => config.NCA.Value,
|
||||||
FileTypes.NRO => config.NRO.Value,
|
FileTypes.NRO => config.NRO.Value,
|
||||||
FileTypes.NSO => config.NSO.Value,
|
FileTypes.NSO => config.NSO.Value,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,8 +49,8 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
StartInfo =
|
StartInfo =
|
||||||
{
|
{
|
||||||
FileName = PkExecPath,
|
FileName = PkExecPath,
|
||||||
ArgumentList = { "sh", "-c", command }
|
ArgumentList = { "sh", "-c", command },
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
process.Start();
|
process.Start();
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ui.Common.Helper
|
namespace Ryujinx.Ui.Common.Helper
|
||||||
{
|
{
|
||||||
@@ -12,44 +10,109 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
|
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
|
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
|
||||||
private static unsafe partial IntPtr sel_getUid(string name);
|
private static partial IntPtr sel_getUid(string name);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
|
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
|
||||||
public static partial IntPtr objc_getClass(string name);
|
private static partial IntPtr objc_getClass(string name);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime)]
|
[LibraryImport(ObjCRuntime)]
|
||||||
public static partial void objc_msgSend(IntPtr receiver, Selector selector);
|
private static partial void objc_msgSend(IntPtr receiver, Selector selector);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime)]
|
[LibraryImport(ObjCRuntime)]
|
||||||
public static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
|
private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime)]
|
[LibraryImport(ObjCRuntime)]
|
||||||
public static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
|
private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime)]
|
[LibraryImport(ObjCRuntime)]
|
||||||
public static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
|
private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime)]
|
[LibraryImport(ObjCRuntime)]
|
||||||
public static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
|
private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
||||||
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
|
private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
||||||
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
|
private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
|
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
|
||||||
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
|
private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
|
||||||
|
|
||||||
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
|
private static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
|
||||||
|
|
||||||
public struct Selector
|
public readonly struct Object
|
||||||
|
{
|
||||||
|
public readonly IntPtr ObjPtr;
|
||||||
|
|
||||||
|
private Object(IntPtr pointer)
|
||||||
|
{
|
||||||
|
ObjPtr = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object(string name)
|
||||||
|
{
|
||||||
|
ObjPtr = objc_getClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(Selector selector)
|
||||||
|
{
|
||||||
|
objc_msgSend(ObjPtr, selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(Selector selector, byte value)
|
||||||
|
{
|
||||||
|
objc_msgSend(ObjPtr, selector, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(Selector selector, Object obj)
|
||||||
|
{
|
||||||
|
objc_msgSend(ObjPtr, selector, obj.ObjPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(Selector selector, NSRect point)
|
||||||
|
{
|
||||||
|
objc_msgSend(ObjPtr, selector, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(Selector selector, double value)
|
||||||
|
{
|
||||||
|
objc_msgSend(ObjPtr, selector, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object GetFromMessage(Selector selector)
|
||||||
|
{
|
||||||
|
return new Object(IntPtr_objc_msgSend(ObjPtr, selector));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object GetFromMessage(Selector selector, Object obj)
|
||||||
|
{
|
||||||
|
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, obj.ObjPtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object GetFromMessage(Selector selector, NSString nsString)
|
||||||
|
{
|
||||||
|
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, nsString.StrPtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object GetFromMessage(Selector selector, string param)
|
||||||
|
{
|
||||||
|
return new Object(IntPtr_objc_msgSend(ObjPtr, selector, param));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetBoolFromMessage(Selector selector, Object obj)
|
||||||
|
{
|
||||||
|
return bool_objc_msgSend(ObjPtr, selector, obj.ObjPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct Selector
|
||||||
{
|
{
|
||||||
public readonly IntPtr SelPtr;
|
public readonly IntPtr SelPtr;
|
||||||
|
|
||||||
public unsafe Selector(string name)
|
private Selector(string name)
|
||||||
{
|
{
|
||||||
SelPtr = sel_getUid(name);
|
SelPtr = sel_getUid(name);
|
||||||
}
|
}
|
||||||
@@ -57,7 +120,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
public static implicit operator Selector(string value) => new(value);
|
public static implicit operator Selector(string value) => new(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct NSString
|
public readonly struct NSString
|
||||||
{
|
{
|
||||||
public readonly IntPtr StrPtr;
|
public readonly IntPtr StrPtr;
|
||||||
|
|
||||||
|
@@ -9,13 +9,13 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
public static partial class OpenHelper
|
public static partial class OpenHelper
|
||||||
{
|
{
|
||||||
[LibraryImport("shell32.dll", SetLastError = true)]
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
||||||
public static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
|
private static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
|
||||||
|
|
||||||
[LibraryImport("shell32.dll", SetLastError = true)]
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
||||||
public static partial void ILFree(IntPtr pidlList);
|
private static partial void ILFree(IntPtr pidlList);
|
||||||
|
|
||||||
[LibraryImport("shell32.dll", SetLastError = true)]
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
||||||
public static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath);
|
private static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath);
|
||||||
|
|
||||||
public static void OpenFolder(string path)
|
public static void OpenFolder(string path)
|
||||||
{
|
{
|
||||||
@@ -25,7 +25,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
{
|
{
|
||||||
FileName = path,
|
FileName = path,
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = "open"
|
Verb = "open",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -56,16 +56,16 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
else if (OperatingSystem.IsMacOS())
|
else if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
ObjectiveC.NSString nsStringPath = new(path);
|
ObjectiveC.NSString nsStringPath = new(path);
|
||||||
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
|
ObjectiveC.Object nsUrl = new("NSURL");
|
||||||
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "fileURLWithPath:", nsStringPath);
|
var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
|
||||||
|
|
||||||
IntPtr nsArray = ObjectiveC.objc_getClass("NSArray");
|
ObjectiveC.Object nsArray = new("NSArray");
|
||||||
IntPtr urlArray = ObjectiveC.IntPtr_objc_msgSend(nsArray, "arrayWithObject:", urlPtr);
|
ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
|
||||||
|
|
||||||
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
|
ObjectiveC.Object nsWorkspace = new("NSWorkspace");
|
||||||
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
|
ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
|
||||||
|
|
||||||
ObjectiveC.objc_msgSend(sharedWorkspace, "activateFileViewerSelectingURLs:", urlArray);
|
sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux())
|
else if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
@@ -95,13 +95,13 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
else if (OperatingSystem.IsMacOS())
|
else if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
ObjectiveC.NSString nsStringPath = new(url);
|
ObjectiveC.NSString nsStringPath = new(url);
|
||||||
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
|
ObjectiveC.Object nsUrl = new("NSURL");
|
||||||
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "URLWithString:", nsStringPath);
|
var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
|
||||||
|
|
||||||
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
|
ObjectiveC.Object nsWorkspace = new("NSWorkspace");
|
||||||
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
|
ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
|
||||||
|
|
||||||
ObjectiveC.bool_objc_msgSend(sharedWorkspace, "openURL:", urlPtr);
|
sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -20,13 +20,11 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
error = UserError.NoFirmware;
|
error = UserError.NoFirmware;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion)
|
public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion)
|
||||||
{
|
{
|
||||||
@@ -107,12 +105,10 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
|
|
||||||
return IsFirmwareValid(contentManager, out error);
|
return IsFirmwareValid(contentManager, out error);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
error = UserError.ApplicationNotFound;
|
error = UserError.ApplicationNotFound;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@@ -29,29 +29,39 @@ namespace Ryujinx.Ui.Common.Models.Amiibo
|
|||||||
[JsonPropertyName("gamesSwitch")]
|
[JsonPropertyName("gamesSwitch")]
|
||||||
public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
|
public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public readonly override string ToString()
|
||||||
{
|
{
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetId()
|
public readonly string GetId()
|
||||||
{
|
{
|
||||||
return Head + Tail;
|
return Head + Tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(AmiiboApi other)
|
public readonly bool Equals(AmiiboApi other)
|
||||||
{
|
{
|
||||||
return Head + Tail == other.Head + other.Tail;
|
return Head + Tail == other.Head + other.Tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public readonly override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
return obj is AmiiboApi other && Equals(other);
|
return obj is AmiiboApi other && Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public readonly override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(Head, Tail);
|
return HashCode.Combine(Head, Tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(AmiiboApi left, AmiiboApi right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(AmiiboApi left, AmiiboApi right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -34,6 +34,6 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An unknown error.
|
/// An unknown error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Unknown = 0xDEAD
|
Unknown = 0xDEAD,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -874,7 +874,7 @@ namespace Ryujinx.Ui
|
|||||||
DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
|
DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
|
||||||
_emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString());
|
_emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString());
|
||||||
|
|
||||||
_applicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata =>
|
ApplicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata =>
|
||||||
{
|
{
|
||||||
appMetadata.LastPlayed = DateTime.UtcNow;
|
appMetadata.LastPlayed = DateTime.UtcNow;
|
||||||
});
|
});
|
||||||
@@ -1017,7 +1017,7 @@ namespace Ryujinx.Ui
|
|||||||
{
|
{
|
||||||
if (_gameLoaded)
|
if (_gameLoaded)
|
||||||
{
|
{
|
||||||
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
|
ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
|
||||||
{
|
{
|
||||||
if (appMetadata.LastPlayed.HasValue)
|
if (appMetadata.LastPlayed.HasValue)
|
||||||
{
|
{
|
||||||
@@ -1156,7 +1156,7 @@ namespace Ryujinx.Ui
|
|||||||
|
|
||||||
_tableStore.SetValue(treeIter, 0, newToggleValue);
|
_tableStore.SetValue(treeIter, 0, newToggleValue);
|
||||||
|
|
||||||
_applicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
|
ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
|
||||||
{
|
{
|
||||||
appMetadata.Favorite = newToggleValue;
|
appMetadata.Favorite = newToggleValue;
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user