mirror of
https://git.ryujinx.app/kenji-nx/ryujinx.git
synced 2025-12-14 07:37:04 +00:00
Revert Android changes
* "Android: NCE support" - Commitcd3221ab* "Android: Numerous fixes" - Commit19dd23c2* "Android: Memory specific switches" - Commit98b4ff33* "Android: Remove unmanaged code" - Commit846b5b6e
This commit is contained in:
parent
3a387309b4
commit
fe7a30c747
62 changed files with 138 additions and 5440 deletions
|
|
@ -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,12 +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
|
|
||||||
using ExecutionContext = ARMeilleure.State.ExecutionContext;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
|
|
@ -40,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();
|
||||||
|
|
@ -54,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();
|
||||||
|
|
@ -68,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();
|
||||||
|
|
@ -83,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;
|
||||||
|
|
@ -135,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);
|
||||||
|
|
@ -187,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);
|
||||||
|
|
@ -280,21 +187,13 @@ 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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
#if ANDROID
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
#else
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
|
|
@ -317,11 +313,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat16_32
|
static class SoftFloat16_32
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPConvert(ushort valueBits)
|
public static float FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -497,11 +489,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat16_64
|
static class SoftFloat16_64
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPConvert(ushort valueBits)
|
public static double FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -677,11 +665,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat32_16
|
static class SoftFloat32_16
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ushort FPConvert(float value)
|
public static ushort FPConvert(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -801,21 +785,13 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat32
|
static class SoftFloat32
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPAdd(float value1, float value2)
|
public static float FPAdd(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, false);
|
return FPAddFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -872,11 +848,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static int FPCompare(float value1, float value2, byte signalNaNs)
|
public static int FPCompare(float value1, float value2, byte signalNaNs)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -915,11 +887,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareEQ(float value1, float value2)
|
public static float FPCompareEQ(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, false);
|
return FPCompareEQFpscrImpl(value1, value2, false);
|
||||||
|
|
@ -952,31 +920,19 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareGE(float value1, float value2)
|
public static float FPCompareGE(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, false);
|
return FPCompareGEFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1006,21 +962,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareGT(float value1, float value2)
|
public static float FPCompareGT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, false);
|
return FPCompareGTFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1050,51 +998,31 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareLE(float value1, float value2)
|
public static float FPCompareLE(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, false);
|
return FPCompareGEFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareLT(float value1, float value2)
|
public static float FPCompareLT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, false);
|
return FPCompareGTFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPDiv(float value1, float value2)
|
public static float FPDiv(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -1147,21 +1075,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMax(float value1, float value2)
|
public static float FPMax(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, false);
|
return FPMaxFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1228,11 +1148,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMaxNum(float value1, float value2)
|
public static float FPMaxNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, false);
|
return FPMaxNumFpscrImpl(value1, value2, false);
|
||||||
|
|
@ -1258,31 +1174,19 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMin(float value1, float value2)
|
public static float FPMin(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, false);
|
return FPMinFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1349,21 +1253,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMinNum(float value1, float value2)
|
public static float FPMinNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, false);
|
return FPMinNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1389,21 +1285,13 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMul(float value1, float value2)
|
public static float FPMul(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, false);
|
return FPMulFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
|
public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1456,21 +1344,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulAdd(float valueA, float value1, float value2)
|
public static float FPMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -1542,11 +1422,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulSub(float valueA, float value1, float value2)
|
public static float FPMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
@ -1554,11 +1430,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
@ -1566,11 +1438,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPMulX(float value1, float value2)
|
public static float FPMulX(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -1616,11 +1484,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
@ -1629,11 +1493,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPNegMulSub(float valueA, float value1, float value2)
|
public static float FPNegMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
@ -1641,21 +1501,13 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRecipEstimate(float value)
|
public static float FPRecipEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, false);
|
return FPRecipEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
|
public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
|
@ -1748,11 +1600,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRecipStep(float value1, float value2)
|
public static float FPRecipStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -1787,11 +1635,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRecipStepFused(float value1, float value2)
|
public static float FPRecipStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -1835,11 +1679,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRecpX(float value)
|
public static float FPRecpX(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -1865,21 +1705,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRSqrtEstimate(float value)
|
public static float FPRSqrtEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, false);
|
return FPRSqrtEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
|
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
|
@ -1999,11 +1831,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRSqrtStep(float value1, float value2)
|
public static float FPRSqrtStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2038,11 +1866,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPRSqrtStepFused(float value1, float value2)
|
public static float FPRSqrtStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2086,11 +1910,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPSqrt(float value)
|
public static float FPSqrt(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2133,11 +1953,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static float FPSub(float value1, float value2)
|
public static float FPSub(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscrImpl(value1, value2, false);
|
return FPSubFpscrImpl(value1, value2, false);
|
||||||
|
|
@ -2384,11 +2200,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat64_16
|
static class SoftFloat64_16
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static ushort FPConvert(double value)
|
public static ushort FPConvert(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2508,21 +2320,13 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
static class SoftFloat64
|
static class SoftFloat64
|
||||||
{
|
{
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPAdd(double value1, double value2)
|
public static double FPAdd(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, false);
|
return FPAddFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2579,11 +2383,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static int FPCompare(double value1, double value2, byte signalNaNs)
|
public static int FPCompare(double value1, double value2, byte signalNaNs)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2622,21 +2422,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareEQ(double value1, double value2)
|
public static double FPCompareEQ(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, false);
|
return FPCompareEQFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2669,21 +2461,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareGE(double value1, double value2)
|
public static double FPCompareGE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, false);
|
return FPCompareGEFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2713,21 +2497,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareGT(double value1, double value2)
|
public static double FPCompareGT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, false);
|
return FPCompareGTFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2757,51 +2533,31 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareLE(double value1, double value2)
|
public static double FPCompareLE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, false);
|
return FPCompareGEFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareLT(double value1, double value2)
|
public static double FPCompareLT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, false);
|
return FPCompareGTFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
|
return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPDiv(double value1, double value2)
|
public static double FPDiv(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -2854,21 +2610,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMax(double value1, double value2)
|
public static double FPMax(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, false);
|
return FPMaxFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2935,21 +2683,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMaxNum(double value1, double value2)
|
public static double FPMaxNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, false);
|
return FPMaxNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -2975,21 +2715,13 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMin(double value1, double value2)
|
public static double FPMin(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, false);
|
return FPMinFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -3056,21 +2788,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMinNum(double value1, double value2)
|
public static double FPMinNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, false);
|
return FPMinNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -3096,21 +2820,13 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMul(double value1, double value2)
|
public static double FPMul(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, false);
|
return FPMulFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
|
public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -3163,21 +2879,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulAdd(double valueA, double value1, double value2)
|
public static double FPMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
|
|
@ -3249,11 +2957,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulSub(double valueA, double value1, double value2)
|
public static double FPMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
@ -3261,11 +2965,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
@ -3273,11 +2973,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPMulX(double value1, double value2)
|
public static double FPMulX(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3323,11 +3019,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
@ -3336,11 +3028,7 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPNegMulSub(double valueA, double value1, double value2)
|
public static double FPNegMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
@ -3348,21 +3036,13 @@ namespace ARMeilleure.Instructions
|
||||||
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRecipEstimate(double value)
|
public static double FPRecipEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, false);
|
return FPRecipEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
|
public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
|
@ -3455,11 +3135,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRecipStep(double value1, double value2)
|
public static double FPRecipStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3494,11 +3170,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRecipStepFused(double value1, double value2)
|
public static double FPRecipStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3542,11 +3214,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRecpX(double value)
|
public static double FPRecpX(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3572,21 +3240,13 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRSqrtEstimate(double value)
|
public static double FPRSqrtEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, false);
|
return FPRSqrtEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
|
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
|
@ -3706,11 +3366,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRSqrtStep(double value1, double value2)
|
public static double FPRSqrtStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3745,11 +3401,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPRSqrtStepFused(double value1, double value2)
|
public static double FPRSqrtStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3793,11 +3445,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPSqrt(double value)
|
public static double FPSqrt(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
|
|
@ -3840,11 +3488,7 @@ namespace ARMeilleure.Instructions
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ANDROID
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#else
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
#endif
|
|
||||||
public static double FPSub(double value1, double value2)
|
public static double FPSub(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscr(value1, value2, false);
|
return FPSubFpscr(value1, value2, false);
|
||||||
|
|
|
||||||
|
|
@ -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,37 +53,12 @@ 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)
|
||||||
{
|
{
|
||||||
return $"{info.DeclaringType?.Name}.{info.Name}";
|
return $"{info.DeclaringType.Name}.{info.Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly SortedList<string, DelegateInfo> _delegates;
|
private static readonly SortedList<string, DelegateInfo> _delegates;
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Ryujinx.Common
|
|
||||||
{
|
|
||||||
public static class PlatformInfo
|
|
||||||
{
|
|
||||||
public static bool IsBionic { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
|
|
@ -27,6 +26,6 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannelOwner);
|
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannelOwner);
|
||||||
|
|
||||||
public static string Version => (IsValid || !RuntimeFeature.IsDynamicCodeCompiled) ? (PlatformInfo.IsBionic ? "Bionic_2.0.3" : BuildVersion) : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
public class AddressSpace : IDisposable
|
public class AddressSpace : IDisposable
|
||||||
{
|
{
|
||||||
private const MemoryAllocationFlags AsFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
|
||||||
|
|
||||||
private readonly MemoryBlock _backingMemory;
|
private readonly MemoryBlock _backingMemory;
|
||||||
|
|
||||||
public MemoryBlock Base { get; }
|
public MemoryBlock Base { get; }
|
||||||
|
|
@ -27,42 +25,28 @@ namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
addressSpace = null;
|
addressSpace = null;
|
||||||
|
|
||||||
MemoryBlock baseMemory = null;
|
const MemoryAllocationFlags AsFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
||||||
MemoryBlock mirrorMemory = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
baseMemory = new MemoryBlock(asSize, AsFlags);
|
|
||||||
mirrorMemory = new MemoryBlock(asSize, AsFlags);
|
|
||||||
addressSpace = new AddressSpace(backingMemory, baseMemory, mirrorMemory, asSize);
|
|
||||||
}
|
|
||||||
catch (SystemException)
|
|
||||||
{
|
|
||||||
baseMemory?.Dispose();
|
|
||||||
mirrorMemory?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
return addressSpace != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryCreateWithoutMirror(ulong asSize, out MemoryBlock addressSpace)
|
|
||||||
{
|
|
||||||
addressSpace = null;
|
|
||||||
|
|
||||||
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
|
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
|
||||||
|
|
||||||
// Attempt to create the address space with expected size or try to reduce it until it succeed.
|
// Attempt to create the address space with expected size or try to reduce it until it succeed.
|
||||||
for (ulong addressSpaceSize = asSize; addressSpaceSize >= minAddressSpaceSize; addressSpaceSize -= 0x100000000UL)
|
for (ulong addressSpaceSize = asSize; addressSpaceSize >= minAddressSpaceSize; addressSpaceSize >>= 1)
|
||||||
{
|
{
|
||||||
|
MemoryBlock baseMemory = null;
|
||||||
|
MemoryBlock mirrorMemory = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MemoryBlock baseMemory = new MemoryBlock(addressSpaceSize, AsFlags);
|
baseMemory = new MemoryBlock(addressSpaceSize, AsFlags);
|
||||||
addressSpace = baseMemory;
|
mirrorMemory = new MemoryBlock(addressSpaceSize, AsFlags);
|
||||||
|
addressSpace = new AddressSpace(backingMemory, baseMemory, mirrorMemory, addressSpaceSize);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (SystemException)
|
catch (SystemException)
|
||||||
{
|
{
|
||||||
|
baseMemory?.Dispose();
|
||||||
|
mirrorMemory?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ namespace ARMeilleure.Common
|
||||||
public static AddressTable<TEntry> CreateForArm(bool for64Bits, MemoryManagerType type)
|
public static AddressTable<TEntry> CreateForArm(bool for64Bits, MemoryManagerType type)
|
||||||
{
|
{
|
||||||
// Assume software memory means that we don't want to use any signal handlers.
|
// Assume software memory means that we don't want to use any signal handlers.
|
||||||
bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable && PlatformInfo.IsBionic != true;
|
bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable;
|
||||||
|
|
||||||
return new AddressTable<TEntry>(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse);
|
return new AddressTable<TEntry>(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,330 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using Ryujinx.Memory.Range;
|
|
||||||
using Ryujinx.Memory.Tracking;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Jit
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a CPU memory manager which maps guest virtual memory directly onto a host virtual region.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class MemoryManagerHostNoMirror : VirtualMemoryManagerRefCountedBase, IMemoryManager, IVirtualMemoryManagerTracked, IWritableBlock
|
|
||||||
{
|
|
||||||
private readonly InvalidAccessHandler _invalidAccessHandler;
|
|
||||||
private readonly bool _unsafeMode;
|
|
||||||
|
|
||||||
private readonly MemoryBlock _addressSpace;
|
|
||||||
private readonly MemoryBlock _backingMemory;
|
|
||||||
private readonly PageTable<ulong> _pageTable;
|
|
||||||
|
|
||||||
public int AddressSpaceBits { get; }
|
|
||||||
protected override ulong AddressSpaceSize { get; }
|
|
||||||
|
|
||||||
private readonly MemoryEhMeilleure _memoryEh;
|
|
||||||
|
|
||||||
private readonly ManagedPageFlags _pages;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool UsesPrivateAllocations => false;
|
|
||||||
|
|
||||||
public IntPtr PageTablePointer => _addressSpace.Pointer;
|
|
||||||
|
|
||||||
public MemoryManagerType Type => _unsafeMode ? MemoryManagerType.HostMappedUnsafe : MemoryManagerType.HostMapped;
|
|
||||||
|
|
||||||
public MemoryTracking Tracking { get; }
|
|
||||||
|
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the host mapped memory manager.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="addressSpace">Address space instance to use</param>
|
|
||||||
/// <param name="unsafeMode">True if unmanaged access should not be masked (unsafe), false otherwise.</param>
|
|
||||||
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
|
||||||
public MemoryManagerHostNoMirror(
|
|
||||||
MemoryBlock addressSpace,
|
|
||||||
MemoryBlock backingMemory,
|
|
||||||
bool unsafeMode,
|
|
||||||
InvalidAccessHandler invalidAccessHandler)
|
|
||||||
{
|
|
||||||
_addressSpace = addressSpace;
|
|
||||||
_backingMemory = backingMemory;
|
|
||||||
_pageTable = new PageTable<ulong>();
|
|
||||||
_invalidAccessHandler = invalidAccessHandler;
|
|
||||||
_unsafeMode = unsafeMode;
|
|
||||||
AddressSpaceSize = addressSpace.Size;
|
|
||||||
|
|
||||||
ulong asSize = PageSize;
|
|
||||||
int asBits = PageBits;
|
|
||||||
|
|
||||||
while (asSize < addressSpace.Size)
|
|
||||||
{
|
|
||||||
asSize <<= 1;
|
|
||||||
asBits++;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressSpaceBits = asBits;
|
|
||||||
|
|
||||||
_pages = new ManagedPageFlags(asBits);
|
|
||||||
|
|
||||||
Tracking = new MemoryTracking(this, (int)MemoryBlock.GetPageSize(), invalidAccessHandler);
|
|
||||||
_memoryEh = new MemoryEhMeilleure(addressSpace, null, Tracking);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="va">Virtual address of the range</param>
|
|
||||||
/// <param name="size">Size of the range in bytes</param>
|
|
||||||
private void AssertMapped(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (!ValidateAddressAndSize(va, size) || !_pages.IsRangeMapped(va, size))
|
|
||||||
{
|
|
||||||
throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
_addressSpace.MapView(_backingMemory, pa, va, size);
|
|
||||||
_pages.AddMapping(va, size);
|
|
||||||
PtMap(va, pa, size);
|
|
||||||
|
|
||||||
Tracking.Map(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PtMap(ulong va, ulong pa, ulong size)
|
|
||||||
{
|
|
||||||
while (size != 0)
|
|
||||||
{
|
|
||||||
_pageTable.Map(va, pa);
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
pa += PageSize;
|
|
||||||
size -= PageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Unmap(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
UnmapEvent?.Invoke(va, size);
|
|
||||||
Tracking.Unmap(va, size);
|
|
||||||
|
|
||||||
_pages.RemoveMapping(va, size);
|
|
||||||
PtUnmap(va, size);
|
|
||||||
_addressSpace.UnmapView(_backingMemory, va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PtUnmap(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
while (size != 0)
|
|
||||||
{
|
|
||||||
_pageTable.Unmap(va);
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
size -= PageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Reprotect(ulong va, ulong size, MemoryPermission permission)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ref T GetRef<T>(ulong va) where T : unmanaged
|
|
||||||
{
|
|
||||||
if (!IsContiguous(va, Unsafe.SizeOf<T>()))
|
|
||||||
{
|
|
||||||
ThrowMemoryNotContiguous();
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
|
|
||||||
|
|
||||||
return ref _backingMemory.GetRef<T>(GetPhysicalAddressChecked(va));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public override bool IsMapped(ulong va)
|
|
||||||
{
|
|
||||||
return ValidateAddress(va) && _pages.IsMapped(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool IsRangeMapped(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
return _pages.IsRangeMapped(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerable<HostMemoryRange> GetHostRegions(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
|
||||||
if (guestRegions == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
IntPtr pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
|
||||||
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<MemoryRange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
|
||||||
ulong regionSize = PageSize;
|
|
||||||
|
|
||||||
for (int page = 0; page < pages - 1; page++)
|
|
||||||
{
|
|
||||||
if (!ValidateAddress(va + PageSize))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
|
||||||
{
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
|
||||||
regionStart = newPa;
|
|
||||||
regionSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
regionSize += PageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetPhysicalAddressChecked(ulong va)
|
|
||||||
{
|
|
||||||
if (!IsMapped(va))
|
|
||||||
{
|
|
||||||
ThrowInvalidMemoryRegionException($"Not mapped: va=0x{va:X16}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPhysicalAddressInternal(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetPhysicalAddressInternal(ulong va)
|
|
||||||
{
|
|
||||||
return _pageTable.Read(va) + (va & PageMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
/// <remarks>
|
|
||||||
/// This function also validates that the given range is both valid and mapped, and will throw if it is not.
|
|
||||||
/// </remarks>
|
|
||||||
public override void SignalMemoryTracking(ulong va, ulong size, bool write, bool precise = false, int? exemptId = null)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
if (precise)
|
|
||||||
{
|
|
||||||
Tracking.VirtualMemoryEvent(va, size, write, precise: true, exemptId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pages.SignalMemoryTracking(Tracking, va, size, write, exemptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection, bool guest)
|
|
||||||
{
|
|
||||||
if (guest)
|
|
||||||
{
|
|
||||||
_addressSpace.Reprotect(va, size, protection, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_pages.TrackingReprotect(va, size, protection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public RegionHandle BeginTracking(ulong address, ulong size, int id, RegionFlags flags)
|
|
||||||
{
|
|
||||||
return Tracking.BeginTracking(address, size, id, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public MultiRegionHandle BeginGranularTracking(ulong address, ulong size, IEnumerable<IRegionHandle> handles, ulong granularity, int id, RegionFlags flags)
|
|
||||||
{
|
|
||||||
return Tracking.BeginGranularTracking(address, size, handles, granularity, id, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public SmartMultiRegionHandle BeginSmartGranularTracking(ulong address, ulong size, ulong granularity, int id)
|
|
||||||
{
|
|
||||||
return Tracking.BeginSmartGranularTracking(address, size, granularity, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of resources used by the memory manager.
|
|
||||||
/// </summary>
|
|
||||||
protected override void Destroy()
|
|
||||||
{
|
|
||||||
_addressSpace.Dispose();
|
|
||||||
_memoryEh.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Memory<byte> GetPhysicalAddressMemory(nuint pa, int size)
|
|
||||||
=> _backingMemory.GetMemory(pa, size);
|
|
||||||
|
|
||||||
protected override Span<byte> GetPhysicalAddressSpan(nuint pa, int size)
|
|
||||||
=> _backingMemory.GetSpan(pa, size);
|
|
||||||
|
|
||||||
protected override nuint TranslateVirtualAddressChecked(ulong va)
|
|
||||||
=> (nuint)GetPhysicalAddressChecked(va);
|
|
||||||
|
|
||||||
protected override nuint TranslateVirtualAddressUnchecked(ulong va)
|
|
||||||
=> (nuint)GetPhysicalAddressInternal(va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -45,11 +45,6 @@ namespace Ryujinx.Cpu.LightningJit
|
||||||
_translator.InvalidateJitCacheRegion(address, size);
|
_translator.InvalidateJitCacheRegion(address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void PatchCodeForNce(ulong textAddress, ulong textSize, ulong patchRegionAddress, ulong patchRegionSize)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
|
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,24 +55,6 @@ namespace Ryujinx.Cpu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemoryEhMeilleure(ulong asSize, MemoryTracking tracking)
|
|
||||||
{
|
|
||||||
_tracking = tracking;
|
|
||||||
_baseAddress = 0UL;
|
|
||||||
ulong endAddress = asSize;
|
|
||||||
|
|
||||||
_trackingEvent = VirtualMemoryEvent;
|
|
||||||
|
|
||||||
_pageSize = MemoryBlock.GetPageSize();
|
|
||||||
|
|
||||||
bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
|
||||||
|
|
||||||
if (!added)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Number of allowed tracked regions exceeded.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong VirtualMemoryEvent(ulong address, ulong size, bool write)
|
private ulong VirtualMemoryEvent(ulong address, ulong size, bool write)
|
||||||
{
|
{
|
||||||
ulong pageSize = _pageSize;
|
ulong pageSize = _pageSize;
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum ArmCondition
|
|
||||||
{
|
|
||||||
Eq = 0,
|
|
||||||
Ne = 1,
|
|
||||||
GeUn = 2,
|
|
||||||
LtUn = 3,
|
|
||||||
Mi = 4,
|
|
||||||
Pl = 5,
|
|
||||||
Vs = 6,
|
|
||||||
Vc = 7,
|
|
||||||
GtUn = 8,
|
|
||||||
LeUn = 9,
|
|
||||||
Ge = 10,
|
|
||||||
Lt = 11,
|
|
||||||
Gt = 12,
|
|
||||||
Le = 13,
|
|
||||||
Al = 14,
|
|
||||||
Nv = 15,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum ArmExtensionType
|
|
||||||
{
|
|
||||||
Uxtb = 0,
|
|
||||||
Uxth = 1,
|
|
||||||
Uxtw = 2,
|
|
||||||
Uxtx = 3,
|
|
||||||
Sxtb = 4,
|
|
||||||
Sxth = 5,
|
|
||||||
Sxtw = 6,
|
|
||||||
Sxtx = 7,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum ArmShiftType
|
|
||||||
{
|
|
||||||
Lsl = 0,
|
|
||||||
Lsr = 1,
|
|
||||||
Asr = 2,
|
|
||||||
Ror = 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,66 +0,0 @@
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
static class CodeGenCommon
|
|
||||||
{
|
|
||||||
public static bool TryEncodeBitMask(Operand operand, out int immN, out int immS, out int immR)
|
|
||||||
{
|
|
||||||
return TryEncodeBitMask(operand.Type, operand.Value, out immN, out immS, out immR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryEncodeBitMask(OperandType type, ulong value, out int immN, out int immS, out int immR)
|
|
||||||
{
|
|
||||||
if (type == OperandType.I32)
|
|
||||||
{
|
|
||||||
value |= value << 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TryEncodeBitMask(value, out immN, out immS, out immR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryEncodeBitMask(ulong value, out int immN, out int immS, out int immR)
|
|
||||||
{
|
|
||||||
// Some special values also can't be encoded:
|
|
||||||
// 0 can't be encoded because we need to subtract 1 from onesCount (which would became negative if 0).
|
|
||||||
// A value with all bits set can't be encoded because it is reserved according to the spec, because:
|
|
||||||
// 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 XOR all ones will be equal its inverse, so one can just use MVN.
|
|
||||||
if (value == 0 || value == ulong.MaxValue)
|
|
||||||
{
|
|
||||||
immN = 0;
|
|
||||||
immS = 0;
|
|
||||||
immR = 0;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize value, rotating it such that the LSB is 1: Ensures we get a complete element that has not
|
|
||||||
// been cut-in-half across the word boundary.
|
|
||||||
int rotation = BitOperations.TrailingZeroCount(value & (value + 1));
|
|
||||||
ulong rotatedValue = ulong.RotateRight(value, rotation);
|
|
||||||
|
|
||||||
// Now that we have a complete element in the LSB with the LSB = 1, determine size and number of ones
|
|
||||||
// in element.
|
|
||||||
int elementSize = BitOperations.TrailingZeroCount(rotatedValue & (rotatedValue + 1));
|
|
||||||
int onesInElement = BitOperations.TrailingZeroCount(~rotatedValue);
|
|
||||||
|
|
||||||
// Check the value is repeating; also ensures element size is a power of two.
|
|
||||||
if (ulong.RotateRight(value, elementSize) != value)
|
|
||||||
{
|
|
||||||
immN = 0;
|
|
||||||
immS = 0;
|
|
||||||
immR = 0;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
immN = (elementSize >> 6) & 1;
|
|
||||||
immS = (((~elementSize + 1) << 1) | (onesInElement - 1)) & 0x3f;
|
|
||||||
immR = (elementSize - rotation) & (elementSize - 1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
struct Operand
|
|
||||||
{
|
|
||||||
public readonly OperandKind Kind { get; }
|
|
||||||
public readonly OperandType Type { get; }
|
|
||||||
public readonly ulong Value { get; }
|
|
||||||
|
|
||||||
public Operand(OperandKind kind, OperandType type, ulong value)
|
|
||||||
{
|
|
||||||
Kind = kind;
|
|
||||||
Type = type;
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(int index, RegisterType regType, OperandType type) : this(OperandKind.Register, type, (ulong)((int)regType << 24 | index))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(OperandType type, ulong value) : this(OperandKind.Constant, type, value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly Register GetRegister()
|
|
||||||
{
|
|
||||||
Debug.Assert(Kind == OperandKind.Register);
|
|
||||||
|
|
||||||
return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly int AsInt32()
|
|
||||||
{
|
|
||||||
return (int)Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum OperandKind
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Constant,
|
|
||||||
Label,
|
|
||||||
Register,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum OperandType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
I32,
|
|
||||||
I64,
|
|
||||||
FP32,
|
|
||||||
FP64,
|
|
||||||
V128,
|
|
||||||
}
|
|
||||||
|
|
||||||
static class OperandTypeExtensions
|
|
||||||
{
|
|
||||||
public static bool IsInteger(this OperandType type)
|
|
||||||
{
|
|
||||||
return type == OperandType.I32 ||
|
|
||||||
type == OperandType.I64;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetSizeInBytes(this OperandType type)
|
|
||||||
{
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
OperandType.FP32 => 4,
|
|
||||||
OperandType.FP64 => 8,
|
|
||||||
OperandType.I32 => 4,
|
|
||||||
OperandType.I64 => 8,
|
|
||||||
OperandType.V128 => 16,
|
|
||||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
readonly struct Register : IEquatable<Register>
|
|
||||||
{
|
|
||||||
public int Index { get; }
|
|
||||||
|
|
||||||
public RegisterType Type { get; }
|
|
||||||
|
|
||||||
public Register(int index, RegisterType type)
|
|
||||||
{
|
|
||||||
Index = index;
|
|
||||||
Type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return (ushort)Index | ((int)Type << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(Register x, Register y)
|
|
||||||
{
|
|
||||||
return x.Equals(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(Register x, Register y)
|
|
||||||
{
|
|
||||||
return !x.Equals(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
return obj is Register reg && Equals(reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(Register other)
|
|
||||||
{
|
|
||||||
return other.Index == Index &&
|
|
||||||
other.Type == Type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,220 +0,0 @@
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
readonly struct RegisterSaveRestore
|
|
||||||
{
|
|
||||||
private const int FpRegister = 29;
|
|
||||||
private const int LrRegister = 30;
|
|
||||||
|
|
||||||
private const int Encodable9BitsOffsetLimit = 0x200;
|
|
||||||
|
|
||||||
private readonly int _intMask;
|
|
||||||
private readonly int _vecMask;
|
|
||||||
private readonly OperandType _vecType;
|
|
||||||
private readonly bool _hasCall;
|
|
||||||
|
|
||||||
public RegisterSaveRestore(int intMask, int vecMask = 0, OperandType vecType = OperandType.FP64, bool hasCall = false)
|
|
||||||
{
|
|
||||||
_intMask = intMask;
|
|
||||||
_vecMask = vecMask;
|
|
||||||
_vecType = vecType;
|
|
||||||
_hasCall = hasCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WritePrologue(Assembler asm)
|
|
||||||
{
|
|
||||||
int intMask = _intMask;
|
|
||||||
int vecMask = _vecMask;
|
|
||||||
|
|
||||||
int intCalleeSavedRegsCount = BitOperations.PopCount((uint)intMask);
|
|
||||||
int vecCalleeSavedRegsCount = BitOperations.PopCount((uint)vecMask);
|
|
||||||
|
|
||||||
int calleeSaveRegionSize = Align16(intCalleeSavedRegsCount * 8 + vecCalleeSavedRegsCount * _vecType.GetSizeInBytes());
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
WritePrologueCalleeSavesPreIndexed(asm, ref intMask, ref offset, calleeSaveRegionSize, OperandType.I64);
|
|
||||||
|
|
||||||
if (_vecType == OperandType.V128 && (intCalleeSavedRegsCount & 1) != 0)
|
|
||||||
{
|
|
||||||
offset += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritePrologueCalleeSavesPreIndexed(asm, ref vecMask, ref offset, calleeSaveRegionSize, _vecType);
|
|
||||||
|
|
||||||
if (_hasCall)
|
|
||||||
{
|
|
||||||
Operand rsp = Register(Assembler.SpRegister);
|
|
||||||
|
|
||||||
asm.StpRiPre(Register(FpRegister), Register(LrRegister), rsp, -16);
|
|
||||||
asm.MovSp(Register(FpRegister), rsp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WritePrologueCalleeSavesPreIndexed(
|
|
||||||
Assembler asm,
|
|
||||||
ref int mask,
|
|
||||||
ref int offset,
|
|
||||||
int calleeSaveRegionSize,
|
|
||||||
OperandType type)
|
|
||||||
{
|
|
||||||
if ((BitOperations.PopCount((uint)mask) & 1) != 0)
|
|
||||||
{
|
|
||||||
int reg = BitOperations.TrailingZeroCount(mask);
|
|
||||||
|
|
||||||
mask &= ~(1 << reg);
|
|
||||||
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
asm.StrRiUn(Register(reg, type), Register(Assembler.SpRegister), offset);
|
|
||||||
}
|
|
||||||
else if (calleeSaveRegionSize < Encodable9BitsOffsetLimit)
|
|
||||||
{
|
|
||||||
asm.StrRiPre(Register(reg, type), Register(Assembler.SpRegister), -calleeSaveRegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.Sub(Register(Assembler.SpRegister), Register(Assembler.SpRegister), new Operand(OperandType.I64, (ulong)calleeSaveRegionSize));
|
|
||||||
asm.StrRiUn(Register(reg, type), Register(Assembler.SpRegister), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += type.GetSizeInBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (mask != 0)
|
|
||||||
{
|
|
||||||
int reg = BitOperations.TrailingZeroCount(mask);
|
|
||||||
|
|
||||||
mask &= ~(1 << reg);
|
|
||||||
|
|
||||||
int reg2 = BitOperations.TrailingZeroCount(mask);
|
|
||||||
|
|
||||||
mask &= ~(1 << reg2);
|
|
||||||
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
asm.StpRiUn(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), offset);
|
|
||||||
}
|
|
||||||
else if (calleeSaveRegionSize < Encodable9BitsOffsetLimit)
|
|
||||||
{
|
|
||||||
asm.StpRiPre(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), -calleeSaveRegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.Sub(Register(Assembler.SpRegister), Register(Assembler.SpRegister), new Operand(OperandType.I64, (ulong)calleeSaveRegionSize));
|
|
||||||
asm.StpRiUn(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += type.GetSizeInBytes() * 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteEpilogue(Assembler asm)
|
|
||||||
{
|
|
||||||
int intMask = _intMask;
|
|
||||||
int vecMask = _vecMask;
|
|
||||||
|
|
||||||
int intCalleeSavedRegsCount = BitOperations.PopCount((uint)intMask);
|
|
||||||
int vecCalleeSavedRegsCount = BitOperations.PopCount((uint)vecMask);
|
|
||||||
|
|
||||||
bool misalignedVector = _vecType == OperandType.V128 && (intCalleeSavedRegsCount & 1) != 0;
|
|
||||||
|
|
||||||
int offset = intCalleeSavedRegsCount * 8 + vecCalleeSavedRegsCount * _vecType.GetSizeInBytes();
|
|
||||||
|
|
||||||
if (misalignedVector)
|
|
||||||
{
|
|
||||||
offset += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
int calleeSaveRegionSize = Align16(offset);
|
|
||||||
|
|
||||||
if (_hasCall)
|
|
||||||
{
|
|
||||||
Operand rsp = Register(Assembler.SpRegister);
|
|
||||||
|
|
||||||
asm.LdpRiPost(Register(FpRegister), Register(LrRegister), rsp, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteEpilogueCalleeSavesPostIndexed(asm, ref vecMask, ref offset, calleeSaveRegionSize, _vecType);
|
|
||||||
|
|
||||||
if (misalignedVector)
|
|
||||||
{
|
|
||||||
offset -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteEpilogueCalleeSavesPostIndexed(asm, ref intMask, ref offset, calleeSaveRegionSize, OperandType.I64);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteEpilogueCalleeSavesPostIndexed(
|
|
||||||
Assembler asm,
|
|
||||||
ref int mask,
|
|
||||||
ref int offset,
|
|
||||||
int calleeSaveRegionSize,
|
|
||||||
OperandType type)
|
|
||||||
{
|
|
||||||
while (mask != 0)
|
|
||||||
{
|
|
||||||
int reg = HighestBitSet(mask);
|
|
||||||
|
|
||||||
mask &= ~(1 << reg);
|
|
||||||
|
|
||||||
if (mask != 0)
|
|
||||||
{
|
|
||||||
int reg2 = HighestBitSet(mask);
|
|
||||||
|
|
||||||
mask &= ~(1 << reg2);
|
|
||||||
|
|
||||||
offset -= type.GetSizeInBytes() * 2;
|
|
||||||
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
asm.LdpRiUn(Register(reg2, type), Register(reg, type), Register(Assembler.SpRegister), offset);
|
|
||||||
}
|
|
||||||
else if (calleeSaveRegionSize < Encodable9BitsOffsetLimit)
|
|
||||||
{
|
|
||||||
asm.LdpRiPost(Register(reg2, type), Register(reg, type), Register(Assembler.SpRegister), calleeSaveRegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.LdpRiUn(Register(reg2, type), Register(reg, type), Register(Assembler.SpRegister), 0);
|
|
||||||
asm.Add(Register(Assembler.SpRegister), Register(Assembler.SpRegister), new Operand(OperandType.I64, (ulong)calleeSaveRegionSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offset -= type.GetSizeInBytes();
|
|
||||||
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
asm.LdrRiUn(Register(reg, type), Register(Assembler.SpRegister), offset);
|
|
||||||
}
|
|
||||||
else if (calleeSaveRegionSize < Encodable9BitsOffsetLimit)
|
|
||||||
{
|
|
||||||
asm.LdrRiPost(Register(reg, type), Register(Assembler.SpRegister), calleeSaveRegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.LdrRiUn(Register(reg, type), Register(Assembler.SpRegister), 0);
|
|
||||||
asm.Add(Register(Assembler.SpRegister), Register(Assembler.SpRegister), new Operand(OperandType.I64, (ulong)calleeSaveRegionSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int HighestBitSet(int value)
|
|
||||||
{
|
|
||||||
return 31 - BitOperations.LeadingZeroCount((uint)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Operand Register(int register, OperandType type = OperandType.I64)
|
|
||||||
{
|
|
||||||
return new Operand(register, RegisterType.Integer, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int Align16(int value)
|
|
||||||
{
|
|
||||||
return (value + 0xf) & ~0xf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
namespace Ryujinx.Cpu.Nce.Arm64
|
|
||||||
{
|
|
||||||
enum RegisterType
|
|
||||||
{
|
|
||||||
Integer,
|
|
||||||
Vector,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,328 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using Ryujinx.Memory.Range;
|
|
||||||
using Ryujinx.Memory.Tracking;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a CPU memory manager which maps guest virtual memory directly onto a host virtual region.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class MemoryManagerNative : VirtualMemoryManagerRefCountedBase, IMemoryManager, IVirtualMemoryManagerTracked, IWritableBlock
|
|
||||||
{
|
|
||||||
private readonly MemoryBlock _addressSpace;
|
|
||||||
|
|
||||||
private readonly MemoryBlock _backingMemory;
|
|
||||||
private readonly PageTable<ulong> _pageTable;
|
|
||||||
|
|
||||||
private readonly MemoryEhMeilleure _memoryEh;
|
|
||||||
|
|
||||||
private readonly ManagedPageFlags _pages;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool UsesPrivateAllocations => false;
|
|
||||||
|
|
||||||
public IntPtr PageTablePointer => IntPtr.Zero;
|
|
||||||
|
|
||||||
public ulong ReservedSize => (ulong)_addressSpace.Pointer.ToInt64();
|
|
||||||
|
|
||||||
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
|
|
||||||
|
|
||||||
public MemoryTracking Tracking { get; }
|
|
||||||
|
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
|
||||||
|
|
||||||
public int AddressSpaceBits { get; }
|
|
||||||
protected override ulong AddressSpaceSize { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the host mapped memory manager.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="addressSpace">Address space memory block</param>
|
|
||||||
/// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
|
|
||||||
/// <param name="addressSpaceSize">Size of the address space</param>
|
|
||||||
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
|
||||||
public MemoryManagerNative(
|
|
||||||
MemoryBlock addressSpace,
|
|
||||||
MemoryBlock backingMemory,
|
|
||||||
ulong addressSpaceSize,
|
|
||||||
InvalidAccessHandler invalidAccessHandler = null)
|
|
||||||
{
|
|
||||||
_backingMemory = backingMemory;
|
|
||||||
_pageTable = new PageTable<ulong>();
|
|
||||||
AddressSpaceSize = addressSpaceSize;
|
|
||||||
|
|
||||||
ulong asSize = PageSize;
|
|
||||||
int asBits = PageBits;
|
|
||||||
|
|
||||||
while (asSize < addressSpaceSize)
|
|
||||||
{
|
|
||||||
asSize <<= 1;
|
|
||||||
asBits++;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressSpaceBits = asBits;
|
|
||||||
|
|
||||||
_pages = new ManagedPageFlags(asBits);
|
|
||||||
|
|
||||||
_addressSpace = addressSpace;
|
|
||||||
|
|
||||||
Tracking = new MemoryTracking(this, PageSize, invalidAccessHandler);
|
|
||||||
_memoryEh = new MemoryEhMeilleure(addressSpaceSize, Tracking);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
_addressSpace.MapView(_backingMemory, pa, AddressToOffset(va), size);
|
|
||||||
_pages.AddMapping(va, size);
|
|
||||||
PtMap(va, pa, size);
|
|
||||||
|
|
||||||
Tracking.Map(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PtMap(ulong va, ulong pa, ulong size)
|
|
||||||
{
|
|
||||||
while (size != 0)
|
|
||||||
{
|
|
||||||
_pageTable.Map(va, pa);
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
pa += PageSize;
|
|
||||||
size -= PageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Unmap(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
UnmapEvent?.Invoke(va, size);
|
|
||||||
Tracking.Unmap(va, size);
|
|
||||||
|
|
||||||
_pages.RemoveMapping(va, size);
|
|
||||||
PtUnmap(va, size);
|
|
||||||
_addressSpace.UnmapView(_backingMemory, AddressToOffset(va), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PtUnmap(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
while (size != 0)
|
|
||||||
{
|
|
||||||
_pageTable.Unmap(va);
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
size -= PageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Reprotect(ulong va, ulong size, MemoryPermission protection)
|
|
||||||
{
|
|
||||||
_addressSpace.Reprotect(AddressToOffset(va), size, protection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ref T GetRef<T>(ulong va) where T : unmanaged
|
|
||||||
{
|
|
||||||
if (!IsContiguous(va, Unsafe.SizeOf<T>()))
|
|
||||||
{
|
|
||||||
ThrowMemoryNotContiguous();
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
|
|
||||||
|
|
||||||
return ref _backingMemory.GetRef<T>(GetPhysicalAddressChecked(va));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public override bool IsMapped(ulong va)
|
|
||||||
{
|
|
||||||
return ValidateAddress(va) && _pages.IsMapped(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool IsRangeMapped(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
return _pages.IsRangeMapped(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerable<HostMemoryRange> GetHostRegions(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
|
||||||
if (guestRegions == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
IntPtr pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
|
||||||
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<MemoryRange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
|
||||||
{
|
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
|
||||||
ulong regionSize = PageSize;
|
|
||||||
|
|
||||||
for (int page = 0; page < pages - 1; page++)
|
|
||||||
{
|
|
||||||
if (!ValidateAddress(va + PageSize))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
|
||||||
{
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
|
||||||
regionStart = newPa;
|
|
||||||
regionSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
va += PageSize;
|
|
||||||
regionSize += PageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetPhysicalAddressChecked(ulong va)
|
|
||||||
{
|
|
||||||
if (!IsMapped(va))
|
|
||||||
{
|
|
||||||
ThrowInvalidMemoryRegionException($"Not mapped: va=0x{va:X16}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPhysicalAddressInternal(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetPhysicalAddressInternal(ulong va)
|
|
||||||
{
|
|
||||||
return _pageTable.Read(va) + (va & PageMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
/// <remarks>
|
|
||||||
/// This function also validates that the given range is both valid and mapped, and will throw if it is not.
|
|
||||||
/// </remarks>
|
|
||||||
public override void SignalMemoryTracking(ulong va, ulong size, bool write, bool precise = false, int? exemptId = null)
|
|
||||||
{
|
|
||||||
AssertValidAddressAndSize(va, size);
|
|
||||||
|
|
||||||
if (precise)
|
|
||||||
{
|
|
||||||
Tracking.VirtualMemoryEvent(va, size, write, precise: true, exemptId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pages.SignalMemoryTracking(Tracking, va, size, write, exemptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection, bool guest)
|
|
||||||
{
|
|
||||||
if (guest)
|
|
||||||
{
|
|
||||||
_addressSpace.Reprotect(AddressToOffset(va), size, protection, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_pages.TrackingReprotect(va, size, protection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public RegionHandle BeginTracking(ulong address, ulong size, int id, RegionFlags flags)
|
|
||||||
{
|
|
||||||
return Tracking.BeginTracking(address, size, id, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public MultiRegionHandle BeginGranularTracking(ulong address, ulong size, IEnumerable<IRegionHandle> handles, ulong granularity, int id, RegionFlags flags)
|
|
||||||
{
|
|
||||||
return Tracking.BeginGranularTracking(address, size, handles, granularity, id, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public SmartMultiRegionHandle BeginSmartGranularTracking(ulong address, ulong size, ulong granularity, int id)
|
|
||||||
{
|
|
||||||
return Tracking.BeginSmartGranularTracking(address, size, granularity, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong AddressToOffset(ulong address)
|
|
||||||
{
|
|
||||||
if (address < ReservedSize)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid address 0x{address:x16}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return address - ReservedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of resources used by the memory manager.
|
|
||||||
/// </summary>
|
|
||||||
protected override void Destroy()
|
|
||||||
{
|
|
||||||
_addressSpace.Dispose();
|
|
||||||
_memoryEh.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Memory<byte> GetPhysicalAddressMemory(nuint pa, int size)
|
|
||||||
=> _backingMemory.GetMemory(pa, size);
|
|
||||||
|
|
||||||
protected override Span<byte> GetPhysicalAddressSpan(nuint pa, int size)
|
|
||||||
=> _backingMemory.GetSpan(pa, size);
|
|
||||||
|
|
||||||
protected override nuint TranslateVirtualAddressChecked(ulong va)
|
|
||||||
=> (nuint)GetPhysicalAddressChecked(va);
|
|
||||||
|
|
||||||
protected override nuint TranslateVirtualAddressUnchecked(ulong va)
|
|
||||||
=> (nuint)GetPhysicalAddressInternal(va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Native Code Execution CPU code patch.
|
|
||||||
/// </summary>
|
|
||||||
public class NceCpuCodePatch
|
|
||||||
{
|
|
||||||
private readonly List<uint> _code;
|
|
||||||
|
|
||||||
private readonly struct PatchTarget
|
|
||||||
{
|
|
||||||
public readonly int TextIndex;
|
|
||||||
public readonly int PatchStartIndex;
|
|
||||||
public readonly int PatchBranchIndex;
|
|
||||||
|
|
||||||
public PatchTarget(int textIndex, int patchStartIndex, int patchBranchIndex)
|
|
||||||
{
|
|
||||||
TextIndex = textIndex;
|
|
||||||
PatchStartIndex = patchStartIndex;
|
|
||||||
PatchBranchIndex = patchBranchIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<PatchTarget> _patchTargets;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public ulong Size => BitUtils.AlignUp((ulong)_code.Count * sizeof(uint), 0x1000UL);
|
|
||||||
|
|
||||||
public NceCpuCodePatch()
|
|
||||||
{
|
|
||||||
_code = new();
|
|
||||||
_patchTargets = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddCode(int textIndex, IEnumerable<uint> code)
|
|
||||||
{
|
|
||||||
int patchStartIndex = _code.Count;
|
|
||||||
_code.AddRange(code);
|
|
||||||
_patchTargets.Add(new PatchTarget(textIndex, patchStartIndex, _code.Count - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Write(IVirtualMemoryManager memoryManager, ulong patchAddress, ulong textAddress)
|
|
||||||
{
|
|
||||||
uint[] code = _code.ToArray();
|
|
||||||
|
|
||||||
foreach (var patchTarget in _patchTargets)
|
|
||||||
{
|
|
||||||
ulong instPatchStartAddress = patchAddress + (ulong)patchTarget.PatchStartIndex * sizeof(uint);
|
|
||||||
ulong instPatchBranchAddress = patchAddress + (ulong)patchTarget.PatchBranchIndex * sizeof(uint);
|
|
||||||
ulong instTextAddress = textAddress + (ulong)patchTarget.TextIndex * sizeof(uint);
|
|
||||||
|
|
||||||
uint prevInst = memoryManager.Read<uint>(instTextAddress);
|
|
||||||
|
|
||||||
code[patchTarget.PatchBranchIndex] |= EncodeSImm26_2(checked((int)((long)instTextAddress - (long)instPatchBranchAddress + sizeof(uint))));
|
|
||||||
memoryManager.Write(instTextAddress, 0x14000000u | EncodeSImm26_2(checked((int)((long)instPatchStartAddress - (long)instTextAddress))));
|
|
||||||
|
|
||||||
uint newInst = memoryManager.Read<uint>(instTextAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Size != 0)
|
|
||||||
{
|
|
||||||
memoryManager.Write(patchAddress, MemoryMarshal.Cast<uint, byte>(code));
|
|
||||||
memoryManager.Reprotect(patchAddress, Size, MemoryPermission.ReadAndExecute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint EncodeSImm26_2(int value)
|
|
||||||
{
|
|
||||||
uint imm = (uint)(value >> 2) & 0x3ffffff;
|
|
||||||
Debug.Assert(((int)imm << 6) >> 4 == value, $"Failed to encode constant 0x{value:X}.");
|
|
||||||
return imm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
using Ryujinx.Cpu.Signal;
|
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
class NceCpuContext : ICpuContext
|
|
||||||
{
|
|
||||||
private static uint[] _getTpidrEl0Code = new uint[]
|
|
||||||
{
|
|
||||||
GetMrsTpidrEl0(0), // mrs x0, tpidr_el0
|
|
||||||
0xd65f03c0u, // ret
|
|
||||||
};
|
|
||||||
|
|
||||||
private static uint GetMrsTpidrEl0(uint rd)
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
return 0xd53bd060u | rd; // TPIDRRO
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0xd53bd040u | rd; // TPIDR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly struct CodeWriter
|
|
||||||
{
|
|
||||||
private readonly List<uint> _fullCode;
|
|
||||||
|
|
||||||
public CodeWriter()
|
|
||||||
{
|
|
||||||
_fullCode = new List<uint>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong Write(uint[] code)
|
|
||||||
{
|
|
||||||
ulong offset = (ulong)_fullCode.Count * sizeof(uint);
|
|
||||||
_fullCode.AddRange(code);
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemoryBlock CreateMemoryBlock()
|
|
||||||
{
|
|
||||||
ReadOnlySpan<byte> codeBytes = MemoryMarshal.Cast<uint, byte>(_fullCode.ToArray());
|
|
||||||
|
|
||||||
MemoryBlock codeBlock = new(BitUtils.AlignUp((ulong)codeBytes.Length, 0x1000UL));
|
|
||||||
|
|
||||||
codeBlock.Write(0, codeBytes);
|
|
||||||
codeBlock.Reprotect(0, (ulong)codeBytes.Length, MemoryPermission.ReadAndExecute, true);
|
|
||||||
|
|
||||||
return codeBlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private delegate void ThreadStart(IntPtr nativeContextPtr);
|
|
||||||
private delegate IntPtr GetTpidrEl0();
|
|
||||||
private static MemoryBlock _codeBlock;
|
|
||||||
private static ThreadStart _threadStart;
|
|
||||||
private static GetTpidrEl0 _getTpidrEl0;
|
|
||||||
|
|
||||||
private readonly ITickSource _tickSource;
|
|
||||||
private readonly IMemoryManager _memoryManager;
|
|
||||||
|
|
||||||
static NceCpuContext()
|
|
||||||
{
|
|
||||||
CodeWriter codeWriter = new();
|
|
||||||
|
|
||||||
uint[] threadStartCode = NcePatcher.GenerateThreadStartCode();
|
|
||||||
uint[] ehSuspendCode = NcePatcher.GenerateSuspendExceptionHandler();
|
|
||||||
|
|
||||||
ulong threadStartCodeOffset = codeWriter.Write(threadStartCode);
|
|
||||||
ulong getTpidrEl0CodeOffset = codeWriter.Write(_getTpidrEl0Code);
|
|
||||||
ulong ehSuspendCodeOffset = codeWriter.Write(ehSuspendCode);
|
|
||||||
|
|
||||||
MemoryBlock codeBlock = null;
|
|
||||||
|
|
||||||
NativeSignalHandler.InitializeSignalHandler((IntPtr oldSignalHandlerSegfaultPtr, IntPtr signalHandlerPtr) =>
|
|
||||||
{
|
|
||||||
uint[] ehWrapperCode = NcePatcher.GenerateWrapperExceptionHandler(oldSignalHandlerSegfaultPtr, signalHandlerPtr);
|
|
||||||
ulong ehWrapperCodeOffset = codeWriter.Write(ehWrapperCode);
|
|
||||||
codeBlock = codeWriter.CreateMemoryBlock();
|
|
||||||
return codeBlock.GetPointer(ehWrapperCodeOffset, (ulong)ehWrapperCode.Length * sizeof(uint));
|
|
||||||
});
|
|
||||||
|
|
||||||
NativeSignalHandler.InstallUnixSignalHandler(NceThreadPal.UnixSuspendSignal, codeBlock.GetPointer(ehSuspendCodeOffset, (ulong)ehSuspendCode.Length * sizeof(uint)));
|
|
||||||
|
|
||||||
_threadStart = Marshal.GetDelegateForFunctionPointer<ThreadStart>(codeBlock.GetPointer(threadStartCodeOffset, (ulong)threadStartCode.Length * sizeof(uint)));
|
|
||||||
_getTpidrEl0 = Marshal.GetDelegateForFunctionPointer<GetTpidrEl0>(codeBlock.GetPointer(getTpidrEl0CodeOffset, (ulong)_getTpidrEl0Code.Length * sizeof(uint)));
|
|
||||||
_codeBlock = codeBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NceCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit)
|
|
||||||
{
|
|
||||||
_tickSource = tickSource;
|
|
||||||
_memoryManager = memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
|
||||||
{
|
|
||||||
return new NceExecutionContext(exceptionCallbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Execute(IExecutionContext context, ulong address)
|
|
||||||
{
|
|
||||||
NceExecutionContext nec = (NceExecutionContext)context;
|
|
||||||
NceNativeInterface.RegisterThread(nec, _tickSource);
|
|
||||||
int tableIndex = NceThreadTable.Register(_getTpidrEl0(), nec.NativeContextPtr);
|
|
||||||
|
|
||||||
nec.SetStartAddress(address);
|
|
||||||
_threadStart(nec.NativeContextPtr);
|
|
||||||
nec.Exit();
|
|
||||||
|
|
||||||
NceThreadTable.Unregister(tableIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void InvalidateCacheRegion(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
|
|
||||||
{
|
|
||||||
return new DummyDiskCacheLoadState();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void PrepareCodeRange(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
public class NceEngine : ICpuEngine
|
|
||||||
{
|
|
||||||
public ITickSource TickSource{ get; }
|
|
||||||
|
|
||||||
public NceEngine(ITickSource tickSource)
|
|
||||||
{
|
|
||||||
TickSource = tickSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICpuContext CreateCpuContext(IMemoryManager memoryManager, bool for64Bit)
|
|
||||||
{
|
|
||||||
return new NceCpuContext(TickSource, memoryManager, for64Bit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
using ARMeilleure.State;
|
|
||||||
using Ryujinx.Cpu.Signal;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
class NceExecutionContext : IExecutionContext
|
|
||||||
{
|
|
||||||
private const ulong AlternateStackSize = 0x4000;
|
|
||||||
|
|
||||||
private readonly NceNativeContext _context;
|
|
||||||
private readonly ExceptionCallbacks _exceptionCallbacks;
|
|
||||||
|
|
||||||
internal IntPtr NativeContextPtr => _context.BasePtr;
|
|
||||||
|
|
||||||
public ulong Pc => 0UL;
|
|
||||||
|
|
||||||
public long TpidrEl0
|
|
||||||
{
|
|
||||||
get => (long)_context.GetStorage().TpidrEl0;
|
|
||||||
set => _context.GetStorage().TpidrEl0 = (ulong)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long TpidrroEl0
|
|
||||||
{
|
|
||||||
get => (long)_context.GetStorage().TpidrroEl0;
|
|
||||||
set => _context.GetStorage().TpidrroEl0 = (ulong)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Pstate
|
|
||||||
{
|
|
||||||
get => _context.GetStorage().Pstate;
|
|
||||||
set => _context.GetStorage().Pstate = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Fpcr
|
|
||||||
{
|
|
||||||
get => _context.GetStorage().Fpcr;
|
|
||||||
set => _context.GetStorage().Fpcr = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Fpsr
|
|
||||||
{
|
|
||||||
get => _context.GetStorage().Fpsr;
|
|
||||||
set => _context.GetStorage().Fpsr = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAarch32
|
|
||||||
{
|
|
||||||
get => false;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong ThreadUid { get; set; }
|
|
||||||
|
|
||||||
public bool Running { get; private set; }
|
|
||||||
|
|
||||||
private delegate bool SupervisorCallHandler(int imm);
|
|
||||||
private SupervisorCallHandler _svcHandler;
|
|
||||||
|
|
||||||
private MemoryBlock _alternateStackMemory;
|
|
||||||
|
|
||||||
public NceExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
|
||||||
{
|
|
||||||
_svcHandler = OnSupervisorCall;
|
|
||||||
IntPtr svcHandlerPtr = Marshal.GetFunctionPointerForDelegate(_svcHandler);
|
|
||||||
|
|
||||||
_context = new NceNativeContext();
|
|
||||||
|
|
||||||
ref var storage = ref _context.GetStorage();
|
|
||||||
storage.SvcCallHandler = svcHandlerPtr;
|
|
||||||
storage.InManaged = 1u;
|
|
||||||
storage.CtrEl0 = 0x8444c004; // TODO: Get value from host CPU instead of using guest one?
|
|
||||||
|
|
||||||
Running = true;
|
|
||||||
_exceptionCallbacks = exceptionCallbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetX(int index) => _context.GetStorage().X[index];
|
|
||||||
public void SetX(int index, ulong value) => _context.GetStorage().X[index] = value;
|
|
||||||
|
|
||||||
public V128 GetV(int index) => _context.GetStorage().V[index];
|
|
||||||
public void SetV(int index, V128 value) => _context.GetStorage().V[index] = value;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
public bool GetPstateFlag(PState flag) => false;
|
|
||||||
public void SetPstateFlag(PState flag, bool value) { }
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
public bool GetFPstateFlag(FPState flag) => false;
|
|
||||||
public void SetFPstateFlag(FPState flag, bool value) { }
|
|
||||||
|
|
||||||
public void SetStartAddress(ulong address)
|
|
||||||
{
|
|
||||||
ref var storage = ref _context.GetStorage();
|
|
||||||
storage.X[30] = address;
|
|
||||||
storage.HostThreadHandle = NceThreadPal.GetCurrentThreadHandle();
|
|
||||||
|
|
||||||
RegisterAlternateStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Exit()
|
|
||||||
{
|
|
||||||
_context.GetStorage().HostThreadHandle = IntPtr.Zero;
|
|
||||||
|
|
||||||
UnregisterAlternateStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterAlternateStack()
|
|
||||||
{
|
|
||||||
// We need to use an alternate stack to handle the suspend signal,
|
|
||||||
// as the guest stack may be in a state that is not suitable for the signal handlers.
|
|
||||||
|
|
||||||
_alternateStackMemory = new MemoryBlock(AlternateStackSize);
|
|
||||||
NativeSignalHandler.InstallUnixAlternateStackForCurrentThread(_alternateStackMemory.GetPointer(0UL, AlternateStackSize), AlternateStackSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnregisterAlternateStack()
|
|
||||||
{
|
|
||||||
NativeSignalHandler.UninstallUnixAlternateStackForCurrentThread();
|
|
||||||
_alternateStackMemory.Dispose();
|
|
||||||
_alternateStackMemory = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnSupervisorCall(int imm)
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.SupervisorCallback?.Invoke(this, 0UL, imm);
|
|
||||||
return Running;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnInterrupt()
|
|
||||||
{
|
|
||||||
_exceptionCallbacks.InterruptCallback?.Invoke(this);
|
|
||||||
return Running;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RequestInterrupt()
|
|
||||||
{
|
|
||||||
IntPtr threadHandle = _context.GetStorage().HostThreadHandle;
|
|
||||||
if (threadHandle != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
// Bit 0 set means that the thread is currently running managed code.
|
|
||||||
// Bit 1 set means that an interrupt was requested for the thread.
|
|
||||||
// This, we only need to send the suspend signal if the value was 0 (not running managed code,
|
|
||||||
// and no interrupt was requested before).
|
|
||||||
|
|
||||||
ref uint inManaged = ref _context.GetStorage().InManaged;
|
|
||||||
uint oldValue = Interlocked.Or(ref inManaged, 2);
|
|
||||||
|
|
||||||
if (oldValue == 0)
|
|
||||||
{
|
|
||||||
NceThreadPal.SuspendThread(threadHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StopRunning()
|
|
||||||
{
|
|
||||||
Running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RequestDebugStep()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong DebugPc { get; set; }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_context.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
class NceMemoryAllocator : IJitMemoryAllocator
|
|
||||||
{
|
|
||||||
public IJitMemoryBlock Allocate(ulong size) => new NceMemoryBlock(size, MemoryAllocationFlags.None);
|
|
||||||
public IJitMemoryBlock Reserve(ulong size) => new NceMemoryBlock(size, MemoryAllocationFlags.Reserve);
|
|
||||||
|
|
||||||
public ulong GetPageSize() => MemoryBlock.GetPageSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
using ARMeilleure.Memory;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
class NceMemoryBlock : IJitMemoryBlock
|
|
||||||
{
|
|
||||||
private readonly MemoryBlock _impl;
|
|
||||||
|
|
||||||
public IntPtr Pointer => _impl.Pointer;
|
|
||||||
|
|
||||||
public NceMemoryBlock(ulong size, MemoryAllocationFlags flags)
|
|
||||||
{
|
|
||||||
_impl = new MemoryBlock(size, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Commit(ulong offset, ulong size) => _impl.Commit(offset, size);
|
|
||||||
public void MapAsRw(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndWrite);
|
|
||||||
public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute);
|
|
||||||
public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute);
|
|
||||||
|
|
||||||
public void Dispose() => _impl.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
using ARMeilleure.State;
|
|
||||||
using Ryujinx.Common.Memory;
|
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
class NceNativeContext : IDisposable
|
|
||||||
{
|
|
||||||
public struct NativeCtxStorage
|
|
||||||
{
|
|
||||||
public Array32<ulong> X;
|
|
||||||
public Array32<V128> V;
|
|
||||||
public ulong TpidrEl0;
|
|
||||||
public ulong TpidrroEl0;
|
|
||||||
public ulong CtrEl0;
|
|
||||||
public uint Pstate;
|
|
||||||
public uint Fpcr;
|
|
||||||
public uint Fpsr;
|
|
||||||
public uint InManaged;
|
|
||||||
public ulong HostSp;
|
|
||||||
public IntPtr HostThreadHandle;
|
|
||||||
public ulong TempStorage;
|
|
||||||
public IntPtr SvcCallHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NativeCtxStorage _dummyStorage = new();
|
|
||||||
|
|
||||||
private readonly MemoryBlock _block;
|
|
||||||
|
|
||||||
public IntPtr BasePtr => _block.Pointer;
|
|
||||||
|
|
||||||
public NceNativeContext()
|
|
||||||
{
|
|
||||||
_block = new MemoryBlock((ulong)Unsafe.SizeOf<NativeCtxStorage>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetXOffset(int index)
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetGuestSPOffset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[31]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetVOffset(int index)
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.V[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetTpidrEl0Offset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrEl0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetTpidrroEl0Offset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrroEl0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetInManagedOffset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.InManaged);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetHostSPOffset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.HostSp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetCtrEl0Offset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CtrEl0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetTempStorageOffset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TempStorage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetSvcCallHandlerOffset()
|
|
||||||
{
|
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.SvcCallHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
|
||||||
{
|
|
||||||
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe ref NativeCtxStorage GetStorage() => ref Unsafe.AsRef<NativeCtxStorage>((void*)_block.Pointer);
|
|
||||||
|
|
||||||
public void Dispose() => _block.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
static class NceNativeInterface
|
|
||||||
{
|
|
||||||
private delegate ulong GetTickCounterDelegate();
|
|
||||||
private delegate bool SuspendThreadHandlerDelegate();
|
|
||||||
private static GetTickCounterDelegate _getTickCounter;
|
|
||||||
private static SuspendThreadHandlerDelegate _suspendThreadHandler;
|
|
||||||
private static IntPtr _getTickCounterPtr;
|
|
||||||
private static IntPtr _suspendThreadHandlerPtr;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static NceExecutionContext _context;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static ITickSource _tickSource;
|
|
||||||
|
|
||||||
static NceNativeInterface()
|
|
||||||
{
|
|
||||||
_getTickCounter = GetTickCounter;
|
|
||||||
_suspendThreadHandler = SuspendThreadHandler;
|
|
||||||
_getTickCounterPtr = Marshal.GetFunctionPointerForDelegate(_getTickCounter);
|
|
||||||
_suspendThreadHandlerPtr = Marshal.GetFunctionPointerForDelegate(_suspendThreadHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RegisterThread(NceExecutionContext context, ITickSource tickSource)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
_tickSource = tickSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetTickCounter()
|
|
||||||
{
|
|
||||||
return _tickSource.Counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool SuspendThreadHandler()
|
|
||||||
{
|
|
||||||
return _context.OnInterrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr GetTickCounterAccessFunctionPointer()
|
|
||||||
{
|
|
||||||
return _getTickCounterPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr GetSuspendThreadHandlerFunctionPointer()
|
|
||||||
{
|
|
||||||
return _suspendThreadHandlerPtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,603 +0,0 @@
|
||||||
using Ryujinx.Cpu.Nce.Arm64;
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
public static class NcePatcher
|
|
||||||
{
|
|
||||||
private const int ScratchBaseReg = 19;
|
|
||||||
|
|
||||||
private const uint IntCalleeSavedRegsMask = 0x1ff80000; // X19 to X28
|
|
||||||
private const uint FpCalleeSavedRegsMask = 0xff00; // D8 to D15
|
|
||||||
|
|
||||||
public static NceCpuCodePatch CreatePatch(ReadOnlySpan<byte> textSection)
|
|
||||||
{
|
|
||||||
NceCpuCodePatch codePatch = new();
|
|
||||||
|
|
||||||
var textUint = MemoryMarshal.Cast<byte, uint>(textSection);
|
|
||||||
|
|
||||||
for (int i = 0; i < textUint.Length; i++)
|
|
||||||
{
|
|
||||||
uint inst = textUint[i];
|
|
||||||
ulong address = (ulong)i * sizeof(uint);
|
|
||||||
|
|
||||||
if ((inst & ~(0xffffu << 5)) == 0xd4000001u) // svc #0
|
|
||||||
{
|
|
||||||
uint svcId = (ushort)(inst >> 5);
|
|
||||||
codePatch.AddCode(i, WriteSvcPatch(svcId));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched SVC #{svcId} at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
else if ((inst & ~0x1f) == 0xd53bd060) // mrs x0, tpidrro_el0
|
|
||||||
{
|
|
||||||
uint rd = inst & 0x1f;
|
|
||||||
codePatch.AddCode(i, WriteMrsTpidrroEl0Patch(rd));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched MRS x{rd}, tpidrro_el0 at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
else if ((inst & ~0x1f) == 0xd53bd040) // mrs x0, tpidr_el0
|
|
||||||
{
|
|
||||||
uint rd = inst & 0x1f;
|
|
||||||
codePatch.AddCode(i, WriteMrsTpidrEl0Patch(rd));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched MRS x{rd}, tpidr_el0 at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
else if ((inst & ~0x1f) == 0xd53b0020 && OperatingSystem.IsMacOS()) // mrs x0, ctr_el0
|
|
||||||
{
|
|
||||||
uint rd = inst & 0x1f;
|
|
||||||
codePatch.AddCode(i, WriteMrsCtrEl0Patch(rd));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched MRS x{rd}, ctr_el0 at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
else if ((inst & ~0x1f) == 0xd53be020) // mrs x0, cntpct_el0
|
|
||||||
{
|
|
||||||
uint rd = inst & 0x1f;
|
|
||||||
codePatch.AddCode(i, WriteMrsCntpctEl0Patch(rd));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched MRS x{rd}, cntpct_el0 at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
else if ((inst & ~0x1f) == 0xd51bd040) // msr tpidr_el0, x0
|
|
||||||
{
|
|
||||||
uint rd = inst & 0x1f;
|
|
||||||
codePatch.AddCode(i, WriteMsrTpidrEl0Patch(rd));
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Patched MSR tpidr_el0, x{rd} at 0x{address:X}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return codePatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteSvcPatch(uint svcId)
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
WriteManagedCall(asm, (asm, ctx, tmp, tmp2) =>
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
asm.StrRiUn(Gpr(i), ctx, NceNativeContext.GetXOffset(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteInManagedLockAcquire(asm, ctx, tmp, tmp2);
|
|
||||||
|
|
||||||
asm.Mov(Gpr(0, OperandType.I32), svcId);
|
|
||||||
asm.LdrRiUn(tmp, ctx, NceNativeContext.GetSvcCallHandlerOffset());
|
|
||||||
asm.Blr(tmp);
|
|
||||||
|
|
||||||
Operand lblContinue = asm.CreateLabel();
|
|
||||||
Operand lblQuit = asm.CreateLabel();
|
|
||||||
|
|
||||||
asm.Cbnz(Gpr(0, OperandType.I32), lblContinue);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblQuit);
|
|
||||||
|
|
||||||
CreateRegisterSaveRestoreForManaged().WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Ret(Gpr(30));
|
|
||||||
|
|
||||||
asm.MarkLabel(lblContinue);
|
|
||||||
|
|
||||||
WriteInManagedLockRelease(asm, ctx, tmp, tmp2, ThreadExitMethod.Label, lblQuit);
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
asm.LdrRiUn(Gpr(i), ctx, NceNativeContext.GetXOffset(i));
|
|
||||||
}
|
|
||||||
}, 0xff);
|
|
||||||
|
|
||||||
asm.B(0);
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMrsTpidrroEl0Patch(uint rd)
|
|
||||||
{
|
|
||||||
return WriteMrsContextRead(rd, NceNativeContext.GetTpidrroEl0Offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMrsTpidrEl0Patch(uint rd)
|
|
||||||
{
|
|
||||||
return WriteMrsContextRead(rd, NceNativeContext.GetTpidrEl0Offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMrsCtrEl0Patch(uint rd)
|
|
||||||
{
|
|
||||||
return WriteMrsContextRead(rd, NceNativeContext.GetCtrEl0Offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMrsCntpctEl0Patch(uint rd)
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
WriteManagedCall(asm, (asm, ctx, tmp, tmp2) =>
|
|
||||||
{
|
|
||||||
WriteInManagedLockAcquire(asm, ctx, tmp, tmp2);
|
|
||||||
|
|
||||||
asm.Mov(tmp, (ulong)NceNativeInterface.GetTickCounterAccessFunctionPointer());
|
|
||||||
asm.Blr(tmp);
|
|
||||||
asm.StrRiUn(Gpr(0), ctx, NceNativeContext.GetTempStorageOffset());
|
|
||||||
|
|
||||||
WriteInManagedLockRelease(asm, ctx, tmp, tmp2, ThreadExitMethod.GenerateReturn);
|
|
||||||
|
|
||||||
asm.LdrRiUn(Gpr((int)rd), ctx, NceNativeContext.GetTempStorageOffset());
|
|
||||||
}, 1u << (int)rd);
|
|
||||||
|
|
||||||
asm.B(0);
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMsrTpidrEl0Patch(uint rd)
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
Span<int> scratchRegs = stackalloc int[3];
|
|
||||||
PickScratchRegs(scratchRegs, 1u << (int)rd);
|
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new((1 << scratchRegs[0]) | (1 << scratchRegs[1]) | (1 << scratchRegs[2]));
|
|
||||||
|
|
||||||
rsr.WritePrologue(asm);
|
|
||||||
|
|
||||||
WriteLoadContext(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]));
|
|
||||||
asm.StrRiUn(Gpr((int)rd), Gpr(scratchRegs[0]),NceNativeContext.GetTpidrEl0Offset());
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.B(0);
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] WriteMrsContextRead(uint rd, int contextOffset)
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
Span<int> scratchRegs = stackalloc int[3];
|
|
||||||
PickScratchRegs(scratchRegs, 1u << (int)rd);
|
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new((1 << scratchRegs[0]) | (1 << scratchRegs[1]) | (1 << scratchRegs[2]));
|
|
||||||
|
|
||||||
rsr.WritePrologue(asm);
|
|
||||||
|
|
||||||
WriteLoadContext(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]));
|
|
||||||
asm.Add(Gpr((int)rd), Gpr(scratchRegs[0]), Const((ulong)contextOffset));
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.LdrRiUn(Gpr((int)rd), Gpr((int)rd), 0);
|
|
||||||
|
|
||||||
asm.B(0);
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteLoadContext(Assembler asm, Operand tmp0, Operand tmp1, Operand tmp2)
|
|
||||||
{
|
|
||||||
asm.Mov(tmp0, (ulong)NceThreadTable.EntriesPointer);
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
asm.MrsTpidrroEl0(tmp1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.MrsTpidrEl0(tmp1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand lblFound = asm.CreateLabel();
|
|
||||||
Operand lblLoop = asm.CreateLabel();
|
|
||||||
|
|
||||||
asm.MarkLabel(lblLoop);
|
|
||||||
|
|
||||||
asm.LdrRiPost(tmp2, tmp0, 16);
|
|
||||||
asm.Cmp(tmp1, tmp2);
|
|
||||||
asm.B(lblFound, ArmCondition.Eq);
|
|
||||||
asm.B(lblLoop);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblFound);
|
|
||||||
|
|
||||||
asm.Ldur(tmp0, tmp0, -8);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteLoadContextSafe(Assembler asm, Operand lblFail, Operand tmp0, Operand tmp1, Operand tmp2, Operand tmp3)
|
|
||||||
{
|
|
||||||
asm.Mov(tmp0, (ulong)NceThreadTable.EntriesPointer);
|
|
||||||
asm.Ldur(tmp3, tmp0, -8);
|
|
||||||
asm.Add(tmp3, tmp0, tmp3, ArmShiftType.Lsl, 4);
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
asm.MrsTpidrroEl0(tmp1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.MrsTpidrEl0(tmp1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand lblFound = asm.CreateLabel();
|
|
||||||
Operand lblLoop = asm.CreateLabel();
|
|
||||||
|
|
||||||
asm.MarkLabel(lblLoop);
|
|
||||||
|
|
||||||
asm.Cmp(tmp0, tmp3);
|
|
||||||
asm.B(lblFail, ArmCondition.GeUn);
|
|
||||||
asm.LdrRiPost(tmp2, tmp0, 16);
|
|
||||||
asm.Cmp(tmp1, tmp2);
|
|
||||||
asm.B(lblFound, ArmCondition.Eq);
|
|
||||||
asm.B(lblLoop);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblFound);
|
|
||||||
|
|
||||||
asm.Ldur(tmp0, tmp0, -8);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PickScratchRegs(Span<int> scratchRegs, uint blacklistedRegMask)
|
|
||||||
{
|
|
||||||
int scratchReg = ScratchBaseReg;
|
|
||||||
|
|
||||||
for (int i = 0; i < scratchRegs.Length; i++)
|
|
||||||
{
|
|
||||||
while ((blacklistedRegMask & (1u << scratchReg)) != 0)
|
|
||||||
{
|
|
||||||
scratchReg++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scratchReg >= 29)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"No enough register for {scratchRegs.Length} scratch register, started from {ScratchBaseReg}");
|
|
||||||
}
|
|
||||||
|
|
||||||
scratchRegs[i] = scratchReg++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Operand Gpr(int register, OperandType type = OperandType.I64)
|
|
||||||
{
|
|
||||||
return new Operand(register, RegisterType.Integer, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Operand Vec(int register, OperandType type = OperandType.V128)
|
|
||||||
{
|
|
||||||
return new Operand(register, RegisterType.Vector, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Operand Const(ulong value)
|
|
||||||
{
|
|
||||||
return new Operand(OperandType.I64, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Operand Const(OperandType type, ulong value)
|
|
||||||
{
|
|
||||||
return new Operand(type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint GetImm26(ulong sourceAddress, ulong targetAddress)
|
|
||||||
{
|
|
||||||
long offset = (long)(targetAddress - sourceAddress);
|
|
||||||
long offsetTrunc = (offset >> 2) & 0x3FFFFFF;
|
|
||||||
|
|
||||||
if ((offsetTrunc << 38) >> 36 != offset)
|
|
||||||
{
|
|
||||||
throw new Exception($"Offset out of range: 0x{sourceAddress:X} -> 0x{targetAddress:X} (0x{offset:X})");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint)offsetTrunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetOffset(ulong sourceAddress, ulong targetAddress)
|
|
||||||
{
|
|
||||||
long offset = (long)(targetAddress - sourceAddress);
|
|
||||||
|
|
||||||
return checked((int)offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] GetCopy(uint[] code)
|
|
||||||
{
|
|
||||||
uint[] codeCopy = new uint[code.Length];
|
|
||||||
code.CopyTo(codeCopy, 0);
|
|
||||||
|
|
||||||
return codeCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteManagedCall(Assembler asm, Action<Assembler, Operand, Operand, Operand> writeCall, uint blacklistedRegMask)
|
|
||||||
{
|
|
||||||
int intMask = 0x7fffffff & (int)~blacklistedRegMask;
|
|
||||||
int vecMask = unchecked((int)0xffffffff);
|
|
||||||
|
|
||||||
Span<int> scratchRegs = stackalloc int[3];
|
|
||||||
PickScratchRegs(scratchRegs, blacklistedRegMask);
|
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new(intMask, vecMask, OperandType.V128);
|
|
||||||
|
|
||||||
rsr.WritePrologue(asm);
|
|
||||||
|
|
||||||
WriteLoadContext(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]));
|
|
||||||
|
|
||||||
asm.MovSp(Gpr(scratchRegs[1]), Gpr(Assembler.SpRegister));
|
|
||||||
asm.StrRiUn(Gpr(scratchRegs[1]), Gpr(scratchRegs[0]), NceNativeContext.GetGuestSPOffset());
|
|
||||||
asm.LdrRiUn(Gpr(scratchRegs[1]), Gpr(scratchRegs[0]), NceNativeContext.GetHostSPOffset());
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[1]));
|
|
||||||
|
|
||||||
writeCall(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]));
|
|
||||||
|
|
||||||
asm.LdrRiUn(Gpr(scratchRegs[1]), Gpr(scratchRegs[0]), NceNativeContext.GetGuestSPOffset());
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[1]));
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static uint[] GenerateThreadStartCode()
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
CreateRegisterSaveRestoreForManaged().WritePrologue(asm);
|
|
||||||
|
|
||||||
asm.MovSp(Gpr(1), Gpr(Assembler.SpRegister));
|
|
||||||
asm.StrRiUn(Gpr(1), Gpr(0), NceNativeContext.GetHostSPOffset());
|
|
||||||
|
|
||||||
for (int i = 2; i < 30; i += 2)
|
|
||||||
{
|
|
||||||
asm.LdpRiUn(Gpr(i), Gpr(i + 1), Gpr(0), NceNativeContext.GetXOffset(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 32; i += 2)
|
|
||||||
{
|
|
||||||
asm.LdpRiUn(Vec(i), Vec(i + 1), Gpr(0), NceNativeContext.GetVOffset(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
asm.LdpRiUn(Gpr(30), Gpr(1), Gpr(0), NceNativeContext.GetXOffset(30));
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(1));
|
|
||||||
|
|
||||||
asm.StrRiUn(Gpr(Assembler.ZrRegister, OperandType.I32), Gpr(0), NceNativeContext.GetInManagedOffset());
|
|
||||||
|
|
||||||
asm.LdpRiUn(Gpr(0), Gpr(1), Gpr(0), NceNativeContext.GetXOffset(0));
|
|
||||||
asm.Br(Gpr(30));
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static uint[] GenerateSuspendExceptionHandler()
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
Span<int> scratchRegs = stackalloc int[4];
|
|
||||||
PickScratchRegs(scratchRegs, 0u);
|
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new((1 << scratchRegs[0]) | (1 << scratchRegs[1]) | (1 << scratchRegs[2]) | (1 << scratchRegs[3]), hasCall: true);
|
|
||||||
|
|
||||||
rsr.WritePrologue(asm);
|
|
||||||
|
|
||||||
Operand lblAgain = asm.CreateLabel();
|
|
||||||
Operand lblFail = asm.CreateLabel();
|
|
||||||
|
|
||||||
WriteLoadContextSafe(asm, lblFail, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]), Gpr(scratchRegs[3]));
|
|
||||||
|
|
||||||
asm.LdrRiUn(Gpr(scratchRegs[1]), Gpr(scratchRegs[0]), NceNativeContext.GetHostSPOffset());
|
|
||||||
asm.MovSp(Gpr(scratchRegs[2]), Gpr(Assembler.SpRegister));
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[1]));
|
|
||||||
|
|
||||||
asm.Cmp(Gpr(0, OperandType.I32), Const((ulong)NceThreadPal.UnixSuspendSignal));
|
|
||||||
asm.B(lblFail, ArmCondition.Ne);
|
|
||||||
|
|
||||||
// SigUsr2
|
|
||||||
|
|
||||||
asm.Mov(Gpr(scratchRegs[1], OperandType.I32), Const(OperandType.I32, 1));
|
|
||||||
asm.StrRiUn(Gpr(scratchRegs[1], OperandType.I32), Gpr(scratchRegs[0]), NceNativeContext.GetInManagedOffset());
|
|
||||||
|
|
||||||
asm.MarkLabel(lblAgain);
|
|
||||||
|
|
||||||
asm.Mov(Gpr(scratchRegs[3]), (ulong)NceNativeInterface.GetSuspendThreadHandlerFunctionPointer());
|
|
||||||
asm.Blr(Gpr(scratchRegs[3]));
|
|
||||||
|
|
||||||
// TODO: Check return value, exit if we must.
|
|
||||||
|
|
||||||
WriteInManagedLockReleaseForSuspendHandler(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[3]), lblAgain);
|
|
||||||
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[2]));
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Ret(Gpr(30));
|
|
||||||
|
|
||||||
asm.MarkLabel(lblFail);
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Ret(Gpr(30));
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static uint[] GenerateWrapperExceptionHandler(IntPtr oldSignalHandlerSegfaultPtr, IntPtr signalHandlerPtr)
|
|
||||||
{
|
|
||||||
Assembler asm = new();
|
|
||||||
|
|
||||||
Span<int> scratchRegs = stackalloc int[4];
|
|
||||||
PickScratchRegs(scratchRegs, 0u);
|
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new((1 << scratchRegs[0]) | (1 << scratchRegs[1]) | (1 << scratchRegs[2]) | (1 << scratchRegs[3]), hasCall: true);
|
|
||||||
|
|
||||||
rsr.WritePrologue(asm);
|
|
||||||
|
|
||||||
Operand lblFail = asm.CreateLabel();
|
|
||||||
|
|
||||||
WriteLoadContextSafe(asm, lblFail, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[2]), Gpr(scratchRegs[3]));
|
|
||||||
|
|
||||||
asm.LdrRiUn(Gpr(scratchRegs[1]), Gpr(scratchRegs[0]), NceNativeContext.GetHostSPOffset());
|
|
||||||
asm.MovSp(Gpr(scratchRegs[2]), Gpr(Assembler.SpRegister));
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[1]));
|
|
||||||
|
|
||||||
// SigSegv
|
|
||||||
|
|
||||||
WriteInManagedLockAcquire(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[3]));
|
|
||||||
|
|
||||||
asm.Mov(Gpr(scratchRegs[3]), (ulong)signalHandlerPtr);
|
|
||||||
asm.Blr(Gpr(scratchRegs[3]));
|
|
||||||
|
|
||||||
WriteInManagedLockRelease(asm, Gpr(scratchRegs[0]), Gpr(scratchRegs[1]), Gpr(scratchRegs[3]), ThreadExitMethod.None);
|
|
||||||
|
|
||||||
asm.MovSp(Gpr(Assembler.SpRegister), Gpr(scratchRegs[2]));
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Ret(Gpr(30));
|
|
||||||
|
|
||||||
asm.MarkLabel(lblFail);
|
|
||||||
|
|
||||||
rsr.WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Mov(Gpr(3), (ulong)oldSignalHandlerSegfaultPtr);
|
|
||||||
asm.Br(Gpr(3));
|
|
||||||
|
|
||||||
return asm.GetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteInManagedLockAcquire(Assembler asm, Operand ctx, Operand tmp, Operand tmp2)
|
|
||||||
{
|
|
||||||
Operand tmpUint = new Operand(tmp.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
Operand tmp2Uint = new Operand(tmp2.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
|
|
||||||
Operand lblLoop = asm.CreateLabel();
|
|
||||||
|
|
||||||
// Bit 0 set means that the thread is currently executing managed code (that case should be impossible here).
|
|
||||||
// Bit 1 being set means there is a signal pending, we should wait for the signal, otherwise it could trigger
|
|
||||||
// while running managed code.
|
|
||||||
|
|
||||||
asm.MarkLabel(lblLoop);
|
|
||||||
|
|
||||||
asm.Add(tmp, ctx, Const((ulong)NceNativeContext.GetInManagedOffset()));
|
|
||||||
asm.Ldaxr(tmp2Uint, tmp);
|
|
||||||
asm.Cbnz(tmp2Uint, lblLoop);
|
|
||||||
asm.Mov(tmp2Uint, Const(OperandType.I32, 1));
|
|
||||||
asm.Stlxr(tmp2Uint, tmp, tmpUint);
|
|
||||||
asm.Cbnz(tmpUint, lblLoop); // Retry if store failed.
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum ThreadExitMethod
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
GenerateReturn,
|
|
||||||
Label
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteInManagedLockRelease(Assembler asm, Operand ctx, Operand tmp, Operand tmp2, ThreadExitMethod exitMethod, Operand lblQuit = default)
|
|
||||||
{
|
|
||||||
Operand tmpUint = new Operand(tmp.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
Operand tmp2Uint = new Operand(tmp2.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
|
|
||||||
Operand lblLoop = asm.CreateLabel();
|
|
||||||
Operand lblInterrupt = asm.CreateLabel();
|
|
||||||
Operand lblDone = asm.CreateLabel();
|
|
||||||
|
|
||||||
// Bit 0 set means that the thread is currently executing managed code (it should be always set here, as we just returned from managed code).
|
|
||||||
// Bit 1 being set means a interrupt was requested while it was in managed, we should service it.
|
|
||||||
|
|
||||||
asm.MarkLabel(lblLoop);
|
|
||||||
|
|
||||||
asm.Add(tmp, ctx, Const((ulong)NceNativeContext.GetInManagedOffset()));
|
|
||||||
asm.Ldaxr(tmp2Uint, tmp);
|
|
||||||
asm.Cmp(tmp2Uint, Const(OperandType.I32, 3));
|
|
||||||
asm.B(lblInterrupt, ArmCondition.Eq);
|
|
||||||
asm.Stlxr(Gpr(Assembler.ZrRegister, OperandType.I32), tmp, tmpUint);
|
|
||||||
asm.Cbnz(tmpUint, lblLoop); // Retry if store failed.
|
|
||||||
asm.B(lblDone);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblInterrupt);
|
|
||||||
|
|
||||||
// If we got here, a interrupt was requested while it was in managed code.
|
|
||||||
// Let's service the interrupt and check what we should do next.
|
|
||||||
|
|
||||||
asm.Mov(tmp2Uint, Const(OperandType.I32, 1));
|
|
||||||
asm.Stlxr(tmp2Uint, tmp, tmpUint);
|
|
||||||
asm.Cbnz(tmpUint, lblLoop); // Retry if store failed.
|
|
||||||
asm.Mov(tmp, (ulong)NceNativeInterface.GetSuspendThreadHandlerFunctionPointer());
|
|
||||||
asm.Blr(tmp);
|
|
||||||
|
|
||||||
// The return value from the interrupt handler indicates if we should continue running.
|
|
||||||
// From here, we either try to release the lock again. We might have received another interrupt
|
|
||||||
// request in the meantime, in which case we should service it again.
|
|
||||||
// If we were requested to exit, then we exit if we can.
|
|
||||||
// TODO: We should also exit while on a signal handler. To do that we need to modify the PC value on the
|
|
||||||
// context. It's a bit more tricky to do, so for now we ignore that case with "ThreadExitMethod.None".
|
|
||||||
|
|
||||||
if (exitMethod == ThreadExitMethod.None)
|
|
||||||
{
|
|
||||||
asm.B(lblLoop);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm.Cbnz(Gpr(0, OperandType.I32), lblLoop);
|
|
||||||
|
|
||||||
if (exitMethod == ThreadExitMethod.Label)
|
|
||||||
{
|
|
||||||
asm.B(lblQuit);
|
|
||||||
}
|
|
||||||
else if (exitMethod == ThreadExitMethod.GenerateReturn)
|
|
||||||
{
|
|
||||||
CreateRegisterSaveRestoreForManaged().WriteEpilogue(asm);
|
|
||||||
|
|
||||||
asm.Ret(Gpr(30));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
asm.MarkLabel(lblDone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteInManagedLockReleaseForSuspendHandler(Assembler asm, Operand ctx, Operand tmp, Operand tmp2, Operand lblAgain)
|
|
||||||
{
|
|
||||||
Operand tmpUint = new Operand(tmp.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
Operand tmp2Uint = new Operand(tmp2.GetRegister().Index, RegisterType.Integer, OperandType.I32);
|
|
||||||
|
|
||||||
Operand lblLoop = asm.CreateLabel();
|
|
||||||
Operand lblInterrupt = asm.CreateLabel();
|
|
||||||
Operand lblDone = asm.CreateLabel();
|
|
||||||
|
|
||||||
// Bit 0 set means that the thread is currently executing managed code (it should be always set here, as we just returned from managed code).
|
|
||||||
// Bit 1 being set means a interrupt was requested while it was in managed, we should service it.
|
|
||||||
|
|
||||||
asm.MarkLabel(lblLoop);
|
|
||||||
|
|
||||||
asm.Add(tmp, ctx, Const((ulong)NceNativeContext.GetInManagedOffset()));
|
|
||||||
asm.Ldaxr(tmp2Uint, tmp);
|
|
||||||
asm.Cmp(tmp2Uint, Const(OperandType.I32, 3));
|
|
||||||
asm.B(lblInterrupt, ArmCondition.Eq);
|
|
||||||
asm.Stlxr(Gpr(Assembler.ZrRegister, OperandType.I32), tmp, tmpUint);
|
|
||||||
asm.Cbnz(tmpUint, lblLoop); // Retry if store failed.
|
|
||||||
asm.B(lblDone);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblInterrupt);
|
|
||||||
|
|
||||||
// If we got here, a interrupt was requested while it was in managed code.
|
|
||||||
// Let's service the interrupt and check what we should do next.
|
|
||||||
|
|
||||||
asm.Mov(tmp2Uint, Const(OperandType.I32, 1));
|
|
||||||
asm.Stlxr(tmp2Uint, tmp, tmpUint);
|
|
||||||
asm.Cbnz(tmpUint, lblLoop); // Retry if store failed.
|
|
||||||
asm.B(lblAgain);
|
|
||||||
|
|
||||||
asm.MarkLabel(lblDone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RegisterSaveRestore CreateRegisterSaveRestoreForManaged()
|
|
||||||
{
|
|
||||||
return new RegisterSaveRestore((int)IntCalleeSavedRegsMask, unchecked((int)FpCalleeSavedRegsMask), OperandType.FP64, hasCall: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
static class NceThreadPal
|
|
||||||
{
|
|
||||||
private const int SigUsr2Linux = 12;
|
|
||||||
private const int SigUsr2MacOS = 31;
|
|
||||||
|
|
||||||
public static int UnixSuspendSignal => OperatingSystem.IsMacOS() ? SigUsr2MacOS : SigUsr2Linux;
|
|
||||||
|
|
||||||
public static IntPtr GetCurrentThreadHandle()
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
return NceThreadPalUnix.GetCurrentThreadHandle();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new PlatformNotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SuspendThread(IntPtr handle)
|
|
||||||
{
|
|
||||||
if (PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
NceThreadPalAndroid.SuspendThread(handle);
|
|
||||||
}
|
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
NceThreadPalUnix.SuspendThread(handle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new PlatformNotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
static class NceThreadPalAndroid
|
|
||||||
{
|
|
||||||
[DllImport("libc", SetLastError = true)]
|
|
||||||
private static extern int pthread_kill(IntPtr thread, int sig);
|
|
||||||
|
|
||||||
public static void SuspendThread(IntPtr handle)
|
|
||||||
{
|
|
||||||
int result = pthread_kill(handle, NceThreadPal.UnixSuspendSignal);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new Exception($"Thread kill returned error 0x{result:X}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
static class NceThreadPalUnix
|
|
||||||
{
|
|
||||||
[DllImport("libc", SetLastError = true)]
|
|
||||||
private static extern IntPtr pthread_self();
|
|
||||||
|
|
||||||
[DllImport("libc", SetLastError = true)]
|
|
||||||
private static extern int pthread_threadid_np(IntPtr arg0, out ulong tid);
|
|
||||||
|
|
||||||
[DllImport("libpthread", SetLastError = true)]
|
|
||||||
private static extern int pthread_kill(IntPtr thread, int sig);
|
|
||||||
|
|
||||||
public static IntPtr GetCurrentThreadHandle()
|
|
||||||
{
|
|
||||||
return pthread_self();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetCurrentThreadId()
|
|
||||||
{
|
|
||||||
pthread_threadid_np(IntPtr.Zero, out ulong tid);
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SuspendThread(IntPtr handle)
|
|
||||||
{
|
|
||||||
int result = pthread_kill(handle, NceThreadPal.UnixSuspendSignal);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new Exception($"Thread kill returned error 0x{result:X}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Nce
|
|
||||||
{
|
|
||||||
static class NceThreadTable
|
|
||||||
{
|
|
||||||
private const int MaxThreads = 4096;
|
|
||||||
|
|
||||||
private struct Entry
|
|
||||||
{
|
|
||||||
public IntPtr ThreadId;
|
|
||||||
public IntPtr NativeContextPtr;
|
|
||||||
|
|
||||||
public Entry(IntPtr threadId, IntPtr nativeContextPtr)
|
|
||||||
{
|
|
||||||
ThreadId = threadId;
|
|
||||||
NativeContextPtr = nativeContextPtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MemoryBlock _block;
|
|
||||||
|
|
||||||
public static IntPtr EntriesPointer => _block.Pointer + 8;
|
|
||||||
|
|
||||||
static NceThreadTable()
|
|
||||||
{
|
|
||||||
_block = new MemoryBlock((ulong)Unsafe.SizeOf<Entry>() * MaxThreads + 8UL);
|
|
||||||
_block.Write(0UL, 0UL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int Register(IntPtr threadId, IntPtr nativeContextPtr)
|
|
||||||
{
|
|
||||||
Span<Entry> entries = GetStorage();
|
|
||||||
|
|
||||||
lock (_block)
|
|
||||||
{
|
|
||||||
ref ulong currentThreadCount = ref GetThreadsCount();
|
|
||||||
|
|
||||||
for (int i = 0; i < MaxThreads; i++)
|
|
||||||
{
|
|
||||||
if (entries[i].ThreadId == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
entries[i] = new Entry(threadId, nativeContextPtr);
|
|
||||||
|
|
||||||
if (currentThreadCount < (ulong)i + 1)
|
|
||||||
{
|
|
||||||
currentThreadCount = (ulong)i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception($"Number of active threads exceeds limit of {MaxThreads}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Unregister(int tableIndex)
|
|
||||||
{
|
|
||||||
Span<Entry> entries = GetStorage();
|
|
||||||
|
|
||||||
lock (_block)
|
|
||||||
{
|
|
||||||
if (entries[tableIndex].ThreadId != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
entries[tableIndex] = default;
|
|
||||||
|
|
||||||
ulong currentThreadCount = GetThreadsCount();
|
|
||||||
|
|
||||||
for (int i = (int)currentThreadCount - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (entries[i].ThreadId != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentThreadCount = (ulong)i;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetThreadsCount() = currentThreadCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ref ulong GetThreadsCount()
|
|
||||||
{
|
|
||||||
return ref _block.GetRef<ulong>(0UL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static unsafe Span<Entry> GetStorage()
|
|
||||||
{
|
|
||||||
return new Span<Entry>((void*)_block.GetPointer(8UL, (ulong)Unsafe.SizeOf<Entry>() * MaxThreads), MaxThreads);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -89,16 +89,10 @@ namespace Ryujinx.Cpu.Signal
|
||||||
|
|
||||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||||
|
|
||||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_signalHandlerPtr = MapCode(NativeSignalHandlerGenerator.GenerateUnixSignalHandler(_handlerConfig, rangeStructSize));
|
_signalHandlerPtr = MapCode(NativeSignalHandlerGenerator.GenerateUnixSignalHandler(_handlerConfig, rangeStructSize));
|
||||||
|
|
||||||
if (PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
config.StructAddressOffset = 16; // si_addr
|
|
||||||
config.StructWriteOffset = 8; // si_code
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customSignalHandlerFactory != null)
|
if (customSignalHandlerFactory != null)
|
||||||
{
|
{
|
||||||
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
|
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
|
||||||
|
|
@ -128,21 +122,6 @@ namespace Ryujinx.Cpu.Signal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InstallUnixAlternateStackForCurrentThread(IntPtr stackPtr, ulong stackSize)
|
|
||||||
{
|
|
||||||
UnixSignalHandlerRegistration.RegisterAlternateStack(stackPtr, stackSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UninstallUnixAlternateStackForCurrentThread()
|
|
||||||
{
|
|
||||||
UnixSignalHandlerRegistration.UnregisterAlternateStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InstallUnixSignalHandler(int sigNum, IntPtr action)
|
|
||||||
{
|
|
||||||
UnixSignalHandlerRegistration.RegisterExceptionHandler(sigNum, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr MapCode(ReadOnlySpan<byte> code)
|
private static IntPtr MapCode(ReadOnlySpan<byte> code)
|
||||||
{
|
{
|
||||||
Debug.Assert(_codeBlock == null);
|
Debug.Assert(_codeBlock == null);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Signal
|
namespace Ryujinx.Cpu.Signal
|
||||||
{
|
{
|
||||||
|
|
@ -24,73 +22,26 @@ namespace Ryujinx.Cpu.Signal
|
||||||
public IntPtr sa_restorer;
|
public IntPtr sa_restorer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("android"), StructLayout(LayoutKind.Sequential, Pack = 8)]
|
|
||||||
public struct SigActionBionic
|
|
||||||
{
|
|
||||||
public int sa_flags;
|
|
||||||
public IntPtr sa_handler;
|
|
||||||
public SigSet sa_mask;
|
|
||||||
public IntPtr sa_restorer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
|
||||||
public struct Stack
|
|
||||||
{
|
|
||||||
public IntPtr ss_sp;
|
|
||||||
public int ss_flags;
|
|
||||||
public IntPtr ss_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int SIGSEGV = 11;
|
private const int SIGSEGV = 11;
|
||||||
private const int SIGBUS = 10;
|
private const int SIGBUS = 10;
|
||||||
private const int SA_SIGINFO = 0x00000004;
|
private const int SA_SIGINFO = 0x00000004;
|
||||||
private const int SA_ONSTACK = 0x08000000;
|
|
||||||
private const int SS_DISABLE = 2;
|
|
||||||
private const int SS_AUTODISARM = 1 << 31;
|
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
|
private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
|
||||||
|
|
||||||
[SupportedOSPlatform("android"), LibraryImport("libc", SetLastError = true)]
|
|
||||||
private static partial int sigaction(int signum, ref SigActionBionic sigAction, out SigActionBionic oldAction);
|
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
private static partial int sigaction(int signum, IntPtr sigAction, out SigAction oldAction);
|
private static partial int sigaction(int signum, IntPtr sigAction, out SigAction oldAction);
|
||||||
|
|
||||||
[SupportedOSPlatform("android"), LibraryImport("libc", SetLastError = true)]
|
|
||||||
private static partial int sigaction(int signum, IntPtr sigAction, out SigActionBionic oldAction);
|
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
private static partial int sigemptyset(ref SigSet set);
|
private static partial int sigemptyset(ref SigSet set);
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
|
||||||
private static partial int sigaltstack(ref Stack ss, out Stack oldSs);
|
|
||||||
|
|
||||||
public static SigAction GetSegfaultExceptionHandler()
|
public static SigAction GetSegfaultExceptionHandler()
|
||||||
{
|
{
|
||||||
int result;
|
int result = sigaction(SIGSEGV, IntPtr.Zero, out SigAction old);
|
||||||
SigAction old;
|
|
||||||
|
|
||||||
if (PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
result = sigaction(SIGSEGV, IntPtr.Zero, out SigActionBionic tmp);
|
|
||||||
|
|
||||||
old = new SigAction
|
|
||||||
{
|
|
||||||
sa_handler = tmp.sa_handler,
|
|
||||||
sa_mask = tmp.sa_mask,
|
|
||||||
sa_flags = tmp.sa_flags,
|
|
||||||
sa_restorer = tmp.sa_restorer
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = sigaction(SIGSEGV, IntPtr.Zero, out old);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
throw new SystemException($"Could not get SIGSEGV sigaction. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
throw new InvalidOperationException($"Could not get SIGSEGV sigaction. Error: {result}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
|
|
@ -98,167 +49,37 @@ namespace Ryujinx.Cpu.Signal
|
||||||
|
|
||||||
public static SigAction RegisterExceptionHandler(IntPtr action)
|
public static SigAction RegisterExceptionHandler(IntPtr action)
|
||||||
{
|
{
|
||||||
int result;
|
SigAction sig = new()
|
||||||
SigAction old;
|
|
||||||
|
|
||||||
if (PlatformInfo.IsBionic)
|
|
||||||
{
|
{
|
||||||
SigActionBionic sig = new()
|
sa_handler = action,
|
||||||
{
|
sa_flags = SA_SIGINFO,
|
||||||
sa_handler = action,
|
};
|
||||||
sa_flags = SA_SIGINFO | SA_ONSTACK,
|
|
||||||
};
|
|
||||||
|
|
||||||
sigemptyset(ref sig.sa_mask);
|
sigemptyset(ref sig.sa_mask);
|
||||||
|
|
||||||
result = sigaction(SIGSEGV, ref sig, out SigActionBionic tmp);
|
int result = sigaction(SIGSEGV, ref sig, out SigAction old);
|
||||||
|
|
||||||
old = new SigAction
|
if (result != 0)
|
||||||
{
|
{
|
||||||
sa_handler = tmp.sa_handler,
|
throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
|
||||||
sa_mask = tmp.sa_mask,
|
|
||||||
sa_flags = tmp.sa_flags,
|
|
||||||
sa_restorer = tmp.sa_restorer
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
SigAction sig = new SigAction
|
result = sigaction(SIGBUS, ref sig, out _);
|
||||||
{
|
|
||||||
sa_handler = action,
|
|
||||||
sa_flags = SA_SIGINFO,
|
|
||||||
};
|
|
||||||
|
|
||||||
sigemptyset(ref sig.sa_mask);
|
|
||||||
|
|
||||||
result = sigaction(SIGSEGV, ref sig, out old);
|
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
throw new SystemException($"Could not register SIGSEGV sigaction. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
throw new InvalidOperationException($"Could not register SIGBUS sigaction. Error: {result}");
|
||||||
}
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
|
||||||
{
|
|
||||||
result = sigaction(SIGBUS, ref sig, out _);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new SystemException($"Could not register SIGBUS sigaction. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterAlternateStack(IntPtr stackPtr, ulong stackSize)
|
|
||||||
{
|
|
||||||
Stack stack = new()
|
|
||||||
{
|
|
||||||
ss_sp = stackPtr,
|
|
||||||
ss_flags = SS_AUTODISARM,
|
|
||||||
ss_size = (IntPtr)stackSize
|
|
||||||
};
|
|
||||||
|
|
||||||
int result = sigaltstack(ref stack, out _);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new SystemException($"Could not set alternate stack. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UnregisterAlternateStack()
|
|
||||||
{
|
|
||||||
Stack stack = new()
|
|
||||||
{
|
|
||||||
ss_flags = SS_DISABLE
|
|
||||||
};
|
|
||||||
|
|
||||||
int result = sigaltstack(ref stack, out _);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new SystemException($"Could not remove alternate stack. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RegisterExceptionHandler(int sigNum, IntPtr action)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
SigActionBionic sig = new()
|
|
||||||
{
|
|
||||||
sa_handler = action,
|
|
||||||
sa_flags = SA_SIGINFO | SA_ONSTACK
|
|
||||||
};
|
|
||||||
|
|
||||||
sigemptyset(ref sig.sa_mask);
|
|
||||||
|
|
||||||
result = sigaction(sigNum, ref sig, out SigActionBionic oldu);
|
|
||||||
|
|
||||||
if (oldu.sa_handler != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"SIG{sigNum} is already in use.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new SystemException($"Could not register SIG{sigNum} sigaction. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SigAction sig = new()
|
|
||||||
{
|
|
||||||
sa_handler = action,
|
|
||||||
sa_flags = SA_SIGINFO | SA_ONSTACK,
|
|
||||||
};
|
|
||||||
|
|
||||||
sigemptyset(ref sig.sa_mask);
|
|
||||||
|
|
||||||
result = sigaction(sigNum, ref sig, out SigAction oldu);
|
|
||||||
|
|
||||||
if (oldu.sa_handler != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"SIG{sigNum} is already in use.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
throw new SystemException($"Could not register SIG{sigNum} sigaction. Error: {Marshal.GetLastPInvokeErrorMessage()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool RestoreExceptionHandler(SigAction oldAction)
|
public static bool RestoreExceptionHandler(SigAction oldAction)
|
||||||
{
|
{
|
||||||
if (PlatformInfo.IsBionic)
|
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
|
||||||
{
|
|
||||||
SigActionBionic tmp = new SigActionBionic
|
|
||||||
{
|
|
||||||
sa_handler = oldAction.sa_handler,
|
|
||||||
sa_mask = oldAction.sa_mask,
|
|
||||||
sa_flags = oldAction.sa_flags,
|
|
||||||
sa_restorer = oldAction.sa_restorer
|
|
||||||
};
|
|
||||||
|
|
||||||
return sigaction(SIGSEGV, ref tmp, out SigActionBionic _) == 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool success = sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0;
|
|
||||||
|
|
||||||
if (success && (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()))
|
|
||||||
{
|
|
||||||
success = sigaction(SIGBUS, ref oldAction, out SigAction _) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Silk.NET.Core;
|
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using Silk.NET.Vulkan.Extensions.EXT;
|
using Silk.NET.Vulkan.Extensions.EXT;
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -17,7 +16,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private readonly ExtDebugUtils _debugUtils;
|
private readonly ExtDebugUtils _debugUtils;
|
||||||
private readonly DebugUtilsMessengerEXT? _debugUtilsMessenger;
|
private readonly DebugUtilsMessengerEXT? _debugUtilsMessenger;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private unsafe delegate* unmanaged[Cdecl]<DebugUtilsMessageSeverityFlagsEXT, DebugUtilsMessageTypeFlagsEXT, DebugUtilsMessengerCallbackDataEXT*, void*, Bool32> _messageDelegate;
|
|
||||||
|
|
||||||
public VulkanDebugMessenger(Vk api, Instance instance, GraphicsDebugLevel logLevel)
|
public VulkanDebugMessenger(Vk api, Instance instance, GraphicsDebugLevel logLevel)
|
||||||
{
|
{
|
||||||
|
|
@ -73,8 +71,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
_messageDelegate = (delegate* unmanaged[Cdecl]<DebugUtilsMessageSeverityFlagsEXT, DebugUtilsMessageTypeFlagsEXT, DebugUtilsMessengerCallbackDataEXT*, void*, Bool32>)Marshal.GetFunctionPointerForDelegate(UserCallback);
|
debugUtilsMessengerCreateInfo.PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(UserCallback);
|
||||||
debugUtilsMessengerCreateInfo.PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(_messageDelegate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugUtilsMessengerEXT messengerHandle = default;
|
DebugUtilsMessengerEXT messengerHandle = default;
|
||||||
|
|
@ -92,7 +89,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe static Bool32 UserCallback(
|
private unsafe static uint UserCallback(
|
||||||
DebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
DebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
||||||
DebugUtilsMessageTypeFlagsEXT messageTypes,
|
DebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ namespace Ryujinx.HLE.HOS
|
||||||
private readonly ICpuContext _cpuContext;
|
private readonly ICpuContext _cpuContext;
|
||||||
private T _memoryManager;
|
private T _memoryManager;
|
||||||
|
|
||||||
public ulong ReservedSize { get; }
|
|
||||||
|
|
||||||
public IVirtualMemoryManager AddressSpace => _memoryManager;
|
public IVirtualMemoryManager AddressSpace => _memoryManager;
|
||||||
|
|
||||||
public ulong AddressSpaceSize { get; }
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
@ -36,8 +34,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
GpuContext gpuContext,
|
GpuContext gpuContext,
|
||||||
T memoryManager,
|
T memoryManager,
|
||||||
ulong addressSpaceSize,
|
ulong addressSpaceSize,
|
||||||
bool for64Bit,
|
bool for64Bit)
|
||||||
ulong reservedSize = 0UL)
|
|
||||||
{
|
{
|
||||||
if (memoryManager is IRefCounted rc)
|
if (memoryManager is IRefCounted rc)
|
||||||
{
|
{
|
||||||
|
|
@ -50,8 +47,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
_gpuContext = gpuContext;
|
_gpuContext = gpuContext;
|
||||||
_cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit);
|
_cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit);
|
||||||
_memoryManager = memoryManager;
|
_memoryManager = memoryManager;
|
||||||
|
|
||||||
AddressSpaceSize = addressSpaceSize;
|
AddressSpaceSize = addressSpaceSize;
|
||||||
ReservedSize = reservedSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ using Ryujinx.Cpu;
|
||||||
using Ryujinx.Cpu.AppleHv;
|
using Ryujinx.Cpu.AppleHv;
|
||||||
using Ryujinx.Cpu.Jit;
|
using Ryujinx.Cpu.Jit;
|
||||||
using Ryujinx.Cpu.LightningJit;
|
using Ryujinx.Cpu.LightningJit;
|
||||||
using Ryujinx.Cpu.Nce;
|
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
|
@ -47,43 +46,17 @@ namespace Ryujinx.HLE.HOS
|
||||||
_codeSize = codeSize;
|
_codeSize = codeSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NceCpuCodePatch CreateCodePatchForNce(KernelContext context, bool for64Bit, ReadOnlySpan<byte> textSection)
|
|
||||||
{
|
|
||||||
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 && for64Bit && context.Device.Configuration.UseHypervisor && !OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
return NcePatcher.CreatePatch(textSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
|
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
|
||||||
{
|
{
|
||||||
IArmProcessContext processContext;
|
IArmProcessContext processContext;
|
||||||
|
|
||||||
bool isArm64Host = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
bool isArm64Host = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
||||||
|
|
||||||
if (isArm64Host && for64Bit && context.Device.Configuration.UseHypervisor)
|
if (OperatingSystem.IsMacOS() && isArm64Host && for64Bit && context.Device.Configuration.UseHypervisor)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsMacOS())
|
var cpuEngine = new HvEngine(_tickSource);
|
||||||
{
|
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||||
var cpuEngine = new HvEngine(_tickSource);
|
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||||
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
|
||||||
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!AddressSpace.TryCreateWithoutMirror(addressSpaceSize, out var addressSpace))
|
|
||||||
{
|
|
||||||
throw new Exception("Address space creation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Cpu, $"NCE Base AS Address: 0x{addressSpace.Pointer.ToInt64():X} Size: 0x{addressSpace.Size:X}");
|
|
||||||
|
|
||||||
var cpuEngine = new NceEngine(_tickSource);
|
|
||||||
var memoryManager = new MemoryManagerNative(addressSpace, context.Memory, addressSpaceSize, invalidAccessHandler);
|
|
||||||
processContext = new ArmProcessContext<MemoryManagerNative>(pid, cpuEngine, _gpu, memoryManager, addressSpace.Size, for64Bit, memoryManager.ReservedSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -101,13 +74,11 @@ namespace Ryujinx.HLE.HOS
|
||||||
: new JitEngine(_tickSource);
|
: new JitEngine(_tickSource);
|
||||||
|
|
||||||
AddressSpace addressSpace = null;
|
AddressSpace addressSpace = null;
|
||||||
MemoryBlock asNoMirror = null;
|
|
||||||
|
|
||||||
// We want to use host tracked mode if the host page size is > 4KB.
|
// We want to use host tracked mode if the host page size is > 4KB.
|
||||||
if ((mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe) && MemoryBlock.GetPageSize() <= 0x1000)
|
if ((mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe) && MemoryBlock.GetPageSize() <= 0x1000)
|
||||||
{
|
{
|
||||||
if (!AddressSpace.TryCreate(context.Memory, addressSpaceSize, out addressSpace) &&
|
if (!AddressSpace.TryCreate(context.Memory, addressSpaceSize, out addressSpace))
|
||||||
!AddressSpace.TryCreateWithoutMirror(addressSpaceSize, out asNoMirror))
|
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Cpu, "Address space creation failed, falling back to software page table");
|
Logger.Warning?.Print(LogClass.Cpu, "Address space creation failed, falling back to software page table");
|
||||||
|
|
||||||
|
|
@ -118,47 +89,35 @@ namespace Ryujinx.HLE.HOS
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case MemoryManagerMode.SoftwarePageTable:
|
case MemoryManagerMode.SoftwarePageTable:
|
||||||
{
|
var memoryManager = new MemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||||
var mm = new MemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
processContext = new ArmProcessContext<MemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||||
processContext = new ArmProcessContext<MemoryManager>(pid, cpuEngine, _gpu, mm, addressSpaceSize, for64Bit);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MemoryManagerMode.HostMapped:
|
case MemoryManagerMode.HostMapped:
|
||||||
case MemoryManagerMode.HostMappedUnsafe:
|
case MemoryManagerMode.HostMappedUnsafe:
|
||||||
if (addressSpace == null && asNoMirror == null)
|
if (addressSpace == null)
|
||||||
{
|
{
|
||||||
var memoryManagerHostTracked = new MemoryManagerHostTracked(context.Memory, addressSpaceSize, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler);
|
var memoryManagerHostTracked = new MemoryManagerHostTracked(context.Memory, addressSpaceSize, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler);
|
||||||
processContext = new ArmProcessContext<MemoryManagerHostTracked>(pid, cpuEngine, _gpu, memoryManagerHostTracked, addressSpaceSize, for64Bit);
|
processContext = new ArmProcessContext<MemoryManagerHostTracked>(pid, cpuEngine, _gpu, memoryManagerHostTracked, addressSpaceSize, for64Bit);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool unsafeMode = mode == MemoryManagerMode.HostMappedUnsafe;
|
if (addressSpaceSize != addressSpace.AddressSpaceSize)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Emulation, $"Allocated address space (0x{addressSpace.AddressSpaceSize:X}) is smaller than guest application requirements (0x{addressSpaceSize:X})");
|
||||||
|
}
|
||||||
|
|
||||||
if (addressSpace != null)
|
var memoryManagerHostMapped = new MemoryManagerHostMapped(addressSpace, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler);
|
||||||
{
|
processContext = new ArmProcessContext<MemoryManagerHostMapped>(pid, cpuEngine, _gpu, memoryManagerHostMapped, addressSpace.AddressSpaceSize, for64Bit);
|
||||||
var mm = new MemoryManagerHostMapped(addressSpace, unsafeMode, invalidAccessHandler);
|
|
||||||
processContext = new ArmProcessContext<MemoryManagerHostMapped>(pid, cpuEngine, _gpu, mm, addressSpace.AddressSpaceSize, for64Bit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var mm = new MemoryManagerHostNoMirror(asNoMirror, context.Memory, unsafeMode, invalidAccessHandler);
|
|
||||||
processContext = new ArmProcessContext<MemoryManagerHostNoMirror>(pid, cpuEngine, _gpu, mm, asNoMirror.Size, for64Bit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException($"{nameof(mode)} contains an invalid value: {mode}");
|
throw new InvalidOperationException($"{nameof(mode)} contains an invalid value: {mode}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressSpaceSize != processContext.AddressSpaceSize)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Emulation, $"Allocated address space (0x{processContext.AddressSpaceSize:X}) is smaller than guest application requirements (0x{addressSpaceSize:X})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, _diskCacheSelector);
|
DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, _diskCacheSelector ?? "default");
|
||||||
|
|
||||||
return processContext;
|
return processContext;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
{
|
{
|
||||||
return arrange switch
|
return arrange switch
|
||||||
{
|
{
|
||||||
MemoryArrange.MemoryArrange4GiB or
|
MemoryArrange.MemoryArrange4GiB => 3455 * MiB,
|
||||||
MemoryArrange.MemoryArrange4GiBSystemDev or
|
MemoryArrange.MemoryArrange4GiBSystemDev or
|
||||||
MemoryArrange.MemoryArrange6GiBAppletDev => 3285 * MiB,
|
MemoryArrange.MemoryArrange6GiBAppletDev => 3285 * MiB,
|
||||||
MemoryArrange.MemoryArrange4GiBAppletDev => 2048 * MiB,
|
MemoryArrange.MemoryArrange4GiBAppletDev => 2048 * MiB,
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
MemoryRegion memRegion,
|
MemoryRegion memRegion,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong reservedSize,
|
|
||||||
KMemoryBlockSlabManager slabManager)
|
KMemoryBlockSlabManager slabManager)
|
||||||
{
|
{
|
||||||
_contextId = Context.ContextIdManager.GetId();
|
_contextId = Context.ContextIdManager.GetId();
|
||||||
|
|
@ -120,7 +119,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
memRegion,
|
memRegion,
|
||||||
address,
|
address,
|
||||||
size,
|
size,
|
||||||
reservedSize,
|
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
|
|
@ -163,7 +161,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
MemoryRegion memRegion,
|
MemoryRegion memRegion,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong reservedSize,
|
|
||||||
KMemoryBlockSlabManager slabManager)
|
KMemoryBlockSlabManager slabManager)
|
||||||
{
|
{
|
||||||
ulong endAddr = address + size;
|
ulong endAddr = address + size;
|
||||||
|
|
@ -221,12 +218,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessCreationFlags.AddressSpace64Bit:
|
case ProcessCreationFlags.AddressSpace64Bit:
|
||||||
ulong reservedAddressSpaceSize = _reservedAddressSpaceSize;
|
|
||||||
if (_reservedAddressSpaceSize < addrSpaceEnd)
|
if (_reservedAddressSpaceSize < addrSpaceEnd)
|
||||||
{
|
{
|
||||||
int addressSpaceWidth = (int)ulong.Log2(reservedAddressSpaceSize);
|
int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize);
|
||||||
|
|
||||||
aliasRegion.Size = reservedAddressSpaceSize >= 0x1800000000 ? 0x1000000000 : 1UL << (addressSpaceWidth - 3);
|
aliasRegion.Size = 1UL << (addressSpaceWidth - 3);
|
||||||
heapRegion.Size = 0x180000000;
|
heapRegion.Size = 0x180000000;
|
||||||
stackRegion.Size = 1UL << (addressSpaceWidth - 8);
|
stackRegion.Size = 1UL << (addressSpaceWidth - 8);
|
||||||
tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3);
|
tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3);
|
||||||
|
|
@ -234,8 +230,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
||||||
stackAndTlsIoStart = 0;
|
stackAndTlsIoStart = 0;
|
||||||
stackAndTlsIoEnd = 0;
|
stackAndTlsIoEnd = 0;
|
||||||
AslrRegionStart = Math.Max(reservedSize, 0x8000000);
|
AslrRegionStart = 0x8000000;
|
||||||
addrSpaceEnd = reservedSize + reservedAddressSpaceSize;
|
addrSpaceEnd = 1UL << addressSpaceWidth;
|
||||||
AslrRegionEnd = addrSpaceEnd;
|
AslrRegionEnd = addrSpaceEnd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -246,7 +242,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
tlsIoRegion.Size = 0x1000000000;
|
tlsIoRegion.Size = 0x1000000000;
|
||||||
CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment);
|
CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment);
|
||||||
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
||||||
AslrRegionStart = Math.Max(reservedSize, 0x8000000);
|
AslrRegionStart = 0x8000000;
|
||||||
AslrRegionEnd = AslrRegionStart + 0x7ff8000000;
|
AslrRegionEnd = AslrRegionStart + 0x7ff8000000;
|
||||||
stackAndTlsIoStart = 0;
|
stackAndTlsIoStart = 0;
|
||||||
stackAndTlsIoEnd = 0;
|
stackAndTlsIoEnd = 0;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
interface IProcessContext : IDisposable
|
interface IProcessContext : IDisposable
|
||||||
{
|
{
|
||||||
IVirtualMemoryManager AddressSpace { get; }
|
IVirtualMemoryManager AddressSpace { get; }
|
||||||
ulong ReservedSize { get; }
|
|
||||||
|
|
||||||
ulong AddressSpaceSize { get; }
|
ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
InitializeMemoryManager(creationInfo.Flags);
|
InitializeMemoryManager(creationInfo.Flags);
|
||||||
|
|
||||||
ulong codeAddress = creationInfo.CodeAddress + Context.ReservedSize;
|
ulong codeAddress = creationInfo.CodeAddress;
|
||||||
|
|
||||||
ulong codeSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
ulong codeSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
||||||
|
|
||||||
|
|
@ -155,7 +155,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
memRegion,
|
memRegion,
|
||||||
codeAddress,
|
codeAddress,
|
||||||
codeSize,
|
codeSize,
|
||||||
Context.ReservedSize,
|
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
|
|
@ -191,8 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
KResourceLimit resourceLimit,
|
KResourceLimit resourceLimit,
|
||||||
MemoryRegion memRegion,
|
MemoryRegion memRegion,
|
||||||
IProcessContextFactory contextFactory,
|
IProcessContextFactory contextFactory,
|
||||||
ThreadStart customThreadStart = null,
|
ThreadStart customThreadStart = null)
|
||||||
ulong entrypointOffset = 0UL)
|
|
||||||
{
|
{
|
||||||
ResourceLimit = resourceLimit;
|
ResourceLimit = resourceLimit;
|
||||||
_memRegion = memRegion;
|
_memRegion = memRegion;
|
||||||
|
|
@ -246,7 +244,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
InitializeMemoryManager(creationInfo.Flags);
|
InitializeMemoryManager(creationInfo.Flags);
|
||||||
|
|
||||||
ulong codeAddress = creationInfo.CodeAddress + Context.ReservedSize;
|
ulong codeAddress = creationInfo.CodeAddress;
|
||||||
|
|
||||||
ulong codeSize = codePagesCount * KPageTableBase.PageSize;
|
ulong codeSize = codePagesCount * KPageTableBase.PageSize;
|
||||||
|
|
||||||
|
|
@ -256,7 +254,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
memRegion,
|
memRegion,
|
||||||
codeAddress,
|
codeAddress,
|
||||||
codeSize,
|
codeSize,
|
||||||
Context.ReservedSize,
|
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
|
|
@ -302,8 +299,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
}
|
}
|
||||||
|
|
||||||
_entrypoint += entrypointOffset;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,12 +343,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
Flags = creationInfo.Flags;
|
Flags = creationInfo.Flags;
|
||||||
TitleId = creationInfo.TitleId;
|
TitleId = creationInfo.TitleId;
|
||||||
_entrypoint = creationInfo.CodeAddress + Context.ReservedSize;
|
_entrypoint = creationInfo.CodeAddress;
|
||||||
_imageSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
_imageSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
||||||
|
|
||||||
// 19.0.0+ sets all regions to same size
|
switch (Flags & ProcessCreationFlags.AddressSpaceMask)
|
||||||
_memoryUsageCapacity = MemoryManager.HeapRegionEnd - MemoryManager.HeapRegionStart;
|
|
||||||
/*switch (Flags & ProcessCreationFlags.AddressSpaceMask)
|
|
||||||
{
|
{
|
||||||
case ProcessCreationFlags.AddressSpace32Bit:
|
case ProcessCreationFlags.AddressSpace32Bit:
|
||||||
case ProcessCreationFlags.AddressSpace64BitDeprecated:
|
case ProcessCreationFlags.AddressSpace64BitDeprecated:
|
||||||
|
|
@ -370,7 +363,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
|
throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
|
||||||
}*/
|
}
|
||||||
|
|
||||||
GenerateRandomEntropy();
|
GenerateRandomEntropy();
|
||||||
|
|
||||||
|
|
@ -548,7 +541,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Trying to start a process with an invalid state!");
|
throw new InvalidOperationException("Trying to start a process with an invalid state!");
|
||||||
}
|
}
|
||||||
// TODO: after 19.0.0+ alignment is not needed
|
|
||||||
ulong stackSizeRounded = BitUtils.AlignUp<ulong>(stackSize, KPageTableBase.PageSize);
|
ulong stackSizeRounded = BitUtils.AlignUp<ulong>(stackSize, KPageTableBase.PageSize);
|
||||||
|
|
||||||
ulong neededSize = stackSizeRounded + _imageSize;
|
ulong neededSize = stackSizeRounded + _imageSize;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
class ProcessContext : IProcessContext
|
class ProcessContext : IProcessContext
|
||||||
{
|
{
|
||||||
public IVirtualMemoryManager AddressSpace { get; }
|
public IVirtualMemoryManager AddressSpace { get; }
|
||||||
public ulong ReservedSize => 0UL;
|
|
||||||
|
|
||||||
public ulong AddressSpaceSize { get; }
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
IsAnyInternetRequestAccepted = true, // NOTE: Why not accept any internet request?
|
IsAnyInternetRequestAccepted = true, // NOTE: Why not accept any internet request?
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!PlatformInfo.IsBionic)
|
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;
|
||||||
{
|
|
||||||
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneralServiceManager.Add(_generalServiceDetail);
|
GeneralServiceManager.Add(_generalServiceDetail);
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
||||||
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
|
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
|
||||||
|
|
||||||
"KenjinxNetwork"u8.CopyTo(networkProfile.Name.AsSpan());
|
"RyujinxNetwork"u8.CopyTo(networkProfile.Name.AsSpan());
|
||||||
|
|
||||||
context.Memory.Write(networkProfileDataPosition, networkProfile);
|
context.Memory.Write(networkProfileDataPosition, networkProfile);
|
||||||
|
|
||||||
|
|
@ -199,10 +196,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
{
|
{
|
||||||
if (isDisposing)
|
if (isDisposing)
|
||||||
{
|
{
|
||||||
if (!PlatformInfo.IsBionic)
|
NetworkChange.NetworkAddressChanged -= LocalInterfaceCacheHandler;
|
||||||
{
|
|
||||||
NetworkChange.NetworkAddressChanged -= LocalInterfaceCacheHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
|
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Pm.Types;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Pm
|
namespace Ryujinx.HLE.HOS.Services.Pm
|
||||||
{
|
{
|
||||||
[Service("pm:bm")]
|
[Service("pm:bm")]
|
||||||
class IBootModeInterface : IpcService
|
class IBootModeInterface : IpcService
|
||||||
{
|
{
|
||||||
public IBootModeInterface(ServiceCtx context) { }
|
public IBootModeInterface(ServiceCtx context) { }
|
||||||
|
|
||||||
[CommandCmif(0)]
|
|
||||||
// GetBootMode() -> u32
|
|
||||||
public ResultCode GetBootMode(ServiceCtx context)
|
|
||||||
{
|
|
||||||
context.ResponseData.Write((uint)BootMode.Normal);
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
namespace Ryujinx.HLE.HOS.Services.Pm.Types
|
|
||||||
{
|
|
||||||
enum BootMode : uint
|
|
||||||
{
|
|
||||||
Normal = 0,
|
|
||||||
Maintenance = 1,
|
|
||||||
SafeMode = 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -244,15 +244,6 @@ namespace Ryujinx.HLE.HOS.Services.Settings
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandCmif(68)]
|
|
||||||
// GetSerialNumber() -> buffer<nn::settings::system::SerialNumber, 0x16>
|
|
||||||
public ResultCode GetSerialNumber(ServiceCtx context)
|
|
||||||
{
|
|
||||||
context.ResponseData.Write(Encoding.ASCII.GetBytes("RYU00000000000"));
|
|
||||||
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandCmif(77)]
|
[CommandCmif(77)]
|
||||||
// GetDeviceNickName() -> buffer<nn::settings::system::DeviceNickName, 0x16>
|
// GetDeviceNickName() -> buffer<nn::settings::system::DeviceNickName, 0x16>
|
||||||
public ResultCode GetDeviceNickName(ServiceCtx context)
|
public ResultCode GetDeviceNickName(ServiceCtx context)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Services.Spl.Types;
|
using Ryujinx.HLE.HOS.Services.Spl.Types;
|
||||||
|
|
@ -52,14 +51,6 @@ namespace Ryujinx.HLE.HOS.Services.Spl
|
||||||
|
|
||||||
context.ResponseData.Write(configValue);
|
context.ResponseData.Write(configValue);
|
||||||
|
|
||||||
if(PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
if (result == SmcResult.Success)
|
|
||||||
{
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ResultCode)((int)result << 9) | ResultCode.ModuleId;
|
return (ResultCode)((int)result << 9) | ResultCode.ModuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,13 +82,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
||||||
// Apply Nsos patches.
|
// Apply Nsos patches.
|
||||||
device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(programId, nsoExecutables);
|
device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(programId, nsoExecutables);
|
||||||
|
|
||||||
// Don't use PTC if ExeFS files have been replaced.
|
|
||||||
bool enablePtc = device.System.EnablePtc && !modLoadResult.Modified;
|
|
||||||
if (!enablePtc)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Ptc, "Detected unsupported ExeFs modifications. PTC disabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
string programName = "";
|
string programName = "";
|
||||||
|
|
||||||
if (!isHomebrew && programId > 0x010000000000FFFF)
|
if (!isHomebrew && programId > 0x010000000000FFFF)
|
||||||
|
|
@ -121,7 +114,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
||||||
device.System.KernelContext,
|
device.System.KernelContext,
|
||||||
metaLoader,
|
metaLoader,
|
||||||
nacpData,
|
nacpData,
|
||||||
enablePtc,
|
device.System.EnablePtc,
|
||||||
modLoadResult.Hash,
|
modLoadResult.Hash,
|
||||||
true,
|
true,
|
||||||
programName,
|
programName,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using LibHac.Account;
|
using LibHac.Account;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using LibHac.Fs.Fsa;
|
using LibHac.Fs.Fsa;
|
||||||
|
|
@ -11,7 +11,6 @@ using LibHac.Tools.FsSystem;
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Cpu.Nce;
|
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
|
@ -22,7 +21,6 @@ using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||||
using Ryujinx.Horizon.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Horizon.Sdk.Arp;
|
using Ryujinx.Horizon.Sdk.Arp;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using ApplicationId = LibHac.Ncm.ApplicationId;
|
using ApplicationId = LibHac.Ncm.ApplicationId;
|
||||||
|
|
||||||
|
|
@ -252,7 +250,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
ulong argsStart = 0;
|
ulong argsStart = 0;
|
||||||
uint argsSize = 0;
|
uint argsSize = 0;
|
||||||
ulong codeStart = ((meta.Flags & 1) != 0 ? 0x8000000UL : 0x200000UL) + CodeStartOffset;
|
ulong codeStart = ((meta.Flags & 1) != 0 ? 0x8000000UL : 0x200000UL) + CodeStartOffset;
|
||||||
ulong codeSize = 0;
|
uint codeSize = 0;
|
||||||
|
|
||||||
string[] buildIds = new string[executables.Length];
|
string[] buildIds = new string[executables.Length];
|
||||||
|
|
||||||
|
|
@ -266,7 +264,6 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
}).ToUpper();
|
}).ToUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
NceCpuCodePatch[] nsoPatch = new NceCpuCodePatch[executables.Length];
|
|
||||||
ulong[] nsoBase = new ulong[executables.Length];
|
ulong[] nsoBase = new ulong[executables.Length];
|
||||||
|
|
||||||
for (int index = 0; index < executables.Length; index++)
|
for (int index = 0; index < executables.Length; index++)
|
||||||
|
|
@ -291,16 +288,6 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
|
|
||||||
nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
|
nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
|
||||||
|
|
||||||
bool for64Bit = ((ProcessCreationFlags)meta.Flags).HasFlag(ProcessCreationFlags.Is64Bit);
|
|
||||||
|
|
||||||
NceCpuCodePatch codePatch = ArmProcessContextFactory.CreateCodePatchForNce(context, for64Bit, nso.Text);
|
|
||||||
nsoPatch[index] = codePatch;
|
|
||||||
|
|
||||||
if (codePatch != null)
|
|
||||||
{
|
|
||||||
codeSize += codePatch.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsoBase[index] = codeStart + codeSize;
|
nsoBase[index] = codeStart + codeSize;
|
||||||
|
|
||||||
codeSize += nsoSize;
|
codeSize += nsoSize;
|
||||||
|
|
@ -402,8 +389,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
MemoryMarshal.Cast<byte, uint>(npdm.KernelCapabilityData),
|
MemoryMarshal.Cast<byte, uint>(npdm.KernelCapabilityData),
|
||||||
resourceLimit,
|
resourceLimit,
|
||||||
memoryRegion,
|
memoryRegion,
|
||||||
processContextFactory,
|
processContextFactory);
|
||||||
entrypointOffset: nsoPatch[0]?.Size ?? 0UL);
|
|
||||||
|
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
|
|
@ -414,12 +400,9 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
|
|
||||||
for (int index = 0; index < executables.Length; index++)
|
for (int index = 0; index < executables.Length; index++)
|
||||||
{
|
{
|
||||||
ulong nsoBaseAddress = process.Context.ReservedSize + nsoBase[index];
|
Logger.Info?.Print(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}...");
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Loader, $"Loading image {index} at 0x{nsoBaseAddress:x16}...");
|
|
||||||
|
|
||||||
result = LoadIntoMemory(process, executables[index], nsoBaseAddress, nsoPatch[index]);
|
|
||||||
|
|
||||||
|
result = LoadIntoMemory(process, executables[index], nsoBase[index]);
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
@ -477,7 +460,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
return processResult;
|
return processResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress, NceCpuCodePatch codePatch = null)
|
public static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress)
|
||||||
{
|
{
|
||||||
ulong textStart = baseAddress + image.TextOffset;
|
ulong textStart = baseAddress + image.TextOffset;
|
||||||
ulong roStart = baseAddress + image.RoOffset;
|
ulong roStart = baseAddress + image.RoOffset;
|
||||||
|
|
@ -497,11 +480,6 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||||
|
|
||||||
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
||||||
|
|
||||||
if (codePatch != null)
|
|
||||||
{
|
|
||||||
codePatch.Write(process.CpuMemory, baseAddress - codePatch.Size, textStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
Result SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
@ -427,7 +426,7 @@ namespace Ryujinx.Memory
|
||||||
return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
|
return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic;
|
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
|
@ -13,7 +12,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
return MemoryManagementWindows.Allocate((IntPtr)size);
|
return MemoryManagementWindows.Allocate((IntPtr)size);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
return MemoryManagementUnix.Allocate(size, forJit);
|
return MemoryManagementUnix.Allocate(size, forJit);
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +28,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
return MemoryManagementWindows.Reserve((IntPtr)size, viewCompatible);
|
return MemoryManagementWindows.Reserve((IntPtr)size, viewCompatible);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
return MemoryManagementUnix.Reserve(size, forJit);
|
return MemoryManagementUnix.Reserve(size, forJit);
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +44,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.Commit(address, (IntPtr)size);
|
MemoryManagementWindows.Commit(address, (IntPtr)size);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.Commit(address, size, forJit);
|
MemoryManagementUnix.Commit(address, size, forJit);
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +60,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.Decommit(address, (IntPtr)size);
|
MemoryManagementWindows.Decommit(address, (IntPtr)size);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.Decommit(address, size);
|
MemoryManagementUnix.Decommit(address, size);
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +76,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size, owner);
|
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size, owner);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.MapView(sharedMemory, srcOffset, address, size);
|
MemoryManagementUnix.MapView(sharedMemory, srcOffset, address, size);
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +92,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size, owner);
|
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size, owner);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.UnmapView(address, size);
|
MemoryManagementUnix.UnmapView(address, size);
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +110,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
result = MemoryManagementWindows.Reprotect(address, (IntPtr)size, permission, forView);
|
result = MemoryManagementWindows.Reprotect(address, (IntPtr)size, permission, forView);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
result = MemoryManagementUnix.Reprotect(address, size, permission);
|
result = MemoryManagementUnix.Reprotect(address, size, permission);
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +131,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
return MemoryManagementWindows.Free(address, (IntPtr)size);
|
return MemoryManagementWindows.Free(address, (IntPtr)size);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
return MemoryManagementUnix.Free(address);
|
return MemoryManagementUnix.Free(address);
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +147,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
return MemoryManagementWindows.CreateSharedMemory((IntPtr)size, reserve);
|
return MemoryManagementWindows.CreateSharedMemory((IntPtr)size, reserve);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
return MemoryManagementUnix.CreateSharedMemory(size, reserve);
|
return MemoryManagementUnix.CreateSharedMemory(size, reserve);
|
||||||
}
|
}
|
||||||
|
|
@ -164,7 +163,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.DestroySharedMemory(handle);
|
MemoryManagementWindows.DestroySharedMemory(handle);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.DestroySharedMemory(handle);
|
MemoryManagementUnix.DestroySharedMemory(handle);
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +179,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
return MemoryManagementWindows.MapSharedMemory(handle);
|
return MemoryManagementWindows.MapSharedMemory(handle);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
return MemoryManagementUnix.MapSharedMemory(handle, size);
|
return MemoryManagementUnix.MapSharedMemory(handle, size);
|
||||||
}
|
}
|
||||||
|
|
@ -196,7 +195,7 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.UnmapSharedMemory(address);
|
MemoryManagementWindows.UnmapSharedMemory(address);
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || PlatformInfo.IsBionic)
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
MemoryManagementUnix.UnmapSharedMemory(address, size);
|
MemoryManagementUnix.UnmapSharedMemory(address, size);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
@ -11,8 +9,6 @@ namespace Ryujinx.Memory
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
[SupportedOSPlatform("android")]
|
|
||||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
|
|
||||||
static class MemoryManagementUnix
|
static class MemoryManagementUnix
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<IntPtr, ulong> _allocations = new();
|
private static readonly ConcurrentDictionary<IntPtr, ulong> _allocations = new();
|
||||||
|
|
@ -161,24 +157,6 @@ namespace Ryujinx.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (PlatformInfo.IsBionic)
|
|
||||||
{
|
|
||||||
byte[] memName = "Ryujinx-XXXXXX"u8.ToArray();
|
|
||||||
|
|
||||||
Logger.Debug?.Print(LogClass.Cpu, $"Creating Android SharedMemory of size:{size}");
|
|
||||||
|
|
||||||
fixed (byte* pMemName = memName)
|
|
||||||
{
|
|
||||||
fd = ASharedMemory_create((IntPtr)pMemName, (nuint)size);
|
|
||||||
if (fd <= 0)
|
|
||||||
{
|
|
||||||
throw new OutOfMemoryException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASharedMemory_create handle ftruncate for us.
|
|
||||||
return (IntPtr)fd;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte[] fileName = "/dev/shm/Ryujinx-XXXXXX"u8.ToArray();
|
byte[] fileName = "/dev/shm/Ryujinx-XXXXXX"u8.ToArray();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
@ -90,9 +89,6 @@ namespace Ryujinx.Memory
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
public static partial int shm_unlink(IntPtr name);
|
public static partial int shm_unlink(IntPtr name);
|
||||||
|
|
||||||
[DllImport("android")]
|
|
||||||
internal static extern int ASharedMemory_create(IntPtr name, nuint size);
|
|
||||||
|
|
||||||
private static int MmapFlagsToSystemFlags(MmapFlags flags)
|
private static int MmapFlagsToSystemFlags(MmapFlags flags)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
@ -114,7 +110,7 @@ namespace Ryujinx.Memory
|
||||||
|
|
||||||
if (flags.HasFlag(MmapFlags.MAP_ANONYMOUS))
|
if (flags.HasFlag(MmapFlags.MAP_ANONYMOUS))
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsLinux() || PlatformInfo.IsBionic)
|
if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
result |= MAP_ANONYMOUS_LINUX_GENERIC;
|
result |= MAP_ANONYMOUS_LINUX_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +126,7 @@ namespace Ryujinx.Memory
|
||||||
|
|
||||||
if (flags.HasFlag(MmapFlags.MAP_NORESERVE))
|
if (flags.HasFlag(MmapFlags.MAP_NORESERVE))
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsLinux() || PlatformInfo.IsBionic)
|
if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
result |= MAP_NORESERVE_LINUX_GENERIC;
|
result |= MAP_NORESERVE_LINUX_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +142,7 @@ namespace Ryujinx.Memory
|
||||||
|
|
||||||
if (flags.HasFlag(MmapFlags.MAP_UNLOCKED))
|
if (flags.HasFlag(MmapFlags.MAP_UNLOCKED))
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsLinux() || PlatformInfo.IsBionic)
|
if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
result |= MAP_UNLOCKED_LINUX_GENERIC;
|
result |= MAP_UNLOCKED_LINUX_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue