mirror of
https://github.com/KeatonTheBot/Ryujinx.git
synced 2026-05-23 06:52:06 +00:00
Compare commits
103 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc92af12a4 | ||
|
|
df21f6019e | ||
|
|
232dc2653e | ||
|
|
98b4ff331c | ||
|
|
846b5b6e8a | ||
|
|
fc0528876f | ||
|
|
299b4cfe1d | ||
|
|
d640f50203 | ||
|
|
95ac0a7a51 | ||
|
|
0dc506317c | ||
|
|
3e3b7d22e6 | ||
|
|
e02463d779 | ||
|
|
cb37aea614 | ||
|
|
b40265e029 | ||
|
|
10c9e46fbe | ||
|
|
01f037ae83 | ||
|
|
bf618dc0b3 | ||
|
|
8b36e9fb39 | ||
|
|
0cf29113c0 | ||
|
|
e75d162dbd | ||
|
|
038f8352e0 | ||
|
|
2f48a5007a | ||
|
|
45db10220e | ||
|
|
ebe623bc07 | ||
|
|
4bcfae5905 | ||
|
|
eb6a7b9fea | ||
|
|
df322e6d57 | ||
|
|
d46a6bfed5 | ||
|
|
0e810e1e96 | ||
|
|
5da6c490b3 | ||
|
|
2ec9dda408 | ||
|
|
5b03721db6 | ||
|
|
3c644a712d | ||
|
|
19013d360a | ||
|
|
9bcb744a6a | ||
|
|
06ea0c32d3 | ||
|
|
feb3d9d31f | ||
|
|
198ee01437 | ||
|
|
58e3b5489b | ||
|
|
73b2eb6aeb | ||
|
|
6202526666 | ||
|
|
25bb6e8af7 | ||
|
|
191819488e | ||
|
|
85eb4761e8 | ||
|
|
90bf2ece82 | ||
|
|
772233d003 | ||
|
|
33955c1cb0 | ||
|
|
0487438978 | ||
|
|
8f55589124 | ||
|
|
f825413b0d | ||
|
|
0cef96477f | ||
|
|
6ca49f912e | ||
|
|
8c49b7080b | ||
|
|
7f9135396a | ||
|
|
a5301073a9 | ||
|
|
b01d3a8d57 | ||
|
|
4743fbcb9d | ||
|
|
0a2fa54037 | ||
|
|
624021ee5b | ||
|
|
efd5a104b6 | ||
|
|
7960ea643f | ||
|
|
e86801fa12 | ||
|
|
ba5fdbb57a | ||
|
|
4efb872d0a | ||
|
|
05a88ccc94 | ||
|
|
340ec79e9f | ||
|
|
c923c0043a | ||
|
|
6a1e3a0174 | ||
|
|
e2973a875a | ||
|
|
4d5757417e | ||
|
|
c838be4403 | ||
|
|
62a54c63b8 | ||
|
|
51f26f89a5 | ||
|
|
a2fcd3038d | ||
|
|
7bf6c3f016 | ||
|
|
1ea90c41a9 | ||
|
|
a58295b885 | ||
|
|
7cf322e0cf | ||
|
|
741ddf8f1c | ||
|
|
b3e5395950 | ||
|
|
a3eef171c4 | ||
|
|
44a28ea530 | ||
|
|
142a031383 | ||
|
|
5e77ca25c8 | ||
|
|
e3258ab026 | ||
|
|
fba6cb68c9 | ||
|
|
323f3f83e4 | ||
|
|
63e145a377 | ||
|
|
a763f7bfd0 | ||
|
|
59c3c5e864 | ||
|
|
33cfce1c44 | ||
|
|
69a1419be5 | ||
|
|
da0c6c57f9 | ||
|
|
a5e8c8ebad | ||
|
|
20699c8edd | ||
|
|
4cbfd38633 | ||
|
|
2e40b436aa | ||
|
|
01cd935cc3 | ||
|
|
628a28290f | ||
|
|
727ac79ebc | ||
|
|
e7dc0f8a63 | ||
|
|
92c1db7c59 | ||
|
|
72ab6ae184 |
575 changed files with 15818 additions and 9889 deletions
|
|
@ -15,14 +15,13 @@
|
|||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.0.2" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.9.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
|
|
@ -35,9 +34,12 @@
|
|||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.2-build4" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.2-build4" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
|
|
@ -48,8 +50,8 @@
|
|||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.5" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) Ryujinx Team and Contributors
|
||||
Copyright (c) Kenji-NX Team and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
|
|||
30
README.md
30
README.md
|
|
@ -1,26 +1,24 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://ryujinx.org/"><img src="distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a>
|
||||
<img src="distribution/misc/Logo.png" alt="Kenji-NX">
|
||||
<br>
|
||||
<b>Ryujinx</b>
|
||||
<b>Kenji-NX</b>
|
||||
<br>
|
||||
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
|
||||
<br>
|
||||
<a href="https://github.com/KeatonTheBot/Ryujinx/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/KeatonTheBot/Ryujinx"
|
||||
<a href="https://github.com/KeatonTheBot/Kenji-NX/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/KeatonTheBot/Kenji-NX"
|
||||
alt="Latest Release">
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Ryujinx is available on Github under the <a href="https://github.com/KeatonTheBot/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
Kenji-NX is available on GitHub under the <a href="https://github.com/KeatonTheBot/Kenji-NX/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
<br><br>
|
||||
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
|
||||
<br><br>
|
||||
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's <a href="https://github.com/GreemDev/Ryujinx">Ryujinx</a> fork and the more preservative <a href="https://github.com/ryujinx-mirror/ryujinx">ryujinx-mirror</a> fork.
|
||||
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's <a href="https://git.ryujinx.app/ryubing/ryujinx">Ryujinx</a> fork and the more preservative <a href="https://git.ryujinx.app/archive/ryujinx-mirror">ryujinx-mirror</a> fork.
|
||||
It brings over many of the front-facing features from the aforementioned forks with <i>additional</i> contributions from KeatonTheBot and others.
|
||||
<br>
|
||||
</p>
|
||||
|
|
@ -48,7 +46,7 @@ failing to meet this requirement may result in a poor gameplay experience or une
|
|||
<s>These builds are compiled automatically for each commit on the master branch.
|
||||
While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**.</s>
|
||||
|
||||
Automated builds are temporarily disabled, but Windows x64 builds will be manually compiled and uploaded until the GitHub workflows are fixed.
|
||||
Automated builds are temporarily disabled, but builds for all platforms will be manually compiled and uploaded until the workflows are fixed.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
@ -65,16 +63,16 @@ Make sure your SDK version is higher or equal to the required version specified
|
|||
|
||||
### Step 2
|
||||
|
||||
Either use `git clone https://github.com/KeatonTheBot/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
Either use `git clone https://github.com/KeatonTheBot/Kenji-NX` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
||||
### Step 3
|
||||
|
||||
To build Ryujinx, open a command prompt inside the project directory.
|
||||
To build Kenji-NX, open a command prompt inside the project directory.
|
||||
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
|
||||
Then type the following command: `dotnet build -c Release -o build`
|
||||
the built files will be found in the newly created build directory.
|
||||
|
||||
Ryujinx system files are stored in the `Ryujinx` folder.
|
||||
System files are stored in the `Ryujinx` folder.
|
||||
This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
## Features
|
||||
|
|
@ -90,7 +88,7 @@ This folder is located in the user folder, which can be accessed by clicking `Op
|
|||
It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
||||
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster).
|
||||
The fastest option (host, unchecked) is set by default.
|
||||
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads.
|
||||
Kenji-NX also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads.
|
||||
The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game.
|
||||
NOTE: This feature is enabled by default in the Options menu > System tab.
|
||||
You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch!
|
||||
|
|
@ -99,7 +97,7 @@ This folder is located in the user folder, which can be accessed by clicking `Op
|
|||
- **GPU**
|
||||
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
|
||||
There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment.
|
||||
There are currently six graphics enhancements available to the end user in Kenji-NX: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment.
|
||||
These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
|
||||
- **Input**
|
||||
|
|
@ -110,7 +108,7 @@ This folder is located in the user folder, which can be accessed by clicking `Op
|
|||
|
||||
- **DLC & Modifications**
|
||||
|
||||
Ryujinx is able to manage add-on content/downloadable content through the GUI.
|
||||
Kenji-NX is able to manage add-on content/downloadable content through the GUI.
|
||||
Mods (romfs, exefs, and runtime mods such as cheats) are also supported;
|
||||
the GUI contains a shortcut to open the respective mods folder for a particular game.
|
||||
|
||||
|
|
|
|||
BIN
distribution/misc/Logo.png
Normal file
BIN
distribution/misc/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
|
|
@ -1,69 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 255.76 255.76"
|
||||
version="1.1"
|
||||
id="svg7"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<style
|
||||
id="style1">.cls-1{fill:#02c5e5;}.cls-2{fill:#ff5f55;}.cls-3{fill:none;}</style>
|
||||
</defs>
|
||||
<g
|
||||
id="Ebene_2"
|
||||
data-name="Ebene 2"
|
||||
transform="rotate(180,127.88,127.88)">
|
||||
<g
|
||||
id="Ebene_1-2"
|
||||
data-name="Ebene 1">
|
||||
<g
|
||||
id="Ebene_2-2"
|
||||
data-name="Ebene 2">
|
||||
<g
|
||||
id="Ebene_1-2-2"
|
||||
data-name="Ebene 1-2">
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M 80.63,0 V 220.39 H 44.37 c -14,0 -35.74,-20.74 -35.74,-39.13 V 40.13 C 8.63,19.19 31.36,0 49.06,0 Z"
|
||||
id="path1" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 175.13,35.37 v 220.39 h 36.26 c 14,0 35.74,-20.74 35.74,-39.13 V 75.5 c 0,-20.94 -22.73,-40.13 -40.43,-40.13 z"
|
||||
id="path2" />
|
||||
<polygon
|
||||
class="cls-1"
|
||||
points="90.64,145.57 92.89,137.96 124.34,137.96 122.58,145.57 "
|
||||
id="polygon2" />
|
||||
<polygon
|
||||
class="cls-2"
|
||||
points="122.58,145.57 124.34,137.96 160.29,137.96 157.84,145.57 "
|
||||
id="polygon3" />
|
||||
<polygon
|
||||
class="cls-1"
|
||||
points="95.14,119.47 97.39,111.86 130.39,111.86 128.62,119.47 "
|
||||
id="polygon4" />
|
||||
<polygon
|
||||
class="cls-2"
|
||||
points="128.62,119.47 130.39,111.86 164.79,111.86 162.34,119.47 "
|
||||
id="polygon5" />
|
||||
<polygon
|
||||
class="cls-1"
|
||||
points="129.78,87.77 111.19,167.99 104.24,167.99 122.83,87.77 "
|
||||
id="polygon6" />
|
||||
<polygon
|
||||
class="cls-2"
|
||||
points="153.89,87.77 135.3,167.99 128.18,167.99 146.77,87.77 "
|
||||
id="polygon7" />
|
||||
</g>
|
||||
<rect
|
||||
class="cls-3"
|
||||
width="255.75999"
|
||||
height="255.75999"
|
||||
id="rect7"
|
||||
x="0"
|
||||
y="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -10,7 +11,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libarmeilleure-jitsupport.dylib</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
|
|
@ -22,4 +23,8 @@
|
|||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
Offset = offset;
|
||||
Symbol = symbol;
|
||||
LdrOffsets = new List<(Operand, int)>();
|
||||
LdrOffsets = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +266,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
}
|
||||
else
|
||||
{
|
||||
relocInfo = new RelocInfo(Array.Empty<RelocEntry>());
|
||||
relocInfo = new RelocInfo([]);
|
||||
}
|
||||
|
||||
return (code, relocInfo);
|
||||
|
|
|
|||
|
|
@ -1079,7 +1079,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
List<UnwindPushEntry> pushEntries = [];
|
||||
|
||||
Operand rsp = Register(SpRegister);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
return false;
|
||||
}
|
||||
|
||||
private static readonly string[] _sysctlNames = new string[]
|
||||
{
|
||||
private static readonly string[] _sysctlNames =
|
||||
[
|
||||
"hw.optional.floatingpoint",
|
||||
"hw.optional.AdvSIMD",
|
||||
"hw.optional.arm.FEAT_FP16",
|
||||
|
|
@ -150,8 +150,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
"hw.optional.arm.FEAT_LSE",
|
||||
"hw.optional.armv8_crc32",
|
||||
"hw.optional.arm.FEAT_SHA1",
|
||||
"hw.optional.arm.FEAT_SHA256",
|
||||
};
|
||||
"hw.optional.arm.FEAT_SHA256"
|
||||
];
|
||||
|
||||
[Flags]
|
||||
public enum MacOsFeatureFlags
|
||||
|
|
|
|||
|
|
@ -261,10 +261,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0),
|
||||
};
|
||||
List<Operand> sources =
|
||||
[
|
||||
operation.GetSource(0)
|
||||
];
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
||||
|
|
@ -365,10 +365,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Operation node,
|
||||
Operation operation)
|
||||
{
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0),
|
||||
};
|
||||
List<Operand> sources =
|
||||
[
|
||||
operation.GetSource(0)
|
||||
];
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
||||
|
|
@ -468,8 +468,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
// Update the sources and destinations with split 64-bit halfs of the whole 128-bit values.
|
||||
// We also need a additional registers that will be used to store temporary information.
|
||||
operation.SetDestinations(new[] { actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64) });
|
||||
operation.SetSources(new[] { address, expectedLow, expectedHigh, desiredLow, desiredHigh });
|
||||
operation.SetDestinations([actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64)]);
|
||||
operation.SetSources([address, expectedLow, expectedHigh, desiredLow, desiredHigh]);
|
||||
|
||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
||||
// so they can't be used as destination operand.
|
||||
|
|
@ -486,7 +486,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
else
|
||||
{
|
||||
// We need a additional register where the store result will be written to.
|
||||
node.SetDestinations(new[] { node.Destination, Local(OperandType.I32) });
|
||||
node.SetDestinations([node.Destination, Local(OperandType.I32)]);
|
||||
|
||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
||||
// so they can't be used as destination operand.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public ParallelCopy()
|
||||
{
|
||||
_copies = new List<Copy>();
|
||||
_copies = [];
|
||||
}
|
||||
|
||||
public void AddCopy(Register dest, Register source, OperandType type)
|
||||
|
|
@ -218,7 +218,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public Operation[] Sequence()
|
||||
{
|
||||
List<Operation> sequence = new();
|
||||
List<Operation> sequence = [];
|
||||
|
||||
if (_spillQueue != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -799,8 +799,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void NumberLocals(ControlFlowGraph cfg, int registersCount)
|
||||
{
|
||||
_operationNodes = new List<(IntrusiveList<Operation>, Operation)>();
|
||||
_intervals = new List<LiveInterval>();
|
||||
_operationNodes = [];
|
||||
_intervals = [];
|
||||
|
||||
for (int index = 0; index < registersCount; index++)
|
||||
{
|
||||
|
|
@ -980,7 +980,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
_blockLiveIn = blkLiveIn;
|
||||
|
||||
_blockEdges = new HashSet<int>();
|
||||
_blockEdges = [];
|
||||
|
||||
// Compute lifetime intervals.
|
||||
int operationPos = _operationsCount;
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_stream = stream;
|
||||
_labels = new Dictionary<Operand, long>();
|
||||
_jumps = new List<Jump>();
|
||||
_jumps = [];
|
||||
|
||||
_relocs = relocatable ? new List<Reloc>() : null;
|
||||
_relocs = relocatable ? [] : null;
|
||||
}
|
||||
|
||||
public void MarkLabel(Operand label)
|
||||
|
|
|
|||
|
|
@ -1748,7 +1748,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
List<UnwindPushEntry> pushEntries = [];
|
||||
|
||||
Operand rsp = Register(X86Register.Rsp);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||
return 0;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> asmGetXcr0 = new byte[]
|
||||
{
|
||||
ReadOnlySpan<byte> asmGetXcr0 =
|
||||
[
|
||||
0x31, 0xc9, // xor ecx, ecx
|
||||
0xf, 0x01, 0xd0, // xgetbv
|
||||
0xc3, // ret
|
||||
};
|
||||
0xc3 // ret
|
||||
];
|
||||
|
||||
using MemoryBlock memGetXcr0 = new((ulong)asmGetXcr0.Length);
|
||||
|
||||
|
|
|
|||
|
|
@ -124,13 +124,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
||||
|
||||
node.SetSources(new Operand[] { Const(stackOffset), node.GetSource(0) });
|
||||
node.SetSources([Const(stackOffset), node.GetSource(0)]);
|
||||
}
|
||||
else if (node.Intrinsic == Intrinsic.X86Stmxcsr)
|
||||
{
|
||||
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
||||
|
||||
node.SetSources(new Operand[] { Const(stackOffset) });
|
||||
node.SetSources([Const(stackOffset)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -253,8 +253,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
|
||||
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
|
||||
|
||||
operation.SetDestinations(new Operand[] { rdx, rax });
|
||||
operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
|
||||
operation.SetDestinations([rdx, rax]);
|
||||
operation.SetSources([operation.GetSource(0), rdx, rax, rcx, rbx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -274,7 +274,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
|
||||
|
||||
node.SetSources(new Operand[] { node.GetSource(0), rax, temp });
|
||||
node.SetSources([node.GetSource(0), rax, temp]);
|
||||
|
||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
||||
|
||||
|
|
@ -303,7 +303,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
||||
|
||||
node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) });
|
||||
node.SetSources([rdx, rax, node.GetSource(1)]);
|
||||
node.Destination = rax;
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
|
||||
|
||||
node.SetDestinations(new Operand[] { rdx, rax });
|
||||
node.SetDestinations([rdx, rax]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
Operand dest = node.Destination;
|
||||
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0),
|
||||
};
|
||||
List<Operand> sources =
|
||||
[
|
||||
node.GetSource(0)
|
||||
];
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
||||
|
|
@ -117,10 +117,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0),
|
||||
};
|
||||
List<Operand> sources =
|
||||
[
|
||||
node.GetSource(0)
|
||||
];
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
nodes.AddBefore(node, retCopyOp);
|
||||
}
|
||||
|
||||
node.SetSources(Array.Empty<Operand>());
|
||||
node.SetSources([]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,52 +3,46 @@ namespace ARMeilleure.Common
|
|||
public static class AddressTablePresets
|
||||
{
|
||||
private static readonly AddressTableLevel[] _levels64Bit =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new(31, 17),
|
||||
[
|
||||
new(31, 17),
|
||||
new(23, 8),
|
||||
new(15, 8),
|
||||
new( 7, 8),
|
||||
new( 2, 5),
|
||||
};
|
||||
new( 2, 5)
|
||||
];
|
||||
|
||||
private static readonly AddressTableLevel[] _levels32Bit =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new(31, 17),
|
||||
[
|
||||
new(31, 17),
|
||||
new(23, 8),
|
||||
new(15, 8),
|
||||
new( 7, 8),
|
||||
new( 1, 6),
|
||||
};
|
||||
new( 1, 6)
|
||||
];
|
||||
|
||||
private static readonly AddressTableLevel[] _levels64BitSparseTiny =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new( 11, 28),
|
||||
new( 2, 9),
|
||||
};
|
||||
[
|
||||
new( 11, 28),
|
||||
new( 2, 9)
|
||||
];
|
||||
|
||||
private static readonly AddressTableLevel[] _levels32BitSparseTiny =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new( 10, 22),
|
||||
new( 1, 9),
|
||||
};
|
||||
[
|
||||
new( 10, 22),
|
||||
new( 1, 9)
|
||||
];
|
||||
|
||||
private static readonly AddressTableLevel[] _levels64BitSparseGiant =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new( 38, 1),
|
||||
new( 2, 36),
|
||||
};
|
||||
[
|
||||
new( 38, 1),
|
||||
new( 2, 36)
|
||||
];
|
||||
|
||||
private static readonly AddressTableLevel[] _levels32BitSparseGiant =
|
||||
new AddressTableLevel[]
|
||||
{
|
||||
new( 31, 1),
|
||||
new( 1, 30),
|
||||
};
|
||||
[
|
||||
new( 31, 1),
|
||||
new( 1, 30)
|
||||
];
|
||||
|
||||
//high power will run worse on DDR3 systems and some DDR4 systems due to the higher ram utilization
|
||||
//low power will never run worse than non-sparse, but for most systems it won't be necessary
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ namespace ARMeilleure.Common
|
|||
_pageIndex = -1;
|
||||
|
||||
_page = null;
|
||||
_pages = new List<PageInfo>();
|
||||
_pages = [];
|
||||
_pageSize = pageSize;
|
||||
_pageCount = pageCount;
|
||||
|
||||
_extras = new List<IntPtr>();
|
||||
_extras = [];
|
||||
}
|
||||
|
||||
public Span<T> AllocateSpan<T>(ulong count) where T : unmanaged
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace ARMeilleure.Common
|
|||
{
|
||||
static class BitUtils
|
||||
{
|
||||
private static ReadOnlySpan<sbyte> HbsNibbleLut => new sbyte[] { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
private static ReadOnlySpan<sbyte> HbsNibbleLut => [-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3];
|
||||
|
||||
public static long FillWithOnes(int bits)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public Block()
|
||||
{
|
||||
OpCodes = new List<OpCode>();
|
||||
OpCodes = [];
|
||||
}
|
||||
|
||||
public Block(ulong address) : this()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, DecoderMode dMode)
|
||||
{
|
||||
List<Block> blocks = new();
|
||||
List<Block> blocks = [];
|
||||
|
||||
Queue<Block> workQueue = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ namespace ARMeilleure.Decoders
|
|||
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
||||
{
|
||||
private static readonly int[] _regsMap =
|
||||
{
|
||||
[
|
||||
1, 1, 4, 2,
|
||||
1, 1, 3, 1,
|
||||
1, 1, 2, 1,
|
||||
1, 1, 1, 1,
|
||||
};
|
||||
1, 1, 1, 1
|
||||
];
|
||||
|
||||
public int Vd { get; }
|
||||
public int Rn { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public OpCodeT16IfThen(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
List<Condition> conds = new();
|
||||
List<Condition> conds = [];
|
||||
|
||||
int cond = (opCode >> 4) & 0xf;
|
||||
int mask = opCode & 0xf;
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly List<InstInfo> _allInstA32 = new();
|
||||
private static readonly List<InstInfo> _allInstT32 = new();
|
||||
private static readonly List<InstInfo> _allInstA64 = new();
|
||||
private static readonly List<InstInfo> _allInstA32 = [];
|
||||
private static readonly List<InstInfo> _allInstT32 = [];
|
||||
private static readonly List<InstInfo> _allInstA64 = [];
|
||||
|
||||
private static readonly InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][];
|
||||
|
|
@ -1330,7 +1330,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
for (int index = 0; index < temp.Length; index++)
|
||||
{
|
||||
temp[index] = new List<InstInfo>();
|
||||
temp[index] = [];
|
||||
}
|
||||
|
||||
foreach (InstInfo inst in allInsts)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace ARMeilleure.Diagnostics
|
|||
static Symbols()
|
||||
{
|
||||
_symbols = new ConcurrentDictionary<ulong, string>();
|
||||
_rangedSymbols = new List<RangedSymbol>();
|
||||
_rangedSymbols = [];
|
||||
}
|
||||
|
||||
public static string Get(ulong address)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
#region "LookUp Tables"
|
||||
#pragma warning disable IDE1006 // Naming rule violation
|
||||
private static ReadOnlySpan<byte> _sBox => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _sBox =>
|
||||
[
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
|
|
@ -26,11 +26,11 @@ namespace ARMeilleure.Instructions
|
|||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _invSBox => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _invSBox =>
|
||||
[
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
|
|
@ -46,11 +46,11 @@ namespace ARMeilleure.Instructions
|
|||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul02 => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul02 =>
|
||||
[
|
||||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
|
||||
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
|
||||
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
|
||||
|
|
@ -66,11 +66,11 @@ namespace ARMeilleure.Instructions
|
|||
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
||||
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
||||
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
|
||||
};
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul03 => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul03 =>
|
||||
[
|
||||
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
|
||||
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
|
||||
0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
|
||||
|
|
@ -86,11 +86,11 @@ namespace ARMeilleure.Instructions
|
|||
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
||||
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
||||
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
|
||||
};
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul09 => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul09 =>
|
||||
[
|
||||
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
|
||||
0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
|
||||
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
|
||||
|
|
@ -106,11 +106,11 @@ namespace ARMeilleure.Instructions
|
|||
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
||||
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
||||
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
|
||||
};
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0B => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul0B =>
|
||||
[
|
||||
0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
|
||||
0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
|
||||
0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
|
||||
|
|
@ -126,11 +126,11 @@ namespace ARMeilleure.Instructions
|
|||
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
||||
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
||||
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
|
||||
};
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0D => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul0D =>
|
||||
[
|
||||
0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
|
||||
0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
|
||||
0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
|
||||
|
|
@ -146,11 +146,11 @@ namespace ARMeilleure.Instructions
|
|||
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
||||
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
||||
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
|
||||
};
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0E => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> _gfMul0E =>
|
||||
[
|
||||
0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
|
||||
0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
|
||||
0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
|
||||
|
|
@ -166,18 +166,18 @@ namespace ARMeilleure.Instructions
|
|||
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
||||
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
||||
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
|
||||
};
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _srPerm => new byte[]
|
||||
{
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3,
|
||||
};
|
||||
private static ReadOnlySpan<byte> _srPerm =>
|
||||
[
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> _isrPerm => new byte[]
|
||||
{
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11,
|
||||
};
|
||||
private static ReadOnlySpan<byte> _isrPerm =>
|
||||
[
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
|
||||
];
|
||||
#pragma warning restore IDE1006
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -283,8 +283,6 @@ namespace ARMeilleure.Instructions
|
|||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
|
|
@ -332,8 +330,6 @@ namespace ARMeilleure.Instructions
|
|||
switch (shiftType)
|
||||
{
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -305,8 +305,6 @@ namespace ARMeilleure.Instructions
|
|||
context.Store16(physAddr, value);
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
|
|
@ -591,8 +589,6 @@ namespace ARMeilleure.Instructions
|
|||
value = context.VectorInsert16(vector, value, elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
|
|
@ -733,8 +729,6 @@ namespace ARMeilleure.Instructions
|
|||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -451,7 +451,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -483,7 +483,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -522,7 +522,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2246,7 +2246,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2265,7 +2265,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2322,7 +2322,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2341,7 +2341,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2390,7 +2390,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2409,7 +2409,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -726,8 +726,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (absolute)
|
||||
{
|
||||
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne);
|
||||
me = EmitUnaryMathCall(context, nameof(Math.Abs), me);
|
||||
ne = EmitUnaryMathCall(context, nameof(MathHelper.Abs), ne);
|
||||
me = EmitUnaryMathCall(context, nameof(MathHelper.Abs), me);
|
||||
}
|
||||
|
||||
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1), signed: true, scalar: false);
|
||||
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1), signed: true, scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -538,7 +538,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,7 +554,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -245,8 +245,8 @@ namespace ARMeilleure.Instructions
|
|||
string name = nameof(Math.Round);
|
||||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
? typeof(MathF).GetMethod(name, [typeof(float), typeof(MidpointRounding)])
|
||||
: typeof(Math).GetMethod(name, [typeof(double), typeof(MidpointRounding)]);
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
|
@ -357,10 +357,10 @@ namespace ARMeilleure.Instructions
|
|||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
||||
break;
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -494,10 +494,10 @@ namespace ARMeilleure.Instructions
|
|||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
||||
break;
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +534,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), m));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +574,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), m));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -613,7 +613,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1));
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,19 +18,19 @@ namespace ARMeilleure.Instructions
|
|||
static class InstEmitSimdHelper
|
||||
{
|
||||
#region "Masks"
|
||||
public static readonly long[] EvenMasks = new long[]
|
||||
{
|
||||
public static readonly long[] EvenMasks =
|
||||
[
|
||||
14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, // B
|
||||
13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, // H
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0, // S
|
||||
};
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 // S
|
||||
];
|
||||
|
||||
public static readonly long[] OddMasks = new long[]
|
||||
{
|
||||
public static readonly long[] OddMasks =
|
||||
[
|
||||
15L << 56 | 13L << 48 | 11L << 40 | 09L << 32 | 07L << 24 | 05L << 16 | 03L << 8 | 01L << 0, // B
|
||||
15L << 56 | 14L << 48 | 11L << 40 | 10L << 32 | 07L << 24 | 06L << 16 | 03L << 8 | 02L << 0, // H
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0, // S
|
||||
};
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0 // S
|
||||
];
|
||||
|
||||
public const long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
|
||||
|
||||
|
|
@ -44,118 +44,118 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "X86 SSE Intrinsics"
|
||||
public static readonly Intrinsic[] X86PaddInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PaddInstruction =
|
||||
[
|
||||
Intrinsic.X86Paddb,
|
||||
Intrinsic.X86Paddw,
|
||||
Intrinsic.X86Paddd,
|
||||
Intrinsic.X86Paddq,
|
||||
};
|
||||
Intrinsic.X86Paddq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PcmpeqInstruction =
|
||||
[
|
||||
Intrinsic.X86Pcmpeqb,
|
||||
Intrinsic.X86Pcmpeqw,
|
||||
Intrinsic.X86Pcmpeqd,
|
||||
Intrinsic.X86Pcmpeqq,
|
||||
};
|
||||
Intrinsic.X86Pcmpeqq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PcmpgtInstruction =
|
||||
[
|
||||
Intrinsic.X86Pcmpgtb,
|
||||
Intrinsic.X86Pcmpgtw,
|
||||
Intrinsic.X86Pcmpgtd,
|
||||
Intrinsic.X86Pcmpgtq,
|
||||
};
|
||||
Intrinsic.X86Pcmpgtq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PmaxsInstruction =
|
||||
[
|
||||
Intrinsic.X86Pmaxsb,
|
||||
Intrinsic.X86Pmaxsw,
|
||||
Intrinsic.X86Pmaxsd,
|
||||
};
|
||||
Intrinsic.X86Pmaxsd
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PmaxuInstruction =
|
||||
[
|
||||
Intrinsic.X86Pmaxub,
|
||||
Intrinsic.X86Pmaxuw,
|
||||
Intrinsic.X86Pmaxud,
|
||||
};
|
||||
Intrinsic.X86Pmaxud
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PminsInstruction =
|
||||
[
|
||||
Intrinsic.X86Pminsb,
|
||||
Intrinsic.X86Pminsw,
|
||||
Intrinsic.X86Pminsd,
|
||||
};
|
||||
Intrinsic.X86Pminsd
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PminuInstruction =
|
||||
[
|
||||
Intrinsic.X86Pminub,
|
||||
Intrinsic.X86Pminuw,
|
||||
Intrinsic.X86Pminud,
|
||||
};
|
||||
Intrinsic.X86Pminud
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PmovsxInstruction =
|
||||
[
|
||||
Intrinsic.X86Pmovsxbw,
|
||||
Intrinsic.X86Pmovsxwd,
|
||||
Intrinsic.X86Pmovsxdq,
|
||||
};
|
||||
Intrinsic.X86Pmovsxdq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PmovzxInstruction =
|
||||
[
|
||||
Intrinsic.X86Pmovzxbw,
|
||||
Intrinsic.X86Pmovzxwd,
|
||||
Intrinsic.X86Pmovzxdq,
|
||||
};
|
||||
Intrinsic.X86Pmovzxdq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PsllInstruction =
|
||||
[
|
||||
0,
|
||||
Intrinsic.X86Psllw,
|
||||
Intrinsic.X86Pslld,
|
||||
Intrinsic.X86Psllq,
|
||||
};
|
||||
Intrinsic.X86Psllq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PsraInstruction =
|
||||
[
|
||||
0,
|
||||
Intrinsic.X86Psraw,
|
||||
Intrinsic.X86Psrad,
|
||||
};
|
||||
Intrinsic.X86Psrad
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PsrlInstruction =
|
||||
[
|
||||
0,
|
||||
Intrinsic.X86Psrlw,
|
||||
Intrinsic.X86Psrld,
|
||||
Intrinsic.X86Psrlq,
|
||||
};
|
||||
Intrinsic.X86Psrlq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PsubInstruction =
|
||||
[
|
||||
Intrinsic.X86Psubb,
|
||||
Intrinsic.X86Psubw,
|
||||
Intrinsic.X86Psubd,
|
||||
Intrinsic.X86Psubq,
|
||||
};
|
||||
Intrinsic.X86Psubq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PunpckhInstruction =
|
||||
[
|
||||
Intrinsic.X86Punpckhbw,
|
||||
Intrinsic.X86Punpckhwd,
|
||||
Intrinsic.X86Punpckhdq,
|
||||
Intrinsic.X86Punpckhqdq,
|
||||
};
|
||||
Intrinsic.X86Punpckhqdq
|
||||
];
|
||||
|
||||
public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[]
|
||||
{
|
||||
public static readonly Intrinsic[] X86PunpcklInstruction =
|
||||
[
|
||||
Intrinsic.X86Punpcklbw,
|
||||
Intrinsic.X86Punpcklwd,
|
||||
Intrinsic.X86Punpckldq,
|
||||
Intrinsic.X86Punpcklqdq,
|
||||
};
|
||||
Intrinsic.X86Punpcklqdq
|
||||
];
|
||||
#endregion
|
||||
|
||||
public static void EnterArmFpMode(EmitterContext context, Func<FPState, Operand> getFpFlag)
|
||||
|
|
@ -460,8 +460,8 @@ namespace ARMeilleure.Instructions
|
|||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) })
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double) });
|
||||
? typeof(MathHelperF).GetMethod(name, [typeof(float)])
|
||||
: typeof(MathHelper).GetMethod(name, [typeof(double)]);
|
||||
|
||||
return context.Call(info, n);
|
||||
}
|
||||
|
|
@ -470,11 +470,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
string name = nameof(Math.Round);
|
||||
string name = nameof(MathHelper.Round);
|
||||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
? typeof(MathHelperF).GetMethod(name, [typeof(float), typeof(int)])
|
||||
: typeof(MathHelper).GetMethod(name, [typeof(double), typeof(int)]);
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
|
@ -510,16 +510,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl2);
|
||||
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Floor), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl3);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
|
@ -2082,8 +2082,6 @@ namespace ARMeilleure.Instructions
|
|||
vector = context.VectorInsert16(vector, value, index);
|
||||
break;
|
||||
case 2:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
case 3:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -12,17 +12,17 @@ namespace ARMeilleure.Instructions
|
|||
static partial class InstEmit
|
||||
{
|
||||
#region "Masks"
|
||||
private static readonly long[] _masksE0_Uzp = new long[]
|
||||
{
|
||||
private static readonly long[] _masksE0_Uzp =
|
||||
[
|
||||
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0,
|
||||
};
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0
|
||||
];
|
||||
|
||||
private static readonly long[] _masksE1_Uzp = new long[]
|
||||
{
|
||||
private static readonly long[] _masksE1_Uzp =
|
||||
[
|
||||
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0,
|
||||
};
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0
|
||||
];
|
||||
#endregion
|
||||
|
||||
public static void Dup_Gp(ArmEmitterContext context)
|
||||
|
|
@ -601,7 +601,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
|
||||
List<Operand> args = new();
|
||||
List<Operand> args = [];
|
||||
|
||||
if (!isTbl)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,17 +13,17 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
#region "Masks"
|
||||
// Same as InstEmitSimdMove, as the instructions do the same thing.
|
||||
private static readonly long[] _masksE0_Uzp = new long[]
|
||||
{
|
||||
private static readonly long[] _masksE0_Uzp =
|
||||
[
|
||||
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0,
|
||||
};
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0
|
||||
];
|
||||
|
||||
private static readonly long[] _masksE1_Uzp = new long[]
|
||||
{
|
||||
private static readonly long[] _masksE1_Uzp =
|
||||
[
|
||||
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0,
|
||||
};
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0
|
||||
];
|
||||
#endregion
|
||||
|
||||
public static void Vmov_I(ArmEmitterContext context)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ namespace ARMeilleure.Instructions
|
|||
static partial class InstEmit
|
||||
{
|
||||
#region "Masks"
|
||||
private static readonly long[] _masks_SliSri = new long[] // Replication masks.
|
||||
{
|
||||
0x0101010101010101L, 0x0001000100010001L, 0x0000000100000001L, 0x0000000000000001L,
|
||||
};
|
||||
private static readonly long[] _masks_SliSri =
|
||||
[
|
||||
0x0101010101010101L, 0x0001000100010001L, 0x0000000100000001L, 0x0000000000000001L
|
||||
];
|
||||
#endregion
|
||||
|
||||
public static void Rshrn_V(ArmEmitterContext context)
|
||||
|
|
|
|||
115
src/ARMeilleure/Instructions/MathHelper.cs
Normal file
115
src/ARMeilleure/Instructions/MathHelper.cs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
#if ANDROID
|
||||
using System.Runtime.CompilerServices;
|
||||
#else
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class MathHelper
|
||||
{
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static double Abs(double value)
|
||||
{
|
||||
return Math.Abs(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static double Ceiling(double value)
|
||||
{
|
||||
return Math.Ceiling(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static double Floor(double value)
|
||||
{
|
||||
return Math.Floor(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static double Round(double value, int mode)
|
||||
{
|
||||
return Math.Round(value, (MidpointRounding)mode);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static double Truncate(double value)
|
||||
{
|
||||
return Math.Truncate(value);
|
||||
}
|
||||
}
|
||||
|
||||
static class MathHelperF
|
||||
{
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static float Abs(float value)
|
||||
{
|
||||
return MathF.Abs(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static float Ceiling(float value)
|
||||
{
|
||||
return MathF.Ceiling(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static float Floor(float value)
|
||||
{
|
||||
return MathF.Floor(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static float Round(float value, int mode)
|
||||
{
|
||||
return MathF.Round(value, (MidpointRounding)mode);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static float Truncate(float value)
|
||||
{
|
||||
return MathF.Truncate(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,11 @@ using ARMeilleure.Memory;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
#if ANDROID
|
||||
using System.Runtime.CompilerServices;
|
||||
#else
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
|
|
@ -34,6 +39,11 @@ namespace ARMeilleure.Instructions
|
|||
Context = null;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void Break(ulong address, int imm)
|
||||
{
|
||||
Statistics.PauseTimer();
|
||||
|
|
@ -43,6 +53,11 @@ namespace ARMeilleure.Instructions
|
|||
Statistics.ResumeTimer();
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void SupervisorCall(ulong address, int imm)
|
||||
{
|
||||
Statistics.PauseTimer();
|
||||
|
|
@ -52,6 +67,11 @@ namespace ARMeilleure.Instructions
|
|||
Statistics.ResumeTimer();
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void Undefined(ulong address, int opCode)
|
||||
{
|
||||
Statistics.PauseTimer();
|
||||
|
|
@ -62,26 +82,51 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
#region "System registers"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetCtrEl0()
|
||||
{
|
||||
return GetContext().CtrEl0;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetDczidEl0()
|
||||
{
|
||||
return GetContext().DczidEl0;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetCntfrqEl0()
|
||||
{
|
||||
return GetContext().CntfrqEl0;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetCntpctEl0()
|
||||
{
|
||||
return GetContext().CntpctEl0;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetCntvctEl0()
|
||||
{
|
||||
return GetContext().CntvctEl0;
|
||||
|
|
@ -89,26 +134,51 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Read"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static byte ReadByte(ulong address)
|
||||
{
|
||||
return GetMemoryManager().ReadGuest<byte>(address);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ushort ReadUInt16(ulong address)
|
||||
{
|
||||
return GetMemoryManager().ReadGuest<ushort>(address);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint ReadUInt32(ulong address)
|
||||
{
|
||||
return GetMemoryManager().ReadGuest<uint>(address);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong ReadUInt64(ulong address)
|
||||
{
|
||||
return GetMemoryManager().ReadGuest<ulong>(address);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 ReadVector128(ulong address)
|
||||
{
|
||||
return GetMemoryManager().ReadGuest<V128>(address);
|
||||
|
|
@ -116,47 +186,92 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Write"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void WriteByte(ulong address, byte value)
|
||||
{
|
||||
GetMemoryManager().WriteGuest(address, value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void WriteUInt16(ulong address, ushort value)
|
||||
{
|
||||
GetMemoryManager().WriteGuest(address, value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void WriteUInt32(ulong address, uint value)
|
||||
{
|
||||
GetMemoryManager().WriteGuest(address, value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void WriteUInt64(ulong address, ulong value)
|
||||
{
|
||||
GetMemoryManager().WriteGuest(address, value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void WriteVector128(ulong address, V128 value)
|
||||
{
|
||||
GetMemoryManager().WriteGuest(address, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void EnqueueForRejit(ulong address)
|
||||
{
|
||||
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
||||
}
|
||||
|
||||
public static void SignalMemoryTracking(ulong address, ulong size, bool write)
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
|
||||
{
|
||||
GetMemoryManager().SignalMemoryTracking(address, size, write);
|
||||
GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void ThrowInvalidMemoryAccess(ulong address)
|
||||
{
|
||||
throw new InvalidAccessException(address);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong GetFunctionAddress(ulong address)
|
||||
{
|
||||
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
||||
|
|
@ -164,12 +279,22 @@ namespace ARMeilleure.Instructions
|
|||
return (ulong)function.FuncPointer.ToInt64();
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static void InvalidateCacheLine(ulong address)
|
||||
{
|
||||
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
||||
}
|
||||
|
||||
public static bool CheckSynchronization()
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static byte CheckSynchronization()
|
||||
{
|
||||
Statistics.PauseTimer();
|
||||
|
||||
|
|
@ -179,7 +304,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Statistics.ResumeTimer();
|
||||
|
||||
return context.Running;
|
||||
return (byte)(context.Running ? 1 : 0);
|
||||
}
|
||||
|
||||
public static ExecutionContext GetContext()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
#if ANDROID
|
||||
using System.Runtime.CompilerServices;
|
||||
#else
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFallback
|
||||
{
|
||||
#region "ShrImm64"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
|
|
@ -48,6 +58,11 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
|
|
@ -92,6 +107,11 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Saturation"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static int SatF32ToS32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
|
|
@ -103,6 +123,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static long SatF32ToS64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
|
|
@ -114,6 +139,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint SatF32ToU32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
|
|
@ -125,6 +155,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong SatF32ToU64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
|
|
@ -136,6 +171,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static int SatF64ToS32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
|
|
@ -147,6 +187,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static long SatF64ToS64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
|
|
@ -158,6 +203,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint SatF64ToU32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
|
|
@ -169,6 +219,11 @@ namespace ARMeilleure.Instructions
|
|||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong SatF64ToU64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
|
|
@ -182,6 +237,11 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Count"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
value ^= value >> 1;
|
||||
|
|
@ -199,8 +259,13 @@ namespace ARMeilleure.Instructions
|
|||
return (ulong)(size - 1);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
if (value == 0ul)
|
||||
|
|
@ -224,41 +289,81 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Table"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
|
|
@ -300,14 +405,54 @@ namespace ARMeilleure.Instructions
|
|||
private const uint Crc32RevPoly = 0xedb88320;
|
||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||
|
||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||
|
|
@ -358,21 +503,41 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Aes"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Encrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 InverseMixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesInvMixColumns(value);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 MixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesMixColumns(value);
|
||||
|
|
@ -380,6 +545,11 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Sha1"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
|
|
@ -400,11 +570,21 @@ namespace ARMeilleure.Instructions
|
|||
return hash_abcd;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static uint FixedRotate(uint hash_e)
|
||||
{
|
||||
return hash_e.Rol(30);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
|
|
@ -425,6 +605,11 @@ namespace ARMeilleure.Instructions
|
|||
return hash_abcd;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
|
|
@ -445,6 +630,11 @@ namespace ARMeilleure.Instructions
|
|||
return hash_abcd;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
||||
{
|
||||
ulong t2 = w4_7.Extract<ulong>(0);
|
||||
|
|
@ -455,6 +645,11 @@ namespace ARMeilleure.Instructions
|
|||
return result ^ (w0_3 ^ w8_11);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
||||
{
|
||||
V128 t = tw0_3 ^ (w12_15 >> 32);
|
||||
|
|
@ -499,16 +694,31 @@ namespace ARMeilleure.Instructions
|
|||
#endregion
|
||||
|
||||
#region "Sha256"
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||
{
|
||||
V128 result = new();
|
||||
|
|
@ -527,6 +737,11 @@ namespace ARMeilleure.Instructions
|
|||
return result;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||
{
|
||||
V128 result = new();
|
||||
|
|
@ -628,6 +843,11 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
#endregion
|
||||
|
||||
#if ANDROID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[UnmanagedCallersOnly]
|
||||
#endif
|
||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||
{
|
||||
V128 result = V128.Zero;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,7 +27,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
{
|
||||
get
|
||||
{
|
||||
_domFrontiers ??= new HashSet<BasicBlock>();
|
||||
_domFrontiers ??= [];
|
||||
|
||||
return _domFrontiers;
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
public BasicBlock(int index)
|
||||
{
|
||||
Operations = new IntrusiveList<Operation>();
|
||||
Predecessors = new List<BasicBlock>();
|
||||
Predecessors = [];
|
||||
|
||||
Index = index;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ namespace ARMeilleure.Memory
|
|||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
|
||||
public IJitMemoryBlock Block { get; }
|
||||
public IJitMemoryAllocator Allocator { get; }
|
||||
|
||||
public IntPtr Pointer => Block.Pointer;
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ namespace ARMeilleure.Memory
|
|||
granularity = DefaultGranularity;
|
||||
}
|
||||
|
||||
Allocator = allocator;
|
||||
Block = allocator.Reserve(maxSize);
|
||||
_maxSize = maxSize;
|
||||
_sizeGranularity = granularity;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
namespace ARMeilleure
|
||||
{
|
||||
using Arm64HardwareCapabilities = ARMeilleure.CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = ARMeilleure.CodeGen.X86.HardwareCapabilities;
|
||||
using Arm64HardwareCapabilities = CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = CodeGen.X86.HardwareCapabilities;
|
||||
|
||||
public static class Optimizations
|
||||
{
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ namespace ARMeilleure.Signal
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I32, OperandType.I64, OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ namespace ARMeilleure.Signal
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Signal
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>();
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ namespace ARMeilleure.Signal
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugThreadLocalMapGetOrReserve>();
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ namespace ARMeilleure.Signal
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugNativeWriteLoop>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace ARMeilleure.Translation
|
|||
public Aarch32Mode Mode { get; }
|
||||
|
||||
private int _ifThenBlockStateIndex = 0;
|
||||
private Condition[] _ifThenBlockState = Array.Empty<Condition>();
|
||||
private Condition[] _ifThenBlockState = [];
|
||||
public bool IsInIfThenBlock => _ifThenBlockStateIndex < _ifThenBlockState.Length;
|
||||
public Condition CurrentIfThenBlockCond => _ifThenBlockState[_ifThenBlockStateIndex];
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
}
|
||||
|
||||
private readonly List<MemoryBlock> _blocks = new();
|
||||
private readonly List<MemoryBlock> _blocks = [];
|
||||
|
||||
public CacheMemoryAllocator(int capacity)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ using ARMeilleure.CodeGen;
|
|||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Native;
|
||||
using Humanizer;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -18,51 +20,68 @@ namespace ARMeilleure.Translation.Cache
|
|||
private static readonly int _pageMask = _pageSize - 1;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
private const int CacheSize = 256 * 1024 * 1024;
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
|
||||
private static CacheMemoryAllocator _cacheAllocator;
|
||||
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
||||
|
||||
private static readonly List<CacheEntry> _cacheEntries = new();
|
||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
private static bool _initialized;
|
||||
|
||||
private static readonly List<ReservedRegion> _jitRegions = [];
|
||||
private static int _activeRegionIndex = 0;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize);
|
||||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
JitUnwindWindows.RemoveFunctionTableHandler(
|
||||
_jitRegions[0].Pointer);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _jitRegions.Count; i++)
|
||||
{
|
||||
_jitRegions[i].Dispose();
|
||||
}
|
||||
|
||||
_jitRegions.Clear();
|
||||
_cacheAllocators.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_activeRegionIndex = 0;
|
||||
|
||||
var firstRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_jitRegions.Add(firstRegion);
|
||||
|
||||
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
|
||||
_cacheAllocators.Add(firstCacheAllocator);
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
|
||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
|
||||
JitUnwindWindows.InstallFunctionTableHandler(
|
||||
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
||||
);
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,8 +94,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
Debug.Assert(_initialized);
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
|
||||
IntPtr funcPtr = targetRegion.Pointer + funcOffset;
|
||||
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
|
|
@ -90,9 +109,9 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
else
|
||||
{
|
||||
ReprotectAsWritable(funcOffset, code.Length);
|
||||
ReprotectAsWritable(targetRegion, funcOffset, code.Length);
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
|
||||
|
||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
|
|
@ -116,50 +135,74 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
Debug.Assert(_initialized);
|
||||
|
||||
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
|
||||
|
||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||
foreach (var region in _jitRegions)
|
||||
{
|
||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
|
||||
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
|
||||
|
||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||
{
|
||||
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size));
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReprotectAsWritable(int offset, int size)
|
||||
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size)
|
||||
{
|
||||
int endOffs = offset + size;
|
||||
|
||||
int regionStart = offset & ~_pageMask;
|
||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||
|
||||
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
||||
private static void ReprotectAsExecutable(int offset, int size)
|
||||
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size)
|
||||
{
|
||||
int endOffs = offset + size;
|
||||
|
||||
int regionStart = offset & ~_pageMask;
|
||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||
|
||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
||||
private static int Allocate(int codeSize)
|
||||
{
|
||||
codeSize = AlignCodeSize(codeSize);
|
||||
|
||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||
|
||||
if (allocOffset < 0)
|
||||
if (allocOffset >= 0)
|
||||
{
|
||||
throw new OutOfMemoryException("JIT Cache exhausted.");
|
||||
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||
return allocOffset;
|
||||
}
|
||||
|
||||
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||
int exhaustedRegion = _activeRegionIndex;
|
||||
var newRegion = new ReservedRegion(_jitRegions[0].Allocator, CacheSize);
|
||||
_jitRegions.Add(newRegion);
|
||||
_activeRegionIndex = _jitRegions.Count - 1;
|
||||
|
||||
return allocOffset;
|
||||
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||
|
||||
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
|
||||
|
||||
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||
if (allocOffsetNew < 0)
|
||||
{
|
||||
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||
}
|
||||
|
||||
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
|
||||
return allocOffsetNew;
|
||||
}
|
||||
|
||||
private static int AlignCodeSize(int codeSize)
|
||||
|
|
@ -185,18 +228,21 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
lock (_lock)
|
||||
{
|
||||
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
||||
|
||||
if (index < 0)
|
||||
foreach (var region in _jitRegions)
|
||||
{
|
||||
index = ~index - 1;
|
||||
}
|
||||
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
entry = _cacheEntries[index];
|
||||
entryIndex = index;
|
||||
return true;
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index - 1;
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
entry = _cacheEntries[index];
|
||||
entryIndex = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
class JitCacheInvalidation
|
||||
{
|
||||
private static readonly int[] _invalidationCode = new int[]
|
||||
{
|
||||
private static readonly int[] _invalidationCode =
|
||||
[
|
||||
unchecked((int)0xd53b0022), // mrs x2, ctr_el0
|
||||
unchecked((int)0xd3504c44), // ubfx x4, x2, #16, #4
|
||||
unchecked((int)0x52800083), // mov w3, #0x4
|
||||
|
|
@ -35,8 +35,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
unchecked((int)0x54ffffa8), // b.hi 54 <ic_clear_loop>
|
||||
unchecked((int)0xd5033b9f), // dsb ish
|
||||
unchecked((int)0xd5033fdf), // isb
|
||||
unchecked((int)0xd65f03c0), // ret
|
||||
};
|
||||
unchecked((int)0xd65f03c0) // ret
|
||||
];
|
||||
|
||||
private delegate void InvalidateCache(ulong start, ulong end);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ namespace ARMeilleure.Translation.Cache
|
|||
IntPtr context,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static unsafe partial bool RtlDeleteFunctionTable(
|
||||
ulong tableIdentifier);
|
||||
|
||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||
|
||||
private static int _sizeOfRuntimeFunction;
|
||||
|
|
@ -91,6 +96,23 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
}
|
||||
|
||||
public static void RemoveFunctionTableHandler(IntPtr codeCachePointer)
|
||||
{
|
||||
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||
|
||||
bool result;
|
||||
|
||||
unsafe
|
||||
{
|
||||
result = RtlDeleteFunctionTable(codeCachePtr | 3);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
throw new InvalidOperationException("Failure removing function table callback.");
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, IntPtr context)
|
||||
{
|
||||
int offset = (int)((long)controlPc - context.ToInt64());
|
||||
|
|
|
|||
|
|
@ -2,17 +2,12 @@ using System;
|
|||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
class DelegateInfo
|
||||
public class DelegateInfo
|
||||
{
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected.
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
public IntPtr FuncPtr { get; }
|
||||
|
||||
public DelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||
public DelegateInfo(IntPtr funcPtr)
|
||||
{
|
||||
_dlg = dlg;
|
||||
FuncPtr = funcPtr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -97,7 +97,14 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||
{
|
||||
IntPtr funcPtr = Delegates.GetDelegateFuncPtr(info);
|
||||
#if ANDROID
|
||||
// For Android, use the Delegates class to get the function pointer
|
||||
int index = Delegates.GetDelegateIndex(info);
|
||||
IntPtr funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
|
||||
#else
|
||||
// For other platforms, use direct method handle approach
|
||||
IntPtr funcPtr = info.MethodHandle.GetFunctionPointer();
|
||||
#endif
|
||||
|
||||
OperandType returnType = GetOperandType(info.ReturnType);
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace ARMeilleure.Translation
|
|||
/// <returns>A list of all values sorted by Key Order</returns>
|
||||
public List<TV> AsList()
|
||||
{
|
||||
List<TV> list = new();
|
||||
List<TV> list = [];
|
||||
|
||||
AddToList(_root, list);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using ARMeilleure.CodeGen.Linking;
|
|||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.State;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
|
|
@ -29,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 6997; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
|
|
@ -152,7 +153,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
private void InitializeCarriers()
|
||||
{
|
||||
_infosStream = MemoryStreamManager.Shared.GetStream();
|
||||
_codesList = new List<byte[]>();
|
||||
_codesList = [];
|
||||
_relocsStream = MemoryStreamManager.Shared.GetStream();
|
||||
_unwindInfosStream = MemoryStreamManager.Shared.GetStream();
|
||||
}
|
||||
|
|
@ -182,6 +183,36 @@ namespace ARMeilleure.Translation.PTC
|
|||
InitializeCarriers();
|
||||
}
|
||||
|
||||
private bool ContainsBlacklistedFunctions()
|
||||
{
|
||||
List<ulong> blacklist = Profiler.GetBlacklistedFunctions();
|
||||
bool containsBlacklistedFunctions = false;
|
||||
_infosStream.Seek(0L, SeekOrigin.Begin);
|
||||
bool foundBadFunction = false;
|
||||
|
||||
for (int index = 0; index < GetEntriesCount(); index++)
|
||||
{
|
||||
InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream);
|
||||
foreach (ulong address in blacklist)
|
||||
{
|
||||
if (infoEntry.Address == address)
|
||||
{
|
||||
containsBlacklistedFunctions = true;
|
||||
Logger.Warning?.Print(LogClass.Ptc, "PPTC cache invalidated: Found blacklisted functions in PPTC cache");
|
||||
foundBadFunction = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundBadFunction)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return containsBlacklistedFunctions;
|
||||
}
|
||||
|
||||
private void PreLoad()
|
||||
{
|
||||
string fileNameActual = $"{CachePathActual}.cache";
|
||||
|
|
@ -530,8 +561,9 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
public void LoadTranslations(Translator translator)
|
||||
{
|
||||
if (AreCarriersEmpty())
|
||||
if (AreCarriersEmpty() || ContainsBlacklistedFunctions())
|
||||
{
|
||||
ResetCarriersIfNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -763,7 +795,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
private void StubCode(int index)
|
||||
{
|
||||
_codesList[index] = Array.Empty<byte>();
|
||||
_codesList[index] = [];
|
||||
}
|
||||
|
||||
private void StubReloc(int relocEntriesCount)
|
||||
|
|
@ -833,10 +865,18 @@ namespace ARMeilleure.Translation.PTC
|
|||
while (profiledFuncsToTranslate.TryDequeue(out var item))
|
||||
{
|
||||
ulong address = item.address;
|
||||
ExecutionMode executionMode = item.funcProfile.Mode;
|
||||
bool highCq = item.funcProfile.HighCq;
|
||||
|
||||
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
|
||||
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq);
|
||||
TranslatedFunction func = translator.Translate(address, executionMode, highCq, pptcTranslation: true);
|
||||
|
||||
if (func == null)
|
||||
{
|
||||
Profiler.UpdateEntry(address, executionMode, true, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func);
|
||||
|
||||
|
|
@ -853,7 +893,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
|
||||
List<Thread> threads = new();
|
||||
List<Thread> threads = [];
|
||||
|
||||
for (int i = 0; i < degreeOfParallelism; i++)
|
||||
{
|
||||
|
|
@ -885,7 +925,14 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);
|
||||
|
||||
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
|
||||
if (_translateCount == _translateTotalCount)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | {_translateTotalCount - _translateCount} function{(_translateTotalCount - _translateCount != 1 ? "s" : "")} blacklisted | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
|
||||
}
|
||||
|
||||
Thread preSaveThread = new(PreSave)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static List<T> DeserializeList<T>(Stream stream) where T : struct
|
||||
{
|
||||
List<T> list = new();
|
||||
List<T> list = [];
|
||||
|
||||
int count = DeserializeStructure<int>(stream);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
|
||||
|
||||
private const uint InternalVersion = 5518; //! Not to be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 6698; //! Not to be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private static readonly uint[] _migrateInternalVersions = {
|
||||
private static readonly uint[] _migrateInternalVersions =
|
||||
[
|
||||
1866,
|
||||
};
|
||||
5518,
|
||||
];
|
||||
|
||||
private const int SaveInterval = 30; // Seconds.
|
||||
|
||||
|
|
@ -72,20 +74,30 @@ namespace ARMeilleure.Translation.PTC
|
|||
Enabled = false;
|
||||
}
|
||||
|
||||
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
public void AddEntry(ulong address, ExecutionMode mode, bool highCq, bool blacklist = false)
|
||||
{
|
||||
if (IsAddressInStaticCodeRange(address))
|
||||
{
|
||||
Debug.Assert(!highCq);
|
||||
|
||||
lock (_lock)
|
||||
if (blacklist)
|
||||
{
|
||||
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false));
|
||||
lock (_lock)
|
||||
{
|
||||
ProfiledFuncs[address] = new FuncProfile(mode, highCq: false, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq, bool? blacklist = null)
|
||||
{
|
||||
if (IsAddressInStaticCodeRange(address))
|
||||
{
|
||||
|
|
@ -95,7 +107,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
Debug.Assert(ProfiledFuncs.ContainsKey(address));
|
||||
|
||||
ProfiledFuncs[address] = new FuncProfile(mode, highCq: true);
|
||||
ProfiledFuncs[address] = new FuncProfile(mode, highCq: true, blacklist ?? ProfiledFuncs[address].Blacklist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +123,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
foreach (var profiledFunc in ProfiledFuncs)
|
||||
{
|
||||
if (!funcs.ContainsKey(profiledFunc.Key))
|
||||
if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
|
||||
{
|
||||
profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value));
|
||||
}
|
||||
|
|
@ -126,6 +138,24 @@ namespace ARMeilleure.Translation.PTC
|
|||
ProfiledFuncs.TrimExcess();
|
||||
}
|
||||
|
||||
public List<ulong> GetBlacklistedFunctions()
|
||||
{
|
||||
List<ulong> funcs = [];
|
||||
|
||||
foreach (var profiledFunc in ProfiledFuncs)
|
||||
{
|
||||
if (profiledFunc.Value.Blacklist)
|
||||
{
|
||||
if (!funcs.Contains(profiledFunc.Key))
|
||||
{
|
||||
funcs.Add(profiledFunc.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
public void PreLoad()
|
||||
{
|
||||
_lastHash = default;
|
||||
|
|
@ -216,13 +246,18 @@ namespace ARMeilleure.Translation.PTC
|
|||
return false;
|
||||
}
|
||||
|
||||
Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null;
|
||||
|
||||
switch (outerHeader.InfoFileVersion)
|
||||
{
|
||||
case InternalVersion:
|
||||
ProfiledFuncs = Deserialize(stream);
|
||||
break;
|
||||
case 1866:
|
||||
ProfiledFuncs = Deserialize(stream, (address, profile) => (address + 0x500000UL, profile));
|
||||
migrateEntryFunc = (address, profile) => (address + 0x500000UL, profile);
|
||||
goto case 5518;
|
||||
case 5518:
|
||||
ProfiledFuncs = DeserializeAddBlacklist(stream, migrateEntryFunc);
|
||||
break;
|
||||
default:
|
||||
Logger.Error?.Print(LogClass.Ptc, $"No migration path for {nameof(outerHeader.InfoFileVersion)} '{outerHeader.InfoFileVersion}'. Discarding cache.");
|
||||
|
|
@ -252,6 +287,16 @@ namespace ARMeilleure.Translation.PTC
|
|||
return DeserializeDictionary<ulong, FuncProfile>(stream, DeserializeStructure<FuncProfile>);
|
||||
}
|
||||
|
||||
private static Dictionary<ulong, FuncProfile> DeserializeAddBlacklist(Stream stream, Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null)
|
||||
{
|
||||
if (migrateEntryFunc != null)
|
||||
{
|
||||
return DeserializeAndUpdateDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); }, migrateEntryFunc);
|
||||
}
|
||||
|
||||
return DeserializeDictionary<ulong, FuncProfile>(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); });
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
||||
{
|
||||
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
|
||||
|
|
@ -383,13 +428,35 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 6*/)]
|
||||
public struct FuncProfile
|
||||
{
|
||||
public ExecutionMode Mode;
|
||||
public bool HighCq;
|
||||
public bool Blacklist;
|
||||
|
||||
public FuncProfile(ExecutionMode mode, bool highCq)
|
||||
public FuncProfile(ExecutionMode mode, bool highCq, bool blacklist)
|
||||
{
|
||||
Mode = mode;
|
||||
HighCq = highCq;
|
||||
Blacklist = blacklist;
|
||||
}
|
||||
|
||||
public FuncProfile(FuncProfilePreBlacklist fp)
|
||||
{
|
||||
Mode = fp.Mode;
|
||||
HighCq = fp.HighCq;
|
||||
Blacklist = false;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
||||
public struct FuncProfilePreBlacklist
|
||||
{
|
||||
public ExecutionMode Mode;
|
||||
public bool HighCq;
|
||||
|
||||
public FuncProfilePreBlacklist(ExecutionMode mode, bool highCq)
|
||||
{
|
||||
Mode = mode;
|
||||
HighCq = highCq;
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
|
||||
{
|
||||
var context = new ArmEmitterContext(
|
||||
Memory,
|
||||
|
|
@ -246,7 +246,12 @@ namespace ARMeilleure.Translation
|
|||
context.Branch(context.GetLabel(address));
|
||||
}
|
||||
|
||||
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter);
|
||||
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter, pptcTranslation);
|
||||
|
||||
if (cfg == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ulong funcSize = funcRange.End - funcRange.Start;
|
||||
|
||||
|
|
@ -321,7 +326,8 @@ namespace ARMeilleure.Translation
|
|||
ArmEmitterContext context,
|
||||
Block[] blocks,
|
||||
out Range range,
|
||||
out Counter<uint> counter)
|
||||
out Counter<uint> counter,
|
||||
bool pptcTranslation)
|
||||
{
|
||||
counter = null;
|
||||
|
||||
|
|
@ -406,6 +412,14 @@ namespace ARMeilleure.Translation
|
|||
if (opCode.Instruction.Emitter != null)
|
||||
{
|
||||
opCode.Instruction.Emitter(context);
|
||||
// if we're pre-compiling PPTC functions, and we hit an Undefined instruction as the first
|
||||
// instruction in the block, mark the function as blacklisted
|
||||
// this way, we don't pre-compile Exlaunch hooks, which allows ExeFS mods to run with PPTC
|
||||
if (pptcTranslation && opCode.Instruction.Name == InstName.Und && blkIndex == 0)
|
||||
{
|
||||
range = new Range(rangeStart, rangeEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -477,7 +491,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
||||
{
|
||||
ulong[] overlapAddresses = Array.Empty<ulong>();
|
||||
ulong[] overlapAddresses = [];
|
||||
|
||||
int overlapsCount = Functions.GetOverlaps(address, size, ref overlapAddresses);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace ARMeilleure.Translation
|
|||
Sync = new object();
|
||||
|
||||
_requests = new Stack<RejitRequest>();
|
||||
_requestAddresses = new HashSet<ulong>();
|
||||
_requestAddresses = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
OperandType[] argTypes = [OperandType.I64];
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<FpFlagsPInvokeTest>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -10,15 +11,15 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-arm64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.dylib</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.so</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
|
|
|
|||
|
|
@ -31,19 +31,19 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||
private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
|
||||
private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
|
||||
|
||||
private static readonly long[] _defaultSurroundToStereoCoefficients = new long[4]
|
||||
{
|
||||
private static readonly long[] _defaultSurroundToStereoCoefficients =
|
||||
[
|
||||
RawQ15One,
|
||||
Minus3dBInQ15,
|
||||
Minus12dBInQ15,
|
||||
Minus3dBInQ15,
|
||||
};
|
||||
Minus3dBInQ15
|
||||
];
|
||||
|
||||
private static readonly long[] _defaultStereoToMonoCoefficients = new long[2]
|
||||
{
|
||||
private static readonly long[] _defaultStereoToMonoCoefficients =
|
||||
[
|
||||
Minus6dBInQ15,
|
||||
Minus6dBInQ15,
|
||||
};
|
||||
Minus6dBInQ15
|
||||
];
|
||||
|
||||
private const int SurroundChannelCount = 6;
|
||||
private const int StereoChannelCount = 2;
|
||||
|
|
|
|||
|
|
@ -164,12 +164,12 @@ namespace Ryujinx.Audio
|
|||
/// <summary>
|
||||
/// The default coefficients used for standard 5.1 surround to stereo downmixing.
|
||||
/// </summary>
|
||||
public static readonly float[] DefaultSurroundToStereoCoefficients = new float[4]
|
||||
{
|
||||
public static readonly float[] DefaultSurroundToStereoCoefficients =
|
||||
[
|
||||
1.0f,
|
||||
0.707f,
|
||||
0.251f,
|
||||
0.707f,
|
||||
};
|
||||
0.707f
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ namespace Ryujinx.Audio.Input
|
|||
// TODO: Detect if the driver supports audio input
|
||||
}
|
||||
|
||||
return new[] { Constants.DefaultDeviceInputName };
|
||||
return [Constants.DefaultDeviceInputName];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ namespace Ryujinx.Audio.Output
|
|||
/// <returns>The list of all audio outputs name</returns>
|
||||
public string[] ListAudioOuts()
|
||||
{
|
||||
return new[] { Constants.DefaultDeviceOutputName };
|
||||
return [Constants.DefaultDeviceOutputName];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||
/// <summary>
|
||||
/// All the defined virtual devices.
|
||||
/// </summary>
|
||||
public static readonly VirtualDevice[] Devices = new VirtualDevice[5]
|
||||
{
|
||||
public static readonly VirtualDevice[] Devices =
|
||||
[
|
||||
new("AudioStereoJackOutput", 2, true),
|
||||
new("AudioBuiltInSpeakerOutput", 2, false),
|
||||
new("AudioTvOutput", 6, false),
|
||||
new("AudioUsbDeviceOutput", 2, true),
|
||||
new("AudioExternalOutput", 6, true),
|
||||
};
|
||||
new("AudioExternalOutput", 6, true)
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// The name of the <see cref="VirtualDevice"/>.
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||
SampleRate = sampleRate;
|
||||
BufferCount = mixBufferCount + voiceChannelCountMax;
|
||||
Buffers = mixBuffer;
|
||||
Commands = new List<ICommand>();
|
||||
Commands = [];
|
||||
MemoryManager = memoryManager;
|
||||
|
||||
_buffersEntryCount = Buffers.Length;
|
||||
|
|
|
|||
|
|
@ -9,21 +9,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||
{
|
||||
public class Reverb3dCommand : ICommand
|
||||
{
|
||||
private static readonly int[] _outputEarlyIndicesTableMono = new int[20] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableMono = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableMono = new int[1] { 0 };
|
||||
private static readonly int[] _outputEarlyIndicesTableMono = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableMono = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
||||
];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableMono = [0];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableStereo = new int[20] { 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableStereo = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableStereo = new int[2] { 0, 1 };
|
||||
private static readonly int[] _outputEarlyIndicesTableStereo = [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1
|
||||
];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableStereo = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
||||
];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableStereo = [0, 1];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableQuadraphonic = new int[20] { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableQuadraphonic = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 };
|
||||
private static readonly int[] _outputEarlyIndicesTableQuadraphonic = [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3
|
||||
];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableQuadraphonic = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
||||
];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableQuadraphonic = [0, 1, 2, 3];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableSurround = new int[40] { 4, 5, 0, 5, 0, 5, 1, 5, 1, 5, 1, 5, 1, 5, 2, 5, 2, 5, 2, 5, 1, 5, 1, 5, 1, 5, 0, 5, 0, 5, 0, 5, 0, 5, 3, 5, 3, 5, 3, 5 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableSurround = new int[40] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableSurround = new int[6] { 0, 1, 2, 3, -1, 3 };
|
||||
private static readonly int[] _outputEarlyIndicesTableSurround = [4, 5, 0, 5, 0, 5, 1, 5, 1, 5, 1, 5, 1, 5, 2, 5, 2, 5, 2, 5, 1, 5, 1, 5, 1, 5, 0, 5, 0, 5, 0, 5, 0, 5, 3, 5, 3, 5, 3, 5
|
||||
];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableSurround = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19
|
||||
];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableSurround = [0, 1, 2, 3, -1, 3];
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -9,25 +9,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||
{
|
||||
public class ReverbCommand : ICommand
|
||||
{
|
||||
private static readonly int[] _outputEarlyIndicesTableMono = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableMono = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
private static readonly int[] _outputIndicesTableMono = new int[4] { 0, 0, 0, 0 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableMono = new int[4] { 0, 1, 2, 3 };
|
||||
private static readonly int[] _outputEarlyIndicesTableMono = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableMono = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
private static readonly int[] _outputIndicesTableMono = [0, 0, 0, 0];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableMono = [0, 1, 2, 3];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableStereo = new int[10] { 0, 0, 1, 1, 0, 1, 0, 0, 1, 1 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableStereo = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
private static readonly int[] _outputIndicesTableStereo = new int[4] { 0, 0, 1, 1 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableStereo = new int[4] { 2, 0, 3, 1 };
|
||||
private static readonly int[] _outputEarlyIndicesTableStereo = [0, 0, 1, 1, 0, 1, 0, 0, 1, 1];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableStereo = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
private static readonly int[] _outputIndicesTableStereo = [0, 0, 1, 1];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableStereo = [2, 0, 3, 1];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableQuadraphonic = new int[10] { 0, 0, 1, 1, 0, 1, 2, 2, 3, 3 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableQuadraphonic = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
private static readonly int[] _outputIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 };
|
||||
private static readonly int[] _outputEarlyIndicesTableQuadraphonic = [0, 0, 1, 1, 0, 1, 2, 2, 3, 3];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableQuadraphonic = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
private static readonly int[] _outputIndicesTableQuadraphonic = [0, 1, 2, 3];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableQuadraphonic = [0, 1, 2, 3];
|
||||
|
||||
private static readonly int[] _outputEarlyIndicesTableSurround = new int[20] { 0, 5, 0, 5, 1, 5, 1, 5, 4, 5, 4, 5, 2, 5, 2, 5, 3, 5, 3, 5 };
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableSurround = new int[20] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 };
|
||||
private static readonly int[] _outputIndicesTableSurround = new int[Constants.ChannelCountMax] { 0, 1, 2, 3, 4, 5 };
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableSurround = new int[Constants.ChannelCountMax] { 0, 1, 2, 3, -1, 3 };
|
||||
private static readonly int[] _outputEarlyIndicesTableSurround = [0, 5, 0, 5, 1, 5, 1, 5, 4, 5, 4, 5, 2, 5, 2, 5, 3, 5, 3, 5
|
||||
];
|
||||
private static readonly int[] _targetEarlyDelayLineIndicesTableSurround = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9
|
||||
];
|
||||
private static readonly int[] _outputIndicesTableSurround = [0, 1, 2, 3, 4, 5];
|
||||
private static readonly int[] _targetOutputFeedbackIndicesTableSurround = [0, 1, 2, 3, -1, 3];
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
/// Map decibel to linear.
|
||||
/// </summary>
|
||||
/// <param name="db">The decibel value to convert</param>
|
||||
/// <returns>Converted linear value/returns>
|
||||
/// <returns>Converted linear value</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float DecibelToLinear(float db)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
public static class ResamplerHelper
|
||||
{
|
||||
#region "Default Quality Lookup Tables"
|
||||
private static readonly short[] _normalCurveLut0 = {
|
||||
private static readonly short[] _normalCurveLut0 =
|
||||
[
|
||||
6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239, 19412, 7093, 22,
|
||||
6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377, 7472, 41, 5773, 19361, 7600, 48,
|
||||
5659, 19342, 7728, 55, 5546, 19321, 7857, 62, 5434, 19298, 7987, 69, 5323, 19273, 8118, 77,
|
||||
|
|
@ -42,10 +43,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
109, 8646, 19148, 4890, 101, 8513, 19183, 4997, 92, 8381, 19215, 5104, 84, 8249, 19245, 5213,
|
||||
77, 8118, 19273, 5323, 69, 7987, 19298, 5434, 62, 7857, 19321, 5546, 55, 7728, 19342, 5659,
|
||||
48, 7600, 19361, 5773, 41, 7472, 19377, 5888, 34, 7345, 19391, 6004, 28, 7219, 19403, 6121,
|
||||
22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 6479, 3, 6722, 19426, 6600,
|
||||
};
|
||||
22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 6479, 3, 6722, 19426, 6600
|
||||
];
|
||||
|
||||
private static readonly short[] _normalCurveLut1 = {
|
||||
private static readonly short[] _normalCurveLut1 =
|
||||
[
|
||||
-68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450, 32586, 512, -36,
|
||||
-568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454, 1000, -69, -891, 32393, 1174, -80,
|
||||
-990, 32323, 1352, -92, -1084, 32244, 1536, -103, -1173, 32157, 1724, -115, -1258, 32061, 1919, -128,
|
||||
|
|
@ -77,10 +79,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
-180, 2747, 31593, -1554, -167, 2532, 31723, -1486, -153, 2322, 31844, -1414, -140, 2118, 31956, -1338,
|
||||
-128, 1919, 32061, -1258, -115, 1724, 32157, -1173, -103, 1536, 32244, -1084, -92, 1352, 32323, -990,
|
||||
-80, 1174, 32393, -891, -69, 1000, 32454, -788, -58, 832, 32507, -680, -47, 669, 32551, -568,
|
||||
-36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, -200, -5, 69, 32639, -68,
|
||||
};
|
||||
-36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, -200, -5, 69, 32639, -68
|
||||
];
|
||||
|
||||
private static readonly short[] _normalCurveLut2 = {
|
||||
private static readonly short[] _normalCurveLut2 =
|
||||
[
|
||||
3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811, 26253, 3751, -42,
|
||||
2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169, 4199, -54, 2338, 26130, 4354, -58,
|
||||
2227, 26085, 4512, -63, 2120, 26035, 4673, -67, 2015, 25980, 4837, -72, 1912, 25919, 5004, -76,
|
||||
|
|
@ -112,12 +115,13 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
-98, 5701, 25621, 1531, -92, 5522, 25704, 1622, -87, 5347, 25780, 1716, -81, 5174, 25852, 1813,
|
||||
-76, 5004, 25919, 1912, -72, 4837, 25980, 2015, -67, 4673, 26035, 2120, -63, 4512, 26085, 2227,
|
||||
-58, 4354, 26130, 2338, -54, 4199, 26169, 2451, -50, 4046, 26202, 2568, -46, 3897, 26230, 2688,
|
||||
-42, 3751, 26253, 2811, -38, 3608, 26270, 2936, -34, 3467, 26281, 3064, -32, 3329, 26287, 3195,
|
||||
};
|
||||
-42, 3751, 26253, 2811, -38, 3608, 26270, 2936, -34, 3467, 26281, 3064, -32, 3329, 26287, 3195
|
||||
];
|
||||
#endregion
|
||||
|
||||
#region "High Quality Lookup Tables"
|
||||
private static readonly short[] _highCurveLut0 = {
|
||||
private static readonly short[] _highCurveLut0 =
|
||||
[
|
||||
-582, -23, 8740, 16386, 8833, 8, -590, 0, -573, -54, 8647, 16385, 8925, 40, -598, -1,
|
||||
-565, -84, 8555, 16383, 9018, 72, -606, -1, -557, -113, 8462, 16379, 9110, 105, -614, -2,
|
||||
-549, -142, 8370, 16375, 9203, 139, -622, -2, -541, -170, 8277, 16369, 9295, 173, -630, -3,
|
||||
|
|
@ -181,10 +185,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
-5, -646, 244, 9480, 16354, 8093, -225, -525, -4, -638, 208, 9387, 16362, 8185, -198, -533,
|
||||
-3, -630, 173, 9295, 16369, 8277, -170, -541, -2, -622, 139, 9203, 16375, 8370, -142, -549,
|
||||
-2, -614, 105, 9110, 16379, 8462, -113, -557, -1, -606, 72, 9018, 16383, 8555, -84, -565,
|
||||
-1, -598, 40, 8925, 16385, 8647, -54, -573, 0, -590, 8, 8833, 16386, 8740, -23, -582,
|
||||
};
|
||||
-1, -598, 40, 8925, 16385, 8647, -54, -573, 0, -590, 8, 8833, 16386, 8740, -23, -582
|
||||
];
|
||||
|
||||
private static readonly short[] _highCurveLut1 = {
|
||||
private static readonly short[] _highCurveLut1 =
|
||||
[
|
||||
-12, 47, -134, 32767, 81, -16, 2, 0, -26, 108, -345, 32760, 301, -79, 17, -1,
|
||||
-40, 168, -552, 32745, 526, -144, 32, -2, -53, 226, -753, 32723, 755, -210, 47, -3,
|
||||
-66, 284, -950, 32694, 989, -277, 63, -5, -78, 340, -1143, 32658, 1226, -346, 79, -6,
|
||||
|
|
@ -248,10 +253,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
-9, 113, -486, 1715, 32564, -1514, 447, -101, -8, 96, -415, 1469, 32615, -1331, 394, -90,
|
||||
-6, 79, -346, 1226, 32658, -1143, 340, -78, -5, 63, -277, 989, 32694, -950, 284, -66,
|
||||
-3, 47, -210, 755, 32723, -753, 226, -53, -2, 32, -144, 526, 32745, -552, 168, -40,
|
||||
-1, 17, -79, 301, 32760, -345, 108, -26, 0, 2, -16, 81, 32767, -134, 47, -12,
|
||||
};
|
||||
-1, 17, -79, 301, 32760, -345, 108, -26, 0, 2, -16, 81, 32767, -134, 47, -12
|
||||
];
|
||||
|
||||
private static readonly short[] _highCurveLut2 = {
|
||||
private static readonly short[] _highCurveLut2 =
|
||||
[
|
||||
418, -2538, 6118, 24615, 6298, -2563, 417, 0, 420, -2512, 5939, 24611, 6479, -2588, 415, 1,
|
||||
421, -2485, 5761, 24605, 6662, -2612, 412, 2, 422, -2458, 5585, 24595, 6846, -2635, 409, 3,
|
||||
423, -2430, 5410, 24582, 7030, -2658, 406, 4, 423, -2402, 5236, 24565, 7216, -2680, 403, 5,
|
||||
|
|
@ -315,8 +321,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||
7, 395, -2721, 7591, 24523, 4893, -2343, 423, 6, 399, -2701, 7403, 24546, 5064, -2373, 423,
|
||||
5, 403, -2680, 7216, 24565, 5236, -2402, 423, 4, 406, -2658, 7030, 24582, 5410, -2430, 423,
|
||||
3, 409, -2635, 6846, 24595, 5585, -2458, 422, 2, 412, -2612, 6662, 24605, 5761, -2485, 421,
|
||||
1, 415, -2588, 6479, 24611, 5939, -2512, 420, 0, 417, -2563, 6298, 24615, 6118, -2538, 418,
|
||||
};
|
||||
1, 415, -2588, 6479, 24611, 5939, -2512, 420, 0, 417, -2563, 6298, 24615, 6118, -2538, 418
|
||||
];
|
||||
#endregion
|
||||
|
||||
private static readonly float[] _normalCurveLut0F;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
{
|
||||
public struct Reverb3dState
|
||||
{
|
||||
private readonly float[] _fdnDelayMinTimes = new float[4] { 5.0f, 6.0f, 13.0f, 14.0f };
|
||||
private readonly float[] _fdnDelayMaxTimes = new float[4] { 45.704f, 82.782f, 149.94f, 271.58f };
|
||||
private readonly float[] _decayDelayMaxTimes1 = new float[4] { 17.0f, 13.0f, 9.0f, 7.0f };
|
||||
private readonly float[] _decayDelayMaxTimes2 = new float[4] { 19.0f, 11.0f, 10.0f, 6.0f };
|
||||
private readonly float[] _earlyDelayTimes = new float[20] { 0.017136f, 0.059154f, 0.16173f, 0.39019f, 0.42526f, 0.45541f, 0.68974f, 0.74591f, 0.83384f, 0.8595f, 0.0f, 0.075024f, 0.16879f, 0.2999f, 0.33744f, 0.3719f, 0.59901f, 0.71674f, 0.81786f, 0.85166f };
|
||||
public readonly float[] EarlyGain = new float[20] { 0.67096f, 0.61027f, 1.0f, 0.35680f, 0.68361f, 0.65978f, 0.51939f, 0.24712f, 0.45945f, 0.45021f, 0.64196f, 0.54879f, 0.92925f, 0.38270f, 0.72867f, 0.69794f, 0.5464f, 0.24563f, 0.45214f, 0.44042f };
|
||||
private readonly float[] _fdnDelayMinTimes = [5.0f, 6.0f, 13.0f, 14.0f];
|
||||
private readonly float[] _fdnDelayMaxTimes = [45.704f, 82.782f, 149.94f, 271.58f];
|
||||
private readonly float[] _decayDelayMaxTimes1 = [17.0f, 13.0f, 9.0f, 7.0f];
|
||||
private readonly float[] _decayDelayMaxTimes2 = [19.0f, 11.0f, 10.0f, 6.0f];
|
||||
private readonly float[] _earlyDelayTimes = [0.017136f, 0.059154f, 0.16173f, 0.39019f, 0.42526f, 0.45541f, 0.68974f, 0.74591f, 0.83384f, 0.8595f, 0.0f, 0.075024f, 0.16879f, 0.2999f, 0.33744f, 0.3719f, 0.59901f, 0.71674f, 0.81786f, 0.85166f
|
||||
];
|
||||
public readonly float[] EarlyGain = [0.67096f, 0.61027f, 1.0f, 0.35680f, 0.68361f, 0.65978f, 0.51939f, 0.24712f, 0.45945f, 0.45021f, 0.64196f, 0.54879f, 0.92925f, 0.38270f, 0.72867f, 0.69794f, 0.5464f, 0.24563f, 0.45214f, 0.44042f
|
||||
];
|
||||
|
||||
public IDelayLine[] FdnDelayLines { get; }
|
||||
public DecayDelay[] DecayDelays1 { get; }
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
{
|
||||
public struct ReverbState
|
||||
{
|
||||
private static readonly float[] _fdnDelayTimes = new float[20]
|
||||
{
|
||||
private static readonly float[] _fdnDelayTimes =
|
||||
[
|
||||
// Room
|
||||
53.953247f, 79.192566f, 116.238770f, 130.615295f,
|
||||
// Hall
|
||||
|
|
@ -18,11 +18,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
// Cathedral
|
||||
47.03f, 71f, 103f, 170f,
|
||||
// Max delay (Hall is the one with the highest values so identical to Hall)
|
||||
53.953247f, 79.192566f, 116.238770f, 170.615295f,
|
||||
};
|
||||
53.953247f, 79.192566f, 116.238770f, 170.615295f
|
||||
];
|
||||
|
||||
private static readonly float[] _decayDelayTimes = new float[20]
|
||||
{
|
||||
private static readonly float[] _decayDelayTimes =
|
||||
[
|
||||
// Room
|
||||
7f, 9f, 13f, 17f,
|
||||
// Hall
|
||||
|
|
@ -32,11 +32,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
// Cathedral
|
||||
7f, 7f, 13f, 9f,
|
||||
// Max delay (Hall is the one with the highest values so identical to Hall)
|
||||
7f, 9f, 13f, 17f,
|
||||
};
|
||||
7f, 9f, 13f, 17f
|
||||
];
|
||||
|
||||
private static readonly float[] _earlyDelayTimes = new float[50]
|
||||
{
|
||||
private static readonly float[] _earlyDelayTimes =
|
||||
[
|
||||
// Room
|
||||
0.0f, 3.5f, 2.8f, 3.9f, 2.7f, 13.4f, 7.9f, 8.4f, 9.9f, 12.0f,
|
||||
// Chamber
|
||||
|
|
@ -46,11 +46,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
// Cathedral
|
||||
33.1f, 43.3f, 22.8f, 37.9f, 14.9f, 35.3f, 17.9f, 34.2f, 0.0f, 43.3f,
|
||||
// Disabled
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
};
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
|
||||
];
|
||||
|
||||
private static readonly float[] _earlyGainBase = new float[50]
|
||||
{
|
||||
private static readonly float[] _earlyGainBase =
|
||||
[
|
||||
// Room
|
||||
0.70f, 0.68f, 0.70f, 0.68f, 0.70f, 0.68f, 0.70f, 0.68f, 0.68f, 0.68f,
|
||||
// Chamber
|
||||
|
|
@ -60,11 +60,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
// Cathedral
|
||||
0.93f, 0.92f, 0.87f, 0.86f, 0.94f, 0.81f, 0.80f, 0.77f, 0.76f, 0.65f,
|
||||
// Disabled
|
||||
0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f,
|
||||
};
|
||||
0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f
|
||||
];
|
||||
|
||||
private static readonly float[] _preDelayTimes = new float[5]
|
||||
{
|
||||
private static readonly float[] _preDelayTimes =
|
||||
[
|
||||
// Room
|
||||
12.5f,
|
||||
// Chamber
|
||||
|
|
@ -74,8 +74,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||
// Cathedral
|
||||
50.0f,
|
||||
// Disabled
|
||||
0.0f,
|
||||
};
|
||||
0.0f
|
||||
];
|
||||
|
||||
public DelayLine[] FdnDelayLines { get; }
|
||||
public DecayDelay[] DecayDelays { get; }
|
||||
|
|
|
|||
|
|
@ -496,12 +496,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
|
||||
return (10090.9f, 3490.9f);
|
||||
case SampleRateConversionQuality.High:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (9446.36f, 2308.91f);
|
||||
}
|
||||
|
||||
return (12520.85f, 3480.61f);
|
||||
case SampleRateConversionQuality.Low:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// <returns>A list of all RangeNodes sorted by Key Order</returns>
|
||||
public List<RangeNode<TKey, TValue>> AsList()
|
||||
{
|
||||
List<RangeNode<TKey, TValue>> list = new();
|
||||
List<RangeNode<TKey, TValue>> list = [];
|
||||
|
||||
AddToList(Root, list);
|
||||
|
||||
|
|
@ -492,7 +492,7 @@ namespace Ryujinx.Common.Collections
|
|||
Start = start;
|
||||
End = end;
|
||||
Max = end;
|
||||
Values = new List<RangeNode<TKey, TValue>> { new RangeNode<TKey, TValue>(start, end, value) };
|
||||
Values = [new RangeNode<TKey, TValue>(start, end, value)];
|
||||
Parent = parent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// <param name="list">List to add the tree pairs into</param>
|
||||
public List<KeyValuePair<TKey, TValue>> AsLevelOrderList()
|
||||
{
|
||||
List<KeyValuePair<TKey, TValue>> list = new();
|
||||
List<KeyValuePair<TKey, TValue>> list = [];
|
||||
|
||||
Queue<Node<TKey, TValue>> nodes = new();
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
|
||||
public List<KeyValuePair<TKey, TValue>> AsList()
|
||||
{
|
||||
List<KeyValuePair<TKey, TValue>> list = new();
|
||||
List<KeyValuePair<TKey, TValue>> list = [];
|
||||
|
||||
AddToList(Root, list);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Configuration
|
|||
|
||||
public ModMetadata()
|
||||
{
|
||||
Mods = new List<Mod>();
|
||||
Mods = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,33 @@
|
|||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver
|
||||
{
|
||||
public static class DriverUtilities
|
||||
{
|
||||
private static void AddMesaFlags(string envVar, string newFlags)
|
||||
{
|
||||
string existingFlags = Environment.GetEnvironmentVariable(envVar);
|
||||
|
||||
string flags = existingFlags == null ? newFlags : $"{existingFlags},{newFlags}";
|
||||
|
||||
OsUtils.SetEnvironmentVariableNoCaching(envVar, flags);
|
||||
}
|
||||
|
||||
public static void InitDriverConfig(bool oglThreading)
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
AddMesaFlags("RADV_DEBUG", "nodcc");
|
||||
}
|
||||
|
||||
ToggleOGLThreading(oglThreading);
|
||||
}
|
||||
|
||||
public static void ToggleOGLThreading(bool enabled)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
|
||||
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||
OsUtils.SetEnvironmentVariableNoCaching("mesa_glthread", enabled.ToString().ToLower());
|
||||
OsUtils.SetEnvironmentVariableNoCaching("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ namespace Ryujinx.Common.Logging
|
|||
_enabledClasses[index] = true;
|
||||
}
|
||||
|
||||
_logTargets = new List<ILogTarget>();
|
||||
_logTargets = [];
|
||||
|
||||
_time = Stopwatch.StartNew();
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ namespace Ryujinx.Common.Logging.Targets
|
|||
return null;
|
||||
}
|
||||
|
||||
// Clean up old logs, should only keep 3
|
||||
// Clean up old logs, should only keep 4
|
||||
FileInfo[] files = logDir.GetFiles("*.log").OrderBy((info => info.CreationTime)).ToArray();
|
||||
for (int i = 0; i < files.Length - 2; i++)
|
||||
for (int i = 0; i < files.Length - 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
7
src/Ryujinx.Common/PlatformInfo.cs
Normal file
7
src/Ryujinx.Common/PlatformInfo.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace Ryujinx.Common
|
||||
{
|
||||
public static class PlatformInfo
|
||||
{
|
||||
public static bool IsBionic { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -125,8 +125,8 @@ namespace Ryujinx.Common.PreciseSleep
|
|||
}
|
||||
|
||||
private readonly Lock _lock = new();
|
||||
private readonly List<NanosleepThread> _threads = new();
|
||||
private readonly List<NanosleepThread> _active = new();
|
||||
private readonly List<NanosleepThread> _threads = [];
|
||||
private readonly List<NanosleepThread> _active = [];
|
||||
private readonly Stack<NanosleepThread> _free = new();
|
||||
private readonly AutoResetEvent _signalTarget;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace Ryujinx.Common.SystemInterop
|
|||
private long _lastId;
|
||||
|
||||
private readonly Lock _lock = new();
|
||||
private readonly List<WaitingObject> _waitingObjects = new();
|
||||
private readonly List<WaitingObject> _waitingObjects = [];
|
||||
|
||||
private WindowsGranularTimer()
|
||||
{
|
||||
|
|
|
|||
24
src/Ryujinx.Common/Utilities/OsUtils.cs
Normal file
24
src/Ryujinx.Common/Utilities/OsUtils.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.Utilities
|
||||
{
|
||||
public partial class OsUtils
|
||||
{
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int setenv([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int overwrite);
|
||||
|
||||
public static void SetEnvironmentVariableNoCaching(string key, string value)
|
||||
{
|
||||
// Set the value in the cached environment variables, too.
|
||||
Environment.SetEnvironmentVariable(key, value);
|
||||
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
int res = setenv(key, value, 1);
|
||||
Debug.Assert(res != -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
if (timedSw.Elapsed.TotalSeconds > 0)
|
||||
{
|
||||
Log?.Write(LogType.Info, $"Checked at {readSizeB / (double)XCIFileTrimmer.BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec");
|
||||
Log?.Write(LogType.Info, $"Checked at {readSizeB / (double)BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec");
|
||||
}
|
||||
|
||||
if (freeSpaceValid)
|
||||
|
|
@ -219,7 +219,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
private bool CheckPadding(long readSizeB, CancellationToken? cancelToken = null)
|
||||
{
|
||||
long maxReads = readSizeB / XCIFileTrimmer.BufferSize;
|
||||
long maxReads = readSizeB / BufferSize;
|
||||
long read = 0;
|
||||
var buffer = new byte[BufferSize];
|
||||
|
||||
|
|
@ -230,12 +230,12 @@ namespace Ryujinx.Common.Utilities
|
|||
return false;
|
||||
}
|
||||
|
||||
int bytes = _fileStream.Read(buffer, 0, XCIFileTrimmer.BufferSize);
|
||||
int bytes = _fileStream.Read(buffer, 0, BufferSize);
|
||||
if (bytes == 0)
|
||||
break;
|
||||
|
||||
Log?.Progress(read, maxReads, "Verifying file can be trimmed", false);
|
||||
if (buffer.Take(bytes).AsParallel().Any(b => b != XCIFileTrimmer.PaddingByte))
|
||||
if (buffer.Take(bytes).AsParallel().Any(b => b != PaddingByte))
|
||||
{
|
||||
Log?.Write(LogType.Warn, "Free space is NOT valid");
|
||||
return false;
|
||||
|
|
@ -380,7 +380,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
if (timedSw.Elapsed.TotalSeconds > 0)
|
||||
{
|
||||
Log?.Write(LogType.Info, $"Wrote at {bytesToWriteB / (double)XCIFileTrimmer.BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec");
|
||||
Log?.Write(LogType.Info, $"Wrote at {bytesToWriteB / (double)BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec");
|
||||
}
|
||||
|
||||
if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
|
||||
|
|
@ -408,13 +408,13 @@ namespace Ryujinx.Common.Utilities
|
|||
private void WritePadding(FileStream outfileStream, long bytesToWriteB, CancellationToken? cancelToken = null)
|
||||
{
|
||||
long bytesLeftToWriteB = bytesToWriteB;
|
||||
long writes = bytesLeftToWriteB / XCIFileTrimmer.BufferSize;
|
||||
long writes = bytesLeftToWriteB / BufferSize;
|
||||
int write = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var buffer = new byte[BufferSize];
|
||||
Array.Fill<byte>(buffer, XCIFileTrimmer.PaddingByte);
|
||||
Array.Fill<byte>(buffer, PaddingByte);
|
||||
|
||||
while (bytesLeftToWriteB > 0)
|
||||
{
|
||||
|
|
@ -423,7 +423,7 @@ namespace Ryujinx.Common.Utilities
|
|||
return;
|
||||
}
|
||||
|
||||
long bytesToWrite = Math.Min(XCIFileTrimmer.BufferSize, bytesLeftToWriteB);
|
||||
long bytesToWrite = Math.Min(BufferSize, bytesLeftToWriteB);
|
||||
|
||||
#if !XCI_TRIMMER_READ_ONLY_MODE
|
||||
outfileStream.Write(buffer, 0, (int)bytesToWrite);
|
||||
|
|
@ -504,12 +504,12 @@ namespace Ryujinx.Common.Utilities
|
|||
}
|
||||
|
||||
// Setup offset
|
||||
_offsetB = (long)(assumeKeyArea ? XCIFileTrimmer.CartKeyAreaSize : 0);
|
||||
_offsetB = (long)(assumeKeyArea ? CartKeyAreaSize : 0);
|
||||
|
||||
// Check header
|
||||
Pos = _offsetB + XCIFileTrimmer.HeaderFilePos;
|
||||
Pos = _offsetB + HeaderFilePos;
|
||||
string head = System.Text.Encoding.ASCII.GetString(_binaryReader.ReadBytes(4));
|
||||
if (head != XCIFileTrimmer.HeaderMagicValue)
|
||||
if (head != HeaderMagicValue)
|
||||
{
|
||||
if (!assumeKeyArea)
|
||||
{
|
||||
|
|
@ -524,17 +524,17 @@ namespace Ryujinx.Common.Utilities
|
|||
}
|
||||
|
||||
// Read Cart Size
|
||||
Pos = _offsetB + XCIFileTrimmer.CartSizeFilePos;
|
||||
Pos = _offsetB + CartSizeFilePos;
|
||||
byte cartSizeId = _binaryReader.ReadByte();
|
||||
if (!_cartSizesGB.TryGetValue(cartSizeId, out long cartSizeNGB))
|
||||
{
|
||||
Log?.Write(LogType.Error, $"The source file doesn't look like an XCI file as the Cartridge Size is incorrect (0x{cartSizeId:X2})");
|
||||
return false;
|
||||
}
|
||||
_cartSizeB = cartSizeNGB * XCIFileTrimmer.CartSizeMBinFormattedGB * XCIFileTrimmer.BytesInAMegabyte;
|
||||
_cartSizeB = cartSizeNGB * CartSizeMBinFormattedGB * BytesInAMegabyte;
|
||||
|
||||
// Read data size
|
||||
Pos = _offsetB + XCIFileTrimmer.DataSizeFilePos;
|
||||
Pos = _offsetB + DataSizeFilePos;
|
||||
long records = (long)BitConverter.ToUInt32(_binaryReader.ReadBytes(4), 0);
|
||||
_dataSizeB = RecordsToByte(records);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ namespace Ryujinx.Common
|
|||
private const ulong Prime64_4 = 0x85EBCA77C2B2AE63UL;
|
||||
private const ulong Prime64_5 = 0x27D4EB2F165667C5UL;
|
||||
|
||||
private static readonly ulong[] _xxh3InitAcc = {
|
||||
private static readonly ulong[] _xxh3InitAcc =
|
||||
[
|
||||
Prime32_3,
|
||||
Prime64_1,
|
||||
Prime64_2,
|
||||
|
|
@ -39,11 +40,11 @@ namespace Ryujinx.Common
|
|||
Prime64_4,
|
||||
Prime32_2,
|
||||
Prime64_5,
|
||||
Prime32_1,
|
||||
};
|
||||
Prime32_1
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<byte> Xxh3KSecret => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> Xxh3KSecret =>
|
||||
[
|
||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
|
||||
|
|
@ -55,8 +56,8 @@ namespace Ryujinx.Common
|
|||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||
};
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e
|
||||
];
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong Mult32To64(ulong x, ulong y)
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ namespace ARMeilleure.Common
|
|||
_fillBottomLevel = new SparseMemoryBlock(bottomLevelSize, null, _sparseFill);
|
||||
_fillBottomLevelPtr = (TEntry*)_fillBottomLevel.Block.Pointer;
|
||||
|
||||
_sparseReserved = new List<TableSparseBlock>();
|
||||
_sparseReserved = [];
|
||||
_sparseLock = new ReaderWriterLockSlim();
|
||||
|
||||
_sparseBlockSize = bottomLevelSize;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
|
|
@ -230,7 +229,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return Enumerable.Empty<HostMemoryRange>();
|
||||
return [];
|
||||
}
|
||||
|
||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||
|
|
@ -256,7 +255,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return Enumerable.Empty<MemoryRange>();
|
||||
return [];
|
||||
}
|
||||
|
||||
return GetPhysicalRegionsImpl(va, size);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked
|
|||
public AddressSpacePartitioned(MemoryTracking tracking, MemoryBlock backingMemory, NativePageTable nativePageTable, bool useProtectionMirrors)
|
||||
{
|
||||
_backingMemory = backingMemory;
|
||||
_partitions = new();
|
||||
_partitions = [];
|
||||
_asAllocator = new(tracking, nativePageTable.Read, _partitions);
|
||||
_updatePtCallback = nativePageTable.Update;
|
||||
_useProtectionMirrors = useProtectionMirrors;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
|
@ -250,7 +249,7 @@ namespace Ryujinx.Cpu.Jit
|
|||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return Enumerable.Empty<HostMemoryRange>();
|
||||
return [];
|
||||
}
|
||||
|
||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||
|
|
@ -276,7 +275,7 @@ namespace Ryujinx.Cpu.Jit
|
|||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return Enumerable.Empty<MemoryRange>();
|
||||
return [];
|
||||
}
|
||||
|
||||
return GetPhysicalRegionsImpl(va, size);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using Ryujinx.Memory.Tracking;
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Cpu.Jit
|
||||
|
|
@ -469,7 +468,7 @@ namespace Ryujinx.Cpu.Jit
|
|||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return Enumerable.Empty<MemoryRange>();
|
||||
return [];
|
||||
}
|
||||
|
||||
return GetPhysicalRegionsImpl(va, size);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||
RegisterAllocator = registerAllocator;
|
||||
MemoryManagerType = mmType;
|
||||
_itConditions = new ArmCondition[4];
|
||||
_pendingBranches = new();
|
||||
_pendingBranches = [];
|
||||
IsThumb = isThumb;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||
{
|
||||
public static MultiBlock DecodeMulti(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, bool isThumb)
|
||||
{
|
||||
List<Block> blocks = new();
|
||||
List<ulong> branchTargets = new();
|
||||
List<Block> blocks = [];
|
||||
List<ulong> branchTargets = [];
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -202,7 +202,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||
{
|
||||
ulong startAddress = address;
|
||||
|
||||
List<InstInfo> insts = new();
|
||||
List<InstInfo> insts = [];
|
||||
|
||||
uint encoding;
|
||||
InstMeta meta;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue