mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
rework TLS allocations, more HLE's, increase import loop history
This commit is contained in:
@@ -231,9 +231,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
ProbeReturnRip(num7, num);
|
ProbeReturnRip(num7, num);
|
||||||
Console.Error.Flush();
|
Console.Error.Flush();
|
||||||
}
|
}
|
||||||
ProbeReturnRip(0x0000000800EA020Eul, 999001);
|
|
||||||
ProbeReturnRip(0x0000000800EA0213ul, 999002);
|
|
||||||
ProbeReturnRip(0x0000000800EA040Aul, 999003);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OrbisGen2Result orbisGen2Result;
|
OrbisGen2Result orbisGen2Result;
|
||||||
@@ -426,7 +423,20 @@ public sealed partial class DirectExecutionBackend
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int num2 = CountDistinctImportLoopValuesFromTail(_importLoopReturnRips, sampleCount, 3);
|
int num2 = CountDistinctImportLoopValuesFromTail(_importLoopReturnRips, sampleCount, 3);
|
||||||
return num2 <= 2;
|
if (num2 > 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int num3 = Math.Min(_importLoopSignatureCount, Math.Max(sampleCount * 8, ImportLoopWideDiversityWindow));
|
||||||
|
if (num3 <= sampleCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (CountDistinctImportLoopValuesFromTail(_importLoopNidHashes, num3, 3) > 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return CountDistinctImportLoopValuesFromTail(_importLoopReturnRips, num3, 3) <= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CountDistinctImportLoopValuesFromTail(ulong[] source, int sampleCount, int stopAfter)
|
private int CountDistinctImportLoopValuesFromTail(ulong[] source, int sampleCount, int stopAfter)
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ namespace SharpEmu.Core.Cpu.Native;
|
|||||||
|
|
||||||
public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, IDisposable
|
public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, IDisposable
|
||||||
{
|
{
|
||||||
|
private const int ImportLoopHistoryLength = 2048;
|
||||||
|
|
||||||
|
private const int ImportLoopWideDiversityWindow = 768;
|
||||||
|
|
||||||
private readonly struct ImportStubEntry
|
private readonly struct ImportStubEntry
|
||||||
{
|
{
|
||||||
public ulong Address { get; }
|
public ulong Address { get; }
|
||||||
@@ -89,7 +93,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
|
|
||||||
private const uint PAGE_EXECUTE_READ = 32u;
|
private const uint PAGE_EXECUTE_READ = 32u;
|
||||||
|
|
||||||
private const int TlsHandlerRegionSize = 4096;
|
private const int TlsHandlerRegionSize = 16384;
|
||||||
|
|
||||||
private const ulong TlsModuleAllocStart = 140726751354880uL;
|
private const ulong TlsModuleAllocStart = 140726751354880uL;
|
||||||
|
|
||||||
@@ -179,11 +183,11 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
|
|
||||||
private ulong _entryReturnSentinelRip;
|
private ulong _entryReturnSentinelRip;
|
||||||
|
|
||||||
private readonly ulong[] _importLoopSignatures = new ulong[192];
|
private readonly ulong[] _importLoopSignatures = new ulong[ImportLoopHistoryLength];
|
||||||
|
|
||||||
private readonly ulong[] _importLoopNidHashes = new ulong[192];
|
private readonly ulong[] _importLoopNidHashes = new ulong[ImportLoopHistoryLength];
|
||||||
|
|
||||||
private readonly ulong[] _importLoopReturnRips = new ulong[192];
|
private readonly ulong[] _importLoopReturnRips = new ulong[ImportLoopHistoryLength];
|
||||||
|
|
||||||
private int _importLoopSignatureCount;
|
private int _importLoopSignatureCount;
|
||||||
|
|
||||||
@@ -601,14 +605,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
{
|
{
|
||||||
return exportName switch
|
return exportName switch
|
||||||
{
|
{
|
||||||
"_init_env" or
|
|
||||||
"atexit" or
|
|
||||||
"strlen" or
|
|
||||||
"strnlen" or
|
|
||||||
"strcmp" or
|
|
||||||
"strncmp" or
|
|
||||||
"strcpy" or
|
|
||||||
"strncpy" or
|
|
||||||
"memcpy" or
|
"memcpy" or
|
||||||
"memmove" or
|
"memmove" or
|
||||||
"memset" or
|
"memset" or
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IDisposable
|
|||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
private static extern bool VirtualProtect(void* lpAddress, nuint dwSize, uint flNewProtect, out uint lpflOldProtect);
|
private static extern bool VirtualProtect(void* lpAddress, nuint dwSize, uint flNewProtect, out uint lpflOldProtect);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern nuint VirtualQuery(void* lpAddress, out MemoryBasicInformation64 lpBuffer, nuint dwLength);
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
private static extern void FlushInstructionCache(void* hProcess, void* lpBaseAddress, nuint dwSize);
|
private static extern void FlushInstructionCache(void* hProcess, void* lpBaseAddress, nuint dwSize);
|
||||||
|
|
||||||
@@ -351,6 +354,11 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IDisposable
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!EnsureRangeCommitted((ulong)srcPtr, (ulong)destination.Length, region))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!TryTemporarilyProtectForRead((ulong)srcPtr, (ulong)destination.Length, region, out var touchedPages))
|
if (!TryTemporarilyProtectForRead((ulong)srcPtr, (ulong)destination.Length, region, out var touchedPages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -389,6 +397,11 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IDisposable
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!EnsureRangeCommitted((ulong)destPtr, (ulong)source.Length, region))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!VirtualProtect(destPtr, (nuint)source.Length, PAGE_EXECUTE_READWRITE, out var oldProtect))
|
if (!VirtualProtect(destPtr, (nuint)source.Length, PAGE_EXECUTE_READWRITE, out var oldProtect))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -494,6 +507,48 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IDisposable
|
|||||||
return protection is PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY;
|
return protection is PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static uint GetCommitProtection(MemoryRegion region)
|
||||||
|
{
|
||||||
|
return region.IsExecutable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static unsafe bool EnsureRangeCommitted(ulong address, ulong size, MemoryRegion region)
|
||||||
|
{
|
||||||
|
if (size == 0 || !region.IsReservedOnly)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var startPage = AlignDown(address, PageSize);
|
||||||
|
var endPage = AlignUp(address + size, PageSize);
|
||||||
|
var commitProtection = GetCommitProtection(region);
|
||||||
|
|
||||||
|
for (var pageAddress = startPage; pageAddress < endPage; pageAddress += PageSize)
|
||||||
|
{
|
||||||
|
if (VirtualQuery((void*)pageAddress, out var info, (nuint)sizeof(MemoryBasicInformation64)) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.State == MEM_COMMIT)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.State != MEM_RESERVE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VirtualAlloc((void*)pageAddress, (nuint)PageSize, MEM_COMMIT, commitProtection) == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryTemporarilyProtectForRead(
|
private bool TryTemporarilyProtectForRead(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
@@ -558,4 +613,17 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IDisposable
|
|||||||
public bool IsReservedOnly { get; set; }
|
public bool IsReservedOnly { get; set; }
|
||||||
public uint Protection { get; set; }
|
public uint Protection { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct MemoryBasicInformation64
|
||||||
|
{
|
||||||
|
public ulong BaseAddress;
|
||||||
|
public ulong AllocationBase;
|
||||||
|
public uint AllocationProtect;
|
||||||
|
public uint Alignment1;
|
||||||
|
public ulong RegionSize;
|
||||||
|
public uint State;
|
||||||
|
public uint Protect;
|
||||||
|
public uint Type;
|
||||||
|
public uint Alignment2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,14 +258,14 @@ public static class KernelPthreadCompatExports
|
|||||||
ExportName = "scePthreadCondSignal",
|
ExportName = "scePthreadCondSignal",
|
||||||
Target = Generation.Gen4 | Generation.Gen5,
|
Target = Generation.Gen4 | Generation.Gen5,
|
||||||
LibraryName = "libKernel")]
|
LibraryName = "libKernel")]
|
||||||
public static int PthreadCondSignal(CpuContext ctx) => PthreadCondSignalCore(ctx[CpuRegister.Rdi], broadcast: false);
|
public static int PthreadCondSignal(CpuContext ctx) => PthreadCondSignalCore(ctx, ctx[CpuRegister.Rdi], broadcast: false);
|
||||||
|
|
||||||
[SysAbiExport(
|
[SysAbiExport(
|
||||||
Nid = "JGgj7Uvrl+A",
|
Nid = "JGgj7Uvrl+A",
|
||||||
ExportName = "scePthreadCondBroadcast",
|
ExportName = "scePthreadCondBroadcast",
|
||||||
Target = Generation.Gen4 | Generation.Gen5,
|
Target = Generation.Gen4 | Generation.Gen5,
|
||||||
LibraryName = "libKernel")]
|
LibraryName = "libKernel")]
|
||||||
public static int PthreadCondBroadcast(CpuContext ctx) => PthreadCondSignalCore(ctx[CpuRegister.Rdi], broadcast: true);
|
public static int PthreadCondBroadcast(CpuContext ctx) => PthreadCondSignalCore(ctx, ctx[CpuRegister.Rdi], broadcast: true);
|
||||||
|
|
||||||
[SysAbiExport(
|
[SysAbiExport(
|
||||||
Nid = "Op8TBGY5KHg",
|
Nid = "Op8TBGY5KHg",
|
||||||
@@ -279,7 +279,7 @@ public static class KernelPthreadCompatExports
|
|||||||
ExportName = "pthread_cond_broadcast",
|
ExportName = "pthread_cond_broadcast",
|
||||||
Target = Generation.Gen4 | Generation.Gen5,
|
Target = Generation.Gen4 | Generation.Gen5,
|
||||||
LibraryName = "libKernel")]
|
LibraryName = "libKernel")]
|
||||||
public static int PosixPthreadCondBroadcast(CpuContext ctx) => PthreadCondSignalCore(ctx[CpuRegister.Rdi], broadcast: true);
|
public static int PosixPthreadCondBroadcast(CpuContext ctx) => PthreadCondSignalCore(ctx, ctx[CpuRegister.Rdi], broadcast: true);
|
||||||
|
|
||||||
[SysAbiExport(
|
[SysAbiExport(
|
||||||
Nid = "m5-2bsNfv7s",
|
Nid = "m5-2bsNfv7s",
|
||||||
@@ -901,14 +901,14 @@ public static class KernelPthreadCompatExports
|
|||||||
return waitResult;
|
return waitResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int PthreadCondSignalCore(ulong condAddress, bool broadcast)
|
private static int PthreadCondSignalCore(CpuContext ctx, ulong condAddress, bool broadcast)
|
||||||
{
|
{
|
||||||
if (condAddress == 0)
|
if (condAddress == 0)
|
||||||
{
|
{
|
||||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryResolveCondState(null, condAddress, createIfZero: false, out _, out var state))
|
if (!TryResolveCondState(ctx, condAddress, createIfZero: true, out _, out var state))
|
||||||
{
|
{
|
||||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user