Compare commits

..

17 Commits

Author SHA1 Message Date
TSRBerry
a5a9b9bc8b GUI: Small Updater refactor & Set correct permissions on Linux when extracting files (#4315)
* ava: Refactor Updater.cs

Fix typos
Remove unused usings
Rename variables to follow naming scheme

* ava: Set file permissions when extracting update files

* gtk: Apply the same refactor to Updater.cs

* updater: Replace assert with if statement

* updater: Remove await usings again
2023-02-15 22:36:35 +00:00
Mary
17078ad929 vulkan: Respect VK_KHR_portability_subset vertex stride alignment (#4419)
* vulkan: Respect VK_KHR_portability_subset vertex stride alignment

We were hardcoding alignment to 4, but by specs it can be any values that
is a power of 2.

This also enable VK_KHR_portability_subset if present as per specs
requirements.

* address gdkchan's comment

* Make NeedsVertexBufferAlignment internal
2023-02-15 08:41:48 +00:00
Mary
32450d45de vulkan: Clean up MemoryAllocator (#4418)
This started as an attempt to remove vkGetPhysicalDeviceMemoryProperties
in FindSuitableMemoryTypeIndex (As this could have some overhead and
shouldn't change at runtime) and turned in a little bigger cleanup.
2023-02-15 07:50:26 +01:00
Ac_K
ed7a0474c6 Infra: Issues template cleanup (#4421)
* Infra: Issues template cleanup

* applied
2023-02-14 15:58:57 +01:00
Mary
fe9c49949a vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level (#4408)
* vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level

This ensure we don't end up trying to initialize with anything currently incompatible.

* Address riperiperi's comment
2023-02-13 22:04:55 +00:00
Mary
052b23c83c vulkan: Do not call vkCmdSetViewport when viewportCount is 0 (#4406)
This fix validation error "VUID-vkCmdSetViewport-viewportCount-arraylength".
2023-02-13 20:32:20 +00:00
riperiperi
e4f68592c3 Fix partial updates for textures. (#4401)
I was forcing some types of texture to partially update when investigating performance with games that stream in data, and noticed that partially loading texture data was really broken on both backends.

Fixes Vulkan texture set by getting the correct expected size for the texture. Fixes partial upload on both backends for both Texture 2D Array and Cubemap using the wrong offset and uploading to the first layer/level for a handle. 3D might also be affected.

This might fix textures randomly having incorrect data in games that render to it - jumbled in the case of OpenGL, and outdated/black in the case of Vulkan. This case typically happens in UE4 games.
2023-02-12 10:30:26 +01:00
Logan Stromberg
1dcd44b94f Treat NpadIdType < 0 as invalid. Filter invalid SupportedPlayers inside IHidServer.SetSupportedNpadIdType(). (#4377)
Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2023-02-10 12:37:20 -03:00
gdkchan
61b1ce252f Allow partially mapped textures with unmapped start (#4394) 2023-02-10 11:47:59 -03:00
gdkchan
5f38086f94 Fix SPIR-V when all inputs/outputs are indexed (#4389) 2023-02-09 04:48:25 +01:00
Isaac Marovitz
7bae440d3a ObjectiveC Helper Class (#4286)
* `NativeMacOS` Helper Class

* Corrections

* Make CFString IDisposable

* Fix `openURL:`

* `dealloc` metal layer

* Remove releases

* Use NSString

* Update Ryujinx.Ui.Common/Helper/NativeMacOS.cs

Co-authored-by: merry <git@mary.rs>

* Programatically select updates in Finder

* Address feedback

* Feedback

* Ptr

* Fix whoopsie

* Ack suggestions

* Update Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* GDK Suggestions

---------

Co-authored-by: merry <git@mary.rs>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-02-09 04:08:15 +01:00
riperiperi
f1943fd0b6 Log shader compile errors with Warning level (#2617)
* Log shader compile errors with Warning level

These are infrequent enough that I think it's worth dumping any errors into the log. They also keep causing graphical glitches, and the only indication that anything went wrong is a debug log that is never enabled.

* Add maximum length for shader log
2023-02-09 03:50:18 +01:00
TSRBerry
ec8d4f3af5 Replace unicorn bindings with Nuget package (#4378)
* Replace unicorn bindings with Nuget package

* Use nameof for ValueSource args

* Remove redundant code from test projects

* Fix wrong values for EmuStart()

Add notes to address this later again

* Improve formatting

* Fix formatting/alignment issues
2023-02-09 02:24:32 +01:00
riperiperi
b3f0978869 Vulkan: Flush command buffers for queries less aggressively (#4387)
The AutoFlushCounter would flush command buffers on any attachment change (write mask or bindings change) if there was a pending query. This is to get query results as soon as possible for draw skips, but it's assuming that a full occlusion query _pass_ happened, that we want to flush it's data before getting onto draws, rather than the queries being randomly interspersed throughout a pass that also draws.

Xenoblade 2 repeatedly switches between performing a samples passed query and outputting to a render target on each draw, and flips the write mask to do so. Flushing the command buffer every 2 draws isn't ideal, so it's best that we only do this if the pattern matches the large block style of occlusion query.

This change makes this flush only happen after a few consecutive query reports. "Consecutive" is interrupted by attachment changes or command buffer flush.

This doesn't really solve the issue where it resets more queries than it uses, it just stops the game doing it as often. I'm not sure of the best way to do that. The cost of resetting could probably be reduced by using query pools with more than one element and resetting in bulk.
2023-02-09 02:03:41 +01:00
Ac_K
f614d2c435 bug_report.yml hotfix 2023-02-09 02:02:00 +01:00
Ac_K
40c9416097 Misc: Update issues form (#4383) 2023-02-09 00:52:43 +00:00
dependabot[bot]
618c8edc79 nuget: bump System.IdentityModel.Tokens.Jwt from 6.26.0 to 6.26.1 (#4384)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.26.0 to 6.26.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.26.0...v6.26.1)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-08 22:51:07 +01:00
93 changed files with 2887 additions and 4124 deletions

View File

@@ -1,31 +1,27 @@
name: Bug Report
description: File a bug report
title: "[Bug]"
labels: bug
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: issue
attributes:
label: Description of Issue
label: Description of the issue
description: What's the issue you encountered?
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction Steps
label: Reproduction steps
description: How can the issue be reproduced?
placeholder: Describe each step as precisely as possible
validations:
required: true
- type: textarea
id: log
attributes:
label: Log File
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
validations:
@@ -34,36 +30,51 @@ body:
id: os
attributes:
label: OS
placeholder: "Example: Windows 10"
placeholder: "e.g. Windows 10"
validations:
required: true
- type: input
id: ryujinx-version
attributes:
label: Ryujinx version
placeholder: |
- *(e.g. 1.0.470)*
placeholder: "e.g. 1.0.470"
validations:
required: true
- type: input
id: game-version
attributes:
label: Game version
placeholder: |
- *(e.g. 1.1.1)*
placeholder: "e.g. 1.1.1"
validations:
required: false
- type: input
id: cpu
attributes:
label: CPU
placeholder: "e.g. i7-6700"
validations:
required: false
- type: input
id: gpu
attributes:
label: GPU
placeholder: "e.g. NVIDIA RTX 2070"
validations:
required: false
- type: input
id: ram
attributes:
label: RAM
placeholder: "e.g. 16GB"
validations:
required: false
- type: textarea
id: environment
id: mods
attributes:
label: Environment?
value: |
- ##### CPU: *(e.g. i7-6700)*
- ##### GPU: *(e.g. NVIDIA RTX 2070)*
- ##### RAM: *(e.g. 16GB)*
- Applied Mods: [ Yes (Which ones) / No ]
label: List of applied mods
placeholder: You can list applied mods here.
validations:
required: true
required: false
- type: textarea
id: additional-context
attributes:

View File

@@ -1,13 +1,7 @@
name: Feature Request
description: Suggest a new feature for Ryujinx.
title: "[Feature Request]"
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the feature you are requesting.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: overview
attributes:
@@ -18,14 +12,14 @@ body:
- type: textarea
id: details
attributes:
label: Smaller Details
label: Smaller details
description: These may include specific methods of implementation etc.
validations:
required: true
- type: textarea
id: request
attributes:
label: Nature of Request
label: Nature of request
validations:
required: true
- type: textarea

View File

@@ -1,13 +1,8 @@
name: Missing CPU Instruction
description: CPU Instruction is missing in Ryujinx.
title: "[CPU]"
labels: [cpu, not-implemented]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search for existing missing CPU instruction
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: instruction
attributes:

View File

@@ -1,17 +1,11 @@
name: Missing Service Call
description: Service call is missing in Ryujinx.
labels: not-implemented
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search for an [existing missing service call issue](https://github.com/Ryujinx/Ryujinx/issues) first.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: instruction
attributes:
label: Service Call
label: Service call
description: What service call is missing?
validations:
required: true

View File

@@ -44,11 +44,12 @@
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.26.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.26.1" />
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageVersion Include="System.Management" Version="7.0.0" />
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-9c9356d" />
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
</ItemGroup>
</Project>

View File

@@ -132,8 +132,8 @@ namespace Ryujinx.Modules
}
}
// If build not done, assume no new update are availaible.
if (_buildUrl == null)
// If build not done, assume no new update are available.
if (_buildUrl is null)
{
if (showVersionUpToDate)
{
@@ -240,13 +240,13 @@ namespace Ryujinx.Modules
{
HttpClient result = new();
// Required by GitHub to interract with APIs.
// Required by GitHub to interact with APIs.
result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
return result;
}
public static async void UpdateRyujinx(Window parent, string downloadUrl)
private static async void UpdateRyujinx(Window parent, string downloadUrl)
{
_updateSuccessful = false;
@@ -300,8 +300,6 @@ namespace Ryujinx.Modules
ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx");
}
SetFileExecutable(ryuExe);
Process.Start(ryuExe, CommandLineState.Arguments);
Environment.Exit(0);
@@ -408,9 +406,9 @@ namespace Ryujinx.Modules
Logger.Warning?.Print(LogClass.Application, ex.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
for (int j = 0; j < webClients.Count; j++)
foreach (WebClient webClient in webClients)
{
webClients[j].CancelAsync();
webClient.CancelAsync();
}
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
@@ -472,22 +470,6 @@ namespace Ryujinx.Modules
worker.Start();
}
private static void SetFileExecutable(string path)
{
const UnixFileMode ExecutableFileMode = UnixFileMode.UserExecute |
UnixFileMode.UserWrite |
UnixFileMode.UserRead |
UnixFileMode.GroupRead |
UnixFileMode.GroupWrite |
UnixFileMode.OtherRead |
UnixFileMode.OtherWrite;
if (!OperatingSystem.IsWindows() && File.Exists(path))
{
File.SetUnixFileMode(path, ExecutableFileMode);
}
}
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
{
// Extract Update
@@ -503,27 +485,30 @@ namespace Ryujinx.Modules
await Task.Run(() =>
{
TarEntry tarEntry;
while ((tarEntry = tarStream.GetNextEntry()) != null)
if (!OperatingSystem.IsWindows())
{
if (tarEntry.IsDirectory) continue;
string outPath = Path.Combine(UpdateDir, tarEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
using (FileStream outStream = File.OpenWrite(outPath))
while ((tarEntry = tarStream.GetNextEntry()) is not null)
{
tarStream.CopyEntryContents(outStream);
if (tarEntry.IsDirectory) continue;
string outPath = Path.Combine(UpdateDir, tarEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
using (FileStream outStream = File.OpenWrite(outPath))
{
tarStream.CopyEntryContents(outStream);
}
File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
Dispatcher.UIThread.Post(() =>
{
taskDialog.SetProgressBarState(GetPercentage(tarEntry.Size, inStream.Length), TaskDialogProgressState.Normal);
});
}
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
TarEntry entry = tarEntry;
Dispatcher.UIThread.Post(() =>
{
taskDialog.SetProgressBarState(GetPercentage(entry.Size, inStream.Length), TaskDialogProgressState.Normal);
});
}
});
@@ -603,8 +588,6 @@ namespace Ryujinx.Modules
Directory.Delete(UpdateDir, true);
SetFileExecutable(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"));
_updateSuccessful = true;
taskDialog.Hide();

View File

@@ -1,127 +0,0 @@
using System;
using System.Runtime.Versioning;
using System.Runtime.InteropServices;
using Avalonia;
namespace Ryujinx.Ava.UI.Helpers
{
public delegate void UpdateBoundsCallbackDelegate(Rect rect);
[SupportedOSPlatform("macos")]
static partial class MetalHelper
{
private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
private struct Selector
{
public readonly IntPtr NativePtr;
public unsafe Selector(string value)
{
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
byte* data = stackalloc byte[size];
fixed (char* pValue = value)
{
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
}
NativePtr = sel_registerName(data);
}
public static implicit operator Selector(string value) => new Selector(value);
}
private static unsafe IntPtr GetClass(string value)
{
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
byte* data = stackalloc byte[size];
fixed (char* pValue = value)
{
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
}
return objc_getClass(data);
}
private struct NSPoint
{
public double X;
public double Y;
public NSPoint(double x, double y)
{
X = x;
Y = y;
}
}
private struct NSRect
{
public NSPoint Pos;
public NSPoint Size;
public NSRect(double x, double y, double width, double height)
{
Pos = new NSPoint(x, y);
Size = new NSPoint(width, height);
}
}
public static IntPtr GetMetalLayer(out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
{
// Create a new CAMetalLayer.
IntPtr layerClass = GetClass("CAMetalLayer");
IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
objc_msgSend(metalLayer, "init");
// Create a child NSView to render into.
IntPtr nsViewClass = GetClass("NSView");
IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
objc_msgSend(child, "init", new NSRect(0, 0, 0, 0));
// Make its renderer our metal layer.
objc_msgSend(child, "setWantsLayer:", (byte)1);
objc_msgSend(child, "setLayer:", metalLayer);
objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
// Ensure the scale factor is up to date.
updateBounds = (Rect rect) => {
objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
};
nsView = child;
return metalLayer;
}
public static void DestroyMetalLayer(IntPtr nsView, IntPtr metalLayer)
{
// TODO
}
[LibraryImport(LibObjCImport)]
private static unsafe partial IntPtr sel_registerName(byte* data);
[LibraryImport(LibObjCImport)]
private static unsafe partial IntPtr objc_getClass(byte* data);
[LibraryImport(LibObjCImport)]
private static partial void objc_msgSend(IntPtr receiver, Selector selector);
[LibraryImport(LibObjCImport)]
private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
[LibraryImport(LibObjCImport)]
private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
[LibraryImport(LibObjCImport)]
private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
[LibraryImport(LibObjCImport)]
private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
[LibraryImport(LibObjCImport, EntryPoint = "objc_msgSend")]
private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
}
}

View File

@@ -2,9 +2,9 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Configuration;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using SPB.Graphics;
using SPB.Platform;
using SPB.Platform.GLX;
@@ -30,6 +30,7 @@ namespace Ryujinx.Ava.UI.Renderer
protected IntPtr NsView { get; set; }
protected IntPtr MetalLayer { get; set; }
public delegate void UpdateBoundsCallbackDelegate(Rect rect);
private UpdateBoundsCallbackDelegate _updateBoundsCallback;
public event EventHandler<IntPtr> WindowCreated;
@@ -237,8 +238,29 @@ namespace Ryujinx.Ava.UI.Renderer
[SupportedOSPlatform("macos")]
IPlatformHandle CreateMacOS()
{
MetalLayer = MetalHelper.GetMetalLayer(out IntPtr nsView, out _updateBoundsCallback);
// Create a new CAMetalLayer.
IntPtr layerClass = ObjectiveC.objc_getClass("CAMetalLayer");
IntPtr metalLayer = ObjectiveC.IntPtr_objc_msgSend(layerClass, "alloc");
ObjectiveC.objc_msgSend(metalLayer, "init");
// Create a child NSView to render into.
IntPtr nsViewClass = ObjectiveC.objc_getClass("NSView");
IntPtr child = ObjectiveC.IntPtr_objc_msgSend(nsViewClass, "alloc");
ObjectiveC.objc_msgSend(child, "init", new ObjectiveC.NSRect(0, 0, 0, 0));
// Make its renderer our metal layer.
ObjectiveC.objc_msgSend(child, "setWantsLayer:", 1);
ObjectiveC.objc_msgSend(child, "setLayer:", metalLayer);
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
// Ensure the scale factor is up to date.
_updateBoundsCallback = rect =>
{
ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
};
IntPtr nsView = child;
MetalLayer = metalLayer;
NsView = nsView;
return new PlatformHandle(nsView, "NSView");
@@ -260,7 +282,7 @@ namespace Ryujinx.Ava.UI.Renderer
[SupportedOSPlatform("macos")]
void DestroyMacOS()
{
MetalHelper.DestroyMetalLayer(NsView, MetalLayer);
// TODO
}
}
}

View File

@@ -474,6 +474,13 @@ namespace Ryujinx.Graphics.Gpu.Image
{
address = memoryManager.Translate(info.GpuAddress);
// If the start address is unmapped, let's try to find a page of memory that is mapped.
if (address == MemoryManager.PteUnmapped)
{
address = memoryManager.TranslateFirstMapped(info.GpuAddress, (ulong)info.CalculateSizeInfo(layerSize).TotalSize);
}
// If address is still invalid, the texture is fully unmapped, so it has no data, just return null.
if (address == MemoryManager.PteUnmapped)
{
return null;

View File

@@ -336,24 +336,23 @@ namespace Ryujinx.Graphics.Gpu.Image
if (_loadNeeded[baseHandle + i])
{
var info = GetHandleInformation(baseHandle + i);
int offsetIndex = info.Index;
// Only one of these will be greater than 1, as partial sync is only called when there are sub-image views.
for (int layer = 0; layer < info.Layers; layer++)
{
for (int level = 0; level < info.Levels; level++)
{
int offsetIndex = GetOffsetIndex(info.BaseLayer + layer, info.BaseLevel + level);
int offset = _allOffsets[offsetIndex];
int endOffset = Math.Min(offset + _sliceSizes[info.BaseLevel + level], (int)Storage.Size);
int size = endOffset - offset;
ReadOnlySpan<byte> data = _physicalMemory.GetSpan(Storage.Range.GetSlice((ulong)offset, (ulong)size));
SpanOrArray<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel, true);
SpanOrArray<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true);
Storage.SetData(result, info.BaseLayer, info.BaseLevel);
offsetIndex++;
Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level);
}
}
}

View File

@@ -583,6 +583,38 @@ namespace Ryujinx.Graphics.Gpu.Memory
return UnpackPaFromPte(pte) + (va & PageMask);
}
/// <summary>
/// Translates a GPU virtual address to a CPU virtual address on the first mapped page of memory
/// on the specified region.
/// If no page is mapped on the specified region, <see cref="PteUnmapped"/> is returned.
/// </summary>
/// <param name="va">GPU virtual address to be translated</param>
/// <param name="size">Size of the range to be translated</param>
/// <returns>CPU virtual address, or <see cref="PteUnmapped"/> if unmapped</returns>
public ulong TranslateFirstMapped(ulong va, ulong size)
{
if (!ValidateAddress(va))
{
return PteUnmapped;
}
ulong endVa = va + size;
ulong pte = GetPte(va);
for (; va < endVa && pte == PteUnmapped; va += PageSize - (va & PageMask))
{
pte = GetPte(va);
}
if (pte == PteUnmapped)
{
return PteUnmapped;
}
return UnpackPaFromPte(pte) + (va & PageMask);
}
/// <summary>
/// Gets the kind of a given memory page.
/// This might indicate the type of resource that can be allocated on the page, and also texture tiling.

View File

@@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.OpenGL
{
class Program : IProgram
{
private const int MaxShaderLogLength = 2048;
public int Handle { get; private set; }
public bool IsLinked
@@ -115,9 +117,16 @@ namespace Ryujinx.Graphics.OpenGL
if (status == 0)
{
// Use GL.GetProgramInfoLog(Handle), it may be too long to print on the log.
_status = ProgramLinkStatus.Failure;
Logger.Debug?.Print(LogClass.Gpu, "Shader linking failed.");
string log = GL.GetProgramInfoLog(Handle);
if (log.Length > MaxShaderLogLength)
{
log = log.Substring(0, MaxShaderLogLength) + "...";
}
Logger.Warning?.Print(LogClass.Gpu, $"Shader linking failed: \n{log}");
}
else
{

View File

@@ -397,6 +397,31 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch)
{
bool iaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.IaIndexing);
if (iaIndexing && !perPatch)
{
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
if (context.Config.Stage == ShaderStage.Geometry)
{
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices));
}
var spvType = context.TypePointer(StorageClass.Input, attrType);
var spvVar = context.Variable(spvType, StorageClass.Input);
if (context.Config.PassthroughAttributes != 0 && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0);
context.AddGlobalVariable(spvVar);
context.InputsArray = spvVar;
}
var inputs = perPatch ? info.InputsPerPatch : info.Inputs;
foreach (int attr in inputs)
@@ -410,60 +435,56 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (iaIndexing && isUserAttr && !perPatch)
{
if (context.InputsArray == null)
{
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
if (context.Config.Stage == ShaderStage.Geometry)
{
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices));
}
var spvType = context.TypePointer(StorageClass.Input, attrType);
var spvVar = context.Variable(spvType, StorageClass.Input);
if (context.Config.PassthroughAttributes != 0 && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0);
context.AddGlobalVariable(spvVar);
context.InputsArray = spvVar;
}
continue;
}
else
PixelImap iq = PixelImap.Unused;
if (context.Config.Stage == ShaderStage.Fragment)
{
PixelImap iq = PixelImap.Unused;
if (context.Config.Stage == ShaderStage.Fragment)
if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
{
if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
{
iq = context.Config.ImapTypes[(attr - AttributeConsts.UserAttributeBase) / 16].GetFirstUsedType();
}
else
{
AttributeInfo attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr: false);
AggregateType elemType = attrInfo.Type & AggregateType.ElementTypeMask;
iq = context.Config.ImapTypes[(attr - AttributeConsts.UserAttributeBase) / 16].GetFirstUsedType();
}
else
{
AttributeInfo attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr: false);
AggregateType elemType = attrInfo.Type & AggregateType.ElementTypeMask;
if (attrInfo.IsBuiltin && (elemType == AggregateType.S32 || elemType == AggregateType.U32))
{
iq = PixelImap.Constant;
}
if (attrInfo.IsBuiltin && (elemType == AggregateType.S32 || elemType == AggregateType.U32))
{
iq = PixelImap.Constant;
}
}
DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq);
}
DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq);
}
}
private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch)
{
bool oaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing);
if (oaIndexing && !perPatch)
{
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
if (context.Config.Stage == ShaderStage.TessellationControl)
{
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), context.Config.ThreadsPerInputPrimitive));
}
var spvType = context.TypePointer(StorageClass.Output, attrType);
var spvVar = context.Variable(spvType, StorageClass.Output);
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0);
context.AddGlobalVariable(spvVar);
context.OutputsArray = spvVar;
}
var outputs = perPatch ? info.OutputsPerPatch : info.Outputs;
foreach (int attr in outputs)
@@ -477,29 +498,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (oaIndexing && isUserAttr && !perPatch)
{
if (context.OutputsArray == null)
{
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
if (context.Config.Stage == ShaderStage.TessellationControl)
{
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), context.Config.ThreadsPerInputPrimitive));
}
var spvType = context.TypePointer(StorageClass.Output, attrType);
var spvVar = context.Variable(spvType, StorageClass.Output);
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0);
context.AddGlobalVariable(spvVar);
context.OutputsArray = spvVar;
}
}
else
{
DeclareOutputAttribute(context, attr, perPatch);
continue;
}
DeclareOutputAttribute(context, attr, perPatch);
}
if (context.Config.Stage == ShaderStage.Vertex)

View File

@@ -10,11 +10,13 @@ namespace Ryujinx.Graphics.Vulkan
private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000;
private const int MinDrawCountForFlush = 10;
private const int MinConsecutiveQueryForFlush = 10;
private const int InitialQueryCountForFlush = 32;
private long _lastFlush;
private ulong _lastDrawCount;
private bool _hasPendingQuery;
private int _consecutiveQueries;
private int _queryCount;
private int[] _queryCountHistory = new int[3];
@@ -27,11 +29,13 @@ namespace Ryujinx.Graphics.Vulkan
_lastDrawCount = drawCount;
_hasPendingQuery = false;
_consecutiveQueries = 0;
}
public bool RegisterPendingQuery()
{
_hasPendingQuery = true;
_consecutiveQueries++;
_remainingQueries--;
_queryCountHistory[_queryCountHistoryIndex]++;
@@ -65,15 +69,18 @@ namespace Ryujinx.Graphics.Vulkan
return _hasPendingQuery;
}
public bool ShouldFlush(ulong drawCount)
public bool ShouldFlushAttachmentChange(ulong drawCount)
{
_queryCount = 0;
if (_hasPendingQuery)
// Flush when there's an attachment change out of a large block of queries.
if (_consecutiveQueries > MinConsecutiveQueryForFlush)
{
return true;
}
_consecutiveQueries = 0;
long draws = (long)(drawCount - _lastDrawCount);
if (draws < MinDrawCountForFlush)

View File

@@ -39,7 +39,6 @@ namespace Ryujinx.Graphics.Vulkan
BufferUsageFlags.VertexBufferBit |
BufferUsageFlags.TransformFeedbackBufferBitExt;
private readonly PhysicalDevice _physicalDevice;
private readonly Device _device;
private readonly IdList<BufferHolder> _buffers;
@@ -48,9 +47,8 @@ namespace Ryujinx.Graphics.Vulkan
public StagingBuffer StagingBuffer { get; }
public BufferManager(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
public BufferManager(VulkanRenderer gd, Device device)
{
_physicalDevice = physicalDevice;
_device = device;
_buffers = new IdList<BufferHolder>();
StagingBuffer = new StagingBuffer(gd, this);
@@ -114,7 +112,7 @@ namespace Ryujinx.Graphics.Vulkan
allocateFlagsAlt = DefaultBufferMemoryAltFlags;
}
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, requirements, allocateFlags, allocateFlagsAlt);
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(requirements, allocateFlags, allocateFlagsAlt);
if (allocation.Memory.Handle == 0UL)
{

View File

@@ -8,11 +8,10 @@ namespace Ryujinx.Graphics.Vulkan
{
None = 0,
VertexBufferAlignment4B = 1,
NoTriangleFans = 1 << 1,
NoPointMode = 1 << 2,
No3DImageView = 1 << 3,
NoLodBias = 1 << 4
NoTriangleFans = 1,
NoPointMode = 1 << 1,
No3DImageView = 1 << 2,
NoLodBias = 1 << 3
}
readonly struct HardwareCapabilities
@@ -40,6 +39,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly ShaderStageFlags RequiredSubgroupSizeStages;
public readonly SampleCountFlags SupportedSampleCounts;
public readonly PortabilitySubsetFlags PortabilitySubset;
public readonly uint VertexBufferAlignment;
public HardwareCapabilities(
bool supportsIndexTypeUint8,
@@ -64,7 +64,8 @@ namespace Ryujinx.Graphics.Vulkan
uint maxSubgroupSize,
ShaderStageFlags requiredSubgroupSizeStages,
SampleCountFlags supportedSampleCounts,
PortabilitySubsetFlags portabilitySubset)
PortabilitySubsetFlags portabilitySubset,
uint vertexBufferAlignment)
{
SupportsIndexTypeUint8 = supportsIndexTypeUint8;
SupportsCustomBorderColor = supportsCustomBorderColor;
@@ -89,6 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
SupportedSampleCounts = supportedSampleCounts;
PortabilitySubset = portabilitySubset;
VertexBufferAlignment = vertexBufferAlignment;
}
}
}

View File

@@ -9,34 +9,36 @@ namespace Ryujinx.Graphics.Vulkan
private ulong MaxDeviceMemoryUsageEstimate = 16UL * 1024 * 1024 * 1024;
private readonly Vk _api;
private readonly PhysicalDevice _physicalDevice;
private readonly Device _device;
private readonly List<MemoryAllocatorBlockList> _blockLists;
private readonly int _blockAlignment;
private readonly PhysicalDeviceMemoryProperties _physicalDeviceMemoryProperties;
private int _blockAlignment;
public MemoryAllocator(Vk api, Device device, uint maxMemoryAllocationCount)
public MemoryAllocator(Vk api, PhysicalDevice physicalDevice, Device device, uint maxMemoryAllocationCount)
{
_api = api;
_physicalDevice = physicalDevice;
_device = device;
_blockLists = new List<MemoryAllocatorBlockList>();
_blockAlignment = (int)Math.Min(int.MaxValue, MaxDeviceMemoryUsageEstimate / (ulong)maxMemoryAllocationCount);
_api.GetPhysicalDeviceMemoryProperties(_physicalDevice, out _physicalDeviceMemoryProperties);
}
public MemoryAllocation AllocateDeviceMemory(
PhysicalDevice physicalDevice,
MemoryRequirements requirements,
MemoryPropertyFlags flags = 0)
{
return AllocateDeviceMemory(physicalDevice, requirements, flags, flags);
return AllocateDeviceMemory(requirements, flags, flags);
}
public MemoryAllocation AllocateDeviceMemory(
PhysicalDevice physicalDevice,
MemoryRequirements requirements,
MemoryPropertyFlags flags,
MemoryPropertyFlags alternativeFlags)
{
int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags, alternativeFlags);
int memoryTypeIndex = FindSuitableMemoryTypeIndex(requirements.MemoryTypeBits, flags, alternativeFlags);
if (memoryTypeIndex < 0)
{
return default;
@@ -65,20 +67,16 @@ namespace Ryujinx.Graphics.Vulkan
return newBl.Allocate(size, alignment, map);
}
private static int FindSuitableMemoryTypeIndex(
Vk api,
PhysicalDevice physicalDevice,
private int FindSuitableMemoryTypeIndex(
uint memoryTypeBits,
MemoryPropertyFlags flags,
MemoryPropertyFlags alternativeFlags)
{
int bestCandidateIndex = -1;
api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties);
for (int i = 0; i < properties.MemoryTypeCount; i++)
for (int i = 0; i < _physicalDeviceMemoryProperties.MemoryTypeCount; i++)
{
var type = properties.MemoryTypes[i];
var type = _physicalDeviceMemoryProperties.MemoryTypes[i];
if ((memoryTypeBits & (1 << i)) != 0)
{

View File

@@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan;
using System;
@@ -650,9 +651,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
DynamicState.Viewports = oldViewports;
DynamicState.ViewportsCount = (int)oldViewportsCount;
DynamicState.SetViewportsDirty();
DynamicState.SetViewports(ref oldViewports, oldViewportsCount);
_newState.ViewportsCount = oldViewportsCount;
SignalStateChange();
@@ -1138,7 +1137,7 @@ namespace Ryujinx.Graphics.Vulkan
buffer.Dispose();
if (!Gd.Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B) &&
if (Gd.Capabilities.VertexBufferAlignment < 2 &&
(vertexBuffer.Stride % FormatExtensions.MaxBufferFormatScalarSize) == 0)
{
buffer = new VertexBufferState(
@@ -1183,6 +1182,8 @@ namespace Ryujinx.Graphics.Vulkan
return Math.Clamp(value, 0f, 1f);
}
DynamicState.ViewportsCount = (uint)count;
for (int i = 0; i < count; i++)
{
var viewport = viewports[i];
@@ -1196,8 +1197,6 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthFar)));
}
DynamicState.ViewportsCount = count;
float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform)
{

View File

@@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan;
using System;
@@ -253,7 +254,7 @@ namespace Ryujinx.Graphics.Vulkan
if (gd.NeedsVertexBufferAlignment(vbScalarSizes[i], out int alignment))
{
alignedStride = (vertexBuffer.Stride + (alignment - 1)) & -alignment;
alignedStride = BitUtils.AlignUp(vertexBuffer.Stride, alignment);
}
// TODO: Support divisor > 1

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
private Array4<float> _blendConstants;
public int ViewportsCount;
public uint ViewportsCount;
public Array16<Viewport> Viewports;
private enum DirtyFlags
@@ -88,9 +88,15 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.Viewport;
}
public void SetViewportsDirty()
public void SetViewports(ref Array16<Viewport> viewports, uint viewportsCount)
{
_dirty |= DirtyFlags.Viewport;
Viewports = viewports;
ViewportsCount = viewportsCount;
if (ViewportsCount != 0)
{
_dirty |= DirtyFlags.Viewport;
}
}
public void ForceAllDirty()
@@ -155,7 +161,10 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordViewport(Vk api, CommandBuffer commandBuffer)
{
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.AsSpan());
if (ViewportsCount != 0)
{
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
}
}
}
}

View File

@@ -281,7 +281,7 @@ namespace Ryujinx.Graphics.Vulkan
protected override void SignalAttachmentChange()
{
if (AutoFlush.ShouldFlush(DrawCount))
if (AutoFlush.ShouldFlushAttachmentChange(DrawCount))
{
FlushCommandsImpl();
}

View File

@@ -55,7 +55,6 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe TextureStorage(
VulkanRenderer gd,
PhysicalDevice physicalDevice,
Device device,
TextureCreateInfo info,
float scaleFactor,
@@ -118,7 +117,7 @@ namespace Ryujinx.Graphics.Vulkan
if (foreignAllocation == null)
{
gd.Api.GetImageMemoryRequirements(device, _image, out var requirements);
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(physicalDevice, requirements, DefaultImageMemoryFlags);
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(requirements, DefaultImageMemoryFlags);
if (allocation.Memory.Handle == 0UL)
{
@@ -173,7 +172,7 @@ namespace Ryujinx.Graphics.Vulkan
var info = NewCreateInfoWith(ref _info, format, _info.BytesPerPixel);
storage = new TextureStorage(_gd, default, _device, info, ScaleFactor, _allocationAuto);
storage = new TextureStorage(_gd, _device, info, ScaleFactor, _allocationAuto);
_aliasedStorages.Add(format, storage);
}

View File

@@ -712,7 +712,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int level = 0; level < levels; level++)
{
int mipSize = GetBufferDataLength(Info.GetMipSize(dstLevel + level));
int mipSize = GetBufferDataLength(Info.GetMipSize2D(dstLevel + level) * dstLayers);
int endOffset = offset + mipSize;

View File

@@ -14,6 +14,9 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe static class VulkanInitialization
{
private const uint InvalidIndex = uint.MaxValue;
private static uint MinimalVulkanVersion = Vk.Version11.Value;
private static uint MinimalInstanceVulkanVersion = Vk.Version12.Value;
private static uint MaximumVulkanVersion = Vk.Version12.Value;
private const string AppName = "Ryujinx.Graphics.Vulkan";
private const int QueuesCount = 2;
@@ -33,7 +36,8 @@ namespace Ryujinx.Graphics.Vulkan
"VK_KHR_shader_float16_int8",
"VK_EXT_shader_subgroup_ballot",
"VK_EXT_subgroup_size_control",
"VK_NV_geometry_shader_passthrough"
"VK_NV_geometry_shader_passthrough",
"VK_KHR_portability_subset", // By spec, we should enable this if present.
};
public static string[] RequiredExtensions { get; } = new string[]
@@ -99,7 +103,7 @@ namespace Ryujinx.Graphics.Vulkan
ApplicationVersion = 1,
PEngineName = (byte*)appName,
EngineVersion = 1,
ApiVersion = Vk.Version12.Value
ApiVersion = MaximumVulkanVersion
};
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
@@ -224,7 +228,7 @@ namespace Ryujinx.Graphics.Vulkan
ApplicationVersion = 1,
PEngineName = (byte*)appName,
EngineVersion = 1,
ApiVersion = Vk.Version12.Value
ApiVersion = MaximumVulkanVersion
};
var instanceCreateInfo = new InstanceCreateInfo
@@ -239,6 +243,27 @@ namespace Ryujinx.Graphics.Vulkan
api.CreateInstance(in instanceCreateInfo, null, out var instance).ThrowOnError();
// We ensure that vkEnumerateInstanceVersion is present (added in 1.1).
// If the instance doesn't support it, no device is going to be 1.1 compatible.
if (api.GetInstanceProcAddr(instance, "vkEnumerateInstanceVersion") == IntPtr.Zero)
{
api.DestroyInstance(instance, null);
return Array.Empty<DeviceInfo>();
}
// We currently assume that the instance is compatible with Vulkan 1.2
// TODO: Remove this once we relax our initialization codepaths.
uint instanceApiVerison = 0;
api.EnumerateInstanceVersion(ref instanceApiVerison).ThrowOnError();
if (instanceApiVerison < MinimalInstanceVulkanVersion)
{
api.DestroyInstance(instance, null);
return Array.Empty<DeviceInfo>();
}
Marshal.FreeHGlobal(appName);
uint physicalDeviceCount;
@@ -259,6 +284,11 @@ namespace Ryujinx.Graphics.Vulkan
var physicalDevice = physicalDevices[i];
api.GetPhysicalDeviceProperties(physicalDevice, out var properties);
if (properties.ApiVersion < MinimalVulkanVersion)
{
continue;
}
devices[i] = new DeviceInfo(
StringFromIdPair(properties.VendorID, properties.DeviceID),
VendorUtils.GetNameFromId(properties.VendorID),

View File

@@ -234,10 +234,12 @@ namespace Ryujinx.Graphics.Vulkan
Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2);
var portabilityFlags = PortabilitySubsetFlags.None;
uint vertexBufferAlignment = 1;
if (usePortability)
{
portabilityFlags |= propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment > 1 ? PortabilitySubsetFlags.VertexBufferAlignment4B : 0;
vertexBufferAlignment = propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment;
portabilityFlags |= featuresPortabilitySubset.TriangleFans ? 0 : PortabilitySubsetFlags.NoTriangleFans;
portabilityFlags |= featuresPortabilitySubset.PointPolygons ? 0 : PortabilitySubsetFlags.NoPointMode;
portabilityFlags |= featuresPortabilitySubset.ImageView2DOn3DImage ? 0 : PortabilitySubsetFlags.No3DImageView;
@@ -278,9 +280,10 @@ namespace Ryujinx.Graphics.Vulkan
propertiesSubgroupSizeControl.MaxSubgroupSize,
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
supportedSampleCounts,
portabilityFlags);
portabilityFlags,
vertexBufferAlignment);
MemoryAllocator = new MemoryAllocator(Api, _device, properties.Limits.MaxMemoryAllocationCount);
MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device, properties.Limits.MaxMemoryAllocationCount);
CommandBufferPool = VulkanInitialization.CreateCommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
@@ -290,7 +293,7 @@ namespace Ryujinx.Graphics.Vulkan
BackgroundResources = new BackgroundResources(this, _device);
BufferManager = new BufferManager(this, _physicalDevice, _device);
BufferManager = new BufferManager(this, _device);
_syncManager = new SyncManager(this, _device);
_pipeline = new PipelineFull(this, _device);
@@ -388,7 +391,7 @@ namespace Ryujinx.Graphics.Vulkan
internal TextureStorage CreateTextureStorage(TextureCreateInfo info, float scale)
{
return new TextureStorage(this, _physicalDevice, _device, info, scale);
return new TextureStorage(this, _device, info, scale);
}
public void DeleteBuffer(BufferHandle buffer)
@@ -636,11 +639,11 @@ namespace Ryujinx.Graphics.Vulkan
PrintGpuInformation();
}
public bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
internal bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
{
if (Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B))
if (Capabilities.VertexBufferAlignment > 1)
{
alignment = 4;
alignment = (int)Capabilities.VertexBufferAlignment;
return true;
}

View File

@@ -38,7 +38,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
public static bool IsValidNpadIdType(NpadIdType npadIdType)
{
return npadIdType <= NpadIdType.Player8 || npadIdType == NpadIdType.Handheld || npadIdType == NpadIdType.Unknown;
return (npadIdType >= NpadIdType.Player1 && npadIdType <= NpadIdType.Player8) ||
npadIdType == NpadIdType.Handheld ||
npadIdType == NpadIdType.Unknown;
}
}
}

View File

@@ -722,7 +722,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
for (int i = 0; i < supportedPlayerIds.Length; ++i)
{
if (supportedPlayerIds[i] >= 0)
if (HidUtils.IsValidNpadIdType(supportedPlayerIds[i]))
{
context.Device.Hid.Npads.SetSupportedPlayer(HidUtils.GetIndexFromNpadIdType(supportedPlayerIds[i]));
}
@@ -1101,7 +1101,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
if (deviceType < NpadStyleIndex.System || deviceType >= NpadStyleIndex.FullKey)
{
if (npadIdType >= (NpadIdType.Player8 + 1) && npadIdType != NpadIdType.Handheld && npadIdType != NpadIdType.Unknown)
if (!HidUtils.IsValidNpadIdType(npadIdType))
{
return ResultCode.InvalidNpadIdType;
}

View File

@@ -1,11 +1,14 @@
using System;
namespace Ryujinx.Tests.Unicorn
{
[Flags]
public enum MemoryPermission
{
NONE = 0,
READ = 1,
WRITE = 2,
EXEC = 4,
ALL = 7,
None = 0,
Read = 1,
Write = 2,
Exec = 4,
All = 7,
}
}
}

View File

@@ -1,20 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Arch
{
ARM = 1,
ARM64 = 2,
MIPS = 3,
X86 = 4,
PPC = 5,
SPARC = 6,
M68K = 7,
RISCV = 8,
S390X = 9,
TRICORE = 10,
MAX = 11,
}
}

View File

@@ -1,200 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Arm
{
// ARM CPU
CPU_ARM_926 = 0,
CPU_ARM_946 = 1,
CPU_ARM_1026 = 2,
CPU_ARM_1136_R2 = 3,
CPU_ARM_1136 = 4,
CPU_ARM_1176 = 5,
CPU_ARM_11MPCORE = 6,
CPU_ARM_CORTEX_M0 = 7,
CPU_ARM_CORTEX_M3 = 8,
CPU_ARM_CORTEX_M4 = 9,
CPU_ARM_CORTEX_M7 = 10,
CPU_ARM_CORTEX_M33 = 11,
CPU_ARM_CORTEX_R5 = 12,
CPU_ARM_CORTEX_R5F = 13,
CPU_ARM_CORTEX_A7 = 14,
CPU_ARM_CORTEX_A8 = 15,
CPU_ARM_CORTEX_A9 = 16,
CPU_ARM_CORTEX_A15 = 17,
CPU_ARM_TI925T = 18,
CPU_ARM_SA1100 = 19,
CPU_ARM_SA1110 = 20,
CPU_ARM_PXA250 = 21,
CPU_ARM_PXA255 = 22,
CPU_ARM_PXA260 = 23,
CPU_ARM_PXA261 = 24,
CPU_ARM_PXA262 = 25,
CPU_ARM_PXA270 = 26,
CPU_ARM_PXA270A0 = 27,
CPU_ARM_PXA270A1 = 28,
CPU_ARM_PXA270B0 = 29,
CPU_ARM_PXA270B1 = 30,
CPU_ARM_PXA270C0 = 31,
CPU_ARM_PXA270C5 = 32,
CPU_ARM_MAX = 33,
CPU_ARM_ENDING = 34,
// ARM registers
REG_INVALID = 0,
REG_APSR = 1,
REG_APSR_NZCV = 2,
REG_CPSR = 3,
REG_FPEXC = 4,
REG_FPINST = 5,
REG_FPSCR = 6,
REG_FPSCR_NZCV = 7,
REG_FPSID = 8,
REG_ITSTATE = 9,
REG_LR = 10,
REG_PC = 11,
REG_SP = 12,
REG_SPSR = 13,
REG_D0 = 14,
REG_D1 = 15,
REG_D2 = 16,
REG_D3 = 17,
REG_D4 = 18,
REG_D5 = 19,
REG_D6 = 20,
REG_D7 = 21,
REG_D8 = 22,
REG_D9 = 23,
REG_D10 = 24,
REG_D11 = 25,
REG_D12 = 26,
REG_D13 = 27,
REG_D14 = 28,
REG_D15 = 29,
REG_D16 = 30,
REG_D17 = 31,
REG_D18 = 32,
REG_D19 = 33,
REG_D20 = 34,
REG_D21 = 35,
REG_D22 = 36,
REG_D23 = 37,
REG_D24 = 38,
REG_D25 = 39,
REG_D26 = 40,
REG_D27 = 41,
REG_D28 = 42,
REG_D29 = 43,
REG_D30 = 44,
REG_D31 = 45,
REG_FPINST2 = 46,
REG_MVFR0 = 47,
REG_MVFR1 = 48,
REG_MVFR2 = 49,
REG_Q0 = 50,
REG_Q1 = 51,
REG_Q2 = 52,
REG_Q3 = 53,
REG_Q4 = 54,
REG_Q5 = 55,
REG_Q6 = 56,
REG_Q7 = 57,
REG_Q8 = 58,
REG_Q9 = 59,
REG_Q10 = 60,
REG_Q11 = 61,
REG_Q12 = 62,
REG_Q13 = 63,
REG_Q14 = 64,
REG_Q15 = 65,
REG_R0 = 66,
REG_R1 = 67,
REG_R2 = 68,
REG_R3 = 69,
REG_R4 = 70,
REG_R5 = 71,
REG_R6 = 72,
REG_R7 = 73,
REG_R8 = 74,
REG_R9 = 75,
REG_R10 = 76,
REG_R11 = 77,
REG_R12 = 78,
REG_S0 = 79,
REG_S1 = 80,
REG_S2 = 81,
REG_S3 = 82,
REG_S4 = 83,
REG_S5 = 84,
REG_S6 = 85,
REG_S7 = 86,
REG_S8 = 87,
REG_S9 = 88,
REG_S10 = 89,
REG_S11 = 90,
REG_S12 = 91,
REG_S13 = 92,
REG_S14 = 93,
REG_S15 = 94,
REG_S16 = 95,
REG_S17 = 96,
REG_S18 = 97,
REG_S19 = 98,
REG_S20 = 99,
REG_S21 = 100,
REG_S22 = 101,
REG_S23 = 102,
REG_S24 = 103,
REG_S25 = 104,
REG_S26 = 105,
REG_S27 = 106,
REG_S28 = 107,
REG_S29 = 108,
REG_S30 = 109,
REG_S31 = 110,
REG_C1_C0_2 = 111,
REG_C13_C0_2 = 112,
REG_C13_C0_3 = 113,
REG_IPSR = 114,
REG_MSP = 115,
REG_PSP = 116,
REG_CONTROL = 117,
REG_IAPSR = 118,
REG_EAPSR = 119,
REG_XPSR = 120,
REG_EPSR = 121,
REG_IEPSR = 122,
REG_PRIMASK = 123,
REG_BASEPRI = 124,
REG_BASEPRI_MAX = 125,
REG_FAULTMASK = 126,
REG_APSR_NZCVQ = 127,
REG_APSR_G = 128,
REG_APSR_NZCVQG = 129,
REG_IAPSR_NZCVQ = 130,
REG_IAPSR_G = 131,
REG_IAPSR_NZCVQG = 132,
REG_EAPSR_NZCVQ = 133,
REG_EAPSR_G = 134,
REG_EAPSR_NZCVQG = 135,
REG_XPSR_NZCVQ = 136,
REG_XPSR_G = 137,
REG_XPSR_NZCVQG = 138,
REG_CP_REG = 139,
REG_ENDING = 140,
// alias registers
REG_R13 = 12,
REG_R14 = 10,
REG_R15 = 11,
REG_SB = 75,
REG_SL = 76,
REG_FP = 77,
REG_IP = 78,
}
}

View File

@@ -1,341 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Arm64
{
// ARM64 CPU
CPU_ARM64_A57 = 0,
CPU_ARM64_A53 = 1,
CPU_ARM64_A72 = 2,
CPU_ARM64_MAX = 3,
CPU_ARM64_ENDING = 4,
// ARM64 registers
REG_INVALID = 0,
REG_X29 = 1,
REG_X30 = 2,
REG_NZCV = 3,
REG_SP = 4,
REG_WSP = 5,
REG_WZR = 6,
REG_XZR = 7,
REG_B0 = 8,
REG_B1 = 9,
REG_B2 = 10,
REG_B3 = 11,
REG_B4 = 12,
REG_B5 = 13,
REG_B6 = 14,
REG_B7 = 15,
REG_B8 = 16,
REG_B9 = 17,
REG_B10 = 18,
REG_B11 = 19,
REG_B12 = 20,
REG_B13 = 21,
REG_B14 = 22,
REG_B15 = 23,
REG_B16 = 24,
REG_B17 = 25,
REG_B18 = 26,
REG_B19 = 27,
REG_B20 = 28,
REG_B21 = 29,
REG_B22 = 30,
REG_B23 = 31,
REG_B24 = 32,
REG_B25 = 33,
REG_B26 = 34,
REG_B27 = 35,
REG_B28 = 36,
REG_B29 = 37,
REG_B30 = 38,
REG_B31 = 39,
REG_D0 = 40,
REG_D1 = 41,
REG_D2 = 42,
REG_D3 = 43,
REG_D4 = 44,
REG_D5 = 45,
REG_D6 = 46,
REG_D7 = 47,
REG_D8 = 48,
REG_D9 = 49,
REG_D10 = 50,
REG_D11 = 51,
REG_D12 = 52,
REG_D13 = 53,
REG_D14 = 54,
REG_D15 = 55,
REG_D16 = 56,
REG_D17 = 57,
REG_D18 = 58,
REG_D19 = 59,
REG_D20 = 60,
REG_D21 = 61,
REG_D22 = 62,
REG_D23 = 63,
REG_D24 = 64,
REG_D25 = 65,
REG_D26 = 66,
REG_D27 = 67,
REG_D28 = 68,
REG_D29 = 69,
REG_D30 = 70,
REG_D31 = 71,
REG_H0 = 72,
REG_H1 = 73,
REG_H2 = 74,
REG_H3 = 75,
REG_H4 = 76,
REG_H5 = 77,
REG_H6 = 78,
REG_H7 = 79,
REG_H8 = 80,
REG_H9 = 81,
REG_H10 = 82,
REG_H11 = 83,
REG_H12 = 84,
REG_H13 = 85,
REG_H14 = 86,
REG_H15 = 87,
REG_H16 = 88,
REG_H17 = 89,
REG_H18 = 90,
REG_H19 = 91,
REG_H20 = 92,
REG_H21 = 93,
REG_H22 = 94,
REG_H23 = 95,
REG_H24 = 96,
REG_H25 = 97,
REG_H26 = 98,
REG_H27 = 99,
REG_H28 = 100,
REG_H29 = 101,
REG_H30 = 102,
REG_H31 = 103,
REG_Q0 = 104,
REG_Q1 = 105,
REG_Q2 = 106,
REG_Q3 = 107,
REG_Q4 = 108,
REG_Q5 = 109,
REG_Q6 = 110,
REG_Q7 = 111,
REG_Q8 = 112,
REG_Q9 = 113,
REG_Q10 = 114,
REG_Q11 = 115,
REG_Q12 = 116,
REG_Q13 = 117,
REG_Q14 = 118,
REG_Q15 = 119,
REG_Q16 = 120,
REG_Q17 = 121,
REG_Q18 = 122,
REG_Q19 = 123,
REG_Q20 = 124,
REG_Q21 = 125,
REG_Q22 = 126,
REG_Q23 = 127,
REG_Q24 = 128,
REG_Q25 = 129,
REG_Q26 = 130,
REG_Q27 = 131,
REG_Q28 = 132,
REG_Q29 = 133,
REG_Q30 = 134,
REG_Q31 = 135,
REG_S0 = 136,
REG_S1 = 137,
REG_S2 = 138,
REG_S3 = 139,
REG_S4 = 140,
REG_S5 = 141,
REG_S6 = 142,
REG_S7 = 143,
REG_S8 = 144,
REG_S9 = 145,
REG_S10 = 146,
REG_S11 = 147,
REG_S12 = 148,
REG_S13 = 149,
REG_S14 = 150,
REG_S15 = 151,
REG_S16 = 152,
REG_S17 = 153,
REG_S18 = 154,
REG_S19 = 155,
REG_S20 = 156,
REG_S21 = 157,
REG_S22 = 158,
REG_S23 = 159,
REG_S24 = 160,
REG_S25 = 161,
REG_S26 = 162,
REG_S27 = 163,
REG_S28 = 164,
REG_S29 = 165,
REG_S30 = 166,
REG_S31 = 167,
REG_W0 = 168,
REG_W1 = 169,
REG_W2 = 170,
REG_W3 = 171,
REG_W4 = 172,
REG_W5 = 173,
REG_W6 = 174,
REG_W7 = 175,
REG_W8 = 176,
REG_W9 = 177,
REG_W10 = 178,
REG_W11 = 179,
REG_W12 = 180,
REG_W13 = 181,
REG_W14 = 182,
REG_W15 = 183,
REG_W16 = 184,
REG_W17 = 185,
REG_W18 = 186,
REG_W19 = 187,
REG_W20 = 188,
REG_W21 = 189,
REG_W22 = 190,
REG_W23 = 191,
REG_W24 = 192,
REG_W25 = 193,
REG_W26 = 194,
REG_W27 = 195,
REG_W28 = 196,
REG_W29 = 197,
REG_W30 = 198,
REG_X0 = 199,
REG_X1 = 200,
REG_X2 = 201,
REG_X3 = 202,
REG_X4 = 203,
REG_X5 = 204,
REG_X6 = 205,
REG_X7 = 206,
REG_X8 = 207,
REG_X9 = 208,
REG_X10 = 209,
REG_X11 = 210,
REG_X12 = 211,
REG_X13 = 212,
REG_X14 = 213,
REG_X15 = 214,
REG_X16 = 215,
REG_X17 = 216,
REG_X18 = 217,
REG_X19 = 218,
REG_X20 = 219,
REG_X21 = 220,
REG_X22 = 221,
REG_X23 = 222,
REG_X24 = 223,
REG_X25 = 224,
REG_X26 = 225,
REG_X27 = 226,
REG_X28 = 227,
REG_V0 = 228,
REG_V1 = 229,
REG_V2 = 230,
REG_V3 = 231,
REG_V4 = 232,
REG_V5 = 233,
REG_V6 = 234,
REG_V7 = 235,
REG_V8 = 236,
REG_V9 = 237,
REG_V10 = 238,
REG_V11 = 239,
REG_V12 = 240,
REG_V13 = 241,
REG_V14 = 242,
REG_V15 = 243,
REG_V16 = 244,
REG_V17 = 245,
REG_V18 = 246,
REG_V19 = 247,
REG_V20 = 248,
REG_V21 = 249,
REG_V22 = 250,
REG_V23 = 251,
REG_V24 = 252,
REG_V25 = 253,
REG_V26 = 254,
REG_V27 = 255,
REG_V28 = 256,
REG_V29 = 257,
REG_V30 = 258,
REG_V31 = 259,
// pseudo registers
REG_PC = 260,
REG_CPACR_EL1 = 261,
// thread registers, depreciated, use UC_ARM64_REG_CP_REG instead
REG_TPIDR_EL0 = 262,
REG_TPIDRRO_EL0 = 263,
REG_TPIDR_EL1 = 264,
REG_PSTATE = 265,
// exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead
REG_ELR_EL0 = 266,
REG_ELR_EL1 = 267,
REG_ELR_EL2 = 268,
REG_ELR_EL3 = 269,
// stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead
REG_SP_EL0 = 270,
REG_SP_EL1 = 271,
REG_SP_EL2 = 272,
REG_SP_EL3 = 273,
// other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead
REG_TTBR0_EL1 = 274,
REG_TTBR1_EL1 = 275,
REG_ESR_EL0 = 276,
REG_ESR_EL1 = 277,
REG_ESR_EL2 = 278,
REG_ESR_EL3 = 279,
REG_FAR_EL0 = 280,
REG_FAR_EL1 = 281,
REG_FAR_EL2 = 282,
REG_FAR_EL3 = 283,
REG_PAR_EL1 = 284,
REG_MAIR_EL1 = 285,
REG_VBAR_EL0 = 286,
REG_VBAR_EL1 = 287,
REG_VBAR_EL2 = 288,
REG_VBAR_EL3 = 289,
REG_CP_REG = 290,
// floating point control and status registers
REG_FPCR = 291,
REG_FPSR = 292,
REG_ENDING = 293,
// alias registers
REG_IP0 = 215,
REG_IP1 = 216,
REG_FP = 1,
REG_LR = 2,
// ARM64 instructions
INS_INVALID = 0,
INS_MRS = 1,
INS_MSR = 2,
INS_SYS = 3,
INS_SYSL = 4,
INS_ENDING = 5,
}
}

View File

@@ -1,44 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Common
{
API_MAJOR = 2,
API_MINOR = 0,
API_PATCH = 0,
API_EXTRA = 255,
VERSION_MAJOR = 2,
VERSION_MINOR = 0,
VERSION_PATCH = 0,
VERSION_EXTRA = 255,
SECOND_SCALE = 1000000,
MILISECOND_SCALE = 1000,
QUERY_MODE = 1,
QUERY_PAGE_SIZE = 2,
QUERY_ARCH = 3,
QUERY_TIMEOUT = 4,
CTL_IO_NONE = 0,
CTL_IO_WRITE = 1,
CTL_IO_READ = 2,
CTL_IO_READ_WRITE = 3,
CTL_UC_MODE = 0,
CTL_UC_PAGE_SIZE = 1,
CTL_UC_ARCH = 2,
CTL_UC_TIMEOUT = 3,
CTL_UC_USE_EXITS = 4,
CTL_UC_EXITS_CNT = 5,
CTL_UC_EXITS = 6,
CTL_CPU_MODEL = 7,
CTL_TB_REQUEST_CACHE = 8,
CTL_TB_REMOVE_CACHE = 9,
CTL_TB_FLUSH = 10,
}
}

View File

@@ -1,31 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Error
{
OK = 0,
NOMEM = 1,
ARCH = 2,
HANDLE = 3,
MODE = 4,
VERSION = 5,
READ_UNMAPPED = 6,
WRITE_UNMAPPED = 7,
FETCH_UNMAPPED = 8,
HOOK = 9,
INSN_INVALID = 10,
MAP = 11,
WRITE_PROT = 12,
READ_PROT = 13,
FETCH_PROT = 14,
ARG = 15,
READ_UNALIGNED = 16,
WRITE_UNALIGNED = 17,
FETCH_UNALIGNED = 18,
HOOK_EXIST = 19,
RESOURCE = 20,
EXCEPTION = 21,
}
}

View File

@@ -1,33 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Hook
{
INTR = 1,
INSN = 2,
CODE = 4,
BLOCK = 8,
MEM_READ_UNMAPPED = 16,
MEM_WRITE_UNMAPPED = 32,
MEM_FETCH_UNMAPPED = 64,
MEM_READ_PROT = 128,
MEM_WRITE_PROT = 256,
MEM_FETCH_PROT = 512,
MEM_READ = 1024,
MEM_WRITE = 2048,
MEM_FETCH = 4096,
MEM_READ_AFTER = 8192,
INSN_INVALID = 16384,
EDGE_GENERATED = 32768,
TCG_OPCODE = 65536,
MEM_UNMAPPED = 112,
MEM_PROT = 896,
MEM_READ_INVALID = 144,
MEM_WRITE_INVALID = 288,
MEM_FETCH_INVALID = 576,
MEM_INVALID = 1008,
MEM_VALID = 7168,
}
}

