mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-09-27 23:57:57 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3bfce3378 | ||
|
|
88e8d1309c | ||
|
|
ebeb532099 | ||
|
|
c501fe264b | ||
|
|
61d0430006 | ||
|
|
cd477cf744 | ||
|
|
0487b781dc | ||
|
|
51b32981b6 | ||
|
|
fa682d406e | ||
|
|
503dea74c2 | ||
|
|
1f979e5c6f | ||
|
|
378dc33cca | ||
|
|
9c37a557dd | ||
|
|
6e5bd0c9f2 | ||
|
|
0f2b11d4d5 | ||
|
|
1abf5b82c5 | ||
|
|
d751cfa81a | ||
|
|
af14fadb2f | ||
|
|
4fd4e3a4ff | ||
|
|
a1834900be | ||
|
|
fe7a30c747 | ||
|
|
3a387309b4 | ||
|
|
867a92a8bc | ||
|
|
45bf443c01 | ||
|
|
a09568d1b7 | ||
|
|
dae7ae7eaf | ||
|
|
c2f54d0a5c | ||
|
|
f4dfdd35b2 | ||
|
|
c56d04a9a9 | ||
|
|
5c6175cebf | ||
|
|
9addccb50f | ||
|
|
17946c78e6 | ||
|
|
29647b6351 | ||
|
|
6e6983799e | ||
|
|
61da23cb9e | ||
|
|
a62deb8cfd | ||
|
|
8ea79ae5d5 | ||
|
|
09f3bf4b55 | ||
|
|
171624e7f0 | ||
|
|
01cb33f658 | ||
|
|
121bb5dc76 | ||
|
|
d73ef0e3fb | ||
|
|
46b2da2435 | ||
|
|
aca897c70c | ||
|
|
e7d423cd07 | ||
|
|
48c809a80d | ||
|
|
7fd01214cf | ||
|
|
ef72e9b790 | ||
|
|
d5c9bc662c | ||
|
|
3cf90e808d | ||
|
|
326f744093 | ||
|
|
6cecbaa625 | ||
|
|
1443e1a2ff | ||
|
|
12d7f95468 | ||
|
|
b59a833467 | ||
|
|
50a2caf799 | ||
|
|
7d1fd99d3d | ||
|
|
c16559f20e | ||
|
|
6ecd6111d5 | ||
|
|
0ee71fa064 | ||
|
|
6e8f7e7fcb | ||
|
|
f9780b33bb | ||
|
|
d2a532f971 | ||
|
|
a90db3464d | ||
|
|
c61d171e52 | ||
|
|
8927a78c4d | ||
|
|
aa836dd924 | ||
|
|
878ea70aa9 | ||
|
|
9f0a35ee9b | ||
|
|
ed0ebdec5b | ||
|
|
b5a1272141 | ||
|
|
6768e1fa71 | ||
|
|
5c2d710fbb | ||
|
|
d3f3eacc41 | ||
|
|
5983cb9e5f | ||
|
|
e09f16838e | ||
|
|
18f302c0b0 | ||
|
|
8f77076117 |
+24
-24
@@ -3,41 +3,41 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
<PackageVersion Include="Avalonia" Version="11.3.6" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.6" />
|
||||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
|
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.6.2" />
|
||||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
|
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.6.2" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
<PackageVersion Include="DynamicData" Version="9.4.1" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI.NoAnim" Version="2.4.0-build2" />
|
||||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||||
<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.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.9.0" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.14.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<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" />
|
||||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||||
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Core" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
<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.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.24.3" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.2-build4" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.3-build5" />
|
||||||
<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.2-build4" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.3-build5" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.20.0-alpha.103" />
|
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.116" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS-Redux" Version="2.32.6" />
|
<PackageVersion Include="Ryujinx.SDL2-CS-Redux" Version="2.32.10" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.5" />
|
<PackageVersion Include="System.IO.Hashing" Version="9.0.9" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.5" />
|
<PackageVersion Include="System.Management" Version="9.0.9" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
+2
-4
@@ -3,14 +3,12 @@
|
|||||||
<packageSources>
|
<packageSources>
|
||||||
<clear />
|
<clear />
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||||
|
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
||||||
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />
|
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />
|
||||||
</packageSources>
|
</packageSources>
|
||||||
|
|
||||||
<!-- Define mappings by adding package patterns beneath the target source. -->
|
|
||||||
<!-- Ryujinx.LibHac packages will be restored from LibHacAlpha,
|
|
||||||
everything else from nuget.org. -->
|
|
||||||
<packageSourceMapping>
|
<packageSourceMapping>
|
||||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||||
|
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
|
||||||
<packageSource key="nuget.org">
|
<packageSource key="nuget.org">
|
||||||
<package pattern="*" />
|
<package pattern="*" />
|
||||||
</packageSource>
|
</packageSource>
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||||
{
|
{
|
||||||
return inst == Instruction.Load || inst == Instruction.Store;
|
return inst is Instruction.Load or Instruction.Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
||||||
// Any value OR all ones will be equal all ones, so one can just use MOV.
|
// Any value OR all ones will be equal all ones, so one can just use MOV.
|
||||||
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
||||||
if (value == 0 || value == ulong.MaxValue)
|
if (value is 0 or ulong.MaxValue)
|
||||||
{
|
{
|
||||||
immN = 0;
|
immN = 0;
|
||||||
immS = 0;
|
immS = 0;
|
||||||
|
|||||||
@@ -189,8 +189,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
// The only blocks which can have 0 successors are exit blocks.
|
// The only blocks which can have 0 successors are exit blocks.
|
||||||
Operation last = block.Operations.Last;
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
||||||
last.Instruction == Instruction.Return);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -464,7 +463,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
Debug.Assert(dest.Type != source.Type);
|
Debug.Assert(dest.Type != source.Type);
|
||||||
Debug.Assert(source.Type != OperandType.V128);
|
Debug.Assert(source.Type != OperandType.V128);
|
||||||
|
|
||||||
@@ -483,7 +482,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
Debug.Assert(dest.Type != source.Type);
|
Debug.Assert(dest.Type != source.Type);
|
||||||
Debug.Assert(source.Type.IsInteger());
|
Debug.Assert(source.Type.IsInteger());
|
||||||
|
|
||||||
@@ -1463,7 +1462,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static bool IsLoadOrStore(Operation operation)
|
private static bool IsLoadOrStore(Operation operation)
|
||||||
{
|
{
|
||||||
return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store;
|
return operation.Instruction is Instruction.Load or Instruction.Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OperandType GetMemOpValueType(Operation operation)
|
private static OperandType GetMemOpValueType(Operation operation)
|
||||||
@@ -1553,7 +1552,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static void EnsureSameReg(Operand op1, Operand op2)
|
private static void EnsureSameReg(Operand op1, Operand op2)
|
||||||
{
|
{
|
||||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||||
Debug.Assert(op1.Kind == op2.Kind);
|
Debug.Assert(op1.Kind == op2.Kind);
|
||||||
Debug.Assert(op1.Value == op2.Value);
|
Debug.Assert(op1.Value == op2.Value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -736,19 +736,19 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||||
|
|
||||||
return info.Type == IntrinsicType.ScalarBinaryRd ||
|
return info.Type is IntrinsicType.ScalarBinaryRd
|
||||||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
or IntrinsicType.ScalarTernaryFPRdByElem
|
||||||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
or IntrinsicType.ScalarTernaryShlRd
|
||||||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
or IntrinsicType.ScalarTernaryShrRd
|
||||||
info.Type == IntrinsicType.Vector128BinaryRd ||
|
or IntrinsicType.Vector128BinaryRd
|
||||||
info.Type == IntrinsicType.VectorBinaryRd ||
|
or IntrinsicType.VectorBinaryRd
|
||||||
info.Type == IntrinsicType.VectorInsertByElem ||
|
or IntrinsicType.VectorInsertByElem
|
||||||
info.Type == IntrinsicType.VectorTernaryRd ||
|
or IntrinsicType.VectorTernaryRd
|
||||||
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
|
or IntrinsicType.VectorTernaryRdBitwise
|
||||||
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
|
or IntrinsicType.VectorTernaryFPRdByElem
|
||||||
info.Type == IntrinsicType.VectorTernaryRdByElem ||
|
or IntrinsicType.VectorTernaryRdByElem
|
||||||
info.Type == IntrinsicType.VectorTernaryShlRd ||
|
or IntrinsicType.VectorTernaryShlRd
|
||||||
info.Type == IntrinsicType.VectorTernaryShrRd;
|
or IntrinsicType.VectorTernaryShrRd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasConstSrc1(Operation node, ulong value)
|
private static bool HasConstSrc1(Operation node, ulong value)
|
||||||
@@ -849,7 +849,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
var compType = (Comparison)comp.AsInt32();
|
var compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an empty <see cref="RelocInfo"/>.
|
/// Gets an empty <see cref="RelocInfo"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static RelocInfo Empty { get; } = new RelocInfo(null);
|
public static RelocInfo Empty { get; } = new(null);
|
||||||
|
|
||||||
private readonly RelocEntry[] _entries;
|
private readonly RelocEntry[] _entries;
|
||||||
|
|
||||||
|
|||||||
@@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||||||
|
|
||||||
private static bool HasSideEffects(Operation node)
|
private static bool HasSideEffects(Operation node)
|
||||||
{
|
{
|
||||||
return node.Instruction == Instruction.Call
|
return node.Instruction is Instruction.Call
|
||||||
|| node.Instruction == Instruction.Tailcall
|
or Instruction.Tailcall
|
||||||
|| node.Instruction == Instruction.CompareAndSwap
|
or Instruction.CompareAndSwap
|
||||||
|| node.Instruction == Instruction.CompareAndSwap16
|
or Instruction.CompareAndSwap16
|
||||||
|| node.Instruction == Instruction.CompareAndSwap8;
|
or Instruction.CompareAndSwap8;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPropagableCompare(Operation operation)
|
private static bool IsPropagableCompare(Operation operation)
|
||||||
|
|||||||
@@ -839,7 +839,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
dest.NumberLocal(_intervals.Count);
|
dest.NumberLocal(_intervals.Count);
|
||||||
|
|
||||||
LiveInterval interval = new LiveInterval(dest);
|
LiveInterval interval = new(dest);
|
||||||
_intervals.Add(interval);
|
_intervals.Add(interval);
|
||||||
|
|
||||||
SetVisited(dest);
|
SetVisited(dest);
|
||||||
@@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
||||||
// This is used for register preferencing later on, which allows the copy to be eliminated
|
// This is used for register preferencing later on, which allows the copy to be eliminated
|
||||||
// in some cases.
|
// in some cases.
|
||||||
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
|
if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32)
|
||||||
{
|
{
|
||||||
Operand source = node.GetSource(0);
|
Operand source = node.GetSource(0);
|
||||||
|
|
||||||
@@ -1120,8 +1120,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private static bool IsLocalOrRegister(OperandKind kind)
|
private static bool IsLocalOrRegister(OperandKind kind)
|
||||||
{
|
{
|
||||||
return kind == OperandKind.LocalVariable ||
|
return kind is OperandKind.LocalVariable or OperandKind.Register;
|
||||||
kind == OperandKind.Register;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1477,7 +1477,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static bool Is64Bits(OperandType type)
|
private static bool Is64Bits(OperandType type)
|
||||||
{
|
{
|
||||||
return type == OperandType.I64 || type == OperandType.FP64;
|
return type is OperandType.I64 or OperandType.FP64;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsImm8(ulong immediate, OperandType type)
|
private static bool IsImm8(ulong immediate, OperandType type)
|
||||||
|
|||||||
@@ -175,8 +175,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// The only blocks which can have 0 successors are exit blocks.
|
// The only blocks which can have 0 successors are exit blocks.
|
||||||
Operation last = block.Operations.Last;
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
||||||
last.Instruction == Instruction.Return);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -478,7 +477,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
||||||
|
|
||||||
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
||||||
Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory);
|
Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory);
|
||||||
|
|
||||||
EnsureSameType(dest, src1, src2, src3);
|
EnsureSameType(dest, src1, src2, src3);
|
||||||
Debug.Assert(dest.Type == OperandType.V128);
|
Debug.Assert(dest.Type == OperandType.V128);
|
||||||
@@ -788,7 +787,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
if (dest.Type == OperandType.FP32)
|
if (dest.Type == OperandType.FP32)
|
||||||
{
|
{
|
||||||
@@ -1723,7 +1722,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||||
Debug.Assert(op1.Kind == op2.Kind);
|
Debug.Assert(op1.Kind == op2.Kind);
|
||||||
Debug.Assert(op1.Value == op2.Value);
|
Debug.Assert(op1.Value == op2.Value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,9 +312,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
case Instruction.Extended:
|
case Instruction.Extended:
|
||||||
{
|
{
|
||||||
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
|
bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd
|
||||||
node.Intrinsic == Intrinsic.X86Blendvps ||
|
or Intrinsic.X86Blendvps
|
||||||
node.Intrinsic == Intrinsic.X86Pblendvb;
|
or Intrinsic.X86Pblendvb;
|
||||||
|
|
||||||
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
||||||
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
||||||
@@ -513,8 +513,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand dest = node.Destination;
|
Operand dest = node.Destination;
|
||||||
Operand source = node.GetSource(0);
|
Operand source = node.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type == OperandType.FP32 ||
|
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64,
|
||||||
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
$"Invalid destination type \"{dest.Type}\".");
|
||||||
|
|
||||||
Operation currentNode = node;
|
Operation currentNode = node;
|
||||||
|
|
||||||
@@ -761,7 +761,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
var compType = (Comparison)comp.AsInt32();
|
var compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||||
{
|
{
|
||||||
return inst == Instruction.Load ||
|
return inst is Instruction.Load
|
||||||
inst == Instruction.Load16 ||
|
or Instruction.Load16
|
||||||
inst == Instruction.Load8 ||
|
or Instruction.Load8
|
||||||
inst == Instruction.Store ||
|
or Instruction.Store
|
||||||
inst == Instruction.Store16 ||
|
or Instruction.Store16
|
||||||
inst == Instruction.Store8;
|
or Instruction.Store8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,8 +254,7 @@ namespace ARMeilleure.Decoders
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare and branch instructions are always conditional.
|
// Compare and branch instructions are always conditional.
|
||||||
if (opCode.Instruction.Name == InstName.Cbz ||
|
if (opCode.Instruction.Name is InstName.Cbz or InstName.Cbnz)
|
||||||
opCode.Instruction.Name == InstName.Cbnz)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -284,7 +283,7 @@ namespace ARMeilleure.Decoders
|
|||||||
// register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
|
// register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
|
||||||
// a write back to PC (wback == true && Rn == 15), however the later may
|
// a write back to PC (wback == true && Rn == 15), however the later may
|
||||||
// be "undefined" depending on the CPU, so compilers should not produce that.
|
// be "undefined" depending on the CPU, so compilers should not produce that.
|
||||||
if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult)
|
if (opCode is IOpCode32Mem or IOpCode32MemMult)
|
||||||
{
|
{
|
||||||
int rt, rn;
|
int rt, rn;
|
||||||
|
|
||||||
@@ -326,15 +325,12 @@ namespace ARMeilleure.Decoders
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Explicit branch instructions.
|
// Explicit branch instructions.
|
||||||
return opCode is IOpCode32BImm ||
|
return opCode is IOpCode32BImm or IOpCode32BReg;
|
||||||
opCode is IOpCode32BReg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsCall(OpCode opCode)
|
private static bool IsCall(OpCode opCode)
|
||||||
{
|
{
|
||||||
return opCode.Instruction.Name == InstName.Bl ||
|
return opCode.Instruction.Name is InstName.Bl or InstName.Blr or InstName.Blx;
|
||||||
opCode.Instruction.Name == InstName.Blr ||
|
|
||||||
opCode.Instruction.Name == InstName.Blx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsException(OpCode opCode)
|
private static bool IsException(OpCode opCode)
|
||||||
@@ -344,9 +340,7 @@ namespace ARMeilleure.Decoders
|
|||||||
|
|
||||||
private static bool IsTrap(OpCode opCode)
|
private static bool IsTrap(OpCode opCode)
|
||||||
{
|
{
|
||||||
return opCode.Instruction.Name == InstName.Brk ||
|
return opCode.Instruction.Name is InstName.Brk or InstName.Trap or InstName.Und;
|
||||||
opCode.Instruction.Name == InstName.Trap ||
|
|
||||||
opCode.Instruction.Name == InstName.Und;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode)
|
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode)
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ namespace ARMeilleure.Decoders
|
|||||||
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
|
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
|
||||||
|
|
||||||
PostIdx = type == MemOp.PostIndexed;
|
PostIdx = type == MemOp.PostIndexed;
|
||||||
Unscaled = type == MemOp.Unscaled ||
|
Unscaled = type is MemOp.Unscaled or MemOp.Unprivileged;
|
||||||
type == MemOp.Unprivileged;
|
|
||||||
|
|
||||||
// Unscaled and Unprivileged doesn't write back,
|
// Unscaled and Unprivileged doesn't write back,
|
||||||
// but they do use the 9-bits Signed Immediate.
|
// but they do use the 9-bits Signed Immediate.
|
||||||
|
|||||||
@@ -235,8 +235,7 @@ namespace ARMeilleure.Diagnostics
|
|||||||
{
|
{
|
||||||
_builder.Append('.').Append(operation.Intrinsic);
|
_builder.Append('.').Append(operation.Intrinsic);
|
||||||
}
|
}
|
||||||
else if (operation.Instruction == Instruction.BranchIf ||
|
else if (operation.Instruction is Instruction.BranchIf or Instruction.Compare)
|
||||||
operation.Instruction == Instruction.Compare)
|
|
||||||
{
|
{
|
||||||
comparison = true;
|
comparison = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(op.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Svc(ArmEmitterContext context)
|
public static void Svc(ArmEmitterContext context)
|
||||||
@@ -49,7 +49,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(op.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(context.CurrOp.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(context.CurrOp.Address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||||
|
|
||||||
context.Return(GetIntOrZR(context, op.Rn));
|
EmitReturn(context, GetIntOrZR(context, op.Rn));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
static class InstEmitFlowHelper
|
static class InstEmitFlowHelper
|
||||||
{
|
{
|
||||||
|
// How many calls we can have in our call stack before we give up and return to the dispatcher.
|
||||||
|
// This prevents stack overflows caused by deep recursive calls.
|
||||||
|
private const int MaxCallDepth = 200;
|
||||||
|
|
||||||
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
||||||
{
|
{
|
||||||
if (cond != Condition.Al)
|
if (cond != Condition.Al)
|
||||||
@@ -142,6 +146,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitCall(ArmEmitterContext context, ulong immediate)
|
public static void EmitCall(ArmEmitterContext context, ulong immediate)
|
||||||
{
|
{
|
||||||
|
if (context.IsSingleStep)
|
||||||
|
{
|
||||||
|
context.Return(Const(immediate));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool isRecursive = immediate == context.EntryAddress;
|
bool isRecursive = immediate == context.EntryAddress;
|
||||||
|
|
||||||
if (isRecursive)
|
if (isRecursive)
|
||||||
@@ -156,12 +166,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
|
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
|
||||||
{
|
{
|
||||||
EmitTableBranch(context, target, isJump: false);
|
if (context.IsSingleStep)
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
|
||||||
{
|
|
||||||
if (isReturn)
|
|
||||||
{
|
{
|
||||||
if (target.Type == OperandType.I32)
|
if (target.Type == OperandType.I32)
|
||||||
{
|
{
|
||||||
@@ -171,11 +176,36 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Return(target);
|
context.Return(target);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
EmitTableBranch(context, target, isJump: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
||||||
|
{
|
||||||
|
if (isReturn || context.IsSingleStep)
|
||||||
|
{
|
||||||
|
EmitReturn(context, target);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
EmitTableBranch(context, target, isJump: true);
|
EmitTableBranch(context, target, isJump: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitReturn(ArmEmitterContext context, Operand target)
|
||||||
|
{
|
||||||
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
|
if (target.Type == OperandType.I32)
|
||||||
|
{
|
||||||
|
target = context.ZeroExtend32(OperandType.I64, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Return(target);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
||||||
{
|
{
|
||||||
context.StoreToContext();
|
context.StoreToContext();
|
||||||
@@ -238,6 +268,8 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (isJump)
|
if (isJump)
|
||||||
{
|
{
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
context.Tailcall(hostAddress, nativeContext);
|
context.Tailcall(hostAddress, nativeContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -259,8 +291,42 @@ namespace ARMeilleure.Instructions
|
|||||||
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
||||||
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
||||||
|
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
context.Return(returnAddress);
|
context.Return(returnAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitCallDepthCheckAndIncrement(EmitterContext context, Operand guestAddress)
|
||||||
|
{
|
||||||
|
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
|
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||||
|
Operand lblDoCall = Label();
|
||||||
|
|
||||||
|
context.BranchIf(lblDoCall, currentCallDepth, Const(MaxCallDepth), Comparison.LessUI);
|
||||||
|
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||||
|
context.Return(guestAddress);
|
||||||
|
|
||||||
|
context.MarkLabel(lblDoCall);
|
||||||
|
context.Store(callDepthAddr, context.Add(currentCallDepth, Const(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DecreaseCallDepth(EmitterContext context, Operand nativeContext)
|
||||||
|
{
|
||||||
|
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||||
|
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (pair)
|
if (pair)
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
|
Debug.Assert(op.Size is 2 or 3, "Invalid size for pairwise store.");
|
||||||
|
|
||||||
Operand t2 = GetIntOrZR(context, op.Rt2);
|
Operand t2 = GetIntOrZR(context, op.Rt2);
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand value = GetInt(context, rt);
|
Operand value = GetInt(context, rt);
|
||||||
|
|
||||||
if (ext == Extension.Sx32 || ext == Extension.Sx64)
|
if (ext is Extension.Sx32 or Extension.Sx64)
|
||||||
{
|
{
|
||||||
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
|
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
|
||||||
|
|
||||||
@@ -124,8 +124,7 @@ namespace ARMeilleure.Instructions
|
|||||||
private static bool IsSimd(ArmEmitterContext context)
|
private static bool IsSimd(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
return context.CurrOp is IOpCodeSimd &&
|
return context.CurrOp is IOpCodeSimd &&
|
||||||
!(context.CurrOp is OpCodeSimdMemMs ||
|
!(context.CurrOp is OpCodeSimdMemMs or OpCodeSimdMemSs);
|
||||||
context.CurrOp is OpCodeSimdMemSs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
|
public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
|
||||||
|
|||||||
@@ -1119,7 +1119,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
|
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||||
Debug.Assert((uint)size < 2);
|
Debug.Assert((uint)size < 2);
|
||||||
|
|
||||||
OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64;
|
OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64;
|
||||||
@@ -1136,7 +1136,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits)
|
private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
value = EmitF2iFBitsMul(context, value, fBits);
|
value = EmitF2iFBitsMul(context, value, fBits);
|
||||||
|
|
||||||
@@ -1160,7 +1160,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
value = EmitF2iFBitsMul(context, value, fBits);
|
value = EmitF2iFBitsMul(context, value, fBits);
|
||||||
|
|
||||||
@@ -1184,7 +1184,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
if (fBits == 0)
|
if (fBits == 0)
|
||||||
{
|
{
|
||||||
@@ -1203,7 +1203,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
if (fBits == 0)
|
if (fBits == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -635,7 +635,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
|
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||||
|
|
||||||
if (signed)
|
if (signed)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
Debug.Assert(op.Type is OperandType.I32 or OperandType.I64);
|
||||||
|
|
||||||
Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L)));
|
Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L)));
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
Debug.Assert(op.Type is OperandType.FP32 or OperandType.FP64);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lbl2 = Label();
|
Operand lbl2 = Label();
|
||||||
@@ -1676,7 +1676,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSize = 8 << size;
|
int eSize = 8 << size;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
@@ -1709,7 +1709,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSize = 8 << size;
|
int eSize = 8 << size;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
@@ -1735,7 +1735,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSizeDst = 8 << sizeDst;
|
int eSizeDst = 8 << sizeDst;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
@@ -1768,7 +1768,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSizeDst = 8 << sizeDst;
|
int eSizeDst = 8 << sizeDst;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||||
|
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Debug.Assert(type != OperandType.V128);
|
Debug.Assert(type != OperandType.V128);
|
||||||
|
|
||||||
if (type == OperandType.FP64 || type == OperandType.I64)
|
if (type is OperandType.FP64 or OperandType.I64)
|
||||||
{
|
{
|
||||||
// From dreg.
|
// From dreg.
|
||||||
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
||||||
@@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Debug.Assert(value.Type != OperandType.V128);
|
Debug.Assert(value.Type != OperandType.V128);
|
||||||
|
|
||||||
Operand vec, insert;
|
Operand vec, insert;
|
||||||
if (value.Type == OperandType.FP64 || value.Type == OperandType.I64)
|
if (value.Type is OperandType.FP64 or OperandType.I64)
|
||||||
{
|
{
|
||||||
// From dreg.
|
// From dreg.
|
||||||
vec = GetVecA32(reg >> 1);
|
vec = GetVecA32(reg >> 1);
|
||||||
@@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value)
|
public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value)
|
||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32);
|
Debug.Assert(value.Type is OperandType.FP32 or OperandType.I32);
|
||||||
|
|
||||||
Operand vec, insert;
|
Operand vec, insert;
|
||||||
vec = GetVecA32(reg >> 2);
|
vec = GetVecA32(reg >> 2);
|
||||||
|
|||||||
@@ -1634,7 +1634,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSize = 8 << size;
|
int eSize = 8 << size;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand res = context.AllocateLocal(OperandType.I64);
|
Operand res = context.AllocateLocal(OperandType.I64);
|
||||||
|
|
||||||
@@ -1657,7 +1657,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int eSize = 8 << size;
|
int eSize = 8 << size;
|
||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
@@ -1732,7 +1732,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
@@ -1769,7 +1769,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lbl2 = Label();
|
Operand lbl2 = Label();
|
||||||
|
|||||||
@@ -1,59 +1,35 @@
|
|||||||
using System;
|
using System;
|
||||||
#if ANDROID
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
#else
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
static class MathHelper
|
static class MathHelper
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double Abs(double value)
|
public static double Abs(double value)
|
||||||
{
|
{
|
||||||
return Math.Abs(value);
|
return Math.Abs(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double Ceiling(double value)
|
public static double Ceiling(double value)
|
||||||
{
|
{
|
||||||
return Math.Ceiling(value);
|
return Math.Ceiling(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double Floor(double value)
|
public static double Floor(double value)
|
||||||
{
|
{
|
||||||
return Math.Floor(value);
|
return Math.Floor(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double Round(double value, int mode)
|
public static double Round(double value, int mode)
|
||||||
{
|
{
|
||||||
return Math.Round(value, (MidpointRounding)mode);
|
return Math.Round(value, (MidpointRounding)mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double Truncate(double value)
|
public static double Truncate(double value)
|
||||||
{
|
{
|
||||||
return Math.Truncate(value);
|
return Math.Truncate(value);
|
||||||
@@ -62,51 +38,31 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class MathHelperF
|
static class MathHelperF
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float Abs(float value)
|
public static float Abs(float value)
|
||||||
{
|
{
|
||||||
return MathF.Abs(value);
|
return MathF.Abs(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float Ceiling(float value)
|
public static float Ceiling(float value)
|
||||||
{
|
{
|
||||||
return MathF.Ceiling(value);
|
return MathF.Ceiling(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float Floor(float value)
|
public static float Floor(float value)
|
||||||
{
|
{
|
||||||
return MathF.Floor(value);
|
return MathF.Floor(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float Round(float value, int mode)
|
public static float Round(float value, int mode)
|
||||||
{
|
{
|
||||||
return MathF.Round(value, (MidpointRounding)mode);
|
return MathF.Round(value, (MidpointRounding)mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float Truncate(float value)
|
public static float Truncate(float value)
|
||||||
{
|
{
|
||||||
return MathF.Truncate(value);
|
return MathF.Truncate(value);
|
||||||
|
|||||||
@@ -2,11 +2,7 @@ using ARMeilleure.Memory;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
#if ANDROID
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
#else
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
@@ -39,11 +35,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Context = null;
|
Context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void Break(ulong address, int imm)
|
public static void Break(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -53,11 +45,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void SupervisorCall(ulong address, int imm)
|
public static void SupervisorCall(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -67,11 +55,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void Undefined(ulong address, int opCode)
|
public static void Undefined(ulong address, int opCode)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -82,51 +66,31 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region "System registers"
|
#region "System registers"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong GetCtrEl0()
|
public static ulong GetCtrEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CtrEl0;
|
return GetContext().CtrEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong GetDczidEl0()
|
public static ulong GetDczidEl0()
|
||||||
{
|
{
|
||||||
return GetContext().DczidEl0;
|
return GetContext().DczidEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong GetCntfrqEl0()
|
public static ulong GetCntfrqEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntfrqEl0;
|
return GetContext().CntfrqEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong GetCntpctEl0()
|
public static ulong GetCntpctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntpctEl0;
|
return GetContext().CntpctEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong GetCntvctEl0()
|
public static ulong GetCntvctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntvctEl0;
|
return GetContext().CntvctEl0;
|
||||||
@@ -134,51 +98,31 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Read"
|
#region "Read"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static byte ReadByte(ulong address)
|
public static byte ReadByte(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<byte>(address);
|
return GetMemoryManager().ReadGuest<byte>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ushort ReadUInt16(ulong address)
|
public static ushort ReadUInt16(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ushort>(address);
|
return GetMemoryManager().ReadGuest<ushort>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint ReadUInt32(ulong address)
|
public static uint ReadUInt32(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<uint>(address);
|
return GetMemoryManager().ReadGuest<uint>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong ReadUInt64(ulong address)
|
public static ulong ReadUInt64(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ulong>(address);
|
return GetMemoryManager().ReadGuest<ulong>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static V128 ReadVector128(ulong address)
|
public static V128 ReadVector128(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<V128>(address);
|
return GetMemoryManager().ReadGuest<V128>(address);
|
||||||
@@ -186,92 +130,56 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Write"
|
#region "Write"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void WriteByte(ulong address, byte value)
|
public static void WriteByte(ulong address, byte value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void WriteUInt16(ulong address, ushort value)
|
public static void WriteUInt16(ulong address, ushort value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void WriteUInt32(ulong address, uint value)
|
public static void WriteUInt32(ulong address, uint value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void WriteUInt64(ulong address, ulong value)
|
public static void WriteUInt64(ulong address, ulong value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void EnqueueForRejit(ulong address)
|
public static void EnqueueForRejit(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
|
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
|
||||||
{
|
{
|
||||||
GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
|
GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void ThrowInvalidMemoryAccess(ulong address)
|
public static void ThrowInvalidMemoryAccess(ulong address)
|
||||||
{
|
{
|
||||||
throw new InvalidAccessException(address);
|
throw new InvalidAccessException(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
@@ -279,28 +187,24 @@ namespace ARMeilleure.Instructions
|
|||||||
return (ulong)function.FuncPointer.ToInt64();
|
return (ulong)function.FuncPointer.ToInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static void InvalidateCacheLine(ulong address)
|
public static void InvalidateCacheLine(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static byte CheckSynchronization()
|
public static byte CheckSynchronization()
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
|
|
||||||
ExecutionContext context = GetContext();
|
ExecutionContext context = GetContext();
|
||||||
|
|
||||||
context.CheckInterrupt();
|
// If debugging, we'll handle interrupts outside
|
||||||
|
if (!Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
context.CheckInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
#if ANDROID
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
#else
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
static class SoftFallback
|
static class SoftFallback
|
||||||
{
|
{
|
||||||
#region "ShrImm64"
|
#region "ShrImm64"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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)
|
||||||
@@ -58,11 +50,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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)
|
||||||
@@ -107,11 +95,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Saturation"
|
#region "Saturation"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static int SatF32ToS32(float value)
|
public static int SatF32ToS32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -123,11 +107,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static long SatF32ToS64(float value)
|
public static long SatF32ToS64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -139,11 +119,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint SatF32ToU32(float value)
|
public static uint SatF32ToU32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -155,11 +131,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong SatF32ToU64(float value)
|
public static ulong SatF32ToU64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -171,11 +143,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static int SatF64ToS32(double value)
|
public static int SatF64ToS32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -187,11 +155,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static long SatF64ToS64(double value)
|
public static long SatF64ToS64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -203,11 +167,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint SatF64ToU32(double value)
|
public static uint SatF64ToU32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -219,11 +179,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ulong SatF64ToU64(double value)
|
public static ulong SatF64ToU64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -237,11 +193,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Count"
|
#region "Count"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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;
|
||||||
@@ -261,11 +213,7 @@ 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];
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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)
|
||||||
@@ -289,81 +237,49 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Table"
|
#region "Table"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
@@ -405,54 +321,22 @@ namespace ARMeilleure.Instructions
|
|||||||
private const uint Crc32RevPoly = 0xedb88320;
|
private const uint Crc32RevPoly = 0xedb88320;
|
||||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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)
|
||||||
@@ -503,41 +387,25 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Aes"
|
#region "Aes"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static V128 InverseMixColumns(V128 value)
|
public static V128 InverseMixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesInvMixColumns(value);
|
return CryptoHelper.AesInvMixColumns(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static V128 MixColumns(V128 value)
|
public static V128 MixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesMixColumns(value);
|
return CryptoHelper.AesMixColumns(value);
|
||||||
@@ -545,11 +413,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha1"
|
#region "Sha1"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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++)
|
||||||
@@ -570,21 +434,13 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static uint FixedRotate(uint hash_e)
|
public static uint FixedRotate(uint hash_e)
|
||||||
{
|
{
|
||||||
return hash_e.Rol(30);
|
return hash_e.Rol(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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++)
|
||||||
@@ -605,11 +461,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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++)
|
||||||
@@ -630,11 +482,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
@@ -645,11 +493,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result ^ (w0_3 ^ w8_11);
|
return result ^ (w0_3 ^ w8_11);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
@@ -694,31 +538,19 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha256"
|
#region "Sha256"
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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();
|
||||||
@@ -737,11 +569,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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();
|
||||||
@@ -843,11 +671,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
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;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -446,7 +446,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
Data* data = null;
|
Data* data = null;
|
||||||
|
|
||||||
// If constant or register, then try to look up in the intern table before allocating.
|
// If constant or register, then try to look up in the intern table before allocating.
|
||||||
if (kind == OperandKind.Constant || kind == OperandKind.Register)
|
if (kind is OperandKind.Constant or OperandKind.Register)
|
||||||
{
|
{
|
||||||
uint hash = (uint)HashCode.Combine(kind, type, value);
|
uint hash = (uint)HashCode.Combine(kind, type, value);
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
{
|
{
|
||||||
public static bool IsInteger(this OperandType type)
|
public static bool IsInteger(this OperandType type)
|
||||||
{
|
{
|
||||||
return type == OperandType.I32 ||
|
return type is OperandType.I32 or OperandType.I64;
|
||||||
type == OperandType.I64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RegisterType ToRegisterType(this OperandType type)
|
public static RegisterType ToRegisterType(this OperandType type)
|
||||||
|
|||||||
@@ -47,12 +47,12 @@ namespace ARMeilleure.Memory
|
|||||||
{
|
{
|
||||||
public static bool IsHostMapped(this MemoryManagerType type)
|
public static bool IsHostMapped(this MemoryManagerType type)
|
||||||
{
|
{
|
||||||
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsHostTracked(this MemoryManagerType type)
|
public static bool IsHostTracked(this MemoryManagerType type)
|
||||||
{
|
{
|
||||||
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe;
|
return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
|
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ namespace ARMeilleure
|
|||||||
|
|
||||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||||
|
public static bool EnableDebugging { get; set; } = false;
|
||||||
|
public static bool EnableDeepCallRecursionProtection { get; set; } = true;
|
||||||
|
|
||||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||||
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.State
|
||||||
{
|
{
|
||||||
@@ -11,7 +12,7 @@ namespace ARMeilleure.State
|
|||||||
|
|
||||||
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
||||||
|
|
||||||
private bool _interrupted;
|
internal bool Interrupted { get; private set; }
|
||||||
|
|
||||||
private readonly ICounter _counter;
|
private readonly ICounter _counter;
|
||||||
|
|
||||||
@@ -68,6 +69,8 @@ namespace ARMeilleure.State
|
|||||||
|
|
||||||
public bool IsAarch32 { get; set; }
|
public bool IsAarch32 { get; set; }
|
||||||
|
|
||||||
|
public ulong ThreadUid { get; set; }
|
||||||
|
|
||||||
internal ExecutionMode ExecutionMode
|
internal ExecutionMode ExecutionMode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -93,14 +96,19 @@ namespace ARMeilleure.State
|
|||||||
|
|
||||||
private readonly ExceptionCallbackNoArgs _interruptCallback;
|
private readonly ExceptionCallbackNoArgs _interruptCallback;
|
||||||
private readonly ExceptionCallback _breakCallback;
|
private readonly ExceptionCallback _breakCallback;
|
||||||
|
private readonly ExceptionCallbackNoArgs _stepCallback;
|
||||||
private readonly ExceptionCallback _supervisorCallback;
|
private readonly ExceptionCallback _supervisorCallback;
|
||||||
private readonly ExceptionCallback _undefinedCallback;
|
private readonly ExceptionCallback _undefinedCallback;
|
||||||
|
|
||||||
|
internal int ShouldStep;
|
||||||
|
public ulong DebugPc { get; set; }
|
||||||
|
|
||||||
public ExecutionContext(
|
public ExecutionContext(
|
||||||
IJitMemoryAllocator allocator,
|
IJitMemoryAllocator allocator,
|
||||||
ICounter counter,
|
ICounter counter,
|
||||||
ExceptionCallbackNoArgs interruptCallback = null,
|
ExceptionCallbackNoArgs interruptCallback = null,
|
||||||
ExceptionCallback breakCallback = null,
|
ExceptionCallback breakCallback = null,
|
||||||
|
ExceptionCallbackNoArgs stepCallback = null,
|
||||||
ExceptionCallback supervisorCallback = null,
|
ExceptionCallback supervisorCallback = null,
|
||||||
ExceptionCallback undefinedCallback = null)
|
ExceptionCallback undefinedCallback = null)
|
||||||
{
|
{
|
||||||
@@ -108,6 +116,7 @@ namespace ARMeilleure.State
|
|||||||
_counter = counter;
|
_counter = counter;
|
||||||
_interruptCallback = interruptCallback;
|
_interruptCallback = interruptCallback;
|
||||||
_breakCallback = breakCallback;
|
_breakCallback = breakCallback;
|
||||||
|
_stepCallback = stepCallback;
|
||||||
_supervisorCallback = supervisorCallback;
|
_supervisorCallback = supervisorCallback;
|
||||||
_undefinedCallback = undefinedCallback;
|
_undefinedCallback = undefinedCallback;
|
||||||
|
|
||||||
@@ -128,11 +137,16 @@ namespace ARMeilleure.State
|
|||||||
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
||||||
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
||||||
|
|
||||||
|
internal void ResetCallDepth()
|
||||||
|
{
|
||||||
|
_nativeContext.ResetCallDepth();
|
||||||
|
}
|
||||||
|
|
||||||
internal void CheckInterrupt()
|
internal void CheckInterrupt()
|
||||||
{
|
{
|
||||||
if (_interrupted)
|
if (Interrupted)
|
||||||
{
|
{
|
||||||
_interrupted = false;
|
Interrupted = false;
|
||||||
|
|
||||||
_interruptCallback?.Invoke(this);
|
_interruptCallback?.Invoke(this);
|
||||||
}
|
}
|
||||||
@@ -142,16 +156,37 @@ namespace ARMeilleure.State
|
|||||||
|
|
||||||
public void RequestInterrupt()
|
public void RequestInterrupt()
|
||||||
{
|
{
|
||||||
_interrupted = true;
|
Interrupted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StepHandler()
|
||||||
|
{
|
||||||
|
_stepCallback?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestDebugStep()
|
||||||
|
{
|
||||||
|
Interlocked.Exchange(ref ShouldStep, 1);
|
||||||
|
RequestInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnBreak(ulong address, int imm)
|
internal void OnBreak(ulong address, int imm)
|
||||||
{
|
{
|
||||||
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
DebugPc = Pc;
|
||||||
|
}
|
||||||
|
|
||||||
_breakCallback?.Invoke(this, address, imm);
|
_breakCallback?.Invoke(this, address, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnSupervisorCall(ulong address, int imm)
|
internal void OnSupervisorCall(ulong address, int imm)
|
||||||
{
|
{
|
||||||
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
DebugPc = Pc;
|
||||||
|
}
|
||||||
|
|
||||||
_supervisorCallback?.Invoke(this, address, imm);
|
_supervisorCallback?.Invoke(this, address, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,14 @@ namespace ARMeilleure.State
|
|||||||
public ulong ExclusiveValueLow;
|
public ulong ExclusiveValueLow;
|
||||||
public ulong ExclusiveValueHigh;
|
public ulong ExclusiveValueHigh;
|
||||||
public int Running;
|
public int Running;
|
||||||
|
public int CallDepth;
|
||||||
public long Tpidr2El0;
|
public long Tpidr2El0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Precise PC value used for debugging.
|
||||||
|
/// This will only be set when Optimizations.EnableDebugging is true.
|
||||||
|
/// </summary>
|
||||||
|
public ulong DebugPrecisePc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NativeCtxStorage _dummyStorage = new();
|
private static NativeCtxStorage _dummyStorage = new();
|
||||||
@@ -39,6 +46,11 @@ namespace ARMeilleure.State
|
|||||||
|
|
||||||
public ulong GetPc()
|
public ulong GetPc()
|
||||||
{
|
{
|
||||||
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
return GetStorage().DebugPrecisePc;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: More precise tracking of PC value.
|
// TODO: More precise tracking of PC value.
|
||||||
return GetStorage().DispatchAddress;
|
return GetStorage().DispatchAddress;
|
||||||
}
|
}
|
||||||
@@ -186,6 +198,8 @@ namespace ARMeilleure.State
|
|||||||
public bool GetRunning() => GetStorage().Running != 0;
|
public bool GetRunning() => GetStorage().Running != 0;
|
||||||
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
||||||
|
|
||||||
|
public void ResetCallDepth() => GetStorage().CallDepth = 0;
|
||||||
|
|
||||||
public unsafe static int GetRegisterOffset(Register reg)
|
public unsafe static int GetRegisterOffset(Register reg)
|
||||||
{
|
{
|
||||||
if (reg.Type == RegisterType.Integer)
|
if (reg.Type == RegisterType.Integer)
|
||||||
@@ -266,6 +280,16 @@ namespace ARMeilleure.State
|
|||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
|
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetDebugPrecisePcOffset()
|
||||||
|
{
|
||||||
|
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetCallDepthOffset()
|
||||||
|
{
|
||||||
|
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
|
||||||
|
}
|
||||||
|
|
||||||
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
||||||
{
|
{
|
||||||
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace ARMeilleure.Translation
|
|||||||
public bool HighCq { get; }
|
public bool HighCq { get; }
|
||||||
public bool HasPtc { get; }
|
public bool HasPtc { get; }
|
||||||
public Aarch32Mode Mode { get; }
|
public Aarch32Mode Mode { get; }
|
||||||
|
public bool IsSingleStep { get; }
|
||||||
|
|
||||||
private int _ifThenBlockStateIndex = 0;
|
private int _ifThenBlockStateIndex = 0;
|
||||||
private Condition[] _ifThenBlockState = [];
|
private Condition[] _ifThenBlockState = [];
|
||||||
@@ -67,7 +68,8 @@ namespace ARMeilleure.Translation
|
|||||||
ulong entryAddress,
|
ulong entryAddress,
|
||||||
bool highCq,
|
bool highCq,
|
||||||
bool hasPtc,
|
bool hasPtc,
|
||||||
Aarch32Mode mode)
|
Aarch32Mode mode,
|
||||||
|
bool isSingleStep)
|
||||||
{
|
{
|
||||||
Memory = memory;
|
Memory = memory;
|
||||||
CountTable = countTable;
|
CountTable = countTable;
|
||||||
@@ -77,6 +79,7 @@ namespace ARMeilleure.Translation
|
|||||||
HighCq = highCq;
|
HighCq = highCq;
|
||||||
HasPtc = hasPtc;
|
HasPtc = hasPtc;
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
|
IsSingleStep = isSingleStep;
|
||||||
|
|
||||||
_labels = new Dictionary<ulong, Operand>();
|
_labels = new Dictionary<ulong, Operand>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
public class DelegateInfo
|
class DelegateInfo
|
||||||
{
|
{
|
||||||
public IntPtr FuncPtr { get; }
|
public IntPtr FuncPtr { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,358 +2,11 @@ using ARMeilleure.Instructions;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#if ANDROID
|
|
||||||
using ARMeilleure.State;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
static class Delegates
|
static class Delegates
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
// MathHelper delegates
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double MathHelperAbsDelegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double MathHelperCeilingDelegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double MathHelperFloorDelegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double MathHelperRoundDelegate(double value, int mode);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double MathHelperTruncateDelegate(double value);
|
|
||||||
|
|
||||||
// MathHelperF delegates
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float MathHelperFAbsDelegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float MathHelperFCeilingDelegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float MathHelperFFloorDelegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float MathHelperFRoundDelegate(float value, int mode);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float MathHelperFTruncateDelegate(float value);
|
|
||||||
|
|
||||||
// NativeInterface delegates
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceBreakDelegate(ulong address, int imm);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate byte NativeInterfaceCheckSynchronizationDelegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceEnqueueForRejitDelegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetCntfrqEl0Delegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetCntpctEl0Delegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetCntvctEl0Delegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetCtrEl0Delegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetDczidEl0Delegate();
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceGetFunctionAddressDelegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceInvalidateCacheLineDelegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate byte NativeInterfaceReadByteDelegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ushort NativeInterfaceReadUInt16Delegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint NativeInterfaceReadUInt32Delegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong NativeInterfaceReadUInt64Delegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 NativeInterfaceReadVector128Delegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceSignalMemoryTrackingDelegate(ulong address, ulong size, byte write);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceSupervisorCallDelegate(ulong address, int imm);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceThrowInvalidMemoryAccessDelegate(ulong address);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceUndefinedDelegate(ulong address, int opCode);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceWriteByteDelegate(ulong address, byte value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceWriteUInt16Delegate(ulong address, ushort value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceWriteUInt32Delegate(ulong address, uint value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceWriteUInt64Delegate(ulong address, ulong value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void NativeInterfaceWriteVector128Delegate(ulong address, V128 value);
|
|
||||||
|
|
||||||
// SoftFallback delegates
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong SoftFallbackCountLeadingSignsDelegate(ulong value, int size);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong SoftFallbackCountLeadingZerosDelegate(ulong value, int size);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32bDelegate(uint crc, byte val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32cbDelegate(uint crc, byte val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32chDelegate(uint crc, ushort val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32cwDelegate(uint crc, uint val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32cxDelegate(uint crc, ulong val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32hDelegate(uint crc, ushort val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32wDelegate(uint crc, uint val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackCrc32xDelegate(uint crc, ulong val);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackDecryptDelegate(V128 value, V128 roundKey);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackEncryptDelegate(V128 value, V128 roundKey);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackFixedRotateDelegate(uint hash_e);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackHashChooseDelegate(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackHashLowerDelegate(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackHashMajorityDelegate(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackHashParityDelegate(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackHashUpperDelegate(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackInverseMixColumnsDelegate(V128 value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackMixColumnsDelegate(V128 value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackPolynomialMult64_128Delegate(ulong op1, ulong op2);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate int SoftFallbackSatF32ToS32Delegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate long SoftFallbackSatF32ToS64Delegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackSatF32ToU32Delegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong SoftFallbackSatF32ToU64Delegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate int SoftFallbackSatF64ToS32Delegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate long SoftFallbackSatF64ToS64Delegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate uint SoftFallbackSatF64ToU32Delegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong SoftFallbackSatF64ToU64Delegate(double value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackSha1SchedulePart1Delegate(V128 w0_3, V128 w4_7, V128 w8_11);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackSha1SchedulePart2Delegate(V128 tw0_3, V128 w12_15);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackSha256SchedulePart1Delegate(V128 w0_3, V128 w4_7);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackSha256SchedulePart2Delegate(V128 w0_3, V128 w8_11, V128 w12_15);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate long SoftFallbackSignedShrImm64Delegate(long value, long roundConst, int shift);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbl1Delegate(V128 vector, int bytes, V128 table);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbl2Delegate(V128 vector, int bytes, V128 table0, V128 table1);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbl3Delegate(V128 vector, int bytes, V128 table0, V128 table1, V128 table2);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbl4Delegate(V128 vector, int bytes, V128 table0, V128 table1, V128 table2, V128 table3);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbx1Delegate(V128 dest, V128 vector, int bytes, V128 table);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbx2Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbx3Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1, V128 table2);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate V128 SoftFallbackTbx4Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1, V128 table2, V128 table3);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ulong SoftFallbackUnsignedShrImm64Delegate(ulong value, long roundConst, int shift);
|
|
||||||
|
|
||||||
// SoftFloat delegates
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat16_32FPConvertDelegate(ushort value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat16_64FPConvertDelegate(ushort value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPAddDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPAddFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate int SoftFloat32FPCompareDelegate(float a, float b, byte signalNaNs);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareEQDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareEQFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareGEDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareGEFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareGTDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareGTFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareLEDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareLEFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareLTDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPCompareLTFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPDivDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMaxDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMaxFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMaxNumDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMaxNumFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMinDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMinFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMinNumDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMinNumFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulFpscrDelegate(float a, float b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulAddDelegate(float a, float b, float c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulAddFpscrDelegate(float a, float b, float c, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulSubDelegate(float a, float b, float c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulSubFpscrDelegate(float a, float b, float c, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPMulXDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPNegMulAddDelegate(float a, float b, float c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPNegMulSubDelegate(float a, float b, float c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRecipEstimateDelegate(float a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRecipEstimateFpscrDelegate(float a, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRecipStepDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRecipStepFusedDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRecpXDelegate(float a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRSqrtEstimateDelegate(float a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRSqrtEstimateFpscrDelegate(float a, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRSqrtStepDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPRSqrtStepFusedDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPSqrtDelegate(float a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate float SoftFloat32FPSubDelegate(float a, float b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ushort SoftFloat32_16FPConvertDelegate(float value);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPAddDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPAddFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate int SoftFloat64FPCompareDelegate(double a, double b, byte signalNaNs);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareEQDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareEQFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareGEDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareGEFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareGTDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareGTFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareLEDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareLEFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareLTDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPCompareLTFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPDivDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMaxDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMaxFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMaxNumDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMaxNumFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMinDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMinFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMinNumDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMinNumFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulFpscrDelegate(double a, double b, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulAddDelegate(double a, double b, double c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulAddFpscrDelegate(double a, double b, double c, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulSubDelegate(double a, double b, double c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulSubFpscrDelegate(double a, double b, double c, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPMulXDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPNegMulAddDelegate(double a, double b, double c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPNegMulSubDelegate(double a, double b, double c);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRecipEstimateDelegate(double a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRecipEstimateFpscrDelegate(double a, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRecipStepDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRecipStepFusedDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRecpXDelegate(double a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRSqrtEstimateDelegate(double a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRSqrtEstimateFpscrDelegate(double a, byte standardFpscr);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRSqrtStepDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPRSqrtStepFusedDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPSqrtDelegate(double a);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate double SoftFloat64FPSubDelegate(double a, double b);
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate ushort SoftFloat64_16FPConvertDelegate(double value);
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, Delegate> _androidDelegates;
|
|
||||||
#endif
|
|
||||||
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr)
|
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < _delegates.Count)
|
if (index >= 0 && index < _delegates.Count)
|
||||||
@@ -400,32 +53,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
string key = GetKey(method);
|
string key = GetKey(method);
|
||||||
|
|
||||||
#if ANDROID
|
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer())); // ArgumentException (key).
|
||||||
if (_androidDelegates.TryGetValue(key, out Delegate del))
|
|
||||||
{
|
|
||||||
IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(del);
|
|
||||||
_delegates.Add(key, new DelegateInfo(funcPtr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer()));
|
|
||||||
}
|
|
||||||
catch (NotSupportedException) when (IsRunningOnAndroid())
|
|
||||||
{
|
|
||||||
throw new PlatformNotSupportedException($"Cannot obtain function pointer {key}: it must be registered.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsRunningOnAndroid()
|
|
||||||
{
|
|
||||||
#if ANDROID
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetKey(MethodInfo info)
|
private static string GetKey(MethodInfo info)
|
||||||
@@ -439,190 +67,6 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
_delegates = new SortedList<string, DelegateInfo>();
|
_delegates = new SortedList<string, DelegateInfo>();
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
_androidDelegates = new Dictionary<string, Delegate>
|
|
||||||
{
|
|
||||||
// MathHelper delegates
|
|
||||||
{ "MathHelper.Abs", new MathHelperAbsDelegate(Math.Abs) },
|
|
||||||
{ "MathHelper.Ceiling", new MathHelperCeilingDelegate(Math.Ceiling) },
|
|
||||||
{ "MathHelper.Floor", new MathHelperFloorDelegate(Math.Floor) },
|
|
||||||
{ "MathHelper.Round", new MathHelperRoundDelegate((value, mode) => Math.Round(value, (MidpointRounding)mode)) },
|
|
||||||
{ "MathHelper.Truncate", new MathHelperTruncateDelegate(Math.Truncate) },
|
|
||||||
|
|
||||||
// MathHelperF delegates
|
|
||||||
{ "MathHelperF.Abs", new MathHelperFAbsDelegate(MathF.Abs) },
|
|
||||||
{ "MathHelperF.Ceiling", new MathHelperFCeilingDelegate(MathF.Ceiling) },
|
|
||||||
{ "MathHelperF.Floor", new MathHelperFFloorDelegate(MathF.Floor) },
|
|
||||||
{ "MathHelperF.Round", new MathHelperFRoundDelegate((value, mode) => MathF.Round(value, (MidpointRounding)mode)) },
|
|
||||||
{ "MathHelperF.Truncate", new MathHelperFTruncateDelegate(MathF.Truncate) },
|
|
||||||
|
|
||||||
// NativeInterface delegates
|
|
||||||
{ "NativeInterface.Break", new NativeInterfaceBreakDelegate(NativeInterface.Break) },
|
|
||||||
{ "NativeInterface.CheckSynchronization", new NativeInterfaceCheckSynchronizationDelegate(NativeInterface.CheckSynchronization) },
|
|
||||||
{ "NativeInterface.EnqueueForRejit", new NativeInterfaceEnqueueForRejitDelegate(NativeInterface.EnqueueForRejit) },
|
|
||||||
{ "NativeInterface.GetCntfrqEl0", new NativeInterfaceGetCntfrqEl0Delegate(NativeInterface.GetCntfrqEl0) },
|
|
||||||
{ "NativeInterface.GetCntpctEl0", new NativeInterfaceGetCntpctEl0Delegate(NativeInterface.GetCntpctEl0) },
|
|
||||||
{ "NativeInterface.GetCntvctEl0", new NativeInterfaceGetCntvctEl0Delegate(NativeInterface.GetCntvctEl0) },
|
|
||||||
{ "NativeInterface.GetCtrEl0", new NativeInterfaceGetCtrEl0Delegate(NativeInterface.GetCtrEl0) },
|
|
||||||
{ "NativeInterface.GetDczidEl0", new NativeInterfaceGetDczidEl0Delegate(NativeInterface.GetDczidEl0) },
|
|
||||||
{ "NativeInterface.GetFunctionAddress", new NativeInterfaceGetFunctionAddressDelegate(NativeInterface.GetFunctionAddress) },
|
|
||||||
{ "NativeInterface.InvalidateCacheLine", new NativeInterfaceInvalidateCacheLineDelegate(NativeInterface.InvalidateCacheLine) },
|
|
||||||
{ "NativeInterface.ReadByte", new NativeInterfaceReadByteDelegate(NativeInterface.ReadByte) },
|
|
||||||
{ "NativeInterface.ReadUInt16", new NativeInterfaceReadUInt16Delegate(NativeInterface.ReadUInt16) },
|
|
||||||
{ "NativeInterface.ReadUInt32", new NativeInterfaceReadUInt32Delegate(NativeInterface.ReadUInt32) },
|
|
||||||
{ "NativeInterface.ReadUInt64", new NativeInterfaceReadUInt64Delegate(NativeInterface.ReadUInt64) },
|
|
||||||
{ "NativeInterface.ReadVector128", new NativeInterfaceReadVector128Delegate(NativeInterface.ReadVector128) },
|
|
||||||
{ "NativeInterface.SignalMemoryTracking", new NativeInterfaceSignalMemoryTrackingDelegate(NativeInterface.SignalMemoryTracking) },
|
|
||||||
{ "NativeInterface.SupervisorCall", new NativeInterfaceSupervisorCallDelegate(NativeInterface.SupervisorCall) },
|
|
||||||
{ "NativeInterface.ThrowInvalidMemoryAccess", new NativeInterfaceThrowInvalidMemoryAccessDelegate(NativeInterface.ThrowInvalidMemoryAccess) },
|
|
||||||
{ "NativeInterface.Undefined", new NativeInterfaceUndefinedDelegate(NativeInterface.Undefined) },
|
|
||||||
{ "NativeInterface.WriteByte", new NativeInterfaceWriteByteDelegate(NativeInterface.WriteByte) },
|
|
||||||
{ "NativeInterface.WriteUInt16", new NativeInterfaceWriteUInt16Delegate(NativeInterface.WriteUInt16) },
|
|
||||||
{ "NativeInterface.WriteUInt32", new NativeInterfaceWriteUInt32Delegate(NativeInterface.WriteUInt32) },
|
|
||||||
{ "NativeInterface.WriteUInt64", new NativeInterfaceWriteUInt64Delegate(NativeInterface.WriteUInt64) },
|
|
||||||
{ "NativeInterface.WriteVector128", new NativeInterfaceWriteVector128Delegate(NativeInterface.WriteVector128) },
|
|
||||||
|
|
||||||
// SoftFallback delegates
|
|
||||||
{ "SoftFallback.CountLeadingSigns", new SoftFallbackCountLeadingSignsDelegate(SoftFallback.CountLeadingSigns) },
|
|
||||||
{ "SoftFallback.CountLeadingZeros", new SoftFallbackCountLeadingZerosDelegate(SoftFallback.CountLeadingZeros) },
|
|
||||||
{ "SoftFallback.Crc32b", new SoftFallbackCrc32bDelegate(SoftFallback.Crc32b) },
|
|
||||||
{ "SoftFallback.Crc32cb", new SoftFallbackCrc32cbDelegate(SoftFallback.Crc32cb) },
|
|
||||||
{ "SoftFallback.Crc32ch", new SoftFallbackCrc32chDelegate(SoftFallback.Crc32ch) },
|
|
||||||
{ "SoftFallback.Crc32cw", new SoftFallbackCrc32cwDelegate(SoftFallback.Crc32cw) },
|
|
||||||
{ "SoftFallback.Crc32cx", new SoftFallbackCrc32cxDelegate(SoftFallback.Crc32cx) },
|
|
||||||
{ "SoftFallback.Crc32h", new SoftFallbackCrc32hDelegate(SoftFallback.Crc32h) },
|
|
||||||
{ "SoftFallback.Crc32w", new SoftFallbackCrc32wDelegate(SoftFallback.Crc32w) },
|
|
||||||
{ "SoftFallback.Crc32x", new SoftFallbackCrc32xDelegate(SoftFallback.Crc32x) },
|
|
||||||
{ "SoftFallback.Decrypt", new SoftFallbackDecryptDelegate(SoftFallback.Decrypt) },
|
|
||||||
{ "SoftFallback.Encrypt", new SoftFallbackEncryptDelegate(SoftFallback.Encrypt) },
|
|
||||||
{ "SoftFallback.FixedRotate", new SoftFallbackFixedRotateDelegate(SoftFallback.FixedRotate) },
|
|
||||||
{ "SoftFallback.HashChoose", new SoftFallbackHashChooseDelegate(SoftFallback.HashChoose) },
|
|
||||||
{ "SoftFallback.HashLower", new SoftFallbackHashLowerDelegate(SoftFallback.HashLower) },
|
|
||||||
{ "SoftFallback.HashMajority", new SoftFallbackHashMajorityDelegate(SoftFallback.HashMajority) },
|
|
||||||
{ "SoftFallback.HashParity", new SoftFallbackHashParityDelegate(SoftFallback.HashParity) },
|
|
||||||
{ "SoftFallback.HashUpper", new SoftFallbackHashUpperDelegate(SoftFallback.HashUpper) },
|
|
||||||
{ "SoftFallback.InverseMixColumns", new SoftFallbackInverseMixColumnsDelegate(SoftFallback.InverseMixColumns) },
|
|
||||||
{ "SoftFallback.MixColumns", new SoftFallbackMixColumnsDelegate(SoftFallback.MixColumns) },
|
|
||||||
{ "SoftFallback.PolynomialMult64_128", new SoftFallbackPolynomialMult64_128Delegate(SoftFallback.PolynomialMult64_128) },
|
|
||||||
{ "SoftFallback.SatF32ToS32", new SoftFallbackSatF32ToS32Delegate(SoftFallback.SatF32ToS32) },
|
|
||||||
{ "SoftFallback.SatF32ToS64", new SoftFallbackSatF32ToS64Delegate(SoftFallback.SatF32ToS64) },
|
|
||||||
{ "SoftFallback.SatF32ToU32", new SoftFallbackSatF32ToU32Delegate(SoftFallback.SatF32ToU32) },
|
|
||||||
{ "SoftFallback.SatF32ToU64", new SoftFallbackSatF32ToU64Delegate(SoftFallback.SatF32ToU64) },
|
|
||||||
{ "SoftFallback.SatF64ToS32", new SoftFallbackSatF64ToS32Delegate(SoftFallback.SatF64ToS32) },
|
|
||||||
{ "SoftFallback.SatF64ToS64", new SoftFallbackSatF64ToS64Delegate(SoftFallback.SatF64ToS64) },
|
|
||||||
{ "SoftFallback.SatF64ToU32", new SoftFallbackSatF64ToU32Delegate(SoftFallback.SatF64ToU32) },
|
|
||||||
{ "SoftFallback.SatF64ToU64", new SoftFallbackSatF64ToU64Delegate(SoftFallback.SatF64ToU64) },
|
|
||||||
{ "SoftFallback.Sha1SchedulePart1", new SoftFallbackSha1SchedulePart1Delegate(SoftFallback.Sha1SchedulePart1) },
|
|
||||||
{ "SoftFallback.Sha1SchedulePart2", new SoftFallbackSha1SchedulePart2Delegate(SoftFallback.Sha1SchedulePart2) },
|
|
||||||
{ "SoftFallback.Sha256SchedulePart1", new SoftFallbackSha256SchedulePart1Delegate(SoftFallback.Sha256SchedulePart1) },
|
|
||||||
{ "SoftFallback.Sha256SchedulePart2", new SoftFallbackSha256SchedulePart2Delegate(SoftFallback.Sha256SchedulePart2) },
|
|
||||||
{ "SoftFallback.SignedShrImm64", new SoftFallbackSignedShrImm64Delegate(SoftFallback.SignedShrImm64) },
|
|
||||||
{ "SoftFallback.Tbl1", new SoftFallbackTbl1Delegate(SoftFallback.Tbl1) },
|
|
||||||
{ "SoftFallback.Tbl2", new SoftFallbackTbl2Delegate(SoftFallback.Tbl2) },
|
|
||||||
{ "SoftFallback.Tbl3", new SoftFallbackTbl3Delegate(SoftFallback.Tbl3) },
|
|
||||||
{ "SoftFallback.Tbl4", new SoftFallbackTbl4Delegate(SoftFallback.Tbl4) },
|
|
||||||
{ "SoftFallback.Tbx1", new SoftFallbackTbx1Delegate(SoftFallback.Tbx1) },
|
|
||||||
{ "SoftFallback.Tbx2", new SoftFallbackTbx2Delegate(SoftFallback.Tbx2) },
|
|
||||||
{ "SoftFallback.Tbx3", new SoftFallbackTbx3Delegate(SoftFallback.Tbx3) },
|
|
||||||
{ "SoftFallback.Tbx4", new SoftFallbackTbx4Delegate(SoftFallback.Tbx4) },
|
|
||||||
{ "SoftFallback.UnsignedShrImm64", new SoftFallbackUnsignedShrImm64Delegate(SoftFallback.UnsignedShrImm64) },
|
|
||||||
|
|
||||||
// SoftFloat delegates
|
|
||||||
{ "SoftFloat16_32.FPConvert", new SoftFloat16_32FPConvertDelegate(SoftFloat16_32.FPConvert) },
|
|
||||||
{ "SoftFloat16_64.FPConvert", new SoftFloat16_64FPConvertDelegate(SoftFloat16_64.FPConvert) },
|
|
||||||
|
|
||||||
{ "SoftFloat32.FPAdd", new SoftFloat32FPAddDelegate(SoftFloat32.FPAdd) },
|
|
||||||
{ "SoftFloat32.FPAddFpscr", new SoftFloat32FPAddFpscrDelegate(SoftFloat32.FPAddFpscr) },
|
|
||||||
{ "SoftFloat32.FPCompare", new SoftFloat32FPCompareDelegate(SoftFloat32.FPCompare) },
|
|
||||||
{ "SoftFloat32.FPCompareEQ", new SoftFloat32FPCompareEQDelegate(SoftFloat32.FPCompareEQ) },
|
|
||||||
{ "SoftFloat32.FPCompareEQFpscr", new SoftFloat32FPCompareEQFpscrDelegate(SoftFloat32.FPCompareEQFpscr) },
|
|
||||||
{ "SoftFloat32.FPCompareGE", new SoftFloat32FPCompareGEDelegate(SoftFloat32.FPCompareGE) },
|
|
||||||
{ "SoftFloat32.FPCompareGEFpscr", new SoftFloat32FPCompareGEFpscrDelegate(SoftFloat32.FPCompareGEFpscr) },
|
|
||||||
{ "SoftFloat32.FPCompareGT", new SoftFloat32FPCompareGTDelegate(SoftFloat32.FPCompareGT) },
|
|
||||||
{ "SoftFloat32.FPCompareGTFpscr", new SoftFloat32FPCompareGTFpscrDelegate(SoftFloat32.FPCompareGTFpscr) },
|
|
||||||
{ "SoftFloat32.FPCompareLE", new SoftFloat32FPCompareLEDelegate(SoftFloat32.FPCompareLE) },
|
|
||||||
{ "SoftFloat32.FPCompareLEFpscr", new SoftFloat32FPCompareLEFpscrDelegate(SoftFloat32.FPCompareLEFpscr) },
|
|
||||||
{ "SoftFloat32.FPCompareLT", new SoftFloat32FPCompareLTDelegate(SoftFloat32.FPCompareLT) },
|
|
||||||
{ "SoftFloat32.FPCompareLTFpscr", new SoftFloat32FPCompareLTFpscrDelegate(SoftFloat32.FPCompareLTFpscr) },
|
|
||||||
{ "SoftFloat32.FPDiv", new SoftFloat32FPDivDelegate(SoftFloat32.FPDiv) },
|
|
||||||
{ "SoftFloat32.FPMax", new SoftFloat32FPMaxDelegate(SoftFloat32.FPMax) },
|
|
||||||
{ "SoftFloat32.FPMaxFpscr", new SoftFloat32FPMaxFpscrDelegate(SoftFloat32.FPMaxFpscr) },
|
|
||||||
{ "SoftFloat32.FPMaxNum", new SoftFloat32FPMaxNumDelegate(SoftFloat32.FPMaxNum) },
|
|
||||||
{ "SoftFloat32.FPMaxNumFpscr", new SoftFloat32FPMaxNumFpscrDelegate(SoftFloat32.FPMaxNumFpscr) },
|
|
||||||
{ "SoftFloat32.FPMin", new SoftFloat32FPMinDelegate(SoftFloat32.FPMin) },
|
|
||||||
{ "SoftFloat32.FPMinFpscr", new SoftFloat32FPMinFpscrDelegate(SoftFloat32.FPMinFpscr) },
|
|
||||||
{ "SoftFloat32.FPMinNum", new SoftFloat32FPMinNumDelegate(SoftFloat32.FPMinNum) },
|
|
||||||
{ "SoftFloat32.FPMinNumFpscr", new SoftFloat32FPMinNumFpscrDelegate(SoftFloat32.FPMinNumFpscr) },
|
|
||||||
{ "SoftFloat32.FPMul", new SoftFloat32FPMulDelegate(SoftFloat32.FPMul) },
|
|
||||||
{ "SoftFloat32.FPMulFpscr", new SoftFloat32FPMulFpscrDelegate(SoftFloat32.FPMulFpscr) },
|
|
||||||
{ "SoftFloat32.FPMulAdd", new SoftFloat32FPMulAddDelegate(SoftFloat32.FPMulAdd) },
|
|
||||||
{ "SoftFloat32.FPMulAddFpscr", new SoftFloat32FPMulAddFpscrDelegate(SoftFloat32.FPMulAddFpscr) },
|
|
||||||
{ "SoftFloat32.FPMulSub", new SoftFloat32FPMulSubDelegate(SoftFloat32.FPMulSub) },
|
|
||||||
{ "SoftFloat32.FPMulSubFpscr", new SoftFloat32FPMulSubFpscrDelegate(SoftFloat32.FPMulSubFpscr) },
|
|
||||||
{ "SoftFloat32.FPMulX", new SoftFloat32FPMulXDelegate(SoftFloat32.FPMulX) },
|
|
||||||
{ "SoftFloat32.FPNegMulAdd", new SoftFloat32FPNegMulAddDelegate(SoftFloat32.FPNegMulAdd) },
|
|
||||||
{ "SoftFloat32.FPNegMulSub", new SoftFloat32FPNegMulSubDelegate(SoftFloat32.FPNegMulSub) },
|
|
||||||
{ "SoftFloat32.FPRecipEstimate", new SoftFloat32FPRecipEstimateDelegate(SoftFloat32.FPRecipEstimate) },
|
|
||||||
{ "SoftFloat32.FPRecipEstimateFpscr", new SoftFloat32FPRecipEstimateFpscrDelegate(SoftFloat32.FPRecipEstimateFpscr) },
|
|
||||||
{ "SoftFloat32.FPRecipStep", new SoftFloat32FPRecipStepDelegate(SoftFloat32.FPRecipStep) },
|
|
||||||
{ "SoftFloat32.FPRecipStepFused", new SoftFloat32FPRecipStepFusedDelegate(SoftFloat32.FPRecipStepFused) },
|
|
||||||
{ "SoftFloat32.FPRecpX", new SoftFloat32FPRecpXDelegate(SoftFloat32.FPRecpX) },
|
|
||||||
{ "SoftFloat32.FPRSqrtEstimate", new SoftFloat32FPRSqrtEstimateDelegate(SoftFloat32.FPRSqrtEstimate) },
|
|
||||||
{ "SoftFloat32.FPRSqrtEstimateFpscr", new SoftFloat32FPRSqrtEstimateFpscrDelegate(SoftFloat32.FPRSqrtEstimateFpscr) },
|
|
||||||
{ "SoftFloat32.FPRSqrtStep", new SoftFloat32FPRSqrtStepDelegate(SoftFloat32.FPRSqrtStep) },
|
|
||||||
{ "SoftFloat32.FPRSqrtStepFused", new SoftFloat32FPRSqrtStepFusedDelegate(SoftFloat32.FPRSqrtStepFused) },
|
|
||||||
{ "SoftFloat32.FPSqrt", new SoftFloat32FPSqrtDelegate(SoftFloat32.FPSqrt) },
|
|
||||||
{ "SoftFloat32.FPSub", new SoftFloat32FPSubDelegate(SoftFloat32.FPSub) },
|
|
||||||
|
|
||||||
{ "SoftFloat32_16.FPConvert", new SoftFloat32_16FPConvertDelegate(SoftFloat32_16.FPConvert) },
|
|
||||||
|
|
||||||
{ "SoftFloat64.FPAdd", new SoftFloat64FPAddDelegate(SoftFloat64.FPAdd) },
|
|
||||||
{ "SoftFloat64.FPAddFpscr", new SoftFloat64FPAddFpscrDelegate(SoftFloat64.FPAddFpscr) },
|
|
||||||
{ "SoftFloat64.FPCompare", new SoftFloat64FPCompareDelegate(SoftFloat64.FPCompare) },
|
|
||||||
{ "SoftFloat64.FPCompareEQ", new SoftFloat64FPCompareEQDelegate(SoftFloat64.FPCompareEQ) },
|
|
||||||
{ "SoftFloat64.FPCompareEQFpscr", new SoftFloat64FPCompareEQFpscrDelegate(SoftFloat64.FPCompareEQFpscr) },
|
|
||||||
{ "SoftFloat64.FPCompareGE", new SoftFloat64FPCompareGEDelegate(SoftFloat64.FPCompareGE) },
|
|
||||||
{ "SoftFloat64.FPCompareGEFpscr", new SoftFloat64FPCompareGEFpscrDelegate(SoftFloat64.FPCompareGEFpscr) },
|
|
||||||
{ "SoftFloat64.FPCompareGT", new SoftFloat64FPCompareGTDelegate(SoftFloat64.FPCompareGT) },
|
|
||||||
{ "SoftFloat64.FPCompareGTFpscr", new SoftFloat64FPCompareGTFpscrDelegate(SoftFloat64.FPCompareGTFpscr) },
|
|
||||||
{ "SoftFloat64.FPCompareLE", new SoftFloat64FPCompareLEDelegate(SoftFloat64.FPCompareLE) },
|
|
||||||
{ "SoftFloat64.FPCompareLEFpscr", new SoftFloat64FPCompareLEFpscrDelegate(SoftFloat64.FPCompareLEFpscr) },
|
|
||||||
{ "SoftFloat64.FPCompareLT", new SoftFloat64FPCompareLTDelegate(SoftFloat64.FPCompareLT) },
|
|
||||||
{ "SoftFloat64.FPCompareLTFpscr", new SoftFloat64FPCompareLTFpscrDelegate(SoftFloat64.FPCompareLTFpscr) },
|
|
||||||
{ "SoftFloat64.FPDiv", new SoftFloat64FPDivDelegate(SoftFloat64.FPDiv) },
|
|
||||||
{ "SoftFloat64.FPMax", new SoftFloat64FPMaxDelegate(SoftFloat64.FPMax) },
|
|
||||||
{ "SoftFloat64.FPMaxFpscr", new SoftFloat64FPMaxFpscrDelegate(SoftFloat64.FPMaxFpscr) },
|
|
||||||
{ "SoftFloat64.FPMaxNum", new SoftFloat64FPMaxNumDelegate(SoftFloat64.FPMaxNum) },
|
|
||||||
{ "SoftFloat64.FPMaxNumFpscr", new SoftFloat64FPMaxNumFpscrDelegate(SoftFloat64.FPMaxNumFpscr) },
|
|
||||||
{ "SoftFloat64.FPMin", new SoftFloat64FPMinDelegate(SoftFloat64.FPMin) },
|
|
||||||
{ "SoftFloat64.FPMinFpscr", new SoftFloat64FPMinFpscrDelegate(SoftFloat64.FPMinFpscr) },
|
|
||||||
{ "SoftFloat64.FPMinNum", new SoftFloat64FPMinNumDelegate(SoftFloat64.FPMinNum) },
|
|
||||||
{ "SoftFloat64.FPMinNumFpscr", new SoftFloat64FPMinNumFpscrDelegate(SoftFloat64.FPMinNumFpscr) },
|
|
||||||
{ "SoftFloat64.FPMul", new SoftFloat64FPMulDelegate(SoftFloat64.FPMul) },
|
|
||||||
{ "SoftFloat64.FPMulFpscr", new SoftFloat64FPMulFpscrDelegate(SoftFloat64.FPMulFpscr) },
|
|
||||||
{ "SoftFloat64.FPMulAdd", new SoftFloat64FPMulAddDelegate(SoftFloat64.FPMulAdd) },
|
|
||||||
{ "SoftFloat64.FPMulAddFpscr", new SoftFloat64FPMulAddFpscrDelegate(SoftFloat64.FPMulAddFpscr) },
|
|
||||||
{ "SoftFloat64.FPMulSub", new SoftFloat64FPMulSubDelegate(SoftFloat64.FPMulSub) },
|
|
||||||
{ "SoftFloat64.FPMulSubFpscr", new SoftFloat64FPMulSubFpscrDelegate(SoftFloat64.FPMulSubFpscr) },
|
|
||||||
{ "SoftFloat64.FPMulX", new SoftFloat64FPMulXDelegate(SoftFloat64.FPMulX) },
|
|
||||||
{ "SoftFloat64.FPNegMulAdd", new SoftFloat64FPNegMulAddDelegate(SoftFloat64.FPNegMulAdd) },
|
|
||||||
{ "SoftFloat64.FPNegMulSub", new SoftFloat64FPNegMulSubDelegate(SoftFloat64.FPNegMulSub) },
|
|
||||||
{ "SoftFloat64.FPRecipEstimate", new SoftFloat64FPRecipEstimateDelegate(SoftFloat64.FPRecipEstimate) },
|
|
||||||
{ "SoftFloat64.FPRecipEstimateFpscr", new SoftFloat64FPRecipEstimateFpscrDelegate(SoftFloat64.FPRecipEstimateFpscr) },
|
|
||||||
{ "SoftFloat64.FPRecipStep", new SoftFloat64FPRecipStepDelegate(SoftFloat64.FPRecipStep) },
|
|
||||||
{ "SoftFloat64.FPRecipStepFused", new SoftFloat64FPRecipStepFusedDelegate(SoftFloat64.FPRecipStepFused) },
|
|
||||||
{ "SoftFloat64.FPRecpX", new SoftFloat64FPRecpXDelegate(SoftFloat64.FPRecpX) },
|
|
||||||
{ "SoftFloat64.FPRSqrtEstimate", new SoftFloat64FPRSqrtEstimateDelegate(SoftFloat64.FPRSqrtEstimate) },
|
|
||||||
{ "SoftFloat64.FPRSqrtEstimateFpscr", new SoftFloat64FPRSqrtEstimateFpscrDelegate(SoftFloat64.FPRSqrtEstimateFpscr) },
|
|
||||||
{ "SoftFloat64.FPRSqrtStep", new SoftFloat64FPRSqrtStepDelegate(SoftFloat64.FPRSqrtStep) },
|
|
||||||
{ "SoftFloat64.FPRSqrtStepFused", new SoftFloat64FPRSqrtStepFusedDelegate(SoftFloat64.FPRSqrtStepFused) },
|
|
||||||
{ "SoftFloat64.FPSqrt", new SoftFloat64FPSqrtDelegate(SoftFloat64.FPSqrt) },
|
|
||||||
{ "SoftFloat64.FPSub", new SoftFloat64FPSubDelegate(SoftFloat64.FPSub) },
|
|
||||||
|
|
||||||
{ "SoftFloat64_16.FPConvert", new SoftFloat64_16FPConvertDelegate(SoftFloat64_16.FPConvert) }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
|
||||||
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
|
||||||
@@ -708,44 +152,44 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
|
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
|
||||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
|
||||||
@@ -753,44 +197,44 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
|
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
|
||||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
|
||||||
|
|||||||
@@ -97,14 +97,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
// For Android, use the Delegates class to get the function pointer
|
|
||||||
int index = Delegates.GetDelegateIndex(info);
|
|
||||||
IntPtr funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
|
|
||||||
#else
|
|
||||||
// For other platforms, use direct method handle approach
|
|
||||||
IntPtr funcPtr = info.MethodHandle.GetFunctionPointer();
|
IntPtr funcPtr = info.MethodHandle.GetFunctionPointer();
|
||||||
#endif
|
|
||||||
|
|
||||||
OperandType returnType = GetOperandType(info.ReturnType);
|
OperandType returnType = GetOperandType(info.ReturnType);
|
||||||
|
|
||||||
@@ -675,8 +668,7 @@ namespace ARMeilleure.Translation
|
|||||||
Operation last = block.Operations.Last;
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
return last != default &&
|
return last != default &&
|
||||||
(last.Instruction == Instruction.Return ||
|
last.Instruction is Instruction.Return or Instruction.Tailcall;
|
||||||
last.Instruction == Instruction.Tailcall);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlFlowGraph GetControlFlowGraph()
|
public ControlFlowGraph GetControlFlowGraph()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ 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 = 7008; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 7010; //! 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";
|
||||||
@@ -190,7 +190,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
_infosStream.Seek(0L, SeekOrigin.Begin);
|
_infosStream.Seek(0L, SeekOrigin.Begin);
|
||||||
bool foundBadFunction = false;
|
bool foundBadFunction = false;
|
||||||
|
|
||||||
for (int index = 0; index < GetEntriesCount(); index++)
|
for (int index = 0; index < _infosStream.Length / Unsafe.SizeOf<InfoEntry>(); index++)
|
||||||
{
|
{
|
||||||
InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream);
|
InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream);
|
||||||
foreach (ulong address in blacklist)
|
foreach (ulong address in blacklist)
|
||||||
@@ -244,56 +244,15 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
||||||
|
|
||||||
if (!outerHeader.IsHeaderValid())
|
if (!outerHeader.IsHeaderValid() ||
|
||||||
{
|
outerHeader.Magic != _outerHeaderMagic ||
|
||||||
InvalidateCompressedStream(compressedStream);
|
outerHeader.CacheFileVersion != InternalVersion ||
|
||||||
|
outerHeader.Endianness != GetEndianness() ||
|
||||||
return false;
|
outerHeader.FeatureInfo != GetFeatureInfo() ||
|
||||||
}
|
outerHeader.MemoryManagerMode != GetMemoryManagerMode() ||
|
||||||
|
outerHeader.OSPlatform != GetOSPlatform() ||
|
||||||
if (outerHeader.Magic != _outerHeaderMagic)
|
outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture ||
|
||||||
{
|
outerHeader.DebuggerMode != Optimizations.EnableDebugging)
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.CacheFileVersion != InternalVersion)
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.Endianness != GetEndianness())
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.FeatureInfo != GetFeatureInfo())
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.MemoryManagerMode != GetMemoryManagerMode())
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.OSPlatform != GetOSPlatform())
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture)
|
|
||||||
{
|
{
|
||||||
InvalidateCompressedStream(compressedStream);
|
InvalidateCompressedStream(compressedStream);
|
||||||
|
|
||||||
@@ -324,14 +283,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream);
|
InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream);
|
||||||
|
|
||||||
if (!innerHeader.IsHeaderValid())
|
if (!innerHeader.IsHeaderValid() || innerHeader.Magic != _innerHeaderMagic)
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (innerHeader.Magic != _innerHeaderMagic)
|
|
||||||
{
|
{
|
||||||
InvalidateCompressedStream(compressedStream);
|
InvalidateCompressedStream(compressedStream);
|
||||||
|
|
||||||
@@ -476,6 +428,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
MemoryManagerMode = GetMemoryManagerMode(),
|
MemoryManagerMode = GetMemoryManagerMode(),
|
||||||
OSPlatform = GetOSPlatform(),
|
OSPlatform = GetOSPlatform(),
|
||||||
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
|
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
|
||||||
|
DebuggerMode = Optimizations.EnableDebugging,
|
||||||
|
|
||||||
UncompressedStreamSize =
|
UncompressedStreamSize =
|
||||||
(long)Unsafe.SizeOf<InnerHeader>() +
|
(long)Unsafe.SizeOf<InnerHeader>() +
|
||||||
@@ -1072,7 +1025,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return osPlatform;
|
return osPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)]
|
||||||
private struct OuterHeader
|
private struct OuterHeader
|
||||||
{
|
{
|
||||||
public ulong Magic;
|
public ulong Magic;
|
||||||
@@ -1084,6 +1037,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
public byte MemoryManagerMode;
|
public byte MemoryManagerMode;
|
||||||
public uint OSPlatform;
|
public uint OSPlatform;
|
||||||
public uint Architecture;
|
public uint Architecture;
|
||||||
|
public bool DebuggerMode;
|
||||||
|
|
||||||
public long UncompressedStreamSize;
|
public long UncompressedStreamSize;
|
||||||
|
|
||||||
@@ -1166,8 +1120,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
if (State == PtcState.Enabled ||
|
if (State is PtcState.Enabled or PtcState.Continuing)
|
||||||
State == PtcState.Continuing)
|
|
||||||
{
|
{
|
||||||
State = PtcState.Closing;
|
State = PtcState.Closing;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,28 +189,10 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
||||||
|
|
||||||
if (!outerHeader.IsHeaderValid())
|
if (!outerHeader.IsHeaderValid() ||
|
||||||
{
|
outerHeader.Magic != _outerHeaderMagic ||
|
||||||
InvalidateCompressedStream(compressedStream);
|
outerHeader.InfoFileVersion != InternalVersion && !_migrateInternalVersions.Contains(outerHeader.InfoFileVersion) ||
|
||||||
|
outerHeader.Endianness != Ptc.GetEndianness())
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.Magic != _outerHeaderMagic)
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.InfoFileVersion != InternalVersion && !_migrateInternalVersions.Contains(outerHeader.InfoFileVersion))
|
|
||||||
{
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerHeader.Endianness != Ptc.GetEndianness())
|
|
||||||
{
|
{
|
||||||
InvalidateCompressedStream(compressedStream);
|
InvalidateCompressedStream(compressedStream);
|
||||||
|
|
||||||
@@ -465,8 +447,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (_ptc.State == PtcState.Enabled ||
|
if (_ptc.State is PtcState.Enabled or PtcState.Continuing)
|
||||||
_ptc.State == PtcState.Continuing)
|
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace ARMeilleure.Translation
|
|||||||
// This is required because we have a implicit context load at the start of the function,
|
// This is required because we have a implicit context load at the start of the function,
|
||||||
// but if there is a jump to the start of the function, the context load would trash the modified values.
|
// but if there is a jump to the start of the function, the context load would trash the modified values.
|
||||||
// Here we insert a new entry block that will jump to the existing entry block.
|
// Here we insert a new entry block that will jump to the existing entry block.
|
||||||
BasicBlock newEntry = new BasicBlock(cfg.Blocks.Count);
|
BasicBlock newEntry = new(cfg.Blocks.Count);
|
||||||
|
|
||||||
cfg.UpdateEntry(newEntry);
|
cfg.UpdateEntry(newEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,25 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
NativeInterface.RegisterThread(context, Memory, this);
|
NativeInterface.RegisterThread(context, Memory, this);
|
||||||
|
|
||||||
if (Optimizations.UseUnmanagedDispatchLoop)
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
context.DebugPc = address;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
|
||||||
|
{
|
||||||
|
context.DebugPc = Step(context, context.DebugPc);
|
||||||
|
context.StepHandler();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.DebugPc = ExecuteSingle(context, context.DebugPc);
|
||||||
|
}
|
||||||
|
context.CheckInterrupt();
|
||||||
|
}
|
||||||
|
while (context.Running && context.DebugPc != 0);
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseUnmanagedDispatchLoop)
|
||||||
{
|
{
|
||||||
Stubs.DispatchLoop(context.NativeContextPtr, address);
|
Stubs.DispatchLoop(context.NativeContextPtr, address);
|
||||||
}
|
}
|
||||||
@@ -168,6 +186,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Statistics.StartTimer();
|
Statistics.StartTimer();
|
||||||
|
|
||||||
|
context.ResetCallDepth();
|
||||||
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
||||||
|
|
||||||
Statistics.StopTimer(address);
|
Statistics.StopTimer(address);
|
||||||
@@ -175,7 +194,7 @@ namespace ARMeilleure.Translation
|
|||||||
return nextAddr;
|
return nextAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong Step(State.ExecutionContext context, ulong address)
|
private ulong Step(State.ExecutionContext context, ulong address)
|
||||||
{
|
{
|
||||||
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
|
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
|
||||||
|
|
||||||
@@ -186,6 +205,8 @@ namespace ARMeilleure.Translation
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||||
{
|
{
|
||||||
if (!Functions.TryGetValue(address, out TranslatedFunction func))
|
if (!Functions.TryGetValue(address, out TranslatedFunction func))
|
||||||
@@ -229,7 +250,8 @@ namespace ARMeilleure.Translation
|
|||||||
address,
|
address,
|
||||||
highCq,
|
highCq,
|
||||||
_ptc.State != PtcState.Disabled,
|
_ptc.State != PtcState.Disabled,
|
||||||
mode: Aarch32Mode.User);
|
mode: Aarch32Mode.User,
|
||||||
|
isSingleStep: singleStep);
|
||||||
|
|
||||||
Logger.StartPass(PassName.Decoding);
|
Logger.StartPass(PassName.Decoding);
|
||||||
|
|
||||||
@@ -239,6 +261,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Logger.StartPass(PassName.Translation);
|
Logger.StartPass(PassName.Translation);
|
||||||
|
|
||||||
|
InstEmitFlowHelper.EmitCallDepthCheckAndIncrement(context, Const(address));
|
||||||
EmitSynchronization(context);
|
EmitSynchronization(context);
|
||||||
|
|
||||||
if (blocks[0].Address != address)
|
if (blocks[0].Address != address)
|
||||||
@@ -367,9 +390,13 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
if (block.Exit)
|
if (block.Exit)
|
||||||
{
|
{
|
||||||
// Left option here as it may be useful if we need to return to managed rather than tail call in
|
// Return to managed rather than tail call.
|
||||||
// future. (eg. for debug)
|
bool useReturns = Optimizations.EnableDebugging;
|
||||||
bool useReturns = false;
|
|
||||||
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
EmitDebugPrecisePcUpdate(context, block.Address);
|
||||||
|
}
|
||||||
|
|
||||||
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
|
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
|
||||||
}
|
}
|
||||||
@@ -393,6 +420,11 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Optimizations.EnableDebugging)
|
||||||
|
{
|
||||||
|
EmitDebugPrecisePcUpdate(context, opCode.Address);
|
||||||
|
}
|
||||||
|
|
||||||
Operand lblPredicateSkip = default;
|
Operand lblPredicateSkip = default;
|
||||||
|
|
||||||
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
|
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
|
||||||
@@ -489,6 +521,14 @@ namespace ARMeilleure.Translation
|
|||||||
context.MarkLabel(lblExit);
|
context.MarkLabel(lblExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
|
||||||
|
{
|
||||||
|
long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
|
||||||
|
|
||||||
|
Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
|
||||||
|
context.Store(debugPrecisePcAddr, Const(address));
|
||||||
|
}
|
||||||
|
|
||||||
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
ulong[] overlapAddresses = [];
|
ulong[] overlapAddresses = [];
|
||||||
|
|||||||
@@ -262,10 +262,18 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
||||||
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
||||||
|
Operand callDepthAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
|
||||||
EmitSyncFpContext(context, nativeContext, true);
|
EmitSyncFpContext(context, nativeContext, true);
|
||||||
|
|
||||||
context.MarkLabel(beginLbl);
|
context.MarkLabel(beginLbl);
|
||||||
|
|
||||||
|
if (Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
// Reset the call depth counter, since this is our first guest function call.
|
||||||
|
context.Store(callDepthAddress, Const(0));
|
||||||
|
}
|
||||||
|
|
||||||
context.Store(dispatchAddress, guestAddress);
|
context.Store(dispatchAddress, guestAddress);
|
||||||
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
||||||
context.BranchIfFalse(endLbl, guestAddress);
|
context.BranchIfFalse(endLbl, guestAddress);
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
|||||||
|
|
||||||
public bool SupportsChannelCount(uint channelCount)
|
public bool SupportsChannelCount(uint channelCount)
|
||||||
{
|
{
|
||||||
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
return channelCount is 1 or 2 or 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsDirection(Direction direction)
|
public bool SupportsDirection(Direction direction)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_onBackendDisconnectNative = (ctx, err) => _onBackendDisconnect(err);
|
_onBackendDisconnectNative = (_, err) => _onBackendDisconnect(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetContext().OnBackendDisconnected = Marshal.GetFunctionPointerForDelegate(_onBackendDisconnectNative);
|
GetContext().OnBackendDisconnected = Marshal.GetFunctionPointerForDelegate(_onBackendDisconnectNative);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writeCallbackNative = (ctx, frameCountMin, frameCountMax) => _writeCallback(frameCountMin, frameCountMax);
|
_writeCallbackNative = (_, frameCountMin, frameCountMax) => _writeCallback(frameCountMin, frameCountMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetOutContext().WriteCallback = Marshal.GetFunctionPointerForDelegate(_writeCallbackNative);
|
GetOutContext().WriteCallback = Marshal.GetFunctionPointerForDelegate(_writeCallbackNative);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
context = SoundIoContext.Create();
|
context = SoundIoContext.Create();
|
||||||
context.OnBackendDisconnect = err =>
|
context.OnBackendDisconnect = _ =>
|
||||||
{
|
{
|
||||||
backendDisconnected = true;
|
backendDisconnected = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
|
|
||||||
public bool SupportsChannelCount(uint channelCount)
|
public bool SupportsChannelCount(uint channelCount)
|
||||||
{
|
{
|
||||||
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
return channelCount is 1 or 2 or 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsSampleFormat(SampleFormat sampleFormat)
|
public bool SupportsSampleFormat(SampleFormat sampleFormat)
|
||||||
@@ -184,7 +184,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
|
|
||||||
public bool SupportsDirection(Direction direction)
|
public bool SupportsDirection(Direction direction)
|
||||||
{
|
{
|
||||||
return direction == Direction.Input || direction == Direction.Output;
|
return direction is Direction.Input or Direction.Output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,12 +81,12 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
|
|
||||||
public bool SupportsDirection(Direction direction)
|
public bool SupportsDirection(Direction direction)
|
||||||
{
|
{
|
||||||
return direction == Direction.Output || direction == Direction.Input;
|
return direction is Direction.Output or Direction.Input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsChannelCount(uint channelCount)
|
public bool SupportsChannelCount(uint channelCount)
|
||||||
{
|
{
|
||||||
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
return channelCount is 1 or 2 or 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// <returns>The state of the session</returns>
|
/// <returns>The state of the session</returns>
|
||||||
public AudioDeviceState GetState()
|
public AudioDeviceState GetState()
|
||||||
{
|
{
|
||||||
Debug.Assert(_state == AudioDeviceState.Started || _state == AudioDeviceState.Stopped);
|
Debug.Assert(_state is AudioDeviceState.Started or AudioDeviceState.Stopped);
|
||||||
|
|
||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,15 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
ReadOnlySpan<float> inputBuffer,
|
ReadOnlySpan<float> inputBuffer,
|
||||||
uint sampleCount)
|
uint sampleCount)
|
||||||
{
|
{
|
||||||
float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
|
Span<short> numeratorSpan = parameter.Numerator.AsSpan();
|
||||||
float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
|
Span<short> denominatorSpan = parameter.Denominator.AsSpan();
|
||||||
float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
|
|
||||||
|
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter);
|
||||||
|
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
|
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter);
|
||||||
float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
|
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
@@ -64,12 +67,15 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
uint sampleCount,
|
uint sampleCount,
|
||||||
float volume)
|
float volume)
|
||||||
{
|
{
|
||||||
float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
|
Span<short> numeratorSpan = parameter.Numerator.AsSpan();
|
||||||
float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
|
Span<short> denominatorSpan = parameter.Denominator.AsSpan();
|
||||||
float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
|
|
||||||
|
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter);
|
||||||
|
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
|
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter);
|
||||||
float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
|
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
@@ -107,12 +113,15 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
float volume,
|
float volume,
|
||||||
float ramp)
|
float ramp)
|
||||||
{
|
{
|
||||||
float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
|
Span<short> numeratorSpan = parameter.Numerator.AsSpan();
|
||||||
float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
|
Span<short> denominatorSpan = parameter.Denominator.AsSpan();
|
||||||
float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
|
|
||||||
|
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter);
|
||||||
|
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
|
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter);
|
||||||
float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
|
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float mixState = 0f;
|
float mixState = 0f;
|
||||||
|
|
||||||
@@ -157,13 +166,16 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
BiquadFilterParameter parameter = parameters[stageIndex];
|
BiquadFilterParameter parameter = parameters[stageIndex];
|
||||||
|
|
||||||
ref BiquadFilterState state = ref states[stageIndex];
|
ref BiquadFilterState state = ref states[stageIndex];
|
||||||
|
|
||||||
|
Span<short> numeratorSpan = parameter.Numerator.AsSpan();
|
||||||
|
Span<short> denominatorSpan = parameter.Denominator.AsSpan();
|
||||||
|
|
||||||
float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
|
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter);
|
||||||
float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
|
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter);
|
||||||
float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
|
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
|
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter);
|
||||||
float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
|
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
@@ -201,19 +213,25 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
uint sampleCount,
|
uint sampleCount,
|
||||||
float volume)
|
float volume)
|
||||||
{
|
{
|
||||||
float a00 = FixedPointHelper.ToFloat(parameter0.Numerator[0], FixedPointPrecisionForParameter);
|
Span<short> numerator0Span = parameter0.Numerator.AsSpan();
|
||||||
float a10 = FixedPointHelper.ToFloat(parameter0.Numerator[1], FixedPointPrecisionForParameter);
|
Span<short> numerator1Span = parameter1.Numerator.AsSpan();
|
||||||
float a20 = FixedPointHelper.ToFloat(parameter0.Numerator[2], FixedPointPrecisionForParameter);
|
Span<short> denominator0Span = parameter0.Denominator.AsSpan();
|
||||||
|
Span<short> denominator1Span = parameter1.Denominator.AsSpan();
|
||||||
|
|
||||||
|
|
||||||
|
float a00 = FixedPointHelper.ToFloat(numerator0Span[0], FixedPointPrecisionForParameter);
|
||||||
|
float a10 = FixedPointHelper.ToFloat(numerator0Span[1], FixedPointPrecisionForParameter);
|
||||||
|
float a20 = FixedPointHelper.ToFloat(numerator0Span[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b10 = FixedPointHelper.ToFloat(parameter0.Denominator[0], FixedPointPrecisionForParameter);
|
float b10 = FixedPointHelper.ToFloat(denominator0Span[0], FixedPointPrecisionForParameter);
|
||||||
float b20 = FixedPointHelper.ToFloat(parameter0.Denominator[1], FixedPointPrecisionForParameter);
|
float b20 = FixedPointHelper.ToFloat(denominator0Span[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float a01 = FixedPointHelper.ToFloat(parameter1.Numerator[0], FixedPointPrecisionForParameter);
|
float a01 = FixedPointHelper.ToFloat(numerator1Span[0], FixedPointPrecisionForParameter);
|
||||||
float a11 = FixedPointHelper.ToFloat(parameter1.Numerator[1], FixedPointPrecisionForParameter);
|
float a11 = FixedPointHelper.ToFloat(numerator1Span[1], FixedPointPrecisionForParameter);
|
||||||
float a21 = FixedPointHelper.ToFloat(parameter1.Numerator[2], FixedPointPrecisionForParameter);
|
float a21 = FixedPointHelper.ToFloat(numerator1Span[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b11 = FixedPointHelper.ToFloat(parameter1.Denominator[0], FixedPointPrecisionForParameter);
|
float b11 = FixedPointHelper.ToFloat(denominator1Span[0], FixedPointPrecisionForParameter);
|
||||||
float b21 = FixedPointHelper.ToFloat(parameter1.Denominator[1], FixedPointPrecisionForParameter);
|
float b21 = FixedPointHelper.ToFloat(denominator1Span[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
@@ -261,19 +279,24 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
float volume,
|
float volume,
|
||||||
float ramp)
|
float ramp)
|
||||||
{
|
{
|
||||||
float a00 = FixedPointHelper.ToFloat(parameter0.Numerator[0], FixedPointPrecisionForParameter);
|
Span<short> numerator0Span = parameter0.Numerator.AsSpan();
|
||||||
float a10 = FixedPointHelper.ToFloat(parameter0.Numerator[1], FixedPointPrecisionForParameter);
|
Span<short> numerator1Span = parameter1.Numerator.AsSpan();
|
||||||
float a20 = FixedPointHelper.ToFloat(parameter0.Numerator[2], FixedPointPrecisionForParameter);
|
Span<short> denominator0Span = parameter0.Denominator.AsSpan();
|
||||||
|
Span<short> denominator1Span = parameter1.Denominator.AsSpan();
|
||||||
|
|
||||||
|
float a00 = FixedPointHelper.ToFloat(numerator0Span[0], FixedPointPrecisionForParameter);
|
||||||
|
float a10 = FixedPointHelper.ToFloat(numerator0Span[1], FixedPointPrecisionForParameter);
|
||||||
|
float a20 = FixedPointHelper.ToFloat(numerator0Span[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b10 = FixedPointHelper.ToFloat(parameter0.Denominator[0], FixedPointPrecisionForParameter);
|
float b10 = FixedPointHelper.ToFloat(denominator0Span[0], FixedPointPrecisionForParameter);
|
||||||
float b20 = FixedPointHelper.ToFloat(parameter0.Denominator[1], FixedPointPrecisionForParameter);
|
float b20 = FixedPointHelper.ToFloat(denominator0Span[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float a01 = FixedPointHelper.ToFloat(parameter1.Numerator[0], FixedPointPrecisionForParameter);
|
float a01 = FixedPointHelper.ToFloat(numerator1Span[0], FixedPointPrecisionForParameter);
|
||||||
float a11 = FixedPointHelper.ToFloat(parameter1.Numerator[1], FixedPointPrecisionForParameter);
|
float a11 = FixedPointHelper.ToFloat(numerator1Span[1], FixedPointPrecisionForParameter);
|
||||||
float a21 = FixedPointHelper.ToFloat(parameter1.Numerator[2], FixedPointPrecisionForParameter);
|
float a21 = FixedPointHelper.ToFloat(numerator1Span[2], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float b11 = FixedPointHelper.ToFloat(parameter1.Denominator[0], FixedPointPrecisionForParameter);
|
float b11 = FixedPointHelper.ToFloat(denominator1Span[0], FixedPointPrecisionForParameter);
|
||||||
float b21 = FixedPointHelper.ToFloat(parameter1.Denominator[1], FixedPointPrecisionForParameter);
|
float b21 = FixedPointHelper.ToFloat(denominator1Span[1], FixedPointPrecisionForParameter);
|
||||||
|
|
||||||
float mixState = 0f;
|
float mixState = 0f;
|
||||||
|
|
||||||
|
|||||||
@@ -39,12 +39,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
OutputBufferIndex = outputBufferIndex;
|
OutputBufferIndex = outputBufferIndex;
|
||||||
SampleRate = serverState.SampleRate;
|
SampleRate = serverState.SampleRate;
|
||||||
Pitch = serverState.Pitch;
|
Pitch = serverState.Pitch;
|
||||||
|
|
||||||
|
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan();
|
||||||
|
|
||||||
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
||||||
|
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
for (int i = 0; i < WaveBuffers.Length; i++)
|
||||||
{
|
{
|
||||||
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i];
|
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
|
||||||
|
|
||||||
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Audio.Renderer.Parameter.Sink;
|
using Ryujinx.Audio.Renderer.Parameter.Sink;
|
||||||
using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
@@ -28,10 +29,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
Input = new ushort[Constants.ChannelCountMax];
|
Input = new ushort[Constants.ChannelCountMax];
|
||||||
InputCount = parameter.InputCount;
|
InputCount = parameter.InputCount;
|
||||||
|
|
||||||
|
Span<byte> inputSpan = parameter.Input.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < InputCount; i++)
|
for (int i = 0; i < InputCount; i++)
|
||||||
{
|
{
|
||||||
Input[i] = (ushort)(bufferOffset + parameter.Input[i]);
|
Input[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CircularBuffer = circularBufferAddressInfo.GetReference(true);
|
CircularBuffer = circularBufferAddressInfo.GetReference(true);
|
||||||
@@ -59,7 +62,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
for (int y = 0; y < context.SampleCount; y++)
|
for (int y = 0; y < context.SampleCount; y++)
|
||||||
{
|
{
|
||||||
context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, PcmHelper.Saturate(inputBuffer[y]));
|
if (inputBuffer != null)
|
||||||
|
{
|
||||||
|
context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount,
|
||||||
|
PcmHelper.Saturate(inputBuffer[y]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentOffset += context.SampleCount * TargetChannelCount;
|
currentOffset += context.SampleCount * TargetChannelCount;
|
||||||
|
|||||||
@@ -42,11 +42,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = _parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = _parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < _parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,10 +174,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
statistics.MinimumGain = MathF.Min(statistics.MinimumGain, compressionGain * state.OutputGain);
|
statistics.MinimumGain = MathF.Min(statistics.MinimumGain, compressionGain * state.OutputGain);
|
||||||
statistics.MaximumMean = MathF.Max(statistics.MaximumMean, mean);
|
statistics.MaximumMean = MathF.Max(statistics.MaximumMean, mean);
|
||||||
|
|
||||||
|
Span<float> lastSamplesSpan = statistics.LastSamples.AsSpan();
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
||||||
{
|
{
|
||||||
statistics.LastSamples[channelIndex] = MathF.Abs(channelInput[channelIndex] * (1f / 32768f));
|
lastSamplesSpan[channelIndex] = MathF.Abs(channelInput[channelIndex] * (1f / 32768f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,12 +52,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex);
|
OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex);
|
||||||
SampleRate = serverState.SampleRate;
|
SampleRate = serverState.SampleRate;
|
||||||
Pitch = serverState.Pitch;
|
Pitch = serverState.Pitch;
|
||||||
|
|
||||||
|
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan();
|
||||||
|
|
||||||
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
||||||
|
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
for (int i = 0; i < WaveBuffers.Length; i++)
|
||||||
{
|
{
|
||||||
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i];
|
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
|
||||||
|
|
||||||
WaveBuffers[i] = voiceWaveBuffer.ToCommon(2);
|
WaveBuffers[i] = voiceWaveBuffer.ToCommon(2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = Parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < Parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
|
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
|
||||||
|
|||||||
@@ -42,14 +42,15 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ref VoiceUpdateState state = ref State.Span[0];
|
ref VoiceUpdateState state = ref State.Span[0];
|
||||||
|
|
||||||
Span<float> depopBuffer = DepopBuffer.Span;
|
Span<float> depopBuffer = DepopBuffer.Span;
|
||||||
|
Span<float> lastSamplesSpan = state.LastSamples.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < MixBufferCount; i++)
|
for (int i = 0; i < MixBufferCount; i++)
|
||||||
{
|
{
|
||||||
if (state.LastSamples[i] != 0)
|
if (lastSamplesSpan[i] != 0)
|
||||||
{
|
{
|
||||||
depopBuffer[OutputBufferIndices[i]] += state.LastSamples[i];
|
depopBuffer[OutputBufferIndices[i]] += lastSamplesSpan[i];
|
||||||
|
|
||||||
state.LastSamples[i] = 0;
|
lastSamplesSpan[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
SessionId = sessionId;
|
SessionId = sessionId;
|
||||||
InputCount = sink.Parameter.InputCount;
|
InputCount = sink.Parameter.InputCount;
|
||||||
InputBufferIndices = new ushort[InputCount];
|
InputBufferIndices = new ushort[InputCount];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = sink.Parameter.Input.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < Math.Min(InputCount, Constants.ChannelCountMax); i++)
|
for (int i = 0; i < Math.Min(InputCount, Constants.ChannelCountMax); i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + sink.Parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sink.UpsamplerState != null)
|
if (sink.UpsamplerState != null)
|
||||||
|
|||||||
@@ -37,11 +37,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = _parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = _parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < _parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,11 +48,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = _parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = _parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < _parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +153,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
{
|
{
|
||||||
ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0];
|
ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0];
|
||||||
|
|
||||||
statistics.InputMax[channelIndex] = Math.Max(statistics.InputMax[channelIndex], sampleInputMax);
|
Span<float> inputMaxSpan = statistics.InputMax.AsSpan();
|
||||||
statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], compressionGain);
|
Span<float> compressionGainMinSpan = statistics.CompressionGainMin.AsSpan();
|
||||||
|
|
||||||
|
inputMaxSpan[channelIndex] = Math.Max(inputMaxSpan[channelIndex], sampleInputMax);
|
||||||
|
compressionGainMinSpan[channelIndex] = Math.Min(compressionGainMinSpan[channelIndex], compressionGain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
public void Process(CommandList context)
|
public void Process(CommandList context)
|
||||||
{
|
{
|
||||||
|
ref VoiceUpdateState state = ref State.Span[0];
|
||||||
|
|
||||||
|
Span<float> lastSamplesSpan = state.LastSamples.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < MixBufferCount; i++)
|
for (int i = 0; i < MixBufferCount; i++)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndices[i]);
|
ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndices[i]);
|
||||||
@@ -87,15 +91,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
float volume0 = Volume0[i];
|
float volume0 = Volume0[i];
|
||||||
float volume1 = Volume1[i];
|
float volume1 = Volume1[i];
|
||||||
|
|
||||||
ref VoiceUpdateState state = ref State.Span[0];
|
|
||||||
|
|
||||||
if (volume0 != 0 || volume1 != 0)
|
if (volume0 != 0 || volume1 != 0)
|
||||||
{
|
{
|
||||||
state.LastSamples[i] = ProcessMixRampGrouped(outputBuffer, inputBuffer, volume0, volume1, (int)context.SampleCount);
|
lastSamplesSpan[i] = ProcessMixRampGrouped(outputBuffer, inputBuffer, volume0, volume1, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state.LastSamples[i] = 0;
|
lastSamplesSpan[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
Pitch = serverState.Pitch;
|
Pitch = serverState.Pitch;
|
||||||
|
|
||||||
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
||||||
|
|
||||||
|
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
for (int i = 0; i < WaveBuffers.Length; i++)
|
||||||
{
|
{
|
||||||
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i];
|
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
|
||||||
|
|
||||||
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
Pitch = serverState.Pitch;
|
Pitch = serverState.Pitch;
|
||||||
|
|
||||||
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
|
||||||
|
|
||||||
|
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
for (int i = 0; i < WaveBuffers.Length; i++)
|
||||||
{
|
{
|
||||||
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i];
|
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
|
||||||
|
|
||||||
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,11 +65,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = Parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < Parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: We do the opposite as Nintendo here for now to restore previous behaviour
|
// NOTE: We do the opposite as Nintendo here for now to restore previous behaviour
|
||||||
|
|||||||
@@ -63,11 +63,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<byte> inputSpan = Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = Parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < Parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsLongSizePreDelaySupported = isLongSizePreDelaySupported;
|
IsLongSizePreDelaySupported = isLongSizePreDelaySupported;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
{
|
{
|
||||||
int tempBufferIndex = 0;
|
int tempBufferIndex = 0;
|
||||||
|
|
||||||
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
|
if ((info.DecodingBehaviour & DecodingBehaviour.SkipPitchAndSampleRateConversion) != DecodingBehaviour.SkipPitchAndSampleRateConversion)
|
||||||
{
|
{
|
||||||
voiceState.Pitch.AsSpan()[..pitchMaxLength].CopyTo(tempBuffer);
|
voiceState.Pitch.AsSpan()[..pitchMaxLength].CopyTo(tempBuffer);
|
||||||
tempBufferIndex += pitchMaxLength;
|
tempBufferIndex += pitchMaxLength;
|
||||||
@@ -208,7 +208,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.DecodingBehaviour.HasFlag(DecodingBehaviour.PlayedSampleCountResetWhenLooping))
|
if ((info.DecodingBehaviour & DecodingBehaviour.PlayedSampleCountResetWhenLooping) == DecodingBehaviour.PlayedSampleCountResetWhenLooping)
|
||||||
{
|
{
|
||||||
playedSampleCount = 0;
|
playedSampleCount = 0;
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
Span<int> outputSpanInt = MemoryMarshal.Cast<float, int>(outputBuffer[i..]);
|
Span<int> outputSpanInt = MemoryMarshal.Cast<float, int>(outputBuffer[i..]);
|
||||||
|
|
||||||
if (info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
|
if ((info.DecodingBehaviour & DecodingBehaviour.SkipPitchAndSampleRateConversion) == DecodingBehaviour.SkipPitchAndSampleRateConversion)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < y; j++)
|
for (int j = 0; j < y; j++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
|
|
||||||
DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain;
|
DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain;
|
||||||
|
|
||||||
if (parameter.ChannelCount == 4 || parameter.ChannelCount == 6)
|
if (parameter.ChannelCount is 4 or 6)
|
||||||
{
|
{
|
||||||
DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain;
|
DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,11 +40,12 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
}
|
}
|
||||||
|
|
||||||
Array20<float> result = new();
|
Array20<float> result = new();
|
||||||
|
Span<float> resultSpan = result.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < FilterBankLength; i++)
|
for (int i = 0; i < FilterBankLength; i++)
|
||||||
{
|
{
|
||||||
float x = (Bank0CenterIndex - i) + offset;
|
float x = (Bank0CenterIndex - i) + offset;
|
||||||
result[i] = Sinc(x) * BlackmanWindow(x / FilterBankLength + 0.5f);
|
resultSpan[i] = Sinc(x) * BlackmanWindow(x / FilterBankLength + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -77,6 +78,9 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
Debug.Assert(state.History.Length == HistoryLength);
|
Debug.Assert(state.History.Length == HistoryLength);
|
||||||
Debug.Assert(bank.Length == FilterBankLength);
|
Debug.Assert(bank.Length == FilterBankLength);
|
||||||
|
|
||||||
|
Span<float> bankSpan = bank.AsSpan();
|
||||||
|
Span<float> historySpan = state.History.AsSpan();
|
||||||
|
|
||||||
int curIdx = 0;
|
int curIdx = 0;
|
||||||
if (Vector.IsHardwareAccelerated)
|
if (Vector.IsHardwareAccelerated)
|
||||||
@@ -87,15 +91,15 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
while (curIdx < stopIdx)
|
while (curIdx < stopIdx)
|
||||||
{
|
{
|
||||||
result += Vector.Dot(
|
result += Vector.Dot(
|
||||||
new Vector<float>(bank.AsSpan().Slice(curIdx, Vector<float>.Count)),
|
new Vector<float>(bankSpan[curIdx..(curIdx + Vector<float>.Count)]),
|
||||||
new Vector<float>(state.History.AsSpan().Slice(curIdx, Vector<float>.Count)));
|
new Vector<float>(historySpan[curIdx..(curIdx + Vector<float>.Count)]));
|
||||||
curIdx += Vector<float>.Count;
|
curIdx += Vector<float>.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (curIdx < FilterBankLength)
|
while (curIdx < FilterBankLength)
|
||||||
{
|
{
|
||||||
result += bank[curIdx] * state.History[curIdx];
|
result += bankSpan[curIdx] * historySpan[curIdx];
|
||||||
curIdx++;
|
curIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
|||||||
/// <returns>Returns true if the channel count is valid.</returns>
|
/// <returns>Returns true if the channel count is valid.</returns>
|
||||||
public static bool IsChannelCountValid(int channelCount)
|
public static bool IsChannelCountValid(int channelCount)
|
||||||
{
|
{
|
||||||
return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6;
|
return channelCount is 1 or 2 or 4 or 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
|||||||
/// <returns>Returns true if the channel count is valid.</returns>
|
/// <returns>Returns true if the channel count is valid.</returns>
|
||||||
public static bool IsChannelCountValid(int channelCount)
|
public static bool IsChannelCountValid(int channelCount)
|
||||||
{
|
{
|
||||||
return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6;
|
return channelCount is 1 or 2 or 4 or 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PoolMapper poolMapper = new PoolMapper(_processHandle, _memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
|
PoolMapper poolMapper = new(_processHandle, _memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
|
||||||
|
|
||||||
result = stateUpdater.UpdateVoices(_voiceContext, poolMapper);
|
result = stateUpdater.UpdateVoices(_voiceContext, poolMapper);
|
||||||
|
|
||||||
@@ -532,13 +532,13 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
CommandType commandType = command.CommandType;
|
CommandType commandType = command.CommandType;
|
||||||
|
|
||||||
if (commandType == CommandType.AdpcmDataSourceVersion1 ||
|
if (commandType is CommandType.AdpcmDataSourceVersion1
|
||||||
commandType == CommandType.AdpcmDataSourceVersion2 ||
|
or CommandType.AdpcmDataSourceVersion2
|
||||||
commandType == CommandType.PcmInt16DataSourceVersion1 ||
|
or CommandType.PcmInt16DataSourceVersion1
|
||||||
commandType == CommandType.PcmInt16DataSourceVersion2 ||
|
or CommandType.PcmInt16DataSourceVersion2
|
||||||
commandType == CommandType.PcmFloatDataSourceVersion1 ||
|
or CommandType.PcmFloatDataSourceVersion1
|
||||||
commandType == CommandType.PcmFloatDataSourceVersion2 ||
|
or CommandType.PcmFloatDataSourceVersion2
|
||||||
commandType == CommandType.Performance)
|
or CommandType.Performance)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,18 +141,20 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
bool supportsOptimizedPath = _rendererContext.BehaviourContext.UseMultiTapBiquadFilterProcessing();
|
bool supportsOptimizedPath = _rendererContext.BehaviourContext.UseMultiTapBiquadFilterProcessing();
|
||||||
|
|
||||||
if (supportsOptimizedPath && voiceState.BiquadFilters[0].Enable && voiceState.BiquadFilters[1].Enable)
|
Span<BiquadFilterParameter> biquadFiltersSpan = voiceState.BiquadFilters.AsSpan();
|
||||||
|
|
||||||
|
if (supportsOptimizedPath && biquadFiltersSpan[0].Enable && biquadFiltersSpan[1].Enable)
|
||||||
{
|
{
|
||||||
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state)[..(Unsafe.SizeOf<BiquadFilterState>() * Constants.VoiceBiquadFilterCount)];
|
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state)[..(Unsafe.SizeOf<BiquadFilterState>() * Constants.VoiceBiquadFilterCount)];
|
||||||
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
||||||
|
|
||||||
_commandBuffer.GenerateMultiTapBiquadFilter(baseIndex, voiceState.BiquadFilters.AsSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
|
_commandBuffer.GenerateMultiTapBiquadFilter(baseIndex, biquadFiltersSpan, stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < voiceState.BiquadFilters.Length; i++)
|
for (int i = 0; i < biquadFiltersSpan.Length; i++)
|
||||||
{
|
{
|
||||||
ref BiquadFilterParameter filter = ref voiceState.BiquadFilters[i];
|
ref BiquadFilterParameter filter = ref biquadFiltersSpan[i];
|
||||||
|
|
||||||
if (filter.Enable)
|
if (filter.Enable)
|
||||||
{
|
{
|
||||||
@@ -311,12 +313,15 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
int nodeId = voiceState.NodeId;
|
int nodeId = voiceState.NodeId;
|
||||||
uint channelsCount = voiceState.ChannelsCount;
|
uint channelsCount = voiceState.ChannelsCount;
|
||||||
|
|
||||||
|
Span<int> channelResourceIdsSpan = voiceState.ChannelResourceIds.AsSpan();
|
||||||
|
Span<BiquadFilterParameter> biquadFiltersSpan = voiceState.BiquadFilters.AsSpan();
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < channelsCount; channelIndex++)
|
for (int channelIndex = 0; channelIndex < channelsCount; channelIndex++)
|
||||||
{
|
{
|
||||||
Memory<VoiceUpdateState> dspStateMemory = _voiceContext.GetUpdateStateForDsp(voiceState.ChannelResourceIds[channelIndex]);
|
Memory<VoiceUpdateState> dspStateMemory = _voiceContext.GetUpdateStateForDsp(channelResourceIdsSpan[channelIndex]);
|
||||||
|
|
||||||
ref VoiceChannelResource channelResource = ref _voiceContext.GetChannelResource(voiceState.ChannelResourceIds[channelIndex]);
|
ref VoiceChannelResource channelResource = ref _voiceContext.GetChannelResource(channelResourceIdsSpan[channelIndex]);
|
||||||
|
|
||||||
PerformanceDetailType dataSourceDetailType = PerformanceDetailType.Adpcm;
|
PerformanceDetailType dataSourceDetailType = PerformanceDetailType.Adpcm;
|
||||||
|
|
||||||
@@ -476,7 +481,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
for (int i = 0; i < voiceState.BiquadFilterNeedInitialization.Length; i++)
|
for (int i = 0; i < voiceState.BiquadFilterNeedInitialization.Length; i++)
|
||||||
{
|
{
|
||||||
voiceState.BiquadFilterNeedInitialization[i] = voiceState.BiquadFilters[i].Enable;
|
voiceState.BiquadFilterNeedInitialization[i] = biquadFiltersSpan[i].Enable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -526,15 +531,19 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
if (effect.IsEnabled)
|
if (effect.IsEnabled)
|
||||||
{
|
{
|
||||||
|
Span<float> volumesSpan = effect.Parameter.Volumes.AsSpan();
|
||||||
|
Span<byte> inputSpan = effect.Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = effect.Parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < effect.Parameter.MixesCount; i++)
|
for (int i = 0; i < effect.Parameter.MixesCount; i++)
|
||||||
{
|
{
|
||||||
if (effect.Parameter.Volumes[i] != 0.0f)
|
if (volumesSpan[i] != 0.0f)
|
||||||
{
|
{
|
||||||
_commandBuffer.GenerateMix(
|
_commandBuffer.GenerateMix(
|
||||||
(uint)bufferOffset + effect.Parameter.Input[i],
|
(uint)bufferOffset + inputSpan[i],
|
||||||
(uint)bufferOffset + effect.Parameter.Output[i],
|
(uint)bufferOffset + outputSpan[i],
|
||||||
nodeId,
|
nodeId,
|
||||||
effect.Parameter.Volumes[i]);
|
volumesSpan[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -554,6 +563,10 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint writeOffset = 0;
|
uint writeOffset = 0;
|
||||||
|
|
||||||
|
Span<byte> inputSpan = effect.Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = effect.Parameter.Output.AsSpan();
|
||||||
|
|
||||||
for (uint channelIndex = effect.Parameter.ChannelCount; channelIndex != 0; channelIndex--)
|
for (uint channelIndex = effect.Parameter.ChannelCount; channelIndex != 0; channelIndex--)
|
||||||
{
|
{
|
||||||
uint newUpdateCount = writeOffset + _commandBuffer.CommandList.SampleCount;
|
uint newUpdateCount = writeOffset + _commandBuffer.CommandList.SampleCount;
|
||||||
@@ -571,8 +584,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
_commandBuffer.GenerateAuxEffect(
|
_commandBuffer.GenerateAuxEffect(
|
||||||
bufferOffset,
|
bufferOffset,
|
||||||
effect.Parameter.Input[i],
|
inputSpan[i],
|
||||||
effect.Parameter.Output[i],
|
outputSpan[i],
|
||||||
ref effect.State,
|
ref effect.State,
|
||||||
effect.IsEnabled,
|
effect.IsEnabled,
|
||||||
effect.Parameter.BufferStorageSize,
|
effect.Parameter.BufferStorageSize,
|
||||||
@@ -619,6 +632,9 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
private void GenerateBiquadFilterEffect(uint bufferOffset, BiquadFilterEffect effect, int nodeId)
|
private void GenerateBiquadFilterEffect(uint bufferOffset, BiquadFilterEffect effect, int nodeId)
|
||||||
{
|
{
|
||||||
Debug.Assert(effect.Type == EffectType.BiquadFilter);
|
Debug.Assert(effect.Type == EffectType.BiquadFilter);
|
||||||
|
|
||||||
|
Span<byte> inputSpan = effect.Parameter.Input.AsSpan();
|
||||||
|
Span<byte> outputSpan = effect.Parameter.Output.AsSpan();
|
||||||
|
|
||||||
if (effect.IsEnabled)
|
if (effect.IsEnabled)
|
||||||
{
|
{
|
||||||
@@ -639,8 +655,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
(int)bufferOffset,
|
(int)bufferOffset,
|
||||||
ref parameter,
|
ref parameter,
|
||||||
effect.State.Slice(i, 1),
|
effect.State.Slice(i, 1),
|
||||||
effect.Parameter.Input[i],
|
inputSpan[i],
|
||||||
effect.Parameter.Output[i],
|
outputSpan[i],
|
||||||
needInitialization,
|
needInitialization,
|
||||||
nodeId);
|
nodeId);
|
||||||
}
|
}
|
||||||
@@ -649,8 +665,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < effect.Parameter.ChannelCount; i++)
|
for (int i = 0; i < effect.Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
uint inputBufferIndex = bufferOffset + effect.Parameter.Input[i];
|
uint inputBufferIndex = bufferOffset + inputSpan[i];
|
||||||
uint outputBufferIndex = bufferOffset + effect.Parameter.Output[i];
|
uint outputBufferIndex = bufferOffset + outputSpan[i];
|
||||||
|
|
||||||
// If the input and output isn't the same, generate a command.
|
// If the input and output isn't the same, generate a command.
|
||||||
if (inputBufferIndex != outputBufferIndex)
|
if (inputBufferIndex != outputBufferIndex)
|
||||||
@@ -701,6 +717,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint writeOffset = 0;
|
uint writeOffset = 0;
|
||||||
|
|
||||||
|
Span<byte> inputSpan = effect.Parameter.Input.AsSpan();
|
||||||
|
|
||||||
for (uint channelIndex = effect.Parameter.ChannelCount; channelIndex != 0; channelIndex--)
|
for (uint channelIndex = effect.Parameter.ChannelCount; channelIndex != 0; channelIndex--)
|
||||||
{
|
{
|
||||||
@@ -719,7 +737,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
_commandBuffer.GenerateCaptureEffect(
|
_commandBuffer.GenerateCaptureEffect(
|
||||||
bufferOffset,
|
bufferOffset,
|
||||||
effect.Parameter.Input[i],
|
inputSpan[i],
|
||||||
effect.State.SendBufferInfo,
|
effect.State.SendBufferInfo,
|
||||||
effect.IsEnabled,
|
effect.IsEnabled,
|
||||||
effect.Parameter.BufferStorageSize,
|
effect.Parameter.BufferStorageSize,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(PerformanceCommand command)
|
public uint Estimate(PerformanceCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(ClearMixBufferCommand command)
|
public uint Estimate(ClearMixBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerBuffer = 668.8f;
|
float costPerBuffer = 668.8f;
|
||||||
float baseCost = 193.2f;
|
float baseCost = 193.2f;
|
||||||
@@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(BiquadFilterCommand command)
|
public uint Estimate(BiquadFilterCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -62,7 +62,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
const float CostPerSample = 7.245f;
|
const float CostPerSample = 7.245f;
|
||||||
|
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
int volumeCount = 0;
|
int volumeCount = 0;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(MixRampCommand command)
|
public uint Estimate(MixRampCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DepopPrepareCommand command)
|
public uint Estimate(DepopPrepareCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(VolumeRampCommand command)
|
public uint Estimate(VolumeRampCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(PcmInt16DataSourceCommandVersion1 command)
|
public uint Estimate(PcmInt16DataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 1195.5f;
|
float costPerSample = 1195.5f;
|
||||||
float baseCost = 7797.0f;
|
float baseCost = 7797.0f;
|
||||||
@@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(AdpcmDataSourceCommandVersion1 command)
|
public uint Estimate(AdpcmDataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 3564.1f;
|
float costPerSample = 3564.1f;
|
||||||
float baseCost = 6225.5f;
|
float baseCost = 6225.5f;
|
||||||
@@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DepopForMixBuffersCommand command)
|
public uint Estimate(DepopForMixBuffersCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(CopyMixBufferCommand command)
|
public uint Estimate(CopyMixBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(MixCommand command)
|
public uint Estimate(MixCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DelayCommand command)
|
public uint Estimate(DelayCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -234,7 +234,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(ReverbCommand command)
|
public uint Estimate(ReverbCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -285,7 +285,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(Reverb3dCommand command)
|
public uint Estimate(Reverb3dCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -335,7 +335,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(AuxiliaryBufferCommand command)
|
public uint Estimate(AuxiliaryBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -357,7 +357,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(VolumeCommand command)
|
public uint Estimate(VolumeCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -369,7 +369,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(CircularBufferSinkCommand command)
|
public uint Estimate(CircularBufferSinkCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerBuffer = 1726.0f;
|
float costPerBuffer = 1726.0f;
|
||||||
float baseCost = 1369.7f;
|
float baseCost = 1369.7f;
|
||||||
@@ -385,7 +385,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DownMixSurroundToStereoCommand command)
|
public uint Estimate(DownMixSurroundToStereoCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -397,7 +397,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(UpsampleCommand command)
|
public uint Estimate(UpsampleCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
if (_sampleCount == 160)
|
if (_sampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -409,8 +409,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DeviceSinkCommand command)
|
public uint Estimate(DeviceSinkCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
Debug.Assert(command.InputCount == 2 || command.InputCount == 6);
|
Debug.Assert(command.InputCount is 2 or 6);
|
||||||
|
|
||||||
if (command.InputCount == 2)
|
if (command.InputCount == 2)
|
||||||
{
|
{
|
||||||
@@ -433,7 +433,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
public uint Estimate(PcmFloatDataSourceCommandVersion1 command)
|
public uint Estimate(PcmFloatDataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
// NOTE: This was added between REV7 and REV8 and for some reasons the estimator v2 was changed...
|
// NOTE: This was added between REV7 and REV8 and for some reasons the estimator v2 was changed...
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 3490.9f;
|
float costPerSample = 3490.9f;
|
||||||
float baseCost = 10091.0f;
|
float baseCost = 10091.0f;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(PerformanceCommand command)
|
public uint Estimate(PerformanceCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(ClearMixBufferCommand command)
|
public uint Estimate(ClearMixBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerBuffer = 440.68f;
|
float costPerBuffer = 440.68f;
|
||||||
float baseCost = 0;
|
float baseCost = 0;
|
||||||
@@ -50,7 +50,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(BiquadFilterCommand command)
|
public uint Estimate(BiquadFilterCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
float costPerSample = 6.4434f;
|
float costPerSample = 6.4434f;
|
||||||
|
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -86,7 +86,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(MixRampCommand command)
|
public uint Estimate(MixRampCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(VolumeRampCommand command)
|
public uint Estimate(VolumeRampCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(PcmInt16DataSourceCommandVersion1 command)
|
public uint Estimate(PcmInt16DataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 710.143f;
|
float costPerSample = 710.143f;
|
||||||
float baseCost = 7853.286f;
|
float baseCost = 7853.286f;
|
||||||
@@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(AdpcmDataSourceCommandVersion1 command)
|
public uint Estimate(AdpcmDataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 3564.1f;
|
float costPerSample = 3564.1f;
|
||||||
float baseCost = 9736.702f;
|
float baseCost = 9736.702f;
|
||||||
@@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DepopForMixBuffersCommand command)
|
public uint Estimate(DepopForMixBuffersCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(CopyMixBufferCommand command)
|
public uint Estimate(CopyMixBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(MixCommand command)
|
public uint Estimate(MixCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public virtual uint Estimate(DelayCommand command)
|
public virtual uint Estimate(DelayCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -233,7 +233,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public virtual uint Estimate(ReverbCommand command)
|
public virtual uint Estimate(ReverbCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -283,7 +283,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public virtual uint Estimate(Reverb3dCommand command)
|
public virtual uint Estimate(Reverb3dCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -333,7 +333,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(AuxiliaryBufferCommand command)
|
public uint Estimate(AuxiliaryBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -355,7 +355,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(VolumeCommand command)
|
public uint Estimate(VolumeCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -367,7 +367,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(CircularBufferSinkCommand command)
|
public uint Estimate(CircularBufferSinkCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerBuffer = 770.26f;
|
float costPerBuffer = 770.26f;
|
||||||
float baseCost = 0f;
|
float baseCost = 0f;
|
||||||
@@ -382,7 +382,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DownMixSurroundToStereoCommand command)
|
public uint Estimate(DownMixSurroundToStereoCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -394,7 +394,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(UpsampleCommand command)
|
public uint Estimate(UpsampleCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -406,8 +406,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DeviceSinkCommand command)
|
public uint Estimate(DeviceSinkCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
Debug.Assert(command.InputCount == 2 || command.InputCount == 6);
|
Debug.Assert(command.InputCount is 2 or 6);
|
||||||
|
|
||||||
if (command.InputCount == 2)
|
if (command.InputCount == 2)
|
||||||
{
|
{
|
||||||
@@ -429,7 +429,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(PcmFloatDataSourceCommandVersion1 command)
|
public uint Estimate(PcmFloatDataSourceCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
float costPerSample = 3490.9f;
|
float costPerSample = 3490.9f;
|
||||||
float baseCost = 10090.9f;
|
float baseCost = 10090.9f;
|
||||||
@@ -445,7 +445,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(DataSourceVersion2Command command)
|
public uint Estimate(DataSourceVersion2Command command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
(float baseCost, float costPerSample) = GetCostByFormat(SampleCount, command.SampleFormat, command.SrcQuality);
|
(float baseCost, float costPerSample) = GetCostByFormat(SampleCount, command.SampleFormat, command.SrcQuality);
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
private static (float, float) GetCostByFormat(uint sampleCount, SampleFormat format, SampleRateConversionQuality quality)
|
private static (float, float) GetCostByFormat(uint sampleCount, SampleFormat format, SampleRateConversionQuality quality)
|
||||||
{
|
{
|
||||||
Debug.Assert(sampleCount == 160 || sampleCount == 240);
|
Debug.Assert(sampleCount is 160 or 240);
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
@@ -540,7 +540,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
private uint EstimateLimiterCommandCommon(LimiterParameter parameter, bool enabled)
|
private uint EstimateLimiterCommandCommon(LimiterParameter parameter, bool enabled)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -590,14 +590,14 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(LimiterCommandVersion1 command)
|
public uint Estimate(LimiterCommandVersion1 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled);
|
return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Estimate(LimiterCommandVersion2 command)
|
public uint Estimate(LimiterCommandVersion2 command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (!command.Parameter.StatisticsEnabled || !command.IsEffectEnabled)
|
if (!command.Parameter.StatisticsEnabled || !command.IsEffectEnabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(MultiTapBiquadFilterCommand command)
|
public override uint Estimate(MultiTapBiquadFilterCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -24,7 +24,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(CaptureBufferCommand command)
|
public override uint Estimate(CaptureBufferCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(DelayCommand command)
|
public override uint Estimate(DelayCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(ReverbCommand command)
|
public override uint Estimate(ReverbCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(Reverb3dCommand command)
|
public override uint Estimate(Reverb3dCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -163,7 +163,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(CompressorCommand command)
|
public override uint Estimate(CompressorCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (SampleCount == 160)
|
if (SampleCount == 160)
|
||||||
{
|
{
|
||||||
@@ -241,7 +241,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(BiquadFilterAndMixCommand command)
|
public override uint Estimate(BiquadFilterAndMixCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (command.HasVolumeRamp)
|
if (command.HasVolumeRamp)
|
||||||
{
|
{
|
||||||
@@ -265,7 +265,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public override uint Estimate(MultiTapBiquadFilterAndMixCommand command)
|
public override uint Estimate(MultiTapBiquadFilterAndMixCommand command)
|
||||||
{
|
{
|
||||||
Debug.Assert(SampleCount == 160 || SampleCount == 240);
|
Debug.Assert(SampleCount is 160 or 240);
|
||||||
|
|
||||||
if (command.HasVolumeRamp)
|
if (command.HasVolumeRamp)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -262,12 +262,8 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool
|
|||||||
return UpdateResult.Success;
|
return UpdateResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % PageSize) != 0)
|
if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % PageSize) != 0 ||
|
||||||
{
|
inParameter.Size == 0 || (inParameter.Size % PageSize) != 0)
|
||||||
return UpdateResult.InvalidParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inParameter.Size == 0 || (inParameter.Size % PageSize) != 0)
|
|
||||||
{
|
{
|
||||||
return UpdateResult.InvalidParameter;
|
return UpdateResult.InvalidParameter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
|||||||
/// <returns>True if any biquad filter is enabled.</returns>
|
/// <returns>True if any biquad filter is enabled.</returns>
|
||||||
public bool IsBiquadFilterEnabled()
|
public bool IsBiquadFilterEnabled()
|
||||||
{
|
{
|
||||||
return _biquadFilters[0].Enable || _biquadFilters[1].Enable;
|
Span<BiquadFilterParameter> biquadFiltersSpan = _biquadFilters.AsSpan();
|
||||||
|
return biquadFiltersSpan[0].Enable || biquadFiltersSpan[1].Enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -162,9 +162,11 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
{
|
{
|
||||||
ref VoiceState currentVoiceState = ref context.GetState(i);
|
ref VoiceState currentVoiceState = ref context.GetState(i);
|
||||||
|
|
||||||
|
Span<int> channelResourceIdsSpan = parameter.ChannelResourceIds.AsSpan();
|
||||||
|
|
||||||
for (int channelResourceIndex = 0; channelResourceIndex < parameter.ChannelCount; channelResourceIndex++)
|
for (int channelResourceIndex = 0; channelResourceIndex < parameter.ChannelCount; channelResourceIndex++)
|
||||||
{
|
{
|
||||||
int channelId = parameter.ChannelResourceIds[channelResourceIndex];
|
int channelId = channelResourceIdsSpan[channelResourceIndex];
|
||||||
|
|
||||||
Debug.Assert(channelId >= 0 && channelId < context.GetCount());
|
Debug.Assert(channelId >= 0 && channelId < context.GetCount());
|
||||||
|
|
||||||
|
|||||||
@@ -126,9 +126,9 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
_sortedVoices.Span[i] = i;
|
_sortedVoices.Span[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] sortedVoicesTemp = _sortedVoices[..(int)GetCount()].ToArray();
|
Span<int> sortedVoicesTemp = _sortedVoices[..(int)_voiceCount].Span;
|
||||||
|
|
||||||
Array.Sort(sortedVoicesTemp, (a, b) =>
|
sortedVoicesTemp.Sort((a, b) =>
|
||||||
{
|
{
|
||||||
ref VoiceState aState = ref GetState(a);
|
ref VoiceState aState = ref GetState(a);
|
||||||
ref VoiceState bState = ref GetState(b);
|
ref VoiceState bState = ref GetState(b);
|
||||||
@@ -143,7 +143,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
sortedVoicesTemp.AsSpan().CopyTo(_sortedVoices.Span);
|
// sortedVoicesTemp.CopyTo(_sortedVoices.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,15 +219,17 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeWaveBuffers()
|
private void InitializeWaveBuffers()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan();
|
||||||
|
|
||||||
|
for (int i = 0; i < waveBuffersSpan.Length; i++)
|
||||||
{
|
{
|
||||||
WaveBuffers[i].StartSampleOffset = 0;
|
waveBuffersSpan[i].StartSampleOffset = 0;
|
||||||
WaveBuffers[i].EndSampleOffset = 0;
|
waveBuffersSpan[i].EndSampleOffset = 0;
|
||||||
WaveBuffers[i].ShouldLoop = false;
|
waveBuffersSpan[i].ShouldLoop = false;
|
||||||
WaveBuffers[i].IsEndOfStream = false;
|
waveBuffersSpan[i].IsEndOfStream = false;
|
||||||
WaveBuffers[i].BufferAddressInfo.Setup(0, 0);
|
waveBuffersSpan[i].BufferAddressInfo.Setup(0, 0);
|
||||||
WaveBuffers[i].ContextAddressInfo.Setup(0, 0);
|
waveBuffersSpan[i].ContextAddressInfo.Setup(0, 0);
|
||||||
WaveBuffers[i].IsSendToAudioProcessor = true;
|
waveBuffersSpan[i].IsSendToAudioProcessor = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,10 +448,13 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
}
|
}
|
||||||
|
|
||||||
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[0].Span[0];
|
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[0].Span[0];
|
||||||
|
|
||||||
|
Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan();
|
||||||
|
Span<WaveBufferInternal> pWaveBuffersSpan = parameter.WaveBuffers.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
|
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
|
||||||
{
|
{
|
||||||
UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref WaveBuffers[i], ref parameter.WaveBuffers[i], parameter.SampleFormat, voiceUpdateState.IsWaveBufferValid[i], mapper, ref behaviourContext);
|
UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref waveBuffersSpan[i], ref pWaveBuffersSpan[i], parameter.SampleFormat, voiceUpdateState.IsWaveBufferValid[i], mapper, ref behaviourContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,9 +539,11 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
/// <param name="context">The voice context.</param>
|
/// <param name="context">The voice context.</param>
|
||||||
private void ResetResources(VoiceContext context)
|
private void ResetResources(VoiceContext context)
|
||||||
{
|
{
|
||||||
|
Span<int> channelResourceIdsSpan = ChannelResourceIds.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < ChannelsCount; i++)
|
for (int i = 0; i < ChannelsCount; i++)
|
||||||
{
|
{
|
||||||
int channelResourceId = ChannelResourceIds[i];
|
int channelResourceId = channelResourceIdsSpan[i];
|
||||||
|
|
||||||
ref VoiceChannelResource voiceChannelResource = ref context.GetChannelResource(channelResourceId);
|
ref VoiceChannelResource voiceChannelResource = ref context.GetChannelResource(channelResourceId);
|
||||||
|
|
||||||
@@ -559,10 +566,12 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
private void FlushWaveBuffers(uint waveBufferCount, Memory<VoiceUpdateState>[] voiceUpdateStates, uint channelCount)
|
private void FlushWaveBuffers(uint waveBufferCount, Memory<VoiceUpdateState>[] voiceUpdateStates, uint channelCount)
|
||||||
{
|
{
|
||||||
uint waveBufferIndex = WaveBuffersIndex;
|
uint waveBufferIndex = WaveBuffersIndex;
|
||||||
|
|
||||||
|
Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < waveBufferCount; i++)
|
for (int i = 0; i < waveBufferCount; i++)
|
||||||
{
|
{
|
||||||
WaveBuffers[(int)waveBufferIndex].IsSendToAudioProcessor = true;
|
waveBuffersSpan[(int)waveBufferIndex].IsSendToAudioProcessor = true;
|
||||||
|
|
||||||
for (int j = 0; j < channelCount; j++)
|
for (int j = 0; j < channelCount; j++)
|
||||||
{
|
{
|
||||||
@@ -591,14 +600,18 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
FlushWaveBufferCount = 0;
|
FlushWaveBufferCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Span<WaveBuffer> waveBuffersSpan;
|
||||||
|
|
||||||
switch (PlayState)
|
switch (PlayState)
|
||||||
{
|
{
|
||||||
case PlayState.Started:
|
case PlayState.Started:
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
waveBuffersSpan = WaveBuffers.AsSpan();
|
||||||
|
|
||||||
|
for (int i = 0; i < waveBuffersSpan.Length; i++)
|
||||||
{
|
{
|
||||||
ref WaveBuffer wavebuffer = ref WaveBuffers[i];
|
ref WaveBuffer waveBuffer = ref waveBuffersSpan[i];
|
||||||
|
|
||||||
if (!wavebuffer.IsSendToAudioProcessor)
|
if (!waveBuffer.IsSendToAudioProcessor)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < ChannelsCount; y++)
|
for (int y = 0; y < ChannelsCount; y++)
|
||||||
{
|
{
|
||||||
@@ -607,7 +620,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
voiceUpdateStates[y].Span[0].IsWaveBufferValid[i] = true;
|
voiceUpdateStates[y].Span[0].IsWaveBufferValid[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wavebuffer.IsSendToAudioProcessor = true;
|
waveBuffer.IsSendToAudioProcessor = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,11 +639,13 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
case PlayState.Stopping:
|
case PlayState.Stopping:
|
||||||
for (int i = 0; i < WaveBuffers.Length; i++)
|
waveBuffersSpan = WaveBuffers.AsSpan();
|
||||||
|
|
||||||
|
for (int i = 0; i < waveBuffersSpan.Length; i++)
|
||||||
{
|
{
|
||||||
ref WaveBuffer wavebuffer = ref WaveBuffers[i];
|
ref WaveBuffer waveBuffer = ref waveBuffersSpan[i];
|
||||||
|
|
||||||
wavebuffer.IsSendToAudioProcessor = true;
|
waveBuffer.IsSendToAudioProcessor = true;
|
||||||
|
|
||||||
for (int j = 0; j < ChannelsCount; j++)
|
for (int j = 0; j < ChannelsCount; j++)
|
||||||
{
|
{
|
||||||
@@ -702,9 +717,11 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
|||||||
|
|
||||||
Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
|
Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
|
Span<int> channelResourceIdsSpan = ChannelResourceIds.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < ChannelsCount; i++)
|
for (int i = 0; i < ChannelsCount; i++)
|
||||||
{
|
{
|
||||||
voiceUpdateStates[i] = context.GetUpdateStateForDsp(ChannelResourceIds[i]);
|
voiceUpdateStates[i] = context.GetUpdateStateForDsp(channelResourceIdsSpan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateParametersForCommandGeneration(voiceUpdateStates);
|
return UpdateParametersForCommandGeneration(voiceUpdateStates);
|
||||||
|
|||||||
@@ -0,0 +1,226 @@
|
|||||||
|
namespace Ryujinx.Common.Collections
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a collection that can store 1 bit values.
|
||||||
|
/// </summary>
|
||||||
|
public struct BitMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Size in bits of the integer used internally for the groups of bits.
|
||||||
|
/// </summary>
|
||||||
|
public const int IntSize = 64;
|
||||||
|
|
||||||
|
private const int IntShift = 6;
|
||||||
|
private const int IntMask = IntSize - 1;
|
||||||
|
|
||||||
|
private readonly long[] _masks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of a bit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bit">Bit to access</param>
|
||||||
|
/// <returns>Bit value</returns>
|
||||||
|
public bool this[int bit]
|
||||||
|
{
|
||||||
|
get => IsSet(bit);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
Set(bit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Clear(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new bitmap.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">Total number of bits</param>
|
||||||
|
public BitMap(int count)
|
||||||
|
{
|
||||||
|
_masks = new long[(count + IntMask) / IntSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if any bit is set.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if any bit is set, false otherwise</returns>
|
||||||
|
public bool AnySet()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _masks.Length; i++)
|
||||||
|
{
|
||||||
|
if (_masks[i] != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specific bit is set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bit">Bit to be checked</param>
|
||||||
|
/// <returns>True if set, false otherwise</returns>
|
||||||
|
public bool IsSet(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
return (_masks[wordIndex] & wordMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if any bit inside a given range of bits is set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">Start bit of the range</param>
|
||||||
|
/// <param name="end">End bit of the range (inclusive)</param>
|
||||||
|
/// <returns>True if any bit is set, false otherwise</returns>
|
||||||
|
public bool IsSet(int start, int end)
|
||||||
|
{
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
return IsSet(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = start >> IntShift;
|
||||||
|
int startBit = start & IntMask;
|
||||||
|
long startMask = -1L << startBit;
|
||||||
|
|
||||||
|
int endIndex = end >> IntShift;
|
||||||
|
int endBit = end & IntMask;
|
||||||
|
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||||
|
|
||||||
|
if (startIndex == endIndex)
|
||||||
|
{
|
||||||
|
return (_masks[startIndex] & startMask & endMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_masks[startIndex] & startMask) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = startIndex + 1; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
if (_masks[i] != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_masks[endIndex] & endMask) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the value of a bit to 1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bit">Bit to be set</param>
|
||||||
|
/// <returns>True if the bit was 0 and then changed to 1, false if it was already 1</returns>
|
||||||
|
public bool Set(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
if ((_masks[wordIndex] & wordMask) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_masks[wordIndex] |= wordMask;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a given range of bits to 1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">Start bit of the range</param>
|
||||||
|
/// <param name="end">End bit of the range (inclusive)</param>
|
||||||
|
public void SetRange(int start, int end)
|
||||||
|
{
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
Set(start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = start >> IntShift;
|
||||||
|
int startBit = start & IntMask;
|
||||||
|
long startMask = -1L << startBit;
|
||||||
|
|
||||||
|
int endIndex = end >> IntShift;
|
||||||
|
int endBit = end & IntMask;
|
||||||
|
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||||
|
|
||||||
|
if (startIndex == endIndex)
|
||||||
|
{
|
||||||
|
_masks[startIndex] |= startMask & endMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_masks[startIndex] |= startMask;
|
||||||
|
|
||||||
|
for (int i = startIndex + 1; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
_masks[i] |= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_masks[endIndex] |= endMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a given bit to 0.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bit">Bit to be cleared</param>
|
||||||
|
public void Clear(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
_masks[wordIndex] &= ~wordMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets all bits to 0.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _masks.Length; i++)
|
||||||
|
{
|
||||||
|
_masks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets one or more groups of bits to 0.
|
||||||
|
/// See <see cref="IntSize"/> for how many bits are inside each group.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">Start index of the group</param>
|
||||||
|
/// <param name="end">End index of the group (inclusive)</param>
|
||||||
|
public void ClearInt(int start, int end)
|
||||||
|
{
|
||||||
|
for (int i = start; i <= end; i++)
|
||||||
|
{
|
||||||
|
_masks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -318,13 +318,16 @@ namespace Ryujinx.Common.Collections
|
|||||||
{
|
{
|
||||||
Root = newNode;
|
Root = newNode;
|
||||||
}
|
}
|
||||||
else if (start.CompareTo(parent.Start) < 0)
|
else if (parent != null && start.CompareTo(parent.Start) < 0)
|
||||||
{
|
{
|
||||||
parent.Left = newNode;
|
parent.Left = newNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parent.Right = newNode;
|
if (parent != null)
|
||||||
|
{
|
||||||
|
parent.Right = newNode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PropagateIncrease(newNode);
|
PropagateIncrease(newNode);
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ namespace Ryujinx.Common.Collections
|
|||||||
/// Adds a new node into the tree.
|
/// Adds a new node into the tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Node to be added</param>
|
/// <param name="node">Node to be added</param>
|
||||||
|
/// <param name="parent">Node to be added under</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
|
||||||
public void Add(T node)
|
public void Add(T node, T parent = null)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(node);
|
ArgumentNullException.ThrowIfNull(node);
|
||||||
|
|
||||||
Insert(node);
|
Insert(node, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -75,9 +76,11 @@ namespace Ryujinx.Common.Collections
|
|||||||
/// Inserts a new node into the tree.
|
/// Inserts a new node into the tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Node to be inserted</param>
|
/// <param name="node">Node to be inserted</param>
|
||||||
private void Insert(T node)
|
/// <param name="parent">Node to be inserted under</param>
|
||||||
|
private void Insert(T node, T parent = null)
|
||||||
{
|
{
|
||||||
T newNode = BSTInsert(node);
|
T newNode = parent != null ? InsertWithParent(node, parent) : BSTInsert(node);
|
||||||
|
|
||||||
RestoreBalanceAfterInsertion(newNode);
|
RestoreBalanceAfterInsertion(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +123,77 @@ namespace Ryujinx.Common.Collections
|
|||||||
else if (newNode.CompareTo(parent) < 0)
|
else if (newNode.CompareTo(parent) < 0)
|
||||||
{
|
{
|
||||||
parent.Left = newNode;
|
parent.Left = newNode;
|
||||||
|
|
||||||
|
newNode.Successor = parent;
|
||||||
|
|
||||||
|
if (parent.Predecessor != null)
|
||||||
|
{
|
||||||
|
newNode.Predecessor = parent.Predecessor;
|
||||||
|
newNode.Predecessor.Successor = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Predecessor = newNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parent.Right = newNode;
|
parent.Right = newNode;
|
||||||
|
|
||||||
|
newNode.Predecessor = parent;
|
||||||
|
|
||||||
|
if (parent.Successor != null)
|
||||||
|
{
|
||||||
|
newNode.Successor = parent.Successor;
|
||||||
|
newNode.Successor.Predecessor = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Successor = newNode;
|
||||||
|
}
|
||||||
|
Count++;
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Insertion Mechanism for a Binary Search Tree (BST).
|
||||||
|
/// <br></br>
|
||||||
|
/// Inserts a new node directly under a parent node
|
||||||
|
/// where all children in the left subtree are less than <paramref name="newNode"/>,
|
||||||
|
/// and all children in the right subtree are greater than <paramref name="newNode"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newNode">Node to be inserted</param>
|
||||||
|
/// <param name="parent">Node to be inserted under</param>
|
||||||
|
/// <returns>The inserted Node</returns>
|
||||||
|
private T InsertWithParent(T newNode, T parent)
|
||||||
|
{
|
||||||
|
newNode.Parent = parent;
|
||||||
|
|
||||||
|
if (newNode.CompareTo(parent) < 0)
|
||||||
|
{
|
||||||
|
parent.Left = newNode;
|
||||||
|
|
||||||
|
newNode.Successor = parent;
|
||||||
|
|
||||||
|
if (parent.Predecessor != null)
|
||||||
|
{
|
||||||
|
newNode.Predecessor = parent.Predecessor;
|
||||||
|
parent.Predecessor = newNode;
|
||||||
|
newNode.Predecessor.Successor = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Predecessor = newNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.Right = newNode;
|
||||||
|
|
||||||
|
newNode.Predecessor = parent;
|
||||||
|
|
||||||
|
if (parent.Successor != null)
|
||||||
|
{
|
||||||
|
newNode.Successor = parent.Successor;
|
||||||
|
newNode.Successor.Predecessor = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Successor = newNode;
|
||||||
}
|
}
|
||||||
Count++;
|
Count++;
|
||||||
return newNode;
|
return newNode;
|
||||||
@@ -156,7 +226,7 @@ namespace Ryujinx.Common.Collections
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
T element = Minimum(RightOf(nodeToDelete));
|
T element = nodeToDelete.Successor;
|
||||||
|
|
||||||
child = RightOf(element);
|
child = RightOf(element);
|
||||||
parent = ParentOf(element);
|
parent = ParentOf(element);
|
||||||
@@ -184,6 +254,9 @@ namespace Ryujinx.Common.Collections
|
|||||||
element.Left = old.Left;
|
element.Left = old.Left;
|
||||||
element.Right = old.Right;
|
element.Right = old.Right;
|
||||||
element.Parent = old.Parent;
|
element.Parent = old.Parent;
|
||||||
|
element.Predecessor = old.Predecessor;
|
||||||
|
if (element.Predecessor != null)
|
||||||
|
element.Predecessor.Successor = element;
|
||||||
|
|
||||||
if (ParentOf(old) == null)
|
if (ParentOf(old) == null)
|
||||||
{
|
{
|
||||||
@@ -238,6 +311,11 @@ namespace Ryujinx.Common.Collections
|
|||||||
{
|
{
|
||||||
RestoreBalanceAfterRemoval(child);
|
RestoreBalanceAfterRemoval(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old.Successor != null)
|
||||||
|
old.Successor.Predecessor = old.Predecessor;
|
||||||
|
if (old.Predecessor != null)
|
||||||
|
old.Predecessor.Successor = old.Successor;
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ namespace Ryujinx.Common.Collections
|
|||||||
public T Left;
|
public T Left;
|
||||||
public T Right;
|
public T Right;
|
||||||
public T Parent;
|
public T Parent;
|
||||||
|
public T Predecessor;
|
||||||
public T Predecessor => IntrusiveRedBlackTreeImpl<T>.PredecessorOf((T)this);
|
public T Successor;
|
||||||
public T Successor => IntrusiveRedBlackTreeImpl<T>.SuccessorOf((T)this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace Ryujinx.Common.Collections
|
|||||||
Node<TKey, TValue> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
Node<TKey, TValue> successor = SuccessorOf(node);
|
Node<TKey, TValue> successor = node.Successor;
|
||||||
|
|
||||||
return successor != null ? successor.Key : default;
|
return successor != null ? successor.Key : default;
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ namespace Ryujinx.Common.Collections
|
|||||||
Node<TKey, TValue> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
Node<TKey, TValue> predecessor = PredecessorOf(node);
|
Node<TKey, TValue> predecessor = node.Predecessor;
|
||||||
|
|
||||||
return predecessor != null ? predecessor.Key : default;
|
return predecessor != null ? predecessor.Key : default;
|
||||||
}
|
}
|
||||||
@@ -132,11 +132,10 @@ namespace Ryujinx.Common.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds all the nodes in the dictionary as key/value pairs into <paramref name="list"/>.
|
/// Adds all the nodes in the dictionary as key/value pairs into a list.
|
||||||
/// <br></br>
|
/// <br></br>
|
||||||
/// The key/value pairs will be added in Level Order.
|
/// The key/value pairs will be added in Level Order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list">List to add the tree pairs into</param>
|
|
||||||
public List<KeyValuePair<TKey, TValue>> AsLevelOrderList()
|
public List<KeyValuePair<TKey, TValue>> AsLevelOrderList()
|
||||||
{
|
{
|
||||||
List<KeyValuePair<TKey, TValue>> list = [];
|
List<KeyValuePair<TKey, TValue>> list = [];
|
||||||
@@ -163,7 +162,7 @@ namespace Ryujinx.Common.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
/// Adds all the nodes in the dictionary into a list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
|
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
|
||||||
public List<KeyValuePair<TKey, TValue>> AsList()
|
public List<KeyValuePair<TKey, TValue>> AsList()
|
||||||
@@ -275,17 +274,20 @@ namespace Ryujinx.Common.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node<TKey, TValue> newNode = new(key, value, parent);
|
Node<TKey, TValue> newNode = new(key, value, parent);
|
||||||
if (newNode.Parent == null)
|
if (parent == null)
|
||||||
{
|
{
|
||||||
Root = newNode;
|
Root = newNode;
|
||||||
}
|
}
|
||||||
else if (key.CompareTo(parent.Key) < 0)
|
else if (parent != null && key.CompareTo(parent.Key) < 0)
|
||||||
{
|
{
|
||||||
parent.Left = newNode;
|
parent.Left = newNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parent.Right = newNode;
|
if (parent != null)
|
||||||
|
{
|
||||||
|
parent.Right = newNode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Count++;
|
Count++;
|
||||||
return newNode;
|
return newNode;
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ namespace Ryujinx.Common.Configuration
|
|||||||
{
|
{
|
||||||
FileSystemInfo resolvedDirectoryInfo =
|
FileSystemInfo resolvedDirectoryInfo =
|
||||||
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
||||||
string resolvedPath = resolvedDirectoryInfo.FullName;
|
string resolvedPath = resolvedDirectoryInfo?.FullName;
|
||||||
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
||||||
}
|
}
|
||||||
catch (Exception symlinkException)
|
catch (Exception symlinkException)
|
||||||
@@ -297,7 +297,7 @@ namespace Ryujinx.Common.Configuration
|
|||||||
{
|
{
|
||||||
FileSystemInfo resolvedDirectoryInfo =
|
FileSystemInfo resolvedDirectoryInfo =
|
||||||
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
||||||
string resolvedPath = resolvedDirectoryInfo.FullName;
|
string resolvedPath = resolvedDirectoryInfo?.FullName;
|
||||||
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
||||||
}
|
}
|
||||||
catch (Exception symlinkException)
|
catch (Exception symlinkException)
|
||||||
|
|||||||
@@ -46,10 +46,11 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
|||||||
// PS5 touchpad button
|
// PS5 touchpad button
|
||||||
Touchpad,
|
Touchpad,
|
||||||
|
|
||||||
// Virtual buttons for single joycon
|
// Virtual buttons for single joycon (left)
|
||||||
SingleLeftTrigger0,
|
SingleLeftTrigger0,
|
||||||
SingleRightTrigger0,
|
SingleRightTrigger0,
|
||||||
|
|
||||||
|
// Virtual buttons for single joycon (right)
|
||||||
SingleLeftTrigger1,
|
SingleLeftTrigger1,
|
||||||
SingleRightTrigger1,
|
SingleRightTrigger1,
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
|||||||
{
|
{
|
||||||
string propertyName = tempReader.GetString();
|
string propertyName = tempReader.GetString();
|
||||||
|
|
||||||
if (propertyName.Equals("motion_backend"))
|
if (propertyName is "motion_backend")
|
||||||
{
|
{
|
||||||
tempReader.Read();
|
tempReader.Read();
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
|||||||
{
|
{
|
||||||
string propertyName = tempReader.GetString();
|
string propertyName = tempReader.GetString();
|
||||||
|
|
||||||
if (propertyName.Equals("backend"))
|
if (propertyName is "backend")
|
||||||
{
|
{
|
||||||
tempReader.Read();
|
tempReader.Read();
|
||||||
|
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
|||||||
public Key VolumeDown { get; set; }
|
public Key VolumeDown { get; set; }
|
||||||
public Key CustomVSyncIntervalIncrement { get; set; }
|
public Key CustomVSyncIntervalIncrement { get; set; }
|
||||||
public Key CustomVSyncIntervalDecrement { get; set; }
|
public Key CustomVSyncIntervalDecrement { get; set; }
|
||||||
|
public Key TurboMode { get; set; }
|
||||||
|
public bool TurboModeWhileHeld { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace Ryujinx.Common.Extensions
|
|||||||
// Not enough data in the current segment, try to peek for the data we need.
|
// Not enough data in the current segment, try to peek for the data we need.
|
||||||
T buffer = default;
|
T buffer = default;
|
||||||
|
|
||||||
Span<byte> tempSpan = new Span<byte>(&buffer, sizeof(T));
|
Span<byte> tempSpan = new(&buffer, sizeof(T));
|
||||||
|
|
||||||
if (!reader.TryCopyTo(tempSpan))
|
if (!reader.TryCopyTo(tempSpan))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Ryujinx.Common.Logging.Formatters
|
namespace Ryujinx.Common.Logging.Formatters
|
||||||
{
|
{
|
||||||
public class DefaultLogFormatter : ILogFormatter
|
internal class DefaultLogFormatter : ILogFormatter
|
||||||
{
|
{
|
||||||
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Ryujinx.Common.Logging
|
|||||||
Cpu,
|
Cpu,
|
||||||
Emulation,
|
Emulation,
|
||||||
FFmpeg,
|
FFmpeg,
|
||||||
|
GdbStub,
|
||||||
Font,
|
Font,
|
||||||
Gpu,
|
Gpu,
|
||||||
Hid,
|
Hid,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ namespace Ryujinx.Common.Logging
|
|||||||
public readonly struct Log
|
public readonly struct Log
|
||||||
{
|
{
|
||||||
private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir).FullName, "[redacted]");
|
private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir)?.FullName ?? string.Empty, "[redacted]");
|
||||||
|
|
||||||
internal readonly LogLevel Level;
|
internal readonly LogLevel Level;
|
||||||
|
|
||||||
@@ -135,14 +136,11 @@ namespace Ryujinx.Common.Logging
|
|||||||
|
|
||||||
_time = Stopwatch.StartNew();
|
_time = Stopwatch.StartNew();
|
||||||
|
|
||||||
if (!PlatformInfo.IsBionic)
|
// Logger should log to console by default
|
||||||
{
|
AddTarget(new AsyncLogTargetWrapper(
|
||||||
// Logger should log to console by default
|
new ConsoleLogTarget("console"),
|
||||||
AddTarget(new AsyncLogTargetWrapper(
|
1000,
|
||||||
new ConsoleLogTarget("console"),
|
AsyncLogTargetOverflowAction.Discard));
|
||||||
1000,
|
|
||||||
AsyncLogTargetOverflowAction.Discard));
|
|
||||||
}
|
|
||||||
|
|
||||||
Notice = new Log(LogLevel.Notice);
|
Notice = new Log(LogLevel.Notice);
|
||||||
|
|
||||||
@@ -160,21 +158,16 @@ namespace Ryujinx.Common.Logging
|
|||||||
_time.Restart();
|
_time.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ILogTarget GetTarget(string targetName)
|
private static ILogTarget GetTarget(string targetName)
|
||||||
{
|
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName));
|
||||||
foreach (var target in _logTargets)
|
|
||||||
{
|
|
||||||
if (target.Name.Equals(targetName))
|
|
||||||
{
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddTarget(ILogTarget target)
|
public static void AddTarget(ILogTarget target)
|
||||||
{
|
{
|
||||||
|
if (_logTargets.Any(t => t.Name == target.Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logTargets.Add(target);
|
_logTargets.Add(target);
|
||||||
|
|
||||||
Updated += target.Log;
|
Updated += target.Log;
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ namespace Ryujinx.Common.Logging.Targets
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up old logs, should only keep 4
|
// Clean up old logs, should only keep 5
|
||||||
FileInfo[] files = logDir.GetFiles("*.log").OrderBy((info => info.CreationTime)).ToArray();
|
FileInfo[] files = logDir.GetFiles("*.log").OrderBy((info => info.CreationTime)).ToArray();
|
||||||
for (int i = 0; i < files.Length - 3; i++)
|
for (int i = 0; i < files.Length - 4; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Memory
|
namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -17,5 +19,10 @@ namespace Ryujinx.Common.Memory
|
|||||||
/// Number of elements on the array.
|
/// Number of elements on the array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int Length { get; }
|
int Length { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of elements on the array.
|
||||||
|
/// </summary>
|
||||||
|
public Span<T> AsSpan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user