mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-10-08 13:38:52 +02:00
Compare commits
61
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f904c82d76 | ||
|
|
48b11b71fa | ||
|
|
53bde335d9 | ||
|
|
ec0ec3a86a | ||
|
|
02d0b480e3 | ||
|
|
07de13a47b | ||
|
|
fc4c45ef1d | ||
|
|
52c6a1890e | ||
|
|
2288084b53 | ||
|
|
dd519a32b6 | ||
|
|
7be8829b0a | ||
|
|
6225e142fc | ||
|
|
9e3c03a606 | ||
|
|
8e9bcb2a8e | ||
|
|
7101f52c01 | ||
|
|
e80fc00462 | ||
|
|
33cbd29c23 | ||
|
|
cfc7c6039f | ||
|
|
ac6db0fe76 | ||
|
|
bed294bb92 | ||
|
|
ed70f7921e | ||
|
|
1a1fe53535 | ||
|
|
47e55acf21 | ||
|
|
0e5fead0f9 | ||
|
|
d1fb89f746 | ||
|
|
cc1861f9bb | ||
|
|
733bd0951b | ||
|
|
087e711e44 | ||
|
|
9c46452388 | ||
|
|
0657b00622 | ||
|
|
87cf0b0cbb | ||
|
|
954332aa2a | ||
|
|
e650d3fb04 | ||
|
|
d578c5e2a9 | ||
|
|
521a18f5a7 | ||
|
|
4b255a98db | ||
|
|
8b34270a22 | ||
|
|
9580f20caa | ||
|
|
152460929d | ||
|
|
7a5554a17f | ||
|
|
d5e4dfae56 | ||
|
|
28268ef7ef | ||
|
|
6c47892b94 | ||
|
|
b362f837c5 | ||
|
|
a82a721df6 | ||
|
|
297df259c3 | ||
|
|
3ace5deadf | ||
|
|
04aacb1385 | ||
|
|
ea91841e9b | ||
|
|
5734ad9090 | ||
|
|
1486d2db40 | ||
|
|
c54ca28843 | ||
|
|
a53e691185 | ||
|
|
bf8c902d13 | ||
|
|
f4dc400a47 | ||
|
|
a36882ab51 | ||
|
|
76a123b81d | ||
|
|
9d3fecf334 | ||
|
|
31d0bc5915 | ||
|
|
30dba1ed36 | ||
|
|
0d6c0aeeab |
+18
-19
@@ -3,25 +3,25 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.3.16" />
|
<PackageVersion Include="Avalonia" Version="12.1.1" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="12.1.2" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.16" />
|
<PackageVersion Include="Avalonia.Desktop" Version="12.1.1" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.16" />
|
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.16" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="12.1.1" />
|
||||||
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.5" />
|
<PackageVersion Include="Svg.Controls.Avalonia" Version="12.0.0.15" />
|
||||||
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.5" />
|
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="12.0.0.15" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.4.31" />
|
<PackageVersion Include="DynamicData" Version="9.4.33" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.5.1" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="3.1.0" />
|
||||||
<PackageVersion Include="Gommon" Version="2.8.1.2" />
|
<PackageVersion Include="Gommon" Version="2.8.1.2" />
|
||||||
<PackageVersion Include="Humanizer" Version="3.0.10" />
|
<PackageVersion Include="Humanizer" Version="3.0.10" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.18.0" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.21.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
|
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
|
||||||
@@ -31,25 +31,24 @@
|
|||||||
<PackageVersion Include="OpenTK.Core" Version="4.9.4" />
|
<PackageVersion Include="OpenTK.Core" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
|
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
|
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" />
|
|
||||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.2" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.4-build6" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.4-build6" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.4-build6" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.4-build6" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.MoltenVK" Version="1.4.2-ryujinx.3" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.MoltenVK" Version="1.4.2-ryujinx.6" />
|
||||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.133" />
|
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.133" />
|
||||||
<PackageVersion Include="Ryujinx.SDL3-CS" Version="2026.501.0" />
|
<PackageVersion Include="Ryujinx.SDL3-CS" Version="2026.707.0" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Shaderc" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Shaderc" Version="2.23.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="3.119.2" />
|
<PackageVersion Include="SkiaSharp" Version="3.119.4" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.2" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.4" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="10.0.8" />
|
<PackageVersion Include="System.IO.Hashing" Version="10.0.11" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.4-a40db6c" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
|
<Configurations>
|
||||||
|
<BuildType Name="Debug" />
|
||||||
|
<BuildType Name="Debug AOT" />
|
||||||
|
<BuildType Name="Release" />
|
||||||
|
<BuildType Name="Release AOT" />
|
||||||
|
</Configurations>
|
||||||
<Folder Name="/Solution Items/">
|
<Folder Name="/Solution Items/">
|
||||||
<File Path=".editorconfig" />
|
<File Path=".editorconfig" />
|
||||||
<File Path="Directory.Build.props" />
|
<File Path="Directory.Build.props" />
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
<RuntimeIdentifiers>osx-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>osx-arm64</RuntimeIdentifiers>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
public static void RunPass(ControlFlowGraph cfg)
|
public static void RunPass(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
var constants = new Dictionary<ulong, Operand>();
|
Dictionary<ulong, Operand> constants = new();
|
||||||
|
|
||||||
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
||||||
{
|
{
|
||||||
// If the constant has many uses, we also force a new constant mov to be added, in order
|
// If the constant has many uses, we also force a new constant mov to be added, in order
|
||||||
// to avoid overflow of the counts field (that is limited to 16 bits).
|
// to avoid overflow of the counts field (that is limited to 16 bits).
|
||||||
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
|
if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
|
||||||
{
|
{
|
||||||
constant = Local(source.Type);
|
constant = Local(source.Type);
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
public void Cset(Operand rd, ArmCondition condition)
|
public void Cset(Operand rd, ArmCondition condition)
|
||||||
{
|
{
|
||||||
var zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
|
Operand zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
|
||||||
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
|
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
long target = _stream.Position;
|
long target = _stream.Position;
|
||||||
|
|
||||||
if (_pendingBranches.TryGetValue(block, out var list))
|
if (_pendingBranches.TryGetValue(block, out List<(ArmCondition Condition, long BranchPos)> list))
|
||||||
{
|
{
|
||||||
foreach ((ArmCondition condition, long branchPos) in list)
|
foreach ((ArmCondition condition, long branchPos) in list)
|
||||||
{
|
{
|
||||||
@@ -119,7 +119,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_pendingBranches.TryGetValue(target, out var list))
|
if (!_pendingBranches.TryGetValue(target, out List<(ArmCondition Condition, long BranchPos)> list))
|
||||||
{
|
{
|
||||||
list = new List<(ArmCondition, long)>();
|
list = new List<(ArmCondition, long)>();
|
||||||
_pendingBranches.Add(target, list);
|
_pendingBranches.Add(target, list);
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Debug.Assert(dest.Type == OperandType.I32);
|
Debug.Assert(dest.Type == OperandType.I32);
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
|
|||||||
@@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var compType = (Comparison)comp.AsInt32();
|
Comparison compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace ARMeilleure.CodeGen
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a compiled function.
|
/// Represents a compiled function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
readonly struct CompiledFunction
|
public readonly struct CompiledFunction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the machine code of the <see cref="CompiledFunction"/>.
|
/// Gets the machine code of the <see cref="CompiledFunction"/>.
|
||||||
@@ -44,10 +44,11 @@ namespace ARMeilleure.CodeGen
|
|||||||
/// <typeparamref name="T"/> pointing to the mapped function.
|
/// <typeparamref name="T"/> pointing to the mapped function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Type of delegate</typeparam>
|
/// <typeparam name="T">Type of delegate</typeparam>
|
||||||
|
/// <param name="jitCache">The jit cache to map the function into</param>
|
||||||
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||||
public T Map<T>()
|
public T Map<T>(JitCache jitCache)
|
||||||
{
|
{
|
||||||
return MapWithPointer<T>(out _);
|
return MapWithPointer<T>(jitCache, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,11 +56,12 @@ namespace ARMeilleure.CodeGen
|
|||||||
/// <typeparamref name="T"/> pointing to the mapped function.
|
/// <typeparamref name="T"/> pointing to the mapped function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Type of delegate</typeparam>
|
/// <typeparam name="T">Type of delegate</typeparam>
|
||||||
|
/// <param name="jitCache">The jit cache to map the function into</param>
|
||||||
/// <param name="codePointer">Pointer to the function code in memory</param>
|
/// <param name="codePointer">Pointer to the function code in memory</param>
|
||||||
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||||
public T MapWithPointer<T>(out nint codePointer)
|
public T MapWithPointer<T>(JitCache jitCache, out nint codePointer)
|
||||||
{
|
{
|
||||||
codePointer = JitCache.Map(this);
|
codePointer = jitCache.Map(this);
|
||||||
|
|
||||||
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
|
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a relocation.
|
/// Represents a relocation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
readonly struct RelocEntry
|
public readonly struct RelocEntry
|
||||||
{
|
{
|
||||||
public const int Stride = 13; // Bytes.
|
public const int Stride = 13; // Bytes.
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents relocation information about a <see cref="CompiledFunction"/>.
|
/// Represents relocation information about a <see cref="CompiledFunction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
readonly struct RelocInfo
|
public readonly struct RelocInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an empty <see cref="RelocInfo"/>.
|
/// Gets an empty <see cref="RelocInfo"/>.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a symbol.
|
/// Represents a symbol.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
readonly struct Symbol
|
public readonly struct Symbol
|
||||||
{
|
{
|
||||||
private readonly ulong _value;
|
private readonly ulong _value;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Types of <see cref="Symbol"/>.
|
/// Types of <see cref="Symbol"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
enum SymbolType : byte
|
public enum SymbolType : byte
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refers to nothing, i.e no symbol.
|
/// Refers to nothing, i.e no symbol.
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
NumberLocals(cfg, regMasks.RegistersCount);
|
NumberLocals(cfg, regMasks.RegistersCount);
|
||||||
|
|
||||||
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
|
AllocationContext context = new(stackAlloc, regMasks, _intervals.Count);
|
||||||
|
|
||||||
BuildIntervals(cfg, context);
|
BuildIntervals(cfg, context);
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
if (_count + 1 > _capacity)
|
if (_count + 1 > _capacity)
|
||||||
{
|
{
|
||||||
var oldSpan = Span;
|
Span<LiveInterval> oldSpan = Span;
|
||||||
|
|
||||||
_capacity = Math.Max(4, _capacity * 2);
|
_capacity = Math.Max(4, _capacity * 2);
|
||||||
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
|
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
|
||||||
|
|
||||||
var newSpan = Span;
|
Span<LiveInterval> newSpan = Span;
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
if (Count + 1 > _capacity)
|
if (Count + 1 > _capacity)
|
||||||
{
|
{
|
||||||
var oldSpan = Span;
|
Span<int> oldSpan = Span;
|
||||||
|
|
||||||
_capacity = Math.Max(4, _capacity * 2);
|
_capacity = Math.Max(4, _capacity * 2);
|
||||||
_items = Allocators.Default.Allocate<int>((uint)_capacity);
|
_items = Allocators.Default.Allocate<int>((uint)_capacity);
|
||||||
|
|
||||||
var newSpan = Span;
|
Span<int> newSpan = Span;
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.CodeGen.Unwinding
|
namespace ARMeilleure.CodeGen.Unwinding
|
||||||
{
|
{
|
||||||
struct UnwindInfo
|
public struct UnwindInfo
|
||||||
{
|
{
|
||||||
public const int Stride = 4; // Bytes.
|
public const int Stride = 4; // Bytes.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.CodeGen.Unwinding
|
namespace ARMeilleure.CodeGen.Unwinding
|
||||||
{
|
{
|
||||||
enum UnwindPseudoOp
|
public enum UnwindPseudoOp
|
||||||
{
|
{
|
||||||
PushReg = 0,
|
PushReg = 0,
|
||||||
SetFrame = 1,
|
SetFrame = 1,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.CodeGen.Unwinding
|
namespace ARMeilleure.CodeGen.Unwinding
|
||||||
{
|
{
|
||||||
struct UnwindPushEntry
|
public struct UnwindPushEntry
|
||||||
{
|
{
|
||||||
public const int Stride = 16; // Bytes.
|
public const int Stride = 16; // Bytes.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure.CodeGen.Linking;
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using Microsoft.IO;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -1324,8 +1325,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public (byte[], RelocInfo) GetCode()
|
public (byte[], RelocInfo) GetCode()
|
||||||
{
|
{
|
||||||
var jumps = CollectionsMarshal.AsSpan(_jumps);
|
Span<Jump> jumps = CollectionsMarshal.AsSpan(_jumps);
|
||||||
var relocs = CollectionsMarshal.AsSpan(_relocs);
|
Span<Reloc> relocs = CollectionsMarshal.AsSpan(_relocs);
|
||||||
|
|
||||||
// Write jump relative offsets.
|
// Write jump relative offsets.
|
||||||
bool modified;
|
bool modified;
|
||||||
@@ -1410,13 +1411,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// Write the code, ignoring the dummy bytes after jumps, into a new stream.
|
// Write the code, ignoring the dummy bytes after jumps, into a new stream.
|
||||||
_stream.Seek(0, SeekOrigin.Begin);
|
_stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
using var codeStream = MemoryStreamManager.Shared.GetStream();
|
using RecyclableMemoryStream codeStream = MemoryStreamManager.Shared.GetStream();
|
||||||
var assembler = new Assembler(codeStream, HasRelocs);
|
Assembler assembler = new(codeStream, HasRelocs);
|
||||||
|
|
||||||
bool hasRelocs = HasRelocs;
|
bool hasRelocs = HasRelocs;
|
||||||
int relocIndex = 0;
|
int relocIndex = 0;
|
||||||
int relocOffset = 0;
|
int relocOffset = 0;
|
||||||
var relocEntries = hasRelocs
|
RelocEntry[] relocEntries = hasRelocs
|
||||||
? new RelocEntry[relocs.Length]
|
? new RelocEntry[relocs.Length]
|
||||||
: Array.Empty<RelocEntry>();
|
: Array.Empty<RelocEntry>();
|
||||||
|
|
||||||
@@ -1469,8 +1470,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
_stream.CopyTo(codeStream);
|
_stream.CopyTo(codeStream);
|
||||||
|
|
||||||
var code = codeStream.ToArray();
|
byte[] code = codeStream.ToArray();
|
||||||
var relocInfo = new RelocInfo(relocEntries);
|
RelocInfo relocInfo = new(relocEntries);
|
||||||
|
|
||||||
return (code, relocInfo);
|
return (code, relocInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -660,7 +660,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Debug.Assert(dest.Type == OperandType.I32);
|
Debug.Assert(dest.Type == OperandType.I32);
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
|
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
|
GetXcr0 fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
|
||||||
|
|
||||||
return fGetXcr0();
|
return fGetXcr0();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -759,7 +759,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
var compType = (Comparison)comp.AsInt32();
|
Comparison compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public static void RunPass(ControlFlowGraph cfg)
|
public static void RunPass(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
var constants = new Dictionary<ulong, Operand>();
|
Dictionary<ulong, Operand> constants = new();
|
||||||
|
|
||||||
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
||||||
{
|
{
|
||||||
// If the constant has many uses, we also force a new constant mov to be added, in order
|
// If the constant has many uses, we also force a new constant mov to be added, in order
|
||||||
// to avoid overflow of the counts field (that is limited to 16 bits).
|
// to avoid overflow of the counts field (that is limited to 16 bits).
|
||||||
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
|
if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
|
||||||
{
|
{
|
||||||
constant = Local(source.Type);
|
constant = Local(source.Type);
|
||||||
|
|
||||||
|
|||||||
@@ -20,45 +20,21 @@ namespace ARMeilleure.Common
|
|||||||
new( 1, 6)
|
new( 1, 6)
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels64BitSparseTiny =
|
private static readonly AddressTableLevel[] _levels64BitMono =
|
||||||
[
|
[
|
||||||
new( 11, 28),
|
new( 2, 37)
|
||||||
new( 2, 9)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels32BitSparseTiny =
|
private static readonly AddressTableLevel[] _levels32BitMono =
|
||||||
[
|
[
|
||||||
new( 10, 22),
|
new( 1, 31)
|
||||||
new( 1, 9)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels64BitSparseGiant =
|
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool mono)
|
||||||
[
|
|
||||||
new( 38, 1),
|
|
||||||
new( 2, 36)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels32BitSparseGiant =
|
|
||||||
[
|
|
||||||
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
|
|
||||||
//high power is always used, but I've left low power in here for future reference
|
|
||||||
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse, bool lowPower = false)
|
|
||||||
{
|
{
|
||||||
if (sparse)
|
if (mono)
|
||||||
{
|
{
|
||||||
if (lowPower)
|
return for64Bits ? _levels64BitMono : _levels32BitMono;
|
||||||
{
|
|
||||||
return for64Bits ? _levels64BitSparseTiny : _levels32BitSparseTiny;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace ARMeilleure.Common
|
||||||
|
{
|
||||||
|
public enum AddressTableType
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Sparse
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -129,13 +129,13 @@ namespace ARMeilleure.Common
|
|||||||
|
|
||||||
if (count > _count)
|
if (count > _count)
|
||||||
{
|
{
|
||||||
var oldMask = _masks;
|
long* oldMask = _masks;
|
||||||
var oldSpan = new Span<long>(_masks, _count);
|
Span<long> oldSpan = new(_masks, _count);
|
||||||
|
|
||||||
_masks = _allocator.Allocate<long>((uint)count);
|
_masks = _allocator.Allocate<long>((uint)count);
|
||||||
_count = count;
|
_count = count;
|
||||||
|
|
||||||
var newSpan = new Span<long>(_masks, _count);
|
Span<long> newSpan = new(_masks, _count);
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
newSpan[oldSpan.Length..].Clear();
|
newSpan[oldSpan.Length..].Clear();
|
||||||
|
|||||||
@@ -53,5 +53,14 @@ namespace ARMeilleure.Common
|
|||||||
{
|
{
|
||||||
return (bits >> shift) | (bits << (size - shift));
|
return (bits >> shift) | (bits << (size - shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T AlignUp<T>(T value, T size) where T : IBinaryInteger<T>
|
||||||
|
=> (value + (size - T.One)) & -size;
|
||||||
|
|
||||||
|
public static T AlignDown<T>(T value, T size) where T : IBinaryInteger<T>
|
||||||
|
=> value & -size;
|
||||||
|
|
||||||
|
public static T DivRoundUp<T>(T value, T dividend) where T : IBinaryInteger<T>
|
||||||
|
=> (value + (dividend - T.One)) / dividend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace ARMeilleure.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
int index = _freeHint++;
|
int index = _freeHint++;
|
||||||
var page = GetPage(index);
|
Span<TEntry> page = GetPage(index);
|
||||||
|
|
||||||
_allocated.Set(index);
|
_allocated.Set(index);
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ namespace ARMeilleure.Common
|
|||||||
throw new ArgumentException("Entry at the specified index was not allocated", nameof(index));
|
throw new ArgumentException("Entry at the specified index was not allocated", nameof(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
var page = GetPage(index);
|
Span<TEntry> page = GetPage(index);
|
||||||
|
|
||||||
return ref GetValue(page, index);
|
return ref GetValue(page, index);
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ namespace ARMeilleure.Common
|
|||||||
/// <returns>Page for the specified <see cref="index"/></returns>
|
/// <returns>Page for the specified <see cref="index"/></returns>
|
||||||
private unsafe Span<TEntry> GetPage(int index)
|
private unsafe Span<TEntry> GetPage(int index)
|
||||||
{
|
{
|
||||||
var pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
|
int pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
|
||||||
|
|
||||||
if (!_pages.TryGetValue(pageIndex, out nint page))
|
if (!_pages.TryGetValue(pageIndex, out nint page))
|
||||||
{
|
{
|
||||||
@@ -168,7 +168,7 @@ namespace ARMeilleure.Common
|
|||||||
{
|
{
|
||||||
_allocated.Dispose();
|
_allocated.Dispose();
|
||||||
|
|
||||||
foreach (var page in _pages.Values)
|
foreach (IntPtr page in _pages.Values)
|
||||||
{
|
{
|
||||||
NativeAllocator.Instance.Free((void*)page);
|
NativeAllocator.Instance.Free((void*)page);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ namespace ARMeilleure.Common
|
|||||||
public interface IAddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
public interface IAddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the address table's bottom level is sparsely mapped.
|
/// Gets the <see cref="AddressTableType"/> of the <see cref="IAddressTable{TEntry}"/> instance.
|
||||||
/// This also ensures the second bottom level is filled with a dummy page rather than 0.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Sparse { get; }
|
AddressTableType TableType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="IAddressTable{TEntry}"/> instance.
|
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="IAddressTable{TEntry}"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -31,6 +30,13 @@ namespace ARMeilleure.Common
|
|||||||
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
||||||
nint Base { get; }
|
nint Base { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal that the given code range exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Guest code range address</param>
|
||||||
|
/// <param name="size">Guest code range size</param>
|
||||||
|
void SignalCodeRange(ulong address, ulong size);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the specified <paramref name="address"/> is in the range of the
|
/// Determines if the specified <paramref name="address"/> is in the range of the
|
||||||
/// <see cref="IAddressTable{TEntry}"/>.
|
/// <see cref="IAddressTable{TEntry}"/>.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace ARMeilleure.Decoders
|
|||||||
|
|
||||||
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
var opc = (opCode >> 16) & 0xf;
|
int opc = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
if ((opc & 0b1) == 1)
|
if ((opc & 0b1) == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace ARMeilleure.Decoders
|
|||||||
Op = (opCode >> 20) & 0x1;
|
Op = (opCode >> 20) & 0x1;
|
||||||
U = ((opCode >> 23) & 1) != 0;
|
U = ((opCode >> 23) & 1) != 0;
|
||||||
|
|
||||||
var opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3);
|
int opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3);
|
||||||
|
|
||||||
if ((opc & 0b01000) == 0b01000)
|
if ((opc & 0b01000) == 0b01000)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace ARMeilleure.Decoders
|
|||||||
}
|
}
|
||||||
else if (DataOp == DataOp.Logical)
|
else if (DataOp == DataOp.Logical)
|
||||||
{
|
{
|
||||||
var bm = DecoderHelper.DecodeBitMask(opCode, true);
|
DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, true);
|
||||||
|
|
||||||
if (bm.IsUndefined)
|
if (bm.IsUndefined)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace ARMeilleure.Decoders
|
|||||||
|
|
||||||
public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
var bm = DecoderHelper.DecodeBitMask(opCode, false);
|
DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, false);
|
||||||
|
|
||||||
if (bm.IsUndefined)
|
if (bm.IsUndefined)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var newBlocks = new List<Block>(blocks.Count);
|
List<Block> newBlocks = new(blocks.Count);
|
||||||
|
|
||||||
// Finally, rebuild decoded block list, ignoring blocks outside the contiguous range.
|
// Finally, rebuild decoded block list, ignoring blocks outside the contiguous range.
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ namespace ARMeilleure.Diagnostics
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OperandKind.Memory:
|
case OperandKind.Memory:
|
||||||
var memOp = operand.GetMemory();
|
MemoryOperand memOp = operand.GetMemory();
|
||||||
|
|
||||||
_builder.Append('[');
|
_builder.Append('[');
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ namespace ARMeilleure.Diagnostics
|
|||||||
|
|
||||||
public static string GetDump(ControlFlowGraph cfg)
|
public static string GetDump(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
var dumper = new IRDumper(1);
|
IRDumper dumper = new(1);
|
||||||
|
|
||||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
||||||
@@ -547,7 +547,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using ARMeilleure.CodeGen.Linking;
|
using ARMeilleure.CodeGen.Linking;
|
||||||
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
|
using System.Linq;
|
||||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand hostAddress;
|
Operand hostAddress;
|
||||||
|
|
||||||
var table = context.FunctionTable;
|
IAddressTable<ulong> table = context.FunctionTable;
|
||||||
|
|
||||||
// If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback
|
// If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback
|
||||||
// onto the dispatch stub.
|
// onto the dispatch stub.
|
||||||
@@ -235,9 +236,9 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
hostAddress = context.Load(OperandType.I64, hostAddressAddr);
|
hostAddress = context.Load(OperandType.I64, hostAddressAddr);
|
||||||
}
|
}
|
||||||
else if (table.Sparse)
|
else if (table.TableType == AddressTableType.Sparse)
|
||||||
{
|
{
|
||||||
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
|
// Inline table lookup. Only enabled when the sparse function table is enabled with 1 level.
|
||||||
// Deliberately attempts to avoid branches.
|
// Deliberately attempts to avoid branches.
|
||||||
|
|
||||||
Operand tableBase = !context.HasPtc ?
|
Operand tableBase = !context.HasPtc ?
|
||||||
@@ -246,24 +247,21 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
hostAddress = tableBase;
|
hostAddress = tableBase;
|
||||||
|
|
||||||
for (int i = 0; i < table.Levels.Length; i++)
|
AddressTableLevel level = table.Levels.Last();
|
||||||
{
|
int clearBits = 64 - (level.Index + level.Length);
|
||||||
var level = table.Levels[i];
|
|
||||||
int clearBits = 64 - (level.Index + level.Length);
|
|
||||||
|
|
||||||
Operand index = context.ShiftLeft(
|
Operand index = context.ShiftLeft(
|
||||||
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
|
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
|
||||||
Const(3)
|
Const(3)
|
||||||
);
|
);
|
||||||
|
|
||||||
hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
|
hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hostAddress = !context.HasPtc ?
|
hostAddress = !context.HasPtc ?
|
||||||
Const((long)context.Stubs.DispatchStub) :
|
Const(context.Stubs.DispatchStub) :
|
||||||
Const((long)context.Stubs.DispatchStub, Ptc.DispatchStubSymbol);
|
Const(context.Stubs.DispatchStub, Ptc.DispatchStubSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isJump)
|
if (isJump)
|
||||||
|
|||||||
@@ -143,8 +143,8 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand address = context.Copy(GetIntA32(context, op.Rn));
|
Operand address = context.Copy(GetIntA32(context, op.Rn));
|
||||||
|
|
||||||
var exclusive = (accType & AccessType.Exclusive) != 0;
|
bool exclusive = (accType & AccessType.Exclusive) != 0;
|
||||||
var ordered = (accType & AccessType.Ordered) != 0;
|
bool ordered = (accType & AccessType.Ordered) != 0;
|
||||||
|
|
||||||
if ((accType & AccessType.Load) != 0)
|
if ((accType & AccessType.Load) != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||||
|
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,7 +451,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||||
|
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,7 +483,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -522,7 +522,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2246,7 +2246,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2265,7 +2265,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2322,7 +2322,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2341,7 +2341,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2390,7 +2390,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2409,7 +2409,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -726,8 +726,8 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (absolute)
|
if (absolute)
|
||||||
{
|
{
|
||||||
ne = EmitUnaryMathCall(context, nameof(MathHelper.Abs), ne);
|
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne);
|
||||||
me = EmitUnaryMathCall(context, nameof(MathHelper.Abs), me);
|
me = EmitUnaryMathCall(context, nameof(Math.Abs), me);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
|
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
|
||||||
{
|
{
|
||||||
var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);
|
Operand ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);
|
||||||
|
|
||||||
return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L));
|
return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +349,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1), signed: true, scalar: false);
|
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1), signed: true, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,15 +118,15 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
|
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
|
||||||
|
|
||||||
var toFixed = op.Opc == 1;
|
bool toFixed = op.Opc == 1;
|
||||||
int fracBits = op.Fbits;
|
int fracBits = op.Fbits;
|
||||||
var unsigned = op.U;
|
bool unsigned = op.U;
|
||||||
|
|
||||||
if (toFixed) // F32 to S32 or U32 (fixed)
|
if (toFixed) // F32 to S32 or U32 (fixed)
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (op1) =>
|
EmitVectorUnaryOpF32(context, (op1) =>
|
||||||
{
|
{
|
||||||
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
|
Operand scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
|
||||||
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
|
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
|
||||||
|
|
||||||
return context.Call(info, scaledValue);
|
return context.Call(info, scaledValue);
|
||||||
@@ -136,7 +136,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpI32(context, (op1) =>
|
EmitVectorUnaryOpI32(context, (op1) =>
|
||||||
{
|
{
|
||||||
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
|
Operand floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
|
||||||
|
|
||||||
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
|
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
|
||||||
}, !unsigned);
|
}, !unsigned);
|
||||||
@@ -357,10 +357,10 @@ namespace ARMeilleure.Instructions
|
|||||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b10: // Towards positive infinity
|
case 0b10: // Towards positive infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b11: // Towards negative infinity
|
case 0b11: // Towards negative infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,10 +494,10 @@ namespace ARMeilleure.Instructions
|
|||||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b10: // Towards positive infinity
|
case 0b10: // Towards positive infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b11: // Towards negative infinity
|
case 0b11: // Towards negative infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), m));
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +574,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), m));
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +613,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1));
|
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -460,8 +460,8 @@ namespace ARMeilleure.Instructions
|
|||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
MethodInfo info = (op.Size & 1) == 0
|
MethodInfo info = (op.Size & 1) == 0
|
||||||
? typeof(MathHelperF).GetMethod(name, [typeof(float)])
|
? typeof(MathF).GetMethod(name, [typeof(float)])
|
||||||
: typeof(MathHelper).GetMethod(name, [typeof(double)]);
|
: typeof(Math).GetMethod(name, [typeof(double)]);
|
||||||
|
|
||||||
return context.Call(info, n);
|
return context.Call(info, n);
|
||||||
}
|
}
|
||||||
@@ -470,11 +470,11 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
string name = nameof(MathHelper.Round);
|
string name = nameof(Math.Round);
|
||||||
|
|
||||||
MethodInfo info = (op.Size & 1) == 0
|
MethodInfo info = (op.Size & 1) == 0
|
||||||
? typeof(MathHelperF).GetMethod(name, [typeof(float), typeof(int)])
|
? typeof(MathF).GetMethod(name, [typeof(float), typeof(MidpointRounding)])
|
||||||
: typeof(MathHelper).GetMethod(name, [typeof(double), typeof(int)]);
|
: typeof(Math).GetMethod(name, [typeof(double), typeof(MidpointRounding)]);
|
||||||
|
|
||||||
return context.Call(info, n, Const((int)roundMode));
|
return context.Call(info, n, Const((int)roundMode));
|
||||||
}
|
}
|
||||||
@@ -510,16 +510,16 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl2);
|
context.MarkLabel(lbl2);
|
||||||
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Floor), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl3);
|
context.MarkLabel(lbl3);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
if (op.Replicate)
|
if (op.Replicate)
|
||||||
{
|
{
|
||||||
var regs = (count > 1) ? 1 : op.Increment;
|
int regs = (count > 1) ? 1 : op.Increment;
|
||||||
for (int reg = 0; reg < regs; reg++)
|
for (int reg = 0; reg < regs; reg++)
|
||||||
{
|
{
|
||||||
int dreg = reg + d;
|
int dreg = reg + d;
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
|
||||||
{
|
|
||||||
static class MathHelper
|
|
||||||
{
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double Abs(double value)
|
|
||||||
{
|
|
||||||
return Math.Abs(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double Ceiling(double value)
|
|
||||||
{
|
|
||||||
return Math.Ceiling(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double Floor(double value)
|
|
||||||
{
|
|
||||||
return Math.Floor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double Round(double value, int mode)
|
|
||||||
{
|
|
||||||
return Math.Round(value, (MidpointRounding)mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double Truncate(double value)
|
|
||||||
{
|
|
||||||
return Math.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MathHelperF
|
|
||||||
{
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float Abs(float value)
|
|
||||||
{
|
|
||||||
return MathF.Abs(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float Ceiling(float value)
|
|
||||||
{
|
|
||||||
return MathF.Ceiling(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float Floor(float value)
|
|
||||||
{
|
|
||||||
return MathF.Floor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float Round(float value, int mode)
|
|
||||||
{
|
|
||||||
return MathF.Round(value, (MidpointRounding)mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float Truncate(float value)
|
|
||||||
{
|
|
||||||
return MathF.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ using ARMeilleure.Memory;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
@@ -35,7 +34,6 @@ namespace ARMeilleure.Instructions
|
|||||||
Context = null;
|
Context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void Break(ulong address, int imm)
|
public static void Break(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -45,7 +43,6 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void SupervisorCall(ulong address, int imm)
|
public static void SupervisorCall(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -55,7 +52,6 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void Undefined(ulong address, int opCode)
|
public static void Undefined(ulong address, int opCode)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -66,31 +62,26 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region "System registers"
|
#region "System registers"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetCtrEl0()
|
public static ulong GetCtrEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CtrEl0;
|
return GetContext().CtrEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetDczidEl0()
|
public static ulong GetDczidEl0()
|
||||||
{
|
{
|
||||||
return GetContext().DczidEl0;
|
return GetContext().DczidEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetCntfrqEl0()
|
public static ulong GetCntfrqEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntfrqEl0;
|
return GetContext().CntfrqEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetCntpctEl0()
|
public static ulong GetCntpctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntpctEl0;
|
return GetContext().CntpctEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetCntvctEl0()
|
public static ulong GetCntvctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntvctEl0;
|
return GetContext().CntvctEl0;
|
||||||
@@ -98,31 +89,26 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Read"
|
#region "Read"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static byte ReadByte(ulong address)
|
public static byte ReadByte(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<byte>(address);
|
return GetMemoryManager().ReadGuest<byte>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ushort ReadUInt16(ulong address)
|
public static ushort ReadUInt16(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ushort>(address);
|
return GetMemoryManager().ReadGuest<ushort>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint ReadUInt32(ulong address)
|
public static uint ReadUInt32(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<uint>(address);
|
return GetMemoryManager().ReadGuest<uint>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong ReadUInt64(ulong address)
|
public static ulong ReadUInt64(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ulong>(address);
|
return GetMemoryManager().ReadGuest<ulong>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 ReadVector128(ulong address)
|
public static V128 ReadVector128(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<V128>(address);
|
return GetMemoryManager().ReadGuest<V128>(address);
|
||||||
@@ -130,56 +116,47 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Write"
|
#region "Write"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void WriteByte(ulong address, byte value)
|
public static void WriteByte(ulong address, byte value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void WriteUInt16(ulong address, ushort value)
|
public static void WriteUInt16(ulong address, ushort value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void WriteUInt32(ulong address, uint value)
|
public static void WriteUInt32(ulong address, uint value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void WriteUInt64(ulong address, ulong value)
|
public static void WriteUInt64(ulong address, ulong value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void WriteVector128(ulong address, V128 value)
|
public static void WriteVector128(ulong address, V128 value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void EnqueueForRejit(ulong address)
|
public static void EnqueueForRejit(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static void SignalMemoryTracking(ulong address, ulong size, bool write)
|
||||||
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
|
|
||||||
{
|
{
|
||||||
GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
|
GetMemoryManager().SignalMemoryTracking(address, size, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void ThrowInvalidMemoryAccess(ulong address)
|
public static void ThrowInvalidMemoryAccess(ulong address)
|
||||||
{
|
{
|
||||||
throw new InvalidAccessException(address);
|
throw new InvalidAccessException(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong GetFunctionAddress(ulong address)
|
public static ulong GetFunctionAddress(ulong address)
|
||||||
{
|
{
|
||||||
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
||||||
@@ -187,14 +164,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return (ulong)function.FuncPointer.ToInt64();
|
return (ulong)function.FuncPointer.ToInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static void InvalidateCacheLine(ulong address)
|
public static void InvalidateCacheLine(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static bool CheckSynchronization()
|
||||||
public static byte CheckSynchronization()
|
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
|
|
||||||
@@ -204,7 +179,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
|
|
||||||
return (byte)(context.Running ? 1 : 0);
|
return context.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExecutionContext GetContext()
|
public static ExecutionContext GetContext()
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
static class SoftFallback
|
static class SoftFallback
|
||||||
{
|
{
|
||||||
#region "ShrImm64"
|
#region "ShrImm64"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
if (roundConst == 0L)
|
if (roundConst == 0L)
|
||||||
@@ -50,7 +48,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
if (roundConst == 0L)
|
if (roundConst == 0L)
|
||||||
@@ -95,7 +92,6 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Saturation"
|
#region "Saturation"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static int SatF32ToS32(float value)
|
public static int SatF32ToS32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -107,7 +103,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static long SatF32ToS64(float value)
|
public static long SatF32ToS64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -119,7 +114,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint SatF32ToU32(float value)
|
public static uint SatF32ToU32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -131,7 +125,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong SatF32ToU64(float value)
|
public static ulong SatF32ToU64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -143,7 +136,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static int SatF64ToS32(double value)
|
public static int SatF64ToS32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -155,7 +147,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static long SatF64ToS64(double value)
|
public static long SatF64ToS64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -167,7 +158,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint SatF64ToU32(double value)
|
public static uint SatF64ToU32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -179,7 +169,6 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong SatF64ToU64(double value)
|
public static ulong SatF64ToU64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -193,7 +182,6 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Count"
|
#region "Count"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||||
{
|
{
|
||||||
value ^= value >> 1;
|
value ^= value >> 1;
|
||||||
@@ -213,7 +201,6 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static ReadOnlySpan<byte> ClzNibbleTbl => [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];
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||||
{
|
{
|
||||||
if (value == 0ul)
|
if (value == 0ul)
|
||||||
@@ -237,49 +224,41 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Table"
|
#region "Table"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0);
|
return TblOrTbx(default, vector, bytes, tb0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
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);
|
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0);
|
return TblOrTbx(dest, vector, bytes, tb0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
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);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
||||||
@@ -321,22 +300,14 @@ namespace ARMeilleure.Instructions
|
|||||||
private const uint Crc32RevPoly = 0xedb88320;
|
private const uint Crc32RevPoly = 0xedb88320;
|
||||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||||
|
|
||||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||||
@@ -387,25 +358,21 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Aes"
|
#region "Aes"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Encrypt(V128 value, V128 roundKey)
|
public static V128 Encrypt(V128 value, V128 roundKey)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 InverseMixColumns(V128 value)
|
public static V128 InverseMixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesInvMixColumns(value);
|
return CryptoHelper.AesInvMixColumns(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 MixColumns(V128 value)
|
public static V128 MixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesMixColumns(value);
|
return CryptoHelper.AesMixColumns(value);
|
||||||
@@ -413,7 +380,6 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha1"
|
#region "Sha1"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -434,13 +400,11 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static uint FixedRotate(uint hash_e)
|
public static uint FixedRotate(uint hash_e)
|
||||||
{
|
{
|
||||||
return hash_e.Rol(30);
|
return hash_e.Rol(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -461,7 +425,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -482,7 +445,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
||||||
{
|
{
|
||||||
ulong t2 = w4_7.Extract<ulong>(0);
|
ulong t2 = w4_7.Extract<ulong>(0);
|
||||||
@@ -493,7 +455,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result ^ (w0_3 ^ w8_11);
|
return result ^ (w0_3 ^ w8_11);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
||||||
{
|
{
|
||||||
V128 t = tw0_3 ^ (w12_15 >> 32);
|
V128 t = tw0_3 ^ (w12_15 >> 32);
|
||||||
@@ -538,19 +499,16 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha256"
|
#region "Sha256"
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||||
{
|
{
|
||||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||||
{
|
{
|
||||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||||
{
|
{
|
||||||
V128 result = new();
|
V128 result = new();
|
||||||
@@ -569,7 +527,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||||
{
|
{
|
||||||
V128 result = new();
|
V128 result = new();
|
||||||
@@ -671,7 +628,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||||
{
|
{
|
||||||
V128 result = V128.Zero;
|
V128 result = V128.Zero;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
@@ -313,7 +312,6 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat16_32
|
static class SoftFloat16_32
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPConvert(ushort valueBits)
|
public static float FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -489,7 +487,6 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat16_64
|
static class SoftFloat16_64
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPConvert(ushort valueBits)
|
public static double FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -665,7 +662,6 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat32_16
|
static class SoftFloat32_16
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ushort FPConvert(float value)
|
public static ushort FPConvert(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -785,19 +781,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat32
|
static class SoftFloat32
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPAdd(float value1, float value2)
|
public static float FPAdd(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, false);
|
return FPAddFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPAddFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPAddFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -848,8 +837,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static int FPCompare(float value1, float value2, bool signalNaNs)
|
||||||
public static int FPCompare(float value1, float value2, byte signalNaNs)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = context.Fpcr;
|
FPCR fpcr = context.Fpcr;
|
||||||
@@ -863,7 +851,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
result = 0b0011;
|
result = 0b0011;
|
||||||
|
|
||||||
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
|
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs)
|
||||||
{
|
{
|
||||||
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
||||||
}
|
}
|
||||||
@@ -887,13 +875,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareEQ(float value1, float value2)
|
public static float FPCompareEQ(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, false);
|
return FPCompareEQFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float FPCompareEQFpscrImpl(float value1, float value2, bool standardFpscr)
|
public static float FPCompareEQFpscr(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -920,25 +907,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareGE(float value1, float value2)
|
public static float FPCompareGE(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, false);
|
return FPCompareGEFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPCompareGEFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPCompareGEFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -962,19 +936,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareGT(float value1, float value2)
|
public static float FPCompareGT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, false);
|
return FPCompareGTFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPCompareGTFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPCompareGTFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -998,31 +965,26 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareLE(float value1, float value2)
|
public static float FPCompareLE(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, false);
|
return FPCompareGE(value2, value1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPCompareLT(float value1, float value2)
|
public static float FPCompareLT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, false);
|
return FPCompareGT(value2, value1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPCompareLEFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGEFpscr(value2, value1, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPCompareLTFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGTFpscr(value2, value1, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPDiv(float value1, float value2)
|
public static float FPDiv(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1075,19 +1037,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMax(float value1, float value2)
|
public static float FPMax(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, false);
|
return FPMaxFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMaxFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPMaxFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1148,13 +1103,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMaxNum(float value1, float value2)
|
public static float FPMaxNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, false);
|
return FPMaxNumFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float FPMaxNumFpscrImpl(float value1, float value2, bool standardFpscr)
|
public static float FPMaxNumFpscr(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1171,28 +1125,15 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(true);
|
value2 = FPInfinity(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
return FPMaxFpscr(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMin(float value1, float value2)
|
public static float FPMin(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, false);
|
return FPMinFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMinFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPMinFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1253,19 +1194,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMinNum(float value1, float value2)
|
public static float FPMinNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, false);
|
return FPMinNumFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMinNumFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPMinNumFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1282,22 +1216,15 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(false);
|
value2 = FPInfinity(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
return FPMinFpscr(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMul(float value1, float value2)
|
public static float FPMul(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, false);
|
return FPMulFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMulFpscr(float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPMulFpscrImpl(float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1344,19 +1271,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMulAdd(float valueA, float value1, float value2)
|
public static float FPMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscr(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPMulAddFpscrImpl(float valueA, float value1, float value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1422,23 +1342,20 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMulSub(float valueA, float value1, float value2)
|
public static float FPMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr)
|
||||||
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscr(valueA, value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPMulX(float value1, float value2)
|
public static float FPMulX(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1484,36 +1401,27 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPNegMulSub(float valueA, float value1, float value2)
|
public static float FPNegMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRecipEstimate(float value)
|
public static float FPRecipEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, false);
|
return FPRecipEstimateFpscr(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPRecipEstimateFpscr(float value, bool standardFpscr)
|
||||||
public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPRecipEstimateFpscrImpl(float value, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1538,7 +1446,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else if (MathF.Abs(value) < MathF.Pow(2f, -128))
|
else if (MathF.Abs(value) < MathF.Pow(2f, -128))
|
||||||
{
|
{
|
||||||
var overflowToInf = fpcr.GetRoundingMode() switch
|
bool overflowToInf = fpcr.GetRoundingMode() switch
|
||||||
{
|
{
|
||||||
FPRoundingMode.ToNearest => true,
|
FPRoundingMode.ToNearest => true,
|
||||||
FPRoundingMode.TowardsPlusInfinity => !sign,
|
FPRoundingMode.TowardsPlusInfinity => !sign,
|
||||||
@@ -1600,7 +1508,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRecipStep(float value1, float value2)
|
public static float FPRecipStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1626,16 +1533,15 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscrImpl(value1, value2, true);
|
product = FPMulFpscr(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPSubFpscrImpl(FPTwo(false), product, true);
|
result = FPSubFpscr(FPTwo(false), product, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRecipStepFused(float value1, float value2)
|
public static float FPRecipStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1679,7 +1585,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRecpX(float value)
|
public static float FPRecpX(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1705,19 +1610,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRSqrtEstimate(float value)
|
public static float FPRSqrtEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, false);
|
return FPRSqrtEstimateFpscr(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static float FPRSqrtEstimateFpscr(float value, bool standardFpscr)
|
||||||
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float FPRSqrtEstimateFpscrImpl(float value, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1831,7 +1729,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRSqrtStep(float value1, float value2)
|
public static float FPRSqrtStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1857,7 +1754,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscrImpl(value1, value2, true);
|
product = FPMulFpscr(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
||||||
@@ -1866,7 +1763,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPRSqrtStepFused(float value1, float value2)
|
public static float FPRSqrtStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1910,7 +1806,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPSqrt(float value)
|
public static float FPSqrt(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1953,13 +1848,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static float FPSub(float value1, float value2)
|
public static float FPSub(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscrImpl(value1, value2, false);
|
return FPSubFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float FPSubFpscrImpl(float value1, float value2, bool standardFpscr)
|
public static float FPSubFpscr(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2200,7 +2094,6 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat64_16
|
static class SoftFloat64_16
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static ushort FPConvert(double value)
|
public static ushort FPConvert(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2320,19 +2213,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat64
|
static class SoftFloat64
|
||||||
{
|
{
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPAdd(double value1, double value2)
|
public static double FPAdd(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, false);
|
return FPAddFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPAddFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPAddFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2383,8 +2269,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static int FPCompare(double value1, double value2, bool signalNaNs)
|
||||||
public static int FPCompare(double value1, double value2, byte signalNaNs)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = context.Fpcr;
|
FPCR fpcr = context.Fpcr;
|
||||||
@@ -2398,7 +2283,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
result = 0b0011;
|
result = 0b0011;
|
||||||
|
|
||||||
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
|
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs)
|
||||||
{
|
{
|
||||||
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
||||||
}
|
}
|
||||||
@@ -2422,19 +2307,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPCompareEQ(double value1, double value2)
|
public static double FPCompareEQ(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, false);
|
return FPCompareEQFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPCompareEQFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPCompareEQFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2461,19 +2339,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPCompareGE(double value1, double value2)
|
public static double FPCompareGE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, false);
|
return FPCompareGEFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPCompareGEFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPCompareGEFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2497,19 +2368,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPCompareGT(double value1, double value2)
|
public static double FPCompareGT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, false);
|
return FPCompareGTFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPCompareGTFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPCompareGTFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2533,31 +2397,26 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPCompareLE(double value1, double value2)
|
public static double FPCompareLE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, false);
|
return FPCompareGE(value2, value1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPCompareLT(double value1, double value2)
|
public static double FPCompareLT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, false);
|
return FPCompareGT(value2, value1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPCompareLEFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGEFpscr(value2, value1, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPCompareLTFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGTFpscr(value2, value1, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPDiv(double value1, double value2)
|
public static double FPDiv(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2610,19 +2469,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMax(double value1, double value2)
|
public static double FPMax(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, false);
|
return FPMaxFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMaxFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMaxFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2683,19 +2535,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMaxNum(double value1, double value2)
|
public static double FPMaxNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, false);
|
return FPMaxNumFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMaxNumFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMaxNumFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2712,22 +2557,15 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(true);
|
value2 = FPInfinity(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
return FPMaxFpscr(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMin(double value1, double value2)
|
public static double FPMin(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, false);
|
return FPMinFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMinFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMinFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2788,19 +2626,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMinNum(double value1, double value2)
|
public static double FPMinNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, false);
|
return FPMinNumFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMinNumFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMinNumFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2817,22 +2648,15 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(false);
|
value2 = FPInfinity(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
return FPMinFpscr(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMul(double value1, double value2)
|
public static double FPMul(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, false);
|
return FPMulFpscr(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMulFpscr(double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMulFpscrImpl(double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2879,19 +2703,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMulAdd(double valueA, double value1, double value2)
|
public static double FPMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscr(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPMulAddFpscrImpl(double valueA, double value1, double value2, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2957,23 +2774,20 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMulSub(double valueA, double value1, double value2)
|
public static double FPMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr)
|
||||||
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscr(valueA, value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPMulX(double value1, double value2)
|
public static double FPMulX(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3019,36 +2833,27 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPNegMulSub(double valueA, double value1, double value2)
|
public static double FPNegMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAdd(valueA, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRecipEstimate(double value)
|
public static double FPRecipEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, false);
|
return FPRecipEstimateFpscr(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPRecipEstimateFpscr(double value, bool standardFpscr)
|
||||||
public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPRecipEstimateFpscrImpl(double value, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -3073,7 +2878,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else if (Math.Abs(value) < Math.Pow(2d, -1024))
|
else if (Math.Abs(value) < Math.Pow(2d, -1024))
|
||||||
{
|
{
|
||||||
var overflowToInf = fpcr.GetRoundingMode() switch
|
bool overflowToInf = fpcr.GetRoundingMode() switch
|
||||||
{
|
{
|
||||||
FPRoundingMode.ToNearest => true,
|
FPRoundingMode.ToNearest => true,
|
||||||
FPRoundingMode.TowardsPlusInfinity => !sign,
|
FPRoundingMode.TowardsPlusInfinity => !sign,
|
||||||
@@ -3135,7 +2940,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRecipStep(double value1, double value2)
|
public static double FPRecipStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3161,7 +2965,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscrImpl(value1, value2, true);
|
product = FPMulFpscr(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPSubFpscr(FPTwo(false), product, true);
|
result = FPSubFpscr(FPTwo(false), product, true);
|
||||||
@@ -3170,7 +2974,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRecipStepFused(double value1, double value2)
|
public static double FPRecipStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3214,7 +3017,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRecpX(double value)
|
public static double FPRecpX(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3240,19 +3042,12 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRSqrtEstimate(double value)
|
public static double FPRSqrtEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, false);
|
return FPRSqrtEstimateFpscr(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
public static double FPRSqrtEstimateFpscr(double value, bool standardFpscr)
|
||||||
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
|
|
||||||
{
|
|
||||||
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double FPRSqrtEstimateFpscrImpl(double value, bool standardFpscr)
|
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -3366,7 +3161,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRSqrtStep(double value1, double value2)
|
public static double FPRSqrtStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3392,7 +3186,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscrImpl(value1, value2, true);
|
product = FPMulFpscr(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
||||||
@@ -3401,7 +3195,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPRSqrtStepFused(double value1, double value2)
|
public static double FPRSqrtStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3445,7 +3238,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPSqrt(double value)
|
public static double FPSqrt(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3488,7 +3280,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
public static double FPSub(double value1, double value2)
|
public static double FPSub(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscr(value1, value2, false);
|
return FPSubFpscr(value1, value2, false);
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
ushort newCount = checked((ushort)(count + 1));
|
ushort newCount = checked((ushort)(count + 1));
|
||||||
ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue);
|
ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue);
|
||||||
|
|
||||||
var oldSpan = new Span<T>(data, count);
|
Span<T> oldSpan = new(data, count);
|
||||||
|
|
||||||
capacity = newCapacity;
|
capacity = newCapacity;
|
||||||
data = Allocators.References.Allocate<T>(capacity);
|
data = Allocators.References.Allocate<T>(capacity);
|
||||||
@@ -338,7 +338,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
throw new OverflowException();
|
throw new OverflowException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldSpan = new Span<T>(data, (int)count);
|
Span<T> oldSpan = new(data, (int)count);
|
||||||
|
|
||||||
capacity = newCapacity;
|
capacity = newCapacity;
|
||||||
data = Allocators.References.Allocate<T>(capacity);
|
data = Allocators.References.Allocate<T>(capacity);
|
||||||
@@ -352,7 +352,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
|
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
|
||||||
{
|
{
|
||||||
var span = new Span<T>(data, count);
|
Span<T> span = new(data, count);
|
||||||
|
|
||||||
for (int i = 0; i < span.Length; i++)
|
for (int i = 0; i < span.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -372,7 +372,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged
|
private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged
|
||||||
{
|
{
|
||||||
var span = new Span<T>(data, (int)count);
|
Span<T> span = new(data, (int)count);
|
||||||
|
|
||||||
for (int i = 0; i < span.Length; i++)
|
for (int i = 0; i < span.Length; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace ARMeilleure.Memory
|
namespace ARMeilleure.Memory
|
||||||
{
|
{
|
||||||
public class ReservedRegion
|
public class ReservedRegion : IDisposable
|
||||||
{
|
{
|
||||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
|
using ARMeilleure.Translation.Cache;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
@@ -17,11 +18,11 @@ namespace ARMeilleure.Signal
|
|||||||
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
|
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
|
||||||
public delegate void DebugNativeWriteLoop(nint nativeWriteLoopPtr, nint writePtr);
|
public delegate void DebugNativeWriteLoop(nint nativeWriteLoopPtr, nint writePtr);
|
||||||
|
|
||||||
public static DebugPartialUnmap GenerateDebugPartialUnmap()
|
public static DebugPartialUnmap GenerateDebugPartialUnmap(JitCache jitCache)
|
||||||
{
|
{
|
||||||
EmitterContext context = new();
|
EmitterContext context = new();
|
||||||
|
|
||||||
var result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
|
Operand result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
|
||||||
|
|
||||||
context.Return(result);
|
context.Return(result);
|
||||||
|
|
||||||
@@ -31,14 +32,14 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
OperandType[] argTypes = [OperandType.I64];
|
OperandType[] argTypes = [OperandType.I64];
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>();
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>(jitCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(nint structPtr)
|
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(JitCache jitCache, nint structPtr)
|
||||||
{
|
{
|
||||||
EmitterContext context = new();
|
EmitterContext context = new();
|
||||||
|
|
||||||
var result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
|
Operand result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
|
||||||
|
|
||||||
context.Return(result);
|
context.Return(result);
|
||||||
|
|
||||||
@@ -48,10 +49,10 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
OperandType[] argTypes = [OperandType.I64];
|
OperandType[] argTypes = [OperandType.I64];
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugThreadLocalMapGetOrReserve>();
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugThreadLocalMapGetOrReserve>(jitCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DebugNativeWriteLoop GenerateDebugNativeWriteLoop()
|
public static DebugNativeWriteLoop GenerateDebugNativeWriteLoop(JitCache jitCache)
|
||||||
{
|
{
|
||||||
EmitterContext context = new();
|
EmitterContext context = new();
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
OperandType[] argTypes = [OperandType.I64];
|
OperandType[] argTypes = [OperandType.I64];
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugNativeWriteLoop>();
|
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugNativeWriteLoop>(jitCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
|
|
||||||
namespace ARMeilleure.Translation.Cache
|
namespace ARMeilleure.Translation.Cache
|
||||||
{
|
{
|
||||||
readonly struct CacheEntry : IComparable<CacheEntry>
|
public readonly struct CacheEntry : IComparable<CacheEntry>
|
||||||
{
|
{
|
||||||
public int Offset { get; }
|
public int Offset { get; }
|
||||||
public int Size { get; }
|
public int Size { get; }
|
||||||
|
|||||||
@@ -23,11 +23,30 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly int _regionSize;
|
||||||
|
private int _regionCount;
|
||||||
|
|
||||||
private readonly List<MemoryBlock> _blocks = [];
|
private readonly List<MemoryBlock> _blocks = [];
|
||||||
|
|
||||||
public CacheMemoryAllocator(int capacity)
|
public CacheMemoryAllocator(int regionSize, int initialRegionCount = 1)
|
||||||
{
|
{
|
||||||
_blocks.Add(new MemoryBlock(0, capacity));
|
_regionCount = 0;
|
||||||
|
_regionSize = regionSize;
|
||||||
|
|
||||||
|
for (; initialRegionCount > 0; initialRegionCount--)
|
||||||
|
{
|
||||||
|
_blocks.Add(new MemoryBlock(_regionSize * _regionCount, _regionSize));
|
||||||
|
_regionCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddNewBlocks(int count)
|
||||||
|
{
|
||||||
|
for (; count > 0; count--)
|
||||||
|
{
|
||||||
|
_blocks.Add(new MemoryBlock(_regionSize * _regionCount, _regionSize));
|
||||||
|
_regionCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Allocate(int size)
|
public int Allocate(int size)
|
||||||
@@ -66,12 +85,13 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
index = ~index;
|
index = ~index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < _blocks.Count)
|
int endOffs = block.Offset + block.Size;
|
||||||
|
|
||||||
|
// Don't merge blocks from different allocations
|
||||||
|
if (index < _blocks.Count && endOffs % _regionSize != 0)
|
||||||
{
|
{
|
||||||
MemoryBlock next = _blocks[index];
|
MemoryBlock next = _blocks[index];
|
||||||
|
|
||||||
int endOffs = block.Offset + block.Size;
|
|
||||||
|
|
||||||
if (next.Offset == endOffs)
|
if (next.Offset == endOffs)
|
||||||
{
|
{
|
||||||
block = new MemoryBlock(block.Offset, block.Size + next.Size);
|
block = new MemoryBlock(block.Offset, block.Size + next.Size);
|
||||||
@@ -79,7 +99,8 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index > 0)
|
// Don't merge blocks from different allocations
|
||||||
|
if (index > 0 && block.Offset % _regionSize != 0)
|
||||||
{
|
{
|
||||||
MemoryBlock prev = _blocks[index - 1];
|
MemoryBlock prev = _blocks[index - 1];
|
||||||
|
|
||||||
|
|||||||
@@ -14,62 +14,35 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace ARMeilleure.Translation.Cache
|
namespace ARMeilleure.Translation.Cache
|
||||||
{
|
{
|
||||||
static partial class JitCache
|
public partial class JitCache : IDisposable
|
||||||
{
|
{
|
||||||
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
||||||
private static readonly int _pageMask = _pageSize - 1;
|
private static readonly int _pageMask = _pageSize - 1;
|
||||||
|
|
||||||
private const int CodeAlignment = 4; // Bytes.
|
private const int CodeAlignment = 4; // Bytes.
|
||||||
private const int CacheSize = 256 * 1024 * 1024;
|
private const uint CacheSize = 256 * 1024 * 1024;
|
||||||
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private readonly JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
private readonly CacheMemoryAllocator _cacheAllocator;
|
||||||
|
|
||||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
private readonly List<CacheEntry> _cacheEntries = [];
|
||||||
|
|
||||||
private static readonly Lock _lock = new();
|
private readonly Lock _lock = new();
|
||||||
private static bool _initialized;
|
|
||||||
|
|
||||||
private static readonly List<ReservedRegion> _jitRegions = [];
|
private readonly List<ReservedRegion> _jitRegions = [];
|
||||||
private static int _activeRegionIndex = 0;
|
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
public static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
|
private static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
|
||||||
|
|
||||||
public static void Initialize(IJitMemoryAllocator allocator)
|
public JitCache(IJitMemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
_jitRegions.Add(new(allocator, CacheSize));
|
||||||
{
|
|
||||||
if (OperatingSystem.IsWindows())
|
|
||||||
{
|
|
||||||
JitUnwindWindows.RemoveFunctionTableHandler(
|
|
||||||
_jitRegions[0].Pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < _jitRegions.Count; i++)
|
_cacheAllocator = new((int)CacheSize);
|
||||||
{
|
|
||||||
_jitRegions[i].Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_jitRegions.Clear();
|
|
||||||
_cacheAllocators.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_activeRegionIndex = 0;
|
|
||||||
|
|
||||||
var firstRegion = new ReservedRegion(allocator, CacheSize);
|
|
||||||
_jitRegions.Add(firstRegion);
|
|
||||||
|
|
||||||
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
|
|
||||||
_cacheAllocators.Add(firstCacheAllocator);
|
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
@@ -79,23 +52,20 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
JitUnwindWindows.InstallFunctionTableHandler(
|
JitUnwindWindows.InstallFunctionTableHandler(
|
||||||
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
this, _jitRegions[0].Pointer, CacheSize, _jitRegions[0].Pointer + Allocate(_pageSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static nint Map(CompiledFunction func)
|
public nint Map(CompiledFunction func)
|
||||||
{
|
{
|
||||||
byte[] code = func.Code;
|
byte[] code = func.Code;
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
Debug.Assert(_initialized);
|
|
||||||
|
|
||||||
int funcOffset = Allocate(code.Length);
|
int funcOffset = Allocate(code.Length);
|
||||||
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
|
nint funcPtr = GetFunctionPtr(funcOffset);
|
||||||
nint funcPtr = targetRegion.Pointer + funcOffset;
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
@@ -109,9 +79,9 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReprotectAsWritable(targetRegion, funcOffset, code.Length);
|
ReprotectAsWritable(funcOffset, code.Length);
|
||||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||||
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
|
ReprotectAsExecutable(funcOffset, code.Length);
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
@@ -129,25 +99,24 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Unmap(nint pointer)
|
public void Unmap(nint pointer)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
Debug.Assert(_initialized);
|
for (int i = 0; i < _jitRegions.Count; i++)
|
||||||
|
|
||||||
foreach (var region in _jitRegions)
|
|
||||||
{
|
{
|
||||||
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
|
ReservedRegion jitRegion = _jitRegions[i];
|
||||||
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
|
if (pointer.ToInt64() < jitRegion.Pointer.ToInt64() ||
|
||||||
|
pointer.ToInt64() >= (jitRegion.Pointer + (nint)CacheSize).ToInt64())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
|
int funcOffset = (int)(pointer.ToInt64() - jitRegion.Pointer.ToInt64() + i * CacheSize);
|
||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
{
|
{
|
||||||
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size));
|
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,53 +125,66 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size)
|
private void ReprotectAsWritable(int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = (offset % (int)CacheSize) & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = endOffs % (int)CacheSize == 0
|
||||||
|
? (((int)CacheSize) + _pageMask) & ~_pageMask
|
||||||
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
: ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
|
||||||
|
GetRegion(offset).Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size)
|
private void ReprotectAsExecutable(int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = (offset % (int)CacheSize) & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = endOffs % (int)CacheSize == 0
|
||||||
|
? (((int)CacheSize) + _pageMask) & ~_pageMask
|
||||||
|
: ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
|
||||||
|
|
||||||
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
GetRegion(offset).Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int Allocate(int codeSize)
|
private int Allocate(int codeSize)
|
||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||||
|
|
||||||
if (allocOffset >= 0)
|
if (allocOffset >= 0)
|
||||||
{
|
{
|
||||||
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
GetRegion(allocOffset).ExpandIfNeeded((ulong)(allocOffset % (int)CacheSize) + (ulong)codeSize);
|
||||||
return allocOffset;
|
return allocOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exhaustedRegion = _activeRegionIndex;
|
_cacheAllocator.AddNewBlocks(1);
|
||||||
var newRegion = new ReservedRegion(_jitRegions[0].Allocator, CacheSize);
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
|
|
||||||
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache of size {(_jitRegions.Count * CacheSize).Bytes()} exhausted, creating new Cache Region ({((_jitRegions.Count + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
_jitRegions.Add(newRegion);
|
_jitRegions.Add(newRegion);
|
||||||
_activeRegionIndex = _jitRegions.Count - 1;
|
|
||||||
|
allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||||
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
|
if (allocOffset < 0)
|
||||||
|
|
||||||
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
|
|
||||||
|
|
||||||
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
|
||||||
if (allocOffsetNew < 0)
|
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
}
|
}
|
||||||
|
|
||||||
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
|
GetRegion(allocOffset).ExpandIfNeeded((ulong)(allocOffset % (int)CacheSize) + (ulong)codeSize);
|
||||||
return allocOffsetNew;
|
return allocOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private nint GetFunctionPtr(int offset)
|
||||||
|
{
|
||||||
|
return GetRegion(offset).Pointer + (offset % (int)CacheSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReservedRegion GetRegion(int offset)
|
||||||
|
{
|
||||||
|
int index = offset / (int)CacheSize;
|
||||||
|
|
||||||
|
return _jitRegions[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AlignCodeSize(int codeSize)
|
private static int AlignCodeSize(int codeSize)
|
||||||
@@ -210,7 +192,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(int offset, int size, UnwindInfo unwindInfo)
|
private void Add(int offset, int size, UnwindInfo unwindInfo)
|
||||||
{
|
{
|
||||||
CacheEntry entry = new(offset, size, unwindInfo);
|
CacheEntry entry = new(offset, size, unwindInfo);
|
||||||
|
|
||||||
@@ -224,25 +206,22 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
_cacheEntries.Insert(index, entry);
|
_cacheEntries.Insert(index, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
|
public bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
foreach (var region in _jitRegions)
|
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
index = ~index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (index < 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
index = ~index - 1;
|
entry = _cacheEntries[index];
|
||||||
}
|
entryIndex = index;
|
||||||
|
return true;
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
entry = _cacheEntries[index];
|
|
||||||
entryIndex = index;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,5 +229,18 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
entryIndex = 0;
|
entryIndex = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
JitUnwindWindows.RemoveFunctionTableHandler(_jitRegions[0].Pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ReservedRegion jitRegion in _jitRegions)
|
||||||
|
{
|
||||||
|
jitRegion.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@@ -27,6 +29,29 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
public unsafe fixed ushort UnwindCodes[MaxUnwindCodesArraySize];
|
public unsafe fixed ushort UnwindCodes[MaxUnwindCodesArraySize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe struct InternalFunctionHandler
|
||||||
|
{
|
||||||
|
public InternalFunctionHandler(JitCache jitCache, nint workBufferPtr)
|
||||||
|
{
|
||||||
|
_jitCache = jitCache;
|
||||||
|
|
||||||
|
_runtimeFunction = (RuntimeFunction*)workBufferPtr;
|
||||||
|
|
||||||
|
_unwindInfo = (UnwindInfo*)(workBufferPtr + _sizeOfRuntimeFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly JitCache _jitCache;
|
||||||
|
|
||||||
|
readonly RuntimeFunction* _runtimeFunction;
|
||||||
|
|
||||||
|
readonly UnwindInfo* _unwindInfo;
|
||||||
|
|
||||||
|
public RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
||||||
|
{
|
||||||
|
return JitUnwindWindows.FunctionTableHandler(_jitCache, _runtimeFunction, _unwindInfo, controlPc, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private enum UnwindOp
|
private enum UnwindOp
|
||||||
{
|
{
|
||||||
PushNonvol = 0,
|
PushNonvol = 0,
|
||||||
@@ -59,27 +84,28 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||||
|
|
||||||
private static int _sizeOfRuntimeFunction;
|
private static readonly int _sizeOfRuntimeFunction;
|
||||||
|
|
||||||
private unsafe static RuntimeFunction* _runtimeFunction;
|
private static readonly ConcurrentDictionary<ulong, InternalFunctionHandler> _functionTableHandlers = new();
|
||||||
|
|
||||||
private unsafe static UnwindInfo* _unwindInfo;
|
static JitUnwindWindows()
|
||||||
|
{
|
||||||
|
_sizeOfRuntimeFunction = Marshal.SizeOf<RuntimeFunction>();
|
||||||
|
}
|
||||||
|
|
||||||
public static void InstallFunctionTableHandler(nint codeCachePointer, uint codeCacheLength, nint workBufferPtr)
|
public static void InstallFunctionTableHandler(JitCache jitCache, nint codeCachePointer, uint codeCacheLength, nint workBufferPtr)
|
||||||
{
|
{
|
||||||
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||||
|
|
||||||
_sizeOfRuntimeFunction = Marshal.SizeOf<RuntimeFunction>();
|
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
|
InternalFunctionHandler handler;
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
_runtimeFunction = (RuntimeFunction*)workBufferPtr;
|
handler = new InternalFunctionHandler(jitCache, workBufferPtr);
|
||||||
|
|
||||||
_unwindInfo = (UnwindInfo*)(workBufferPtr + _sizeOfRuntimeFunction);
|
_getRuntimeFunctionCallback = handler.FunctionTableHandler;
|
||||||
|
|
||||||
_getRuntimeFunctionCallback = new GetRuntimeFunctionCallback(FunctionTableHandler);
|
|
||||||
|
|
||||||
result = RtlInstallFunctionTableCallback(
|
result = RtlInstallFunctionTableCallback(
|
||||||
codeCachePtr | 3,
|
codeCachePtr | 3,
|
||||||
@@ -94,6 +120,8 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failure installing function table callback.");
|
throw new InvalidOperationException("Failure installing function table callback.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_functionTableHandlers.TryAdd(codeCachePtr, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
||||||
@@ -111,24 +139,26 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failure removing function table callback.");
|
throw new InvalidOperationException("Failure removing function table callback.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_functionTableHandlers.Remove(codeCachePtr, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
private static unsafe RuntimeFunction* FunctionTableHandler(JitCache jitCache, RuntimeFunction* runtimeFunction, UnwindInfo* unwindInfo, ulong controlPc, nint context)
|
||||||
{
|
{
|
||||||
int offset = (int)((long)controlPc - context.ToInt64());
|
int offset = (int)((long)controlPc - context.ToInt64());
|
||||||
|
|
||||||
if (!JitCache.TryFind(offset, out CacheEntry funcEntry, out _))
|
if (!jitCache.TryFind(offset, out CacheEntry funcEntry, out _))
|
||||||
{
|
{
|
||||||
return null; // Not found.
|
return null; // Not found.
|
||||||
}
|
}
|
||||||
|
|
||||||
var unwindInfo = funcEntry.UnwindInfo;
|
CodeGen.Unwinding.UnwindInfo funcUnwindInfo = funcEntry.UnwindInfo;
|
||||||
|
|
||||||
int codeIndex = 0;
|
int codeIndex = 0;
|
||||||
|
|
||||||
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
|
for (int index = funcUnwindInfo.PushEntries.Length - 1; index >= 0; index--)
|
||||||
{
|
{
|
||||||
var entry = unwindInfo.PushEntries[index];
|
UnwindPushEntry entry = funcUnwindInfo.PushEntries[index];
|
||||||
|
|
||||||
switch (entry.PseudoOp)
|
switch (entry.PseudoOp)
|
||||||
{
|
{
|
||||||
@@ -140,14 +170,14 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
if (stackOffset <= 0xFFFF0)
|
if (stackOffset <= 0xFFFF0)
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128, entry.PrologOffset, entry.RegIndex);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128, entry.PrologOffset, entry.RegIndex);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -161,18 +191,18 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
if (allocSize <= 128)
|
if (allocSize <= 128)
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
|
||||||
}
|
}
|
||||||
else if (allocSize <= 0x7FFF8)
|
else if (allocSize <= 0x7FFF8)
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
|
unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -180,7 +210,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
case UnwindPseudoOp.PushReg:
|
case UnwindPseudoOp.PushReg:
|
||||||
{
|
{
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.PushNonvol, entry.PrologOffset, entry.RegIndex);
|
unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.PushNonvol, entry.PrologOffset, entry.RegIndex);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -192,16 +222,16 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
Debug.Assert(codeIndex <= MaxUnwindCodesArraySize);
|
Debug.Assert(codeIndex <= MaxUnwindCodesArraySize);
|
||||||
|
|
||||||
_unwindInfo->VersionAndFlags = 1; // Flags: The function has no handler.
|
unwindInfo->VersionAndFlags = 1; // Flags: The function has no handler.
|
||||||
_unwindInfo->SizeOfProlog = (byte)unwindInfo.PrologSize;
|
unwindInfo->SizeOfProlog = (byte)funcUnwindInfo.PrologSize;
|
||||||
_unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
|
unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
|
||||||
_unwindInfo->FrameRegister = 0;
|
unwindInfo->FrameRegister = 0;
|
||||||
|
|
||||||
_runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
|
runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
|
||||||
_runtimeFunction->EndAddress = (uint)(funcEntry.Offset + funcEntry.Size);
|
runtimeFunction->EndAddress = (uint)(funcEntry.Offset + funcEntry.Size);
|
||||||
_runtimeFunction->UnwindData = (uint)_sizeOfRuntimeFunction;
|
runtimeFunction->UnwindData = (uint)_sizeOfRuntimeFunction;
|
||||||
|
|
||||||
return _runtimeFunction;
|
return runtimeFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ushort PackUnwindOp(UnwindOp op, int prologOffset, int opInfo)
|
private static ushort PackUnwindOp(UnwindOp op, int prologOffset, int opInfo)
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
RemoveUnreachableBlocks(Blocks);
|
RemoveUnreachableBlocks(Blocks);
|
||||||
|
|
||||||
var visited = new HashSet<BasicBlock>();
|
HashSet<BasicBlock> visited = new();
|
||||||
var blockStack = new Stack<BasicBlock>();
|
Stack<BasicBlock> blockStack = new();
|
||||||
|
|
||||||
Array.Resize(ref _postOrderBlocks, Blocks.Count);
|
Array.Resize(ref _postOrderBlocks, Blocks.Count);
|
||||||
Array.Resize(ref _postOrderMap, Blocks.Count);
|
Array.Resize(ref _postOrderMap, Blocks.Count);
|
||||||
@@ -88,8 +88,8 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
|
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
|
||||||
{
|
{
|
||||||
var visited = new HashSet<BasicBlock>();
|
HashSet<BasicBlock> visited = new();
|
||||||
var workQueue = new Queue<BasicBlock>();
|
Queue<BasicBlock> workQueue = new();
|
||||||
|
|
||||||
visited.Add(Entry);
|
visited.Add(Entry);
|
||||||
workQueue.Enqueue(Entry);
|
workQueue.Enqueue(Entry);
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
class DelegateInfo
|
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 nint FuncPtr { get; }
|
public nint FuncPtr { get; }
|
||||||
|
|
||||||
public DelegateInfo(nint funcPtr)
|
public DelegateInfo(Delegate dlg, nint funcPtr)
|
||||||
{
|
{
|
||||||
|
_dlg = dlg;
|
||||||
FuncPtr = funcPtr;
|
FuncPtr = funcPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using ARMeilleure.Instructions;
|
using ARMeilleure.Instructions;
|
||||||
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
@@ -33,6 +35,20 @@ namespace ARMeilleure.Translation
|
|||||||
return _delegates.Values[index].FuncPtr; // O(1).
|
return _delegates.Values[index].FuncPtr; // O(1).
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetDelegateFuncPtr(MethodInfo info)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(info);
|
||||||
|
|
||||||
|
string key = GetKey(info);
|
||||||
|
|
||||||
|
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo)) // O(log(n)).
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException($"({nameof(key)} = {key})");
|
||||||
|
}
|
||||||
|
|
||||||
|
return dlgInfo.FuncPtr;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetDelegateIndex(MethodInfo info)
|
public static int GetDelegateIndex(MethodInfo info)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(info);
|
ArgumentNullException.ThrowIfNull(info);
|
||||||
@@ -49,11 +65,11 @@ namespace ARMeilleure.Translation
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetDelegateInfo(MethodInfo method)
|
private static void SetDelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||||
{
|
{
|
||||||
string key = GetKey(method);
|
string key = GetKey(dlg.Method);
|
||||||
|
|
||||||
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer())); // ArgumentException (key).
|
_delegates.Add(key, new DelegateInfo(dlg, funcPtr)); // ArgumentException (key).
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetKey(MethodInfo info)
|
private static string GetKey(MethodInfo info)
|
||||||
@@ -63,183 +79,532 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
private static readonly SortedList<string, DelegateInfo> _delegates;
|
private static readonly SortedList<string, DelegateInfo> _delegates;
|
||||||
|
|
||||||
unsafe static Delegates()
|
static Delegates()
|
||||||
{
|
{
|
||||||
_delegates = new SortedList<string, DelegateInfo>();
|
_delegates = new SortedList<string, DelegateInfo>();
|
||||||
|
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
|
var dlgMathAbs = new MathAbs(Math.Abs);
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
|
var dlgMathCeiling = new MathCeiling(Math.Ceiling);
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
|
var dlgMathFloor = new MathFloor(Math.Floor);
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Round)));
|
var dlgMathRound = new MathRound(Math.Round);
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Truncate)));
|
var dlgMathTruncate = new MathTruncate(Math.Truncate);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Abs)));
|
var dlgMathFAbs = new MathFAbs(MathF.Abs);
|
||||||
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Ceiling)));
|
var dlgMathFCeiling = new MathFCeiling(MathF.Ceiling);
|
||||||
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Floor)));
|
var dlgMathFFloor = new MathFFloor(MathF.Floor);
|
||||||
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Round)));
|
var dlgMathFRound = new MathFRound(MathF.Round);
|
||||||
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Truncate)));
|
var dlgMathFTruncate = new MathFTruncate(MathF.Truncate);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Break)));
|
var dlgNativeInterfaceBreak = new NativeInterfaceBreak(NativeInterface.Break);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
|
var dlgNativeInterfaceCheckSynchronization = new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)));
|
var dlgNativeInterfaceEnqueueForRejit = new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)));
|
var dlgNativeInterfaceGetCntfrqEl0 = new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)));
|
var dlgNativeInterfaceGetCntpctEl0 = new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
var dlgNativeInterfaceGetCntvctEl0 = new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
var dlgNativeInterfaceGetCtrEl0 = new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
var dlgNativeInterfaceGetDczidEl0 = new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
var dlgNativeInterfaceGetFunctionAddress = new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
var dlgNativeInterfaceInvalidateCacheLine = new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
|
var dlgNativeInterfaceReadByte = new NativeInterfaceReadByte(NativeInterface.ReadByte);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
|
var dlgNativeInterfaceReadUInt16 = new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
var dlgNativeInterfaceReadUInt32 = new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
var dlgNativeInterfaceReadUInt64 = new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
var dlgNativeInterfaceReadVector128 = new NativeInterfaceReadVector128(NativeInterface.ReadVector128);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
var dlgNativeInterfaceSignalMemoryTracking = new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
|
var dlgNativeInterfaceSupervisorCall = new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
|
var dlgNativeInterfaceThrowInvalidMemoryAccess = new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)));
|
var dlgNativeInterfaceUndefined = new NativeInterfaceUndefined(NativeInterface.Undefined);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)));
|
var dlgNativeInterfaceWriteByte = new NativeInterfaceWriteByte(NativeInterface.WriteByte);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)));
|
var dlgNativeInterfaceWriteUInt16 = new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)));
|
var dlgNativeInterfaceWriteUInt32 = new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
|
var dlgNativeInterfaceWriteUInt64 = new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64);
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
|
var dlgNativeInterfaceWriteVector128 = new NativeInterfaceWriteVector128(NativeInterface.WriteVector128);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
|
var dlgSoftFallbackCountLeadingSigns = new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
|
var dlgSoftFallbackCountLeadingZeros = new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
|
var dlgSoftFallbackCrc32b = new SoftFallbackCrc32b(SoftFallback.Crc32b);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cb)));
|
var dlgSoftFallbackCrc32cb = new SoftFallbackCrc32cb(SoftFallback.Crc32cb);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32ch)));
|
var dlgSoftFallbackCrc32ch = new SoftFallbackCrc32ch(SoftFallback.Crc32ch);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cw)));
|
var dlgSoftFallbackCrc32cw = new SoftFallbackCrc32cw(SoftFallback.Crc32cw);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cx)));
|
var dlgSoftFallbackCrc32cx = new SoftFallbackCrc32cx(SoftFallback.Crc32cx);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32h)));
|
var dlgSoftFallbackCrc32h = new SoftFallbackCrc32h(SoftFallback.Crc32h);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
var dlgSoftFallbackCrc32w = new SoftFallbackCrc32w(SoftFallback.Crc32w);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
var dlgSoftFallbackCrc32x = new SoftFallbackCrc32x(SoftFallback.Crc32x);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
var dlgSoftFallbackDecrypt = new SoftFallbackDecrypt(SoftFallback.Decrypt);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
var dlgSoftFallbackEncrypt = new SoftFallbackEncrypt(SoftFallback.Encrypt);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
var dlgSoftFallbackFixedRotate = new SoftFallbackFixedRotate(SoftFallback.FixedRotate);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
var dlgSoftFallbackHashChoose = new SoftFallbackHashChoose(SoftFallback.HashChoose);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
var dlgSoftFallbackHashLower = new SoftFallbackHashLower(SoftFallback.HashLower);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
var dlgSoftFallbackHashMajority = new SoftFallbackHashMajority(SoftFallback.HashMajority);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)));
|
var dlgSoftFallbackHashParity = new SoftFallbackHashParity(SoftFallback.HashParity);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)));
|
var dlgSoftFallbackHashUpper = new SoftFallbackHashUpper(SoftFallback.HashUpper);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
var dlgSoftFallbackInverseMixColumns = new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
var dlgSoftFallbackMixColumns = new SoftFallbackMixColumns(SoftFallback.MixColumns);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
var dlgSoftFallbackPolynomialMult64_128 = new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
var dlgSoftFallbackSatF32ToS32 = new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
var dlgSoftFallbackSatF32ToS64 = new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
var dlgSoftFallbackSatF32ToU32 = new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64)));
|
var dlgSoftFallbackSatF32ToU64 = new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32)));
|
var dlgSoftFallbackSatF64ToS32 = new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64)));
|
var dlgSoftFallbackSatF64ToS64 = new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32)));
|
var dlgSoftFallbackSatF64ToU32 = new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64)));
|
var dlgSoftFallbackSatF64ToU64 = new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)));
|
var dlgSoftFallbackSha1SchedulePart1 = new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
|
var dlgSoftFallbackSha1SchedulePart2 = new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
|
var dlgSoftFallbackSha256SchedulePart1 = new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
|
var dlgSoftFallbackSha256SchedulePart2 = new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
|
var dlgSoftFallbackSignedShrImm64 = new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
|
var dlgSoftFallbackTbl1 = new SoftFallbackTbl1(SoftFallback.Tbl1);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
|
var dlgSoftFallbackTbl2 = new SoftFallbackTbl2(SoftFallback.Tbl2);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
|
var dlgSoftFallbackTbl3 = new SoftFallbackTbl3(SoftFallback.Tbl3);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)));
|
var dlgSoftFallbackTbl4 = new SoftFallbackTbl4(SoftFallback.Tbl4);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)));
|
var dlgSoftFallbackTbx1 = new SoftFallbackTbx1(SoftFallback.Tbx1);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
|
var dlgSoftFallbackTbx2 = new SoftFallbackTbx2(SoftFallback.Tbx2);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
|
var dlgSoftFallbackTbx3 = new SoftFallbackTbx3(SoftFallback.Tbx3);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
|
var dlgSoftFallbackTbx4 = new SoftFallbackTbx4(SoftFallback.Tbx4);
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
|
var dlgSoftFallbackUnsignedShrImm64 = new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
|
var dlgSoftFloat16_32FPConvert = new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert);
|
||||||
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
|
var dlgSoftFloat16_64FPConvert = new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
|
var dlgSoftFloat32FPAdd = new SoftFloat32FPAdd(SoftFloat32.FPAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
|
var dlgSoftFloat32FPAddFpscr = new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
|
var dlgSoftFloat32FPCompare = new SoftFloat32FPCompare(SoftFloat32.FPCompare);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
|
var dlgSoftFloat32FPCompareEQ = new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
|
var dlgSoftFloat32FPCompareEQFpscr = new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
|
var dlgSoftFloat32FPCompareGE = new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
|
var dlgSoftFloat32FPCompareGEFpscr = new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
|
var dlgSoftFloat32FPCompareGT = new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
|
var dlgSoftFloat32FPCompareGTFpscr = new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
|
var dlgSoftFloat32FPCompareLE = new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
|
var dlgSoftFloat32FPCompareLEFpscr = new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
|
var dlgSoftFloat32FPCompareLT = new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
|
var dlgSoftFloat32FPCompareLTFpscr = new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
|
var dlgSoftFloat32FPDiv = new SoftFloat32FPDiv(SoftFloat32.FPDiv);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
|
var dlgSoftFloat32FPMax = new SoftFloat32FPMax(SoftFloat32.FPMax);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
|
var dlgSoftFloat32FPMaxFpscr = new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
|
var dlgSoftFloat32FPMaxNum = new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
|
var dlgSoftFloat32FPMaxNumFpscr = new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
|
var dlgSoftFloat32FPMin = new SoftFloat32FPMin(SoftFloat32.FPMin);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
|
var dlgSoftFloat32FPMinFpscr = new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
|
var dlgSoftFloat32FPMinNum = new SoftFloat32FPMinNum(SoftFloat32.FPMinNum);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
|
var dlgSoftFloat32FPMinNumFpscr = new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
|
var dlgSoftFloat32FPMul = new SoftFloat32FPMul(SoftFloat32.FPMul);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
|
var dlgSoftFloat32FPMulFpscr = new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
|
var dlgSoftFloat32FPMulAdd = new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
|
var dlgSoftFloat32FPMulAddFpscr = new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
|
var dlgSoftFloat32FPMulSub = new SoftFloat32FPMulSub(SoftFloat32.FPMulSub);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
|
var dlgSoftFloat32FPMulSubFpscr = new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
|
var dlgSoftFloat32FPMulX = new SoftFloat32FPMulX(SoftFloat32.FPMulX);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
|
var dlgSoftFloat32FPNegMulAdd = new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
|
var dlgSoftFloat32FPNegMulSub = new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
|
var dlgSoftFloat32FPRecipEstimate = new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
|
var dlgSoftFloat32FPRecipEstimateFpscr = new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
|
var dlgSoftFloat32FPRecipStep = new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
|
var dlgSoftFloat32FPRecipStepFused = new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
|
var dlgSoftFloat32FPRecpX = new SoftFloat32FPRecpX(SoftFloat32.FPRecpX);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
|
var dlgSoftFloat32FPRSqrtEstimate = new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
|
var dlgSoftFloat32FPRSqrtEstimateFpscr = new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
|
var dlgSoftFloat32FPRSqrtStep = new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
|
var dlgSoftFloat32FPRSqrtStepFused = new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
|
var dlgSoftFloat32FPSqrt = new SoftFloat32FPSqrt(SoftFloat32.FPSqrt);
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
|
var dlgSoftFloat32FPSub = new SoftFloat32FPSub(SoftFloat32.FPSub);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
|
var dlgSoftFloat32_16FPConvert = new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
|
var dlgSoftFloat64FPAdd = new SoftFloat64FPAdd(SoftFloat64.FPAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
|
var dlgSoftFloat64FPAddFpscr = new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
|
var dlgSoftFloat64FPCompare = new SoftFloat64FPCompare(SoftFloat64.FPCompare);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
|
var dlgSoftFloat64FPCompareEQ = new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
|
var dlgSoftFloat64FPCompareEQFpscr = new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
|
var dlgSoftFloat64FPCompareGE = new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
|
var dlgSoftFloat64FPCompareGEFpscr = new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
|
var dlgSoftFloat64FPCompareGT = new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
|
var dlgSoftFloat64FPCompareGTFpscr = new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
|
var dlgSoftFloat64FPCompareLE = new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
|
var dlgSoftFloat64FPCompareLEFpscr = new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
|
var dlgSoftFloat64FPCompareLT = new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
|
var dlgSoftFloat64FPCompareLTFpscr = new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
|
var dlgSoftFloat64FPDiv = new SoftFloat64FPDiv(SoftFloat64.FPDiv);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
|
var dlgSoftFloat64FPMax = new SoftFloat64FPMax(SoftFloat64.FPMax);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
|
var dlgSoftFloat64FPMaxFpscr = new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
|
var dlgSoftFloat64FPMaxNum = new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
|
var dlgSoftFloat64FPMaxNumFpscr = new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
|
var dlgSoftFloat64FPMin = new SoftFloat64FPMin(SoftFloat64.FPMin);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
|
var dlgSoftFloat64FPMinFpscr = new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
|
var dlgSoftFloat64FPMinNum = new SoftFloat64FPMinNum(SoftFloat64.FPMinNum);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
|
var dlgSoftFloat64FPMinNumFpscr = new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
|
var dlgSoftFloat64FPMul = new SoftFloat64FPMul(SoftFloat64.FPMul);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
|
var dlgSoftFloat64FPMulFpscr = new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
|
var dlgSoftFloat64FPMulAdd = new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
|
var dlgSoftFloat64FPMulAddFpscr = new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
|
var dlgSoftFloat64FPMulSub = new SoftFloat64FPMulSub(SoftFloat64.FPMulSub);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
|
var dlgSoftFloat64FPMulSubFpscr = new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
|
var dlgSoftFloat64FPMulX = new SoftFloat64FPMulX(SoftFloat64.FPMulX);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
|
var dlgSoftFloat64FPNegMulAdd = new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
|
var dlgSoftFloat64FPNegMulSub = new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
|
var dlgSoftFloat64FPRecipEstimate = new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
|
var dlgSoftFloat64FPRecipEstimateFpscr = new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
|
var dlgSoftFloat64FPRecipStep = new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
|
var dlgSoftFloat64FPRecipStepFused = new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
|
var dlgSoftFloat64FPRecpX = new SoftFloat64FPRecpX(SoftFloat64.FPRecpX);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
|
var dlgSoftFloat64FPRSqrtEstimate = new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
|
var dlgSoftFloat64FPRSqrtEstimateFpscr = new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
|
var dlgSoftFloat64FPRSqrtStep = new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
|
var dlgSoftFloat64FPRSqrtStepFused = new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
|
var dlgSoftFloat64FPSqrt = new SoftFloat64FPSqrt(SoftFloat64.FPSqrt);
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
|
var dlgSoftFloat64FPSub = new SoftFloat64FPSub(SoftFloat64.FPSub);
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)));
|
var dlgSoftFloat64_16FPConvert = new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert);
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgMathAbs, Marshal.GetFunctionPointerForDelegate<MathAbs>(dlgMathAbs));
|
||||||
|
SetDelegateInfo(dlgMathCeiling, Marshal.GetFunctionPointerForDelegate<MathCeiling>(dlgMathCeiling));
|
||||||
|
SetDelegateInfo(dlgMathFloor, Marshal.GetFunctionPointerForDelegate<MathFloor>(dlgMathFloor));
|
||||||
|
SetDelegateInfo(dlgMathRound, Marshal.GetFunctionPointerForDelegate<MathRound>(dlgMathRound));
|
||||||
|
SetDelegateInfo(dlgMathTruncate, Marshal.GetFunctionPointerForDelegate<MathTruncate>(dlgMathTruncate));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgMathFAbs, Marshal.GetFunctionPointerForDelegate<MathFAbs>(dlgMathFAbs));
|
||||||
|
SetDelegateInfo(dlgMathFCeiling, Marshal.GetFunctionPointerForDelegate<MathFCeiling>(dlgMathFCeiling));
|
||||||
|
SetDelegateInfo(dlgMathFFloor, Marshal.GetFunctionPointerForDelegate<MathFFloor>(dlgMathFFloor));
|
||||||
|
SetDelegateInfo(dlgMathFRound, Marshal.GetFunctionPointerForDelegate<MathFRound>(dlgMathFRound));
|
||||||
|
SetDelegateInfo(dlgMathFTruncate, Marshal.GetFunctionPointerForDelegate<MathFTruncate>(dlgMathFTruncate));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceBreak, Marshal.GetFunctionPointerForDelegate<NativeInterfaceBreak>(dlgNativeInterfaceBreak));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceCheckSynchronization, Marshal.GetFunctionPointerForDelegate<NativeInterfaceCheckSynchronization>(dlgNativeInterfaceCheckSynchronization));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceEnqueueForRejit, Marshal.GetFunctionPointerForDelegate<NativeInterfaceEnqueueForRejit>(dlgNativeInterfaceEnqueueForRejit));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntfrqEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntfrqEl0>(dlgNativeInterfaceGetCntfrqEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntpctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntpctEl0>(dlgNativeInterfaceGetCntpctEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntvctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntvctEl0>(dlgNativeInterfaceGetCntvctEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCtrEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCtrEl0>(dlgNativeInterfaceGetCtrEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetDczidEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetDczidEl0>(dlgNativeInterfaceGetDczidEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetFunctionAddress, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetFunctionAddress>(dlgNativeInterfaceGetFunctionAddress));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceInvalidateCacheLine, Marshal.GetFunctionPointerForDelegate<NativeInterfaceInvalidateCacheLine>(dlgNativeInterfaceInvalidateCacheLine));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadByte>(dlgNativeInterfaceReadByte));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt16>(dlgNativeInterfaceReadUInt16));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt32>(dlgNativeInterfaceReadUInt32));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt64>(dlgNativeInterfaceReadUInt64));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadVector128>(dlgNativeInterfaceReadVector128));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceSignalMemoryTracking, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSignalMemoryTracking>(dlgNativeInterfaceSignalMemoryTracking));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceSupervisorCall, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSupervisorCall>(dlgNativeInterfaceSupervisorCall));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceThrowInvalidMemoryAccess, Marshal.GetFunctionPointerForDelegate<NativeInterfaceThrowInvalidMemoryAccess>(dlgNativeInterfaceThrowInvalidMemoryAccess));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceUndefined, Marshal.GetFunctionPointerForDelegate<NativeInterfaceUndefined>(dlgNativeInterfaceUndefined));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteByte>(dlgNativeInterfaceWriteByte));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt16>(dlgNativeInterfaceWriteUInt16));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt32>(dlgNativeInterfaceWriteUInt32));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt64>(dlgNativeInterfaceWriteUInt64));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteVector128>(dlgNativeInterfaceWriteVector128));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCountLeadingSigns, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingSigns>(dlgSoftFallbackCountLeadingSigns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCountLeadingZeros, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingZeros>(dlgSoftFallbackCountLeadingZeros));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32b, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32b>(dlgSoftFallbackCrc32b));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cb, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cb>(dlgSoftFallbackCrc32cb));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32ch, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32ch>(dlgSoftFallbackCrc32ch));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cw, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cw>(dlgSoftFallbackCrc32cw));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cx, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cx>(dlgSoftFallbackCrc32cx));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32h, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32h>(dlgSoftFallbackCrc32h));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32w, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32w>(dlgSoftFallbackCrc32w));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32x, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32x>(dlgSoftFallbackCrc32x));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackDecrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackDecrypt>(dlgSoftFallbackDecrypt));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackEncrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackEncrypt>(dlgSoftFallbackEncrypt));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackFixedRotate, Marshal.GetFunctionPointerForDelegate<SoftFallbackFixedRotate>(dlgSoftFallbackFixedRotate));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashChoose, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashChoose>(dlgSoftFallbackHashChoose));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashLower, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashLower>(dlgSoftFallbackHashLower));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashMajority, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashMajority>(dlgSoftFallbackHashMajority));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashParity, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashParity>(dlgSoftFallbackHashParity));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashUpper, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashUpper>(dlgSoftFallbackHashUpper));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackInverseMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackInverseMixColumns>(dlgSoftFallbackInverseMixColumns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackMixColumns>(dlgSoftFallbackMixColumns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackPolynomialMult64_128, Marshal.GetFunctionPointerForDelegate<SoftFallbackPolynomialMult64_128>(dlgSoftFallbackPolynomialMult64_128));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS32>(dlgSoftFallbackSatF32ToS32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS64>(dlgSoftFallbackSatF32ToS64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU32>(dlgSoftFallbackSatF32ToU32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU64>(dlgSoftFallbackSatF32ToU64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS32>(dlgSoftFallbackSatF64ToS32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS64>(dlgSoftFallbackSatF64ToS64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU32>(dlgSoftFallbackSatF64ToU32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU64>(dlgSoftFallbackSatF64ToU64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart1>(dlgSoftFallbackSha1SchedulePart1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart2>(dlgSoftFallbackSha1SchedulePart2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart1>(dlgSoftFallbackSha256SchedulePart1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart2>(dlgSoftFallbackSha256SchedulePart2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSignedShrImm64>(dlgSoftFallbackSignedShrImm64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl1>(dlgSoftFallbackTbl1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl2>(dlgSoftFallbackTbl2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl3>(dlgSoftFallbackTbl3));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl4>(dlgSoftFallbackTbl4));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx1>(dlgSoftFallbackTbx1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx2>(dlgSoftFallbackTbx2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx3>(dlgSoftFallbackTbx3));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx4>(dlgSoftFallbackTbx4));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackUnsignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackUnsignedShrImm64>(dlgSoftFallbackUnsignedShrImm64));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat16_32FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_32FPConvert>(dlgSoftFloat16_32FPConvert));
|
||||||
|
SetDelegateInfo(dlgSoftFloat16_64FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_64FPConvert>(dlgSoftFloat16_64FPConvert));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAdd>(dlgSoftFloat32FPAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAddFpscr>(dlgSoftFloat32FPAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompare>(dlgSoftFloat32FPCompare));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQ>(dlgSoftFloat32FPCompareEQ));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQFpscr>(dlgSoftFloat32FPCompareEQFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGE>(dlgSoftFloat32FPCompareGE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGEFpscr>(dlgSoftFloat32FPCompareGEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGT>(dlgSoftFloat32FPCompareGT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGTFpscr>(dlgSoftFloat32FPCompareGTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLE>(dlgSoftFloat32FPCompareLE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLEFpscr>(dlgSoftFloat32FPCompareLEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLT>(dlgSoftFloat32FPCompareLT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLTFpscr>(dlgSoftFloat32FPCompareLTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPDiv>(dlgSoftFloat32FPDiv));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMax>(dlgSoftFloat32FPMax));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxFpscr>(dlgSoftFloat32FPMaxFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNum>(dlgSoftFloat32FPMaxNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNumFpscr>(dlgSoftFloat32FPMaxNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMin>(dlgSoftFloat32FPMin));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinFpscr>(dlgSoftFloat32FPMinFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNum>(dlgSoftFloat32FPMinNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNumFpscr>(dlgSoftFloat32FPMinNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMul>(dlgSoftFloat32FPMul));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulFpscr>(dlgSoftFloat32FPMulFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAdd>(dlgSoftFloat32FPMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAddFpscr>(dlgSoftFloat32FPMulAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSub>(dlgSoftFloat32FPMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSubFpscr>(dlgSoftFloat32FPMulSubFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulX>(dlgSoftFloat32FPMulX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulAdd>(dlgSoftFloat32FPNegMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulSub>(dlgSoftFloat32FPNegMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimate>(dlgSoftFloat32FPRecipEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimateFpscr>(dlgSoftFloat32FPRecipEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStep>(dlgSoftFloat32FPRecipStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStepFused>(dlgSoftFloat32FPRecipStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecpX>(dlgSoftFloat32FPRecpX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimate>(dlgSoftFloat32FPRSqrtEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimateFpscr>(dlgSoftFloat32FPRSqrtEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStep>(dlgSoftFloat32FPRSqrtStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStepFused>(dlgSoftFloat32FPRSqrtStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSqrt>(dlgSoftFloat32FPSqrt));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSub>(dlgSoftFloat32FPSub));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat32_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat32_16FPConvert>(dlgSoftFloat32_16FPConvert));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAdd>(dlgSoftFloat64FPAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAddFpscr>(dlgSoftFloat64FPAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompare>(dlgSoftFloat64FPCompare));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQ>(dlgSoftFloat64FPCompareEQ));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQFpscr>(dlgSoftFloat64FPCompareEQFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGE>(dlgSoftFloat64FPCompareGE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGEFpscr>(dlgSoftFloat64FPCompareGEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGT>(dlgSoftFloat64FPCompareGT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGTFpscr>(dlgSoftFloat64FPCompareGTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLE>(dlgSoftFloat64FPCompareLE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLEFpscr>(dlgSoftFloat64FPCompareLEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLT>(dlgSoftFloat64FPCompareLT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLTFpscr>(dlgSoftFloat64FPCompareLTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPDiv>(dlgSoftFloat64FPDiv));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMax>(dlgSoftFloat64FPMax));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxFpscr>(dlgSoftFloat64FPMaxFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNum>(dlgSoftFloat64FPMaxNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNumFpscr>(dlgSoftFloat64FPMaxNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMin>(dlgSoftFloat64FPMin));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinFpscr>(dlgSoftFloat64FPMinFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNum>(dlgSoftFloat64FPMinNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNumFpscr>(dlgSoftFloat64FPMinNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMul>(dlgSoftFloat64FPMul));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulFpscr>(dlgSoftFloat64FPMulFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAdd>(dlgSoftFloat64FPMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAddFpscr>(dlgSoftFloat64FPMulAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSub>(dlgSoftFloat64FPMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSubFpscr>(dlgSoftFloat64FPMulSubFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulX>(dlgSoftFloat64FPMulX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulAdd>(dlgSoftFloat64FPNegMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulSub>(dlgSoftFloat64FPNegMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimate>(dlgSoftFloat64FPRecipEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimateFpscr>(dlgSoftFloat64FPRecipEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStep>(dlgSoftFloat64FPRecipStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStepFused>(dlgSoftFloat64FPRecipStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecpX>(dlgSoftFloat64FPRecpX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimate>(dlgSoftFloat64FPRSqrtEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimateFpscr>(dlgSoftFloat64FPRSqrtEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStep>(dlgSoftFloat64FPRSqrtStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStepFused>(dlgSoftFloat64FPRSqrtStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSqrt>(dlgSoftFloat64FPSqrt));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSub>(dlgSoftFloat64FPSub));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat64_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat64_16FPConvert>(dlgSoftFloat64_16FPConvert));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private delegate double MathAbs(double value);
|
||||||
|
private delegate double MathCeiling(double a);
|
||||||
|
private delegate double MathFloor(double d);
|
||||||
|
private delegate double MathRound(double value, MidpointRounding mode);
|
||||||
|
private delegate double MathTruncate(double d);
|
||||||
|
|
||||||
|
private delegate float MathFAbs(float x);
|
||||||
|
private delegate float MathFCeiling(float x);
|
||||||
|
private delegate float MathFFloor(float x);
|
||||||
|
private delegate float MathFRound(float x, MidpointRounding mode);
|
||||||
|
private delegate float MathFTruncate(float x);
|
||||||
|
|
||||||
|
private delegate void NativeInterfaceBreak(ulong address, int imm);
|
||||||
|
private delegate bool NativeInterfaceCheckSynchronization();
|
||||||
|
private delegate void NativeInterfaceEnqueueForRejit(ulong address);
|
||||||
|
private delegate ulong NativeInterfaceGetCntfrqEl0();
|
||||||
|
private delegate ulong NativeInterfaceGetCntpctEl0();
|
||||||
|
private delegate ulong NativeInterfaceGetCntvctEl0();
|
||||||
|
private delegate ulong NativeInterfaceGetCtrEl0();
|
||||||
|
private delegate ulong NativeInterfaceGetDczidEl0();
|
||||||
|
private delegate ulong NativeInterfaceGetFunctionAddress(ulong address);
|
||||||
|
private delegate void NativeInterfaceInvalidateCacheLine(ulong address);
|
||||||
|
private delegate byte NativeInterfaceReadByte(ulong address);
|
||||||
|
private delegate ushort NativeInterfaceReadUInt16(ulong address);
|
||||||
|
private delegate uint NativeInterfaceReadUInt32(ulong address);
|
||||||
|
private delegate ulong NativeInterfaceReadUInt64(ulong address);
|
||||||
|
private delegate V128 NativeInterfaceReadVector128(ulong address);
|
||||||
|
private delegate void NativeInterfaceSignalMemoryTracking(ulong address, ulong size, bool write);
|
||||||
|
private delegate void NativeInterfaceSupervisorCall(ulong address, int imm);
|
||||||
|
private delegate void NativeInterfaceThrowInvalidMemoryAccess(ulong address);
|
||||||
|
private delegate void NativeInterfaceUndefined(ulong address, int opCode);
|
||||||
|
private delegate void NativeInterfaceWriteByte(ulong address, byte value);
|
||||||
|
private delegate void NativeInterfaceWriteUInt16(ulong address, ushort value);
|
||||||
|
private delegate void NativeInterfaceWriteUInt32(ulong address, uint value);
|
||||||
|
private delegate void NativeInterfaceWriteUInt64(ulong address, ulong value);
|
||||||
|
private delegate void NativeInterfaceWriteVector128(ulong address, V128 value);
|
||||||
|
|
||||||
|
private delegate ulong SoftFallbackCountLeadingSigns(ulong value, int size);
|
||||||
|
private delegate ulong SoftFallbackCountLeadingZeros(ulong value, int size);
|
||||||
|
private delegate uint SoftFallbackCrc32b(uint crc, byte value);
|
||||||
|
private delegate uint SoftFallbackCrc32cb(uint crc, byte value);
|
||||||
|
private delegate uint SoftFallbackCrc32ch(uint crc, ushort value);
|
||||||
|
private delegate uint SoftFallbackCrc32cw(uint crc, uint value);
|
||||||
|
private delegate uint SoftFallbackCrc32cx(uint crc, ulong value);
|
||||||
|
private delegate uint SoftFallbackCrc32h(uint crc, ushort value);
|
||||||
|
private delegate uint SoftFallbackCrc32w(uint crc, uint value);
|
||||||
|
private delegate uint SoftFallbackCrc32x(uint crc, ulong value);
|
||||||
|
private delegate V128 SoftFallbackDecrypt(V128 value, V128 roundKey);
|
||||||
|
private delegate V128 SoftFallbackEncrypt(V128 value, V128 roundKey);
|
||||||
|
private delegate uint SoftFallbackFixedRotate(uint hash_e);
|
||||||
|
private delegate V128 SoftFallbackHashChoose(V128 hash_abcd, uint hash_e, V128 wk);
|
||||||
|
private delegate V128 SoftFallbackHashLower(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
||||||
|
private delegate V128 SoftFallbackHashMajority(V128 hash_abcd, uint hash_e, V128 wk);
|
||||||
|
private delegate V128 SoftFallbackHashParity(V128 hash_abcd, uint hash_e, V128 wk);
|
||||||
|
private delegate V128 SoftFallbackHashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
||||||
|
private delegate V128 SoftFallbackInverseMixColumns(V128 value);
|
||||||
|
private delegate V128 SoftFallbackMixColumns(V128 value);
|
||||||
|
private delegate V128 SoftFallbackPolynomialMult64_128(ulong op1, ulong op2);
|
||||||
|
private delegate int SoftFallbackSatF32ToS32(float value);
|
||||||
|
private delegate long SoftFallbackSatF32ToS64(float value);
|
||||||
|
private delegate uint SoftFallbackSatF32ToU32(float value);
|
||||||
|
private delegate ulong SoftFallbackSatF32ToU64(float value);
|
||||||
|
private delegate int SoftFallbackSatF64ToS32(double value);
|
||||||
|
private delegate long SoftFallbackSatF64ToS64(double value);
|
||||||
|
private delegate uint SoftFallbackSatF64ToU32(double value);
|
||||||
|
private delegate ulong SoftFallbackSatF64ToU64(double value);
|
||||||
|
private delegate V128 SoftFallbackSha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11);
|
||||||
|
private delegate V128 SoftFallbackSha1SchedulePart2(V128 tw0_3, V128 w12_15);
|
||||||
|
private delegate V128 SoftFallbackSha256SchedulePart1(V128 w0_3, V128 w4_7);
|
||||||
|
private delegate V128 SoftFallbackSha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15);
|
||||||
|
private delegate long SoftFallbackSignedShrImm64(long value, long roundConst, int shift);
|
||||||
|
private delegate V128 SoftFallbackTbl1(V128 vector, int bytes, V128 tb0);
|
||||||
|
private delegate V128 SoftFallbackTbl2(V128 vector, int bytes, V128 tb0, V128 tb1);
|
||||||
|
private delegate V128 SoftFallbackTbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
|
||||||
|
private delegate V128 SoftFallbackTbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
|
||||||
|
private delegate V128 SoftFallbackTbx1(V128 dest, V128 vector, int bytes, V128 tb0);
|
||||||
|
private delegate V128 SoftFallbackTbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1);
|
||||||
|
private delegate V128 SoftFallbackTbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
|
||||||
|
private delegate V128 SoftFallbackTbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
|
||||||
|
private delegate ulong SoftFallbackUnsignedShrImm64(ulong value, long roundConst, int shift);
|
||||||
|
|
||||||
|
private delegate float SoftFloat16_32FPConvert(ushort valueBits);
|
||||||
|
|
||||||
|
private delegate double SoftFloat16_64FPConvert(ushort valueBits);
|
||||||
|
|
||||||
|
private delegate float SoftFloat32FPAdd(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPAddFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate int SoftFloat32FPCompare(float value1, float value2, bool signalNaNs);
|
||||||
|
private delegate float SoftFloat32FPCompareEQ(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPCompareEQFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPCompareGE(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPCompareGEFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPCompareGT(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPCompareGTFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPCompareLE(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPCompareLEFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPCompareLT(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPCompareLTFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPDiv(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMax(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMaxFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMaxNum(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMaxNumFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMin(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMinFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMinNum(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMinNumFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMul(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMulFpscr(float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMulAdd(float valueA, float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMulSub(float valueA, float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPMulX(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPNegMulAdd(float valueA, float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPNegMulSub(float valueA, float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPRecipEstimate(float value);
|
||||||
|
private delegate float SoftFloat32FPRecipEstimateFpscr(float value, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPRecipStep(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPRecipStepFused(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPRecpX(float value);
|
||||||
|
private delegate float SoftFloat32FPRSqrtEstimate(float value);
|
||||||
|
private delegate float SoftFloat32FPRSqrtEstimateFpscr(float value, bool standardFpscr);
|
||||||
|
private delegate float SoftFloat32FPRSqrtStep(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPRSqrtStepFused(float value1, float value2);
|
||||||
|
private delegate float SoftFloat32FPSqrt(float value);
|
||||||
|
private delegate float SoftFloat32FPSub(float value1, float value2);
|
||||||
|
|
||||||
|
private delegate ushort SoftFloat32_16FPConvert(float value);
|
||||||
|
|
||||||
|
private delegate double SoftFloat64FPAdd(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPAddFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate int SoftFloat64FPCompare(double value1, double value2, bool signalNaNs);
|
||||||
|
private delegate double SoftFloat64FPCompareEQ(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPCompareEQFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPCompareGE(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPCompareGEFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPCompareGT(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPCompareGTFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPCompareLE(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPCompareLEFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPCompareLT(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPCompareLTFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPDiv(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMax(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMaxFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMaxNum(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMaxNumFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMin(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMinFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMinNum(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMinNumFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMul(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMulFpscr(double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMulAdd(double valueA, double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMulSub(double valueA, double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPMulX(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPNegMulAdd(double valueA, double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPNegMulSub(double valueA, double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPRecipEstimate(double value);
|
||||||
|
private delegate double SoftFloat64FPRecipEstimateFpscr(double value, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPRecipStep(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPRecipStepFused(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPRecpX(double value);
|
||||||
|
private delegate double SoftFloat64FPRSqrtEstimate(double value);
|
||||||
|
private delegate double SoftFloat64FPRSqrtEstimateFpscr(double value, bool standardFpscr);
|
||||||
|
private delegate double SoftFloat64FPRSqrtStep(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPRSqrtStepFused(double value1, double value2);
|
||||||
|
private delegate double SoftFloat64FPSqrt(double value);
|
||||||
|
private delegate double SoftFloat64FPSub(double value1, double value2);
|
||||||
|
|
||||||
|
private delegate ushort SoftFloat64_16FPConvert(double value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||||
{
|
{
|
||||||
nint funcPtr = info.MethodHandle.GetFunctionPointer();
|
nint funcPtr = Delegates.GetDelegateFuncPtr(info);
|
||||||
|
|
||||||
OperandType returnType = GetOperandType(info.ReturnType);
|
OperandType returnType = GetOperandType(info.ReturnType);
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ using ARMeilleure.CodeGen.Unwinding;
|
|||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using ARMeilleure.Translation.Cache;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -30,14 +32,11 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 7031; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
|
||||||
private const string TitleIdTextDefault = "0000000000000000";
|
|
||||||
private const string DisplayVersionDefault = "0";
|
|
||||||
|
|
||||||
public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
|
public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
|
||||||
public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
|
public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
|
||||||
public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
|
public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
|
||||||
@@ -48,6 +47,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public PtcProfiler Profiler { get; }
|
public PtcProfiler Profiler { get; }
|
||||||
|
|
||||||
|
private readonly JitCache _jitCache;
|
||||||
|
|
||||||
// Carriers.
|
// Carriers.
|
||||||
private MemoryStream _infosStream;
|
private MemoryStream _infosStream;
|
||||||
private List<byte[]> _codesList;
|
private List<byte[]> _codesList;
|
||||||
@@ -63,8 +64,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public string TitleIdText { get; private set; }
|
public PtcCacheInfo CacheInfo { get; private set; }
|
||||||
public string DisplayVersion { get; private set; }
|
|
||||||
|
|
||||||
private MemoryManagerType _memoryMode;
|
private MemoryManagerType _memoryMode;
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private volatile int _translateTotalCount;
|
private volatile int _translateTotalCount;
|
||||||
public event Action<PtcLoadingState, int, int> PtcStateChanged;
|
public event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||||
|
|
||||||
public Ptc()
|
public Ptc(JitCache jitCache)
|
||||||
{
|
{
|
||||||
Profiler = new PtcProfiler(this);
|
Profiler = new PtcProfiler(this);
|
||||||
|
|
||||||
@@ -89,10 +89,11 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
_waitEvent = new ManualResetEvent(true);
|
_waitEvent = new ManualResetEvent(true);
|
||||||
|
|
||||||
|
_jitCache = jitCache;
|
||||||
|
|
||||||
_disposed = false;
|
_disposed = false;
|
||||||
|
|
||||||
TitleIdText = TitleIdTextDefault;
|
CacheInfo = new PtcCacheInfo(0, null, null, 0, null, "Unknown", "default");
|
||||||
DisplayVersion = DisplayVersionDefault;
|
|
||||||
|
|
||||||
CachePathActual = string.Empty;
|
CachePathActual = string.Empty;
|
||||||
CachePathBackup = string.Empty;
|
CachePathBackup = string.Empty;
|
||||||
@@ -100,20 +101,24 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
Disable();
|
Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode, string cacheSelector)
|
public void Initialize(PtcCacheInfo cacheInfo, bool enabled, MemoryManagerType memoryMode)
|
||||||
{
|
{
|
||||||
Wait();
|
Wait();
|
||||||
|
|
||||||
Profiler.Wait();
|
Profiler.Wait();
|
||||||
Profiler.ClearEntries();
|
Profiler.ClearEntries();
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t (title: {titleIdText}, version: '{displayVersion}', selector: '{cacheSelector}', enabled: {enabled}).");
|
CacheInfo = cacheInfo;
|
||||||
|
|
||||||
if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault)
|
Logger.Info?.Print(
|
||||||
|
LogClass.Ptc,
|
||||||
|
$"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t " +
|
||||||
|
$"(pid: {cacheInfo.ProcessId}, title: {cacheInfo.TitleIdText}, application: {cacheInfo.ApplicationIdText}, " +
|
||||||
|
$"programIndex: {cacheInfo.ProgramIndex}, version: '{cacheInfo.DisplayVersion}', kind: {cacheInfo.ProcessKind}, " +
|
||||||
|
$"selector: '{cacheInfo.CacheSelector}', key: '{cacheInfo.CacheKey}', enabled: {enabled}).");
|
||||||
|
|
||||||
|
if (!enabled || cacheInfo.TitleIdText == PtcCacheInfo.TitleIdTextDefault)
|
||||||
{
|
{
|
||||||
TitleIdText = TitleIdTextDefault;
|
|
||||||
DisplayVersion = DisplayVersionDefault;
|
|
||||||
|
|
||||||
CachePathActual = string.Empty;
|
CachePathActual = string.Empty;
|
||||||
CachePathBackup = string.Empty;
|
CachePathBackup = string.Empty;
|
||||||
|
|
||||||
@@ -122,12 +127,10 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleIdText = titleIdText;
|
|
||||||
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
|
|
||||||
_memoryMode = memoryMode;
|
_memoryMode = memoryMode;
|
||||||
|
|
||||||
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir);
|
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", ActualDir);
|
||||||
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir);
|
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", BackupDir);
|
||||||
|
|
||||||
if (!Directory.Exists(workPathActual))
|
if (!Directory.Exists(workPathActual))
|
||||||
{
|
{
|
||||||
@@ -139,8 +142,14 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
Directory.CreateDirectory(workPathBackup);
|
Directory.CreateDirectory(workPathBackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachePathActual = Path.Combine(workPathActual, DisplayVersion) + "-" + cacheSelector;
|
CachePathActual = Path.Combine(workPathActual, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector;
|
||||||
CachePathBackup = Path.Combine(workPathBackup, DisplayVersion) + "-" + cacheSelector;
|
CachePathBackup = Path.Combine(workPathBackup, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector;
|
||||||
|
|
||||||
|
Logger.Info?.Print(
|
||||||
|
LogClass.Ptc,
|
||||||
|
$"PPTC cache owner selected (pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, application: {CacheInfo.ApplicationIdText}, " +
|
||||||
|
$"version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, selector: '{CacheInfo.CacheSelector}', " +
|
||||||
|
$"key: '{CacheInfo.CacheKey}', path: '{CachePathActual}').");
|
||||||
|
|
||||||
PreLoad();
|
PreLoad();
|
||||||
Profiler.PreLoad();
|
Profiler.PreLoad();
|
||||||
@@ -364,7 +373,12 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
long fileSize = new FileInfo(fileName).Length;
|
long fileSize = new FileInfo(fileName).Length;
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()}).");
|
Logger.Info?.Print(
|
||||||
|
LogClass.Ptc,
|
||||||
|
$"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} " +
|
||||||
|
$"(pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, " +
|
||||||
|
$"selector: '{CacheInfo.CacheSelector}', key: '{CacheInfo.CacheKey}', path: '{fileName}', " +
|
||||||
|
$"size: {fileSize} bytes, translated functions: {GetEntriesCount()}).");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -544,7 +558,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize);
|
bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize);
|
||||||
|
|
||||||
if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq))
|
if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out PtcProfiler.FuncProfile value) && value.HighCq))
|
||||||
{
|
{
|
||||||
infoEntry.Stubbed = true;
|
infoEntry.Stubbed = true;
|
||||||
infoEntry.CodeLength = 0;
|
infoEntry.CodeLength = 0;
|
||||||
@@ -724,15 +738,15 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return new UnwindInfo(pushEntries, prologueSize);
|
return new UnwindInfo(pushEntries, prologueSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TranslatedFunction FastTranslate(
|
private TranslatedFunction FastTranslate(
|
||||||
byte[] code,
|
byte[] code,
|
||||||
Counter<uint> callCounter,
|
Counter<uint> callCounter,
|
||||||
ulong guestSize,
|
ulong guestSize,
|
||||||
UnwindInfo unwindInfo,
|
UnwindInfo unwindInfo,
|
||||||
bool highCq)
|
bool highCq)
|
||||||
{
|
{
|
||||||
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
|
CompiledFunction cFunc = new(code, unwindInfo, RelocInfo.Empty);
|
||||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out nint gFuncPointer);
|
GuestFunction gFunc = cFunc.MapWithPointer<GuestFunction>(_jitCache, out nint gFuncPointer);
|
||||||
|
|
||||||
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
|
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
|
||||||
}
|
}
|
||||||
@@ -769,7 +783,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public void MakeAndSaveTranslations(Translator translator)
|
public void MakeAndSaveTranslations(Translator translator)
|
||||||
{
|
{
|
||||||
var profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions);
|
ConcurrentQueue<(ulong address, PtcProfiler.FuncProfile funcProfile)> profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions);
|
||||||
|
|
||||||
_translateCount = 0;
|
_translateCount = 0;
|
||||||
_translateTotalCount = profiledFuncsToTranslate.Count;
|
_translateTotalCount = profiledFuncsToTranslate.Count;
|
||||||
@@ -813,7 +827,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
void TranslateFuncs()
|
void TranslateFuncs()
|
||||||
{
|
{
|
||||||
while (profiledFuncsToTranslate.TryDequeue(out var item))
|
while (profiledFuncsToTranslate.TryDequeue(out (ulong address, PtcProfiler.FuncProfile funcProfile) item))
|
||||||
{
|
{
|
||||||
ulong address = item.address;
|
ulong address = item.address;
|
||||||
ExecutionMode executionMode = item.funcProfile.Mode;
|
ExecutionMode executionMode = item.funcProfile.Mode;
|
||||||
@@ -858,11 +872,11 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
Stopwatch sw = Stopwatch.StartNew();
|
Stopwatch sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
foreach (var thread in threads)
|
foreach (Thread thread in threads)
|
||||||
{
|
{
|
||||||
thread.Start();
|
thread.Start();
|
||||||
}
|
}
|
||||||
foreach (var thread in threads)
|
foreach (Thread thread in threads)
|
||||||
{
|
{
|
||||||
thread.Join();
|
thread.Join();
|
||||||
}
|
}
|
||||||
@@ -942,7 +956,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
WriteCode(code.AsSpan());
|
WriteCode(code.AsSpan());
|
||||||
|
|
||||||
// WriteReloc.
|
// WriteReloc.
|
||||||
using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true);
|
using BinaryWriter relocInfoWriter = new(_relocsStream, EncodingCache.UTF8NoBOM, true);
|
||||||
|
|
||||||
foreach (RelocEntry entry in relocInfo.Entries)
|
foreach (RelocEntry entry in relocInfo.Entries)
|
||||||
{
|
{
|
||||||
@@ -952,7 +966,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteUnwindInfo.
|
// WriteUnwindInfo.
|
||||||
using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true);
|
using BinaryWriter unwindInfoWriter = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true);
|
||||||
|
|
||||||
unwindInfoWriter.Write(unwindInfo.PushEntries.Length);
|
unwindInfoWriter.Write(unwindInfo.PushEntries.Length);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
namespace ARMeilleure.Translation.PTC
|
||||||
|
{
|
||||||
|
public readonly struct PtcCacheInfo
|
||||||
|
{
|
||||||
|
public const string TitleIdTextDefault = "0000000000000000";
|
||||||
|
public const string ApplicationIdTextDefault = "0000000000000000";
|
||||||
|
public const string DisplayVersionDefault = "0";
|
||||||
|
|
||||||
|
public ulong ProcessId { get; }
|
||||||
|
public string TitleIdText { get; }
|
||||||
|
public string ApplicationIdText { get; }
|
||||||
|
public byte ProgramIndex { get; }
|
||||||
|
public string DisplayVersion { get; }
|
||||||
|
public string ProcessKind { get; }
|
||||||
|
public string CacheSelector { get; }
|
||||||
|
|
||||||
|
public string CacheKey => $"{DisplayVersion}-{CacheSelector}";
|
||||||
|
|
||||||
|
public PtcCacheInfo(
|
||||||
|
ulong processId,
|
||||||
|
string titleIdText,
|
||||||
|
string applicationIdText,
|
||||||
|
byte programIndex,
|
||||||
|
string displayVersion,
|
||||||
|
string processKind,
|
||||||
|
string cacheSelector)
|
||||||
|
{
|
||||||
|
ProcessId = processId;
|
||||||
|
TitleIdText = !string.IsNullOrEmpty(titleIdText) ? titleIdText : TitleIdTextDefault;
|
||||||
|
ApplicationIdText = !string.IsNullOrEmpty(applicationIdText) ? applicationIdText : ApplicationIdTextDefault;
|
||||||
|
ProgramIndex = programIndex;
|
||||||
|
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
|
||||||
|
ProcessKind = processKind ?? string.Empty;
|
||||||
|
CacheSelector = string.IsNullOrEmpty(cacheSelector) ? "default" : cacheSelector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
|
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 6698; //! Not to be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 7031; //! Not to be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private static readonly uint[] _migrateInternalVersions =
|
private static readonly uint[] _migrateInternalVersions =
|
||||||
[
|
[
|
||||||
@@ -119,9 +119,9 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
|
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
|
||||||
{
|
{
|
||||||
var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>();
|
ConcurrentQueue<(ulong address, FuncProfile funcProfile)> profiledFuncsToTranslate = new();
|
||||||
|
|
||||||
foreach (var profiledFunc in ProfiledFuncs)
|
foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
|
||||||
{
|
{
|
||||||
if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
|
if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
|
||||||
{
|
{
|
||||||
@@ -142,7 +142,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
List<ulong> funcs = [];
|
List<ulong> funcs = [];
|
||||||
|
|
||||||
foreach (var profiledFunc in ProfiledFuncs)
|
foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
|
||||||
{
|
{
|
||||||
if (profiledFunc.Value.Blacklist)
|
if (profiledFunc.Value.Blacklist)
|
||||||
{
|
{
|
||||||
@@ -254,7 +254,12 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
long fileSize = new FileInfo(fileName).Length;
|
long fileSize = new FileInfo(fileName).Length;
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count}).");
|
Logger.Info?.Print(
|
||||||
|
LogClass.Ptc,
|
||||||
|
$"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} " +
|
||||||
|
$"(pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " +
|
||||||
|
$"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " +
|
||||||
|
$"path: '{fileName}', size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count}).");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -375,7 +380,11 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
if (fileSize != 0L)
|
if (fileSize != 0L)
|
||||||
{
|
{
|
||||||
Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount}).");
|
Logger.Info?.Print(
|
||||||
|
LogClass.Ptc,
|
||||||
|
$"Saved Profiling Info (pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " +
|
||||||
|
$"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " +
|
||||||
|
$"path: '{fileName}', size: {fileSize} bytes, profiled functions: {profiledFuncsCount}).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public static void Construct(ControlFlowGraph cfg)
|
public static void Construct(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
var globalDefs = new DefMap[cfg.Blocks.Count];
|
DefMap[] globalDefs = new DefMap[cfg.Blocks.Count];
|
||||||
var localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount];
|
Operand[] localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount];
|
||||||
|
|
||||||
var dfPhiBlocks = new Queue<BasicBlock>();
|
Queue<BasicBlock> dfPhiBlocks = new();
|
||||||
|
|
||||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ namespace ARMeilleure.Translation
|
|||||||
private readonly IJitMemoryAllocator _allocator;
|
private readonly IJitMemoryAllocator _allocator;
|
||||||
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
|
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
|
||||||
|
|
||||||
|
public readonly JitCache JitCache;
|
||||||
private readonly Ptc _ptc;
|
private readonly Ptc _ptc;
|
||||||
|
|
||||||
internal TranslatorCache<TranslatedFunction> Functions { get; }
|
internal TranslatorCache<TranslatedFunction> Functions { get; }
|
||||||
internal IAddressTable<ulong> FunctionTable { get; }
|
public IAddressTable<ulong> FunctionTable { get; }
|
||||||
internal EntryTable<uint> CountTable { get; }
|
internal EntryTable<uint> CountTable { get; }
|
||||||
internal TranslatorStubs Stubs { get; }
|
internal TranslatorStubs Stubs { get; }
|
||||||
internal TranslatorQueue Queue { get; }
|
internal TranslatorQueue Queue { get; }
|
||||||
@@ -43,23 +44,26 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
_oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>();
|
_oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>();
|
||||||
|
|
||||||
_ptc = new Ptc();
|
JitCache = new JitCache(allocator);
|
||||||
|
|
||||||
|
_ptc = new Ptc(JitCache);
|
||||||
|
|
||||||
Queue = new TranslatorQueue();
|
Queue = new TranslatorQueue();
|
||||||
|
|
||||||
JitCache.Initialize(allocator);
|
|
||||||
|
|
||||||
CountTable = new EntryTable<uint>();
|
CountTable = new EntryTable<uint>();
|
||||||
Functions = new TranslatorCache<TranslatedFunction>();
|
Functions = new TranslatorCache<TranslatedFunction>();
|
||||||
|
|
||||||
FunctionTable = functionTable;
|
FunctionTable = functionTable;
|
||||||
Stubs = new TranslatorStubs(FunctionTable);
|
|
||||||
|
Stubs = new TranslatorStubs(JitCache, FunctionTable);
|
||||||
|
|
||||||
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
|
public IPtcLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled)
|
||||||
{
|
{
|
||||||
_ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type, cacheSelector);
|
_ptc.Initialize(cacheInfo, enabled, Memory.Type);
|
||||||
return _ptc;
|
return _ptc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,6 +171,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClearJitCache();
|
ClearJitCache();
|
||||||
|
JitCache.Dispose();
|
||||||
|
|
||||||
Stubs.Dispose();
|
Stubs.Dispose();
|
||||||
FunctionTable.Dispose();
|
FunctionTable.Dispose();
|
||||||
@@ -242,7 +247,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
|
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
|
||||||
{
|
{
|
||||||
var context = new ArmEmitterContext(
|
ArmEmitterContext context = new(
|
||||||
Memory,
|
Memory,
|
||||||
CountTable,
|
CountTable,
|
||||||
FunctionTable,
|
FunctionTable,
|
||||||
@@ -286,10 +291,10 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Logger.EndPass(PassName.RegisterUsage);
|
Logger.EndPass(PassName.RegisterUsage);
|
||||||
|
|
||||||
var retType = OperandType.I64;
|
OperandType retType = OperandType.I64;
|
||||||
var argTypes = new OperandType[] { OperandType.I64 };
|
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||||
|
|
||||||
var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
|
CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
|
||||||
|
|
||||||
if (context.HasPtc && !singleStep)
|
if (context.HasPtc && !singleStep)
|
||||||
{
|
{
|
||||||
@@ -305,7 +310,7 @@ namespace ARMeilleure.Translation
|
|||||||
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out nint funcPointer);
|
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(JitCache, out nint funcPointer);
|
||||||
|
|
||||||
Allocators.ResetAll();
|
Allocators.ResetAll();
|
||||||
|
|
||||||
@@ -574,7 +579,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
List<TranslatedFunction> functions = Functions.AsList();
|
List<TranslatedFunction> functions = Functions.AsList();
|
||||||
|
|
||||||
foreach (var func in functions)
|
foreach (TranslatedFunction func in functions)
|
||||||
{
|
{
|
||||||
JitCache.Unmap(func.FuncPointer);
|
JitCache.Unmap(func.FuncPointer);
|
||||||
|
|
||||||
@@ -583,7 +588,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Functions.Clear();
|
Functions.Clear();
|
||||||
|
|
||||||
while (_oldFuncs.TryDequeue(out var kv))
|
while (_oldFuncs.TryDequeue(out KeyValuePair<ulong, TranslatedFunction> kv))
|
||||||
{
|
{
|
||||||
JitCache.Unmap(kv.Value.FuncPointer);
|
JitCache.Unmap(kv.Value.FuncPointer);
|
||||||
|
|
||||||
@@ -604,7 +609,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
|
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
|
||||||
{
|
{
|
||||||
if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null)
|
if (Functions.TryGetValue(request.Address, out TranslatedFunction func) && func.CallCounter != null)
|
||||||
{
|
{
|
||||||
Volatile.Write(ref func.CallCounter.Value, 0);
|
Volatile.Write(ref func.CallCounter.Value, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ namespace ARMeilleure.Translation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class TranslatorStubs : IDisposable
|
class TranslatorStubs : IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly JitCache _jitCache;
|
||||||
|
|
||||||
private readonly Lazy<nint> _slowDispatchStub;
|
private readonly Lazy<nint> _slowDispatchStub;
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
@@ -83,12 +85,15 @@ namespace ARMeilleure.Translation
|
|||||||
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
|
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
|
||||||
/// <see cref="Translator"/> instance.
|
/// <see cref="Translator"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="jitCache">Jit cache to map functions in</param>
|
||||||
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
|
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
|
||||||
public TranslatorStubs(IAddressTable<ulong> functionTable)
|
public TranslatorStubs(JitCache jitCache, IAddressTable<ulong> functionTable)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(functionTable);
|
ArgumentNullException.ThrowIfNull(functionTable);
|
||||||
|
|
||||||
|
_jitCache = jitCache;
|
||||||
|
|
||||||
_functionTable = functionTable;
|
_functionTable = functionTable;
|
||||||
_slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
_slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
||||||
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
|
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
|
||||||
@@ -115,12 +120,12 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
if (_dispatchStub.IsValueCreated)
|
if (_dispatchStub.IsValueCreated)
|
||||||
{
|
{
|
||||||
JitCache.Unmap(_dispatchStub.Value);
|
_jitCache.Unmap(_dispatchStub.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dispatchLoop.IsValueCreated)
|
if (_dispatchLoop.IsValueCreated)
|
||||||
{
|
{
|
||||||
JitCache.Unmap(Marshal.GetFunctionPointerForDelegate(_dispatchLoop.Value));
|
_jitCache.Unmap(Marshal.GetFunctionPointerForDelegate(_dispatchLoop.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
@@ -141,7 +146,7 @@ namespace ARMeilleure.Translation
|
|||||||
/// <returns>Generated <see cref="DispatchStub"/></returns>
|
/// <returns>Generated <see cref="DispatchStub"/></returns>
|
||||||
private nint GenerateDispatchStub()
|
private nint GenerateDispatchStub()
|
||||||
{
|
{
|
||||||
var context = new EmitterContext();
|
EmitterContext context = new();
|
||||||
|
|
||||||
Operand lblFallback = Label();
|
Operand lblFallback = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
@@ -160,7 +165,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
for (int i = 0; i < _functionTable.Levels.Length; i++)
|
for (int i = 0; i < _functionTable.Levels.Length; i++)
|
||||||
{
|
{
|
||||||
ref var level = ref _functionTable.Levels[i];
|
ref AddressTableLevel level = ref _functionTable.Levels[i];
|
||||||
|
|
||||||
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
|
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
|
||||||
// be encoded as an immediate on x86's bitwise and operation.
|
// be encoded as an immediate on x86's bitwise and operation.
|
||||||
@@ -184,11 +189,11 @@ namespace ARMeilleure.Translation
|
|||||||
hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
||||||
context.Tailcall(hostAddress, nativeContext);
|
context.Tailcall(hostAddress, nativeContext);
|
||||||
|
|
||||||
var cfg = context.GetControlFlowGraph();
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
var retType = OperandType.I64;
|
OperandType retType = OperandType.I64;
|
||||||
var argTypes = new[] { OperandType.I64 };
|
OperandType[] argTypes = new[] { OperandType.I64 };
|
||||||
|
|
||||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
|
GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(_jitCache);
|
||||||
|
|
||||||
return Marshal.GetFunctionPointerForDelegate(func);
|
return Marshal.GetFunctionPointerForDelegate(func);
|
||||||
}
|
}
|
||||||
@@ -199,7 +204,7 @@ namespace ARMeilleure.Translation
|
|||||||
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
|
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
|
||||||
private nint GenerateSlowDispatchStub()
|
private nint GenerateSlowDispatchStub()
|
||||||
{
|
{
|
||||||
var context = new EmitterContext();
|
EmitterContext context = new();
|
||||||
|
|
||||||
// Load the target guest address from the native context.
|
// Load the target guest address from the native context.
|
||||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
@@ -209,11 +214,11 @@ namespace ARMeilleure.Translation
|
|||||||
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
||||||
context.Tailcall(hostAddress, nativeContext);
|
context.Tailcall(hostAddress, nativeContext);
|
||||||
|
|
||||||
var cfg = context.GetControlFlowGraph();
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
var retType = OperandType.I64;
|
OperandType retType = OperandType.I64;
|
||||||
var argTypes = new[] { OperandType.I64 };
|
OperandType[] argTypes = new[] { OperandType.I64 };
|
||||||
|
|
||||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
|
GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(_jitCache);
|
||||||
|
|
||||||
return Marshal.GetFunctionPointerForDelegate(func);
|
return Marshal.GetFunctionPointerForDelegate(func);
|
||||||
}
|
}
|
||||||
@@ -250,7 +255,7 @@ namespace ARMeilleure.Translation
|
|||||||
/// <returns><see cref="DispatchLoop"/> function</returns>
|
/// <returns><see cref="DispatchLoop"/> function</returns>
|
||||||
private DispatcherFunction GenerateDispatchLoop()
|
private DispatcherFunction GenerateDispatchLoop()
|
||||||
{
|
{
|
||||||
var context = new EmitterContext();
|
EmitterContext context = new();
|
||||||
|
|
||||||
Operand beginLbl = Label();
|
Operand beginLbl = Label();
|
||||||
Operand endLbl = Label();
|
Operand endLbl = Label();
|
||||||
@@ -286,11 +291,11 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
context.Return();
|
context.Return();
|
||||||
|
|
||||||
var cfg = context.GetControlFlowGraph();
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
var retType = OperandType.None;
|
OperandType retType = OperandType.None;
|
||||||
var argTypes = new[] { OperandType.I64, OperandType.I64 };
|
OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>();
|
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>(_jitCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -299,7 +304,7 @@ namespace ARMeilleure.Translation
|
|||||||
/// <returns><see cref="ContextWrapper"/> function</returns>
|
/// <returns><see cref="ContextWrapper"/> function</returns>
|
||||||
private WrapperFunction GenerateContextWrapper()
|
private WrapperFunction GenerateContextWrapper()
|
||||||
{
|
{
|
||||||
var context = new EmitterContext();
|
EmitterContext context = new();
|
||||||
|
|
||||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
Operand guestMethod = context.LoadArgument(OperandType.I64, 1);
|
Operand guestMethod = context.LoadArgument(OperandType.I64, 1);
|
||||||
@@ -310,11 +315,11 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
context.Return(returnValue);
|
context.Return(returnValue);
|
||||||
|
|
||||||
var cfg = context.GetControlFlowGraph();
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
var retType = OperandType.I64;
|
OperandType retType = OperandType.I64;
|
||||||
var argTypes = new[] { OperandType.I64, OperandType.I64 };
|
OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>();
|
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>(_jitCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ARMeilleure.CodeGen.X86;
|
using ARMeilleure.CodeGen.X86;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using ARMeilleure.Translation.Cache;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
@@ -59,7 +60,7 @@ namespace ARMeilleure.Translation
|
|||||||
return context.VectorExtract(OperandType.I32, vec, 0);
|
return context.VectorExtract(OperandType.I32, vec, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FpFlagsPInvokeTest GenerateFpFlagsPInvokeTest()
|
public static FpFlagsPInvokeTest GenerateFpFlagsPInvokeTest(JitCache jitCache)
|
||||||
{
|
{
|
||||||
EmitterContext context = new();
|
EmitterContext context = new();
|
||||||
|
|
||||||
@@ -141,7 +142,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
OperandType[] argTypes = [OperandType.I64];
|
OperandType[] argTypes = [OperandType.I64];
|
||||||
|
|
||||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<FpFlagsPInvokeTest>();
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<FpFlagsPInvokeTest>(jitCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Ryujinx.Audio.Backends.Apple
|
|||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
AudioChannelLayout layout = new AudioChannelLayout
|
AudioChannelLayout layout = new()
|
||||||
{
|
{
|
||||||
AudioChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A,
|
AudioChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A,
|
||||||
AudioChannelBitmap = 0,
|
AudioChannelBitmap = 0,
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace Ryujinx.Audio.Backends.SDL3
|
|||||||
{
|
{
|
||||||
SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount);
|
SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount);
|
||||||
SDL_AudioSpec got = desired;
|
SDL_AudioSpec got = desired;
|
||||||
var pCallback = callback != null ? (SDL_AudioStreamCallbackPointer)Marshal.GetFunctionPointerForDelegate(callback) : null;
|
SDL_AudioStreamCallbackPointer pCallback = callback != null ? (SDL_AudioStreamCallbackPointer)Marshal.GetFunctionPointerForDelegate(callback) : null;
|
||||||
|
|
||||||
// From SDL 3 and on, SDL requires us to set this as a hint
|
// From SDL 3 and on, SDL requires us to set this as a hint
|
||||||
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, $"{sampleCount}");
|
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, $"{sampleCount}");
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
|
|||||||
get => Marshal.PtrToStringAnsi(GetOutContext().Name);
|
get => Marshal.PtrToStringAnsi(GetOutContext().Name);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var context = GetOutContext();
|
SoundIoOutStream context = GetOutContext();
|
||||||
|
|
||||||
if (_nameStored != nint.Zero && context.Name == _nameStored)
|
if (_nameStored != nint.Zero && context.Name == _nameStored)
|
||||||
{
|
{
|
||||||
@@ -129,8 +129,8 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
|
|||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var frameCountPtr = &nativeFrameCount;
|
int* frameCountPtr = &nativeFrameCount;
|
||||||
var arenasPtr = &arenas;
|
IntPtr* arenasPtr = &arenas;
|
||||||
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
|
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
|
||||||
|
|
||||||
frameCount = *frameCountPtr;
|
frameCount = *frameCountPtr;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Ryujinx.Audio.Renderer.Utils
|
|||||||
|
|
||||||
private void UpdateHeader()
|
private void UpdateHeader()
|
||||||
{
|
{
|
||||||
var writer = new BinaryWriter(_stream);
|
BinaryWriter writer = new(_stream);
|
||||||
|
|
||||||
long currentPos = writer.Seek(0, SeekOrigin.Current);
|
long currentPos = writer.Seek(0, SeekOrigin.Current);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var item in _queue.GetConsumingEnumerable(_cts.Token))
|
foreach (T item in _queue.GetConsumingEnumerable(_cts.Token))
|
||||||
{
|
{
|
||||||
_workerAction(item);
|
_workerAction(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@@ -16,15 +17,15 @@ namespace Ryujinx.Common.Extensions
|
|||||||
/// <param name="fileFullName">The path and name of the file to create and dump to</param>
|
/// <param name="fileFullName">The path and name of the file to create and dump to</param>
|
||||||
public static void DumpToFile(this ref SequenceReader<byte> reader, string fileFullName)
|
public static void DumpToFile(this ref SequenceReader<byte> reader, string fileFullName)
|
||||||
{
|
{
|
||||||
var initialConsumed = reader.Consumed;
|
long initialConsumed = reader.Consumed;
|
||||||
|
|
||||||
reader.Rewind(initialConsumed);
|
reader.Rewind(initialConsumed);
|
||||||
|
|
||||||
using (var fileStream = System.IO.File.Create(fileFullName, 4096, System.IO.FileOptions.None))
|
using (FileStream fileStream = System.IO.File.Create(fileFullName, 4096, System.IO.FileOptions.None))
|
||||||
{
|
{
|
||||||
while (reader.End == false)
|
while (reader.End == false)
|
||||||
{
|
{
|
||||||
var span = reader.CurrentSpan;
|
ReadOnlySpan<byte> span = reader.CurrentSpan;
|
||||||
fileStream.Write(span);
|
fileStream.Write(span);
|
||||||
reader.Advance(span.Length);
|
reader.Advance(span.Length);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
|||||||
|
|
||||||
sb.Append('{');
|
sb.Append('{');
|
||||||
|
|
||||||
foreach (var prop in props)
|
foreach (PropertyInfo prop in props)
|
||||||
{
|
{
|
||||||
sb.Append(prop.Name);
|
sb.Append(prop.Name);
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
@@ -52,7 +52,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
|||||||
|
|
||||||
if (array is not null)
|
if (array is not null)
|
||||||
{
|
{
|
||||||
foreach (var item in array)
|
foreach (object? item in array)
|
||||||
{
|
{
|
||||||
sb.Append(item);
|
sb.Append(item);
|
||||||
sb.Append(", ");
|
sb.Append(", ");
|
||||||
|
|||||||
@@ -136,11 +136,7 @@ namespace Ryujinx.Common.Logging
|
|||||||
|
|
||||||
_time = Stopwatch.StartNew();
|
_time = Stopwatch.StartNew();
|
||||||
|
|
||||||
// Logger should log to console by default
|
SetConsoleTargetEnabled(true);
|
||||||
AddTarget(new AsyncLogTargetWrapper(
|
|
||||||
new ConsoleLogTarget("console"),
|
|
||||||
1000,
|
|
||||||
AsyncLogTargetOverflowAction.Discard));
|
|
||||||
|
|
||||||
Notice = new Log(LogLevel.Notice);
|
Notice = new Log(LogLevel.Notice);
|
||||||
|
|
||||||
@@ -173,6 +169,21 @@ namespace Ryujinx.Common.Logging
|
|||||||
Updated += target.Log;
|
Updated += target.Log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetConsoleTargetEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
AddTarget(new AsyncLogTargetWrapper(
|
||||||
|
new ConsoleLogTarget("console"),
|
||||||
|
1000,
|
||||||
|
AsyncLogTargetOverflowAction.Discard));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveTarget("console");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void RemoveTarget(string target)
|
public static void RemoveTarget(string target)
|
||||||
{
|
{
|
||||||
ILogTarget logTarget = GetTarget(target);
|
ILogTarget logTarget = GetTarget(target);
|
||||||
@@ -204,7 +215,7 @@ namespace Ryujinx.Common.Logging
|
|||||||
|
|
||||||
_stdErrAdapter.Dispose();
|
_stdErrAdapter.Dispose();
|
||||||
|
|
||||||
foreach (var target in _logTargets)
|
foreach (ILogTarget target in _logTargets)
|
||||||
{
|
{
|
||||||
target.Dispose();
|
target.Dispose();
|
||||||
}
|
}
|
||||||
@@ -214,9 +225,9 @@ namespace Ryujinx.Common.Logging
|
|||||||
|
|
||||||
public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
|
public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
|
||||||
{
|
{
|
||||||
var logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
|
Log?[] logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
|
||||||
List<LogLevel> levels = new(logs.Length);
|
List<LogLevel> levels = new(logs.Length);
|
||||||
foreach (var log in logs)
|
foreach (Log? log in logs)
|
||||||
{
|
{
|
||||||
if (log.HasValue)
|
if (log.HasValue)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var signal = new ManualResetEventSlim(false);
|
using ManualResetEventSlim signal = new(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_messageQueue.Add(new FlushEventArgs(signal));
|
_messageQueue.Add(new FlushEventArgs(signal));
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||||||
|
|
||||||
public void Log(object sender, LogEventArgs e)
|
public void Log(object sender, LogEventArgs e)
|
||||||
{
|
{
|
||||||
var logEventArgsJson = LogEventArgsJson.FromLogEventArgs(e);
|
LogEventArgsJson logEventArgsJson = LogEventArgsJson.FromLogEventArgs(e);
|
||||||
JsonHelper.SerializeToStream(_stream, logEventArgsJson, LogEventJsonSerializerContext.Default.LogEventArgsJson);
|
JsonHelper.SerializeToStream(_stream, logEventArgsJson, LogEventJsonSerializerContext.Default.LogEventArgsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||||
|
<Configurations>Debug;Release;Debug AOT;Release AOT</Configurations>
|
||||||
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
public static byte[] Read(string filename)
|
public static byte[] Read(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return Read(assembly, path);
|
return Read(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<byte[]> ReadAsync(string filename)
|
public static Task<byte[]> ReadAsync(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return ReadAsync(assembly, path);
|
return ReadAsync(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] Read(Assembly assembly, string filename)
|
public static byte[] Read(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(assembly, filename);
|
using Stream stream = GetStream(assembly, filename);
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -44,14 +44,14 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
public static MemoryOwner<byte> ReadFileToRentedMemory(string filename)
|
public static MemoryOwner<byte> ReadFileToRentedMemory(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return ReadFileToRentedMemory(assembly, path);
|
return ReadFileToRentedMemory(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemoryOwner<byte> ReadFileToRentedMemory(Assembly assembly, string filename)
|
public static MemoryOwner<byte> ReadFileToRentedMemory(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(assembly, filename);
|
using Stream stream = GetStream(assembly, filename);
|
||||||
|
|
||||||
return stream is null
|
return stream is null
|
||||||
? null
|
? null
|
||||||
@@ -60,7 +60,7 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
|
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(assembly, filename);
|
using Stream stream = GetStream(assembly, filename);
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -71,55 +71,55 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
public static string ReadAllText(string filename)
|
public static string ReadAllText(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return ReadAllText(assembly, path);
|
return ReadAllText(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<string> ReadAllTextAsync(string filename)
|
public static Task<string> ReadAllTextAsync(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return ReadAllTextAsync(assembly, path);
|
return ReadAllTextAsync(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadAllText(Assembly assembly, string filename)
|
public static string ReadAllText(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(assembly, filename);
|
using Stream stream = GetStream(assembly, filename);
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var reader = new StreamReader(stream);
|
using StreamReader reader = new(stream);
|
||||||
return reader.ReadToEnd();
|
return reader.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
|
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(assembly, filename);
|
using Stream stream = GetStream(assembly, filename);
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var reader = new StreamReader(stream);
|
using StreamReader reader = new(stream);
|
||||||
return await reader.ReadToEndAsync();
|
return await reader.ReadToEndAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream GetStream(string filename)
|
public static Stream GetStream(string filename)
|
||||||
{
|
{
|
||||||
var (assembly, path) = ResolveManifestPath(filename);
|
(Assembly assembly, string path) = ResolveManifestPath(filename);
|
||||||
|
|
||||||
return GetStream(assembly, path);
|
return GetStream(assembly, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream GetStream(Assembly assembly, string filename)
|
public static Stream GetStream(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
var @namespace = assembly.GetName().Name;
|
string @namespace = assembly.GetName().Name;
|
||||||
var manifestUri = @namespace + "." + filename.Replace('/', '.');
|
string manifestUri = @namespace + "." + filename.Replace('/', '.');
|
||||||
|
|
||||||
var stream = assembly.GetManifestResourceStream(manifestUri);
|
Stream stream = assembly.GetManifestResourceStream(manifestUri);
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
@@ -133,11 +133,11 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
private static (Assembly, string) ResolveManifestPath(string filename)
|
private static (Assembly, string) ResolveManifestPath(string filename)
|
||||||
{
|
{
|
||||||
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
string[] segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
if (segments.Length >= 2)
|
if (segments.Length >= 2)
|
||||||
{
|
{
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
if (assembly.GetName().Name == segments[0])
|
if (assembly.GetName().Name == segments[0])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
|
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
|
||||||
{
|
{
|
||||||
// Get information about the source directory
|
// Get information about the source directory
|
||||||
var dir = new DirectoryInfo(sourceDir);
|
DirectoryInfo dir = new(sourceDir);
|
||||||
|
|
||||||
// Check if the source directory exists
|
// Check if the source directory exists
|
||||||
if (!dir.Exists)
|
if (!dir.Exists)
|
||||||
@@ -49,7 +49,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
public static string SanitizeFileName(string fileName)
|
public static string SanitizeFileName(string fileName)
|
||||||
{
|
{
|
||||||
var reservedChars = new HashSet<char>(Path.GetInvalidFileNameChars());
|
HashSet<char> reservedChars = new(Path.GetInvalidFileNameChars());
|
||||||
return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c));
|
return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using MsgPack;
|
using MsgPack;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Utilities
|
namespace Ryujinx.Common.Utilities
|
||||||
@@ -18,7 +19,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
public static string Format(MessagePackObject obj)
|
public static string Format(MessagePackObject obj)
|
||||||
{
|
{
|
||||||
var builder = new IndentedStringBuilder();
|
IndentedStringBuilder builder = new();
|
||||||
|
|
||||||
FormatMsgPackObj(obj, builder);
|
FormatMsgPackObj(obj, builder);
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var literal = obj.ToObject();
|
object literal = obj.ToObject();
|
||||||
|
|
||||||
if (literal is String)
|
if (literal is String)
|
||||||
{
|
{
|
||||||
@@ -88,7 +89,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
builder.Append("[ ");
|
builder.Append("[ ");
|
||||||
|
|
||||||
foreach (var b in arr)
|
foreach (byte b in arr)
|
||||||
{
|
{
|
||||||
builder.Append("0x");
|
builder.Append("0x");
|
||||||
builder.Append(ToHexChar(b >> 4));
|
builder.Append(ToHexChar(b >> 4));
|
||||||
@@ -111,7 +112,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
builder.Append("0x");
|
builder.Append("0x");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var b in arr)
|
foreach (byte b in arr)
|
||||||
{
|
{
|
||||||
builder.Append(ToHexChar(b >> 4));
|
builder.Append(ToHexChar(b >> 4));
|
||||||
builder.Append(ToHexChar(b & 0xF));
|
builder.Append(ToHexChar(b & 0xF));
|
||||||
@@ -122,7 +123,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder)
|
private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder)
|
||||||
{
|
{
|
||||||
var map = obj.AsDictionary();
|
MessagePackObjectDictionary map = obj.AsDictionary();
|
||||||
|
|
||||||
builder.Append('{');
|
builder.Append('{');
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
builder.IncreaseIndent()
|
builder.IncreaseIndent()
|
||||||
.AppendLine();
|
.AppendLine();
|
||||||
|
|
||||||
foreach (var item in map)
|
foreach (KeyValuePair<MessagePackObject, MessagePackObject> item in map)
|
||||||
{
|
{
|
||||||
FormatMsgPackObj(item.Key, builder);
|
FormatMsgPackObj(item.Key, builder);
|
||||||
|
|
||||||
@@ -154,11 +155,11 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder)
|
private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder)
|
||||||
{
|
{
|
||||||
var arr = obj.AsList();
|
IList<MessagePackObject> arr = obj.AsList();
|
||||||
|
|
||||||
builder.Append("[ ");
|
builder.Append("[ ");
|
||||||
|
|
||||||
foreach (var item in arr)
|
foreach (MessagePackObject item in arr)
|
||||||
{
|
{
|
||||||
FormatMsgPackObj(item, builder);
|
FormatMsgPackObj(item, builder);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.IO;
|
using Microsoft.IO;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -27,7 +28,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
MemoryOwner<byte> ownedMemory = MemoryOwner<byte>.Rent(checked((int)bytesExpected));
|
MemoryOwner<byte> ownedMemory = MemoryOwner<byte>.Rent(checked((int)bytesExpected));
|
||||||
|
|
||||||
var destSpan = ownedMemory.Span;
|
Span<byte> destSpan = ownedMemory.Span;
|
||||||
|
|
||||||
int totalBytesRead = 0;
|
int totalBytesRead = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
internal static TimeSpan Measure(Action action)
|
internal static TimeSpan Measure(Action action)
|
||||||
{
|
{
|
||||||
var sw = new Stopwatch();
|
Stopwatch sw = new();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -66,7 +66,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
|
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
var trimmer = new XCIFileTrimmer(filename, log);
|
XCIFileTrimmer trimmer = new(filename, log);
|
||||||
return trimmer.CanBeTrimmed;
|
return trimmer.CanBeTrimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
|
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
var trimmer = new XCIFileTrimmer(filename, log);
|
XCIFileTrimmer trimmer = new(filename, log);
|
||||||
return trimmer.CanBeUntrimmed;
|
return trimmer.CanBeUntrimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
long maxReads = readSizeB / BufferSize;
|
long maxReads = readSizeB / BufferSize;
|
||||||
long read = 0;
|
long read = 0;
|
||||||
var buffer = new byte[BufferSize];
|
byte[] buffer = new byte[BufferSize];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -287,7 +287,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var info = new FileInfo(Filename);
|
FileInfo info = new(Filename);
|
||||||
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
|
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -308,7 +308,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
return OperationOutcome.FileSizeChanged;
|
return OperationOutcome.FileSizeChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
var outfileStream = new FileStream(_filename, FileMode.Open, FileAccess.Write, FileShare.Write);
|
FileStream outfileStream = new(_filename, FileMode.Open, FileAccess.Write, FileShare.Write);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -347,7 +347,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
{
|
{
|
||||||
Log?.Write(LogType.Info, "Untrimming...");
|
Log?.Write(LogType.Info, "Untrimming...");
|
||||||
|
|
||||||
var info = new FileInfo(Filename);
|
FileInfo info = new(Filename);
|
||||||
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
|
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -368,7 +368,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
return OperationOutcome.FileSizeChanged;
|
return OperationOutcome.FileSizeChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
var outfileStream = new FileStream(_filename, FileMode.Append, FileAccess.Write, FileShare.Write);
|
FileStream outfileStream = new(_filename, FileMode.Append, FileAccess.Write, FileShare.Write);
|
||||||
long bytesToWriteB = UntrimmedFileSizeB - FileSizeB;
|
long bytesToWriteB = UntrimmedFileSizeB - FileSizeB;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -413,7 +413,7 @@ namespace Ryujinx.Common.Utilities
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var buffer = new byte[BufferSize];
|
byte[] buffer = new byte[BufferSize];
|
||||||
Array.Fill<byte>(buffer, PaddingByte);
|
Array.Fill<byte>(buffer, PaddingByte);
|
||||||
|
|
||||||
while (bytesLeftToWriteB > 0)
|
while (bytesLeftToWriteB > 0)
|
||||||
|
|||||||
+35
-296
@@ -1,15 +1,9 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Common;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Cpu.Signal;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
|
||||||
using static Ryujinx.Cpu.MemoryEhMeilleure;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Common
|
namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a table of guest address to a value.
|
/// Represents a table of guest address to a value.
|
||||||
@@ -17,84 +11,12 @@ namespace ARMeilleure.Common
|
|||||||
/// <typeparam name="TEntry">Type of the value</typeparam>
|
/// <typeparam name="TEntry">Type of the value</typeparam>
|
||||||
public unsafe class AddressTable<TEntry> : IAddressTable<TEntry> where TEntry : unmanaged
|
public unsafe class AddressTable<TEntry> : IAddressTable<TEntry> where TEntry : unmanaged
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Represents a page of the address table.
|
|
||||||
/// </summary>
|
|
||||||
private readonly struct AddressTablePage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// True if the allocation belongs to a sparse block, false otherwise.
|
|
||||||
/// </summary>
|
|
||||||
public readonly bool IsSparse;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base address for the page.
|
|
||||||
/// </summary>
|
|
||||||
public readonly nint Address;
|
|
||||||
|
|
||||||
public AddressTablePage(bool isSparse, nint address)
|
|
||||||
{
|
|
||||||
IsSparse = isSparse;
|
|
||||||
Address = address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A sparsely mapped block of memory with a signal handler to map pages as they're accessed.
|
|
||||||
/// </summary>
|
|
||||||
private readonly struct TableSparseBlock : IDisposable
|
|
||||||
{
|
|
||||||
public readonly SparseMemoryBlock Block;
|
|
||||||
private readonly TrackingEventDelegate _trackingEvent;
|
|
||||||
|
|
||||||
public TableSparseBlock(ulong size, Action<nint> ensureMapped, PageInitDelegate pageInit)
|
|
||||||
{
|
|
||||||
var block = new SparseMemoryBlock(size, pageInit, null);
|
|
||||||
|
|
||||||
_trackingEvent = (ulong address, ulong _, bool _) =>
|
|
||||||
{
|
|
||||||
ulong pointer = (ulong)block.Block.Pointer + address;
|
|
||||||
ensureMapped((nint)pointer);
|
|
||||||
return pointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool added = NativeSignalHandler.AddTrackedRegion(
|
|
||||||
(nuint)block.Block.Pointer,
|
|
||||||
(nuint)(block.Block.Pointer + (nint)block.Block.Size),
|
|
||||||
Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
|
||||||
|
|
||||||
if (!added)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Number of allowed tracked regions exceeded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Block = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
NativeSignalHandler.RemoveTrackedRegion((nuint)Block.Block.Pointer);
|
|
||||||
|
|
||||||
Block.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private TEntry** _table;
|
private TEntry** _table;
|
||||||
private readonly List<AddressTablePage> _pages;
|
private readonly List<nint> _pages;
|
||||||
private TEntry _fill;
|
|
||||||
|
|
||||||
private readonly MemoryBlock _sparseFill;
|
/// <inheritdoc/>
|
||||||
private readonly SparseMemoryBlock _fillBottomLevel;
|
public AddressTableType TableType => AddressTableType.Default;
|
||||||
private readonly TEntry* _fillBottomLevelPtr;
|
|
||||||
|
|
||||||
private readonly List<TableSparseBlock> _sparseReserved;
|
|
||||||
private readonly ReaderWriterLockSlim _sparseLock;
|
|
||||||
|
|
||||||
private ulong _sparseBlockSize;
|
|
||||||
private ulong _sparseReservedOffset;
|
|
||||||
|
|
||||||
public bool Sparse { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ulong Mask { get; }
|
public ulong Mask { get; }
|
||||||
@@ -103,17 +25,7 @@ namespace ARMeilleure.Common
|
|||||||
public AddressTableLevel[] Levels { get; }
|
public AddressTableLevel[] Levels { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public TEntry Fill
|
public TEntry Fill { get; set; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _fill;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
UpdateFill(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public nint Base
|
public nint Base
|
||||||
@@ -131,44 +43,24 @@ namespace ARMeilleure.Common
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
|
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
|
||||||
/// <see cref="Level"/>.
|
/// <see cref="AddressTableLevel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="levels">Levels for the address table</param>
|
/// <param name="levels">Levels for the address table</param>
|
||||||
/// <param name="sparse">True if the bottom page should be sparsely mapped</param>
|
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
|
||||||
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
|
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
|
||||||
public AddressTable(AddressTableLevel[] levels, bool sparse)
|
public AddressTable(AddressTableLevel[] levels)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(levels);
|
ArgumentNullException.ThrowIfNull(levels);
|
||||||
|
|
||||||
_pages = new List<AddressTablePage>(capacity: 16);
|
_pages = new List<nint>(capacity: 16);
|
||||||
|
|
||||||
Levels = levels;
|
Levels = levels;
|
||||||
Mask = 0;
|
Mask = 0;
|
||||||
|
|
||||||
foreach (var level in Levels)
|
foreach (AddressTableLevel level in Levels)
|
||||||
{
|
{
|
||||||
Mask |= level.Mask;
|
Mask |= level.Mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sparse = sparse;
|
|
||||||
|
|
||||||
if (sparse)
|
|
||||||
{
|
|
||||||
// If the address table is sparse, allocate a fill block
|
|
||||||
|
|
||||||
_sparseFill = new MemoryBlock(268435456ul, MemoryAllocationFlags.Mirrorable); //low Power TC uses size: 65536ul
|
|
||||||
|
|
||||||
ulong bottomLevelSize = (1ul << levels.Last().Length) * (ulong)sizeof(TEntry);
|
|
||||||
|
|
||||||
_fillBottomLevel = new SparseMemoryBlock(bottomLevelSize, null, _sparseFill);
|
|
||||||
_fillBottomLevelPtr = (TEntry*)_fillBottomLevel.Block.Pointer;
|
|
||||||
|
|
||||||
_sparseReserved = [];
|
|
||||||
_sparseLock = new ReaderWriterLockSlim();
|
|
||||||
|
|
||||||
_sparseBlockSize = bottomLevelSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -176,29 +68,10 @@ namespace ARMeilleure.Common
|
|||||||
/// Selects the best table structure for A32/A64, taking into account the selected memory manager type.
|
/// Selects the best table structure for A32/A64, taking into account the selected memory manager type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="for64Bits">True if the guest is A64, false otherwise</param>
|
/// <param name="for64Bits">True if the guest is A64, false otherwise</param>
|
||||||
/// <param name="type">Memory manager type</param>
|
|
||||||
/// <returns>An <see cref="AddressTable{TEntry}"/> for ARM function lookup</returns>
|
/// <returns>An <see cref="AddressTable{TEntry}"/> for ARM function lookup</returns>
|
||||||
public static AddressTable<TEntry> CreateForArm(bool for64Bits, MemoryManagerType type)
|
public static AddressTable<TEntry> CreateForArm(bool for64Bits)
|
||||||
{
|
{
|
||||||
// Assume software memory means that we don't want to use any signal handlers.
|
return new AddressTable<TEntry>(AddressTablePresets.GetArmPreset(for64Bits, false));
|
||||||
bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable;
|
|
||||||
|
|
||||||
return new AddressTable<TEntry>(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the fill value for the bottom level of the table.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fillValue">New fill value</param>
|
|
||||||
private void UpdateFill(TEntry fillValue)
|
|
||||||
{
|
|
||||||
if (_sparseFill != null)
|
|
||||||
{
|
|
||||||
Span<byte> span = _sparseFill.GetSpan(0, (int)_sparseFill.Size);
|
|
||||||
MemoryMarshal.Cast<byte, TEntry>(span).Fill(fillValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
_fill = fillValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -206,17 +79,7 @@ namespace ARMeilleure.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address"></param>
|
/// <param name="address"></param>
|
||||||
/// <param name="size"></param>
|
/// <param name="size"></param>
|
||||||
public void SignalCodeRange(ulong address, ulong size)
|
public void SignalCodeRange(ulong address, ulong size) { }
|
||||||
{
|
|
||||||
AddressTableLevel bottom = Levels.Last();
|
|
||||||
ulong bottomLevelEntries = 1ul << bottom.Length;
|
|
||||||
|
|
||||||
ulong entryIndex = address >> bottom.Index;
|
|
||||||
ulong entries = size >> bottom.Index;
|
|
||||||
entries += entryIndex - BitUtils.AlignDown(entryIndex, bottomLevelEntries);
|
|
||||||
|
|
||||||
_sparseBlockSize = Math.Max(_sparseBlockSize, BitUtils.AlignUp(entries, bottomLevelEntries) * (ulong)sizeof(TEntry));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool IsValid(ulong address)
|
public bool IsValid(ulong address)
|
||||||
@@ -240,8 +103,6 @@ namespace ARMeilleure.Common
|
|||||||
|
|
||||||
long index = Levels[^1].GetValue(address);
|
long index = Levels[^1].GetValue(address);
|
||||||
|
|
||||||
EnsureMapped((nint)(page + index));
|
|
||||||
|
|
||||||
return ref page[index];
|
return ref page[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,19 +121,19 @@ namespace ARMeilleure.Common
|
|||||||
ref AddressTableLevel level = ref Levels[i];
|
ref AddressTableLevel level = ref Levels[i];
|
||||||
if (page != null)
|
if (page != null)
|
||||||
{
|
{
|
||||||
ref TEntry* nextPage = ref page[level.GetValue(address)];
|
ref TEntry* nextPage = ref page![level.GetValue(address)];
|
||||||
|
|
||||||
if (nextPage == null || nextPage == _fillBottomLevelPtr)
|
if (nextPage == null)
|
||||||
{
|
{
|
||||||
ref AddressTableLevel nextLevel = ref Levels[i + 1];
|
ref AddressTableLevel nextLevel = ref Levels[i + 1];
|
||||||
|
|
||||||
if (i == Levels.Length - 2)
|
if (i == Levels.Length - 2)
|
||||||
{
|
{
|
||||||
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true);
|
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false);
|
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, nint.Zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,57 +144,6 @@ namespace ARMeilleure.Common
|
|||||||
return (TEntry*)page;
|
return (TEntry*)page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ensure the given pointer is mapped in any overlapping sparse reservations.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ptr">Pointer to be mapped</param>
|
|
||||||
private void EnsureMapped(nint ptr)
|
|
||||||
{
|
|
||||||
if (Sparse)
|
|
||||||
{
|
|
||||||
// Check sparse allocations to see if the pointer is in any of them.
|
|
||||||
// Ensure the page is committed if there's a match.
|
|
||||||
|
|
||||||
_sparseLock.EnterReadLock();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (TableSparseBlock reserved in _sparseReserved)
|
|
||||||
{
|
|
||||||
SparseMemoryBlock sparse = reserved.Block;
|
|
||||||
|
|
||||||
if (ptr >= sparse.Block.Pointer && ptr < sparse.Block.Pointer + (nint)sparse.Block.Size)
|
|
||||||
{
|
|
||||||
sparse.EnsureMapped((ulong)(ptr - sparse.Block.Pointer));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_sparseLock.ExitReadLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the fill value for a non-leaf level of the table.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="level">Level to get the fill value for</param>
|
|
||||||
/// <returns>The fill value</returns>
|
|
||||||
private nint GetFillValue(int level)
|
|
||||||
{
|
|
||||||
if (_fillBottomLevel != null && level == Levels.Length - 2)
|
|
||||||
{
|
|
||||||
return (nint)_fillBottomLevelPtr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return nint.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
|
/// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -343,91 +153,35 @@ namespace ARMeilleure.Common
|
|||||||
if (_table == null)
|
if (_table == null)
|
||||||
{
|
{
|
||||||
if (Levels.Length == 1)
|
if (Levels.Length == 1)
|
||||||
_table = (TEntry**)Allocate(1 << Levels[0].Length, Fill, leaf: true);
|
_table = (TEntry**)Allocate(1 << Levels[0].Length, Fill);
|
||||||
else
|
else
|
||||||
_table = (TEntry**)Allocate(1 << Levels[0].Length, GetFillValue(0), leaf: false);
|
_table = (TEntry**)Allocate(1 << Levels[0].Length, nint.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _table;
|
return _table;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initialize a leaf page with the fill value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="page">Page to initialize</param>
|
|
||||||
private void InitLeafPage(Span<byte> page)
|
|
||||||
{
|
|
||||||
MemoryMarshal.Cast<byte, TEntry>(page).Fill(_fill);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reserve a new sparse block, and add it to the list.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The new sparse block that was added</returns>
|
|
||||||
private TableSparseBlock ReserveNewSparseBlock()
|
|
||||||
{
|
|
||||||
var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage);
|
|
||||||
|
|
||||||
_sparseReserved.Add(block);
|
|
||||||
_sparseReservedOffset = 0;
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allocates a block of memory of the specified type and length.
|
/// Allocates a block of memory of the specified type and length.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Type of elements</typeparam>
|
/// <typeparam name="T">Type of elements</typeparam>
|
||||||
/// <param name="length">Number of elements</param>
|
/// <param name="length">Number of elements</param>
|
||||||
/// <param name="fill">Fill value</param>
|
/// <param name="fill">Fill value</param>
|
||||||
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
|
||||||
/// <returns>Allocated block</returns>
|
/// <returns>Allocated block</returns>
|
||||||
private nint Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
private nint Allocate<T>(int length, T fill) where T : unmanaged
|
||||||
{
|
{
|
||||||
var size = sizeof(T) * length;
|
int size = sizeof(T) * length;
|
||||||
|
|
||||||
AddressTablePage page;
|
nint address = (nint)NativeAllocator.Instance.Allocate((uint)size);
|
||||||
|
|
||||||
if (Sparse && leaf)
|
Span<T> span = new((void*)address, length);
|
||||||
{
|
span.Fill(fill);
|
||||||
_sparseLock.EnterWriteLock();
|
|
||||||
|
|
||||||
SparseMemoryBlock block;
|
_pages.Add(address);
|
||||||
|
|
||||||
if (_sparseReserved.Count == 0)
|
|
||||||
{
|
|
||||||
block = ReserveNewSparseBlock().Block;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
block = _sparseReserved.Last().Block;
|
|
||||||
|
|
||||||
if (_sparseReservedOffset == block.Block.Size)
|
|
||||||
{
|
|
||||||
block = ReserveNewSparseBlock().Block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
page = new AddressTablePage(true, block.Block.Pointer + (nint)_sparseReservedOffset);
|
|
||||||
|
|
||||||
_sparseReservedOffset += (ulong)size;
|
|
||||||
|
|
||||||
_sparseLock.ExitWriteLock();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var address = (nint)NativeAllocator.Instance.Allocate((uint)size);
|
|
||||||
page = new AddressTablePage(false, address);
|
|
||||||
|
|
||||||
var span = new Span<T>((void*)page.Address, length);
|
|
||||||
span.Fill(fill);
|
|
||||||
}
|
|
||||||
|
|
||||||
_pages.Add(page);
|
|
||||||
|
|
||||||
//TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
|
//TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
|
||||||
|
|
||||||
return page.Address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -446,32 +200,17 @@ namespace ARMeilleure.Common
|
|||||||
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
|
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
foreach (var page in _pages)
|
return;
|
||||||
{
|
|
||||||
if (!page.IsSparse)
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(page.Address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Sparse)
|
|
||||||
{
|
|
||||||
foreach (TableSparseBlock block in _sparseReserved)
|
|
||||||
{
|
|
||||||
block.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_sparseReserved.Clear();
|
|
||||||
|
|
||||||
_fillBottomLevel.Dispose();
|
|
||||||
_sparseFill.Dispose();
|
|
||||||
_sparseLock.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (nint page in _pages)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
|
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
|
||||||
{
|
{
|
||||||
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
|
(_asBase, HvIpaAllocator ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
|
||||||
_backingSize = backingMemory.Size;
|
_backingSize = backingMemory.Size;
|
||||||
|
|
||||||
_userRange = new HvAddressSpaceRange(ipaAllocator);
|
_userRange = new HvAddressSpaceRange(ipaAllocator);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
|
using ARMeilleure.Translation.PTC;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.AppleHv
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
@@ -32,7 +33,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
|
public IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled)
|
||||||
{
|
{
|
||||||
return new DummyDiskCacheLoadState();
|
return new DummyDiskCacheLoadState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Cpu.AppleHv.Arm;
|
using Ryujinx.Cpu.AppleHv.Arm;
|
||||||
using Ryujinx.Memory.Tracking;
|
using Ryujinx.Memory.Tracking;
|
||||||
using System;
|
using System;
|
||||||
@@ -17,9 +18,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
||||||
if (currentEl == (uint)ExceptionLevel.EL1h)
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
{
|
|
||||||
return _impl.ElrEl1;
|
return _impl.ElrEl1;
|
||||||
}
|
|
||||||
return _impl.Pc;
|
return _impl.Pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,9 +68,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,11 +79,13 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
private readonly IHvExecutionContext _shadowContext;
|
private readonly IHvExecutionContext _shadowContext;
|
||||||
private IHvExecutionContext _impl;
|
private IHvExecutionContext _impl;
|
||||||
private int _shouldStep;
|
private int _shouldStep;
|
||||||
|
|
||||||
private readonly ExceptionCallbacks _exceptionCallbacks;
|
private readonly ExceptionCallbacks _exceptionCallbacks;
|
||||||
|
|
||||||
private int _interruptRequested;
|
private int _interruptRequested;
|
||||||
|
|
||||||
|
// GPU Sync control
|
||||||
|
private int _syncCounter;
|
||||||
|
private int _strongSyncCounter;
|
||||||
|
|
||||||
public HvExecutionContext(ICounter counter, ExceptionCallbacks exceptionCallbacks)
|
public HvExecutionContext(ICounter counter, ExceptionCallbacks exceptionCallbacks)
|
||||||
{
|
{
|
||||||
_counter = counter;
|
_counter = counter;
|
||||||
@@ -108,38 +107,17 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void SetV(int index, V128 value) => _impl.SetV(index, value);
|
public void SetV(int index, V128 value) => _impl.SetV(index, value);
|
||||||
|
|
||||||
private void InterruptHandler()
|
private void InterruptHandler() => _exceptionCallbacks.InterruptCallback?.Invoke(this);
|
||||||
{
|
private void BreakHandler(ulong address, int imm) => _exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
|
||||||
_exceptionCallbacks.InterruptCallback?.Invoke(this);
|
private void StepHandler() => _exceptionCallbacks.StepCallback?.Invoke(this);
|
||||||
}
|
private void SupervisorCallHandler(ulong address, int imm) => _exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
|
||||||
|
private void UndefinedHandler(ulong address, int opCode) => _exceptionCallbacks.UndefinedCallback?.Invoke(this, address, opCode);
|
||||||
private void BreakHandler(ulong address, int imm)
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StepHandler()
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.StepCallback?.Invoke(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SupervisorCallHandler(ulong address, int imm)
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UndefinedHandler(ulong address, int opCode)
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.UndefinedCallback?.Invoke(this, address, opCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void RequestInterrupt()
|
public void RequestInterrupt()
|
||||||
{
|
{
|
||||||
if (Interlocked.Exchange(ref _interruptRequested, 1) == 0 && _impl is HvExecutionContextVcpu impl)
|
if (Interlocked.Exchange(ref _interruptRequested, 1) == 0 && _impl is HvExecutionContextVcpu impl)
|
||||||
{
|
|
||||||
impl.RequestInterrupt();
|
impl.RequestInterrupt();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool GetAndClearInterruptRequested()
|
private bool GetAndClearInterruptRequested()
|
||||||
@@ -161,13 +139,9 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
||||||
if (currentEl == (uint)ExceptionLevel.EL1h)
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
{
|
|
||||||
_impl.ElrEl1 = value;
|
_impl.ElrEl1 = value;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
_impl.Pc = value;
|
_impl.Pc = value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,9 +155,11 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
public unsafe void Execute(HvMemoryManager memoryManager, ulong address)
|
public unsafe void Execute(HvMemoryManager memoryManager, ulong address)
|
||||||
{
|
{
|
||||||
HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext);
|
HvVcpu vcpu = HvVcpuPool.Instance.Create(memoryManager.AddressSpace, _shadowContext, SwapContext);
|
||||||
|
|
||||||
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
||||||
|
|
||||||
|
_syncCounter = 0;
|
||||||
|
_strongSyncCounter = 0;
|
||||||
|
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
|
if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
|
||||||
@@ -192,16 +168,23 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
if (currentEl == (uint)ExceptionLevel.EL1h)
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
||||||
spsr |= (1 << 21);
|
spsr |= (1U << 21);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
|
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pstate |= (1 << 21);
|
Pstate |= (1U << 21);
|
||||||
}
|
}
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
|
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adaptive GPU synchronization to prevent 0 FPS
|
||||||
|
if (++_syncCounter % 12 == 0)
|
||||||
|
{
|
||||||
|
TryGpuSync();
|
||||||
|
_syncCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
|
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
|
||||||
|
|
||||||
HvExitReason reason = vcpu.ExitInfo->Reason;
|
HvExitReason reason = vcpu.ExitInfo->Reason;
|
||||||
@@ -212,9 +195,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
|
ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26);
|
||||||
|
|
||||||
if (hvEc != ExceptionClass.HvcAarch64)
|
if (hvEc != ExceptionClass.HvcAarch64)
|
||||||
{
|
|
||||||
throw new Exception($"Unhandled exception from guest kernel with ESR 0x{hvEsr:X} ({hvEc}).");
|
throw new Exception($"Unhandled exception from guest kernel with ESR 0x{hvEsr:X} ({hvEc}).");
|
||||||
}
|
|
||||||
|
|
||||||
address = SynchronousException(memoryManager, ref vcpu);
|
address = SynchronousException(memoryManager, ref vcpu);
|
||||||
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
||||||
@@ -245,10 +226,31 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
HvVcpuPool.Instance.Destroy(vcpu, SwapContext);
|
HvVcpuPool.Instance.Destroy(vcpu, SwapContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryGpuSync() is called periodically in the main Execute() loop. The "syncing" value can be tuned based on gameplay results.
|
||||||
|
// This feature it to be followed-up and further completed in a future PR.
|
||||||
|
private void TryGpuSync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.Yield();
|
||||||
|
|
||||||
|
if (++_strongSyncCounter % 6 == 0)
|
||||||
|
{
|
||||||
|
Thread.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (_strongSyncCounter % 100 == 0)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"[AppleHv] GPU sync issue: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ulong SynchronousException(HvMemoryManager memoryManager, ref HvVcpu vcpu)
|
private ulong SynchronousException(HvMemoryManager memoryManager, ref HvVcpu vcpu)
|
||||||
{
|
{
|
||||||
ulong vcpuHandle = vcpu.Handle;
|
ulong vcpuHandle = vcpu.Handle;
|
||||||
|
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
|
||||||
|
|
||||||
@@ -259,16 +261,20 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
case ExceptionClass.DataAbortLowerEl:
|
case ExceptionClass.DataAbortLowerEl:
|
||||||
DataAbort(memoryManager.Tracking, vcpuHandle, (uint)esr);
|
DataAbort(memoryManager.Tracking, vcpuHandle, (uint)esr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExceptionClass.TrappedMsrMrsSystem:
|
case ExceptionClass.TrappedMsrMrsSystem:
|
||||||
InstructionTrap((uint)esr);
|
InstructionTrap((uint)esr);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, elr + 4UL).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.ELR_EL1, elr + 4UL).ThrowOnError();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExceptionClass.SvcAarch64:
|
case ExceptionClass.SvcAarch64:
|
||||||
ReturnToPool(vcpu);
|
ReturnToPool(vcpu);
|
||||||
ushort id = (ushort)esr;
|
ushort id = (ushort)esr;
|
||||||
SupervisorCallHandler(elr - 4UL, id);
|
SupervisorCallHandler(elr - 4UL, id);
|
||||||
|
Thread.Yield(); // MoltenVK causes extremely frequent SVC exits, and HVF handles them in a busy loop. Hypervisor.Framework accelerates the guest CPU, and without periodic yielding/flushing, MoltenVK's presentation queue can starve, causing permanent 0 FPS deadlock.
|
||||||
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExceptionClass.SoftwareStepLowerEl:
|
case ExceptionClass.SoftwareStepLowerEl:
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
||||||
spsr &= ~((ulong)(1 << 21));
|
spsr &= ~((ulong)(1 << 21));
|
||||||
@@ -278,21 +284,23 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
StepHandler();
|
StepHandler();
|
||||||
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExceptionClass.BrkAarch64:
|
case ExceptionClass.BrkAarch64:
|
||||||
ReturnToPool(vcpu);
|
ReturnToPool(vcpu);
|
||||||
BreakHandler(elr, (ushort)esr);
|
BreakHandler(elr, (ushort)esr);
|
||||||
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Unhandled guest exception {ec}.");
|
throw new Exception($"Unhandled guest exception {ec}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we will continue running at EL0.
|
// Make sure we will continue running at EL0.
|
||||||
if (memoryManager.AddressSpace.GetAndClearUserTlbInvalidationPending())
|
if (memoryManager.AddressSpace.GetAndClearUserTlbInvalidationPending())
|
||||||
{
|
|
||||||
// TODO: Invalidate only the range that was modified?
|
// TODO: Invalidate only the range that was modified?
|
||||||
return HvAddressSpace.KernelRegionTlbiEretAddress;
|
return HvAddressSpace.KernelRegionTlbiEretAddress;
|
||||||
}
|
|
||||||
return HvAddressSpace.KernelRegionEretAddress;
|
return HvAddressSpace.KernelRegionEretAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +313,6 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
if (farValid)
|
if (farValid)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpu, HvSysReg.FAR_EL1, out ulong far).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpu, HvSysReg.FAR_EL1, out ulong far).ThrowOnError();
|
||||||
|
|
||||||
ulong size = 1UL << accessSizeLog2;
|
ulong size = 1UL << accessSizeLog2;
|
||||||
|
|
||||||
if (!tracking.VirtualMemoryEvent(far, size, write))
|
if (!tracking.VirtualMemoryEvent(far, size, write))
|
||||||
@@ -349,9 +356,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
private void WriteRt(uint rt, ulong value)
|
private void WriteRt(uint rt, ulong value)
|
||||||
{
|
{
|
||||||
if (rt < 31)
|
if (rt < 31)
|
||||||
{
|
|
||||||
SetX((int)rt, value);
|
SetX((int)rt, value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReturnToPool(HvVcpu vcpu)
|
private void ReturnToPool(HvVcpu vcpu)
|
||||||
@@ -369,8 +374,6 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
_impl = newContext;
|
_impl = newContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -14,8 +16,31 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
private static readonly SetSimdFpReg _setSimdFpReg;
|
private static readonly SetSimdFpReg _setSimdFpReg;
|
||||||
private static readonly nint _setSimdFpRegNativePtr;
|
private static readonly nint _setSimdFpRegNativePtr;
|
||||||
|
|
||||||
|
public static bool AggressiveMode { get; set; } = false;
|
||||||
|
private bool _earlyBootPhase = true;
|
||||||
|
|
||||||
public ulong ThreadUid { get; set; }
|
public ulong ThreadUid { get; set; }
|
||||||
|
|
||||||
|
private readonly ulong[] _x = new ulong[32];
|
||||||
|
private readonly V128[] _v = new V128[32];
|
||||||
|
|
||||||
|
private ulong _pc;
|
||||||
|
private ulong _elrEl1;
|
||||||
|
private ulong _esrEl1;
|
||||||
|
private ulong _tpidrEl0;
|
||||||
|
private ulong _tpidrroEl0;
|
||||||
|
private ulong _fpcr;
|
||||||
|
private ulong _fpsr;
|
||||||
|
private ulong _pstateRaw;
|
||||||
|
|
||||||
|
private long _fallbackCount;
|
||||||
|
private long _lastWarningTicks;
|
||||||
|
private const long WarningCooldownTicks = 500_000_000; // 0.5 seconds
|
||||||
|
|
||||||
|
private readonly ulong _vcpu;
|
||||||
|
private int _interruptRequested;
|
||||||
|
private readonly object _registerLock = new object();
|
||||||
|
|
||||||
static HvExecutionContextVcpu()
|
static HvExecutionContextVcpu()
|
||||||
{
|
{
|
||||||
// .NET does not support passing vectors by value, so we need to pass a pointer and use a native
|
// .NET does not support passing vectors by value, so we need to pass a pointer and use a native
|
||||||
@@ -33,155 +58,293 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HvExecutionContextVcpu(ulong vcpu)
|
||||||
|
{
|
||||||
|
_vcpu = vcpu;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
lock (_registerLock)
|
||||||
|
{
|
||||||
|
_pstateRaw = 0x80000000UL;
|
||||||
|
_pc = 0;
|
||||||
|
_elrEl1 = 0;
|
||||||
|
_esrEl1 = 0;
|
||||||
|
_tpidrEl0 = 0;
|
||||||
|
_tpidrroEl0 = 0;
|
||||||
|
_fpcr = 0;
|
||||||
|
_fpsr = 0;
|
||||||
|
|
||||||
|
Array.Clear(_x, 0, _x.Length);
|
||||||
|
Array.Clear(_v, 0, _v.Length);
|
||||||
|
|
||||||
|
_fallbackCount = 0;
|
||||||
|
_lastWarningTicks = 0;
|
||||||
|
_interruptRequested = 0;
|
||||||
|
_earlyBootPhase = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogHvWarning(string operation, string regName, string extra = "")
|
||||||
|
{
|
||||||
|
if (AggressiveMode) return;
|
||||||
|
|
||||||
|
long now = DateTime.UtcNow.Ticks;
|
||||||
|
if (now - _lastWarningTicks <= WarningCooldownTicks) return;
|
||||||
|
|
||||||
|
string msg = $"[AppleHv] BadArgument on {operation} {regName} | PC=0x{_pc:X16}";
|
||||||
|
if (!string.IsNullOrEmpty(extra)) msg += $" | {extra}";
|
||||||
|
msg += $" | Total: {Interlocked.Read(ref _fallbackCount)}";
|
||||||
|
|
||||||
|
Logger.Warning?.Print(LogClass.Cpu, msg);
|
||||||
|
_lastWarningTicks = now;
|
||||||
|
}
|
||||||
|
|
||||||
public ulong Pc
|
public ulong Pc
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return GetRegCached(HvReg.PC, ref _pc, "PC"); }
|
||||||
{
|
set { lock (_registerLock) SetRegCached(HvReg.PC, value, ref _pc, "PC"); }
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.PC, out ulong pc).ThrowOnError();
|
|
||||||
return pc;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.PC, value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong ElrEl1
|
public ulong ElrEl1
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return GetSysRegCached(HvSysReg.ELR_EL1, ref _elrEl1, "ELR_EL1"); }
|
||||||
{
|
set { lock (_registerLock) SetSysRegCached(HvSysReg.ELR_EL1, value, ref _elrEl1, "ELR_EL1"); }
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ELR_EL1, out ulong elr).ThrowOnError();
|
|
||||||
return elr;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ELR_EL1, value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong EsrEl1
|
public ulong EsrEl1
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return GetSysRegCached(HvSysReg.ESR_EL1, ref _esrEl1, "ESR_EL1"); }
|
||||||
{
|
set { lock (_registerLock) SetSysRegCached(HvSysReg.ESR_EL1, value, ref _esrEl1, "ESR_EL1"); }
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.ESR_EL1, out ulong esr).ThrowOnError();
|
|
||||||
return esr;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.ESR_EL1, value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long TpidrEl0
|
public long TpidrEl0
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return (long)GetSysRegCached(HvSysReg.TPIDR_EL0, ref _tpidrEl0, "TPIDR_EL0"); }
|
||||||
{
|
set { lock (_registerLock) SetSysRegCached(HvSysReg.TPIDR_EL0, (ulong)value, ref _tpidrEl0, "TPIDR_EL0"); }
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, out ulong tpidrEl0).ThrowOnError();
|
|
||||||
return (long)tpidrEl0;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDR_EL0, (ulong)value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long TpidrroEl0
|
public long TpidrroEl0
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return (long)GetSysRegCached(HvSysReg.TPIDRRO_EL0, ref _tpidrroEl0, "TPIDRRO_EL0"); }
|
||||||
{
|
set { lock (_registerLock) SetSysRegCached(HvSysReg.TPIDRRO_EL0, (ulong)value, ref _tpidrroEl0, "TPIDRRO_EL0"); }
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError();
|
|
||||||
return (long)tpidrroEl0;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.TPIDRRO_EL0, (ulong)value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Pstate
|
public uint Pstate
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.CPSR, out ulong cpsr).ThrowOnError();
|
lock (_registerLock)
|
||||||
return (uint)cpsr;
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_get_reg(_vcpu, HvReg.CPSR, out ulong val);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("Get", "CPSR (Pstate)");
|
||||||
|
return (uint)_pstateRaw;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
_pstateRaw = val;
|
||||||
|
return (uint)val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.CPSR, (ulong)value).ThrowOnError();
|
lock (_registerLock)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_set_reg(_vcpu, HvReg.CPSR, value);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("Set", "CPSR (Pstate)", $"value=0x{value:X}");
|
||||||
|
}
|
||||||
|
else res.ThrowOnError();
|
||||||
|
_pstateRaw = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Fpcr
|
public uint Fpcr
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return (uint)GetRegCached(HvReg.FPCR, ref _fpcr, "FPCR"); }
|
||||||
{
|
set { lock (_registerLock) SetRegCached(HvReg.FPCR, value, ref _fpcr, "FPCR"); }
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPCR, out ulong fpcr).ThrowOnError();
|
|
||||||
return (uint)fpcr;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPCR, (ulong)value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Fpsr
|
public uint Fpsr
|
||||||
{
|
{
|
||||||
get
|
get { lock (_registerLock) return (uint)GetRegCached(HvReg.FPSR, ref _fpsr, "FPSR"); }
|
||||||
{
|
set { lock (_registerLock) SetRegCached(HvReg.FPSR, value, ref _fpsr, "FPSR"); }
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.FPSR, out ulong fpsr).ThrowOnError();
|
|
||||||
return (uint)fpsr;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.FPSR, (ulong)value).ThrowOnError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ulong _vcpu;
|
|
||||||
private int _interruptRequested;
|
|
||||||
|
|
||||||
public HvExecutionContextVcpu(ulong vcpu)
|
|
||||||
{
|
|
||||||
_vcpu = vcpu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetX(int index)
|
public ulong GetX(int index)
|
||||||
{
|
{
|
||||||
if (index == 31)
|
lock (_registerLock)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.SP_EL0, out ulong value).ThrowOnError();
|
ulong value;
|
||||||
return value;
|
string regName = index == 31 ? "SP_EL0" : $"X{index}";
|
||||||
}
|
|
||||||
else
|
if (index == 31)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_reg(_vcpu, HvReg.X0 + (uint)index, out ulong value).ThrowOnError();
|
HvResult res = HvApi.hv_vcpu_get_sys_reg(_vcpu, HvSysReg.SP_EL0, out value);
|
||||||
return value;
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("GetX", regName);
|
||||||
|
return _x[31];
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
return _x[31] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint)index > 30) return 0;
|
||||||
|
|
||||||
|
if (index == 0 && _earlyBootPhase && _pc == 0)
|
||||||
|
{
|
||||||
|
return _x[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
HvResult resX = HvApi.hv_vcpu_get_reg(_vcpu, HvReg.X0 + (uint)index, out value);
|
||||||
|
if (resX == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("GetX", regName);
|
||||||
|
return _x[index];
|
||||||
|
}
|
||||||
|
resX.ThrowOnError();
|
||||||
|
return _x[index] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetX(int index, ulong value)
|
public void SetX(int index, ulong value)
|
||||||
{
|
{
|
||||||
if (index == 31)
|
lock (_registerLock)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.SP_EL0, value).ThrowOnError();
|
string regName = index == 31 ? "SP_EL0" : $"X{index}";
|
||||||
}
|
|
||||||
else
|
if (index == 31)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_set_reg(_vcpu, HvReg.X0 + (uint)index, value).ThrowOnError();
|
HvResult res = HvApi.hv_vcpu_set_sys_reg(_vcpu, HvSysReg.SP_EL0, value);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("SetX", regName, $"value=0x{value:X16}");
|
||||||
|
_x[31] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
_x[31] = value;
|
||||||
|
}
|
||||||
|
else if ((uint)index <= 30)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_set_reg(_vcpu, HvReg.X0 + (uint)index, value);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("SetX", regName, $"value=0x{value:X16}");
|
||||||
|
_x[index] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
_x[index] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public V128 GetV(int index)
|
public V128 GetV(int index)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, HvSimdFPReg.Q0 + (uint)index, out HvSimdFPUchar16 value).ThrowOnError();
|
lock (_registerLock)
|
||||||
return new V128(value.Low, value.High);
|
{
|
||||||
|
if ((uint)index > 31) return default;
|
||||||
|
|
||||||
|
HvResult res = HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, HvSimdFPReg.Q0 + (uint)index, out HvSimdFPUchar16 val);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("GetV", $"Q{index}");
|
||||||
|
return _v[index];
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
return _v[index] = new V128(val.Low, val.High);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetV(int index, V128 value)
|
public void SetV(int index, V128 value)
|
||||||
{
|
{
|
||||||
_setSimdFpReg(_vcpu, HvSimdFPReg.Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError();
|
lock (_registerLock)
|
||||||
|
{
|
||||||
|
if ((uint)index > 31) return;
|
||||||
|
|
||||||
|
HvResult res = _setSimdFpReg(_vcpu, HvSimdFPReg.Q0 + (uint)index, value, _setSimdFpRegNativePtr);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("SetV", $"Q{index}");
|
||||||
|
_v[index] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
_v[index] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong GetRegCached(HvReg reg, ref ulong cached, string name)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_get_reg(_vcpu, reg, out ulong val);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("GetReg", name);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
return cached = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetRegCached(HvReg reg, ulong value, ref ulong cached, string name)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_set_reg(_vcpu, reg, value);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("SetReg", name, $"value=0x{value:X16}");
|
||||||
|
cached = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
cached = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetSysRegCached(HvSysReg reg, ref ulong cached, string name)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_get_sys_reg(_vcpu, reg, out ulong val);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("GetSysReg", name);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
return cached = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSysRegCached(HvSysReg reg, ulong value, ref ulong cached, string name)
|
||||||
|
{
|
||||||
|
HvResult res = HvApi.hv_vcpu_set_sys_reg(_vcpu, reg, value);
|
||||||
|
if (res == HvResult.BadArgument)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _fallbackCount);
|
||||||
|
LogHvWarning("SetSysReg", name, $"value=0x{value:X16}");
|
||||||
|
cached = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.ThrowOnError();
|
||||||
|
cached = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetFallbackCount() => Interlocked.Read(ref _fallbackCount);
|
||||||
|
|
||||||
public void RequestInterrupt()
|
public void RequestInterrupt()
|
||||||
{
|
{
|
||||||
if (Interlocked.Exchange(ref _interruptRequested, 1) == 0)
|
if (Interlocked.Exchange(ref _interruptRequested, 1) == 0)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
|
public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
|
||||||
{
|
{
|
||||||
var allocation = Allocate(size, alignment, CreateBlock);
|
Allocation allocation = Allocate(size, alignment, CreateBlock);
|
||||||
|
|
||||||
return new HvMemoryBlockAllocation(this, allocation.Block, allocation.Offset, allocation.Size);
|
return new HvMemoryBlockAllocation(this, allocation.Block, allocation.Offset, allocation.Size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,17 +237,17 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
List<MemoryRange> guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||||
if (guestRegions == null)
|
if (guestRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
HostMemoryRange[] regions = new HostMemoryRange[guestRegions.Count];
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
for (int i = 0; i < regions.Length; i++)
|
||||||
{
|
{
|
||||||
var guestRegion = guestRegions[i];
|
MemoryRange guestRegion = guestRegions[i];
|
||||||
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
||||||
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
List<MemoryRange> regions = new();
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
// Calculate our time delta in ticks based on the current clock frequency.
|
// Calculate our time delta in ticks based on the current clock frequency.
|
||||||
|
|
||||||
int result = TimeApi.mach_timebase_info(out var timeBaseInfo);
|
int result = TimeApi.mach_timebase_info(out MachTimebaseInfo timeBaseInfo);
|
||||||
|
|
||||||
Debug.Assert(result == 0);
|
Debug.Assert(result == 0);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
|
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec;
|
HvMemoryFlags rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec;
|
||||||
|
|
||||||
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();
|
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using ARMeilleure.Translation.PTC;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu
|
namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
@@ -44,11 +45,10 @@ namespace Ryujinx.Cpu
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the execution engine is recompiling guest code, this can be used to load cached code from disk.
|
/// If the execution engine is recompiling guest code, this can be used to load cached code from disk.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="titleIdText">Title ID of the application in padded hex form</param>
|
/// <param name="cacheInfo">Identity and selector for the process-owned disk cache</param>
|
||||||
/// <param name="displayVersion">Version of the application</param>
|
|
||||||
/// <param name="enabled">True if the cache should be loaded from disk if it exists, false otherwise</param>
|
/// <param name="enabled">True if the cache should be loaded from disk if it exists, false otherwise</param>
|
||||||
/// <returns>Disk cache load progress reporter and manager</returns>
|
/// <returns>Disk cache load progress reporter and manager</returns>
|
||||||
IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector);
|
IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that code has been loaded into guest memory, and that it might be executed in the future.
|
/// Indicates that code has been loaded into guest memory, and that it might be executed in the future.
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked
|
|||||||
Debug.Assert(leftSize > 0);
|
Debug.Assert(leftSize > 0);
|
||||||
Debug.Assert(rightSize > 0);
|
Debug.Assert(rightSize > 0);
|
||||||
|
|
||||||
(var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
|
(PrivateMemoryAllocation leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
|
||||||
|
|
||||||
PrivateMapping left = new(Address, leftSize, leftAllocation);
|
PrivateMapping left = new(Address, leftSize, leftAllocation);
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user