View File

@@ -1,19 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Memory
{
READ = 16,
WRITE = 17,
FETCH = 18,
READ_UNMAPPED = 19,
WRITE_UNMAPPED = 20,
FETCH_UNMAPPED = 21,
WRITE_PROT = 22,
READ_PROT = 23,
FETCH_PROT = 24,
READ_AFTER = 25,
}
}

View File

@@ -1,35 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Mode
{
LITTLE_ENDIAN = 0,
BIG_ENDIAN = 1073741824,
ARM = 0,
THUMB = 16,
MCLASS = 32,
V8 = 64,
ARMBE8 = 1024,
ARM926 = 128,
ARM946 = 256,
ARM1176 = 512,
MICRO = 16,
MIPS3 = 32,
MIPS32R6 = 64,
MIPS32 = 4,
MIPS64 = 8,
MODE_16 = 2,
MODE_32 = 4,
MODE_64 = 8,
PPC32 = 4,
PPC64 = 8,
QPX = 16,
SPARC32 = 4,
SPARC64 = 8,
V9 = 16,
RISCV32 = 4,
RISCV64 = 8,
}
}

View File

@@ -1,14 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum Permission
{
NONE = 0,
READ = 1,
WRITE = 2,
EXEC = 4,
ALL = 7,
}
}

View File

@@ -1,12 +0,0 @@
// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ReSharper disable InconsistentNaming
namespace Ryujinx.Tests.Unicorn.Native.Const
{
public enum TCG
{
OP_SUB = 0,
OP_FLAG_CMP = 1,
OP_FLAG_DIRECT = 2,
}
}

View File

@@ -1,101 +0,0 @@
using Ryujinx.Tests.Unicorn.Native.Const;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Tests.Unicorn.Native
{
public static partial class Interface
{
public static bool IsUnicornAvailable { get; private set; } = true;
private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (libraryName == "unicorn")
{
string loadPath = $"{Path.GetDirectoryName(assembly.Location)}/";
loadPath += OperatingSystem.IsWindows() ? $"{libraryName}.dll" : $"lib{libraryName}.so";
if (!NativeLibrary.TryLoad(loadPath, out IntPtr libraryPtr))
{
IsUnicornAvailable = false;
Console.Error.WriteLine($"ERROR: Could not find unicorn at: {loadPath}");
}
return libraryPtr;
}
// Otherwise, fallback to default import resolver.
return IntPtr.Zero;
}
static Interface()
{
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), ImportResolver);
}
public static void Checked(Error error)
{
if (error != Error.OK)
{
throw new UnicornException(error);
}
}
public static void MarshalArrayOf<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(IntPtr input, int length, out T[] output)
{
int size = Marshal.SizeOf<T>();
output = new T[length];
for (int i = 0; i < length; i++)
{
IntPtr item = new IntPtr(input.ToInt64() + i * size);
output[i] = Marshal.PtrToStructure<T>(item);
}
}
[LibraryImport("unicorn")]
public static partial uint uc_version(out uint major, out uint minor);
[LibraryImport("unicorn")]
public static partial Error uc_open(Arch arch, Mode mode, out IntPtr uc);
[LibraryImport("unicorn")]
public static partial Error uc_close(IntPtr uc);
[LibraryImport("unicorn")]
public static partial IntPtr uc_strerror(Error err);
[LibraryImport("unicorn")]
public static partial Error uc_reg_write(IntPtr uc, int regid, byte[] value);
[LibraryImport("unicorn")]
public static partial Error uc_reg_read(IntPtr uc, int regid, byte[] value);
[LibraryImport("unicorn")]
public static partial Error uc_mem_write(IntPtr uc, ulong address, byte[] bytes, ulong size);
[LibraryImport("unicorn")]
public static partial Error uc_mem_read(IntPtr uc, ulong address, byte[] bytes, ulong size);
[LibraryImport("unicorn")]
public static partial Error uc_emu_start(IntPtr uc, ulong begin, ulong until, ulong timeout, ulong count);
[LibraryImport("unicorn")]
public static partial Error uc_mem_map(IntPtr uc, ulong address, ulong size, uint perms);
[LibraryImport("unicorn")]
public static partial Error uc_mem_unmap(IntPtr uc, ulong address, ulong size);
[LibraryImport("unicorn")]
public static partial Error uc_mem_protect(IntPtr uc, ulong address, ulong size, uint perms);
[LibraryImport("unicorn")]
public static partial Error uc_mem_regions(IntPtr uc, out IntPtr regions, out uint count);
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Tests.Unicorn.Native
{
[StructLayout(LayoutKind.Sequential)]
public struct UnicornMemoryRegion
{
public UInt64 begin; // begin address of the region (inclusive)
public UInt64 end; // end address of the region (inclusive)
public UInt32 perms; // memory permissions of the region
}
}

View File

@@ -10,4 +10,8 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="UnicornEngine.Unicorn" />
</ItemGroup>
</Project>

View File

