diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 4edb2f44..e34f5af2 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -234,8 +234,6 @@ ARMJIT::~ARMJIT() noexcept { JitEnableWrite(); ResetBlockCache(); - - ARMJIT_Global::DeInit(); } void ARMJIT::Reset() noexcept @@ -477,10 +475,8 @@ ARMJIT::ARMJIT(melonDS::NDS& nds, std::optional jit) noexcept : MaxBlockSize(jit.has_value() ? std::clamp(jit->MaxBlockSize, 1u, 32u) : 32), LiteralOptimizations(jit.has_value() ? jit->LiteralOptimizations : false), BranchOptimizations(jit.has_value() ? jit->BranchOptimizations : false), - FastMemory(jit.has_value() ? jit->FastMemory : false) -{ - ARMJIT_Global::Init(); -} + FastMemory((jit.has_value() ? jit->FastMemory : false) && ARMJIT_Memory::IsFastMemSupported()) +{} void ARMJIT::RetireJitBlock(JitBlock* block) noexcept { @@ -498,6 +494,7 @@ void ARMJIT::RetireJitBlock(JitBlock* block) noexcept void ARMJIT::SetJITArgs(JITArgs args) noexcept { + args.FastMemory = args.FastMemory && ARMJIT_Memory::IsFastMemSupported(); args.MaxBlockSize = std::clamp(args.MaxBlockSize, 1u, 32u); if (MaxBlockSize != args.MaxBlockSize @@ -514,36 +511,22 @@ void ARMJIT::SetJITArgs(JITArgs args) noexcept void ARMJIT::SetMaxBlockSize(int size) noexcept { - size = std::clamp(size, 1, 32); - - if (size != MaxBlockSize) - ResetBlockCache(); - - MaxBlockSize = size; + SetJITArgs(JITArgs{static_cast(size), LiteralOptimizations, LiteralOptimizations, FastMemory}); } void ARMJIT::SetLiteralOptimizations(bool enabled) noexcept { - if (LiteralOptimizations != enabled) - ResetBlockCache(); - - LiteralOptimizations = enabled; + SetJITArgs(JITArgs{static_cast(MaxBlockSize), enabled, BranchOptimizations, FastMemory}); } void ARMJIT::SetBranchOptimizations(bool enabled) noexcept { - if (BranchOptimizations != enabled) - ResetBlockCache(); - - BranchOptimizations = enabled; + SetJITArgs(JITArgs{static_cast(MaxBlockSize), LiteralOptimizations, enabled, FastMemory}); } void ARMJIT::SetFastMemory(bool enabled) noexcept { - if (FastMemory != enabled) - ResetBlockCache(); - - FastMemory = enabled; + SetJITArgs(JITArgs{static_cast(MaxBlockSize), LiteralOptimizations, BranchOptimizations, enabled}); } void ARMJIT::CompileBlock(ARM* cpu) noexcept diff --git a/src/ARMJIT_Global.cpp b/src/ARMJIT_Global.cpp index 3bf1b4b2..b6510379 100644 --- a/src/ARMJIT_Global.cpp +++ b/src/ARMJIT_Global.cpp @@ -9,6 +9,7 @@ #endif #include +#include #include @@ -20,33 +21,43 @@ namespace ARMJIT_Global std::mutex globalMutex; +#ifndef __APPLE__ static constexpr size_t NumCodeMemSlices = 4; +static constexpr size_t CodeMemoryAlignedSize = NumCodeMemSlices * CodeMemorySliceSize; // 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; +u8* GetAlignedCodeMemoryStart() +{ + return reinterpret_cast((reinterpret_cast(CodeMemory) + (16*1024-1)) & ~static_cast(16*1024-1)); +} +#endif + int RefCounter = 0; void* AllocateCodeMem() { std::lock_guard guard(globalMutex); +#ifndef __APPLE__ if (AvailableCodeMemSlices) { int slice = __builtin_ctz(AvailableCodeMemSlices); AvailableCodeMemSlices &= ~(1 << slice); //printf("allocating slice %d\n", slice); - return &CodeMemory[slice * CodeMemorySliceSize]; + return &GetAlignedCodeMemoryStart()[slice * CodeMemorySliceSize]; } +#endif // allocate #ifdef _WIN32 - // FIXME + return VirtualAlloc(nullptr, CodeMemorySliceSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else //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 } @@ -56,7 +67,7 @@ void FreeCodeMem(void* codeMem) for (int i = 0; i < NumCodeMemSlices; i++) { - if (codeMem == &CodeMemory[CodeMemorySliceSize * i]) + if (codeMem == &GetAlignedCodeMemoryStart()[CodeMemorySliceSize * i]) { //printf("freeing slice\n"); AvailableCodeMemSlices |= 1 << i; @@ -65,7 +76,7 @@ void FreeCodeMem(void* codeMem) } #ifdef _WIN32 - // FIXME + VirtualFree(codeMem, CodeMemorySliceSize, MEM_RELEASE|MEM_DECOMMIT); #else munmap(codeMem, CodeMemorySliceSize); #endif @@ -80,11 +91,11 @@ void Init() { #ifdef _WIN32 DWORD dummy; - VirtualProtect(CodeMemory, sizeof(CodeMemory), PAGE_EXECUTE_READWRITE, &dummy); + VirtualProtect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PAGE_EXECUTE_READWRITE, &dummy); #elif defined(__APPLE__) // Apple always uses dynamic allocation #else - mprotect(CodeMemory, sizeof(CodeMemory), PROT_EXEC | PROT_READ | PROT_WRITE); + mprotect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PROT_EXEC | PROT_READ | PROT_WRITE); #endif ARMJIT_Memory::RegisterFaultHandler(); diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp index 418bbe87..d189d046 100644 --- a/src/ARMJIT_Memory.cpp +++ b/src/ARMJIT_Memory.cpp @@ -39,6 +39,7 @@ #include "ARMJIT_Internal.h" #include "ARMJIT_Compiler.h" +#include "ARMJIT_Global.h" #include "DSi.h" #include "GPU.h" @@ -155,6 +156,15 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx) #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) { if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) @@ -173,6 +183,7 @@ LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo) return EXCEPTION_CONTINUE_EXECUTION; } + Log(LogLevel::Debug, "it all returns to nothing\n"); 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)); return R_SUCCEEDED(r); #elif defined(_WIN32) - bool r = MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, offset, size, dst) == dst; - return r; + uintptr_t uintptrDst = reinterpret_cast(dst); + 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 return mmap(dst, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, offset) != MAP_FAILED; #endif @@ -289,7 +339,47 @@ bool ARMJIT_Memory::UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size) noex (u64)(MemoryBaseCodeMem + offset), size); return R_SUCCEEDED(r); #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(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(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 return mmap(dst, size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != MAP_FAILED; #endif @@ -308,6 +398,10 @@ void ARMJIT_Memory::SetCodeProtectionRange(u32 addr, u32 size, u32 num, int prot else winProtection = PAGE_READWRITE; bool success = VirtualProtect(dst, size, winProtection, &oldProtection); + if (!success) + { + Log(LogLevel::Debug, "VirtualProtect failed with %x\n", GetLastError()); + } assert(success); #else int posixProt; @@ -361,7 +455,6 @@ void ARMJIT_Memory::Mapping::Unmap(int region, melonDS::NDS& nds) noexcept } #ifndef __SWITCH__ -#ifndef _WIN32 u32 dtcmEnd = dtcmStart + dtcmSize; if (Num == 0 && dtcmEnd >= Addr @@ -381,7 +474,6 @@ void ARMJIT_Memory::Mapping::Unmap(int region, melonDS::NDS& nds) noexcept } } else -#endif { bool succeded = nds.JIT.Memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size); assert(succeded); @@ -546,7 +638,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept u32 dtcmSize = ~NDS.ARM9.DTCMMask + 1; u32 dtcmEnd = dtcmStart + dtcmSize; #ifndef __SWITCH__ -#ifndef _WIN32 if (num == 0 && dtcmEnd >= mirrorStart && dtcmStart < mirrorStart + mirrorSize) @@ -565,7 +656,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept } } else -#endif { bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize); assert(succeded); @@ -582,9 +672,6 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept { if (skipDTCM && mirrorStart + offset == dtcmStart) { -#ifdef _WIN32 - SetCodeProtectionRange(dtcmStart, dtcmSize, 0, 0); -#endif offset += dtcmSize; } else @@ -627,10 +714,45 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept 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() { #ifdef _WIN32 + ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler); + KernelBaseDll = LoadLibrary("KernelBase.dll"); +/* if (KernelBaseDll) + { + virtualAlloc2Ptr = reinterpret_cast(GetProcAddress(KernelBaseDll, "VirtualAlloc2")); + mapViewOfFile3Ptr = reinterpret_cast(GetProcAddress(KernelBaseDll, "MapViewOfFile3")); + }*/ + + if (!virtualAlloc2Ptr) + { + Log(LogLevel::Error, "Could not load new Windows virtual memory functions, fast memory is disabled.\n"); + } #else struct sigaction sa; sa.sa_handler = nullptr; @@ -646,10 +768,24 @@ void ARMJIT_Memory::RegisterFaultHandler() void ARMJIT_Memory::UnregisterFaultHandler() { +#ifdef _WIN32 + if (ExceptionHandlerHandle) + { + RemoveVectoredExceptionHandler(ExceptionHandlerHandle); + ExceptionHandlerHandle = nullptr; + } + + if (KernelBaseDll) + { + FreeLibrary(KernelBaseDll); + KernelBaseDll = nullptr; + } +#else sigaction(SIGSEGV, &OldSaSegv, nullptr); #ifdef __APPLE__ sigaction(SIGBUS, &OldSaBus, nullptr); #endif +#endif } 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_Global::Init(); #if defined(__SWITCH__) MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize); virtmemLock(); @@ -697,27 +834,27 @@ ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds) u8* basePtr = MemoryBaseCodeMem; #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(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); - VirtualFree(MemoryBase, 0, MEM_RELEASE); - // this is incredible hacky - // but someone else is trying to go into our address space! - // Windows will very likely give them virtual memory starting at the same address - // as it is giving us now. - // 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); + VirtmemPlaceholders.push_back({reinterpret_cast(MemoryBase)+MemoryTotalSize, AddrSpaceSize*2}); + } + else + { + // old Windows version + MemoryBase = new u8[MemoryTotalSize]; + } #else - MemoryBase = (u8*)mmap(NULL, VirtmemAreaSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); - FastMem9Start = MemoryBase+MemoryTotalSize; - FastMem7Start = static_cast(FastMem9Start)+AddrSpaceSize; + MemoryBase = (u8*)mmap(nullptr, VirtmemAreaSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); #if defined(__ANDROID__) 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); #endif + FastMem9Start = MemoryBase+MemoryTotalSize; + FastMem7Start = static_cast(FastMem9Start)+AddrSpaceSize; } ARMJIT_Memory::~ARMJIT_Memory() noexcept @@ -772,25 +911,32 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept free(MemoryBase); MemoryBase = nullptr; #elif defined(_WIN32) - if (MemoryBase) + if (virtualAlloc2Ptr) { - bool viewUnmapped = UnmapViewOfFile(MemoryBase); - assert(viewUnmapped); - MemoryBase = nullptr; - FastMem9Start = nullptr; - FastMem7Start = nullptr; - } + if (MemoryBase) + { + bool viewUnmapped = UnmapViewOfFileEx(MemoryBase, MEM_PRESERVE_PLACEHOLDER); + assert(viewUnmapped); + bool viewCoalesced = VirtualFree(MemoryBase, VirtmemAreaSize, MEM_RELEASE|MEM_COALESCE_PLACEHOLDERS); + assert(viewCoalesced); + bool freeEverything = VirtualFree(MemoryBase, 0, MEM_RELEASE); + assert(freeEverything); - if (MemoryFile) - { - CloseHandle(MemoryFile); - MemoryFile = INVALID_HANDLE_VALUE; - } + MemoryBase = nullptr; + FastMem9Start = nullptr; + FastMem7Start = nullptr; + printf("unmappinged everything\n"); + } - if (ExceptionHandlerHandle) + if (MemoryFile) + { + CloseHandle(MemoryFile); + MemoryFile = INVALID_HANDLE_VALUE; + } + } + else { - RemoveVectoredExceptionHandler(ExceptionHandlerHandle); - ExceptionHandlerHandle = nullptr; + delete[] MemoryBase; } #else if (MemoryBase) @@ -816,6 +962,8 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept #endif #endif + + ARMJIT_Global::DeInit(); } void ARMJIT_Memory::Reset() noexcept @@ -838,17 +986,6 @@ void ARMJIT_Memory::Reset() 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; } diff --git a/src/ARMJIT_Memory.h b/src/ARMJIT_Memory.h index 2b039cbd..f6fd563f 100644 --- a/src/ARMJIT_Memory.h +++ b/src/ARMJIT_Memory.h @@ -51,21 +51,17 @@ class ARMJIT; constexpr u32 RoundUp(u32 size) noexcept { -#ifdef _WIN32 - return (size + 0xFFFF) & ~0xFFFF; -#else return size; -#endif } -const u32 MemBlockMainRAMOffset = 0; -const u32 MemBlockSWRAMOffset = RoundUp(MainRAMMaxSize); -const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(SharedWRAMSize); -const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(ARM7WRAMSize); -const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize); -const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(NWRAMSize); -const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(NWRAMSize); -const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(NWRAMSize); +static constexpr u32 MemBlockMainRAMOffset = 0; +static constexpr u32 MemBlockSWRAMOffset = RoundUp(MainRAMMaxSize); +static constexpr u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(SharedWRAMSize); +static constexpr u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(ARM7WRAMSize); +static constexpr u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize); +static constexpr u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(NWRAMSize); +static constexpr u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(NWRAMSize); +static constexpr u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(NWRAMSize); class ARMJIT_Memory { @@ -139,6 +135,8 @@ public: void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept; bool MapAtAddress(u32 addr) noexcept; + static bool IsFastMemSupported(); + static void RegisterFaultHandler(); static void UnregisterFaultHandler(); private: @@ -170,9 +168,15 @@ private: VirtmemReservation* FastMem9Reservation, *FastMem7Reservation; u8* MemoryBaseCodeMem; #elif defined(_WIN32) + struct VirtmemPlaceholder + { + uintptr_t Start; + size_t Size; + }; + std::vector VirtmemPlaceholders; + static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo); HANDLE MemoryFile = INVALID_HANDLE_VALUE; - LPVOID ExceptionHandlerHandle = nullptr; #else static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext); int MemoryFile = -1; diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp index 9ebcc667..6de4caf6 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp @@ -225,6 +225,8 @@ void Compiler::A_Comp_MSR() Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds) { + ARMJIT_Global::Init(); + CodeMemBase = static_cast(ARMJIT_Global::AllocateCodeMem()); CodeMemSize = ARMJIT_Global::CodeMemorySliceSize; @@ -445,6 +447,8 @@ Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds) Compiler::~Compiler() { ARMJIT_Global::FreeCodeMem(CodeMemBase); + + ARMJIT_Global::DeInit(); } void Compiler::LoadCPSR() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e1f6ee26..1a8e3697 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,6 +100,10 @@ if (ENABLE_JIT) ARMJIT_Global.cpp dolphin/CommonFuncs.cpp) + + if (WIN32) + target_link_libraries(core PRIVATE onecore) + endif() if (ARCHITECTURE STREQUAL x86_64) target_sources(core PRIVATE diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index b37f7118..98bd6b20 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -81,10 +81,8 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new ui->chkEnableJIT->setChecked(cfg.GetBool("JIT.Enable")); ui->chkJITBranchOptimisations->setChecked(cfg.GetBool("JIT.BranchOptimisations")); ui->chkJITLiteralOptimisations->setChecked(cfg.GetBool("JIT.LiteralOptimisations")); - ui->chkJITFastMemory->setChecked(cfg.GetBool("JIT.FastMemory")); - #ifdef __APPLE__ - ui->chkJITFastMemory->setDisabled(true); - #endif + ui->chkJITFastMemory->setDisabled(!ARMJIT_Memory::IsFastMemSupported()); + ui->chkJITFastMemory->setChecked(cfg.GetBool("JIT.FastMemory") && ui->chkJITFastMemory->isEnabled()); ui->spnJITMaximumBlockSize->setValue(cfg.GetInt("JIT.MaxBlockSize")); #else ui->chkEnableJIT->setDisabled(true); @@ -541,9 +539,7 @@ void EmuSettingsDialog::on_chkEnableJIT_toggled() bool disabled = !ui->chkEnableJIT->isChecked(); ui->chkJITBranchOptimisations->setDisabled(disabled); ui->chkJITLiteralOptimisations->setDisabled(disabled); - #ifndef __APPLE__ - ui->chkJITFastMemory->setDisabled(disabled); - #endif + ui->chkJITFastMemory->setDisabled(!ARMJIT_Memory::IsFastMemSupported()); ui->spnJITMaximumBlockSize->setDisabled(disabled); on_cbGdbEnabled_toggled();