Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a5a9b9bc8b | ||
|
17078ad929 | ||
|
32450d45de | ||
|
ed7a0474c6 | ||
|
fe9c49949a | ||
|
052b23c83c | ||
|
e4f68592c3 | ||
|
1dcd44b94f | ||
|
61b1ce252f | ||
|
5f38086f94 | ||
|
7bae440d3a | ||
|
f1943fd0b6 | ||
|
ec8d4f3af5 | ||
|
b3f0978869 | ||
|
f614d2c435 | ||
|
40c9416097 | ||
|
618c8edc79 | ||
|
99fc4fa61b | ||
|
f6d5499a16 | ||
|
26bf13a65d | ||
|
96cf242bcf |
57
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
57
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -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:
|
||||
|
12
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
12
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -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
|
||||
|
@@ -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:
|
||||
|
10
.github/ISSUE_TEMPLATE/missing_service_call.yml
vendored
10
.github/ISSUE_TEMPLATE/missing_service_call.yml
vendored
@@ -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
|
||||
|
@@ -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>
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
@@ -725,10 +725,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
return;
|
||||
}
|
||||
|
||||
bool clearDepth = (argument & 1) != 0;
|
||||
bool clearStencil = (argument & 2) != 0;
|
||||
uint componentMask = (uint)((argument >> 2) & 0xf);
|
||||
int index = (argument >> 6) & 0xf;
|
||||
int layer = (argument >> 10) & 0x3ff;
|
||||
|
||||
engine.UpdateRenderTargetState(useControl: false, layered: layer != 0 || layerCount > 1, singleUse: index);
|
||||
RenderTargetUpdateFlags updateFlags = RenderTargetUpdateFlags.SingleColor;
|
||||
|
||||
if (layer != 0 || layerCount > 1)
|
||||
{
|
||||
updateFlags |= RenderTargetUpdateFlags.Layered;
|
||||
}
|
||||
|
||||
if (clearDepth || clearStencil)
|
||||
{
|
||||
updateFlags |= RenderTargetUpdateFlags.UpdateDepthStencil;
|
||||
}
|
||||
|
||||
engine.UpdateRenderTargetState(updateFlags, singleUse: componentMask != 0 ? index : -1);
|
||||
|
||||
// If there is a mismatch on the host clip region and the one explicitly defined by the guest
|
||||
// on the screen scissor state, then we need to force only one texture to be bound to avoid
|
||||
@@ -788,18 +803,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
_context.Renderer.Pipeline.SetScissors(scissors);
|
||||
}
|
||||
|
||||
if (clipMismatch)
|
||||
{
|
||||
_channel.TextureManager.UpdateRenderTarget(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
_channel.TextureManager.UpdateRenderTargets();
|
||||
}
|
||||
|
||||
bool clearDepth = (argument & 1) != 0;
|
||||
bool clearStencil = (argument & 2) != 0;
|
||||
uint componentMask = (uint)((argument >> 2) & 0xf);
|
||||
_channel.TextureManager.UpdateRenderTargets();
|
||||
|
||||
if (componentMask != 0)
|
||||
{
|
||||
@@ -841,7 +845,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
engine.UpdateScissorState();
|
||||
}
|
||||
|
||||
engine.UpdateRenderTargetState(useControl: true);
|
||||
engine.UpdateRenderTargetState(RenderTargetUpdateFlags.UpdateAll);
|
||||
|
||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||
{
|
||||
|
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags indicating how the render targets should be updated.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
enum RenderTargetUpdateFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// No flags.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Get render target index from the control register.
|
||||
/// </summary>
|
||||
UseControl = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that all render targets are 2D array textures.
|
||||
/// </summary>
|
||||
Layered = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that only a single color target will be used.
|
||||
/// </summary>
|
||||
SingleColor = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the depth-stencil target will be used.
|
||||
/// </summary>
|
||||
UpdateDepthStencil = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// Default update flags for draw.
|
||||
/// </summary>
|
||||
UpdateAll = UseControl | UpdateDepthStencil
|
||||
}
|
||||
}
|
@@ -402,20 +402,23 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
/// </summary>
|
||||
private void UpdateRenderTargetState()
|
||||
{
|
||||
UpdateRenderTargetState(true);
|
||||
UpdateRenderTargetState(RenderTargetUpdateFlags.UpdateAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
||||
/// </summary>
|
||||
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
||||
/// <param name="layered">Indicates if the texture is layered</param>
|
||||
/// <param name="updateFlags">Flags indicating which render targets should be updated and how</param>
|
||||
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
||||
public void UpdateRenderTargetState(bool useControl, bool layered = false, int singleUse = -1)
|
||||
public void UpdateRenderTargetState(RenderTargetUpdateFlags updateFlags, int singleUse = -1)
|
||||
{
|
||||
var memoryManager = _channel.MemoryManager;
|
||||
var rtControl = _state.State.RtControl;
|
||||
|
||||
bool useControl = updateFlags.HasFlag(RenderTargetUpdateFlags.UseControl);
|
||||
bool layered = updateFlags.HasFlag(RenderTargetUpdateFlags.Layered);
|
||||
bool singleColor = updateFlags.HasFlag(RenderTargetUpdateFlags.SingleColor);
|
||||
|
||||
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
|
||||
|
||||
var msaaMode = _state.State.RtMsaaMode;
|
||||
@@ -438,7 +441,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
var colorState = _state.State.RtColorState[rtIndex];
|
||||
|
||||
if (index >= count || !IsRtEnabled(colorState))
|
||||
if (index >= count || !IsRtEnabled(colorState) || (singleColor && index != singleUse))
|
||||
{
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, null);
|
||||
|
||||
@@ -478,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
Image.Texture depthStencil = null;
|
||||
|
||||
if (dsEnable)
|
||||
if (dsEnable && updateFlags.HasFlag(RenderTargetUpdateFlags.UpdateDepthStencil))
|
||||
{
|
||||
var dsState = _state.State.RtDepthStencilState;
|
||||
var dsSize = _state.State.RtDepthStencilSize;
|
||||
|
@@ -139,12 +139,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
/// <summary>
|
||||
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
||||
/// </summary>
|
||||
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
||||
/// <param name="layered">Indicates if the texture is layered</param>
|
||||
/// <param name="updateFlags">Flags indicating which render targets should be updated and how</param>
|
||||
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
||||
public void UpdateRenderTargetState(bool useControl, bool layered = false, int singleUse = -1)
|
||||
public void UpdateRenderTargetState(RenderTargetUpdateFlags updateFlags, int singleUse = -1)
|
||||
{
|
||||
_stateUpdater.UpdateRenderTargetState(useControl, layered, singleUse);
|
||||
_stateUpdater.UpdateRenderTargetState(updateFlags, singleUse);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -33,10 +33,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
class AutoDeleteCache : IEnumerable<Texture>
|
||||
{
|
||||
private const int MinCountForDeletion = 32;
|
||||
private const int MaxCapacity = 2048;
|
||||
private const ulong MaxTextureSizeCapacity = 512 * 1024 * 1024; // MB;
|
||||
|
||||
private readonly LinkedList<Texture> _textures;
|
||||
private readonly ConcurrentQueue<Texture> _deferredRemovals;
|
||||
private ulong _totalSize;
|
||||
|
||||
private HashSet<ShortTextureCacheEntry> _shortCacheBuilder;
|
||||
private HashSet<ShortTextureCacheEntry> _shortCache;
|
||||
@@ -49,7 +51,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
public AutoDeleteCache()
|
||||
{
|
||||
_textures = new LinkedList<Texture>();
|
||||
_deferredRemovals = new ConcurrentQueue<Texture>();
|
||||
|
||||
_shortCacheBuilder = new HashSet<ShortTextureCacheEntry>();
|
||||
_shortCache = new HashSet<ShortTextureCacheEntry>();
|
||||
@@ -67,37 +68,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <param name="texture">The texture to be added to the cache</param>
|
||||
public void Add(Texture texture)
|
||||
{
|
||||
texture.IncrementReferenceCount();
|
||||
_totalSize += texture.Size;
|
||||
|
||||
texture.IncrementReferenceCount();
|
||||
texture.CacheNode = _textures.AddLast(texture);
|
||||
|
||||
if (_textures.Count > MaxCapacity)
|
||||
if (_textures.Count > MaxCapacity ||
|
||||
(_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion))
|
||||
{
|
||||
Texture oldestTexture = _textures.First.Value;
|
||||
|
||||
if (!oldestTexture.CheckModified(false))
|
||||
{
|
||||
// The texture must be flushed if it falls out of the auto delete cache.
|
||||
// Flushes out of the auto delete cache do not trigger write tracking,
|
||||
// as it is expected that other overlapping textures exist that have more up-to-date contents.
|
||||
|
||||
oldestTexture.Group.SynchronizeDependents(oldestTexture);
|
||||
oldestTexture.FlushModified(false);
|
||||
}
|
||||
|
||||
_textures.RemoveFirst();
|
||||
|
||||
oldestTexture.DecrementReferenceCount();
|
||||
|
||||
oldestTexture.CacheNode = null;
|
||||
}
|
||||
|
||||
if (_deferredRemovals.Count > 0)
|
||||
{
|
||||
while (_deferredRemovals.TryDequeue(out Texture textureToRemove))
|
||||
{
|
||||
Remove(textureToRemove, false);
|
||||
}
|
||||
RemoveLeastUsedTexture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +99,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
texture.CacheNode = _textures.AddLast(texture);
|
||||
}
|
||||
|
||||
if (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)
|
||||
{
|
||||
RemoveLeastUsedTexture();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -127,6 +111,31 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the least used texture from the cache.
|
||||
/// </summary>
|
||||
private void RemoveLeastUsedTexture()
|
||||
{
|
||||
Texture oldestTexture = _textures.First.Value;
|
||||
|
||||
_totalSize -= oldestTexture.Size;
|
||||
|
||||
if (!oldestTexture.CheckModified(false))
|
||||
{
|
||||
// The texture must be flushed if it falls out of the auto delete cache.
|
||||
// Flushes out of the auto delete cache do not trigger write tracking,
|
||||
// as it is expected that other overlapping textures exist that have more up-to-date contents.
|
||||
|
||||
oldestTexture.Group.SynchronizeDependents(oldestTexture);
|
||||
oldestTexture.FlushModified(false);
|
||||
}
|
||||
|
||||
_textures.RemoveFirst();
|
||||
|
||||
oldestTexture.DecrementReferenceCount();
|
||||
oldestTexture.CacheNode = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a texture from the cache.
|
||||
/// </summary>
|
||||
@@ -148,20 +157,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
_textures.Remove(texture.CacheNode);
|
||||
|
||||
_totalSize -= texture.Size;
|
||||
|
||||
texture.CacheNode = null;
|
||||
|
||||
return texture.DecrementReferenceCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues removal of a texture from the cache in a thread safe way.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to be removed from the cache</param>
|
||||
public void RemoveDeferred(Texture texture)
|
||||
{
|
||||
_deferredRemovals.Enqueue(texture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to find a texture on the short duration cache.
|
||||
/// </summary>
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
@@ -89,12 +88,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
public TextureGroup Group { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set when a texture has been changed size. This indicates that it may need to be
|
||||
/// changed again when obtained as a sampler.
|
||||
/// </summary>
|
||||
public bool ChangedSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set when a texture's GPU VA has ever been partially or fully unmapped.
|
||||
/// This indicates that the range must be fully checked when matching the texture.
|
||||
@@ -410,122 +403,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
Group.CreateCopyDependency(contained, FirstLayer + layer, FirstLevel + level, copyTo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the texture size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This operation may also change the size of all mipmap levels, including from the parent
|
||||
/// and other possible child textures, to ensure that all sizes are consistent.
|
||||
/// </remarks>
|
||||
/// <param name="width">The new texture width</param>
|
||||
/// <param name="height">The new texture height</param>
|
||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
||||
public void ChangeSize(int width, int height, int depthOrLayers)
|
||||
{
|
||||
int blockWidth = Info.FormatInfo.BlockWidth;
|
||||
int blockHeight = Info.FormatInfo.BlockHeight;
|
||||
|
||||
width <<= FirstLevel;
|
||||
height <<= FirstLevel;
|
||||
|
||||
if (Target == Target.Texture3D)
|
||||
{
|
||||
depthOrLayers <<= FirstLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
depthOrLayers = _viewStorage.Info.DepthOrLayers;
|
||||
}
|
||||
|
||||
_viewStorage.RecreateStorageOrView(width, height, blockWidth, blockHeight, depthOrLayers);
|
||||
|
||||
foreach (Texture view in _viewStorage._views)
|
||||
{
|
||||
int viewWidth = Math.Max(1, width >> view.FirstLevel);
|
||||
int viewHeight = Math.Max(1, height >> view.FirstLevel);
|
||||
|
||||
int viewDepthOrLayers;
|
||||
|
||||
if (view.Info.Target == Target.Texture3D)
|
||||
{
|
||||
viewDepthOrLayers = Math.Max(1, depthOrLayers >> view.FirstLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewDepthOrLayers = view.Info.DepthOrLayers;
|
||||
}
|
||||
|
||||
view.RecreateStorageOrView(viewWidth, viewHeight, blockWidth, blockHeight, viewDepthOrLayers);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recreates the texture storage (or view, in the case of child textures) of this texture.
|
||||
/// This allows recreating the texture with a new size.
|
||||
/// A copy is automatically performed from the old to the new texture.
|
||||
/// </summary>
|
||||
/// <param name="width">The new texture width</param>
|
||||
/// <param name="height">The new texture height</param>
|
||||
/// <param name="width">The block width related to the given width</param>
|
||||
/// <param name="height">The block height related to the given height</param>
|
||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
||||
private void RecreateStorageOrView(int width, int height, int blockWidth, int blockHeight, int depthOrLayers)
|
||||
{
|
||||
RecreateStorageOrView(
|
||||
BitUtils.DivRoundUp(width * Info.FormatInfo.BlockWidth, blockWidth),
|
||||
BitUtils.DivRoundUp(height * Info.FormatInfo.BlockHeight, blockHeight),
|
||||
depthOrLayers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recreates the texture storage (or view, in the case of child textures) of this texture.
|
||||
/// This allows recreating the texture with a new size.
|
||||
/// A copy is automatically performed from the old to the new texture.
|
||||
/// </summary>
|
||||
/// <param name="width">The new texture width</param>
|
||||
/// <param name="height">The new texture height</param>
|
||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
||||
private void RecreateStorageOrView(int width, int height, int depthOrLayers)
|
||||
{
|
||||
ChangedSize = true;
|
||||
|
||||
SetInfo(new TextureInfo(
|
||||
Info.GpuAddress,
|
||||
width,
|
||||
height,
|
||||
depthOrLayers,
|
||||
Info.Levels,
|
||||
Info.SamplesInX,
|
||||
Info.SamplesInY,
|
||||
Info.Stride,
|
||||
Info.IsLinear,
|
||||
Info.GobBlocksInY,
|
||||
Info.GobBlocksInZ,
|
||||
Info.GobBlocksInTileX,
|
||||
Info.Target,
|
||||
Info.FormatInfo,
|
||||
Info.DepthStencilMode,
|
||||
Info.SwizzleR,
|
||||
Info.SwizzleG,
|
||||
Info.SwizzleB,
|
||||
Info.SwizzleA));
|
||||
|
||||
TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
|
||||
|
||||
if (_viewStorage != this)
|
||||
{
|
||||
ReplaceStorage(_viewStorage.HostTexture.CreateView(createInfo, FirstLayer, FirstLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
ITexture newStorage = _context.Renderer.CreateTexture(createInfo, ScaleFactor);
|
||||
|
||||
HostTexture.CopyTo(newStorage, 0, 0);
|
||||
|
||||
ReplaceStorage(newStorage);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers when a texture has had its data set after being scaled, and
|
||||
/// determines if it should be blacklisted from scaling to improve performance.
|
||||
@@ -1215,7 +1092,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <returns>A value indicating how well this texture matches the given info</returns>
|
||||
public TextureMatchQuality IsExactMatch(TextureInfo info, TextureSearchFlags flags)
|
||||
{
|
||||
TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0);
|
||||
bool forSampler = (flags & TextureSearchFlags.ForSampler) != 0;
|
||||
|
||||
TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, forSampler, (flags & TextureSearchFlags.ForCopy) != 0);
|
||||
|
||||
if (matchQuality == TextureMatchQuality.NoMatch)
|
||||
{
|
||||
@@ -1227,12 +1106,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
return TextureMatchQuality.NoMatch;
|
||||
}
|
||||
|
||||
if (!TextureCompatibility.SizeMatches(Info, info, (flags & TextureSearchFlags.Strict) == 0, FirstLevel))
|
||||
if (!TextureCompatibility.SizeMatches(Info, info, forSampler))
|
||||
{
|
||||
return TextureMatchQuality.NoMatch;
|
||||
}
|
||||
|
||||
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
|
||||
if ((flags & TextureSearchFlags.ForSampler) != 0)
|
||||
{
|
||||
if (!TextureCompatibility.SamplerParamsMatches(Info, info))
|
||||
{
|
||||
@@ -1262,12 +1141,20 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
/// <param name="info">Texture view information</param>
|
||||
/// <param name="range">Texture view physical memory ranges</param>
|
||||
/// <param name="exactSize">Indicates if the texture sizes must be exactly equal, or width is allowed to differ</param>
|
||||
/// <param name="layerSize">Layer size on the given texture</param>
|
||||
/// <param name="caps">Host GPU capabilities</param>
|
||||
/// <param name="firstLayer">Texture view initial layer on this texture</param>
|
||||
/// <param name="firstLevel">Texture view first mipmap level on this texture</param>
|
||||
/// <returns>The level of compatiblilty a view with the given parameters created from this texture has</returns>
|
||||
public TextureViewCompatibility IsViewCompatible(TextureInfo info, MultiRange range, int layerSize, Capabilities caps, out int firstLayer, out int firstLevel)
|
||||
public TextureViewCompatibility IsViewCompatible(
|
||||
TextureInfo info,
|
||||
MultiRange range,
|
||||
bool exactSize,
|
||||
int layerSize,
|
||||
Capabilities caps,
|
||||
out int firstLayer,
|
||||
out int firstLevel)
|
||||
{
|
||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||
|
||||
@@ -1317,7 +1204,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
return TextureViewCompatibility.LayoutIncompatible;
|
||||
}
|
||||
|
||||
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSizeMatches(Info, info, firstLevel));
|
||||
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSizeMatches(Info, info, exactSize, firstLevel));
|
||||
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSubImagesInBounds(Info, info, firstLayer, firstLevel));
|
||||
|
||||
return result;
|
||||
@@ -1750,13 +1637,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
|
||||
RemoveFromPools(true);
|
||||
|
||||
// We only want to remove if there's no mapped region of the texture that was modified by the GPU,
|
||||
// otherwise we could lose data.
|
||||
if (!Group.AnyModified(this))
|
||||
{
|
||||
_physicalMemory.TextureCache.QueueAutoDeleteCacheRemoval(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -210,8 +210,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
ulong offset,
|
||||
FormatInfo formatInfo,
|
||||
bool shouldCreate,
|
||||
bool preferScaling = true,
|
||||
Size? sizeHint = null)
|
||||
bool preferScaling,
|
||||
Size sizeHint)
|
||||
{
|
||||
int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY();
|
||||
int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ();
|
||||
@@ -229,7 +229,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
TextureInfo info = new TextureInfo(
|
||||
copyTexture.Address.Pack() + offset,
|
||||
width,
|
||||
GetMinimumWidthInGob(width, sizeHint.Width, formatInfo.BytesPerPixel, copyTexture.LinearLayout),
|
||||
copyTexture.Height,
|
||||
copyTexture.Depth,
|
||||
1,
|
||||
@@ -255,7 +255,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
flags |= TextureSearchFlags.NoCreate;
|
||||
}
|
||||
|
||||
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0, sizeHint);
|
||||
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0);
|
||||
|
||||
texture?.SynchronizeMemory();
|
||||
|
||||
@@ -326,7 +326,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
TextureInfo info = new TextureInfo(
|
||||
colorState.Address.Pack(),
|
||||
width,
|
||||
GetMinimumWidthInGob(width, sizeHint.Width, formatInfo.BytesPerPixel, isLinear),
|
||||
colorState.Height,
|
||||
colorState.Depth,
|
||||
1,
|
||||
@@ -342,7 +342,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
int layerSize = !isLinear ? colorState.LayerSize * 4 : 0;
|
||||
|
||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize, sizeHint);
|
||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize);
|
||||
|
||||
texture?.SynchronizeMemory();
|
||||
|
||||
@@ -395,7 +395,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
TextureInfo info = new TextureInfo(
|
||||
dsState.Address.Pack(),
|
||||
size.Width,
|
||||
GetMinimumWidthInGob(size.Width, sizeHint.Width, formatInfo.BytesPerPixel, false),
|
||||
size.Height,
|
||||
size.Depth,
|
||||
1,
|
||||
@@ -409,13 +409,41 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
target,
|
||||
formatInfo);
|
||||
|
||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4, sizeHint);
|
||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4);
|
||||
|
||||
texture?.SynchronizeMemory();
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For block linear textures, gets the minimum width of the texture
|
||||
/// that would still have the same number of GOBs per row as the original width.
|
||||
/// </summary>
|
||||
/// <param name="width">The possibly aligned texture width</param>
|
||||
/// <param name="minimumWidth">The minimum width that the texture may have without losing data</param>
|
||||
/// <param name="bytesPerPixel">Bytes per pixel of the texture format</param>
|
||||
/// <param name="isLinear">True if the texture is linear, false for block linear</param>
|
||||
/// <returns>The minimum width of the texture with the same amount of GOBs per row</returns>
|
||||
private static int GetMinimumWidthInGob(int width, int minimumWidth, int bytesPerPixel, bool isLinear)
|
||||
{
|
||||
if (isLinear || (uint)minimumWidth >= (uint)width)
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
// Calculate the minimum possible that would not cause data loss
|
||||
// and would be still within the same GOB (aligned size would be the same).
|
||||
// This is useful for render and copy operations, where we don't know the
|
||||
// exact width of the texture, but it doesn't matter, as long the texture is
|
||||
// at least as large as the region being rendered or copied.
|
||||
|
||||
int alignment = 64 / bytesPerPixel;
|
||||
int widthAligned = BitUtils.AlignUp(width, alignment);
|
||||
|
||||
return Math.Clamp(widthAligned - alignment + 1, minimumWidth, widthAligned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find an existing texture, or create a new one if not found.
|
||||
/// </summary>
|
||||
@@ -423,7 +451,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <param name="flags">The texture search flags, defines texture comparison rules</param>
|
||||
/// <param name="info">Texture information of the texture to be found or created</param>
|
||||
/// <param name="layerSize">Size in bytes of a single texture layer</param>
|
||||
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||
/// <param name="range">Optional ranges of physical memory where the texture data is located</param>
|
||||
/// <returns>The texture</returns>
|
||||
public Texture FindOrCreateTexture(
|
||||
@@ -431,7 +458,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
TextureSearchFlags flags,
|
||||
TextureInfo info,
|
||||
int layerSize = 0,
|
||||
Size? sizeHint = null,
|
||||
MultiRange? range = null)
|
||||
{
|
||||
bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
|
||||
@@ -448,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;
|
||||
@@ -512,8 +545,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
if (texture != null)
|
||||
{
|
||||
ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint);
|
||||
|
||||
texture.SynchronizeMemory();
|
||||
|
||||
return texture;
|
||||
@@ -568,6 +599,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(
|
||||
info,
|
||||
range.Value,
|
||||
isSamplerTexture,
|
||||
sizeInfo.LayerSize,
|
||||
_context.Capabilities,
|
||||
out int firstLayer,
|
||||
@@ -598,17 +630,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
if (oInfo.Compatibility == TextureViewCompatibility.Full)
|
||||
{
|
||||
TextureInfo adjInfo = AdjustSizes(overlap, info, oInfo.FirstLevel);
|
||||
|
||||
if (!isSamplerTexture)
|
||||
{
|
||||
info = adjInfo;
|
||||
// If this is not a sampler texture, the size might be different from the requested size,
|
||||
// so we need to make sure the texture information has the correct size for this base texture,
|
||||
// before creating the view.
|
||||
info = info.CreateInfoForLevelView(overlap, oInfo.FirstLevel);
|
||||
}
|
||||
|
||||
texture = overlap.CreateView(adjInfo, sizeInfo, range.Value, oInfo.FirstLayer, oInfo.FirstLevel);
|
||||
|
||||
ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint);
|
||||
|
||||
texture = overlap.CreateView(info, sizeInfo, range.Value, oInfo.FirstLayer, oInfo.FirstLevel);
|
||||
texture.SynchronizeMemory();
|
||||
break;
|
||||
}
|
||||
@@ -682,6 +712,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
TextureViewCompatibility compatibility = texture.IsViewCompatible(
|
||||
overlap.Info,
|
||||
overlap.Range,
|
||||
exactSize: true,
|
||||
overlap.LayerSize,
|
||||
_context.Capabilities,
|
||||
out int firstLayer,
|
||||
@@ -792,7 +823,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
continue;
|
||||
}
|
||||
|
||||
TextureInfo overlapInfo = AdjustSizes(texture, overlap.Info, oInfo.FirstLevel);
|
||||
// Note: If we allow different sizes for those overlaps,
|
||||
// we need to make sure that the "info" has the correct size for the parent texture here.
|
||||
// Since this is not allowed right now, we don't need to do it.
|
||||
|
||||
TextureInfo overlapInfo = overlap.Info;
|
||||
|
||||
if (texture.ScaleFactor != overlap.ScaleFactor)
|
||||
{
|
||||
@@ -856,44 +891,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
return texture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes a texture's size to match the desired size for samplers,
|
||||
/// or increases a texture's size to fit the region indicated by a size hint.
|
||||
/// </summary>
|
||||
/// <param name="info">The desired texture info</param>
|
||||
/// <param name="texture">The texture to resize</param>
|
||||
/// <param name="isSamplerTexture">True if the texture will be used for a sampler, false otherwise</param>
|
||||
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||
private void ChangeSizeIfNeeded(TextureInfo info, Texture texture, bool isSamplerTexture, Size? sizeHint)
|
||||
{
|
||||
if (isSamplerTexture)
|
||||
{
|
||||
// If this is used for sampling, the size must match,
|
||||
// otherwise the shader would sample garbage data.
|
||||
// To fix that, we create a new texture with the correct
|
||||
// size, and copy the data from the old one to the new one.
|
||||
|
||||
if (!TextureCompatibility.SizeMatches(texture.Info, info))
|
||||
{
|
||||
texture.ChangeSize(info.Width, info.Height, info.DepthOrLayers);
|
||||
}
|
||||
}
|
||||
else if (sizeHint != null)
|
||||
{
|
||||
// A size hint indicates that data will be used within that range, at least.
|
||||
// If the texture is smaller than the size hint, it must be enlarged to meet it.
|
||||
// The maximum size is provided by the requested info, which generally has an aligned size.
|
||||
|
||||
int width = Math.Max(texture.Info.Width, Math.Min(sizeHint.Value.Width, info.Width));
|
||||
int height = Math.Max(texture.Info.Height, Math.Min(sizeHint.Value.Height, info.Height));
|
||||
|
||||
if (texture.Info.Width != width || texture.Info.Height != height)
|
||||
{
|
||||
texture.ChangeSize(width, height, info.DepthOrLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to find a texture on the short duration cache.
|
||||
/// </summary>
|
||||
@@ -1000,92 +997,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the size of the texture information for a given mipmap level,
|
||||
/// based on the size of a parent texture.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent texture</param>
|
||||
/// <param name="info">The texture information to be adjusted</param>
|
||||
/// <param name="firstLevel">The first level of the texture view</param>
|
||||
/// <returns>The adjusted texture information with the new size</returns>
|
||||
private static TextureInfo AdjustSizes(Texture parent, TextureInfo info, int firstLevel)
|
||||
{
|
||||
// When the texture is used as view of another texture, we must
|
||||
// ensure that the sizes are valid, otherwise data uploads would fail
|
||||
// (and the size wouldn't match the real size used on the host API).
|
||||
// Given a parent texture from where the view is created, we have the
|
||||
// following rules:
|
||||
// - The view size must be equal to the parent size, divided by (2 ^ l),
|
||||
// where l is the first mipmap level of the view. The division result must
|
||||
// be rounded down, and the result must be clamped to 1.
|
||||
// - If the parent format is compressed, and the view format isn't, the
|
||||
// view size is calculated as above, but the width and height of the
|
||||
// view must be also divided by the compressed format block width and height.
|
||||
// - If the parent format is not compressed, and the view is, the view
|
||||
// size is calculated as described on the first point, but the width and height
|
||||
// of the view must be also multiplied by the block width and height.
|
||||
int width = Math.Max(1, parent.Info.Width >> firstLevel);
|
||||
int height = Math.Max(1, parent.Info.Height >> firstLevel);
|
||||
|
||||
if (parent.Info.FormatInfo.IsCompressed && !info.FormatInfo.IsCompressed)
|
||||
{
|
||||
width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth);
|
||||
height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight);
|
||||
}
|
||||
else if (!parent.Info.FormatInfo.IsCompressed && info.FormatInfo.IsCompressed)
|
||||
{
|
||||
width *= info.FormatInfo.BlockWidth;
|
||||
height *= info.FormatInfo.BlockHeight;
|
||||
}
|
||||
|
||||
int depthOrLayers;
|
||||
|
||||
if (info.Target == Target.Texture3D)
|
||||
{
|
||||
depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
depthOrLayers = info.DepthOrLayers;
|
||||
}
|
||||
|
||||
// 2D and 2D multisample textures are not considered compatible.
|
||||
// This specific case is required for copies, where the source texture might be multisample.
|
||||
// In this case, we inherit the parent texture multisample state.
|
||||
Target target = info.Target;
|
||||
int samplesInX = info.SamplesInX;
|
||||
int samplesInY = info.SamplesInY;
|
||||
|
||||
if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample)
|
||||
{
|
||||
target = Target.Texture2DMultisample;
|
||||
samplesInX = parent.Info.SamplesInX;
|
||||
samplesInY = parent.Info.SamplesInY;
|
||||
}
|
||||
|
||||
return new TextureInfo(
|
||||
info.GpuAddress,
|
||||
width,
|
||||
height,
|
||||
depthOrLayers,
|
||||
info.Levels,
|
||||
samplesInX,
|
||||
samplesInY,
|
||||
info.Stride,
|
||||
info.IsLinear,
|
||||
info.GobBlocksInY,
|
||||
info.GobBlocksInZ,
|
||||
info.GobBlocksInTileX,
|
||||
target,
|
||||
info.FormatInfo,
|
||||
info.DepthStencilMode,
|
||||
info.SwizzleR,
|
||||
info.SwizzleG,
|
||||
info.SwizzleB,
|
||||
info.SwizzleA);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a texture creation information from texture information.
|
||||
/// This can be used to create new host textures.
|
||||
@@ -1175,19 +1086,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues the removal of a texture from the auto delete cache.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function is thread safe and can be called from any thread.
|
||||
/// The texture will be deleted on the next time the cache is used.
|
||||
/// </remarks>
|
||||
/// <param name="texture">The texture to be removed</param>
|
||||
public void QueueAutoDeleteCacheRemoval(Texture texture)
|
||||
{
|
||||
_cache.RemoveDeferred(texture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a texture to the short duration cache. This typically keeps it alive for two ticks.
|
||||
/// </summary>
|
||||
|
@@ -380,42 +380,37 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
/// <param name="lhs">Texture information of the texture view</param>
|
||||
/// <param name="rhs">Texture information of the texture view to match against</param>
|
||||
/// <param name="exact">Indicates if the sizes must be exactly equal</param>
|
||||
/// <param name="level">Mipmap level of the texture view in relation to this texture</param>
|
||||
/// <returns>The view compatibility level of the view sizes</returns>
|
||||
public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, int level)
|
||||
public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact, int level)
|
||||
{
|
||||
Size size = GetAlignedSize(lhs, level);
|
||||
Size lhsAlignedSize = GetAlignedSize(lhs, level);
|
||||
Size rhsAlignedSize = GetAlignedSize(rhs);
|
||||
|
||||
Size otherSize = GetAlignedSize(rhs);
|
||||
Size lhsSize = GetSizeInBlocks(lhs, level);
|
||||
Size rhsSize = GetSizeInBlocks(rhs);
|
||||
|
||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||
|
||||
// For copies, we can copy a subset of the 3D texture slices,
|
||||
// so the depth may be different in this case.
|
||||
if (rhs.Target == Target.Texture3D && size.Depth != otherSize.Depth)
|
||||
if (rhs.Target == Target.Texture3D && lhsSize.Depth != rhsSize.Depth)
|
||||
{
|
||||
result = TextureViewCompatibility.CopyOnly;
|
||||
}
|
||||
|
||||
if (size.Width == otherSize.Width && size.Height == otherSize.Height)
|
||||
// Some APIs align the width for copy and render target textures,
|
||||
// so the width may not match in this case for different uses of the same texture.
|
||||
// To account for this, we compare the aligned width here.
|
||||
// We expect height to always match exactly, if the texture is the same.
|
||||
if (lhsAlignedSize.Width == rhsAlignedSize.Width && lhsSize.Height == rhsSize.Height)
|
||||
{
|
||||
if (level > 0 && result == TextureViewCompatibility.Full)
|
||||
{
|
||||
// A resize should not change the aligned size of the largest mip.
|
||||
// If it would, then create a copy dependency rather than a full view.
|
||||
|
||||
Size mip0SizeLhs = GetAlignedSize(lhs);
|
||||
Size mip0SizeRhs = GetLargestAlignedSize(rhs, level);
|
||||
|
||||
if (mip0SizeLhs.Width != mip0SizeRhs.Width || mip0SizeLhs.Height != mip0SizeRhs.Height)
|
||||
{
|
||||
result = TextureViewCompatibility.CopyOnly;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return (exact && lhsSize.Width != rhsSize.Width) || lhsSize.Width < rhsSize.Width
|
||||
? TextureViewCompatibility.CopyOnly
|
||||
: result;
|
||||
}
|
||||
else if (lhs.IsLinear && rhs.IsLinear)
|
||||
else if (lhs.IsLinear && rhs.IsLinear && lhsSize.Height == rhsSize.Height)
|
||||
{
|
||||
// Copy between linear textures with matching stride.
|
||||
int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment);
|
||||
@@ -454,57 +449,33 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
/// <param name="lhs">Texture information to compare</param>
|
||||
/// <param name="rhs">Texture information to compare with</param>
|
||||
/// <returns>True if the size matches, false otherwise</returns>
|
||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs)
|
||||
{
|
||||
return SizeMatches(lhs, rhs, alignSizes: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the texture sizes of the supplied texture informations match the given level
|
||||
/// </summary>
|
||||
/// <param name="lhs">Texture information to compare</param>
|
||||
/// <param name="rhs">Texture information to compare with</param>
|
||||
/// <param name="level">Mipmap level of this texture to compare with</param>
|
||||
/// <returns>True if the size matches with the level, false otherwise</returns>
|
||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, int level)
|
||||
{
|
||||
return Math.Max(1, lhs.Width >> level) == rhs.Width &&
|
||||
Math.Max(1, lhs.Height >> level) == rhs.Height &&
|
||||
Math.Max(1, lhs.GetDepth() >> level) == rhs.GetDepth();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the texture sizes of the supplied texture informations match.
|
||||
/// </summary>
|
||||
/// <param name="lhs">Texture information to compare</param>
|
||||
/// <param name="rhs">Texture information to compare with</param>
|
||||
/// <param name="alignSizes">True to align the sizes according to the texture layout for comparison</param>
|
||||
/// <param name="lhsLevel">Mip level of the lhs texture. Aligned sizes are compared for the largest mip</param>
|
||||
/// <param name="exact">Indicates if the size must be exactly equal between the textures, or if <paramref name="rhs"/> is allowed to be larger</param>
|
||||
/// <returns>True if the sizes matches, false otherwise</returns>
|
||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool alignSizes, int lhsLevel = 0)
|
||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact)
|
||||
{
|
||||
if (lhs.GetLayers() != rhs.GetLayers())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isTextureBuffer = lhs.Target == Target.TextureBuffer || rhs.Target == Target.TextureBuffer;
|
||||
Size lhsSize = GetSizeInBlocks(lhs);
|
||||
Size rhsSize = GetSizeInBlocks(rhs);
|
||||
|
||||
if (alignSizes && !isTextureBuffer)
|
||||
if (exact || lhs.IsLinear || rhs.IsLinear)
|
||||
{
|
||||
Size size0 = GetLargestAlignedSize(lhs, lhsLevel);
|
||||
Size size1 = GetLargestAlignedSize(rhs, lhsLevel);
|
||||
|
||||
return size0.Width == size1.Width &&
|
||||
size0.Height == size1.Height &&
|
||||
size0.Depth == size1.Depth;
|
||||
return lhsSize.Width == rhsSize.Width &&
|
||||
lhsSize.Height == rhsSize.Height &&
|
||||
lhsSize.Depth == rhsSize.Depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lhs.Width == rhs.Width &&
|
||||
lhs.Height == rhs.Height &&
|
||||
lhs.GetDepth() == rhs.GetDepth();
|
||||
Size lhsAlignedSize = GetAlignedSize(lhs);
|
||||
Size rhsAlignedSize = GetAlignedSize(rhs);
|
||||
|
||||
return lhsAlignedSize.Width == rhsAlignedSize.Width &&
|
||||
lhsSize.Width >= rhsSize.Width &&
|
||||
lhsSize.Height == rhsSize.Height &&
|
||||
lhsSize.Depth == rhsSize.Depth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,22 +514,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aligned sizes of the specified texture information, shifted to the largest mip from a given level.
|
||||
/// The alignment depends on the texture layout and format bytes per pixel.
|
||||
/// </summary>
|
||||
/// <param name="info">Texture information to calculate the aligned size from</param>
|
||||
/// <param name="level">Mipmap level for texture views. Shifts the aligned size to represent the largest mip level</param>
|
||||
/// <returns>The aligned texture size of the largest mip level</returns>
|
||||
public static Size GetLargestAlignedSize(TextureInfo info, int level)
|
||||
{
|
||||
int width = info.Width << level;
|
||||
int height = info.Height << level;
|
||||
int depth = info.GetDepth() << level;
|
||||
|
||||
return GetAlignedSize(info, width, height, depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aligned sizes of the specified texture information.
|
||||
/// The alignment depends on the texture layout and format bytes per pixel.
|
||||
@@ -575,6 +530,25 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
return GetAlignedSize(info, width, height, depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size in blocks for the given texture information.
|
||||
/// For non-compressed formats, that's the same as the regular size.
|
||||
/// </summary>
|
||||
/// <param name="info">Texture information to calculate the aligned size from</param>
|
||||
/// <param name="level">Mipmap level for texture views</param>
|
||||
/// <returns>The texture size in blocks</returns>
|
||||
public static Size GetSizeInBlocks(TextureInfo info, int level = 0)
|
||||
{
|
||||
int width = Math.Max(1, info.Width >> level);
|
||||
int height = Math.Max(1, info.Height >> level);
|
||||
int depth = Math.Max(1, info.GetDepth() >> level);
|
||||
|
||||
return new Size(
|
||||
BitUtils.DivRoundUp(width, info.FormatInfo.BlockWidth),
|
||||
BitUtils.DivRoundUp(height, info.FormatInfo.BlockHeight),
|
||||
depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it's possible to create a view with the layout of the second texture information from the first.
|
||||
/// The layout information is composed of the Stride for linear textures, or GOB block size
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -434,32 +433,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a texture was modified by the GPU.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to be checked</param>
|
||||
/// <returns>True if any region of the texture was modified by the GPU, false otherwise</returns>
|
||||
public bool AnyModified(Texture texture)
|
||||
{
|
||||
bool anyModified = false;
|
||||
|
||||
EvaluateRelevantHandles(texture, (baseHandle, regionCount, split) =>
|
||||
{
|
||||
for (int i = 0; i < regionCount; i++)
|
||||
{
|
||||
TextureGroupHandle group = _handles[baseHandle + i];
|
||||
|
||||
if (group.Modified)
|
||||
{
|
||||
anyModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return anyModified;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flush modified ranges for a given texture.
|
||||
/// </summary>
|
||||
|
@@ -1,5 +1,7 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Texture;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Image
|
||||
{
|
||||
@@ -292,5 +294,88 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
layerSize);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates texture information for a given mipmap level of the specified parent texture and this information.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent texture</param>
|
||||
/// <param name="firstLevel">The first level of the texture view</param>
|
||||
/// <returns>The adjusted texture information with the new size</returns>
|
||||
public TextureInfo CreateInfoForLevelView(Texture parent, int firstLevel)
|
||||
{
|
||||
// When the texture is used as view of another texture, we must
|
||||
// ensure that the sizes are valid, otherwise data uploads would fail
|
||||
// (and the size wouldn't match the real size used on the host API).
|
||||
// Given a parent texture from where the view is created, we have the
|
||||
// following rules:
|
||||
// - The view size must be equal to the parent size, divided by (2 ^ l),
|
||||
// where l is the first mipmap level of the view. The division result must
|
||||
// be rounded down, and the result must be clamped to 1.
|
||||
// - If the parent format is compressed, and the view format isn't, the
|
||||
// view size is calculated as above, but the width and height of the
|
||||
// view must be also divided by the compressed format block width and height.
|
||||
// - If the parent format is not compressed, and the view is, the view
|
||||
// size is calculated as described on the first point, but the width and height
|
||||
// of the view must be also multiplied by the block width and height.
|
||||
int width = Math.Max(1, parent.Info.Width >> firstLevel);
|
||||
int height = Math.Max(1, parent.Info.Height >> firstLevel);
|
||||
|
||||
if (parent.Info.FormatInfo.IsCompressed && !FormatInfo.IsCompressed)
|
||||
{
|
||||
width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth);
|
||||
height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight);
|
||||
}
|
||||
else if (!parent.Info.FormatInfo.IsCompressed && FormatInfo.IsCompressed)
|
||||
{
|
||||
width *= FormatInfo.BlockWidth;
|
||||
height *= FormatInfo.BlockHeight;
|
||||
}
|
||||
|
||||
int depthOrLayers;
|
||||
|
||||
if (Target == Target.Texture3D)
|
||||
{
|
||||
depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
depthOrLayers = DepthOrLayers;
|
||||
}
|
||||
|
||||
// 2D and 2D multisample textures are not considered compatible.
|
||||
// This specific case is required for copies, where the source texture might be multisample.
|
||||
// In this case, we inherit the parent texture multisample state.
|
||||
Target target = Target;
|
||||
int samplesInX = SamplesInX;
|
||||
int samplesInY = SamplesInY;
|
||||
|
||||
if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample)
|
||||
{
|
||||
target = Target.Texture2DMultisample;
|
||||
samplesInX = parent.Info.SamplesInX;
|
||||
samplesInY = parent.Info.SamplesInY;
|
||||
}
|
||||
|
||||
return new TextureInfo(
|
||||
GpuAddress,
|
||||
width,
|
||||
height,
|
||||
depthOrLayers,
|
||||
Levels,
|
||||
samplesInX,
|
||||
samplesInY,
|
||||
Stride,
|
||||
IsLinear,
|
||||
GobBlocksInY,
|
||||
GobBlocksInZ,
|
||||
GobBlocksInTileX,
|
||||
target,
|
||||
FormatInfo,
|
||||
DepthStencilMode,
|
||||
SwizzleR,
|
||||
SwizzleG,
|
||||
SwizzleB,
|
||||
SwizzleA);
|
||||
}
|
||||
}
|
||||
}
|
@@ -437,22 +437,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update host framebuffer attachments based on currently bound render target buffers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All attachments other than <paramref name="index"/> will be unbound.
|
||||
/// </remarks>
|
||||
/// <param name="index">Index of the render target color to be updated</param>
|
||||
public void UpdateRenderTarget(int index)
|
||||
{
|
||||
new Span<ITexture>(_rtHostColors).Fill(null);
|
||||
_rtHostColors[index] = _rtColors[index]?.HostTexture;
|
||||
_rtHostDs = null;
|
||||
|
||||
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update host framebuffer attachments based on currently bound render target buffers.
|
||||
/// </summary>
|
||||
|
@@ -77,22 +77,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
else
|
||||
{
|
||||
if (texture.ChangedSize)
|
||||
{
|
||||
// Texture changed size at one point - it may be a different size than the sampler expects.
|
||||
// This can be triggered when the size is changed by a size hint on copy or draw, but the texture has been sampled before.
|
||||
|
||||
int baseLevel = descriptor.UnpackBaseLevel();
|
||||
int width = Math.Max(1, descriptor.UnpackWidth() >> baseLevel);
|
||||
int height = Math.Max(1, descriptor.UnpackHeight() >> baseLevel);
|
||||
|
||||
if (texture.Info.Width != width || texture.Info.Height != height)
|
||||
{
|
||||
texture.ChangeSize(width, height, texture.Info.DepthOrLayers);
|
||||
}
|
||||
}
|
||||
|
||||
// Memory is automatically synchronized on texture creation.
|
||||
// On the path above (texture not yet in the pool), memory is automatically synchronized on texture creation.
|
||||
texture.SynchronizeMemory();
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
enum TextureSearchFlags
|
||||
{
|
||||
None = 0,
|
||||
Strict = 1 << 0,
|
||||
ForSampler = 1 << 1,
|
||||
ForCopy = 1 << 2,
|
||||
WithUpscale = 1 << 3,
|
||||
|
@@ -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.
|
||||
|
@@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
pt.AcquireCallback(_context, pt.UserObj);
|
||||
|
||||
Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, null, pt.Range);
|
||||
Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, pt.Range);
|
||||
|
||||
pt.Cache.Tick();
|
||||
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
|
||||
@@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
int attachmentCount = 0;
|
||||
int colorCount = 0;
|
||||
int maxColorAttachmentIndex = -1;
|
||||
|
||||
for (int i = 0; i < state.AttachmentEnable.Length; i++)
|
||||
{
|
||||
@@ -36,6 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
attachmentIndices[attachmentCount++] = i;
|
||||
colorCount++;
|
||||
maxColorAttachmentIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,12 +76,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
if (colorAttachmentsCount != 0)
|
||||
{
|
||||
int maxAttachmentIndex = Constants.MaxRenderTargets - 1;
|
||||
subpass.ColorAttachmentCount = (uint)maxAttachmentIndex + 1;
|
||||
subpass.ColorAttachmentCount = (uint)maxColorAttachmentIndex + 1;
|
||||
subpass.PColorAttachments = &attachmentReferences[0];
|
||||
|
||||
// Fill with VK_ATTACHMENT_UNUSED to cover any gaps.
|
||||
for (int i = 0; i <= maxAttachmentIndex; i++)
|
||||
for (int i = 0; i <= maxColorAttachmentIndex; i++)
|
||||
{
|
||||
subpass.PColorAttachments[i] = new AttachmentReference(Vk.AttachmentUnused, ImageLayout.Undefined);
|
||||
}
|
||||
@@ -252,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
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
private const ulong MinByteWeightForFlush = 256 * 1024 * 1024; // MiB
|
||||
|
||||
private readonly List<QueryPool> _activeQueries;
|
||||
private readonly List<(QueryPool, bool)> _activeQueries;
|
||||
private CounterQueueEvent _activeConditionalRender;
|
||||
|
||||
private readonly List<BufferedQuery> _pendingQueryCopies;
|
||||
@@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public PipelineFull(VulkanRenderer gd, Device device) : base(gd, device)
|
||||
{
|
||||
_activeQueries = new List<QueryPool>();
|
||||
_activeQueries = new List<(QueryPool, bool)>();
|
||||
_pendingQueryCopies = new();
|
||||
|
||||
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
||||
@@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
AutoFlush.RegisterFlush(DrawCount);
|
||||
EndRenderPass();
|
||||
|
||||
foreach (var queryPool in _activeQueries)
|
||||
foreach ((var queryPool, _) in _activeQueries)
|
||||
{
|
||||
Gd.Api.CmdEndQuery(CommandBuffer, queryPool, 0);
|
||||
}
|
||||
@@ -220,10 +220,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
// Restore per-command buffer state.
|
||||
|
||||
foreach (var queryPool in _activeQueries)
|
||||
foreach ((var queryPool, var isOcclusion) in _activeQueries)
|
||||
{
|
||||
bool isPrecise = Gd.Capabilities.SupportsPreciseOcclusionQueries && isOcclusion;
|
||||
|
||||
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
|
||||
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
||||
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, isPrecise ? QueryControlFlags.PreciseBit : 0);
|
||||
}
|
||||
|
||||
Gd.ResetCounterPool();
|
||||
@@ -231,7 +233,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Restore();
|
||||
}
|
||||
|
||||
public void BeginQuery(BufferedQuery query, QueryPool pool, bool needsReset, bool fromSamplePool)
|
||||
public void BeginQuery(BufferedQuery query, QueryPool pool, bool needsReset, bool isOcclusion, bool fromSamplePool)
|
||||
{
|
||||
if (needsReset)
|
||||
{
|
||||
@@ -247,16 +249,24 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
||||
bool isPrecise = Gd.Capabilities.SupportsPreciseOcclusionQueries && isOcclusion;
|
||||
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, isPrecise ? QueryControlFlags.PreciseBit : 0);
|
||||
|
||||
_activeQueries.Add(pool);
|
||||
_activeQueries.Add((pool, isOcclusion));
|
||||
}
|
||||
|
||||
public void EndQuery(QueryPool pool)
|
||||
{
|
||||
Gd.Api.CmdEndQuery(CommandBuffer, pool, 0);
|
||||
|
||||
_activeQueries.Remove(pool);
|
||||
for (int i = 0; i < _activeQueries.Count; i++)
|
||||
{
|
||||
if (_activeQueries[i].Item1.Handle == pool.Handle)
|
||||
{
|
||||
_activeQueries.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyQueryResults(BufferedQuery query)
|
||||
@@ -271,7 +281,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
protected override void SignalAttachmentChange()
|
||||
{
|
||||
if (AutoFlush.ShouldFlush(DrawCount))
|
||||
if (AutoFlush.ShouldFlushAttachmentChange(DrawCount))
|
||||
{
|
||||
FlushCommandsImpl();
|
||||
}
|
||||
|
@@ -100,7 +100,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
||||
if (_isSupported)
|
||||
{
|
||||
bool needsReset = resetSequence == null || _resetSequence == null || resetSequence.Value != _resetSequence.Value;
|
||||
_pipeline.BeginQuery(this, _queryPool, needsReset, _type == CounterType.SamplesPassed && resetSequence != null);
|
||||
bool isOcclusion = _type == CounterType.SamplesPassed;
|
||||
_pipeline.BeginQuery(this, _queryPool, needsReset, isOcclusion, isOcclusion && resetSequence != null);
|
||||
}
|
||||
_resetSequence = null;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var componentMapping = new ComponentMapping(swizzleR, swizzleG, swizzleB, swizzleA);
|
||||
|
||||
var aspectFlags = info.Format.ConvertAspectFlags(info.DepthStencilMode);
|
||||
var aspectFlagsDepth = info.Format.ConvertAspectFlags(DepthStencilMode.Depth);
|
||||
var aspectFlagsDepth = info.Format.ConvertAspectFlags();
|
||||
|
||||
var subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
||||
var subresourceRangeDepth = new ImageSubresourceRange(aspectFlagsDepth, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
||||
@@ -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;
|
||||
|
||||
|
@@ -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),
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -229,7 +229,7 @@ namespace Ryujinx.HLE.FileSystem
|
||||
continue;
|
||||
}
|
||||
|
||||
string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
|
||||
string ncaId = Convert.ToHexString(cnmt.ContentEntries[0].NcaId).ToLower();
|
||||
|
||||
AddAocItem(cnmt.TitleId, containerPath, $"{ncaId}.nca", true);
|
||||
}
|
||||
|
@@ -696,8 +696,8 @@ namespace Ryujinx.HLE.HOS
|
||||
|
||||
var buildIds = programs.Select(p => p switch
|
||||
{
|
||||
NsoExecutable nso => BitConverter.ToString(nso.BuildId.ItemsRo.ToArray()).Replace("-", "").TrimEnd('0'),
|
||||
NroExecutable nro => BitConverter.ToString(nro.Header.BuildId).Replace("-", "").TrimEnd('0'),
|
||||
NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'),
|
||||
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'),
|
||||
_ => string.Empty
|
||||
}).ToList();
|
||||
|
||||
|
@@ -51,11 +51,11 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
|
||||
|
||||
var payload = new JwtPayload
|
||||
{
|
||||
{ "sub", BitConverter.ToString(rawUserId).Replace("-", "").ToLower() },
|
||||
{ "sub", Convert.ToHexString(rawUserId).ToLower() },
|
||||
{ "aud", "ed9e2f05d286f7b8" },
|
||||
{ "di", BitConverter.ToString(deviceId).Replace("-", "").ToLower() },
|
||||
{ "di", Convert.ToHexString(deviceId).ToLower() },
|
||||
{ "sn", "XAW10000000000" },
|
||||
{ "bs:did", BitConverter.ToString(deviceAccountId).Replace("-", "").ToLower() },
|
||||
{ "bs:did", Convert.ToHexString(deviceAccountId).ToLower() },
|
||||
{ "iss", "https://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com" },
|
||||
{ "typ", "id_token" },
|
||||
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
|
||||
|
@@ -101,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps
|
||||
};
|
||||
|
||||
// NOTE: The hex hash is a HMAC-SHA256 (first 32 bytes) using a hardcoded secret key over the titleId, we can simulate it by hashing the titleId instead.
|
||||
string hash = BitConverter.ToString(SHA256.HashData(BitConverter.GetBytes(titleId))).Replace("-", "").Remove(0x20);
|
||||
string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId))).Remove(0x20);
|
||||
string folderPath = Path.Combine(_sdCardPath, "Nintendo", "Album", currentDateTime.Year.ToString("00"), currentDateTime.Month.ToString("00"), currentDateTime.Day.ToString("00"));
|
||||
string filePath = GenerateFilePath(folderPath, applicationAlbumEntry, currentDateTime, hash);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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,
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
@@ -10,4 +10,8 @@
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="UnicornEngine.Unicorn" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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.
|
Binary file not shown.
Binary file not shown.
@@ -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)
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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()),
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
{
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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 =
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user