@@ -1,62 +1,45 @@
using Ryujinx.Tests.Unicorn.Native;
using Ryujinx.Tests.Unicorn.Native.Const;
using System;
using System;
using UnicornEngine.Const;
namespace Ryujinx.Tests.Unicorn
{
public class UnicornAArch32 : IDisposable
{
internal readonly IntPtr uc;
private bool _isDisposed = false;
internal readonly UnicornEngine.Unicorn uc;
private bool _isDisposed;
public IndexedProperty<int, uint> R
{
get
{
return new IndexedProperty<int, uint>(
(int i) => GetX(i),
(int i, uint value) => SetX(i, value));
}
}
public IndexedProperty<int, uint> R => new(GetX, SetX);
public IndexedProperty<int, SimdValue> Q
{
get
{
return new IndexedProperty<int, SimdValue>(
(int i) => GetQ(i),
(int i, SimdValue value) => SetQ(i, value));
}
}
public IndexedProperty<int, SimdValue> Q => new(GetQ, SetQ);
public uint LR
{
get => GetRegister(Arm.REG_LR);
set => SetRegister(Arm.REG_LR, value);
get => GetRegister(Arm.UC_ARM_REG_LR);
set => SetRegister(Arm.UC_ARM_REG_LR, value);
}
public uint SP
{
get => GetRegister(Arm.REG_SP);
set => SetRegister(Arm.REG_SP, value);
get => GetRegister(Arm.UC_ARM_REG_SP);
set => SetRegister(Arm.UC_ARM_REG_SP, value);
}
public uint PC
{
get => GetRegister(Arm.REG_PC) & 0xfffffffeu;
set => SetRegister(Arm.REG_PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u));
get => GetRegister(Arm.UC_ARM_REG_PC) & 0xfffffffeu;
set => SetRegister(Arm.UC_ARM_REG_PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u));
}
public uint CPSR
{
get => GetRegister(Arm.REG_CPSR);
set => SetRegister(Arm.REG_CPSR, value);
get => GetRegister(Arm.UC_ARM_REG_CPSR);
set => SetRegister(Arm.UC_ARM_REG_CPSR, value);
}
public int Fpscr
{
get => (int)GetRegister(Arm.REG_FPSCR) | ((int)GetRegister(Arm.REG_FPSCR_NZCV));
set => SetRegister(Arm.REG_FPSCR, (uint)value);
get => (int)GetRegister(Arm.UC_ARM_REG_FPSCR) | ((int)GetRegister(Arm.UC_ARM_REG_FPSCR_NZCV));
set => SetRegister(Arm.UC_ARM_REG_FPSCR, (uint)value);
}
public bool QFlag
@@ -95,16 +78,16 @@ namespace Ryujinx.Tests.Unicorn
set
{
CPSR = (CPSR & ~0x00000020u) | (value ? 0x00000020u : 0u);
SetRegister(Arm.REG_PC, (GetRegister(Arm.REG_PC) & 0xfffffffeu) | (value ? 1u : 0u));
SetRegister(Arm.UC_ARM_REG_PC, (GetRegister(Arm.UC_ARM_REG_PC) & 0xfffffffeu) | (value ? 1u : 0u));
}
}
public UnicornAArch32()
{
Interface.Checked(Interface.uc_open(Arch.ARM, Mode.LITTLE_ENDIAN, out uc));
uc = new UnicornEngine.Unicorn(Common.UC_ARCH_ARM, Common.UC_MODE_LITTLE_ENDIAN);
SetRegister(Arm.REG_C1_C0_2, GetRegister(Arm.REG_C1_C0_2) | 0xf00000);
SetRegister(Arm.REG_FPEXC, 0x40000000);
SetRegister(Arm.UC_ARM_REG_C1_C0_2, GetRegister(Arm.UC_ARM_REG_C1_C0_2) | 0xf00000);
SetRegister(Arm.UC_ARM_REG_FPEXC, 0x40000000);
}
~UnicornAArch32()
@@ -122,14 +105,15 @@ namespace Ryujinx.Tests.Unicorn
{
if (!_isDisposed)
{
Interface.Checked(Interface.uc_close(uc));
uc.Close();
_isDisposed = true;
}
}
public void RunForCount(ulong count)
{
Interface.Checked(Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
// FIXME: untilAddr should be 0xFFFFFFFFFFFFFFFFu
uc.EmuStart(this.PC, -1, 0, (long)count);
}
public void Step()
@@ -137,44 +121,44 @@ namespace Ryujinx.Tests.Unicorn
RunForCount(1);
}
private static Arm[] XRegisters = new Arm[16]
private static int[] XRegisters =
{
Arm.REG_R0,
Arm.REG_R1,
Arm.REG_R2,
Arm.REG_R3,
Arm.REG_R4,
Arm.REG_R5,
Arm.REG_R6,
Arm.REG_R7,
Arm.REG_R8,
Arm.REG_R9,
Arm.REG_R10,
Arm.REG_R11,
Arm.REG_R12,
Arm.REG_R13,
Arm.REG_R14,
Arm.REG_R15,
Arm.UC_ARM_REG_R0,
Arm.UC_ARM_REG_R1,
Arm.UC_ARM_REG_R2,
Arm.UC_ARM_REG_R3,
Arm.UC_ARM_REG_R4,
Arm.UC_ARM_REG_R5,
Arm.UC_ARM_REG_R6,
Arm.UC_ARM_REG_R7,
Arm.UC_ARM_REG_R8,
Arm.UC_ARM_REG_R9,
Arm.UC_ARM_REG_R10,
Arm.UC_ARM_REG_R11,
Arm.UC_ARM_REG_R12,
Arm.UC_ARM_REG_R13,
Arm.UC_ARM_REG_R14,
Arm.UC_ARM_REG_R15,
};
private static Arm[] QRegisters = new Arm[16]
private static int[] QRegisters =
{
Arm.REG_Q0,
Arm.REG_Q1,
Arm.REG_Q2,
Arm.REG_Q3,
Arm.REG_Q4,
Arm.REG_Q5,
Arm.REG_Q6,
Arm.REG_Q7,
Arm.REG_Q8,
Arm.REG_Q9,
Arm.REG_Q10,
Arm.REG_Q11,
Arm.REG_Q12,
Arm.REG_Q13,
Arm.REG_Q14,
Arm.REG_Q15
Arm.UC_ARM_REG_Q0,
Arm.UC_ARM_REG_Q1,
Arm.UC_ARM_REG_Q2,
Arm.UC_ARM_REG_Q3,
Arm.UC_ARM_REG_Q4,
Arm.UC_ARM_REG_Q5,
Arm.UC_ARM_REG_Q6,
Arm.UC_ARM_REG_Q7,
Arm.UC_ARM_REG_Q8,
Arm.UC_ARM_REG_Q9,
Arm.UC_ARM_REG_Q10,
Arm.UC_ARM_REG_Q11,
Arm.UC_ARM_REG_Q12,
Arm.UC_ARM_REG_Q13,
Arm.UC_ARM_REG_Q14,
Arm.UC_ARM_REG_Q15
};
public uint GetX(int index)
@@ -205,7 +189,7 @@ namespace Ryujinx.Tests.Unicorn
}
// Getting quadword registers from Unicorn A32 seems to be broken, so we combine its 2 doubleword registers instead.
return GetVector((Arm)((int)Arm.REG_D0 + index * 2));
return GetVector(Arm.UC_ARM_REG_D0 + index * 2);
}
public void SetQ(int index, SimdValue value)
@@ -215,96 +199,85 @@ namespace Ryujinx.Tests.Unicorn
throw new ArgumentOutOfRangeException(nameof(index));
}
SetVector((Arm)((int)Arm.REG_D0 + index * 2), value);
SetVector(Arm.UC_ARM_REG_D0 + index * 2, value);
}
public uint GetRegister(Arm register)
public uint GetRegister(int register)
{
byte[] data = new byte[4];
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
uc.RegRead(register, data);
return (uint)BitConverter.ToInt32(data, 0);
return BitConverter.ToUInt32(data, 0);
}
public void SetRegister(Arm register, uint value)
public void SetRegister(int register, uint value)
{
byte[] data = BitConverter.GetBytes(value);
Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
uc.RegWrite(register, data);
}
public SimdValue GetVector(Arm register)
public SimdValue GetVector(int register)
{
byte[] data = new byte[8];
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
uc.RegRead(register, data);
ulong lo = BitConverter.ToUInt64(data, 0);
Interface.Checked(Interface.uc_reg_read(uc, (int)register + 1, data));
uc.RegRead(register + 1, data);
ulong hi = BitConverter.ToUInt64(data, 0);
return new SimdValue(lo, hi);
}
private void SetVector(Arm register, SimdValue value)
private void SetVector(int register, SimdValue value)
{
byte[] data = BitConverter.GetBytes(value.GetUInt64(0));
Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
uc.RegWrite(register, data);
data = BitConverter.GetBytes(value.GetUInt64(1));
Interface.Checked(Interface.uc_reg_write(uc, (int)register + 1, data));
uc.RegWrite(register + 1, data);
}
public byte[] MemoryRead(ulong address, ulong size)
{
byte[] value = new byte[size];
Interface.Checked(Interface.uc_mem_read(uc, address, value, size));
uc.MemRead((long)address, value);
return value;
}
public byte MemoryRead8(ulong address) => MemoryRead(address, 1)[0];
public UInt16 MemoryRead16(ulong address) => (UInt16)BitConverter.ToInt16(MemoryRead(address, 2), 0);
public UInt32 MemoryRead32(ulong address) => (UInt32)BitConverter.ToInt32(MemoryRead(address, 4), 0);
public UInt64 MemoryRead64(ulong address) => (UInt64)BitConverter.ToInt64(MemoryRead(address, 8), 0);
public ushort MemoryRead16(ulong address) => BitConverter.ToUInt16(MemoryRead(address, 2), 0);
public uint MemoryRead32(ulong address) => BitConverter.ToUInt32(MemoryRead(address, 4), 0);
public ulong MemoryRead64(ulong address) => BitConverter.ToUInt64(MemoryRead(address, 8), 0);
public void MemoryWrite(ulong address, byte[] value)
{
Interface.Checked(Interface.uc_mem_write(uc, address, value, (ulong)value.Length));
uc.MemWrite((long)address, value);
}
public void MemoryWrite8(ulong address, byte value) => MemoryWrite(address, new byte[] { value });
public void MemoryWrite16(ulong address, Int16 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite16(ulong address, UInt16 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, Int32 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, UInt32 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, Int64 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, UInt64 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite8(ulong address, byte value) => MemoryWrite(address, new[] { value });
public void MemoryWrite16(ulong address, short value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite16(ulong address, ushort value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, int value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, uint value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, long value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, ulong value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryMap(ulong address, ulong size, MemoryPermission permissions)
{
Interface.Checked(Interface.uc_mem_map(uc, address, size, (uint)permissions));
uc.MemMap((long)address, (long)size, (int)permissions);
}
public void MemoryUnmap(ulong address, ulong size)
{
Interface.Checked(Interface.uc_mem_unmap(uc, address, size));
uc.MemUnmap((long)address, (long)size);
}
public void MemoryProtect(ulong address, ulong size, MemoryPermission permissions)
{
Interface.Checked(Interface.uc_mem_protect(uc, address, size, (uint)permissions));
}
public static bool IsAvailable()
{
try
{
Interface.uc_version(out _, out _);
}
catch (DllNotFoundException) { }
return Interface.IsUnicornAvailable;
uc.MemProtect((long)address, (long)size, (int)permissions);
}
}
}

View File

@@ -1,68 +1,51 @@
using Ryujinx.Tests.Unicorn.Native;
using Ryujinx.Tests.Unicorn.Native.Const;
using System;
using UnicornEngine.Const;
namespace Ryujinx.Tests.Unicorn
{
public class UnicornAArch64 : IDisposable
{
internal readonly IntPtr uc;
private bool _isDisposed = false;
internal readonly UnicornEngine.Unicorn uc;
private bool _isDisposed;
public IndexedProperty<int, ulong> X
{
get
{
return new IndexedProperty<int, ulong>(
(int i) => GetX(i),
(int i, ulong value) => SetX(i, value));
}
}
public IndexedProperty<int, ulong> X => new(GetX, SetX);
public IndexedProperty<int, SimdValue> Q
{
get
{
return new IndexedProperty<int, SimdValue>(
(int i) => GetQ(i),
(int i, SimdValue value) => SetQ(i, value));
}
}
public IndexedProperty<int, SimdValue> Q => new(GetQ, SetQ);
public ulong LR
{
get => GetRegister(Arm64.REG_LR);
set => SetRegister(Arm64.REG_LR, value);
get => GetRegister(Arm64.UC_ARM64_REG_LR);
set => SetRegister(Arm64.UC_ARM64_REG_LR, value);
}
public ulong SP
{
get => GetRegister(Arm64.REG_SP);
set => SetRegister(Arm64.REG_SP, value);
get => GetRegister(Arm64.UC_ARM64_REG_SP);
set => SetRegister(Arm64.UC_ARM64_REG_SP, value);
}
public ulong PC
{
get => GetRegister(Arm64.REG_PC);
set => SetRegister(Arm64.REG_PC, value);
get => GetRegister(Arm64.UC_ARM64_REG_PC);
set => SetRegister(Arm64.UC_ARM64_REG_PC, value);
}
public uint Pstate
{
get => (uint)GetRegister(Arm64.REG_PSTATE);
set => SetRegister(Arm64.REG_PSTATE, (uint)value);
get => (uint)GetRegister(Arm64.UC_ARM64_REG_PSTATE);
set => SetRegister(Arm64.UC_ARM64_REG_PSTATE, value);
}
public int Fpcr
{
get => (int)GetRegister(Arm64.REG_FPCR);
set => SetRegister(Arm64.REG_FPCR, (uint)value);
get => (int)GetRegister(Arm64.UC_ARM64_REG_FPCR);
set => SetRegister(Arm64.UC_ARM64_REG_FPCR, (uint)value);
}
public int Fpsr
{
get => (int)GetRegister(Arm64.REG_FPSR);
set => SetRegister(Arm64.REG_FPSR, (uint)value);
get => (int)GetRegister(Arm64.UC_ARM64_REG_FPSR);
set => SetRegister(Arm64.UC_ARM64_REG_FPSR, (uint)value);
}
public bool OverflowFlag
@@ -91,9 +74,9 @@ namespace Ryujinx.Tests.Unicorn
public UnicornAArch64()
{
Interface.Checked(Interface.uc_open(Arch.ARM64, Mode.LITTLE_ENDIAN, out uc));
uc = new UnicornEngine.Unicorn(Common.UC_ARCH_ARM64, Common.UC_MODE_LITTLE_ENDIAN);
SetRegister(Arm64.REG_CPACR_EL1, 0x00300000);
SetRegister(Arm64.UC_ARM64_REG_CPACR_EL1, 0x00300000);
}
~UnicornAArch64()
@@ -111,14 +94,15 @@ namespace Ryujinx.Tests.Unicorn
{
if (!_isDisposed)
{
Interface.Checked(Interface.uc_close(uc));
uc.Close();
_isDisposed = true;
}
}
public void RunForCount(ulong count)
{
Interface.Checked(Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
// FIXME: untilAddr should be 0xFFFFFFFFFFFFFFFFul
uc.EmuStart((long)this.PC, -1, 0, (long)count);
}
public void Step()
@@ -126,75 +110,75 @@ namespace Ryujinx.Tests.Unicorn
RunForCount(1);
}
private static Arm64[] XRegisters = new Arm64[31]
private static int[] XRegisters =
{
Arm64.REG_X0,
Arm64.REG_X1,
Arm64.REG_X2,
Arm64.REG_X3,
Arm64.REG_X4,
Arm64.REG_X5,
Arm64.REG_X6,
Arm64.REG_X7,
Arm64.REG_X8,
Arm64.REG_X9,
Arm64.REG_X10,
Arm64.REG_X11,
Arm64.REG_X12,
Arm64.REG_X13,
Arm64.REG_X14,
Arm64.REG_X15,
Arm64.REG_X16,
Arm64.REG_X17,
Arm64.REG_X18,
Arm64.REG_X19,
Arm64.REG_X20,
Arm64.REG_X21,
Arm64.REG_X22,
Arm64.REG_X23,
Arm64.REG_X24,
Arm64.REG_X25,
Arm64.REG_X26,
Arm64.REG_X27,
Arm64.REG_X28,
Arm64.REG_X29,
Arm64.REG_X30,
Arm64.UC_ARM64_REG_X0,
Arm64.UC_ARM64_REG_X1,
Arm64.UC_ARM64_REG_X2,
Arm64.UC_ARM64_REG_X3,
Arm64.UC_ARM64_REG_X4,
Arm64.UC_ARM64_REG_X5,
Arm64.UC_ARM64_REG_X6,
Arm64.UC_ARM64_REG_X7,
Arm64.UC_ARM64_REG_X8,
Arm64.UC_ARM64_REG_X9,
Arm64.UC_ARM64_REG_X10,
Arm64.UC_ARM64_REG_X11,
Arm64.UC_ARM64_REG_X12,
Arm64.UC_ARM64_REG_X13,
Arm64.UC_ARM64_REG_X14,
Arm64.UC_ARM64_REG_X15,
Arm64.UC_ARM64_REG_X16,
Arm64.UC_ARM64_REG_X17,
Arm64.UC_ARM64_REG_X18,
Arm64.UC_ARM64_REG_X19,
Arm64.UC_ARM64_REG_X20,
Arm64.UC_ARM64_REG_X21,
Arm64.UC_ARM64_REG_X22,
Arm64.UC_ARM64_REG_X23,
Arm64.UC_ARM64_REG_X24,
Arm64.UC_ARM64_REG_X25,
Arm64.UC_ARM64_REG_X26,
Arm64.UC_ARM64_REG_X27,
Arm64.UC_ARM64_REG_X28,
Arm64.UC_ARM64_REG_X29,
Arm64.UC_ARM64_REG_X30,
};
private static Arm64[] QRegisters = new Arm64[32]
private static int[] QRegisters =
{
Arm64.REG_Q0,
Arm64.REG_Q1,
Arm64.REG_Q2,
Arm64.REG_Q3,
Arm64.REG_Q4,
Arm64.REG_Q5,
Arm64.REG_Q6,
Arm64.REG_Q7,
Arm64.REG_Q8,
Arm64.REG_Q9,
Arm64.REG_Q10,
Arm64.REG_Q11,
Arm64.REG_Q12,
Arm64.REG_Q13,
Arm64.REG_Q14,
Arm64.REG_Q15,
Arm64.REG_Q16,
Arm64.REG_Q17,
Arm64.REG_Q18,
Arm64.REG_Q19,
Arm64.REG_Q20,
Arm64.REG_Q21,
Arm64.REG_Q22,
Arm64.REG_Q23,
Arm64.REG_Q24,
Arm64.REG_Q25,
Arm64.REG_Q26,
Arm64.REG_Q27,
Arm64.REG_Q28,
Arm64.REG_Q29,
Arm64.REG_Q30,
Arm64.REG_Q31,
Arm64.UC_ARM64_REG_Q0,
Arm64.UC_ARM64_REG_Q1,
Arm64.UC_ARM64_REG_Q2,
Arm64.UC_ARM64_REG_Q3,
Arm64.UC_ARM64_REG_Q4,
Arm64.UC_ARM64_REG_Q5,
Arm64.UC_ARM64_REG_Q6,
Arm64.UC_ARM64_REG_Q7,
Arm64.UC_ARM64_REG_Q8,
Arm64.UC_ARM64_REG_Q9,
Arm64.UC_ARM64_REG_Q10,
Arm64.UC_ARM64_REG_Q11,
Arm64.UC_ARM64_REG_Q12,
Arm64.UC_ARM64_REG_Q13,
Arm64.UC_ARM64_REG_Q14,
Arm64.UC_ARM64_REG_Q15,
Arm64.UC_ARM64_REG_Q16,
Arm64.UC_ARM64_REG_Q17,
Arm64.UC_ARM64_REG_Q18,
Arm64.UC_ARM64_REG_Q19,
Arm64.UC_ARM64_REG_Q20,
Arm64.UC_ARM64_REG_Q21,
Arm64.UC_ARM64_REG_Q22,
Arm64.UC_ARM64_REG_Q23,
Arm64.UC_ARM64_REG_Q24,
Arm64.UC_ARM64_REG_Q25,
Arm64.UC_ARM64_REG_Q26,
Arm64.UC_ARM64_REG_Q27,
Arm64.UC_ARM64_REG_Q28,
Arm64.UC_ARM64_REG_Q29,
Arm64.UC_ARM64_REG_Q30,
Arm64.UC_ARM64_REG_Q31,
};
public ulong GetX(int index)
@@ -237,89 +221,78 @@ namespace Ryujinx.Tests.Unicorn
SetVector(QRegisters[index], value);
}
private ulong GetRegister(Arm64 register)
private ulong GetRegister(int register)
{
byte[] data = new byte[8];
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
uc.RegRead(register, data);
return (ulong)BitConverter.ToInt64(data, 0);
return BitConverter.ToUInt64(data, 0);
}
private void SetRegister(Arm64 register, ulong value)
private void SetRegister(int register, ulong value)
{
byte[] data = BitConverter.GetBytes(value);
Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
uc.RegWrite(register, data);
}
private SimdValue GetVector(Arm64 register)
private SimdValue GetVector(int register)
{
byte[] data = new byte[16];
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
uc.RegRead(register, data);
return new SimdValue(data);
}
private void SetVector(Arm64 register, SimdValue value)
private void SetVector(int register, SimdValue value)
{
byte[] data = value.ToArray();
Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
uc.RegWrite(register, data);
}
public byte[] MemoryRead(ulong address, ulong size)
{
byte[] value = new byte[size];
Interface.Checked(Interface.uc_mem_read(uc, address, value, size));
uc.MemRead((long)address, value);
return value;
}
public byte MemoryRead8 (ulong address) => MemoryRead(address, 1)[0];
public UInt16 MemoryRead16(ulong address) => (UInt16)BitConverter.ToInt16(MemoryRead(address, 2), 0);
public UInt32 MemoryRead32(ulong address) => (UInt32)BitConverter.ToInt32(MemoryRead(address, 4), 0);
public UInt64 MemoryRead64(ulong address) => (UInt64)BitConverter.ToInt64(MemoryRead(address, 8), 0);
public ushort MemoryRead16(ulong address) => BitConverter.ToUInt16(MemoryRead(address, 2), 0);
public uint MemoryRead32(ulong address) => BitConverter.ToUInt32(MemoryRead(address, 4), 0);
public ulong MemoryRead64(ulong address) => BitConverter.ToUInt64(MemoryRead(address, 8), 0);
public void MemoryWrite(ulong address, byte[] value)
{
Interface.Checked(Interface.uc_mem_write(uc, address, value, (ulong)value.Length));
uc.MemWrite((long)address, value);
}
public void MemoryWrite8 (ulong address, byte value) => MemoryWrite(address, new byte[]{value});
public void MemoryWrite16(ulong address, Int16 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite16(ulong address, UInt16 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, Int32 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, UInt32 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, Int64 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, UInt64 value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite8 (ulong address, byte value) => MemoryWrite(address, new[]{ value });
public void MemoryWrite16(ulong address, short value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite16(ulong address, ushort value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, int value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite32(ulong address, uint value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, long value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryWrite64(ulong address, ulong value) => MemoryWrite(address, BitConverter.GetBytes(value));
public void MemoryMap(ulong address, ulong size, MemoryPermission permissions)
{
Interface.Checked(Interface.uc_mem_map(uc, address, size, (uint)permissions));
uc.MemMap((long)address, (long)size, (int)permissions);
}
public void MemoryUnmap(ulong address, ulong size)
{
Interface.Checked(Interface.uc_mem_unmap(uc, address, size));
uc.MemUnmap((long)address, (long)size);
}
public void MemoryProtect(ulong address, ulong size, MemoryPermission permissions)
{
Interface.Checked(Interface.uc_mem_protect(uc, address, size, (uint)permissions));
}
public static bool IsAvailable()
{
try
{
Interface.uc_version(out _, out _);
}
catch (DllNotFoundException) { }
return Interface.IsUnicornAvailable;
uc.MemProtect((long)address, (long)size, (int)permissions);
}
}
}

View File

@@ -1,24 +0,0 @@
using Ryujinx.Tests.Unicorn.Native.Const;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Tests.Unicorn
{
public class UnicornException : Exception
{
public readonly Error Error;
internal UnicornException(Error error)
{
Error = error;
}
public override string Message
{
get
{
return Marshal.PtrToStringAnsi(Native.Interface.uc_strerror(Error));
}
}
}
}

View File

@@ -1,20 +0,0 @@
# Unicorn
Unicorn is a CPU simulator with bindings in many languages, including
C#/.NET.
It is used by the Ryujinx test suite for comparative testing with its built-in
CPU simulator, Armeilleure.
## Windows
On Windows, Unicorn is shipped as a pre-compiled dynamic library (`.dll`), licenced under the GPLv2.
The source code for `windows/unicorn.dll` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698
## Linux
On Windows, Unicorn is shipped as a pre-compiled shared object (`.so`), licenced under the GPLv2.
The source code for `linux/unicorn.so` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698
See https://github.com/Ryujinx/Ryujinx/pull/1433 for details.

View File

@@ -1,199 +0,0 @@
#!/usr/bin/env python3
# Unicorn Engine
# By Dang Hoang Vu, 2013
# Modified for Ryujinx from: https://github.com/unicorn-engine/unicorn/blob/6c1cbef6ac505d355033aef1176b684d02e1eb3a/bindings/const_generator.py
from __future__ import print_function
import sys, re, os
include = [ 'arm.h', 'arm64.h', 'unicorn.h' ]
split_common = [ 'ARCH', 'MODE', 'ERR', 'MEM', 'TCG', 'HOOK', 'PROT' ]
template = {
'dotnet': {
'header': "// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\n// ReSharper disable InconsistentNaming\nnamespace Ryujinx.Tests.Unicorn.Native.Const\n{\n public enum %s\n {\n",
'footer': " }\n}\n",
'line_format': ' %s = %s,\n',
'out_file': os.path.join(os.path.dirname(__file__), 'Native', 'Const', '%s.cs'),
# prefixes for constant filenames of all archs - case sensitive
'arm.h': 'Arm',
'arm64.h': 'Arm64',
'unicorn.h': 'Common',
# prefixes for filenames of split_common values - case sensitive
'ARCH': 'Arch',
'MODE': 'Mode',
'ERR': 'Error',
'MEM': 'Memory',
'TCG': 'TCG',
'HOOK': 'Hook',
'PROT': 'Permission',
'comment_open': ' //',
'comment_close': '',
}
}
# markup for comments to be added to autogen files
MARKUP = '//>'
def gen(unicorn_repo_path):
global include
include_dir = os.path.join(unicorn_repo_path, 'include', 'unicorn')
templ = template["dotnet"]
for target in include:
prefix = templ[target]
outfile = open(templ['out_file'] %(prefix), 'wb') # open as binary prevents windows newlines
outfile.write((templ['header'] % (prefix)).encode("utf-8"))
if target == 'unicorn.h':
prefix = ''
for cat in split_common:
with open(templ['out_file'] %(templ[cat]), 'wb') as file:
file.write((templ['header'] %(templ[cat])).encode("utf-8"))
with open(os.path.join(include_dir, target)) as f:
lines = f.readlines()
previous = {}
count = 0
skip = 0
in_comment = False
for lno, line in enumerate(lines):
if "/*" in line:
in_comment = True
if "*/" in line:
in_comment = False
if in_comment:
continue
if skip > 0:
# Due to clang-format, values may come up in the next line
skip -= 1
continue
line = line.strip()
if line.startswith(MARKUP): # markup for comments
outfile.write(("\n%s%s%s\n" %(templ['comment_open'], \
line.replace(MARKUP, ''), templ['comment_close'])).encode("utf-8"))
continue
if line == '' or line.startswith('//'):
continue
tmp = line.strip().split(',')
if len(tmp) >= 2 and tmp[0] != "#define" and not tmp[0].startswith("UC_"):
continue
for t in tmp:
t = t.strip()
if not t or t.startswith('//'): continue
f = re.split('\s+', t)
# parse #define UC_TARGET (num)
define = False
if f[0] == '#define' and len(f) >= 3:
define = True
f.pop(0)
f.insert(1, '=')
if f[0].startswith("UC_" + prefix.upper()) or f[0].startswith("UC_CPU"):
if len(f) > 1 and f[1] not in ('//', '='):
print("WARNING: Unable to convert %s" % f)
print(" Line =", line)
continue
elif len(f) > 1 and f[1] == '=':
# Like:
# UC_A =
# (1 << 2)
# #define UC_B \
# (UC_A | UC_C)
# Let's search the next line
if len(f) == 2:
if lno == len(lines) - 1:
print("WARNING: Unable to convert %s" % f)
print(" Line =", line)
continue
skip += 1
next_line = lines[lno + 1]
next_line_tmp = next_line.strip().split(",")
rhs = next_line_tmp[0]
elif f[-1] == "\\":
idx = 0
rhs = ""
while True:
idx += 1
if lno + idx == len(lines):
print("WARNING: Unable to convert %s" % f)
print(" Line =", line)
continue
skip += 1
next_line = lines[lno + idx]
next_line_f = re.split('\s+', next_line.strip())
if next_line_f[-1] == "\\":
rhs += "".join(next_line_f[:-1])
else:
rhs += next_line.strip()
break
else:
rhs = ''.join(f[2:])
else:
rhs = str(count)
lhs = f[0].strip()
#print(f'lhs: {lhs} rhs: {rhs} f:{f}')
# evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1"
match = re.match(r'(?P<rhs>\s*\d+\s*<<\s*\d+\s*)', rhs)
if match:
rhs = str(eval(match.group(1)))
else:
# evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP"
match = re.match(r'^([^\d]\w+)$', rhs)
if match:
rhs = previous[match.group(1)]
if not rhs.isdigit():
for k, v in previous.items():
rhs = re.sub(r'\b%s\b' % k, v, rhs)
rhs = str(eval(rhs))
lhs_strip = re.sub(r'^UC_', '', lhs)
count = int(rhs) + 1
if target == "unicorn.h":
matched_cat = False
for cat in split_common:
if lhs_strip.startswith(f"{cat}_"):
with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file:
cat_lhs_strip = lhs_strip
if not lhs_strip.lstrip(f"{cat}_").isnumeric():
cat_lhs_strip = lhs_strip.replace(f"{cat}_", "", 1)
cat_file.write(
(templ['line_format'] % (cat_lhs_strip, rhs)).encode("utf-8"))
matched_cat = True
break
if matched_cat:
previous[lhs] = str(rhs)
continue
if (count == 1):
outfile.write(("\n").encode("utf-8"))
if lhs_strip.startswith(f"{prefix.upper()}_") and not lhs_strip.replace(f"{prefix.upper()}_", "", 1).isnumeric():
lhs_strip = lhs_strip.replace(f"{prefix.upper()}_", "", 1)
outfile.write((templ['line_format'] % (lhs_strip, rhs)).encode("utf-8"))
previous[lhs] = str(rhs)
outfile.write((templ['footer']).encode("utf-8"))
outfile.close()
if target == "unicorn.h":
for cat in split_common:
with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file:
cat_file.write(templ['footer'].encode('utf-8'))
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage:", sys.argv[0], " <path to unicorn repo>")
sys.exit(1)
unicorn_repo_path = sys.argv[1]
if os.path.isdir(unicorn_repo_path):
print("Generating constants for dotnet")
gen(unicorn_repo_path)
else:
print("Couldn't find unicorn repo at:", unicorn_repo_path)

View File

@@ -6,7 +6,6 @@ using Ryujinx.Cpu.Jit;
using Ryujinx.Memory;
using Ryujinx.Tests.Unicorn;
using System;
using MemoryPermission = Ryujinx.Tests.Unicorn.MemoryPermission;
namespace Ryujinx.Tests.Cpu
@@ -33,18 +32,10 @@ namespace Ryujinx.Tests.Cpu
private CpuContext _cpuContext;
private static bool _unicornAvailable;
private UnicornAArch64 _unicornEmu;
private bool _usingMemory;
[OneTimeSetUp]
public void OneTimeSetup()
{
_unicornAvailable = UnicornAArch64.IsAvailable();
Assume.That(_unicornAvailable, "Unicorn is not available");
}
[SetUp]
public void Setup()
{
@@ -65,23 +56,17 @@ namespace Ryujinx.Tests.Cpu
Optimizations.AllowLcqInFunctionTable = false;
Optimizations.UseUnmanagedDispatchLoop = false;
if (_unicornAvailable)
{
_unicornEmu = new UnicornAArch64();
_unicornEmu.MemoryMap(CodeBaseAddress, Size, MemoryPermission.READ | MemoryPermission.EXEC);
_unicornEmu.MemoryMap(DataBaseAddress, Size, MemoryPermission.READ | MemoryPermission.WRITE);
_unicornEmu.PC = CodeBaseAddress;
}
_unicornEmu = new UnicornAArch64();
_unicornEmu.MemoryMap(CodeBaseAddress, Size, MemoryPermission.Read | MemoryPermission.Exec);
_unicornEmu.MemoryMap(DataBaseAddress, Size, MemoryPermission.Read | MemoryPermission.Write);
_unicornEmu.PC = CodeBaseAddress;
}
[TearDown]
public void Teardown()
{
if (_unicornAvailable)
{
_unicornEmu.Dispose();
_unicornEmu = null;
}
_unicornEmu.Dispose();
_unicornEmu = null;
_memory.DecrementReferenceCount();
_context.Dispose();
@@ -105,10 +90,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(_currAddress, opcode);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite32(_currAddress, opcode);
}
_unicornEmu.MemoryWrite32(_currAddress, opcode);
_currAddress += 4;
}
@@ -158,38 +140,35 @@ namespace Ryujinx.Tests.Cpu
_context.Fpcr = (FPCR)fpcr;
_context.Fpsr = (FPSR)fpsr;
if (_unicornAvailable)
{
_unicornEmu.X[0] = x0;
_unicornEmu.X[1] = x1;
_unicornEmu.X[2] = x2;
_unicornEmu.X[3] = x3;
_unicornEmu.SP = x31;
_unicornEmu.X[0] = x0;
_unicornEmu.X[1] = x1;
_unicornEmu.X[2] = x2;
_unicornEmu.X[3] = x3;
_unicornEmu.SP = x31;
_unicornEmu.Q[0] = V128ToSimdValue(v0);
_unicornEmu.Q[1] = V128ToSimdValue(v1);
_unicornEmu.Q[2] = V128ToSimdValue(v2);
_unicornEmu.Q[3] = V128ToSimdValue(v3);
_unicornEmu.Q[4] = V128ToSimdValue(v4);
_unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[30] = V128ToSimdValue(v30);
_unicornEmu.Q[31] = V128ToSimdValue(v31);
_unicornEmu.Q[0] = V128ToSimdValue(v0);
_unicornEmu.Q[1] = V128ToSimdValue(v1);
_unicornEmu.Q[2] = V128ToSimdValue(v2);
_unicornEmu.Q[3] = V128ToSimdValue(v3);
_unicornEmu.Q[4] = V128ToSimdValue(v4);
_unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[30] = V128ToSimdValue(v30);
_unicornEmu.Q[31] = V128ToSimdValue(v31);
_unicornEmu.OverflowFlag = overflow;
_unicornEmu.CarryFlag = carry;
_unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative;
_unicornEmu.OverflowFlag = overflow;
_unicornEmu.CarryFlag = carry;
_unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative;
_unicornEmu.Fpcr = fpcr;
_unicornEmu.Fpsr = fpsr;
}
_unicornEmu.Fpcr = fpcr;
_unicornEmu.Fpsr = fpsr;
}
protected void ExecuteOpcodes(bool runUnicorn = true)
{
_cpuContext.Execute(_context, CodeBaseAddress);
if (_unicornAvailable && runUnicorn)
if (runUnicorn)
{
_unicornEmu.RunForCount((_currAddress - CodeBaseAddress - 4) / 4);
}
@@ -239,10 +218,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(DataBaseAddress + offset, data);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite(DataBaseAddress + offset, data);
}
_unicornEmu.MemoryWrite(DataBaseAddress + offset, data);
_usingMemory = true; // When true, CompareAgainstUnicorn checks the working memory for equality too.
}
@@ -251,10 +227,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(DataBaseAddress + offset, data);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite8(DataBaseAddress + offset, data);
}
_unicornEmu.MemoryWrite8(DataBaseAddress + offset, data);
_usingMemory = true; // When true, CompareAgainstUnicorn checks the working memory for equality too.
}
@@ -331,11 +304,6 @@ namespace Ryujinx.Tests.Cpu
FpSkips fpSkips = FpSkips.None,
FpTolerances fpTolerances = FpTolerances.None)
{
if (!_unicornAvailable)
{
return;
}
if (IgnoreAllExcept_FpsrQc)
{
fpsrMask &= Fpsr.Qc;

View File

@@ -6,7 +6,6 @@ using Ryujinx.Cpu.Jit;
using Ryujinx.Memory;
using Ryujinx.Tests.Unicorn;
using System;
using MemoryPermission = Ryujinx.Tests.Unicorn.MemoryPermission;
namespace Ryujinx.Tests.Cpu
@@ -27,19 +26,10 @@ namespace Ryujinx.Tests.Cpu
private ExecutionContext _context;
private CpuContext _cpuContext;
private static bool _unicornAvailable;
private UnicornAArch32 _unicornEmu;
private bool _usingMemory;
[OneTimeSetUp]
public void OneTimeSetup()
{
_unicornAvailable = UnicornAArch32.IsAvailable();
Assume.That(_unicornAvailable, "Unicorn is not available");
}
[SetUp]
public void Setup()
{
@@ -61,23 +51,17 @@ namespace Ryujinx.Tests.Cpu
Optimizations.AllowLcqInFunctionTable = false;
Optimizations.UseUnmanagedDispatchLoop = false;
if (_unicornAvailable)
{
_unicornEmu = new UnicornAArch32();
_unicornEmu.MemoryMap(CodeBaseAddress, Size, MemoryPermission.READ | MemoryPermission.EXEC);
_unicornEmu.MemoryMap(DataBaseAddress, Size, MemoryPermission.READ | MemoryPermission.WRITE);
_unicornEmu.PC = CodeBaseAddress;
}
_unicornEmu = new UnicornAArch32();
_unicornEmu.MemoryMap(CodeBaseAddress, Size, MemoryPermission.Read | MemoryPermission.Exec);
_unicornEmu.MemoryMap(DataBaseAddress, Size, MemoryPermission.Read | MemoryPermission.Write);
_unicornEmu.PC = CodeBaseAddress;
}
[TearDown]
public void Teardown()
{
if (_unicornAvailable)
{
_unicornEmu.Dispose();
_unicornEmu = null;
}
_unicornEmu.Dispose();
_unicornEmu = null;
_memory.DecrementReferenceCount();
_context.Dispose();
@@ -101,10 +85,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(_currAddress, opcode);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite32(_currAddress, opcode);
}
_unicornEmu.MemoryWrite32(_currAddress, opcode);
_currAddress += 4;
}
@@ -113,10 +94,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(_currAddress, opcode);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite16(_currAddress, opcode);
}
_unicornEmu.MemoryWrite16(_currAddress, opcode);
_currAddress += 2;
}
@@ -169,40 +147,37 @@ namespace Ryujinx.Tests.Cpu
_context.SetPstateFlag(PState.TFlag, thumb);
if (_unicornAvailable)
{
_unicornEmu.R[0] = r0;
_unicornEmu.R[1] = r1;
_unicornEmu.R[2] = r2;
_unicornEmu.R[3] = r3;
_unicornEmu.SP = sp;
_unicornEmu.R[0] = r0;
_unicornEmu.R[1] = r1;
_unicornEmu.R[2] = r2;
_unicornEmu.R[3] = r3;
_unicornEmu.SP = sp;
_unicornEmu.Q[0] = V128ToSimdValue(v0);
_unicornEmu.Q[1] = V128ToSimdValue(v1);
_unicornEmu.Q[2] = V128ToSimdValue(v2);
_unicornEmu.Q[3] = V128ToSimdValue(v3);
_unicornEmu.Q[4] = V128ToSimdValue(v4);
_unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[14] = V128ToSimdValue(v14);
_unicornEmu.Q[15] = V128ToSimdValue(v15);
_unicornEmu.Q[0] = V128ToSimdValue(v0);
_unicornEmu.Q[1] = V128ToSimdValue(v1);
_unicornEmu.Q[2] = V128ToSimdValue(v2);
_unicornEmu.Q[3] = V128ToSimdValue(v3);
_unicornEmu.Q[4] = V128ToSimdValue(v4);
_unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[14] = V128ToSimdValue(v14);
_unicornEmu.Q[15] = V128ToSimdValue(v15);
_unicornEmu.QFlag = saturation;
_unicornEmu.OverflowFlag = overflow;
_unicornEmu.CarryFlag = carry;
_unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative;
_unicornEmu.QFlag = saturation;
_unicornEmu.OverflowFlag = overflow;
_unicornEmu.CarryFlag = carry;
_unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative;
_unicornEmu.Fpscr = fpscr;
_unicornEmu.Fpscr = fpscr;
_unicornEmu.ThumbFlag = thumb;
}
_unicornEmu.ThumbFlag = thumb;
}
protected void ExecuteOpcodes(bool runUnicorn = true)
{
_cpuContext.Execute(_context, CodeBaseAddress);
if (_unicornAvailable && runUnicorn)
if (runUnicorn)
{
_unicornEmu.RunForCount((_currAddress - CodeBaseAddress - 4) / 4);
}
@@ -322,10 +297,7 @@ namespace Ryujinx.Tests.Cpu
{
_memory.Write(DataBaseAddress + offset, data);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite(DataBaseAddress + offset, data);
}
_unicornEmu.MemoryWrite(DataBaseAddress + offset, data);
_usingMemory = true; // When true, CompareAgainstUnicorn checks the working memory for equality too.
}
@@ -407,11 +379,6 @@ namespace Ryujinx.Tests.Cpu
FpSkips fpSkips = FpSkips.None,
FpTolerances fpTolerances = FpTolerances.None)
{
if (!_unicornAvailable)
{
return;
}
if (fpSkips != FpSkips.None)
{
ManageFpSkips(fpSkips);

View File

@@ -1,7 +1,6 @@
#define Alu
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -91,12 +90,10 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[Test, Pairwise, Description("CLS <Xd>, <Xn>")]
public void Cls_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_GenLeadingSignsX_")] [Random(RndCnt)] ulong xn)
[ValueSource(nameof(_GenLeadingSignsX_))] ulong xn)
{
uint opcode = 0xDAC01400; // CLS X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -111,7 +108,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLS <Wd>, <Wn>")]
public void Cls_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_GenLeadingSignsW_")] [Random(RndCnt)] uint wn)
[ValueSource(nameof(_GenLeadingSignsW_))] uint wn)
{
uint opcode = 0x5AC01400; // CLS W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -126,7 +123,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLZ <Xd>, <Xn>")]
public void Clz_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_GenLeadingZerosX_")] [Random(RndCnt)] ulong xn)
[ValueSource(nameof(_GenLeadingZerosX_))] ulong xn)
{
uint opcode = 0xDAC01000; // CLZ X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -141,7 +138,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CLZ <Wd>, <Wn>")]
public void Clz_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_GenLeadingZerosW_")] [Random(RndCnt)] uint wn)
[ValueSource(nameof(_GenLeadingZerosW_))] uint wn)
{
uint opcode = 0x5AC01000; // CLZ W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -157,7 +154,7 @@ namespace Ryujinx.Tests.Cpu
public void Rbit_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn)
{
uint opcode = 0xDAC00000; // RBIT X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -173,7 +170,7 @@ namespace Ryujinx.Tests.Cpu
public void Rbit_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
uint opcode = 0x5AC00000; // RBIT W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -189,7 +186,7 @@ namespace Ryujinx.Tests.Cpu
public void Rev16_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn)
{
uint opcode = 0xDAC00400; // REV16 X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -205,7 +202,7 @@ namespace Ryujinx.Tests.Cpu
public void Rev16_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
uint opcode = 0x5AC00400; // REV16 W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -221,7 +218,7 @@ namespace Ryujinx.Tests.Cpu
public void Rev32_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn)
{
uint opcode = 0xDAC00800; // REV32 X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -237,7 +234,7 @@ namespace Ryujinx.Tests.Cpu
public void Rev32_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
uint opcode = 0x5AC00800; // REV W0, W0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -253,7 +250,7 @@ namespace Ryujinx.Tests.Cpu
public void Rev64_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn)
{
uint opcode = 0xDAC00C00; // REV64 X0, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -266,4 +263,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _SU_H_AddSub_8_()
{
return new uint[]
return new[]
{
0xe6100f90u, // SADD8 R0, R0, R0
0xe6100ff0u, // SSUB8 R0, R0, R0
@@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Ssat_Usat_()
{
return new uint[]
return new[]
{
0xe6a00010u, // SSAT R0, #1, R0, LSL #0
0xe6a00050u, // SSAT R0, #1, R0, ASR #32
@@ -38,7 +38,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Ssat16_Usat16_()
{
return new uint[]
return new[]
{
0xe6a00f30u, // SSAT16 R0, #1, R0
0xe6e00f30u, // USAT16 R0, #0, R0
@@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Lsr_Lsl_Asr_Ror_()
{
return new uint[]
return new[]
{
0xe1b00030u, // LSRS R0, R0, R0
0xe1b00010u, // LSLS R0, R0, R0
@@ -63,7 +63,7 @@ namespace Ryujinx.Tests.Cpu
public void Rbit_32bit([Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
uint opcode = 0xe6ff0f30u; // RBIT R0, R0
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12);
@@ -76,10 +76,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Lsr_Lsl_Asr_Ror([ValueSource("_Lsr_Lsl_Asr_Ror_")] uint opcode,
public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(_Lsr_Lsl_Asr_Ror_))] uint opcode,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount)
0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
[Range(0, 31)] int shiftAmount)
{
uint rd = 0;
uint rm = 1;
@@ -130,13 +130,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode,
public void Ssat_Usat([ValueSource(nameof(_Ssat_Usat_))] uint opcode,
[Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint shift,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
opcode |= ((rn & 15) << 0) | ((shift & 31) << 7) | ((rd & 15) << 12) | ((sat & 31) << 16);
@@ -148,12 +148,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Ssat16_Usat16([ValueSource("_Ssat16_Usat16_")] uint opcode,
public void Ssat16_Usat16([ValueSource(nameof(_Ssat16_Usat16_))] uint opcode,
[Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu)] uint sat,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
0x80000000u, 0xFFFFFFFFu)] uint wn)
{
opcode |= ((rn & 15) << 0) | ((rd & 15) << 12) | ((sat & 15) << 16);
@@ -165,7 +165,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_H_AddSub_8([ValueSource("_SU_H_AddSub_8_")] uint opcode,
public void SU_H_AddSub_8([ValueSource(nameof(_SU_H_AddSub_8_))] uint opcode,
[Values(0u, 0xdu)] uint rd,
[Values(1u)] uint rm,
[Values(2u)] uint rn,
@@ -206,4 +206,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Cpu
// - xor 0
// Only includes non-C variant, as the other can be tested with unicorn.
return new CrcTest[]
return new[]
{
new CrcTest(0x00000000u, 0x00_00_00_00_00_00_00_00u, false, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
new CrcTest(0x00000000u, 0x7f_ff_ff_ff_ff_ff_ff_ffu, false, 0x2d02ef8d, 0xbe2612ff, 0xdebb20e3, 0xa9de8355),
@@ -53,14 +53,12 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[Test, Combinatorial]
public void Crc32_b_h_w_x([Values(0u)] uint rd,
[Values(1u)] uint rn,
[Values(2u)] uint rm,
[Range(0u, 3u)] uint size,
[ValueSource("_CRC32_Test_Values_")] CrcTest test)
[ValueSource(nameof(_CRC32_Test_Values_))] CrcTest test)
{
uint opcode = 0x1AC04000; // CRC32B W0, W0, W0
@@ -85,11 +83,11 @@ namespace Ryujinx.Tests.Cpu
public void Crc32x([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((ulong)0x00_00_00_00_00_00_00_00,
(ulong)0x7F_FF_FF_FF_FF_FF_FF_FF,
(ulong)0x80_00_00_00_00_00_00_00,
(ulong)0xFF_FF_FF_FF_FF_FF_FF_FF)] [Random(RndCnt)] ulong xm)
0x80_00_00_00_00_00_00_00,
0xFF_FF_FF_FF_FF_FF_FF_FF)] ulong xm)
{
uint opcode = 0x9AC04C00; // CRC32X W0, W0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -105,9 +103,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32w([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((uint)0x00_00_00_00, (uint)0x7F_FF_FF_FF,
(uint)0x80_00_00_00, (uint)0xFF_FF_FF_FF)] [Random(RndCnt)] uint wm)
0x80_00_00_00, 0xFF_FF_FF_FF)] uint wm)
{
uint opcode = 0x1AC04800; // CRC32W W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -123,9 +121,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32h([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((ushort)0x00_00, (ushort)0x7F_FF,
(ushort)0x80_00, (ushort)0xFF_FF)] [Random(RndCnt)] ushort wm)
(ushort)0x80_00, (ushort)0xFF_FF)] ushort wm)
{
uint opcode = 0x1AC04400; // CRC32H W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -141,9 +139,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32b([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm)
(byte)0x80, (byte)0xFF)] byte wm)
{
uint opcode = 0x1AC04000; // CRC32B W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -159,11 +157,11 @@ namespace Ryujinx.Tests.Cpu
public void Crc32cx([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((ulong)0x00_00_00_00_00_00_00_00,
(ulong)0x7F_FF_FF_FF_FF_FF_FF_FF,
(ulong)0x80_00_00_00_00_00_00_00,
(ulong)0xFF_FF_FF_FF_FF_FF_FF_FF)] [Random(RndCnt)] ulong xm)
0x80_00_00_00_00_00_00_00,
0xFF_FF_FF_FF_FF_FF_FF_FF)] ulong xm)
{
uint opcode = 0x9AC05C00; // CRC32CX W0, W0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -179,9 +177,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32cw([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((uint)0x00_00_00_00, (uint)0x7F_FF_FF_FF,
(uint)0x80_00_00_00, (uint)0xFF_FF_FF_FF)] [Random(RndCnt)] uint wm)
0x80_00_00_00, 0xFF_FF_FF_FF)] uint wm)
{
uint opcode = 0x1AC05800; // CRC32CW W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -197,9 +195,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32ch([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((ushort)0x00_00, (ushort)0x7F_FF,
(ushort)0x80_00, (ushort)0xFF_FF)] [Random(RndCnt)] ushort wm)
(ushort)0x80_00, (ushort)0xFF_FF)] ushort wm)
{
uint opcode = 0x1AC05400; // CRC32CH W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -215,9 +213,9 @@ namespace Ryujinx.Tests.Cpu
public void Crc32cb([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0xFFFFFFFFu)] uint wn,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm)
(byte)0x80, (byte)0xFF)] byte wm)
{
uint opcode = 0x1AC05000; // CRC32CB W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -234,9 +232,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC00C00; // SDIV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -253,9 +251,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC00C00; // SDIV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -272,9 +270,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC00800; // UDIV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -291,9 +289,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC00800; // UDIV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -306,4 +304,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Cpu
// - bytes in order of increasing significance
// - xor 0
return new CrcTest32[]
return new[]
{
new CrcTest32(0x00000000u, 0x00_00_00_00u, false, 0x00000000, 0x00000000, 0x00000000),
new CrcTest32(0x00000000u, 0x7f_ff_ff_ffu, false, 0x2d02ef8d, 0xbe2612ff, 0x3303a3c3),
@@ -70,7 +70,7 @@ namespace Ryujinx.Tests.Cpu
[Values(1u)] uint rn,
[Values(2u)] uint rm,
[Range(0u, 2u)] uint size,
[ValueSource("_CRC32_Test_Values_")] CrcTest32 test)
[ValueSource(nameof(_CRC32_Test_Values_))] CrcTest32 test)
{
// Unicorn does not yet support 32bit crc instructions, so test against a known table of results/values.

View File

@@ -8,17 +8,13 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestAluImm : CpuTest
{
#if AluImm
private const int RndCnt = 2;
private const int RndCntImm = 2;
private const int RndCntImms = 2;
private const int RndCntImmr = 2;
[Test, Pairwise, Description("ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")]
public void Add_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0x91000000; // ADD X0, X0, #0, LSL #0
@@ -41,8 +37,8 @@ namespace Ryujinx.Tests.Cpu
public void Add_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0x11000000; // ADD W0, W0, #0, LSL #0
@@ -65,8 +61,8 @@ namespace Ryujinx.Tests.Cpu
public void Adds_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0xB1000000; // ADDS X0, X0, #0, LSL #0
@@ -89,8 +85,8 @@ namespace Ryujinx.Tests.Cpu
public void Adds_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0x31000000; // ADDS W0, W0, #0, LSL #0
@@ -113,9 +109,9 @@ namespace Ryujinx.Tests.Cpu
public void And_N1_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 62u)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] uint immr) // <imm>
{
uint opcode = 0x92400000; // AND X0, X0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -132,9 +128,9 @@ namespace Ryujinx.Tests.Cpu
public void And_N0_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0x92000000; // AND X0, X0, #0x100000001
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -151,9 +147,9 @@ namespace Ryujinx.Tests.Cpu
public void And_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0x12000000; // AND W0, W0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -170,9 +166,9 @@ namespace Ryujinx.Tests.Cpu
public void Ands_N1_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 62u)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] uint immr) // <imm>
{
uint opcode = 0xF2400000; // ANDS X0, X0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -189,9 +185,9 @@ namespace Ryujinx.Tests.Cpu
public void Ands_N0_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0xF2000000; // ANDS X0, X0, #0x100000001
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -208,9 +204,9 @@ namespace Ryujinx.Tests.Cpu
public void Ands_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0x72000000; // ANDS W0, W0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -227,9 +223,9 @@ namespace Ryujinx.Tests.Cpu
public void Eor_N1_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 62u)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] uint immr) // <imm>
{
uint opcode = 0xD2400000; // EOR X0, X0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -246,9 +242,9 @@ namespace Ryujinx.Tests.Cpu
public void Eor_N0_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0xD2000000; // EOR X0, X0, #0x100000001
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -265,9 +261,9 @@ namespace Ryujinx.Tests.Cpu
public void Eor_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0x52000000; // EOR W0, W0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -284,9 +280,9 @@ namespace Ryujinx.Tests.Cpu
public void Orr_N1_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 62u)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] uint immr) // <imm>
{
uint opcode = 0xB2400000; // ORR X0, X0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -303,9 +299,9 @@ namespace Ryujinx.Tests.Cpu
public void Orr_N0_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0xB2000000; // ORR X0, X0, #0x100000001
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -322,9 +318,9 @@ namespace Ryujinx.Tests.Cpu
public void Orr_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 30u)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] uint immr) // <imm>
{
uint opcode = 0x32000000; // ORR W0, W0, #0x1
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -341,8 +337,8 @@ namespace Ryujinx.Tests.Cpu
public void Sub_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0xD1000000; // SUB X0, X0, #0, LSL #0
@@ -365,8 +361,8 @@ namespace Ryujinx.Tests.Cpu
public void Sub_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0x51000000; // SUB W0, W0, #0, LSL #0
@@ -389,8 +385,8 @@ namespace Ryujinx.Tests.Cpu
public void Subs_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0xF1000000; // SUBS X0, X0, #0, LSL #0
@@ -413,8 +409,8 @@ namespace Ryujinx.Tests.Cpu
public void Subs_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint opcode = 0x71000000; // SUBS W0, W0, #0, LSL #0
@@ -434,4 +430,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _opcodes()
{
return new uint[]
return new[]
{
0xe2a00000u, // ADC R0, R0, #0
0xe2b00000u, // ADCS R0, R0, #0
@@ -33,10 +33,9 @@ namespace Ryujinx.Tests.Cpu
#endregion
private const int RndCnt = 2;
private const int RndCntAmount = 2;
[Test, Pairwise]
public void TestCpuTestAluImm32([ValueSource("_opcodes")] uint opcode,
public void TestCpuTestAluImm32([ValueSource(nameof(_opcodes))] uint opcode,
[Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Random(RndCnt)] uint imm,
@@ -53,4 +52,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,18 +8,15 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestAluRs : CpuTest
{
#if AluRs
private const int RndCnt = 2;
private const int RndCntAmount = 2;
private const int RndCntLsb = 2;
[Test, Pairwise, Description("ADC <Xd>, <Xn>, <Xm>")]
public void Adc_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values] bool carryIn)
{
uint opcode = 0x9A000000; // ADC X0, X0, X0
@@ -37,9 +34,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0x1A000000; // ADC W0, W0, W0
@@ -57,9 +54,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values] bool carryIn)
{
uint opcode = 0xBA000000; // ADCS X0, X0, X0
@@ -77,9 +74,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0x3A000000; // ADCS W0, W0, W0
@@ -97,11 +94,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0x8B000000; // ADD X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -119,11 +116,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x0B000000; // ADD W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -141,11 +138,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xAB000000; // ADDS X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -163,11 +160,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x2B000000; // ADDS W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -185,11 +182,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0x8A000000; // AND X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -207,11 +204,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x0A000000; // AND W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -229,11 +226,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xEA000000; // ANDS X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -251,11 +248,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x6A000000; // ANDS W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -273,9 +270,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0ul, 31ul, 32ul, 63ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC02800; // ASRV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -292,9 +289,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC02800; // ASRV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -311,11 +308,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0x8A200000; // BIC X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -333,11 +330,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x0A200000; // BIC W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -355,11 +352,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xEA200000; // BICS X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -377,11 +374,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x6A200000; // BICS W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -399,11 +396,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xCA200000; // EON X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -421,11 +418,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x4A200000; // EON W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -443,11 +440,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xCA000000; // EOR X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -465,11 +462,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x4A000000; // EOR W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -487,10 +484,10 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntLsb)] uint lsb)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0u, 31u, 32u, 63u)] uint lsb)
{
uint opcode = 0x93C00000; // EXTR X0, X0, X0, #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -508,10 +505,10 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntLsb)] uint lsb)
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0u, 15u, 16u, 31u)] uint lsb)
{
uint opcode = 0x13800000; // EXTR W0, W0, W0, #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -529,9 +526,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0ul, 31ul, 32ul, 63ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC02000; // LSLV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -548,9 +545,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC02000; // LSLV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -567,9 +564,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0ul, 31ul, 32ul, 63ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC02400; // LSRV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -586,9 +583,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC02400; // LSRV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -605,11 +602,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xAA200000; // ORN X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -627,11 +624,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x2A200000; // ORN W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -649,11 +646,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xAA000000; // ORR X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -671,11 +668,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x2A000000; // ORR W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -693,9 +690,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0ul, 31ul, 32ul, 63ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9AC02C00; // RORV X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -712,9 +709,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
uint opcode = 0x1AC02C00; // RORV W0, W0, W0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -731,9 +728,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values] bool carryIn)
{
uint opcode = 0xDA000000; // SBC X0, X0, X0
@@ -751,9 +748,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0x5A000000; // SBC W0, W0, W0
@@ -771,9 +768,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values] bool carryIn)
{
uint opcode = 0xFA000000; // SBCS X0, X0, X0
@@ -791,9 +788,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0x7A000000; // SBCS W0, W0, W0
@@ -811,11 +808,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xCB000000; // SUB X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -833,11 +830,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x4B000000; // SUB W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -855,11 +852,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntAmount)] uint amount)
[Values(0u, 31u, 32u, 63u)] uint amount)
{
uint opcode = 0xEB000000; // SUBS X0, X0, X0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -877,11 +874,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u)] uint shift, // <LSL, LSR, ASR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
uint opcode = 0x6B000000; // SUBS W0, W0, W0, LSL #0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -895,4 +892,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _Add_Adds_Rsb_Rsbs_()
{
return new uint[]
return new[]
{
0xe0800000u, // ADD R0, R0, R0, LSL #0
0xe0900000u, // ADDS R0, R0, R0, LSL #0
@@ -23,7 +23,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_()
{
return new uint[]
return new[]
{
0xe0a00000u, // ADC R0, R0, R0
0xe0b00000u, // ADCS R0, R0, R0
@@ -35,8 +35,6 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
private const int RndCntAmount = 2;
[Test, Pairwise]
public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource("_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_")] uint opcode,
@@ -44,9 +42,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values] bool carryIn)
{
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
@@ -64,11 +62,11 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
[Values(0u, 15u, 16u, 31u)] uint amount)
{
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
opcode |= ((shift & 3) << 5) | ((amount & 31) << 7);
@@ -81,4 +79,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,16 +8,15 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestAluRx : CpuTest
{
#if AluRx
private const int RndCnt = 2;
[Test, Pairwise, Description("ADD <Xd|SP>, <Xn|SP>, <X><m>{, <extend> {#<amount>}}")]
public void Add_X_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
(ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(RndCnt)] ulong xm,
0x8000000000000000, 0xFFFFFFFFFFFFFFFF)] ulong xm,
[Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
{
@@ -44,9 +43,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -74,9 +73,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -104,9 +103,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -134,9 +133,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -164,9 +163,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -194,9 +193,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -224,9 +223,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
(ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(RndCnt)] ulong xm,
0x8000000000000000, 0xFFFFFFFFFFFFFFFF)] ulong xm,
[Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
{
@@ -244,9 +243,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -265,9 +264,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -286,9 +285,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -307,9 +306,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -328,9 +327,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -349,9 +348,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -370,9 +369,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
(ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(RndCnt)] ulong xm,
0x8000000000000000, 0xFFFFFFFFFFFFFFFF)] ulong xm,
[Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
{
@@ -399,9 +398,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -429,9 +428,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -459,9 +458,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -489,9 +488,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -519,9 +518,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -549,9 +548,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -579,9 +578,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
(ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(RndCnt)] ulong xm,
0x8000000000000000, 0xFFFFFFFFFFFFFFFF)] ulong xm,
[Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
{
@@ -599,9 +598,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -620,9 +619,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -641,9 +640,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xnSp,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xnSp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -662,9 +661,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((uint)0x00000000, (uint)0x7FFFFFFF,
(uint)0x80000000, (uint)0xFFFFFFFF)] [Random(RndCnt)] uint wm,
0x80000000, 0xFFFFFFFF)] uint wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -683,9 +682,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((ushort)0x0000, (ushort)0x7FFF,
(ushort)0x8000, (ushort)0xFFFF)] [Random(RndCnt)] ushort wm,
(ushort)0x8000, (ushort)0xFFFF)] ushort wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -704,9 +703,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wnWsp,
0x80000000u, 0xFFFFFFFFu)] uint wnWsp,
[Values((byte)0x00, (byte)0x7F,
(byte)0x80, (byte)0xFF)] [Random(RndCnt)] byte wm,
(byte)0x80, (byte)0xFF)] byte wm,
[Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
[Values(0u, 1u, 2u, 3u, 4u)] uint amount)
@@ -721,4 +720,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -10,15 +10,13 @@ namespace Ryujinx.Tests.Cpu
{
#if Bf32
private const int RndCnt = 2;
private const int RndCntImmr = 2;
private const int RndCntImms = 2;
[Test, Pairwise, Description("BFC <Rd>, #<lsb>, #<width>")]
public void Bfc([Values(0u, 0xdu)] uint rd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wd,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb)
0x80000000u, 0xFFFFFFFFu)] uint wd,
[Values(0u, 15u, 16u, 31u)] uint lsb,
[Values(0u, 15u, 16u, 31u)] uint msb)
{
msb = Math.Max(lsb, msb); // Don't test unpredictable for now.
uint opcode = 0xe7c0001fu; // BFC R0, #0, #1
@@ -37,9 +35,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint lsb,
[Values(0u, 15u, 16u, 31u)] uint msb)
{
msb = Math.Max(lsb, msb); // Don't test unpredictable for now.
uint opcode = 0xe7c00010u; // BFI R0, R0, #0, #1
@@ -59,9 +57,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint lsb,
[Values(0u, 15u, 16u, 31u)] uint widthm1)
{
if (lsb + widthm1 > 31)
{
@@ -84,9 +82,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint lsb,
[Values(0u, 15u, 16u, 31u)] uint widthm1)
{
if (lsb + widthm1 > 31)
{
@@ -105,4 +103,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -9,17 +9,15 @@ namespace Ryujinx.Tests.Cpu
{
#if Bfm
private const int RndCnt = 2;
private const int RndCntImmr = 2;
private const int RndCntImms = 2;
[Test, Pairwise, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Bfm_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Random(RndCnt)] ulong xd,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 63u)] uint immr,
[Values(0u, 31u, 32u, 63u)] uint imms)
{
uint opcode = 0xB3400000; // BFM X0, X0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -37,9 +35,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint immr,
[Values(0u, 15u, 16u, 31u)] uint imms)
{
uint opcode = 0x33000000; // BFM W0, W0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -56,9 +54,9 @@ namespace Ryujinx.Tests.Cpu
public void Sbfm_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 63u)] uint immr,
[Values(0u, 31u, 32u, 63u)] uint imms)
{
uint opcode = 0x93400000; // SBFM X0, X0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -75,9 +73,9 @@ namespace Ryujinx.Tests.Cpu
public void Sbfm_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint immr,
[Values(0u, 15u, 16u, 31u)] uint imms)
{
uint opcode = 0x13000000; // SBFM W0, W0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -94,9 +92,9 @@ namespace Ryujinx.Tests.Cpu
public void Ubfm_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u, 32u, 63u)] uint immr,
[Values(0u, 31u, 32u, 63u)] uint imms)
{
uint opcode = 0xD3400000; // UBFM X0, X0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -113,9 +111,9 @@ namespace Ryujinx.Tests.Cpu
public void Ubfm_32bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 15u, 16u, 31u)] uint immr,
[Values(0u, 15u, 16u, 31u)] uint imms)
{
uint opcode = 0x53000000; // UBFM W0, W0, #0, #0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -129,4 +127,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,15 +8,13 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestCcmpImm : CpuTest
{
#if CcmpImm
private const int RndCnt = 2;
private const int RndCntImm = 2;
private const int RndCntNzcv = 2;
[Test, Pairwise, Description("CCMN <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -37,8 +35,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CCMN <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_32bit([Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 31u)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -59,8 +57,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CCMP <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_64bit([Values(1u, 31u)] uint rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 31u)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -81,8 +79,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("CCMP <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_32bit([Values(1u, 31u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 31u)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -101,4 +99,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,16 +8,15 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestCcmpReg : CpuTest
{
#if CcmpReg
private const int RndCnt = 2;
private const int RndCntNzcv = 2;
[Test, Pairwise, Description("CCMN <Xn>, <Xm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -39,9 +38,9 @@ namespace Ryujinx.Tests.Cpu
public void Ccmn_32bit([Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -63,9 +62,9 @@ namespace Ryujinx.Tests.Cpu
public void Ccmp_64bit([Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -87,9 +86,9 @@ namespace Ryujinx.Tests.Cpu
public void Ccmp_32bit([Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -108,4 +107,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,16 +8,15 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestCsel : CpuTest
{
#if Csel
private const int RndCnt = 2;
[Test, Pairwise, Description("CSEL <Xd>, <Xn>, <Xm>, <cond>")]
public void Csel_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -39,9 +38,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -63,9 +62,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -87,9 +86,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -111,9 +110,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -135,9 +134,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -159,9 +158,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -183,9 +182,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -203,4 +202,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define Misc
using ARMeilleure.State;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@@ -59,7 +57,6 @@ namespace Ryujinx.Tests.Cpu
#endregion
private const int RndCnt = 2;
private const int RndCntImm = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
@@ -68,8 +65,8 @@ namespace Ryujinx.Tests.Cpu
#region "AluImm & Csel"
[Test, Pairwise]
public void Adds_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift, // <LSL #0, LSL #12>
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -93,8 +90,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise]
public void Adds_Csinc_32bit([Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift, // <LSL #0, LSL #12>
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -118,8 +115,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise]
public void Subs_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift, // <LSL #0, LSL #12>
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -143,8 +140,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise]
public void Subs_Csinc_32bit([Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0u, 4095u)] uint imm,
[Values(0b00u, 0b01u)] uint shift, // <LSL #0, LSL #12>
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -412,9 +409,9 @@ namespace Ryujinx.Tests.Cpu
[Explicit]
[Test, Pairwise]
public void Misc4([ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
[ValueSource("_1S_F_")] ulong c,
public void Misc4([ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
[ValueSource(nameof(_1S_F_))] ulong c,
[Values(0ul, 1ul, 2ul, 3ul)] ulong displacement)
{
if (!BitConverter.IsLittleEndian)
@@ -460,7 +457,7 @@ namespace Ryujinx.Tests.Cpu
[Explicit]
[Test]
public void Misc5([ValueSource("_1S_F_")] ulong a)
public void Misc5([ValueSource(nameof(_1S_F_))] ulong a)
{
SetContext(
v0: MakeVectorE0E1(a, TestContext.CurrentContext.Random.NextULong()),
@@ -482,4 +479,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define Misc32
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -64,8 +62,8 @@ namespace Ryujinx.Tests.Cpu
private static readonly bool NoNaNs = false;
[Test, Pairwise]
public void Vmsr_Vcmp_Vmrs([ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
[Values] bool mode1,
[Values] bool mode2,
[Values] bool mode3)

View File

@@ -9,12 +9,11 @@ namespace Ryujinx.Tests.Cpu
{
#if Mov
private const int RndCnt = 2;
private const int RndCntImm = 2;
[Test, Pairwise, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")]
public void Movk_64bit([Values(0u, 31u)] uint rd,
[Random(RndCnt)] ulong xd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift)
{
uint opcode = 0xF2800000; // MOVK X0, #0, LSL #0
@@ -31,7 +30,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("MOVK <Wd>, #<imm>{, LSL #<shift>}")]
public void Movk_32bit([Values(0u, 31u)] uint rd,
[Random(RndCnt)] uint wd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u)] uint shift)
{
uint opcode = 0x72800000; // MOVK W0, #0, LSL #0
@@ -47,7 +46,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("MOVN <Xd>, #<imm>{, LSL #<shift>}")]
public void Movn_64bit([Values(0u, 31u)] uint rd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift)
{
uint opcode = 0x92800000; // MOVN X0, #0, LSL #0
@@ -63,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("MOVN <Wd>, #<imm>{, LSL #<shift>}")]
public void Movn_32bit([Values(0u, 31u)] uint rd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u)] uint shift)
{
uint opcode = 0x12800000; // MOVN W0, #0, LSL #0
@@ -79,7 +78,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("MOVZ <Xd>, #<imm>{, LSL #<shift>}")]
public void Movz_64bit([Values(0u, 31u)] uint rd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift)
{
uint opcode = 0xD2800000; // MOVZ X0, #0, LSL #0
@@ -95,7 +94,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("MOVZ <Wd>, #<imm>{, LSL #<shift>}")]
public void Movz_32bit([Values(0u, 31u)] uint rd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 65535u)] uint imm,
[Values(0u, 16u)] uint shift)
{
uint opcode = 0x52800000; // MOVZ W0, #0, LSL #0
@@ -110,4 +109,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -8,19 +8,17 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestMul : CpuTest
{
#if Mul
private const int RndCnt = 2;
[Test, Pairwise, Description("MADD <Xd>, <Xn>, <Xm>, <Xa>")]
public void Madd_64bit([Values(0u, 31u)] uint rd,
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9B000000; // MADD X0, X0, X0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -38,11 +36,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
0x80000000u, 0xFFFFFFFFu)] uint wa)
{
uint opcode = 0x1B000000; // MADD W0, W0, W0, W0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -60,11 +58,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9B008000; // MSUB X0, X0, X0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -82,11 +80,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
0x80000000u, 0xFFFFFFFFu)] uint wa)
{
uint opcode = 0x1B008000; // MSUB W0, W0, W0, W0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -104,11 +102,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9B200000; // SMADDL X0, W0, W0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -126,11 +124,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9BA00000; // UMADDL X0, W0, W0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -148,11 +146,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9B208000; // SMSUBL X0, W0, W0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -170,11 +168,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 31u)] uint rm,
[Values(3u, 31u)] uint ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xa)
{
uint opcode = 0x9BA08000; // UMSUBL X0, W0, W0, X0
opcode |= ((rm & 31) << 16) | ((ra & 31) << 10) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -191,9 +189,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9B407C00; // SMULH X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -210,9 +208,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 31u)] uint rn,
[Values(2u, 31u)] uint rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xm)
{
uint opcode = 0x9BC07C00; // UMULH X0, X0, X0
opcode |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -225,4 +223,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _Smlabb_Smlabt_Smlatb_Smlatt_()
{
return new uint[]
return new[]
{
0xe1000080u, // SMLABB R0, R0, R0, R0
0xe10000C0u, // SMLABT R0, R0, R0, R0
@@ -23,7 +23,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Smlawb_Smlawt_()
{
return new uint[]
return new[]
{
0xe1200080u, // SMLAWB R0, R0, R0, R0
0xe12000C0u, // SMLAWT R0, R0, R0, R0
@@ -32,7 +32,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Smulbb_Smulbt_Smultb_Smultt_()
{
return new uint[]
return new[]
{
0xe1600080u, // SMULBB R0, R0, R0
0xe16000C0u, // SMULBT R0, R0, R0
@@ -43,7 +43,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Smulwb_Smulwt_()
{
return new uint[]
return new[]
{
0xe12000a0u, // SMULWB R0, R0, R0
0xe12000e0u, // SMULWT R0, R0, R0
@@ -51,8 +51,6 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")]
public void Smla___32bit([ValueSource("_Smlabb_Smlabt_Smlatb_Smlatt_")] uint opcode,
[Values(0u, 0xdu)] uint rn,
@@ -60,11 +58,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 0xdu)] uint ra,
[Values(3u, 0xdu)] uint rd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
0x80000000u, 0xFFFFFFFFu)] uint wa)
{
opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((ra & 15) << 12) | ((rd & 15) << 16);
@@ -82,11 +80,11 @@ namespace Ryujinx.Tests.Cpu
[Values(2u, 0xdu)] uint ra,
[Values(3u, 0xdu)] uint rd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
0x80000000u, 0xFFFFFFFFu)] uint wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
0x80000000u, 0xFFFFFFFFu)] uint wa)
{
opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((ra & 15) << 12) | ((rd & 15) << 16);
@@ -103,9 +101,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((rd & 15) << 16);
@@ -122,9 +120,9 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rm,
[Values(2u, 0xdu)] uint rd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
0x80000000u, 0xFFFFFFFFu)] uint wm)
{
opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((rd & 15) << 16);
@@ -136,4 +134,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _Vabs_Vneg_Vpaddl_I_()
{
return new uint[]
return new[]
{
0xf3b10300u, // VABS.S8 D0, D0
0xf3b10380u, // VNEG.S8 D0, D0
@@ -24,7 +24,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vabs_Vneg_F_()
{
return new uint[]
return new[]
{
0xf3b90700u, // VABS.F32 D0, D0
0xf3b90780u // VNEG.F32 D0, D0
@@ -35,10 +35,10 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _8B4H2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<ulong> _1S_F_()
@@ -211,11 +211,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vabs_Vneg_Vpaddl_V_I([ValueSource("_Vabs_Vneg_Vpaddl_I_")] uint opcode,
public void Vabs_Vneg_Vpaddl_V_I([ValueSource(nameof(_Vabs_Vneg_Vpaddl_I_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S_))] ulong z,
[ValueSource(nameof(_8B4H2S_))] ulong b,
[Values(0u, 1u, 2u)] uint size, // <S8, S16, S32>
[Values] bool q)
{
@@ -241,11 +241,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vabs_Vneg_V_F32([ValueSource("_Vabs_Vneg_F_")] uint opcode,
public void Vabs_Vneg_V_F32([ValueSource(nameof(_Vabs_Vneg_F_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_2S_F_")] ulong z,
[ValueSource("_2S_F_")] ulong b,
[ValueSource(nameof(_2S_F_))] ulong z,
[ValueSource(nameof(_2S_F_))] ulong b,
[Values] bool q)
{
if (q)
@@ -270,7 +270,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VCNT.8 D0, D0 | VCNT.8 Q0, Q0")]
public void Vcnt([Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rm,
[ValueSource(nameof(_GenPopCnt8B_))] [Random(RndCnt)] ulong d0,
[ValueSource(nameof(_GenPopCnt8B_))] ulong d0,
[Values] bool q)
{
ulong d1 = ~d0; // It's expensive to have a second generator.
@@ -298,8 +298,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise]
public void Vmovn_V([Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S_))] ulong z,
[ValueSource(nameof(_8B4H2S_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint op,
[Values(0u, 1u, 2u)] uint size) // <S8, S16, S32>
{
@@ -322,4 +322,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define SimdCvt
using ARMeilleure.State;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@@ -17,14 +15,14 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static uint[] _W_()
{
return new uint[] { 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
return new[] { 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
}
private static ulong[] _X_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<ulong> _1S_F_WX_()
@@ -89,13 +87,13 @@ namespace Ryujinx.Tests.Cpu
ulong grbg = TestContext.CurrentContext.Random.NextUInt();
ulong rnd1 = (uint)BitConverter.SingleToInt32Bits(
(float)((int)TestContext.CurrentContext.Random.NextUInt()));
(int)TestContext.CurrentContext.Random.NextUInt());
ulong rnd2 = (uint)BitConverter.SingleToInt32Bits(
(float)((long)TestContext.CurrentContext.Random.NextULong()));
(long)TestContext.CurrentContext.Random.NextULong());
ulong rnd3 = (uint)BitConverter.SingleToInt32Bits(
(float)((uint)TestContext.CurrentContext.Random.NextUInt()));
TestContext.CurrentContext.Random.NextUInt());
ulong rnd4 = (uint)BitConverter.SingleToInt32Bits(
(float)((ulong)TestContext.CurrentContext.Random.NextULong()));
TestContext.CurrentContext.Random.NextULong());
ulong rnd5 = GenNormalS();
ulong rnd6 = GenSubnormalS();
@@ -170,13 +168,13 @@ namespace Ryujinx.Tests.Cpu
for (int cnt = 1; cnt <= RndCnt; cnt++)
{
ulong rnd1 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((int)TestContext.CurrentContext.Random.NextUInt()));
(int)TestContext.CurrentContext.Random.NextUInt());
ulong rnd2 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((long)TestContext.CurrentContext.Random.NextULong()));
(long)TestContext.CurrentContext.Random.NextULong());
ulong rnd3 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((uint)TestContext.CurrentContext.Random.NextUInt()));
TestContext.CurrentContext.Random.NextUInt());
ulong rnd4 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((ulong)TestContext.CurrentContext.Random.NextULong()));
TestContext.CurrentContext.Random.NextULong());
ulong rnd5 = GenNormalD();
ulong rnd6 = GenSubnormalD();
@@ -195,7 +193,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_AMPZ_SU_Gp_SW_()
{
return new uint[]
return new[]
{
0x1E240000u, // FCVTAS W0, S0
0x1E250000u, // FCVTAU W0, S0
@@ -211,7 +209,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_AMPZ_SU_Gp_SX_()
{
return new uint[]
return new[]
{
0x9E240000u, // FCVTAS X0, S0
0x9E250000u, // FCVTAU X0, S0
@@ -227,7 +225,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_AMPZ_SU_Gp_DW_()
{
return new uint[]
return new[]
{
0x1E640000u, // FCVTAS W0, D0
0x1E650000u, // FCVTAU W0, D0
@@ -243,7 +241,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_AMPZ_SU_Gp_DX_()
{
return new uint[]
return new[]
{
0x9E640000u, // FCVTAS X0, D0
0x9E650000u, // FCVTAU X0, D0
@@ -259,7 +257,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_Z_SU_Gp_Fixed_SW_()
{
return new uint[]
return new[]
{
0x1E188000u, // FCVTZS W0, S0, #32
0x1E198000u // FCVTZU W0, S0, #32
@@ -268,7 +266,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_Z_SU_Gp_Fixed_SX_()
{
return new uint[]
return new[]
{
0x9E180000u, // FCVTZS X0, S0, #64
0x9E190000u // FCVTZU X0, S0, #64
@@ -277,7 +275,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_Z_SU_Gp_Fixed_DW_()
{
return new uint[]
return new[]
{
0x1E588000u, // FCVTZS W0, D0, #32
0x1E598000u // FCVTZU W0, D0, #32
@@ -286,7 +284,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_Z_SU_Gp_Fixed_DX_()
{
return new uint[]
return new[]
{
0x9E580000u, // FCVTZS X0, D0, #64
0x9E590000u // FCVTZU X0, D0, #64
@@ -295,7 +293,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_WS_()
{
return new uint[]
return new[]
{
0x1E220000u, // SCVTF S0, W0
0x1E230000u // UCVTF S0, W0
@@ -304,7 +302,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_WD_()
{
return new uint[]
return new[]
{
0x1E620000u, // SCVTF D0, W0
0x1E630000u // UCVTF D0, W0
@@ -313,7 +311,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_XS_()
{
return new uint[]
return new[]
{
0x9E220000u, // SCVTF S0, X0
0x9E230000u // UCVTF S0, X0
@@ -322,7 +320,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_XD_()
{
return new uint[]
return new[]
{
0x9E620000u, // SCVTF D0, X0
0x9E630000u // UCVTF D0, X0
@@ -331,7 +329,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_Fixed_WS_()
{
return new uint[]
return new[]
{
0x1E028000u, // SCVTF S0, W0, #32
0x1E038000u // UCVTF S0, W0, #32
@@ -340,7 +338,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_Fixed_WD_()
{
return new uint[]
return new[]
{
0x1E428000u, // SCVTF D0, W0, #32
0x1E438000u // UCVTF D0, W0, #32
@@ -349,7 +347,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_Fixed_XS_()
{
return new uint[]
return new[]
{
0x9E020000u, // SCVTF S0, X0, #64
0x9E030000u // UCVTF S0, X0, #64
@@ -358,7 +356,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_Gp_Fixed_XD_()
{
return new uint[]
return new[]
{
0x9E420000u, // SCVTF D0, X0, #64
0x9E430000u // UCVTF D0, X0, #64
@@ -367,17 +365,16 @@ namespace Ryujinx.Tests.Cpu
#endregion
private const int RndCnt = 2;
private const int RndCntFBits = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
[Test, Pairwise] [Explicit]
public void F_Cvt_AMPZ_SU_Gp_SW([ValueSource("_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(1u)] uint rn,
[ValueSource("_1S_F_WX_")] ulong a)
[ValueSource(nameof(_1S_F_WX_))] ulong a)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -391,10 +388,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_AMPZ_SU_Gp_SX([ValueSource("_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(1u)] uint rn,
[ValueSource("_1S_F_WX_")] ulong a)
[ValueSource(nameof(_1S_F_WX_))] ulong a)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -407,10 +404,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_AMPZ_SU_Gp_DW([ValueSource("_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(1u)] uint rn,
[ValueSource("_1D_F_WX_")] ulong a)
[ValueSource(nameof(_1D_F_WX_))] ulong a)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -424,10 +421,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_AMPZ_SU_Gp_DX([ValueSource("_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(1u)] uint rn,
[ValueSource("_1D_F_WX_")] ulong a)
[ValueSource(nameof(_1D_F_WX_))] ulong a)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -440,11 +437,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_SW([ValueSource("_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(1u)] uint rn,
[ValueSource("_1S_F_WX_")] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1S_F_WX_))] ulong a,
[Values(1u, 32u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -461,11 +458,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_SX([ValueSource("_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(1u)] uint rn,
[ValueSource("_1S_F_WX_")] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1S_F_WX_))] ulong a,
[Values(1u, 64u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -481,11 +478,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_DW([ValueSource("_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(1u)] uint rn,
[ValueSource("_1D_F_WX_")] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1D_F_WX_))] ulong a,
[Values(1u, 32u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -502,11 +499,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_Gp_Fixed_DX([ValueSource("_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(1u)] uint rn,
[ValueSource("_1D_F_WX_")] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1D_F_WX_))] ulong a,
[Values(1u, 64u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -522,10 +519,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_WS([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_W_")] [Random(RndCnt)] uint wn)
[ValueSource(nameof(_W_))] uint wn)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -539,10 +536,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_WD([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_W_")] [Random(RndCnt)] uint wn)
[ValueSource(nameof(_W_))] uint wn)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -556,10 +553,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_XS([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn)
[ValueSource(nameof(_X_))] ulong xn)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -573,10 +570,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_XD([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn)
[ValueSource(nameof(_X_))] ulong xn)
{
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -590,11 +587,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_Fixed_WS([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_W_))] uint wn,
[Values(1u, 32u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -611,11 +608,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_Fixed_WD([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_W_))] uint wn,
[Values(1u, 32u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -632,11 +629,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_Fixed_XS([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_X_))] ulong xn,
[Values(1u, 64u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -653,11 +650,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_Gp_Fixed_XD([ValueSource("_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(1u, 31u)] uint rn,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_X_))] ulong xn,
[Values(1u, 64u)] uint fBits)
{
uint scale = (64u - fBits) & 0x3Fu;
@@ -674,4 +671,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _Vrint_AMNP_V_F32_()
{
return new uint[]
return new[]
{
0xf3ba0500u, // VRINTA.F32 Q0, Q0
0xf3ba0680u, // VRINTM.F32 Q0, Q0
@@ -28,8 +28,8 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static uint[] _1S_()
{
return new uint[] { 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
return new[] { 0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
}
private static IEnumerable<ulong> _1S_F_()
@@ -219,10 +219,10 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VCVT.F32.<dt> <Sd>, <Sm>")]
public void Vcvt_I32_F32([Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rm,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
[ValueSource(nameof(_1S_))] uint s0,
[ValueSource(nameof(_1S_))] uint s1,
[ValueSource(nameof(_1S_))] uint s2,
[ValueSource(nameof(_1S_))] uint s3,
[Values] bool unsigned, // <U32, S32>
[Values(RMode.Rn)] RMode rMode)
{
@@ -249,10 +249,10 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VCVT.F64.<dt> <Dd>, <Sm>")]
public void Vcvt_I32_F64([Values(0u, 1u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rm,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
[ValueSource(nameof(_1S_))] uint s0,
[ValueSource(nameof(_1S_))] uint s1,
[ValueSource(nameof(_1S_))] uint s2,
[ValueSource(nameof(_1S_))] uint s3,
[Values] bool unsigned, // <U32, S32>
[Values(RMode.Rn)] RMode rMode)
{
@@ -344,10 +344,10 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VCVT<top>.F16.F32 <Sd>, <Dm>")]
public void Vcvt_F32_F16([Values(0u, 1u, 2u, 3u)] uint rd,
[Values(0u, 1u, 2u, 3u)] uint rm,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
[ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
[ValueSource(nameof(_1S_))] uint s0,
[ValueSource(nameof(_1S_))] uint s1,
[ValueSource(nameof(_1S_))] uint s2,
[ValueSource(nameof(_1S_))] uint s3,
[Values] bool top)
{
uint opcode = 0xeeb30a40; // VCVTB.F16.F32 S0, D0
@@ -428,4 +428,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,7 +1,6 @@
#define SimdExt
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -14,22 +13,19 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource"
private static ulong[] _8B_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
}
#endregion
private const int RndCnt = 2;
private const int RndCntIndex = 2;
[Test, Pairwise, Description("EXT <Vd>.8B, <Vn>.8B, <Vm>.8B, #<index>")]
public void Ext_V_8B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B_")] [Random(RndCnt)] ulong b,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[ValueSource(nameof(_8B_))] ulong b,
[Values(0u, 7u)] uint index)
{
uint imm4 = index & 0x7u;
@@ -50,10 +46,10 @@ namespace Ryujinx.Tests.Cpu
public void Ext_V_16B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B_")] [Random(RndCnt)] ulong b,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[ValueSource(nameof(_8B_))] ulong b,
[Values(0u, 15u)] uint index)
{
uint imm4 = index & 0xFu;
@@ -71,4 +67,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define SimdFcond
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -101,7 +99,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _F_Ccmp_Ccmpe_S_S_()
{
return new uint[]
return new[]
{
0x1E220420u, // FCCMP S1, S2, #0, EQ
0x1E220430u // FCCMPE S1, S2, #0, EQ
@@ -110,7 +108,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Ccmp_Ccmpe_S_D_()
{
return new uint[]
return new[]
{
0x1E620420u, // FCCMP D1, D2, #0, EQ
0x1E620430u // FCCMPE D1, D2, #0, EQ
@@ -119,7 +117,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Csel_S_S_()
{
return new uint[]
return new[]
{
0x1E220C20u // FCSEL S0, S1, S2, EQ
};
@@ -127,7 +125,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Csel_S_D_()
{
return new uint[]
return new[]
{
0x1E620C20u // FCSEL D0, D1, D2, EQ
};
@@ -142,9 +140,9 @@ namespace Ryujinx.Tests.Cpu
private static readonly bool NoNaNs = false;
[Test, Pairwise] [Explicit]
public void F_Ccmp_Ccmpe_S_S([ValueSource("_F_Ccmp_Ccmpe_S_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
public void F_Ccmp_Ccmpe_S_S([ValueSource(nameof(_F_Ccmp_Ccmpe_S_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -167,9 +165,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Ccmp_Ccmpe_S_D([ValueSource("_F_Ccmp_Ccmpe_S_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
public void F_Ccmp_Ccmpe_S_D([ValueSource(nameof(_F_Ccmp_Ccmpe_S_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
@@ -192,9 +190,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Csel_S_S([ValueSource("_F_Csel_S_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
public void F_Csel_S_S([ValueSource(nameof(_F_Csel_S_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@@ -213,9 +211,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Csel_S_D([ValueSource("_F_Csel_S_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
public void F_Csel_S_D([ValueSource(nameof(_F_Csel_S_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,

View File

@@ -1,7 +1,6 @@
#define SimdFmov
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -14,7 +13,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource"
private static uint[] _F_Mov_Si_S_()
{
return new uint[]
return new[]
{
0x1E201000u // FMOV S0, #2.0
};
@@ -22,7 +21,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mov_Si_D_()
{
return new uint[]
return new[]
{
0x1E601000u // FMOV D0, #2.0
};
@@ -30,7 +29,7 @@ namespace Ryujinx.Tests.Cpu
#endregion
[Test, Pairwise] [Explicit]
public void F_Mov_Si_S([ValueSource("_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)
{
opcodes |= ((imm8 & 0xFFu) << 13);
@@ -44,7 +43,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mov_Si_D([ValueSource("_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)
{
opcodes |= ((imm8 & 0xFFu) << 13);

View File

@@ -1,9 +1,7 @@
#define SimdImm
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -50,14 +48,14 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<byte> _8BIT_IMM_()
@@ -94,7 +92,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _Bic_Orr_Vi_16bit_()
{
return new uint[]
return new[]
{
0x2F009400u, // BIC V0.4H, #0
0x0F009400u // ORR V0.4H, #0
@@ -103,7 +101,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Bic_Orr_Vi_32bit_()
{
return new uint[]
return new[]
{
0x2F001400u, // BIC V0.2S, #0
0x0F001400u // ORR V0.2S, #0
@@ -112,7 +110,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mov_Vi_2S_()
{
return new uint[]
return new[]
{
0x0F00F400u // FMOV V0.2S, #2.0
};
@@ -120,7 +118,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mov_Vi_4S_()
{
return new uint[]
return new[]
{
0x4F00F400u // FMOV V0.4S, #2.0
};
@@ -128,7 +126,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mov_Vi_2D_()
{
return new uint[]
return new[]
{
0x6F00F400u // FMOV V0.2D, #2.0
};
@@ -136,7 +134,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_V_8bit_()
{
return new uint[]
return new[]
{
0x0F00E400u // MOVI V0.8B, #0
};
@@ -144,7 +142,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_Mvni_V_16bit_shifted_imm_()
{
return new uint[]
return new[]
{
0x0F008400u, // MOVI V0.4H, #0
0x2F008400u // MVNI V0.4H, #0
@@ -153,7 +151,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_Mvni_V_32bit_shifted_imm_()
{
return new uint[]
return new[]
{
0x0F000400u, // MOVI V0.2S, #0
0x2F000400u // MVNI V0.2S, #0
@@ -162,7 +160,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_Mvni_V_32bit_shifting_ones_()
{
return new uint[]
return new[]
{
0x0F00C400u, // MOVI V0.2S, #0, MSL #8
0x2F00C400u // MVNI V0.2S, #0, MSL #8
@@ -171,7 +169,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_V_64bit_scalar_()
{
return new uint[]
return new[]
{
0x2F00E400u // MOVI D0, #0
};
@@ -179,21 +177,20 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Movi_V_64bit_vector_()
{
return new uint[]
return new[]
{
0x6F00E400u // MOVI V0.2D, #0
};
}
#endregion
private const int RndCnt = 2;
private const int RndCntImm8 = 2;
private const int RndCntImm64 = 2;
[Test, Pairwise]
public void Bic_Orr_Vi_16bit([ValueSource("_Bic_Orr_Vi_16bit_")] uint opcodes,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Bic_Orr_Vi_16bit([ValueSource(nameof(_Bic_Orr_Vi_16bit_))] uint opcodes,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b0u, 0b1u)] uint amount, // <0, 8>
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
@@ -212,9 +209,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Bic_Orr_Vi_32bit([ValueSource("_Bic_Orr_Vi_32bit_")] uint opcodes,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Bic_Orr_Vi_32bit([ValueSource(nameof(_Bic_Orr_Vi_32bit_))] uint opcodes,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -233,7 +230,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mov_Vi_2S([ValueSource("_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)
{
uint abc = (abcdefgh & 0xE0u) >> 5;
@@ -250,7 +247,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mov_Vi_4S([ValueSource("_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)
{
uint abc = (abcdefgh & 0xE0u) >> 5;
@@ -264,7 +261,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mov_Vi_2D([ValueSource("_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)
{
uint abc = (abcdefgh & 0xE0u) >> 5;
@@ -278,8 +275,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_V_8bit([ValueSource("_Movi_V_8bit_")] uint opcodes,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Movi_V_8bit([ValueSource(nameof(_Movi_V_8bit_))] uint opcodes,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
uint abc = (imm8 & 0xE0u) >> 5;
@@ -297,8 +294,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_Mvni_V_16bit_shifted_imm([ValueSource("_Movi_Mvni_V_16bit_shifted_imm_")] uint opcodes,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Movi_Mvni_V_16bit_shifted_imm([ValueSource(nameof(_Movi_Mvni_V_16bit_shifted_imm_))] uint opcodes,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b0u, 0b1u)] uint amount, // <0, 8>
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
@@ -318,8 +315,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_Mvni_V_32bit_shifted_imm([ValueSource("_Movi_Mvni_V_32bit_shifted_imm_")] uint opcodes,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Movi_Mvni_V_32bit_shifted_imm([ValueSource(nameof(_Movi_Mvni_V_32bit_shifted_imm_))] uint opcodes,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -339,8 +336,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_Mvni_V_32bit_shifting_ones([ValueSource("_Movi_Mvni_V_32bit_shifting_ones_")] uint opcodes,
[ValueSource("_8BIT_IMM_")] byte imm8,
public void Movi_Mvni_V_32bit_shifting_ones([ValueSource(nameof(_Movi_Mvni_V_32bit_shifting_ones_))] uint opcodes,
[ValueSource(nameof(_8BIT_IMM_))] byte imm8,
[Values(0b0u, 0b1u)] uint amount, // <8, 16>
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -360,8 +357,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_V_64bit_scalar([ValueSource("_Movi_V_64bit_scalar_")] uint opcodes,
[ValueSource("_64BIT_IMM_")] ulong imm)
public void Movi_V_64bit_scalar([ValueSource(nameof(_Movi_V_64bit_scalar_))] uint opcodes,
[ValueSource(nameof(_64BIT_IMM_))] ulong imm)
{
byte imm8 = ShrinkImm64(imm);
@@ -379,8 +376,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Movi_V_64bit_vector([ValueSource("_Movi_V_64bit_vector_")] uint opcodes,
[ValueSource("_64BIT_IMM_")] ulong imm)
public void Movi_V_64bit_vector([ValueSource(nameof(_Movi_V_64bit_vector_))] uint opcodes,
[ValueSource(nameof(_64BIT_IMM_))] ulong imm)
{
byte imm8 = ShrinkImm64(imm);
@@ -395,4 +392,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,7 +1,6 @@
#define SimdIns
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -14,66 +13,63 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource"
private static ulong[] _1D_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B4H2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static uint[] _W_()
{
return new uint[] { 0x00000000u, 0x0000007Fu,
0x00000080u, 0x000000FFu,
0x00007FFFu, 0x00008000u,
0x0000FFFFu, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
return new[] { 0x00000000u, 0x0000007Fu,
0x00000080u, 0x000000FFu,
0x00007FFFu, 0x00008000u,
0x0000FFFFu, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu };
}
private static ulong[] _X_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
#endregion
private const int RndCnt = 2;
private const int RndCntIndex = 2;
[Test, Pairwise, Description("DUP <Vd>.<T>, W<n>")]
public void Dup_Gp_W([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[ValueSource(nameof(_W_))] uint wn,
[Values(0, 1, 2)] int size, // Q0: <8B, 4H, 2S>
[Values(0b0u, 0b1u)] uint q) // Q1: <16B, 8H, 4S>
{
@@ -96,7 +92,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("DUP <Vd>.<T>, X<n>")]
public void Dup_Gp_X([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn)
[ValueSource(nameof(_X_))] ulong xn)
{
uint opcode = 0x4E080C00; // DUP V0.2D, X0
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -111,8 +107,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise, Description("DUP B0, V1.B[<index>]")]
public void Dup_S_B([ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
public void Dup_S_B([ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index)
{
const int size = 0;
@@ -131,8 +127,8 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise, Description("DUP H0, V1.H[<index>]")]
public void Dup_S_H([ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
public void Dup_S_H([ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index)
{
const int size = 1;
@@ -151,7 +147,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise, Description("DUP S0, V1.S[<index>]")]
public void Dup_S_S([ValueSource("_2S_")] [Random(RndCnt)] ulong a,
public void Dup_S_S([ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index)
{
const int size = 2;
@@ -171,7 +167,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise, Description("DUP D0, V1.D[<index>]")]
public void Dup_S_D([ValueSource("_1D_")] [Random(RndCnt)] ulong a,
public void Dup_S_D([ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 1u)] uint index)
{
const int size = 3;
@@ -193,9 +189,9 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.B[<index>]")]
public void Dup_V_8B_16B([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
const int size = 0;
@@ -218,9 +214,9 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.H[<index>]")]
public void Dup_V_4H_8H([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
const int size = 1;
@@ -243,8 +239,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.S[<index>]")]
public void Dup_V_2S_4S([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -268,8 +264,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.D[<index>]")]
public void Dup_V_2D([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 1u)] uint index,
[Values(0b1u)] uint q) // <2D>
{
@@ -293,9 +289,9 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.B[<index>], W<n>")]
public void Ins_Gp_WB([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_W_))] uint wn,
[Values(0u, 15u)] uint index)
{
const int size = 0;
@@ -316,9 +312,9 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.H[<index>], W<n>")]
public void Ins_Gp_WH([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_W_))] uint wn,
[Values(0u, 7u)] uint index)
{
const int size = 1;
@@ -339,8 +335,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.S[<index>], W<n>")]
public void Ins_Gp_WS([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_W_")] [Random(RndCnt)] uint wn,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_W_))] uint wn,
[Values(0u, 1u, 2u, 3u)] uint index)
{
const int size = 2;
@@ -362,8 +358,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.D[<index>], X<n>")]
public void Ins_Gp_XD([Values(0u)] uint rd,
[Values(1u, 31u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_X_")] [Random(RndCnt)] ulong xn,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_X_))] ulong xn,
[Values(0u, 1u)] uint index)
{
const int size = 3;
@@ -385,10 +381,10 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.B[<index1>], <Vn>.B[<index2>]")]
public void Ins_V_BB([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint dstIndex,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint srcIndex)
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint dstIndex,
[Values(0u, 15u)] uint srcIndex)
{
const int size = 0;
@@ -411,10 +407,10 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.H[<index1>], <Vn>.H[<index2>]")]
public void Ins_V_HH([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint dstIndex,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint srcIndex)
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint dstIndex,
[Values(0u, 7u)] uint srcIndex)
{
const int size = 1;
@@ -437,8 +433,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.S[<index1>], <Vn>.S[<index2>]")]
public void Ins_V_SS([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint dstIndex,
[Values(0u, 1u, 2u, 3u)] uint srcIndex)
{
@@ -463,8 +459,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("INS <Vd>.D[<index1>], <Vn>.D[<index2>]")]
public void Ins_V_DD([Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 1u)] uint dstIndex,
[Values(0u, 1u)] uint srcIndex)
{
@@ -489,8 +485,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Wd>, <Vn>.B[<index>]")]
public void Smov_S_BW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index)
{
const int size = 0;
@@ -512,8 +508,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Wd>, <Vn>.H[<index>]")]
public void Smov_S_HW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index)
{
const int size = 1;
@@ -535,8 +531,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.B[<index>]")]
public void Smov_S_BX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index)
{
const int size = 0;
@@ -557,8 +553,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.H[<index>]")]
public void Smov_S_HX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index)
{
const int size = 1;
@@ -579,7 +575,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("SMOV <Xd>, <Vn>.S[<index>]")]
public void Smov_S_SX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index)
{
const int size = 2;
@@ -601,8 +597,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.B[<index>]")]
public void Umov_S_BW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 15u)] uint index)
{
const int size = 0;
@@ -624,8 +620,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.H[<index>]")]
public void Umov_S_HW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 7u)] uint index)
{
const int size = 1;
@@ -647,7 +643,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Wd>, <Vn>.S[<index>]")]
public void Umov_S_SW([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 1u, 2u, 3u)] uint index)
{
const int size = 2;
@@ -670,7 +666,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("UMOV <Xd>, <Vn>.D[<index>]")]
public void Umov_S_DX([Values(0u, 31u)] uint rd,
[Values(1u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 1u)] uint index)
{
const int size = 3;
@@ -690,4 +686,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -13,17 +13,17 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _8B4H2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
#endregion
#region "ValueSource (Opcodes)"
private static uint[] _Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_()
{
return new uint[]
return new[]
{
0xf2100110u, // VBIC D0, D0, D0
0xf3300110u, // VBIF D0, D0, D0
@@ -38,7 +38,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vbic_Vorr_II_()
{
return new uint[]
return new[]
{
0xf2800130u, // VBIC.I32 D0, #0 (A1)
0xf2800930u, // VBIC.I16 D0, #0 (A2)
@@ -48,16 +48,14 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[Test, Pairwise]
public void Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I([ValueSource("_Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_")] uint opcode,
public void Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I([ValueSource(nameof(_Vbic_Vbif_Vbit_Vbsl_Vand_Vorn_Vorr_Veor_I_))] uint opcode,
[Range(0u, 5u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
[Values(ulong.MinValue, ulong.MaxValue)] [Random(RndCnt)] ulong z,
[Values(ulong.MinValue, ulong.MaxValue)] [Random(RndCnt)] ulong a,
[Values(ulong.MinValue, ulong.MaxValue)] [Random(RndCnt)] ulong b,
[Values(ulong.MinValue, ulong.MaxValue)] ulong z,
[Values(ulong.MinValue, ulong.MaxValue)] ulong a,
[Values(ulong.MinValue, ulong.MaxValue)] ulong b,
[Values] bool q)
{
if (q)
@@ -83,10 +81,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vbic_Vorr_II([ValueSource("_Vbic_Vorr_II_")] uint opcode,
public void Vbic_Vorr_II([ValueSource(nameof(_Vbic_Vorr_II_))] uint opcode,
[Values(0u, 1u)] uint rd,
[Values(ulong.MinValue, ulong.MaxValue)] [Random(RndCnt)] ulong z,
[Values(byte.MinValue, byte.MaxValue)] [Random(RndCnt)] byte imm,
[Values(ulong.MinValue, ulong.MaxValue)] ulong z,
[Values(byte.MinValue, byte.MaxValue)] byte imm,
[Values(0u, 1u, 2u, 3u)] uint cMode,
[Values] bool q)
{
@@ -119,9 +117,9 @@ namespace Ryujinx.Tests.Cpu
public void Vtst([Range(0u, 5u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S_))] ulong z,
[ValueSource(nameof(_8B4H2S_))] ulong a,
[ValueSource(nameof(_8B4H2S_))] ulong b,
[Values(0u, 1u, 2u)] uint size,
[Values] bool q)
{
@@ -152,4 +150,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -10,7 +10,6 @@ namespace Ryujinx.Tests.Cpu
public sealed class CpuTestSimdMemory32 : CpuTest32
{
#if SimdMemory32
private const int RndCntImm = 2;
private uint[] _ldStModes =
{
@@ -41,7 +40,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint vd,
[Range(0u, 7u)] uint index,
[Range(0u, 3u)] uint n,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint offset)
[Values(0x0u)] uint offset)
{
var data = GenerateVectorSequence(0x1000);
SetWorkingMemory(0, data);
@@ -71,7 +70,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 3u)] uint n,
[Range(0u, 2u)] uint size,
[Values] bool t,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint offset)
[Values(0x0u)] uint offset)
{
var data = GenerateVectorSequence(0x1000);
SetWorkingMemory(0, data);
@@ -97,7 +96,7 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 13u, 15u)] uint rm,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint vd,
[Range(0u, 10u)] uint mode,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint offset)
[Values(0x0u)] uint offset)
{
var data = GenerateVectorSequence(0x1000);
SetWorkingMemory(0, data);
@@ -127,7 +126,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint vd,
[Range(0u, 7u)] uint index,
[Range(0u, 3u)] uint n,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint offset)
[Values(0x0u)] uint offset)
{
var data = GenerateVectorSequence(0x1000);
SetWorkingMemory(0, data);
@@ -158,7 +157,7 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 13u, 15u)] uint rm,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint vd,
[Range(0u, 10u)] uint mode,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint offset)
[Values(0x0u)] uint offset)
{
var data = GenerateVectorSequence(0x1000);
SetWorkingMemory(0, data);
@@ -187,7 +186,7 @@ namespace Ryujinx.Tests.Cpu
public void Vldm([Values(0u, 13u)] uint rn,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint vd,
[Range(0u, 2u)] uint mode,
[Values(0x1u, 0x32u)] [Random(2u, 31u, RndCntImm)] uint regs,
[Values(0x1u, 0x32u)] uint regs,
[Values] bool single)
{
var data = GenerateVectorSequence(0x1000);
@@ -235,7 +234,7 @@ namespace Ryujinx.Tests.Cpu
public void Vldr([Values(2u, 3u)] uint size, // FP16 is not supported for now
[Values(0u)] uint rn,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
[Values(0x0u)] uint imm,
[Values] bool sub)
{
var data = GenerateVectorSequence(0x1000);
@@ -270,7 +269,7 @@ namespace Ryujinx.Tests.Cpu
public void Vstr([Values(2u, 3u)] uint size, // FP16 is not supported for now
[Values(0u)] uint rn,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
[Values(0x0u)] uint imm,
[Values] bool sub)
{
var data = GenerateVectorSequence(0x1000);
@@ -329,4 +328,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -14,7 +14,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VMOV.I<size> <Dd/Qd>, #<imm>")]
public void Movi_V([Range(0u, 10u)] uint variant,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
[Values(0x0u)] uint imm,
[Values] bool q)
{
uint[] variants =
@@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VMOV.F<size> <Sd>, #<imm>")]
public void Movi_S([Range(2u, 3u)] uint size,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm)
[Values(0x0u)] uint imm)
{
uint opcode = 0xeeb00800u;
opcode |= (size & 3) << 8;
@@ -292,7 +292,7 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VMVN.I<size> <Dd/Qd>, #<imm>")]
public void Mvni_V([Range(0u, 7u)] uint variant,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
[Values(0x0u)] uint imm,
[Values] bool q)
{
uint[] variants =
@@ -596,4 +596,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _V_Add_Sub_Long_Wide_I_()
{
return new uint[]
return new[]
{
0xf2800000u, // VADDL.S8 Q0, D0, D0
0xf2800100u, // VADDW.S8 Q0, Q0, D0
@@ -25,7 +25,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vfma_Vfms_Vfnma_Vfnms_S_F32_()
{
return new uint[]
return new[]
{
0xEEA00A00u, // VFMA. F32 S0, S0, S0
0xEEA00A40u, // VFMS. F32 S0, S0, S0
@@ -36,7 +36,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vfma_Vfms_Vfnma_Vfnms_S_F64_()
{
return new uint[]
return new[]
{
0xEEA00B00u, // VFMA. F64 D0, D0, D0
0xEEA00B40u, // VFMS. F64 D0, D0, D0
@@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vfma_Vfms_V_F32_()
{
return new uint[]
return new[]
{
0xF2000C10u, // VFMA.F32 D0, D0, D0
0xF2200C10u // VFMS.F32 D0, D0, D0
@@ -56,7 +56,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vmla_Vmls_Vnmla_Vnmls_S_F32_()
{
return new uint[]
return new[]
{
0xEE000A00u, // VMLA. F32 S0, S0, S0
0xEE000A40u, // VMLS. F32 S0, S0, S0
@@ -67,7 +67,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vmla_Vmls_Vnmla_Vnmls_S_F64_()
{
return new uint[]
return new[]
{
0xEE000B00u, // VMLA. F64 D0, D0, D0
0xEE000B40u, // VMLS. F64 D0, D0, D0
@@ -78,7 +78,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vmlal_Vmlsl_V_I_()
{
return new uint[]
return new[]
{
0xf2800800u, // VMLAL.S8 Q0, D0, D0
0xf2800a00u // VMLSL.S8 Q0, D0, D0
@@ -87,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vp_Add_Max_Min_F_()
{
return new uint[]
return new[]
{
0xf3000d00u, // VPADD.F32 D0, D0, D0
0xf3000f00u, // VPMAX.F32 D0, D0, D0
@@ -97,7 +97,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vp_Add_I_()
{
return new uint[]
return new[]
{
0xf2000b10u // VPADD.I8 D0, D0, D0
};
@@ -105,7 +105,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _V_Pmax_Pmin_Rhadd_I_()
{
return new uint[]
return new[]
{
0xf2000a00u, // VPMAX .S8 D0, D0, D0
0xf2000a10u, // VPMIN .S8 D0, D0, D0
@@ -115,7 +115,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vq_Add_Sub_I_()
{
return new uint[]
return new[]
{
0xf2000050u, // VQADD.S8 Q0, Q0, Q0
0xf2000250u // VQSUB.S8 Q0, Q0, Q0
@@ -126,18 +126,18 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _8B1D_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B4H2S1D_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<ulong> _1S_F_()
@@ -378,12 +378,12 @@ namespace Ryujinx.Tests.Cpu
public void Vadd_F32([Values(0u)] uint rd,
[Values(0u, 1u)] uint rn,
[Values(0u, 2u)] uint rm,
[ValueSource("_2S_F_")] ulong z0,
[ValueSource("_2S_F_")] ulong z1,
[ValueSource("_2S_F_")] ulong a0,
[ValueSource("_2S_F_")] ulong a1,
[ValueSource("_2S_F_")] ulong b0,
[ValueSource("_2S_F_")] ulong b1,
[ValueSource(nameof(_2S_F_))] ulong z0,
[ValueSource(nameof(_2S_F_))] ulong z1,
[ValueSource(nameof(_2S_F_))] ulong a0,
[ValueSource(nameof(_2S_F_))] ulong a1,
[ValueSource(nameof(_2S_F_))] ulong b0,
[ValueSource(nameof(_2S_F_))] ulong b1,
[Values] bool q)
{
uint opcode = 0xf2000d00u; // VADD.F32 D0, D0, D0
@@ -409,13 +409,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void V_Add_Sub_Long_Wide_I([ValueSource("_V_Add_Sub_Long_Wide_I_")] uint opcode,
public void V_Add_Sub_Long_Wide_I([ValueSource(nameof(_V_Add_Sub_Long_Wide_I_))] uint opcode,
[Range(0u, 5u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_8B4H2S1D_))] ulong a,
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
[Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32>
[Values] bool u) // <S, U>
{
@@ -444,8 +444,8 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise, Description("VCMP.f<size> Vd, Vm")]
public void Vcmp([Values(2u, 3u)] uint size,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_1S_F_))] ulong b,
[Values] bool e)
{
uint opcode = 0xeeb40840u;
@@ -666,8 +666,8 @@ namespace Ryujinx.Tests.Cpu
public void Vmull_I_P8_P64([Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rn,
[Values(0u, 1u)] uint rm,
[ValueSource(nameof(_8B1D_))] [Random(RndCnt)] ulong d0,
[ValueSource(nameof(_8B1D_))] [Random(RndCnt)] ulong d1,
[ValueSource(nameof(_8B1D_))] ulong d0,
[ValueSource(nameof(_8B1D_))] ulong d1,
[Values(0u/*, 2u*/)] uint size) // <P8, P64>
{
/*if (size == 2u)
@@ -734,22 +734,21 @@ namespace Ryujinx.Tests.Cpu
[Explicit]
[Test, Pairwise]
public void Vp_Add_Max_Min_F([ValueSource("_Vp_Add_Max_Min_F_")] uint opcode,
public void Vp_Add_Max_Min_F([ValueSource(nameof(_Vp_Add_Max_Min_F_))] uint opcode,
[Values(0u)] uint rd,
[Range(0u, 7u)] uint rn,
[Range(0u, 7u)] uint rm,
[ValueSource("_2S_F_")] ulong z0,
[ValueSource("_2S_F_")] ulong z1,
[ValueSource("_2S_F_")] ulong a0,
[ValueSource("_2S_F_")] ulong a1,
[ValueSource("_2S_F_")] ulong b0,
[ValueSource("_2S_F_")] ulong b1)
[ValueSource(nameof(_2S_F_))] ulong z0,
[ValueSource(nameof(_2S_F_))] ulong z1,
[ValueSource(nameof(_2S_F_))] ulong a0,
[ValueSource(nameof(_2S_F_))] ulong a1,
[ValueSource(nameof(_2S_F_))] ulong b0,
[ValueSource(nameof(_2S_F_))] ulong b1)
{
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
var rnd = TestContext.CurrentContext.Random;
V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1);
V128 v2 = MakeVectorE0E1(b0, b1);
@@ -760,7 +759,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vp_Add_I([ValueSource("_Vp_Add_I_")] uint opcode,
public void Vp_Add_I([ValueSource(nameof(_Vp_Add_I_))] uint opcode,
[Values(0u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
@@ -785,7 +784,7 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void V_Pmax_Pmin_Rhadd_I([ValueSource("_V_Pmax_Pmin_Rhadd_I_")] uint opcode,
public void V_Pmax_Pmin_Rhadd_I([ValueSource(nameof(_V_Pmax_Pmin_Rhadd_I_))] uint opcode,
[Values(0u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
@@ -816,13 +815,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vq_Add_Sub_I([ValueSource("_Vq_Add_Sub_I_")] uint opcode,
public void Vq_Add_Sub_I([ValueSource(nameof(_Vq_Add_Sub_I_))] uint opcode,
[Range(0u, 5u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_8B4H2S1D_))] ulong a,
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
[Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32>
[Values] bool u) // <S, U>
{
@@ -854,9 +853,9 @@ namespace Ryujinx.Tests.Cpu
public void Vqdmulh_I([Range(0u, 5u)] uint rd,
[Range(0u, 5u)] uint rn,
[Range(0u, 5u)] uint rm,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a,
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_8B4H2S1D_))] ulong z,
[ValueSource(nameof(_8B4H2S1D_))] ulong a,
[ValueSource(nameof(_8B4H2S1D_))] ulong b,
[Values(1u, 2u)] uint size) // <S16, S32>
{
rd >>= 1; rd <<= 1;
@@ -881,4 +880,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,7 +1,6 @@
#define SimdRegElem
using ARMeilleure.State;
using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
@@ -14,21 +13,21 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
#endregion
#region "ValueSource (Opcodes)"
private static uint[] _Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_()
{
return new uint[]
return new[]
{
0x2F400000u, // MLA V0.4H, V0.4H, V0.H[0]
0x2F404000u, // MLS V0.4H, V0.4H, V0.H[0]
@@ -40,7 +39,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_2S_4S_()
{
return new uint[]
return new[]
{
0x2F800000u, // MLA V0.2S, V0.2S, V0.S[0]
0x2F804000u, // MLS V0.2S, V0.2S, V0.S[0]
@@ -52,7 +51,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S_()
{
return new uint[]
return new[]
{
0x0F402000u, // SMLAL V0.4S, V0.4H, V0.H[0]
0x0F406000u, // SMLSL V0.4S, V0.4H, V0.H[0]
@@ -65,7 +64,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D_()
{
return new uint[]
return new[]
{
0x0F802000u, // SMLAL V0.2D, V0.2S, V0.S[0]
0x0F806000u, // SMLSL V0.2D, V0.2S, V0.S[0]
@@ -77,18 +76,16 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
private const int RndCntIndex = 2;
[Test, Pairwise]
public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_4H_))] [Random(RndCnt)] ulong z,
[ValueSource(nameof(_4H_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_4H_))] [Random(RndCnt)] ulong b,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[ValueSource(nameof(_4H_))] ulong b,
[Values(0u, 7u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
uint h = (index >> 2) & 1;
@@ -110,12 +107,12 @@ namespace Ryujinx.Tests.Cpu
[Test, Pairwise]
public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_2S_4S([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_2S_4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource(nameof(_2S_))] [Random(RndCnt)] ulong z,
[ValueSource(nameof(_2S_))] [Random(RndCnt)] ulong a,
[ValueSource(nameof(_2S_))] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[ValueSource(nameof(_2S_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -136,14 +133,14 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S([ValueSource("_SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S_")] uint opcodes,
public void SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_4H4S_8H4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[ValueSource("_4H_")] [Random(RndCnt)] ulong b,
[Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[ValueSource(nameof(_4H_))] ulong b,
[Values(0u, 7u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <4H4S, 8H4S>
{
uint h = (index >> 2) & 1;
@@ -164,13 +161,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D([ValueSource("_SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D_")] uint opcodes,
public void SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D([ValueSource(nameof(_SU_Mlal_Mlsl_Mull_Ve_2S2D_4S2D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[ValueSource("_2S_")] [Random(RndCnt)] ulong b,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[ValueSource(nameof(_2S_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <2S2D, 4S2D>
{
@@ -191,4 +188,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define SimdRegElemF
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -142,7 +140,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _F_Mla_Mls_Se_S_()
{
return new uint[]
return new[]
{
0x5F821020u, // FMLA S0, S1, V2.S[0]
0x5F825020u // FMLS S0, S1, V2.S[0]
@@ -151,7 +149,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mla_Mls_Se_D_()
{
return new uint[]
return new[]
{
0x5FC21020u, // FMLA D0, D1, V2.D[0]
0x5FC25020u // FMLS D0, D1, V2.D[0]
@@ -160,7 +158,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mla_Mls_Ve_2S_4S_()
{
return new uint[]
return new[]
{
0x0F801000u, // FMLA V0.2S, V0.2S, V0.S[0]
0x0F805000u // FMLS V0.2S, V0.2S, V0.S[0]
@@ -169,7 +167,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mla_Mls_Ve_2D_()
{
return new uint[]
return new[]
{
0x4FC01000u, // FMLA V0.2D, V0.2D, V0.D[0]
0x4FC05000u // FMLS V0.2D, V0.2D, V0.D[0]
@@ -178,7 +176,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mul_Mulx_Se_S_()
{
return new uint[]
return new[]
{
0x5F829020u, // FMUL S0, S1, V2.S[0]
0x7F829020u // FMULX S0, S1, V2.S[0]
@@ -187,7 +185,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mul_Mulx_Se_D_()
{
return new uint[]
return new[]
{
0x5FC29020u, // FMUL D0, D1, V2.D[0]
0x7FC29020u // FMULX D0, D1, V2.D[0]
@@ -196,7 +194,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mul_Mulx_Ve_2S_4S_()
{
return new uint[]
return new[]
{
0x0F809000u, // FMUL V0.2S, V0.2S, V0.S[0]
0x2F809000u // FMULX V0.2S, V0.2S, V0.S[0]
@@ -205,7 +203,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Mul_Mulx_Ve_2D_()
{
return new uint[]
return new[]
{
0x4FC09000u, // FMUL V0.2D, V0.2D, V0.D[0]
0x6FC09000u // FMULX V0.2D, V0.2D, V0.D[0]
@@ -220,10 +218,10 @@ namespace Ryujinx.Tests.Cpu
private static readonly bool NoNaNs = false;
[Test, Pairwise] [Explicit] // Fused.
public void F_Mla_Mls_Se_S([ValueSource("_F_Mla_Mls_Se_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong z,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
public void F_Mla_Mls_Se_S([ValueSource(nameof(_F_Mla_Mls_Se_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong z,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index)
{
uint h = (index >> 1) & 1;
@@ -246,10 +244,10 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit] // Fused.
public void F_Mla_Mls_Se_D([ValueSource("_F_Mla_Mls_Se_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong z,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
public void F_Mla_Mls_Se_D([ValueSource(nameof(_F_Mla_Mls_Se_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong z,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Values(0u, 1u)] uint index)
{
uint h = index & 1;
@@ -271,13 +269,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit] // Fused.
public void F_Mla_Mls_Ve_2S_4S([ValueSource("_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(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_2S_F_")] ulong z,
[ValueSource("_2S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
[ValueSource(nameof(_2S_F_))] ulong z,
[ValueSource(nameof(_2S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -303,13 +301,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit] // Fused.
public void F_Mla_Mls_Ve_2D([ValueSource("_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(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_1D_F_")] ulong z,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
[ValueSource(nameof(_1D_F_))] ulong z,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Values(0u, 1u)] uint index)
{
uint h = index & 1;
@@ -332,9 +330,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mul_Mulx_Se_S([ValueSource("_F_Mul_Mulx_Se_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
public void F_Mul_Mulx_Se_S([ValueSource(nameof(_F_Mul_Mulx_Se_S_))] uint opcodes,
[ValueSource(nameof(_1S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index)
{
uint h = (index >> 1) & 1;
@@ -358,9 +356,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mul_Mulx_Se_D([ValueSource("_F_Mul_Mulx_Se_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
public void F_Mul_Mulx_Se_D([ValueSource(nameof(_F_Mul_Mulx_Se_D_))] uint opcodes,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Values(0u, 1u)] uint index)
{
uint h = index & 1;
@@ -383,13 +381,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mul_Mulx_Ve_2S_4S([ValueSource("_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(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_2S_F_")] ulong z,
[ValueSource("_2S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
[ValueSource(nameof(_2S_F_))] ulong z,
[ValueSource(nameof(_2S_F_))] ulong a,
[ValueSource(nameof(_2S_F_))] ulong b,
[Values(0u, 1u, 2u, 3u)] uint index,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
@@ -415,13 +413,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Mul_Mulx_Ve_2D([ValueSource("_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(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_1D_F_")] ulong z,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b,
[ValueSource(nameof(_1D_F_))] ulong z,
[ValueSource(nameof(_1D_F_))] ulong a,
[ValueSource(nameof(_1D_F_))] ulong b,
[Values(0u, 1u)] uint index)
{
uint h = index & 1;

View File

@@ -1,9 +1,7 @@
#define SimdShImm
using ARMeilleure.State;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@@ -17,38 +15,38 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _1D_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _1H_()
{
return new ulong[] { 0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul };
return new[] { 0x0000000000000000ul, 0x0000000000007FFFul,
0x0000000000008000ul, 0x000000000000FFFFul };
}
private static ulong[] _1S_()
{
return new ulong[] { 0x0000000000000000ul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x000000007FFFFFFFul,
0x0000000080000000ul, 0x00000000FFFFFFFFul };
}
private static ulong[] _2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<ulong> _2S_F_W_()
@@ -97,10 +95,8 @@ namespace Ryujinx.Tests.Cpu
for (int cnt = 1; cnt <= RndCnt; cnt++)
{
ulong rnd1 = (uint)BitConverter.SingleToInt32Bits(
(float)((int)TestContext.CurrentContext.Random.NextUInt()));
ulong rnd2 = (uint)BitConverter.SingleToInt32Bits(
(float)((uint)TestContext.CurrentContext.Random.NextUInt()));
ulong rnd1 = (uint)BitConverter.SingleToInt32Bits((int)TestContext.CurrentContext.Random.NextUInt());
ulong rnd2 = (uint)BitConverter.SingleToInt32Bits(TestContext.CurrentContext.Random.NextUInt());
ulong rnd3 = GenNormalS();
ulong rnd4 = GenSubnormalS();
@@ -160,9 +156,9 @@ namespace Ryujinx.Tests.Cpu
for (int cnt = 1; cnt <= RndCnt; cnt++)
{
ulong rnd1 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((long)TestContext.CurrentContext.Random.NextULong()));
(long)TestContext.CurrentContext.Random.NextULong());
ulong rnd2 = (ulong)BitConverter.DoubleToInt64Bits(
(double)((ulong)TestContext.CurrentContext.Random.NextULong()));
TestContext.CurrentContext.Random.NextULong());
ulong rnd3 = GenNormalD();
ulong rnd4 = GenSubnormalD();
@@ -179,7 +175,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _F_Cvt_Z_SU_V_Fixed_2S_4S_()
{
return new uint[]
return new[]
{
0x0F20FC00u, // FCVTZS V0.2S, V0.2S, #32
0x2F20FC00u // FCVTZU V0.2S, V0.2S, #32
@@ -188,7 +184,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _F_Cvt_Z_SU_V_Fixed_2D_()
{
return new uint[]
return new[]
{
0x4F40FC00u, // FCVTZS V0.2D, V0.2D, #64
0x6F40FC00u // FCVTZU V0.2D, V0.2D, #64
@@ -197,7 +193,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_S_Fixed_S_()
{
return new uint[]
return new[]
{
0x5F20E420u, // SCVTF S0, S1, #32
0x7F20E420u // UCVTF S0, S1, #32
@@ -206,7 +202,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_S_Fixed_D_()
{
return new uint[]
return new[]
{
0x5F40E420u, // SCVTF D0, D1, #64
0x7F40E420u // UCVTF D0, D1, #64
@@ -215,7 +211,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_V_Fixed_2S_4S_()
{
return new uint[]
return new[]
{
0x0F20E400u, // SCVTF V0.2S, V0.2S, #32
0x2F20E400u // UCVTF V0.2S, V0.2S, #32
@@ -224,7 +220,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Cvt_F_V_Fixed_2D_()
{
return new uint[]
return new[]
{
0x4F40E400u, // SCVTF V0.2D, V0.2D, #64
0x6F40E400u // UCVTF V0.2D, V0.2D, #64
@@ -233,7 +229,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Shl_Sli_S_D_()
{
return new uint[]
return new[]
{
0x5F405400u, // SHL D0, D0, #0
0x7F405400u // SLI D0, D0, #0
@@ -242,7 +238,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Shl_Sli_V_8B_16B_()
{
return new uint[]
return new[]
{
0x0F085400u, // SHL V0.8B, V0.8B, #0
0x2F085400u // SLI V0.8B, V0.8B, #0
@@ -251,7 +247,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Shl_Sli_V_4H_8H_()
{
return new uint[]
return new[]
{
0x0F105400u, // SHL V0.4H, V0.4H, #0
0x2F105400u // SLI V0.4H, V0.4H, #0
@@ -260,7 +256,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Shl_Sli_V_2S_4S_()
{
return new uint[]
return new[]
{
0x0F205400u, // SHL V0.2S, V0.2S, #0
0x2F205400u // SLI V0.2S, V0.2S, #0
@@ -269,7 +265,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Shl_Sli_V_2D_()
{
return new uint[]
return new[]
{
0x4F405400u, // SHL V0.2D, V0.2D, #0
0x6F405400u // SLI V0.2D, V0.2D, #0
@@ -278,7 +274,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Shll_V_8B8H_16B8H_()
{
return new uint[]
return new[]
{
0x0F08A400u, // SSHLL V0.8H, V0.8B, #0
0x2F08A400u // USHLL V0.8H, V0.8B, #0
@@ -287,7 +283,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Shll_V_4H4S_8H4S_()
{
return new uint[]
return new[]
{
0x0F10A400u, // SSHLL V0.4S, V0.4H, #0
0x2F10A400u // USHLL V0.4S, V0.4H, #0
@@ -296,7 +292,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _SU_Shll_V_2S2D_4S2D_()
{
return new uint[]
return new[]
{
0x0F20A400u, // SSHLL V0.2D, V0.2S, #0
0x2F20A400u // USHLL V0.2D, V0.2S, #0
@@ -305,7 +301,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImm_Sri_S_D_()
{
return new uint[]
return new[]
{
0x7F404400u, // SRI D0, D0, #64
0x5F402400u, // SRSHR D0, D0, #64
@@ -321,7 +317,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImm_Sri_V_8B_16B_()
{
return new uint[]
return new[]
{
0x2F084400u, // SRI V0.8B, V0.8B, #8
0x0F082400u, // SRSHR V0.8B, V0.8B, #8
@@ -337,7 +333,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImm_Sri_V_4H_8H_()
{
return new uint[]
return new[]
{
0x2F104400u, // SRI V0.4H, V0.4H, #16
0x0F102400u, // SRSHR V0.4H, V0.4H, #16
@@ -353,7 +349,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImm_Sri_V_2S_4S_()
{
return new uint[]
return new[]
{
0x2F204400u, // SRI V0.2S, V0.2S, #32
0x0F202400u, // SRSHR V0.2S, V0.2S, #32
@@ -369,7 +365,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImm_Sri_V_2D_()
{
return new uint[]
return new[]
{
0x6F404400u, // SRI V0.2D, V0.2D, #64
0x4F402400u, // SRSHR V0.2D, V0.2D, #64
@@ -385,7 +381,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmNarrow_V_8H8B_8H16B_()
{
return new uint[]
return new[]
{
0x0F088C00u, // RSHRN V0.8B, V0.8H, #8
0x0F088400u // SHRN V0.8B, V0.8H, #8
@@ -394,7 +390,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmNarrow_V_4S4H_4S8H_()
{
return new uint[]
return new[]
{
0x0F108C00u, // RSHRN V0.4H, V0.4S, #16
0x0F108400u // SHRN V0.4H, V0.4S, #16
@@ -403,7 +399,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmNarrow_V_2D2S_2D4S_()
{
return new uint[]
return new[]
{
0x0F208C00u, // RSHRN V0.2S, V0.2D, #32
0x0F208400u // SHRN V0.2S, V0.2D, #32
@@ -412,7 +408,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_S_HB_()
{
return new uint[]
return new[]
{
0x5F089C00u, // SQRSHRN B0, H0, #8
0x7F089C00u, // UQRSHRN B0, H0, #8
@@ -425,7 +421,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_S_SH_()
{
return new uint[]
return new[]
{
0x5F109C00u, // SQRSHRN H0, S0, #16
0x7F109C00u, // UQRSHRN H0, S0, #16
@@ -438,7 +434,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_S_DS_()
{
return new uint[]
return new[]
{
0x5F209C00u, // SQRSHRN S0, D0, #32
0x7F209C00u, // UQRSHRN S0, D0, #32
@@ -451,7 +447,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_V_8H8B_8H16B_()
{
return new uint[]
return new[]
{
0x0F089C00u, // SQRSHRN V0.8B, V0.8H, #8
0x2F089C00u, // UQRSHRN V0.8B, V0.8H, #8
@@ -464,7 +460,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_V_4S4H_4S8H_()
{
return new uint[]
return new[]
{
0x0F109C00u, // SQRSHRN V0.4H, V0.4S, #16
0x2F109C00u, // UQRSHRN V0.4H, V0.4S, #16
@@ -477,7 +473,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ShrImmSaturatingNarrow_V_2D2S_2D4S_()
{
return new uint[]
return new[]
{
0x0F209C00u, // SQRSHRN V0.2S, V0.2D, #32
0x2F209C00u, // UQRSHRN V0.2S, V0.2D, #32
@@ -490,20 +486,18 @@ namespace Ryujinx.Tests.Cpu
#endregion
private const int RndCnt = 2;
private const int RndCntFBits = 2;
private const int RndCntShift = 2;
private static readonly bool NoZeros = false;
private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false;
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_V_Fixed_2S_4S([ValueSource("_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(1u, 0u)] uint rn,
[ValueSource("_2S_F_W_")] ulong z,
[ValueSource("_2S_F_W_")] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits,
[ValueSource(nameof(_2S_F_W_))] ulong z,
[ValueSource(nameof(_2S_F_W_))] ulong a,
[Values(1u, 32u)] uint fBits,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
uint immHb = (64 - fBits) & 0x7F;
@@ -521,12 +515,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cvt_Z_SU_V_Fixed_2D([ValueSource("_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(1u, 0u)] uint rn,
[ValueSource("_1D_F_X_")] ulong z,
[ValueSource("_1D_F_X_")] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1D_F_X_))] ulong z,
[ValueSource(nameof(_1D_F_X_))] ulong a,
[Values(1u, 64u)] uint fBits)
{
uint immHb = (128 - fBits) & 0x7F;
@@ -542,9 +536,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_S_Fixed_S([ValueSource("_SU_Cvt_F_S_Fixed_S_")] uint opcodes,
[ValueSource("_1S_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
public void SU_Cvt_F_S_Fixed_S([ValueSource(nameof(_SU_Cvt_F_S_Fixed_S_))] uint opcodes,
[ValueSource(nameof(_1S_))] ulong a,
[Values(1u, 32u)] uint fBits)
{
uint immHb = (64 - fBits) & 0x7F;
@@ -560,9 +554,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_S_Fixed_D([ValueSource("_SU_Cvt_F_S_Fixed_D_")] uint opcodes,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
public void SU_Cvt_F_S_Fixed_D([ValueSource(nameof(_SU_Cvt_F_S_Fixed_D_))] uint opcodes,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint fBits)
{
uint immHb = (128 - fBits) & 0x7F;
@@ -578,12 +572,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource("_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(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(1u, 32u)] uint fBits,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
uint immHb = (64 - fBits) & 0x7F;
@@ -601,12 +595,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void SU_Cvt_F_V_Fixed_2D([ValueSource("_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(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint fBits)
{
uint immHb = (128 - fBits) & 0x7F;
@@ -622,12 +616,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Shl_Sli_S_D([ValueSource("_Shl_Sli_S_D_")] uint opcodes,
public void Shl_Sli_S_D([ValueSource(nameof(_Shl_Sli_S_D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(0u, 63u)] [Random(1u, 62u, RndCntShift)] uint shift)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 63u)] uint shift)
{
uint immHb = (64 + shift) & 0x7F;
@@ -643,12 +637,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Shl_Sli_V_8B_16B([ValueSource("_Shl_Sli_V_8B_16B_")] uint opcodes,
public void Shl_Sli_V_8B_16B([ValueSource(nameof(_Shl_Sli_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntShift)] uint shift,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 7u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
uint immHb = (8 + shift) & 0x7F;
@@ -666,12 +660,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Shl_Sli_V_4H_8H([ValueSource("_Shl_Sli_V_4H_8H_")] uint opcodes,
public void Shl_Sli_V_4H_8H([ValueSource(nameof(_Shl_Sli_V_4H_8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntShift)] uint shift,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 15u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
uint immHb = (16 + shift) & 0x7F;
@@ -689,12 +683,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Shl_Sli_V_2S_4S([ValueSource("_Shl_Sli_V_2S_4S_")] uint opcodes,
public void Shl_Sli_V_2S_4S([ValueSource(nameof(_Shl_Sli_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(0u, 31u)] [Random(1u, 30u, RndCntShift)] uint shift,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 31u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
uint immHb = (32 + shift) & 0x7F;
@@ -712,12 +706,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Shl_Sli_V_2D([ValueSource("_Shl_Sli_V_2D_")] uint opcodes,
public void Shl_Sli_V_2D([ValueSource(nameof(_Shl_Sli_V_2D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(0u, 63u)] [Random(1u, 62u, RndCntShift)] uint shift)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(0u, 63u)] uint shift)
{
uint immHb = (64 + shift) & 0x7F;
@@ -733,12 +727,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_Shll_V_8B8H_16B8H([ValueSource("_SU_Shll_V_8B8H_16B8H_")] uint opcodes,
public void SU_Shll_V_8B8H_16B8H([ValueSource(nameof(_SU_Shll_V_8B8H_16B8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(0u, 7u)] [Random(1u, 6u, RndCntShift)] uint shift,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[Values(0u, 7u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <8B8H, 16B8H>
{
uint immHb = (8 + shift) & 0x7F;
@@ -756,12 +750,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_Shll_V_4H4S_8H4S([ValueSource("_SU_Shll_V_4H4S_8H4S_")] uint opcodes,
public void SU_Shll_V_4H4S_8H4S([ValueSource(nameof(_SU_Shll_V_4H4S_8H4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(0u, 15u)] [Random(1u, 14u, RndCntShift)] uint shift,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(0u, 15u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <4H4S, 8H4S>
{
uint immHb = (16 + shift) & 0x7F;
@@ -779,12 +773,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void SU_Shll_V_2S2D_4S2D([ValueSource("_SU_Shll_V_2S2D_4S2D_")] uint opcodes,
public void SU_Shll_V_2S2D_4S2D([ValueSource(nameof(_SU_Shll_V_2S2D_4S2D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(0u, 31u)] [Random(1u, 30u, RndCntShift)] uint shift,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(0u, 31u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <2S2D, 4S2D>
{
uint immHb = (32 + shift) & 0x7F;
@@ -802,12 +796,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImm_Sri_S_D([ValueSource("_ShrImm_Sri_S_D_")] uint opcodes,
public void ShrImm_Sri_S_D([ValueSource(nameof(_ShrImm_Sri_S_D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntShift)] uint shift)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint shift)
{
uint immHb = (128 - shift) & 0x7F;
@@ -823,12 +817,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImm_Sri_V_8B_16B([ValueSource("_ShrImm_Sri_V_8B_16B_")] uint opcodes,
public void ShrImm_Sri_V_8B_16B([ValueSource(nameof(_ShrImm_Sri_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong a,
[Values(1u, 8u)] [Random(2u, 7u, RndCntShift)] uint shift,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong a,
[Values(1u, 8u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
uint immHb = (16 - shift) & 0x7F;
@@ -846,12 +840,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImm_Sri_V_4H_8H([ValueSource("_ShrImm_Sri_V_4H_8H_")] uint opcodes,
public void ShrImm_Sri_V_4H_8H([ValueSource(nameof(_ShrImm_Sri_V_4H_8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(1u, 16u)] [Random(2u, 15u, RndCntShift)] uint shift,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(1u, 16u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <4H, 8H>
{
uint immHb = (32 - shift) & 0x7F;
@@ -869,12 +863,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImm_Sri_V_2S_4S([ValueSource("_ShrImm_Sri_V_2S_4S_")] uint opcodes,
public void ShrImm_Sri_V_2S_4S([ValueSource(nameof(_ShrImm_Sri_V_2S_4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntShift)] uint shift,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(1u, 32u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
uint immHb = (64 - shift) & 0x7F;
@@ -892,12 +886,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImm_Sri_V_2D([ValueSource("_ShrImm_Sri_V_2D_")] uint opcodes,
public void ShrImm_Sri_V_2D([ValueSource(nameof(_ShrImm_Sri_V_2D_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 64u)] [Random(2u, 63u, RndCntShift)] uint shift)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 64u)] uint shift)
{
uint immHb = (128 - shift) & 0x7F;
@@ -913,12 +907,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmNarrow_V_8H8B_8H16B([ValueSource("_ShrImmNarrow_V_8H8B_8H16B_")] uint opcodes,
public void ShrImmNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmNarrow_V_8H8B_8H16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(1u, 8u)] [Random(2u, 7u, RndCntShift)] uint shift,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(1u, 8u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <8H8B, 8H16B>
{
uint immHb = (16 - shift) & 0x7F;
@@ -936,12 +930,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmNarrow_V_4S4H_4S8H([ValueSource("_ShrImmNarrow_V_4S4H_4S8H_")] uint opcodes,
public void ShrImmNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmNarrow_V_4S4H_4S8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(1u, 16u)] [Random(2u, 15u, RndCntShift)] uint shift,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(1u, 16u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <4S4H, 4S8H>
{
uint immHb = (32 - shift) & 0x7F;
@@ -959,12 +953,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmNarrow_V_2D2S_2D4S([ValueSource("_ShrImmNarrow_V_2D2S_2D4S_")] uint opcodes,
public void ShrImmNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmNarrow_V_2D2S_2D4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntShift)] uint shift,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 32u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <2D2S, 2D4S>
{
uint immHb = (64 - shift) & 0x7F;
@@ -982,12 +976,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_S_HB([ValueSource("_ShrImmSaturatingNarrow_S_HB_")] uint opcodes,
public void ShrImmSaturatingNarrow_S_HB([ValueSource(nameof(_ShrImmSaturatingNarrow_S_HB_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1H_")] [Random(RndCnt)] ulong z,
[ValueSource("_1H_")] [Random(RndCnt)] ulong a,
[Values(1u, 8u)] [Random(2u, 7u, RndCntShift)] uint shift)
[ValueSource(nameof(_1H_))] ulong z,
[ValueSource(nameof(_1H_))] ulong a,
[Values(1u, 8u)] uint shift)
{
uint immHb = (16 - shift) & 0x7F;
@@ -1003,12 +997,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_S_SH([ValueSource("_ShrImmSaturatingNarrow_S_SH_")] uint opcodes,
public void ShrImmSaturatingNarrow_S_SH([ValueSource(nameof(_ShrImmSaturatingNarrow_S_SH_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1S_")] [Random(RndCnt)] ulong z,
[ValueSource("_1S_")] [Random(RndCnt)] ulong a,
[Values(1u, 16u)] [Random(2u, 15u, RndCntShift)] uint shift)
[ValueSource(nameof(_1S_))] ulong z,
[ValueSource(nameof(_1S_))] ulong a,
[Values(1u, 16u)] uint shift)
{
uint immHb = (32 - shift) & 0x7F;
@@ -1024,12 +1018,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_S_DS([ValueSource("_ShrImmSaturatingNarrow_S_DS_")] uint opcodes,
public void ShrImmSaturatingNarrow_S_DS([ValueSource(nameof(_ShrImmSaturatingNarrow_S_DS_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntShift)] uint shift)
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 32u)] uint shift)
{
uint immHb = (64 - shift) & 0x7F;
@@ -1045,12 +1039,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_V_8H8B_8H16B([ValueSource("_ShrImmSaturatingNarrow_V_8H8B_8H16B_")] uint opcodes,
public void ShrImmSaturatingNarrow_V_8H8B_8H16B([ValueSource(nameof(_ShrImmSaturatingNarrow_V_8H8B_8H16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong a,
[Values(1u, 8u)] [Random(2u, 7u, RndCntShift)] uint shift,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong a,
[Values(1u, 8u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <8H8B, 8H16B>
{
uint immHb = (16 - shift) & 0x7F;
@@ -1068,12 +1062,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_V_4S4H_4S8H([ValueSource("_ShrImmSaturatingNarrow_V_4S4H_4S8H_")] uint opcodes,
public void ShrImmSaturatingNarrow_V_4S4H_4S8H([ValueSource(nameof(_ShrImmSaturatingNarrow_V_4S4H_4S8H_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong a,
[Values(1u, 16u)] [Random(2u, 15u, RndCntShift)] uint shift,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong a,
[Values(1u, 16u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <4S4H, 4S8H>
{
uint immHb = (32 - shift) & 0x7F;
@@ -1091,12 +1085,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ShrImmSaturatingNarrow_V_2D2S_2D4S([ValueSource("_ShrImmSaturatingNarrow_V_2D2S_2D4S_")] uint opcodes,
public void ShrImmSaturatingNarrow_V_2D2S_2D4S([ValueSource(nameof(_ShrImmSaturatingNarrow_V_2D2S_2D4S_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
[Values(1u, 32u)] [Random(2u, 31u, RndCntShift)] uint shift,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong a,
[Values(1u, 32u)] uint shift,
[Values(0b0u, 0b1u)] uint q) // <2D2S, 2D4S>
{
uint immHb = (64 - shift) & 0x7F;
@@ -1114,4 +1108,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -13,33 +13,30 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _1D_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _2S_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul,
0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _4H_()
{
return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
}
private static ulong[] _8B_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
}
#endregion
#region "ValueSource (Opcodes)"
private static uint[] _Vshr_Imm_SU8_()
{
return new uint[]
return new[]
{
0xf2880010u, // VSHR.S8 D0, D0, #8
0xf2880110u, // VSRA.S8 D0, D0, #8
@@ -50,7 +47,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vshr_Imm_SU16_()
{
return new uint[]
return new[]
{
0xf2900010u, // VSHR.S16 D0, D0, #16
0xf2900110u, // VSRA.S16 D0, D0, #16
@@ -61,7 +58,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vshr_Imm_SU32_()
{
return new uint[]
return new[]
{
0xf2a00010u, // VSHR.S32 D0, D0, #32
0xf2a00110u, // VSRA.S32 D0, D0, #32
@@ -72,7 +69,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vshr_Imm_SU64_()
{
return new uint[]
return new[]
{
0xf2800190u, // VSRA.S64 D0, D0, #64
0xf2800290u, // VRSHR.S64 D0, D0, #64
@@ -82,7 +79,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vqshrn_Vqrshrn_Vrshrn_Imm_()
{
return new uint[]
return new[]
{
0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN)
0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
@@ -92,7 +89,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _Vqshrun_Vqrshrun_Imm_()
{
return new uint[]
return new[]
{
0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
@@ -104,12 +101,12 @@ namespace Ryujinx.Tests.Cpu
private const int RndCntShiftImm = 2;
[Test, Pairwise]
public void Vshr_Imm_SU8([ValueSource("_Vshr_Imm_SU8_")] uint opcode,
public void Vshr_Imm_SU8([ValueSource(nameof(_Vshr_Imm_SU8_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_8B_")] [Random(RndCnt)] ulong z,
[ValueSource("_8B_")] [Random(RndCnt)] ulong b,
[Values(1u, 8u)] [Random(2u, 7u, RndCntShiftImm)] uint shiftImm,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong b,
[Values(1u, 8u)] uint shiftImm,
[Values] bool u,
[Values] bool q)
{
@@ -119,12 +116,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vshr_Imm_SU16([ValueSource("_Vshr_Imm_SU16_")] uint opcode,
public void Vshr_Imm_SU16([ValueSource(nameof(_Vshr_Imm_SU16_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_4H_")] [Random(RndCnt)] ulong z,
[ValueSource("_4H_")] [Random(RndCnt)] ulong b,
[Values(1u, 16u)] [Random(2u, 15u, RndCntShiftImm)] uint shiftImm,
[ValueSource(nameof(_4H_))] ulong z,
[ValueSource(nameof(_4H_))] ulong b,
[Values(1u, 16u)] uint shiftImm,
[Values] bool u,
[Values] bool q)
{
@@ -134,12 +131,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vshr_Imm_SU32([ValueSource("_Vshr_Imm_SU32_")] uint opcode,
public void Vshr_Imm_SU32([ValueSource(nameof(_Vshr_Imm_SU32_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_2S_")] [Random(RndCnt)] ulong z,
[ValueSource("_2S_")] [Random(RndCnt)] ulong b,
[Values(1u, 32u)] [Random(2u, 31u, RndCntShiftImm)] uint shiftImm,
[ValueSource(nameof(_2S_))] ulong z,
[ValueSource(nameof(_2S_))] ulong b,
[Values(1u, 32u)] uint shiftImm,
[Values] bool u,
[Values] bool q)
{
@@ -149,12 +146,12 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vshr_Imm_SU64([ValueSource("_Vshr_Imm_SU64_")] uint opcode,
public void Vshr_Imm_SU64([ValueSource(nameof(_Vshr_Imm_SU64_))] uint opcode,
[Range(0u, 3u)] uint rd,
[Range(0u, 3u)] uint rm,
[ValueSource("_1D_")] [Random(RndCnt)] ulong z,
[ValueSource("_1D_")] [Random(RndCnt)] ulong b,
[Values(1u, 64u)] [Random(2u, 63u, RndCntShiftImm)] uint shiftImm,
[ValueSource(nameof(_1D_))] ulong z,
[ValueSource(nameof(_1D_))] ulong b,
[Values(1u, 64u)] uint shiftImm,
[Values] bool u,
[Values] bool q)
{
@@ -195,7 +192,7 @@ namespace Ryujinx.Tests.Cpu
public void Vshl_Imm([Values(0u)] uint rd,
[Values(2u, 0u)] uint rm,
[Values(0u, 1u, 2u, 3u)] uint size,
[Random(RndCntShiftImm)] [Values(0u)] uint shiftImm,
[Random(RndCntShiftImm)] uint shiftImm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
@@ -229,7 +226,7 @@ namespace Ryujinx.Tests.Cpu
public void Vshrn_Imm([Values(0u, 1u)] uint rd,
[Values(2u, 0u)] uint rm,
[Values(0u, 1u, 2u)] uint size,
[Random(RndCntShiftImm)] [Values(0u)] uint shiftImm,
[Random(RndCntShiftImm)] uint shiftImm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b)
@@ -253,11 +250,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vqshrn_Vqrshrn_Vrshrn_Imm([ValueSource("_Vqshrn_Vqrshrn_Vrshrn_Imm_")] uint opcode,
public void Vqshrn_Vqrshrn_Vrshrn_Imm([ValueSource(nameof(_Vqshrn_Vqrshrn_Vrshrn_Imm_))] uint opcode,
[Values(0u, 1u)] uint rd,
[Values(2u, 0u)] uint rm,
[Values(0u, 1u, 2u)] uint size,
[Random(RndCntShiftImm)] [Values(0u)] uint shiftImm,
[Random(RndCntShiftImm)] uint shiftImm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
@@ -287,11 +284,11 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Vqshrun_Vqrshrun_Imm([ValueSource("_Vqshrun_Vqrshrun_Imm_")] uint opcode,
public void Vqshrun_Vqrshrun_Imm([ValueSource(nameof(_Vqshrun_Vqrshrun_Imm_))] uint opcode,
[Values(0u, 1u)] uint rd,
[Values(2u, 0u)] uint rm,
[Values(0u, 1u, 2u)] uint size,
[Random(RndCntShiftImm)] [Values(0u)] uint shiftImm,
[Random(RndCntShiftImm)] uint shiftImm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b)
@@ -315,4 +312,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define SimdTbl
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -16,17 +14,17 @@ namespace Ryujinx.Tests.Cpu
#region "Helper methods"
private static ulong GenIdxsForTbls(int regs)
{
const byte idxInRngMin = (byte)0;
byte idxInRngMax = (byte)((16 * regs) - 1);
byte idxOutRngMin = (byte) (16 * regs);
const byte idxOutRngMax = (byte)255;
const byte idxInRngMin = 0;
byte idxInRngMax = (byte)((16 * regs) - 1);
byte idxOutRngMin = (byte) (16 * regs);
const byte idxOutRngMax = 255;
ulong idxs = 0ul;
for (int cnt = 1; cnt <= 8; cnt++)
{
ulong idxInRng = (ulong)TestContext.CurrentContext.Random.NextByte(idxInRngMin, idxInRngMax);
ulong idxOutRng = (ulong)TestContext.CurrentContext.Random.NextByte(idxOutRngMin, idxOutRngMax);
ulong idxInRng = TestContext.CurrentContext.Random.NextByte(idxInRngMin, idxInRngMax);
ulong idxOutRng = TestContext.CurrentContext.Random.NextByte(idxOutRngMin, idxOutRngMax);
ulong idx = TestContext.CurrentContext.Random.NextBool() ? idxInRng : idxOutRng;
@@ -40,8 +38,8 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Types)"
private static ulong[] _8B_()
{
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
}
private static IEnumerable<ulong> _GenIdxsForTbl1_()
@@ -100,7 +98,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _SingleRegisterTable_V_8B_16B_()
{
return new uint[]
return new[]
{
0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B
0x0E001000u // TBX V0.8B, { V0.16B }, V0.8B
@@ -109,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _TwoRegisterTable_V_8B_16B_()
{
return new uint[]
return new[]
{
0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B
0x0E003000u // TBX V0.8B, { V0.16B, V1.16B }, V0.8B
@@ -118,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _ThreeRegisterTable_V_8B_16B_()
{
return new uint[]
return new[]
{
0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
0x0E005000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
@@ -127,7 +125,7 @@ namespace Ryujinx.Tests.Cpu
private static uint[] _FourRegisterTable_V_8B_16B_()
{
return new uint[]
return new[]
{
0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
0x0E006000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
@@ -135,18 +133,16 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCntDest = 2;
private const int RndCntTbls = 2;
private const int RndCntIdxs = 2;
[Test, Pairwise]
public void SingleRegisterTable_V_8B_16B([ValueSource("_SingleRegisterTable_V_8B_16B_")] uint opcodes,
public void SingleRegisterTable_V_8B_16B([ValueSource(nameof(_SingleRegisterTable_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u)] uint rn,
[Values(2u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_GenIdxsForTbl1_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_GenIdxsForTbl1_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -162,14 +158,14 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void TwoRegisterTable_V_8B_16B([ValueSource("_TwoRegisterTable_V_8B_16B_")] uint opcodes,
public void TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u)] uint rn,
[Values(3u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_GenIdxsForTbl2_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_GenIdxsForTbl2_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -186,14 +182,14 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Mod_TwoRegisterTable_V_8B_16B([ValueSource("_TwoRegisterTable_V_8B_16B_")] uint opcodes,
public void Mod_TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 1u)] uint rd,
[Values(31u)] uint rn,
[Values(1u, 30u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_GenIdxsForTbl2_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_GenIdxsForTbl2_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -210,15 +206,15 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void ThreeRegisterTable_V_8B_16B([ValueSource("_ThreeRegisterTable_V_8B_16B_")] uint opcodes,
public void ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u)] uint rn,
[Values(4u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2,
[ValueSource("_GenIdxsForTbl3_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_8B_))] ulong table2,
[ValueSource(nameof(_GenIdxsForTbl3_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -236,15 +232,15 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource("_ThreeRegisterTable_V_8B_16B_")] uint opcodes,
public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 2u)] uint rd,
[Values(31u)] uint rn,
[Values(2u, 30u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2,
[ValueSource("_GenIdxsForTbl3_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_8B_))] ulong table2,
[ValueSource(nameof(_GenIdxsForTbl3_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -262,16 +258,16 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void FourRegisterTable_V_8B_16B([ValueSource("_FourRegisterTable_V_8B_16B_")] uint opcodes,
public void FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes,
[Values(0u)] uint rd,
[Values(1u)] uint rn,
[Values(5u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3,
[ValueSource("_GenIdxsForTbl4_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_8B_))] ulong table2,
[ValueSource(nameof(_8B_))] ulong table3,
[ValueSource(nameof(_GenIdxsForTbl4_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -290,16 +286,16 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise]
public void Mod_FourRegisterTable_V_8B_16B([ValueSource("_FourRegisterTable_V_8B_16B_")] uint opcodes,
public void Mod_FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes,
[Values(30u, 3u)] uint rd,
[Values(31u)] uint rn,
[Values(3u, 30u)] uint rm,
[ValueSource("_8B_")] [Random(RndCntDest)] ulong z,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2,
[ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3,
[ValueSource("_GenIdxsForTbl4_")] ulong indexes,
[ValueSource(nameof(_8B_))] ulong z,
[ValueSource(nameof(_8B_))] ulong table0,
[ValueSource(nameof(_8B_))] ulong table1,
[ValueSource(nameof(_8B_))] ulong table2,
[ValueSource(nameof(_8B_))] ulong table3,
[ValueSource(nameof(_GenIdxsForTbl4_))] ulong indexes,
[Values(0b0u, 0b1u)] uint q) // <8B, 16B>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
@@ -318,4 +314,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -1,9 +1,7 @@
#define System
using ARMeilleure.State;
using NUnit.Framework;
using System.Collections.Generic;
namespace Ryujinx.Tests.Cpu
@@ -40,7 +38,7 @@ namespace Ryujinx.Tests.Cpu
#region "ValueSource (Opcodes)"
private static uint[] _MrsMsr_Nzcv_()
{
return new uint[]
return new[]
{
0xD53B4200u, // MRS X0, NZCV
0xD51B4200u // MSR NZCV, X0
@@ -48,12 +46,10 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[Test, Pairwise]
public void MrsMsr_Nzcv([ValueSource("_MrsMsr_Nzcv_")] uint opcodes,
[Values(0u, 1u, 31u)] uint rt,
[ValueSource("_GenNzcv_")] [Random(RndCnt)] ulong xt)
[ValueSource("_GenNzcv_")] ulong xt)
{
opcodes |= (rt & 31) << 0;
@@ -70,4 +66,4 @@ namespace Ryujinx.Tests.Cpu
}
#endif
}
}
}

View File

@@ -142,10 +142,10 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetContext().GetX(1), Is.EqualTo(w1 ^ w2));
break;
case 2:
Assert.That(GetContext().GetX(1), Is.EqualTo(shift >= 32 ? 0 : (uint)(w1 << (int)shift)));
Assert.That(GetContext().GetX(1), Is.EqualTo(shift >= 32 ? 0 : w1 << (int)shift));
break;
case 3:
Assert.That(GetContext().GetX(1), Is.EqualTo(shift >= 32 ? 0 : (uint)(w1 >> (int)shift)));
Assert.That(GetContext().GetX(1), Is.EqualTo(shift >= 32 ? 0 : w1 >> (int)shift));
break;
case 4:
Assert.That(GetContext().GetX(1), Is.EqualTo(shift >= 32 ? (uint)((int)w1 >> 31) : (uint)((int)w1 >> (int)shift)));

View File

@@ -0,0 +1,97 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
namespace Ryujinx.Ui.Common.Helper
{
[SupportedOSPlatform("macos")]
public static partial class ObjectiveC
{
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
private static unsafe partial IntPtr sel_getUid(string name);
[LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
public static partial IntPtr objc_getClass(string name);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
[LibraryImport(ObjCRuntime)]
public static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
[LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
public struct Selector
{
public readonly IntPtr SelPtr;
public unsafe Selector(string name)
{
SelPtr = sel_getUid(name);
}
public static implicit operator Selector(string value) => new(value);
}
public struct NSString
{
public readonly IntPtr StrPtr;
public NSString(string aString)
{
IntPtr nsString = objc_getClass("NSString");
StrPtr = IntPtr_objc_msgSend(nsString, "stringWithUTF8String:", aString);
}
public static implicit operator IntPtr(NSString nsString) => nsString.StrPtr;
}
public readonly struct NSPoint
{
public readonly double X;
public readonly double Y;
public NSPoint(double x, double y)
{
X = x;
Y = y;
}
}
public readonly struct NSRect
{
public readonly NSPoint Pos;
public readonly NSPoint Size;
public NSRect(double x, double y, double width, double height)
{
Pos = new NSPoint(x, y);
Size = new NSPoint(width, height);
}
}
}
}

View File

@@ -55,7 +55,17 @@ namespace Ryujinx.Ui.Common.Helper
}
else if (OperatingSystem.IsMacOS())
{
Process.Start("open", $"-R \"{path}\"");
ObjectiveC.NSString nsStringPath = new(path);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "fileURLWithPath:", nsStringPath);
IntPtr nsArray = ObjectiveC.objc_getClass("NSArray");
IntPtr urlArray = ObjectiveC.IntPtr_objc_msgSend(nsArray, "arrayWithObject:", urlPtr);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
ObjectiveC.objc_msgSend(sharedWorkspace, "activateFileViewerSelectingURLs:", urlArray);
}
else if (OperatingSystem.IsLinux())
{
@@ -84,7 +94,14 @@ namespace Ryujinx.Ui.Common.Helper
}
else if (OperatingSystem.IsMacOS())
{
Process.Start("open", url);
ObjectiveC.NSString nsStringPath = new(url);
IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "URLWithString:", nsStringPath);
IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
ObjectiveC.bool_objc_msgSend(sharedWorkspace, "openURL:", urlPtr);
}
else
{

View File

@@ -9,6 +9,7 @@ using Ryujinx.Ui;
using Ryujinx.Ui.Widgets;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
@@ -23,20 +24,20 @@ namespace Ryujinx.Modules
{
public static class Updater
{
private const string GitHubApiURL = "https://api.github.com";
private const int ConnectionCount = 4;
internal static bool Running;
private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
private static readonly string UpdatePublishDir = Path.Combine(UpdateDir, "publish");
private static readonly int ConnectionCount = 4;
private static string _buildVer;
private static string _platformExt;
private static string _buildUrl;
private static long _buildSize;
private const string GitHubApiURL = "https://api.github.com";
// On Windows, GtkSharp.Dependencies adds these extra dirs that must be cleaned during updates.
private static readonly string[] WindowsDependencyDirs = new string[] { "bin", "etc", "lib", "share" };
@@ -44,7 +45,7 @@ namespace Ryujinx.Modules
{
HttpClient result = new HttpClient();
// Required by GitHub to interract with APIs.
// Required by GitHub to interact with APIs.
result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
return result;
@@ -101,50 +102,48 @@ namespace Ryujinx.Modules
// Get latest version number from GitHub API
try
{
using (HttpClient jsonClient = ConstructHttpClient())
using HttpClient jsonClient = ConstructHttpClient();
string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
// Fetch latest build information
string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL);
JObject jsonRoot = JObject.Parse(fetchedJson);
JToken assets = jsonRoot["assets"];
_buildVer = (string)jsonRoot["name"];
foreach (JToken asset in assets)
{
string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
string assetName = (string)asset["name"];
string assetState = (string)asset["state"];
string downloadURL = (string)asset["browser_download_url"];
// Fetch latest build information
string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL);
JObject jsonRoot = JObject.Parse(fetchedJson);
JToken assets = jsonRoot["assets"];
_buildVer = (string)jsonRoot["name"];
foreach (JToken asset in assets)
if (assetName.StartsWith("ryujinx") && assetName.EndsWith(_platformExt))
{
string assetName = (string)asset["name"];
string assetState = (string)asset["state"];
string downloadURL = (string)asset["browser_download_url"];
_buildUrl = downloadURL;
if (assetName.StartsWith("ryujinx") && assetName.EndsWith(_platformExt))
if (assetState != "uploaded")
{
_buildUrl = downloadURL;
if (assetState != "uploaded")
if (showVersionUpToDate)
{
if (showVersionUpToDate)
{
GtkDialog.CreateUpdaterInfoDialog("You are already using the latest version of Ryujinx!", "");
}
return;
GtkDialog.CreateUpdaterInfoDialog("You are already using the latest version of Ryujinx!", "");
}
break;
return;
}
}
if (_buildUrl == null)
break;
}
}
if (_buildUrl == null)
{
if (showVersionUpToDate)
{
if (showVersionUpToDate)
{
GtkDialog.CreateUpdaterInfoDialog("You are already using the latest version of Ryujinx!", "");
}
return;
GtkDialog.CreateUpdaterInfoDialog("You are already using the latest version of Ryujinx!", "");
}
return;
}
}
catch (Exception exception)
@@ -247,160 +246,142 @@ namespace Ryujinx.Modules
for (int i = 0; i < ConnectionCount; i++)
{
list.Add(new byte[0]);
list.Add(Array.Empty<byte>());
}
for (int i = 0; i < ConnectionCount; i++)
{
#pragma warning disable SYSLIB0014
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
using (WebClient client = new WebClient())
using WebClient client = new WebClient();
#pragma warning restore SYSLIB0014
webClients.Add(client);
if (i == ConnectionCount - 1)
{
webClients.Add(client);
client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}");
}
else
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{chunkSize * (i + 1) - 1}");
}
if (i == ConnectionCount - 1)
client.DownloadProgressChanged += (_, args) =>
{
int index = (int)args.UserState;
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
updateDialog.ProgressBar.Value = totalProgressPercentage / ConnectionCount;
};
client.DownloadDataCompleted += (_, args) =>
{
int index = (int)args.UserState;
if (args.Cancelled)
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}");
}
else
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{chunkSize * (i + 1) - 1}");
}
client.DownloadProgressChanged += (_, args) =>
{
int index = (int)args.UserState;
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
updateDialog.ProgressBar.Value = totalProgressPercentage / ConnectionCount;
};
client.DownloadDataCompleted += (_, args) =>
{
int index = (int)args.UserState;
if (args.Cancelled)
{
webClients[index].Dispose();
return;
}
list[index] = args.Result;
Interlocked.Increment(ref completedRequests);
if (Equals(completedRequests, ConnectionCount))
{
byte[] mergedFileBytes = new byte[_buildSize];
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
{
Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
destinationOffset += list[connectionIndex].Length;
}
File.WriteAllBytes(updateFile, mergedFileBytes);
try
{
InstallUpdate(updateDialog, updateFile);
}
catch (Exception e)
{
Logger.Warning?.Print(LogClass.Application, e.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
return;
}
}
};
try
{
client.DownloadDataAsync(new Uri(downloadUrl), i);
}
catch (WebException ex)
{
Logger.Warning?.Print(LogClass.Application, ex.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
for (int j = 0; j < webClients.Count; j++)
{
webClients[j].CancelAsync();
}
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
webClients[index].Dispose();
return;
}
list[index] = args.Result;
Interlocked.Increment(ref completedRequests);
if (Equals(completedRequests, ConnectionCount))
{
byte[] mergedFileBytes = new byte[_buildSize];
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
{
Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
destinationOffset += list[connectionIndex].Length;
}
File.WriteAllBytes(updateFile, mergedFileBytes);
try
{
InstallUpdate(updateDialog, updateFile);
}
catch (Exception e)
{
Logger.Warning?.Print(LogClass.Application, e.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
return;
}
}
};
try
{
client.DownloadDataAsync(new Uri(downloadUrl), i);
}
catch (WebException ex)
{
Logger.Warning?.Print(LogClass.Application, ex.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
foreach (WebClient webClient in webClients)
{
webClient.CancelAsync();
}
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
return;
}
}
}
private static void DoUpdateWithSingleThreadWorker(UpdateDialog updateDialog, string downloadUrl, string updateFile)
{
using (HttpClient client = new HttpClient())
using HttpClient client = new HttpClient();
// We do not want to timeout while downloading
client.Timeout = TimeSpan.FromDays(1);
using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
{
// We do not want to timeout while downloading
client.Timeout = TimeSpan.FromDays(1);
using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
using (Stream updateFileStream = File.Open(updateFile, FileMode.Create))
{
using (Stream updateFileStream = File.Open(updateFile, FileMode.Create))
long totalBytes = response.Content.Headers.ContentLength.Value;
long byteWritten = 0;
byte[] buffer = new byte[32 * 1024];
while (true)
{
long totalBytes = response.Content.Headers.ContentLength.Value;
long byteWritten = 0;
int readSize = remoteFileStream.Read(buffer);
byte[] buffer = new byte[32 * 1024];
while (true)
if (readSize == 0)
{
int readSize = remoteFileStream.Read(buffer);
if (readSize == 0)
{
break;
}
byteWritten += readSize;
updateDialog.ProgressBar.Value = ((double)byteWritten / totalBytes) * 100;
updateFileStream.Write(buffer, 0, readSize);
break;
}
byteWritten += readSize;
updateDialog.ProgressBar.Value = ((double)byteWritten / totalBytes) * 100;
updateFileStream.Write(buffer, 0, readSize);
}
}
InstallUpdate(updateDialog, updateFile);
}
InstallUpdate(updateDialog, updateFile);
}
private static void DoUpdateWithSingleThread(UpdateDialog updateDialog, string downloadUrl, string updateFile)
{
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(updateDialog, downloadUrl, updateFile));
worker.Name = "Updater.SingleThreadWorker";
worker.Start();
}
private static void SetFileExecutable(string path)
{
const UnixFileMode ExecutableFileMode = UnixFileMode.UserExecute |
UnixFileMode.UserWrite |
UnixFileMode.UserRead |
UnixFileMode.GroupRead |
UnixFileMode.GroupWrite |
UnixFileMode.OtherRead |
UnixFileMode.OtherWrite;
if (!OperatingSystem.IsWindows() && File.Exists(path))
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(updateDialog, downloadUrl, updateFile))
{
File.SetUnixFileMode(path, ExecutableFileMode);
}
Name = "Updater.SingleThreadWorker"
};
worker.Start();
}
private static async void InstallUpdate(UpdateDialog updateDialog, string updateFile)
@@ -411,15 +392,17 @@ namespace Ryujinx.Modules
if (OperatingSystem.IsLinux())
{
using (Stream inStream = File.OpenRead(updateFile))
using (Stream gzipStream = new GZipInputStream(inStream))
using (TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII))
{
updateDialog.ProgressBar.MaxValue = inStream.Length;
using Stream inStream = File.OpenRead(updateFile);
using Stream gzipStream = new GZipInputStream(inStream);
using TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII);
updateDialog.ProgressBar.MaxValue = inStream.Length;
await Task.Run(() =>
await Task.Run(() =>
{
TarEntry tarEntry;
if (!OperatingSystem.IsWindows())
{
TarEntry tarEntry;
while ((tarEntry = tarStream.GetNextEntry()) != null)
{
if (tarEntry.IsDirectory) continue;
@@ -433,6 +416,7 @@ namespace Ryujinx.Modules
tarStream.CopyEntryContents(outStream);
}
File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
TarEntry entry = tarEntry;
@@ -442,43 +426,41 @@ namespace Ryujinx.Modules
updateDialog.ProgressBar.Value += entry.Size;
});
}
});
}
});
updateDialog.ProgressBar.Value = inStream.Length;
}
updateDialog.ProgressBar.Value = inStream.Length;
}
else
{
using (Stream inStream = File.OpenRead(updateFile))
using (ZipFile zipFile = new ZipFile(inStream))
using Stream inStream = File.OpenRead(updateFile);
using ZipFile zipFile = new ZipFile(inStream);
updateDialog.ProgressBar.MaxValue = zipFile.Count;
await Task.Run(() =>
{
updateDialog.ProgressBar.MaxValue = zipFile.Count;
await Task.Run(() =>
foreach (ZipEntry zipEntry in zipFile)
{
foreach (ZipEntry zipEntry in zipFile)
if (zipEntry.IsDirectory) continue;
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
using (Stream zipStream = zipFile.GetInputStream(zipEntry))
using (FileStream outStream = File.OpenWrite(outPath))
{
if (zipEntry.IsDirectory) continue;
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
using (Stream zipStream = zipFile.GetInputStream(zipEntry))
using (FileStream outStream = File.OpenWrite(outPath))
{
zipStream.CopyTo(outStream);
}
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
Application.Invoke(delegate
{
updateDialog.ProgressBar.Value++;
});
zipStream.CopyTo(outStream);
}
});
}
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
Application.Invoke(delegate
{
updateDialog.ProgressBar.Value++;
});
}
});
}
// Delete downloaded zip
@@ -522,8 +504,6 @@ namespace Ryujinx.Modules
Directory.Delete(UpdateDir, true);
SetFileExecutable(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"));
updateDialog.MainText.Text = "Update Complete!";
updateDialog.SecondaryText.Text = "Do you want to restart Ryujinx now?";
updateDialog.Modal = true;
@@ -640,4 +620,4 @@ namespace Ryujinx.Modules
}
}
}
}
}