This commit is contained in:
RSDuck 2024-10-31 21:27:03 +01:00
parent 0a34a21ee7
commit c1f43a66c2
7 changed files with 245 additions and 106 deletions

View File

@ -234,8 +234,6 @@ ARMJIT::~ARMJIT() noexcept
{ {
JitEnableWrite(); JitEnableWrite();
ResetBlockCache(); ResetBlockCache();
ARMJIT_Global::DeInit();
} }
void ARMJIT::Reset() noexcept void ARMJIT::Reset() noexcept
@ -477,10 +475,8 @@ ARMJIT::ARMJIT(melonDS::NDS& nds, std::optional<JITArgs> jit) noexcept :
MaxBlockSize(jit.has_value() ? std::clamp(jit->MaxBlockSize, 1u, 32u) : 32), MaxBlockSize(jit.has_value() ? std::clamp(jit->MaxBlockSize, 1u, 32u) : 32),
LiteralOptimizations(jit.has_value() ? jit->LiteralOptimizations : false), LiteralOptimizations(jit.has_value() ? jit->LiteralOptimizations : false),
BranchOptimizations(jit.has_value() ? jit->BranchOptimizations : false), BranchOptimizations(jit.has_value() ? jit->BranchOptimizations : false),
FastMemory(jit.has_value() ? jit->FastMemory : false) FastMemory((jit.has_value() ? jit->FastMemory : false) && ARMJIT_Memory::IsFastMemSupported())
{ {}
ARMJIT_Global::Init();
}
void ARMJIT::RetireJitBlock(JitBlock* block) noexcept void ARMJIT::RetireJitBlock(JitBlock* block) noexcept
{ {
@ -498,6 +494,7 @@ void ARMJIT::RetireJitBlock(JitBlock* block) noexcept
void ARMJIT::SetJITArgs(JITArgs args) noexcept void ARMJIT::SetJITArgs(JITArgs args) noexcept
{ {
args.FastMemory = args.FastMemory && ARMJIT_Memory::IsFastMemSupported();
args.MaxBlockSize = std::clamp(args.MaxBlockSize, 1u, 32u); args.MaxBlockSize = std::clamp(args.MaxBlockSize, 1u, 32u);
if (MaxBlockSize != args.MaxBlockSize if (MaxBlockSize != args.MaxBlockSize
@ -514,36 +511,22 @@ void ARMJIT::SetJITArgs(JITArgs args) noexcept
void ARMJIT::SetMaxBlockSize(int size) noexcept void ARMJIT::SetMaxBlockSize(int size) noexcept
{ {
size = std::clamp(size, 1, 32); SetJITArgs(JITArgs{static_cast<unsigned>(size), LiteralOptimizations, LiteralOptimizations, FastMemory});
if (size != MaxBlockSize)
ResetBlockCache();
MaxBlockSize = size;
} }
void ARMJIT::SetLiteralOptimizations(bool enabled) noexcept void ARMJIT::SetLiteralOptimizations(bool enabled) noexcept
{ {
if (LiteralOptimizations != enabled) SetJITArgs(JITArgs{static_cast<unsigned>(MaxBlockSize), enabled, BranchOptimizations, FastMemory});
ResetBlockCache();
LiteralOptimizations = enabled;
} }
void ARMJIT::SetBranchOptimizations(bool enabled) noexcept void ARMJIT::SetBranchOptimizations(bool enabled) noexcept
{ {
if (BranchOptimizations != enabled) SetJITArgs(JITArgs{static_cast<unsigned>(MaxBlockSize), LiteralOptimizations, enabled, FastMemory});
ResetBlockCache();
BranchOptimizations = enabled;
} }
void ARMJIT::SetFastMemory(bool enabled) noexcept void ARMJIT::SetFastMemory(bool enabled) noexcept
{ {
if (FastMemory != enabled) SetJITArgs(JITArgs{static_cast<unsigned>(MaxBlockSize), LiteralOptimizations, BranchOptimizations, enabled});
ResetBlockCache();
FastMemory = enabled;
} }
void ARMJIT::CompileBlock(ARM* cpu) noexcept void ARMJIT::CompileBlock(ARM* cpu) noexcept

View File

@ -9,6 +9,7 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <mutex> #include <mutex>
@ -20,33 +21,43 @@ namespace ARMJIT_Global
std::mutex globalMutex; std::mutex globalMutex;
#ifndef __APPLE__
static constexpr size_t NumCodeMemSlices = 4; static constexpr size_t NumCodeMemSlices = 4;
static constexpr size_t CodeMemoryAlignedSize = NumCodeMemSlices * CodeMemorySliceSize;
// I haven't heard of pages larger than 16 KB // I haven't heard of pages larger than 16 KB
alignas(16*1024) u8 CodeMemory[NumCodeMemSlices * CodeMemorySliceSize]; u8 CodeMemory[CodeMemoryAlignedSize + 16*1024];
u32 AvailableCodeMemSlices = (1 << NumCodeMemSlices) - 1; u32 AvailableCodeMemSlices = (1 << NumCodeMemSlices) - 1;
u8* GetAlignedCodeMemoryStart()
{
return reinterpret_cast<u8*>((reinterpret_cast<intptr_t>(CodeMemory) + (16*1024-1)) & ~static_cast<intptr_t>(16*1024-1));
}
#endif
int RefCounter = 0; int RefCounter = 0;
void* AllocateCodeMem() void* AllocateCodeMem()
{ {
std::lock_guard guard(globalMutex); std::lock_guard guard(globalMutex);
#ifndef __APPLE__
if (AvailableCodeMemSlices) if (AvailableCodeMemSlices)
{ {
int slice = __builtin_ctz(AvailableCodeMemSlices); int slice = __builtin_ctz(AvailableCodeMemSlices);
AvailableCodeMemSlices &= ~(1 << slice); AvailableCodeMemSlices &= ~(1 << slice);
//printf("allocating slice %d\n", slice); //printf("allocating slice %d\n", slice);
return &CodeMemory[slice * CodeMemorySliceSize]; return &GetAlignedCodeMemoryStart()[slice * CodeMemorySliceSize];
} }
#endif
// allocate // allocate
#ifdef _WIN32 #ifdef _WIN32
// FIXME return VirtualAlloc(nullptr, CodeMemorySliceSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else #else
//printf("mmaping...\n"); //printf("mmaping...\n");
return mmap(NULL, CodeMemorySliceSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); return mmap(nullptr, CodeMemorySliceSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif #endif
} }
@ -56,7 +67,7 @@ void FreeCodeMem(void* codeMem)
for (int i = 0; i < NumCodeMemSlices; i++) for (int i = 0; i < NumCodeMemSlices; i++)
{ {
if (codeMem == &CodeMemory[CodeMemorySliceSize * i]) if (codeMem == &GetAlignedCodeMemoryStart()[CodeMemorySliceSize * i])
{ {
//printf("freeing slice\n"); //printf("freeing slice\n");
AvailableCodeMemSlices |= 1 << i; AvailableCodeMemSlices |= 1 << i;
@ -65,7 +76,7 @@ void FreeCodeMem(void* codeMem)
} }
#ifdef _WIN32 #ifdef _WIN32
// FIXME VirtualFree(codeMem, CodeMemorySliceSize, MEM_RELEASE|MEM_DECOMMIT);
#else #else
munmap(codeMem, CodeMemorySliceSize); munmap(codeMem, CodeMemorySliceSize);
#endif #endif
@ -80,11 +91,11 @@ void Init()
{ {
#ifdef _WIN32 #ifdef _WIN32
DWORD dummy; DWORD dummy;
VirtualProtect(CodeMemory, sizeof(CodeMemory), PAGE_EXECUTE_READWRITE, &dummy); VirtualProtect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PAGE_EXECUTE_READWRITE, &dummy);
#elif defined(__APPLE__) #elif defined(__APPLE__)
// Apple always uses dynamic allocation // Apple always uses dynamic allocation
#else #else
mprotect(CodeMemory, sizeof(CodeMemory), PROT_EXEC | PROT_READ | PROT_WRITE); mprotect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PROT_EXEC | PROT_READ | PROT_WRITE);
#endif #endif
ARMJIT_Memory::RegisterFaultHandler(); ARMJIT_Memory::RegisterFaultHandler();

View File

@ -39,6 +39,7 @@
#include "ARMJIT_Internal.h" #include "ARMJIT_Internal.h"
#include "ARMJIT_Compiler.h" #include "ARMJIT_Compiler.h"
#include "ARMJIT_Global.h"
#include "DSi.h" #include "DSi.h"
#include "GPU.h" #include "GPU.h"
@ -155,6 +156,15 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx)
#elif defined(_WIN32) #elif defined(_WIN32)
static LPVOID ExceptionHandlerHandle = nullptr;
static HMODULE KernelBaseDll = nullptr;
using VirtualAlloc2Type = PVOID WINAPI (*)(HANDLE Process, PVOID BaseAddress, SIZE_T Size, ULONG AllocationType, ULONG PageProtection, MEM_EXTENDED_PARAMETER* ExtendedParameters, ULONG ParameterCount);
using MapViewOfFile3Type = PVOID WINAPI (*)(HANDLE FileMapping, HANDLE Process, PVOID BaseAddress, ULONG64 Offset, SIZE_T ViewSize, ULONG AllocationType, ULONG PageProtection, MEM_EXTENDED_PARAMETER* ExtendedParameters, ULONG ParameterCount);
static VirtualAlloc2Type virtualAlloc2Ptr;
static MapViewOfFile3Type mapViewOfFile3Ptr;
LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo) LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
{ {
if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
@ -173,6 +183,7 @@ LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} }
Log(LogLevel::Debug, "it all returns to nothing\n");
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
@ -274,8 +285,47 @@ bool ARMJIT_Memory::MapIntoRange(u32 addr, u32 num, u32 offset, u32 size) noexce
(u64)(MemoryBaseCodeMem + offset), size)); (u64)(MemoryBaseCodeMem + offset), size));
return R_SUCCEEDED(r); return R_SUCCEEDED(r);
#elif defined(_WIN32) #elif defined(_WIN32)
bool r = MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, offset, size, dst) == dst; uintptr_t uintptrDst = reinterpret_cast<uintptr_t>(dst);
return r; for (auto it = VirtmemPlaceholders.begin(); it != VirtmemPlaceholders.end(); it++)
{
if (uintptrDst >= it->Start && uintptrDst+size <= it->Start+it->Size)
{
//Log(LogLevel::Debug, "found mapping %llx %llx %llx %llx\n", uintptrDst, size, it->Start, it->Size);
// we split this place holder so that we have a fitting place holder for the mapping
if (uintptrDst != it->Start || size != it->Size)
{
if (!VirtualFree(dst, size, MEM_RELEASE|MEM_PRESERVE_PLACEHOLDER))
{
Log(LogLevel::Debug, "VirtualFree failed with %x\n", GetLastError());
return false;
}
}
VirtmemPlaceholder splitPlaceholder = *it;
VirtmemPlaceholders.erase(it);
if (uintptrDst > splitPlaceholder.Start)
{
//Log(LogLevel::Debug, "splitting on the left %llx\n", uintptrDst - splitPlaceholder.Start);
VirtmemPlaceholders.push_back({splitPlaceholder.Start, uintptrDst - splitPlaceholder.Start});
}
if (uintptrDst+size < splitPlaceholder.Start+splitPlaceholder.Size)
{
//Log(LogLevel::Debug, "splitting on the right %llx\n", (splitPlaceholder.Start+splitPlaceholder.Size)-(uintptrDst+size));
VirtmemPlaceholders.push_back({uintptrDst+size, (splitPlaceholder.Start+splitPlaceholder.Size)-(uintptrDst+size)});
}
if (!mapViewOfFile3Ptr(MemoryFile, nullptr, dst, offset, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0))
{
Log(LogLevel::Debug, "MapViewOfFile3 failed with %x\n", GetLastError());
return false;
}
return true;
}
}
Log(LogLevel::Debug, "no mapping at all found??? %p %x %p\n", dst, size, MemoryBase);
return false;
#else #else
return mmap(dst, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, offset) != MAP_FAILED; return mmap(dst, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, offset) != MAP_FAILED;
#endif #endif
@ -289,7 +339,47 @@ bool ARMJIT_Memory::UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size) noex
(u64)(MemoryBaseCodeMem + offset), size); (u64)(MemoryBaseCodeMem + offset), size);
return R_SUCCEEDED(r); return R_SUCCEEDED(r);
#elif defined(_WIN32) #elif defined(_WIN32)
return UnmapViewOfFile(dst); if (!UnmapViewOfFileEx(dst, MEM_PRESERVE_PLACEHOLDER))
{
Log(LogLevel::Debug, "UnmapViewOfFileEx failed %x\n", GetLastError());
return false;
}
uintptr_t uintptrDst = reinterpret_cast<uintptr_t>(dst);
uintptr_t coalesceStart = uintptrDst;
size_t coalesceSize = size;
for (auto it = VirtmemPlaceholders.begin(); it != VirtmemPlaceholders.end();)
{
if (it->Start+it->Size == uintptrDst)
{
//Log(LogLevel::Debug, "Coalescing to the left\n");
coalesceStart = it->Start;
coalesceSize += it->Size;
it = VirtmemPlaceholders.erase(it);
}
else if (it->Start == uintptrDst+size)
{
//Log(LogLevel::Debug, "Coalescing to the right\n");
coalesceSize += it->Size;
it = VirtmemPlaceholders.erase(it);
}
else
{
it++;
}
}
if (coalesceStart != uintptrDst || coalesceSize != size)
{
if (!VirtualFree(reinterpret_cast<void*>(coalesceStart), coalesceSize, MEM_RELEASE|MEM_COALESCE_PLACEHOLDERS))
return false;
}
VirtmemPlaceholders.push_back({coalesceStart, coalesceSize});
//Log(LogLevel::Debug, "Adding coalesced region %llx %llx", coalesceStart, coalesceSize);
return true;
#else #else
return mmap(dst, size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != MAP_FAILED; return mmap(dst, size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != MAP_FAILED;
#endif #endif
@ -308,6 +398,10 @@ void ARMJIT_Memory::SetCodeProtectionRange(u32 addr, u32 size, u32 num, int prot
else else
winProtection = PAGE_READWRITE; winProtection = PAGE_READWRITE;
bool success = VirtualProtect(dst, size, winProtection, &oldProtection); bool success = VirtualProtect(dst, size, winProtection, &oldProtection);
if (!success)
{
Log(LogLevel::Debug, "VirtualProtect failed with %x\n", GetLastError());
}
assert(success); assert(success);
#else #else
int posixProt; int posixProt;
@ -361,7 +455,6 @@ void ARMJIT_Memory::Mapping::Unmap(int region, melonDS::NDS& nds) noexcept
} }
#ifndef __SWITCH__ #ifndef __SWITCH__
#ifndef _WIN32
u32 dtcmEnd = dtcmStart + dtcmSize; u32 dtcmEnd = dtcmStart + dtcmSize;
if (Num == 0 if (Num == 0
&& dtcmEnd >= Addr && dtcmEnd >= Addr
@ -381,7 +474,6 @@ void ARMJIT_Memory::Mapping::Unmap(int region, melonDS::NDS& nds) noexcept
} }
} }
else else
#endif
{ {
bool succeded = nds.JIT.Memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size); bool succeded = nds.JIT.Memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
assert(succeded); assert(succeded);
@ -546,7 +638,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
u32 dtcmSize = ~NDS.ARM9.DTCMMask + 1; u32 dtcmSize = ~NDS.ARM9.DTCMMask + 1;
u32 dtcmEnd = dtcmStart + dtcmSize; u32 dtcmEnd = dtcmStart + dtcmSize;
#ifndef __SWITCH__ #ifndef __SWITCH__
#ifndef _WIN32
if (num == 0 if (num == 0
&& dtcmEnd >= mirrorStart && dtcmEnd >= mirrorStart
&& dtcmStart < mirrorStart + mirrorSize) && dtcmStart < mirrorStart + mirrorSize)
@ -565,7 +656,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
} }
} }
else else
#endif
{ {
bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize); bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize);
assert(succeded); assert(succeded);
@ -582,9 +672,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
{ {
if (skipDTCM && mirrorStart + offset == dtcmStart) if (skipDTCM && mirrorStart + offset == dtcmStart)
{ {
#ifdef _WIN32
SetCodeProtectionRange(dtcmStart, dtcmSize, 0, 0);
#endif
offset += dtcmSize; offset += dtcmSize;
} }
else else
@ -627,10 +714,45 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
return true; return true;
} }
bool ARMJIT_Memory::IsFastMemSupported()
{
#ifdef __APPLE__
return false;
#else
static bool initialised = false;
static bool isSupported = false;
if (!initialised)
{
#ifdef _WIN32
ARMJIT_Global::Init();
isSupported = virtualAlloc2Ptr != nullptr;
ARMJIT_Global::DeInit();
#else
// TODO: check page size is 4kb for posix
isSupported = true;
#endif
initialised = true;
}
return isSupported;
#endif
}
void ARMJIT_Memory::RegisterFaultHandler() void ARMJIT_Memory::RegisterFaultHandler()
{ {
#ifdef _WIN32 #ifdef _WIN32
ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler);
KernelBaseDll = LoadLibrary("KernelBase.dll");
/* if (KernelBaseDll)
{
virtualAlloc2Ptr = reinterpret_cast<VirtualAlloc2Type>(GetProcAddress(KernelBaseDll, "VirtualAlloc2"));
mapViewOfFile3Ptr = reinterpret_cast<MapViewOfFile3Type>(GetProcAddress(KernelBaseDll, "MapViewOfFile3"));
}*/
if (!virtualAlloc2Ptr)
{
Log(LogLevel::Error, "Could not load new Windows virtual memory functions, fast memory is disabled.\n");
}
#else #else
struct sigaction sa; struct sigaction sa;
sa.sa_handler = nullptr; sa.sa_handler = nullptr;
@ -646,10 +768,24 @@ void ARMJIT_Memory::RegisterFaultHandler()
void ARMJIT_Memory::UnregisterFaultHandler() void ARMJIT_Memory::UnregisterFaultHandler()
{ {
#ifdef _WIN32
if (ExceptionHandlerHandle)
{
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
ExceptionHandlerHandle = nullptr;
}
if (KernelBaseDll)
{
FreeLibrary(KernelBaseDll);
KernelBaseDll = nullptr;
}
#else
sigaction(SIGSEGV, &OldSaSegv, nullptr); sigaction(SIGSEGV, &OldSaSegv, nullptr);
#ifdef __APPLE__ #ifdef __APPLE__
sigaction(SIGBUS, &OldSaBus, nullptr); sigaction(SIGBUS, &OldSaBus, nullptr);
#endif #endif
#endif
} }
bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, melonDS::NDS& nds) bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, melonDS::NDS& nds)
@ -673,6 +809,7 @@ bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, melonDS::NDS& nds)
ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds) ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
{ {
ARMJIT_Global::Init();
#if defined(__SWITCH__) #if defined(__SWITCH__)
MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize); MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize);
virtmemLock(); virtmemLock();
@ -697,27 +834,27 @@ ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
u8* basePtr = MemoryBaseCodeMem; u8* basePtr = MemoryBaseCodeMem;
#elif defined(_WIN32) #elif defined(_WIN32)
ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler); if (virtualAlloc2Ptr)
{
MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, MemoryTotalSize, nullptr);
MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemoryTotalSize, NULL); MemoryBase = reinterpret_cast<u8*>(virtualAlloc2Ptr(nullptr, nullptr, VirtmemAreaSize,
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
PAGE_NOACCESS,
nullptr, 0));
// split off placeholder and map base mapping
VirtualFree(MemoryBase, MemoryTotalSize, MEM_RELEASE|MEM_PRESERVE_PLACEHOLDER);
mapViewOfFile3Ptr(MemoryFile, nullptr, MemoryBase, 0, MemoryTotalSize, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
MemoryBase = (u8*)VirtualAlloc(NULL, AddrSpaceSize*4, MEM_RESERVE, PAGE_READWRITE); VirtmemPlaceholders.push_back({reinterpret_cast<uintptr_t>(MemoryBase)+MemoryTotalSize, AddrSpaceSize*2});
VirtualFree(MemoryBase, 0, MEM_RELEASE); }
// this is incredible hacky else
// but someone else is trying to go into our address space! {
// Windows will very likely give them virtual memory starting at the same address // old Windows version
// as it is giving us now. MemoryBase = new u8[MemoryTotalSize];
// That's why we don't use this address, but instead 4gb inwards }
// I know this is terrible
FastMem9Start = MemoryBase + AddrSpaceSize;
FastMem7Start = MemoryBase + AddrSpaceSize*2;
MemoryBase = MemoryBase + AddrSpaceSize*3;
MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, MemoryTotalSize, MemoryBase);
#else #else
MemoryBase = (u8*)mmap(NULL, VirtmemAreaSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); MemoryBase = (u8*)mmap(nullptr, VirtmemAreaSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
FastMem9Start = MemoryBase+MemoryTotalSize;
FastMem7Start = static_cast<u8*>(FastMem9Start)+AddrSpaceSize;
#if defined(__ANDROID__) #if defined(__ANDROID__)
Libandroid = Platform::DynamicLibrary_Load("libandroid.so"); Libandroid = Platform::DynamicLibrary_Load("libandroid.so");
@ -752,6 +889,8 @@ ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
mmap(MemoryBase, MemoryTotalSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, 0); mmap(MemoryBase, MemoryTotalSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, 0);
#endif #endif
FastMem9Start = MemoryBase+MemoryTotalSize;
FastMem7Start = static_cast<u8*>(FastMem9Start)+AddrSpaceSize;
} }
ARMJIT_Memory::~ARMJIT_Memory() noexcept ARMJIT_Memory::~ARMJIT_Memory() noexcept
@ -772,13 +911,21 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
free(MemoryBase); free(MemoryBase);
MemoryBase = nullptr; MemoryBase = nullptr;
#elif defined(_WIN32) #elif defined(_WIN32)
if (virtualAlloc2Ptr)
{
if (MemoryBase) if (MemoryBase)
{ {
bool viewUnmapped = UnmapViewOfFile(MemoryBase); bool viewUnmapped = UnmapViewOfFileEx(MemoryBase, MEM_PRESERVE_PLACEHOLDER);
assert(viewUnmapped); assert(viewUnmapped);
bool viewCoalesced = VirtualFree(MemoryBase, VirtmemAreaSize, MEM_RELEASE|MEM_COALESCE_PLACEHOLDERS);
assert(viewCoalesced);
bool freeEverything = VirtualFree(MemoryBase, 0, MEM_RELEASE);
assert(freeEverything);
MemoryBase = nullptr; MemoryBase = nullptr;
FastMem9Start = nullptr; FastMem9Start = nullptr;
FastMem7Start = nullptr; FastMem7Start = nullptr;
printf("unmappinged everything\n");
} }
if (MemoryFile) if (MemoryFile)
@ -786,11 +933,10 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
CloseHandle(MemoryFile); CloseHandle(MemoryFile);
MemoryFile = INVALID_HANDLE_VALUE; MemoryFile = INVALID_HANDLE_VALUE;
} }
}
if (ExceptionHandlerHandle) else
{ {
RemoveVectoredExceptionHandler(ExceptionHandlerHandle); delete[] MemoryBase;
ExceptionHandlerHandle = nullptr;
} }
#else #else
if (MemoryBase) if (MemoryBase)
@ -816,6 +962,8 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
#endif #endif
#endif #endif
ARMJIT_Global::DeInit();
} }
void ARMJIT_Memory::Reset() noexcept void ARMJIT_Memory::Reset() noexcept
@ -838,17 +986,6 @@ void ARMJIT_Memory::Reset() noexcept
bool ARMJIT_Memory::IsFastmemCompatible(int region) const noexcept bool ARMJIT_Memory::IsFastmemCompatible(int region) const noexcept
{ {
#ifdef _WIN32
/*
TODO: with some hacks, the smaller shared WRAM regions
could be mapped in some occaisons as well
*/
if (region == memregion_DTCM
|| region == memregion_SharedWRAM
|| region == memregion_NewSharedWRAM_B
|| region == memregion_NewSharedWRAM_C)
return false;
#endif
return OffsetsPerRegion[region] != UINT32_MAX; return OffsetsPerRegion[region] != UINT32_MAX;
} }

View File

@ -51,21 +51,17 @@ class ARMJIT;
constexpr u32 RoundUp(u32 size) noexcept constexpr u32 RoundUp(u32 size) noexcept
{ {
#ifdef _WIN32
return (size + 0xFFFF) & ~0xFFFF;
#else
return size; return size;
#endif
} }
const u32 MemBlockMainRAMOffset = 0; static constexpr u32 MemBlockMainRAMOffset = 0;
const u32 MemBlockSWRAMOffset = RoundUp(MainRAMMaxSize); static constexpr u32 MemBlockSWRAMOffset = RoundUp(MainRAMMaxSize);
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(SharedWRAMSize); static constexpr u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(SharedWRAMSize);
const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(ARM7WRAMSize); static constexpr u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(ARM7WRAMSize);
const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize); static constexpr u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize);
const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(NWRAMSize); static constexpr u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(NWRAMSize);
const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(NWRAMSize); static constexpr u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(NWRAMSize);
const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(NWRAMSize); static constexpr u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(NWRAMSize);
class ARMJIT_Memory class ARMJIT_Memory
{ {
@ -139,6 +135,8 @@ public:
void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept; void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept;
bool MapAtAddress(u32 addr) noexcept; bool MapAtAddress(u32 addr) noexcept;
static bool IsFastMemSupported();
static void RegisterFaultHandler(); static void RegisterFaultHandler();
static void UnregisterFaultHandler(); static void UnregisterFaultHandler();
private: private:
@ -170,9 +168,15 @@ private:
VirtmemReservation* FastMem9Reservation, *FastMem7Reservation; VirtmemReservation* FastMem9Reservation, *FastMem7Reservation;
u8* MemoryBaseCodeMem; u8* MemoryBaseCodeMem;
#elif defined(_WIN32) #elif defined(_WIN32)
struct VirtmemPlaceholder
{
uintptr_t Start;
size_t Size;
};
std::vector<VirtmemPlaceholder> VirtmemPlaceholders;
static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo); static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo);
HANDLE MemoryFile = INVALID_HANDLE_VALUE; HANDLE MemoryFile = INVALID_HANDLE_VALUE;
LPVOID ExceptionHandlerHandle = nullptr;
#else #else
static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext); static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext);
int MemoryFile = -1; int MemoryFile = -1;

View File

@ -225,6 +225,8 @@ void Compiler::A_Comp_MSR()
Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds) Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds)
{ {
ARMJIT_Global::Init();
CodeMemBase = static_cast<u8*>(ARMJIT_Global::AllocateCodeMem()); CodeMemBase = static_cast<u8*>(ARMJIT_Global::AllocateCodeMem());
CodeMemSize = ARMJIT_Global::CodeMemorySliceSize; CodeMemSize = ARMJIT_Global::CodeMemorySliceSize;
@ -445,6 +447,8 @@ Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds)
Compiler::~Compiler() Compiler::~Compiler()
{ {
ARMJIT_Global::FreeCodeMem(CodeMemBase); ARMJIT_Global::FreeCodeMem(CodeMemBase);
ARMJIT_Global::DeInit();
} }
void Compiler::LoadCPSR() void Compiler::LoadCPSR()

View File

@ -101,6 +101,10 @@ if (ENABLE_JIT)
dolphin/CommonFuncs.cpp) dolphin/CommonFuncs.cpp)
if (WIN32)
target_link_libraries(core PRIVATE onecore)
endif()
if (ARCHITECTURE STREQUAL x86_64) if (ARCHITECTURE STREQUAL x86_64)
target_sources(core PRIVATE target_sources(core PRIVATE
dolphin/x64ABI.cpp dolphin/x64ABI.cpp

View File

@ -81,10 +81,8 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new
ui->chkEnableJIT->setChecked(cfg.GetBool("JIT.Enable")); ui->chkEnableJIT->setChecked(cfg.GetBool("JIT.Enable"));
ui->chkJITBranchOptimisations->setChecked(cfg.GetBool("JIT.BranchOptimisations")); ui->chkJITBranchOptimisations->setChecked(cfg.GetBool("JIT.BranchOptimisations"));
ui->chkJITLiteralOptimisations->setChecked(cfg.GetBool("JIT.LiteralOptimisations")); ui->chkJITLiteralOptimisations->setChecked(cfg.GetBool("JIT.LiteralOptimisations"));
ui->chkJITFastMemory->setChecked(cfg.GetBool("JIT.FastMemory")); ui->chkJITFastMemory->setDisabled(!ARMJIT_Memory::IsFastMemSupported());
#ifdef __APPLE__ ui->chkJITFastMemory->setChecked(cfg.GetBool("JIT.FastMemory") && ui->chkJITFastMemory->isEnabled());
ui->chkJITFastMemory->setDisabled(true);
#endif
ui->spnJITMaximumBlockSize->setValue(cfg.GetInt("JIT.MaxBlockSize")); ui->spnJITMaximumBlockSize->setValue(cfg.GetInt("JIT.MaxBlockSize"));
#else #else
ui->chkEnableJIT->setDisabled(true); ui->chkEnableJIT->setDisabled(true);
@ -541,9 +539,7 @@ void EmuSettingsDialog::on_chkEnableJIT_toggled()
bool disabled = !ui->chkEnableJIT->isChecked(); bool disabled = !ui->chkEnableJIT->isChecked();
ui->chkJITBranchOptimisations->setDisabled(disabled); ui->chkJITBranchOptimisations->setDisabled(disabled);
ui->chkJITLiteralOptimisations->setDisabled(disabled); ui->chkJITLiteralOptimisations->setDisabled(disabled);
#ifndef __APPLE__ ui->chkJITFastMemory->setDisabled(!ARMJIT_Memory::IsFastMemSupported());
ui->chkJITFastMemory->setDisabled(disabled);
#endif
ui->spnJITMaximumBlockSize->setDisabled(disabled); ui->spnJITMaximumBlockSize->setDisabled(disabled);
on_cbGdbEnabled_toggled(); on_cbGdbEnabled_toggled();