diff --git a/common/General.h b/common/General.h index 041b07dacb..6d3808f882 100644 --- a/common/General.h +++ b/common/General.h @@ -187,11 +187,6 @@ private: #endif }; - -// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it. -#define SafeSysMunmap(ptr, size) \ - ((void)(HostSys::Munmap(ptr, size), (ptr) = 0)) - extern u64 GetTickFrequency(); extern u64 GetCPUTicks(); extern u64 GetPhysicalMemory(); diff --git a/pcsx2-qt/Settings/GamePatchSettingsWidget.cpp b/pcsx2-qt/Settings/GamePatchSettingsWidget.cpp index 4f5bd244d8..f83f29e440 100644 --- a/pcsx2-qt/Settings/GamePatchSettingsWidget.cpp +++ b/pcsx2-qt/Settings/GamePatchSettingsWidget.cpp @@ -24,6 +24,8 @@ #include "pcsx2/GameList.h" #include "pcsx2/Patch.h" +#include "common/Assertions.h" + #include GamePatchDetailsWidget::GamePatchDetailsWidget(std::string name, const std::string& author, diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 99a7ed51f1..1f73999011 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -140,7 +140,6 @@ set(pcsx2Sources Vif_Codes.cpp Vif_Transfer.cpp Vif_Unpack.cpp - VirtualMemory.cpp VMManager.cpp vtlb.cpp VU0.cpp @@ -217,7 +216,6 @@ set(pcsx2Headers Vif_Dma.h Vif.h Vif_Unpack.h - VirtualMemory.h VMManager.h vtlb.h VUflags.h diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 843225deb2..877a57a3d3 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -15,6 +15,7 @@ #pragma once +#include "common/Assertions.h" #include "common/StringUtil.h" // Useful enums for some of the fields. diff --git a/pcsx2/GS/Renderers/Common/GSFunctionMap.cpp b/pcsx2/GS/Renderers/Common/GSFunctionMap.cpp index 2b29062b88..80ac47ccc6 100644 --- a/pcsx2/GS/Renderers/Common/GSFunctionMap.cpp +++ b/pcsx2/GS/Renderers/Common/GSFunctionMap.cpp @@ -17,39 +17,33 @@ #include "GS/Renderers/Common/GSFunctionMap.h" #include "System.h" -static GSCodeReserve s_instance; - -GSCodeReserve::GSCodeReserve() - : RecompiledCodeReserve("GS Software Renderer") +namespace GSCodeReserve { + static u8* s_memory_base; + static u8* s_memory_end; + static u8* s_memory_ptr; } -GSCodeReserve::~GSCodeReserve() = default; - -GSCodeReserve& GSCodeReserve::GetInstance() +void GSCodeReserve::ResetMemory() { - return s_instance; + s_memory_base = SysMemory::GetSWRec(); + s_memory_end = SysMemory::GetSWRecEnd(); + s_memory_ptr = s_memory_base; } -void GSCodeReserve::Assign(VirtualMemoryManagerPtr allocator) +size_t GSCodeReserve::GetMemoryUsed() { - RecompiledCodeReserve::Assign(std::move(allocator), HostMemoryMap::SWrecOffset, HostMemoryMap::SWrecSize); + return s_memory_ptr - s_memory_base; } -void GSCodeReserve::Reset() +u8* GSCodeReserve::ReserveMemory(size_t size) { - RecompiledCodeReserve::Reset(); - m_memory_used = 0; + pxAssert((s_memory_ptr + size) <= s_memory_end); + return s_memory_ptr; } -u8* GSCodeReserve::Reserve(size_t size) +void GSCodeReserve::CommitMemory(size_t size) { - pxAssert((m_memory_used + size) <= m_size); - return m_baseptr + m_memory_used; -} - -void GSCodeReserve::Commit(size_t size) -{ - pxAssert((m_memory_used + size) <= m_size); - m_memory_used += size; + pxAssert((s_memory_ptr + size) <= s_memory_end); + s_memory_ptr += size; } diff --git a/pcsx2/GS/Renderers/Common/GSFunctionMap.h b/pcsx2/GS/Renderers/Common/GSFunctionMap.h index 1d86be1e0c..d030a3bf0c 100644 --- a/pcsx2/GS/Renderers/Common/GSFunctionMap.h +++ b/pcsx2/GS/Renderers/Common/GSFunctionMap.h @@ -17,7 +17,7 @@ #include "GS/GSExtra.h" #include "GS/Renderers/SW/GSScanlineEnvironment.h" -#include "VirtualMemory.h" +#include "System.h" #include "common/emitter/tools.h" template @@ -147,25 +147,15 @@ public: // -------------------------------------------------------------------------------------- // Stores code buffers for the GS software JIT. // -class GSCodeReserve : public RecompiledCodeReserve +namespace GSCodeReserve { -public: - GSCodeReserve(); - ~GSCodeReserve(); + void ResetMemory(); - static GSCodeReserve& GetInstance(); + size_t GetMemoryUsed(); - size_t GetMemoryUsed() const { return m_memory_used; } - - void Assign(VirtualMemoryManagerPtr allocator); - void Reset(); - - u8* Reserve(size_t size); - void Commit(size_t size); - -private: - size_t m_memory_used = 0; -}; + u8* ReserveMemory(size_t size); + void CommitMemory(size_t size); +} template class GSCodeGeneratorFunctionMap : public GSFunctionMap @@ -200,7 +190,7 @@ public: } else { - u8* code_ptr = GSCodeReserve::GetInstance().Reserve(MAX_SIZE); + u8* code_ptr = GSCodeReserve::ReserveMemory(MAX_SIZE); CG cg(key, code_ptr, MAX_SIZE); ASSERT(cg.getSize() < MAX_SIZE); @@ -210,7 +200,7 @@ public: sel.Print(); #endif - GSCodeReserve::GetInstance().Commit(cg.getSize()); + GSCodeReserve::CommitMemory(cg.getSize()); ret = (VALUE)cg.getCode(); diff --git a/pcsx2/GS/Renderers/SW/GSDrawScanline.cpp b/pcsx2/GS/Renderers/SW/GSDrawScanline.cpp index 997feaf28a..62f3a8b6f2 100644 --- a/pcsx2/GS/Renderers/SW/GSDrawScanline.cpp +++ b/pcsx2/GS/Renderers/SW/GSDrawScanline.cpp @@ -38,12 +38,12 @@ GSDrawScanline::GSDrawScanline() : m_sp_map("GSSetupPrim") , m_ds_map("GSDrawScanline") { - GSCodeReserve::GetInstance().Reset(); + GSCodeReserve::ResetMemory(); } GSDrawScanline::~GSDrawScanline() { - if (const size_t used = GSCodeReserve::GetInstance().GetMemoryUsed(); used > 0) + if (const size_t used = GSCodeReserve::GetMemoryUsed(); used > 0) DevCon.WriteLn("SW JIT generated %zu bytes of code", used); } @@ -82,7 +82,7 @@ void GSDrawScanline::ResetCodeCache() Console.Warning("GS Software JIT cache overflow, resetting."); m_sp_map.Clear(); m_ds_map.Clear(); - GSCodeReserve::GetInstance().Reset(); + GSCodeReserve::ResetMemory(); } bool GSDrawScanline::SetupDraw(GSRasterizerData& data) diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 86514cd628..7b61133d59 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -20,7 +20,6 @@ #include "Hardware.h" #include "SPU2/spu2.h" #include "USB/USB.h" -#include "x86/newVif.h" #include "common/WrappedMemCopy.h" @@ -31,35 +30,8 @@ using namespace R5900; const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX int rdram_sdevid = 0; -static bool hwInitialized = false; - -void hwInit() -{ - // [TODO] / FIXME: PCSX2 no longer works on an Init system. It assumes that the - // static global vars for the process will be initialized when the process is created, and - // then issues *resets only* from then on. (reset code for various S2 components should do - // NULL checks and allocate memory and such if the pointers are NULL only). - - if( hwInitialized ) return; - - VifUnpackSSE_Init(); - - hwInitialized = true; -} - -void hwShutdown() -{ - if (!hwInitialized) return; - - VifUnpackSSE_Destroy(); - - hwInitialized = false; -} - void hwReset() { - hwInit(); - std::memset(eeHw, 0, sizeof(eeHw)); psHu32(SBUS_F260) = 0x1D000060; diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h index 51ab5396ef..ca1d040e4c 100644 --- a/pcsx2/Hw.h +++ b/pcsx2/Hw.h @@ -364,7 +364,6 @@ enum GSRegisterAddresses }; extern void hwReset(); -extern void hwShutdown(); extern const int rdram_devices; extern int rdram_sdevid; diff --git a/pcsx2/IopMem.cpp b/pcsx2/IopMem.cpp index ff6c173c03..49455dea0b 100644 --- a/pcsx2/IopMem.cpp +++ b/pcsx2/IopMem.cpp @@ -30,35 +30,20 @@ IopVM_MemoryAllocMess* iopMem = NULL; alignas(__pagesize) u8 iopHw[Ps2MemSize::IopHardware]; -// -------------------------------------------------------------------------------------- -// iopMemoryReserve -// -------------------------------------------------------------------------------------- -iopMemoryReserve::iopMemoryReserve() - : _parent("IOP Main Memory (2mb)") -{ -} - -iopMemoryReserve::~iopMemoryReserve() -{ - Release(); -} - -void iopMemoryReserve::Assign(VirtualMemoryManagerPtr allocator) +void iopMemAlloc() { + // TODO: Move to memmap psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16); if (!psxMemWLUT) pxFailRel("Failed to allocate IOP memory lookup table"); psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); - VtlbMemoryReserve::Assign(std::move(allocator), HostMemoryMap::IOPmemOffset, sizeof(*iopMem)); - iopMem = reinterpret_cast(GetPtr()); + iopMem = reinterpret_cast(SysMemory::GetCodePtr(HostMemoryMap::IOPmemOffset)); } -void iopMemoryReserve::Release() +void iopMemRelease() { - _parent::Release(); - safe_aligned_free(psxMemWLUT); psxMemRLUT = nullptr; iopMem = nullptr; @@ -66,10 +51,8 @@ void iopMemoryReserve::Release() // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated, // which is performed by MemInit and PsxMemInit() -void iopMemoryReserve::Reset() +void iopMemReset() { - _parent::Reset(); - pxAssert( iopMem ); DbgCon.WriteLn("IOP resetting main memory..."); diff --git a/pcsx2/IopMem.h b/pcsx2/IopMem.h index 372b2482b4..43550cd445 100644 --- a/pcsx2/IopMem.h +++ b/pcsx2/IopMem.h @@ -71,10 +71,9 @@ static __fi u8* iopPhysMem( u32 addr ) #define psxHu16(mem) (*(u16*)&iopHw[(mem) & 0xffff]) #define psxHu32(mem) (*(u32*)&iopHw[(mem) & 0xffff]) -extern void psxMemReserve(); -extern void psxMemAlloc(); -extern void psxMemReset(); -extern void psxMemShutdown(); +extern void iopMemAlloc(); +extern void iopMemReset(); +extern void iopMemRelease(); extern u8 iopMemRead8 (u32 mem); extern u16 iopMemRead16(u32 mem); diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 72a407201d..89fb669100 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -701,28 +701,13 @@ void memBindConditionalHandlers() // -------------------------------------------------------------------------------------- // eeMemoryReserve (implementations) // -------------------------------------------------------------------------------------- -eeMemoryReserve::eeMemoryReserve() - : _parent("EE Main Memory") +void memAllocate() { + eeMem = reinterpret_cast(SysMemory::GetEEMem()); } -eeMemoryReserve::~eeMemoryReserve() +void memReset() { - Release(); -} - -void eeMemoryReserve::Assign(VirtualMemoryManagerPtr allocator) -{ - _parent::Assign(std::move(allocator), HostMemoryMap::EEmemOffset, sizeof(*eeMem)); - eeMem = reinterpret_cast(GetPtr()); -} - - -// Resets memory mappings, unmaps TLBs, reloads bios roms, etc. -void eeMemoryReserve::Reset() -{ - _parent::Reset(); - // Note!! Ideally the vtlb should only be initialized once, and then subsequent // resets of the system hardware would only clear vtlb mappings, but since the // rest of the emu is not really set up to support a "soft" reset of that sort @@ -842,8 +827,7 @@ void eeMemoryReserve::Reset() CopyBIOSToMemory(); } -void eeMemoryReserve::Release() +void memRelease() { eeMem = nullptr; - _parent::Release(); } diff --git a/pcsx2/Memory.h b/pcsx2/Memory.h index ad8f14b66b..09130c9526 100644 --- a/pcsx2/Memory.h +++ b/pcsx2/Memory.h @@ -97,6 +97,9 @@ static __fi void ZeroQWC( u128& dest ) #define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff]) #define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff]) +extern void memAllocate(); +extern void memReset(); +extern void memRelease(); extern void memSetKernelMode(); //extern void memSetSupervisorMode(); diff --git a/pcsx2/MemoryTypes.h b/pcsx2/MemoryTypes.h index 401c3b9686..f9310fa54d 100644 --- a/pcsx2/MemoryTypes.h +++ b/pcsx2/MemoryTypes.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -18,18 +18,19 @@ namespace Ps2MemSize { - static const uint MainRam = _32mb; // 32 MB main memory! - static const uint Rom = _1mb * 4; // 4 MB main rom - static const uint Rom1 = _1mb * 4; // DVD player - static const uint Rom2 = 0x00080000; // Chinese rom extension - static const uint Hardware = _64kb; - static const uint Scratch = _16kb; + static constexpr u32 MainRam = _32mb; // 32 MB main memory. + static constexpr u32 ExtraRam = _1mb * 96; // 32+96 MB devkit memory. + static constexpr u32 Rom = _1mb * 4; // 4 MB main rom + static constexpr u32 Rom1 = _1mb * 4; // DVD player + static constexpr u32 Rom2 = 0x00080000; // Chinese rom extension + static constexpr u32 Hardware = _64kb; + static constexpr u32 Scratch = _16kb; - static const uint IopRam = _1mb * 2; // 2MB main ram on the IOP. - static const uint IopHardware = _64kb; + static constexpr u32 IopRam = _1mb * 2; // 2MB main ram on the IOP. + static constexpr u32 IopHardware = _64kb; - static const uint GSregs = 0x00002000; // 8k for the GS registers and stuff. -} + static constexpr u32 GSregs = 0x00002000; // 8k for the GS registers and stuff. +} // namespace Ps2MemSize typedef u8 mem8_t; typedef u16 mem16_t; @@ -39,11 +40,12 @@ typedef u128 mem128_t; struct EEVM_MemoryAllocMess { - u8 Main[Ps2MemSize::MainRam]; // Main memory (hard-wired to 32MB) - u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad! - u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB) - u8 ROM1[Ps2MemSize::Rom1]; // DVD player (4MB) - u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions + u8 Main[Ps2MemSize::MainRam]; // Main memory (hard-wired to 32MB) + u8 ExtraMemory[Ps2MemSize::ExtraRam]; // Extra memory (32MB up to 128MB => 96MB). + u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad! + u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB) + u8 ROM1[Ps2MemSize::Rom1]; // DVD player (4MB) + u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions // Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB). // Such accesses are not documented as causing bus errors but as the memory does @@ -56,9 +58,9 @@ struct EEVM_MemoryAllocMess struct IopVM_MemoryAllocMess { - u8 Main[Ps2MemSize::IopRam]; // Main memory (hard-wired to 2MB) - u8 P[_64kb]; // I really have no idea what this is... --air - u8 Sif[0x100]; // a few special SIF/SBUS registers (likely not needed) + u8 Main[Ps2MemSize::IopRam]; // Main memory (hard-wired to 2MB) + u8 P[_64kb]; // I really have no idea what this is... --air + u8 Sif[0x100]; // a few special SIF/SBUS registers (likely not needed) }; diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 7fe439fabb..85baa2de31 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -17,6 +17,7 @@ #define _PC_ // disables MIPS opcode macros. +#include "common/Assertions.h" #include "common/ByteSwap.h" #include "common/FileSystem.h" #include "common/Path.h" diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index af4a3dc0e0..e330d67941 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -207,7 +207,6 @@ extern R3000Acpu psxRec; extern void psxReset(); extern void psxException(u32 code, u32 step); extern void iopEventTest(); -extern void psxMemReset(); int psxIsBreakpointNeeded(u32 addr); int psxIsMemcheckNeeded(u32 pc); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index b046b75528..c353a0c254 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -67,12 +67,8 @@ const int kMaxArgs = 16; uptr g_argPtrs[kMaxArgs]; #define DEBUG_LAUNCHARG 0 // show lots of helpful console messages as the launch arguments are passed to the game -extern SysMainMemory& GetVmMemory(); - void cpuReset() { - GetVmMemory().Reset(); - std::memset(&cpuRegs, 0, sizeof(cpuRegs)); std::memset(&fpuRegs, 0, sizeof(fpuRegs)); std::memset(&tlb, 0, sizeof(tlb)); @@ -91,8 +87,6 @@ void cpuReset() psxReset(); pgifInit(); - hwReset(); - extern void Deci2Reset(); // lazy, no good header for it yet. Deci2Reset(); diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 2d49676527..66f6627d60 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -248,48 +248,19 @@ struct R5900cpu // the virtual cpu provider. Allocating additional heap memory from this method is // NOT recommended. Heap allocations should be performed by Reset only. This // maximizes the likeliness of reservations claiming addresses they prefer. - // - // Thread Affinity: - // Called from the main/UI thread only. Cpu execution status is guaranteed to - // be inactive. No locking is necessary. - // - // Exception Throws: - // HardwareDeficiency - The host machine's hardware does not support this CPU provider. - // OutOfMemory - Not enough memory, or the memory areas required were already - // reserved. void (*Reserve)(); // Deallocates ram allocated by Allocate, Reserve, and/or by runtime code execution. - // - // Thread Affinity: - // Called from the main/UI thread only. Cpu execution status is guaranteed to - // be inactive. No locking is necessary. - // - // Exception Throws: None. This function is a destructor, and should not throw. - // void (*Shutdown)(); // Initializes / Resets code execution states. Typically implementation is only // needed for recompilers, as interpreters have no internal execution states and // rely on the CPU/VM states almost entirely. - // - // Thread Affinity: - // Can be called from any thread. CPU execution status is indeterminate and may - // already be in progress. Implementations should be sure to queue and execute - // resets at the earliest safe convenience (typically right before recompiling a - // new block of code, or after a vsync event). - // - // Exception Throws: Emulator-defined. Common exception types to expect are - // OutOfMemory, Stream Exceptions - // void (*Reset)(); // Steps a single instruction. Meant to be used by debuggers. Is currently unused // and unimplemented. Future note: recompiler "step" should *always* fall back // on interpreters. - // - // Exception Throws: [TODO] (possible execution-related throws to be added) - // void (*Step)(); // Executes code until a break is signaled. Execution can be paused or suspended @@ -297,11 +268,6 @@ struct R5900cpu // Execution Breakages are handled the same way, where-by a signal causes the Execute // call to return at the nearest state check (typically handled internally using // either C++ exceptions or setjmp/longjmp). - // - // Exception Throws: - // Throws BaseR5900Exception and all derivatives. - // Throws FileNotFound or other Streaming errors (typically related to BIOS MEC/NVM) - // void (*Execute)(); // Immediately exits execution of recompiled code if we are in a state to do so, or @@ -319,13 +285,6 @@ struct R5900cpu // Also: the calls from COP0's TLB remap code should be replaced with full recompiler // resets, since TLB remaps affect more than just the code they contain (code that // may reference the remapped blocks via memory loads/stores, for example). - // - // Thread Affinity Rule: - // Can be called from any thread (namely for being called from debugging threads) - // - // Exception Throws: [TODO] Emulator defined? (probably shouldn't throw, probably - // doesn't matter if we're stripping it out soon. ;) - // void (*Clear)(u32 Addr, u32 Size); }; diff --git a/pcsx2/SIO/Memcard/MemoryCardFile.cpp b/pcsx2/SIO/Memcard/MemoryCardFile.cpp index da300057ea..98c2842965 100644 --- a/pcsx2/SIO/Memcard/MemoryCardFile.cpp +++ b/pcsx2/SIO/Memcard/MemoryCardFile.cpp @@ -20,6 +20,7 @@ #include "SIO/Memcard/MemoryCardFolder.h" #include "SIO/Sio.h" +#include "common/Assertions.h" #include "common/FileSystem.h" #include "common/Path.h" #include "common/StringUtil.h" diff --git a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp index e124978682..71ac149cb9 100644 --- a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp +++ b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp @@ -18,6 +18,7 @@ #include "SIO/Memcard/MemoryCardFile.h" #include "SIO/Memcard/MemoryCardFolder.h" +#include "common/Assertions.h" #include "common/Path.h" #include "System.h" diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 6070139a71..9ddd098fe8 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -20,6 +20,8 @@ #include "CDVD/CDVD.h" #include "Elfheader.h" #include "GSDumpReplayer.h" +#include "Host.h" +#include "IopMem.h" #include "MTVU.h" #include "R3000A.h" #include "VUmicro.h" @@ -44,6 +46,20 @@ SSE_MXCSR g_sseMXCSR = {DEFAULT_sseMXCSR}; SSE_MXCSR g_sseVU0MXCSR = {DEFAULT_sseVUMXCSR}; SSE_MXCSR g_sseVU1MXCSR = {DEFAULT_sseVUMXCSR}; +namespace SysMemory +{ + static u8* TryAllocateVirtualMemory(const char* name, void* file_handle, uptr base, size_t size); + static u8* AllocateVirtualMemory(const char* name, void* file_handle, size_t size, size_t offset_from_base); + + static bool AllocateMemoryMap(); + static void DumpMemoryMap(); + static void ReleaseMemoryMap(); + + static u8* s_data_memory; + static void* s_data_memory_file_handle; + static u8* s_code_memory; +} // namespace SysMemory + // SetCPUState -- for assignment of SSE roundmodes and clampmodes. // void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVU0MXCSR, SSE_MXCSR sseVU1MXCSR) @@ -140,20 +156,55 @@ namespace HostMemoryMap // For debuggers extern "C" { #ifdef _WIN32 - _declspec(dllexport) uptr EEmem, IOPmem, VUmem, EErec, IOPrec, VIF0rec, VIF1rec, mVU0rec, mVU1rec, SWjit, bumpAllocator; + _declspec(dllexport) uptr EEmem, IOPmem, VUmem; #else - __attribute__((visibility("default"), used)) uptr EEmem, IOPmem, VUmem, EErec, IOPrec, VIF0rec, VIF1rec, mVU0rec, mVU1rec, SWjit, bumpAllocator; + __attribute__((visibility("default"), used)) uptr EEmem, IOPmem, VUmem; #endif } } // namespace HostMemoryMap -/// Attempts to find a spot near static variables for the main memory -static VirtualMemoryManagerPtr makeMemoryManager(const char* name, const char* file_mapping_name, size_t size, size_t offset_from_base) +u8* SysMemory::TryAllocateVirtualMemory(const char* name, void* file_handle, uptr base, size_t size) { + u8* baseptr; + + if (file_handle) + baseptr = static_cast(HostSys::MapSharedMemory(file_handle, 0, (void*)base, size, PageAccess_ReadWrite())); + else + baseptr = static_cast(HostSys::Mmap((void*)base, size, PageAccess_Any())); + + if (!baseptr) + return nullptr; + + if ((uptr)baseptr != base) + { + if (file_handle) + { + if (baseptr) + HostSys::UnmapSharedMemory(baseptr, size); + } + else + { + if (baseptr) + HostSys::Munmap(baseptr, size); + } + + return nullptr; + } + + DevCon.WriteLn(Color_Gray, "%-32s @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " %s", name, + baseptr, (uptr)baseptr + size, fmt::format("[{}mb]", size / _1mb).c_str()); + + return baseptr; +} + +u8* SysMemory::AllocateVirtualMemory(const char* name, void* file_handle, size_t size, size_t offset_from_base) +{ + pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Virtual memory size is page aligned"); + // Everything looks nicer when the start of all the sections is a nice round looking number. // Also reduces the variation in the address due to small changes in code. // Breaks ASLR but so does anything else that tries to make addresses constant for our debugging pleasure - uptr codeBase = (uptr)(void*)makeMemoryManager / (1 << 28) * (1 << 28); + uptr codeBase = (uptr)(void*)AllocateVirtualMemory / (1 << 28) * (1 << 28); // The allocation is ~640mb in size, slighly under 3*2^28. // We'll hope that the code generated for the PCSX2 executable stays under 512mb (which is likely) @@ -167,122 +218,177 @@ static VirtualMemoryManagerPtr makeMemoryManager(const char* name, const char* f // VTLB will throw a fit if we try to put EE main memory here continue; } - auto mgr = std::make_shared(name, file_mapping_name, base, size, /*upper_bounds=*/0, /*strict=*/true); - if (mgr->IsOk()) - { - return mgr; - } + + if (u8* ret = TryAllocateVirtualMemory(name, file_handle, base, size)) + return ret; + + DevCon.Warning("%s: host memory @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " is unavailable; attempting to map elsewhere...", name, + base, base + size); } - // If the above failed and it's x86-64, recompiled code is going to break! - // If it's i386 anything can reach anything so it doesn't matter - if (sizeof(void*) == 8) + return nullptr; +} + +bool SysMemory::AllocateMemoryMap() +{ + s_data_memory_file_handle = HostSys::CreateSharedMemory(HostSys::GetFileMappingName("pcsx2").c_str(), HostMemoryMap::MainSize); + if (!s_data_memory_file_handle) { - pxAssertRel(0, "Failed to find a good place for the memory allocation, recompilers may fail"); + Host::ReportErrorAsync("Error", "Failed to create shared memory file."); + ReleaseMemoryMap(); + return false; } - return std::make_shared(name, file_mapping_name, 0, size); + + if ((s_data_memory = AllocateVirtualMemory("Data Memory", s_data_memory_file_handle, HostMemoryMap::MainSize, 0)) == nullptr) + { + Host::ReportErrorAsync("Error", "Failed to map data memory at an acceptable location."); + ReleaseMemoryMap(); + return false; + } + + if ((s_code_memory = AllocateVirtualMemory("Code Memory", nullptr, HostMemoryMap::CodeSize, HostMemoryMap::MainSize)) == nullptr) + { + Host::ReportErrorAsync("Error", "Failed to allocate code memory at an acceptable location."); + ReleaseMemoryMap(); + return false; + } + + HostMemoryMap::EEmem = (uptr)(s_data_memory + HostMemoryMap::EEmemOffset); + HostMemoryMap::IOPmem = (uptr)(s_data_memory + HostMemoryMap::IOPmemOffset); + HostMemoryMap::VUmem = (uptr)(s_data_memory + HostMemoryMap::VUmemSize); + + DumpMemoryMap(); + return true; } -// -------------------------------------------------------------------------------------- -// SysReserveVM (implementations) -// -------------------------------------------------------------------------------------- -SysMainMemory::SysMainMemory() - : m_mainMemory(makeMemoryManager("Main Memory Manager", "pcsx2", HostMemoryMap::MainSize, 0)) - , m_codeMemory(makeMemoryManager("Code Memory Manager", nullptr, HostMemoryMap::CodeSize, HostMemoryMap::MainSize)) - , m_bumpAllocator(m_mainMemory, HostMemoryMap::bumpAllocatorOffset, HostMemoryMap::MainSize - HostMemoryMap::bumpAllocatorOffset) +void SysMemory::DumpMemoryMap() { - uptr main_base = (uptr)MainMemory()->GetBase(); - uptr code_base = (uptr)MainMemory()->GetBase(); - HostMemoryMap::EEmem = main_base + HostMemoryMap::EEmemOffset; - HostMemoryMap::IOPmem = main_base + HostMemoryMap::IOPmemOffset; - HostMemoryMap::VUmem = main_base + HostMemoryMap::VUmemOffset; - HostMemoryMap::EErec = code_base + HostMemoryMap::EErecOffset; - HostMemoryMap::IOPrec = code_base + HostMemoryMap::IOPrecOffset; - HostMemoryMap::VIF0rec = code_base + HostMemoryMap::VIF0recOffset; - HostMemoryMap::VIF1rec = code_base + HostMemoryMap::VIF1recOffset; - HostMemoryMap::mVU0rec = code_base + HostMemoryMap::mVU0recOffset; - HostMemoryMap::mVU1rec = code_base + HostMemoryMap::mVU1recOffset; - HostMemoryMap::bumpAllocator = main_base + HostMemoryMap::bumpAllocatorOffset; +#define DUMP_REGION(name, base, offset, size) \ + DevCon.WriteLn(Color_Gray, "%-32s @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " %s", name, \ + (uptr)(base + offset), (uptr)(base + offset + size), fmt::format("[{}mb]", size / _1mb).c_str()); + + DUMP_REGION("EE Main Memory", s_data_memory, HostMemoryMap::EEmemOffset, HostMemoryMap::EEmemSize); + DUMP_REGION("IOP Main Memory", s_data_memory, HostMemoryMap::IOPmemOffset, HostMemoryMap::IOPmemSize); + DUMP_REGION("VU0/1 On-Chip Memory", s_data_memory, HostMemoryMap::VUmemOffset, HostMemoryMap::VUmemSize); + DUMP_REGION("VTLB Virtual Map", s_data_memory, HostMemoryMap::VTLBAddressMapOffset, HostMemoryMap::VTLBVirtualMapSize); + DUMP_REGION("VTLB Address Map", s_data_memory, HostMemoryMap::VTLBAddressMapSize, HostMemoryMap::VTLBAddressMapSize); + + DUMP_REGION("R5900 Recompiler Cache", s_code_memory, HostMemoryMap::EErecOffset, HostMemoryMap::EErecSize); + DUMP_REGION("R3000A Recompiler Cache", s_code_memory, HostMemoryMap::IOPrecOffset, HostMemoryMap::IOPrecSize); + DUMP_REGION("Micro VU0 Recompiler Cache", s_code_memory, HostMemoryMap::mVU0recOffset, HostMemoryMap::mVU0recSize); + DUMP_REGION("Micro VU0 Recompiler Cache", s_code_memory, HostMemoryMap::mVU1recOffset, HostMemoryMap::mVU1recSize); + DUMP_REGION("VIF0 Unpack Recompiler Cache", s_code_memory, HostMemoryMap::VIF0recOffset, HostMemoryMap::VIF0recSize); + DUMP_REGION("VIF1 Unpack Recompiler Cache", s_code_memory, HostMemoryMap::VIF1recOffset, HostMemoryMap::VIF1recSize); + DUMP_REGION("VIF Unpack Recompiler Cache", s_code_memory, HostMemoryMap::VIFUnpackRecOffset, HostMemoryMap::VIFUnpackRecSize); + DUMP_REGION("GS Software Renderer", s_code_memory, HostMemoryMap::SWrecOffset, HostMemoryMap::SWrecSize); + + +#undef DUMP_REGION } -SysMainMemory::~SysMainMemory() +void SysMemory::ReleaseMemoryMap() { - Release(); + if (s_code_memory) + { + HostSys::Munmap(s_code_memory, HostMemoryMap::CodeSize); + s_code_memory = nullptr; + } + + if (s_data_memory) + { + HostSys::UnmapSharedMemory(s_data_memory, HostMemoryMap::MainSize); + s_data_memory = nullptr; + } + + if (s_data_memory_file_handle) + { + HostSys::DestroySharedMemory(s_data_memory_file_handle); + s_data_memory_file_handle = nullptr; + } } -bool SysMainMemory::Allocate() +bool SysMemory::Allocate() { DevCon.WriteLn(Color_StrongBlue, "Allocating host memory for virtual systems..."); ConsoleIndentScope indent(1); - m_ee.Assign(MainMemory()); - m_iop.Assign(MainMemory()); - m_vu.Assign(MainMemory()); + if (!AllocateMemoryMap()) + return false; - vtlb_Core_Alloc(); + memAllocate(); + iopMemAlloc(); + vuMemAllocate(); + + if (!vtlb_Core_Alloc()) + return false; return true; } -void SysMainMemory::Reset() +void SysMemory::Reset() { DevCon.WriteLn(Color_StrongBlue, "Resetting host memory for virtual systems..."); ConsoleIndentScope indent(1); - m_ee.Reset(); - m_iop.Reset(); - m_vu.Reset(); + memReset(); + iopMemReset(); + vuMemReset(); // Note: newVif is reset as part of other VIF structures. // Software is reset on the GS thread. } -void SysMainMemory::Release() +void SysMemory::Release() { Console.WriteLn(Color_Blue, "Releasing host memory for virtual systems..."); ConsoleIndentScope indent(1); - hwShutdown(); - vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit). releaseNewVif(0); releaseNewVif(1); - m_ee.Release(); - m_iop.Release(); - m_vu.Release(); + vuMemRelease(); + iopMemRelease(); + memRelease(); + + ReleaseMemoryMap(); } +u8* SysMemory::GetDataPtr(size_t offset) +{ + pxAssert(offset <= HostMemoryMap::MainSize); + return s_data_memory + offset; +} + +u8* SysMemory::GetCodePtr(size_t offset) +{ + pxAssert(offset <= HostMemoryMap::CodeSize); + return s_code_memory + offset; +} + +void* SysMemory::GetDataFileHandle() +{ + return s_data_memory_file_handle; +} // -------------------------------------------------------------------------------------- // SysCpuProviderPack (implementations) // -------------------------------------------------------------------------------------- SysCpuProviderPack::SysCpuProviderPack() { - Console.WriteLn(Color_StrongBlue, "Reserving memory for recompilers..."); - ConsoleIndentScope indent(1); - recCpu.Reserve(); psxRec.Reserve(); CpuMicroVU0.Reserve(); CpuMicroVU1.Reserve(); - if constexpr (newVifDynaRec) - { - dVifReserve(0); - dVifReserve(1); - } - - GSCodeReserve::GetInstance().Assign(GetVmMemory().CodeMemory()); + VifUnpackSSE_Init(); } SysCpuProviderPack::~SysCpuProviderPack() { - GSCodeReserve::GetInstance().Release(); - if (newVifDynaRec) { dVifRelease(1); diff --git a/pcsx2/System.h b/pcsx2/System.h index de3b8d3203..8a42290f38 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -16,7 +16,6 @@ #pragma once #include "Config.h" -#include "VirtualMemory.h" #include "vtlb.h" // This is a table of default virtual map addresses for ps2vm components. These locations @@ -35,85 +34,125 @@ namespace HostMemoryMap ////////////////////////////////////////////////////////////////////////// // Main ////////////////////////////////////////////////////////////////////////// - static const u32 MainSize = 0x14000000; - // PS2 main memory, SPR, and ROMs (approximately 40.5MB, but we round up to 64MB for simplicity). - static const u32 EEmemOffset = 0x00000000; + // PS2 main memory, SPR, and ROMs (approximately 138.5MB, but we round up to 139MB for simplicity). + static constexpr u32 EEmemOffset = 0x00000000; + static constexpr u32 EEmemSize = 0x8B00000; - // IOP main memory and ROMs - static const u32 IOPmemOffset = 0x04000000; + // IOP main memory (2MB + 64K + 256b, rounded up to 3MB for simplicity). + static constexpr u32 IOPmemOffset = EEmemOffset + EEmemSize; + static constexpr u32 IOPmemSize = 0x300000; - // VU0 and VU1 memory. - static const u32 VUmemOffset = 0x08000000; + // VU0 and VU1 memory (40KB, rounded up to 1MB for simplicity). + static constexpr u32 VUmemOffset = IOPmemOffset + IOPmemSize; + static constexpr u32 VUmemSize = 0x100000; - // Bump allocator for any other small allocations - // size: Difference between it and HostMemoryMap::Size, so nothing should allocate higher than it! - static const u32 bumpAllocatorOffset = 0x10000000; + // VTLB virtual map ((4GB / 4096) * sizeof(ptr)) + static constexpr u32 VTLBVirtualMapOffset = VUmemOffset + VUmemSize; + static constexpr u32 VTLBVirtualMapSize = (0x100000000ULL / 4096) * sizeof(void*); + + // VTLB address map ((4GB / 4096) * sizeof(u32)) + static constexpr u32 VTLBAddressMapOffset = VTLBVirtualMapOffset + VTLBVirtualMapSize; + static constexpr u32 VTLBAddressMapSize = (0x100000000ULL / 4096) * sizeof(u32); + + // Overall size. + static constexpr u32 MainSize = VTLBAddressMapOffset + VTLBAddressMapSize; ////////////////////////////////////////////////////////////////////////// // Code ////////////////////////////////////////////////////////////////////////// - static const u32 CodeSize = 0x13100000; // 305 mb // EE recompiler code cache area (64mb) - static const u32 EErecOffset = 0x00000000; + static constexpr u32 EErecOffset = 0x00000000; + static constexpr u32 EErecSize = 0x4000000; // IOP recompiler code cache area (32mb) - static const u32 IOPrecOffset = 0x04000000; + static constexpr u32 IOPrecOffset = EErecOffset + EErecSize; + static constexpr u32 IOPrecSize = 0x2000000; // newVif0 recompiler code cache area (8mb) - static const u32 VIF0recOffset = 0x06000000; + static constexpr u32 VIF0recOffset = IOPrecOffset + IOPrecSize; + static constexpr u32 VIF0recSize = 0x800000; // newVif1 recompiler code cache area (8mb) - static const u32 VIF1recOffset = 0x06800000; + static constexpr u32 VIF1recOffset = VIF0recOffset + VIF0recSize; + static constexpr u32 VIF1recSize = 0x800000; // microVU1 recompiler code cache area (64mb) - static const u32 mVU0recOffset = 0x07000000; + static constexpr u32 mVU0recOffset = VIF1recOffset + VIF1recSize; + static constexpr u32 mVU0recSize = 0x4000000; // microVU0 recompiler code cache area (64mb) - static const u32 mVU1recOffset = 0x0B000000; + static constexpr u32 mVU1recOffset = mVU0recOffset + mVU0recSize; + static constexpr u32 mVU1recSize = 0x4000000; // SSE-optimized VIF unpack functions (1mb) - static const u32 VIFUnpackRecOffset = 0x0F000000; + static constexpr u32 VIFUnpackRecOffset = mVU1recOffset + mVU1recSize; + static constexpr u32 VIFUnpackRecSize = 0x100000; // Software Renderer JIT buffer (64mb) - static const u32 SWrecOffset = 0x0F100000; - static const u32 SWrecSize = 0x04000000; -} + static constexpr u32 SWrecOffset = VIFUnpackRecOffset + VIFUnpackRecSize; + static constexpr u32 SWrecSize = 0x04000000; + + // Overall size. + static constexpr u32 CodeSize = SWrecOffset + SWrecSize; // 305 mb +} // namespace HostMemoryMap // -------------------------------------------------------------------------------------- -// SysMainMemory +// HostMemory // -------------------------------------------------------------------------------------- // This class provides the main memory for the virtual machines. -class SysMainMemory final + +namespace SysMemory { -protected: - const VirtualMemoryManagerPtr m_mainMemory; - const VirtualMemoryManagerPtr m_codeMemory; - - VirtualMemoryBumpAllocator m_bumpAllocator; - - eeMemoryReserve m_ee; - iopMemoryReserve m_iop; - vuMemoryReserve m_vu; - -public: - SysMainMemory(); - ~SysMainMemory(); - - const VirtualMemoryManagerPtr& MainMemory() { return m_mainMemory; } - const VirtualMemoryManagerPtr& CodeMemory() { return m_codeMemory; } - - VirtualMemoryBumpAllocator& BumpAllocator() { return m_bumpAllocator; } - - const eeMemoryReserve& EEMemory() const { return m_ee; } - const iopMemoryReserve& IOPMemory() const { return m_iop; } - const vuMemoryReserve& VUMemory() const { return m_vu; } - bool Allocate(); void Reset(); void Release(); -}; + + /// Returns data memory (Main in Memory Map). + u8* GetDataPtr(size_t offset); + + /// Returns memory used for the recompilers. + u8* GetCodePtr(size_t offset); + + /// Returns the file mapping which backs the data memory. + void* GetDataFileHandle(); + + // clang-format off + + ////////////////////////////////////////////////////////////////////////// + // Data Memory Accessors + ////////////////////////////////////////////////////////////////////////// + __fi static u8* GetEEMem() { return GetDataPtr(HostMemoryMap::EEmemOffset); } + __fi static u8* GetEEMemEnd() { return GetDataPtr(HostMemoryMap::EEmemOffset + HostMemoryMap::EEmemSize); } + __fi static u8* GetIOPMem() { return GetDataPtr(HostMemoryMap::IOPmemOffset); } + __fi static u8* GetIOPMemEnd() { return GetDataPtr(HostMemoryMap::IOPmemOffset + HostMemoryMap::IOPmemSize); } + __fi static u8* GetVUMem() { return GetDataPtr(HostMemoryMap::VUmemOffset); } + __fi static u8* GetVUMemEnd() { return GetDataPtr(HostMemoryMap::VUmemOffset + HostMemoryMap::VUmemSize); } + __fi static u8* GetVTLBVirtualMap() { return GetDataPtr(HostMemoryMap::VTLBVirtualMapOffset); } + __fi static u8* GetVTLBVirtualMapEnd() { return GetDataPtr(HostMemoryMap::VTLBVirtualMapOffset + HostMemoryMap::VTLBVirtualMapSize); } + __fi static u8* GetVTLBAddressMap() { return GetDataPtr(HostMemoryMap::VTLBAddressMapOffset); } + __fi static u8* GetVTLBAddressMapEnd() { return GetDataPtr(HostMemoryMap::VTLBAddressMapOffset + HostMemoryMap::VTLBAddressMapSize); } + + ////////////////////////////////////////////////////////////////////////// + // Code Memory Accessors + ////////////////////////////////////////////////////////////////////////// + __fi static u8* GetEERec() { return GetCodePtr(HostMemoryMap::EErecOffset); } + __fi static u8* GetEERecEnd() { return GetCodePtr(HostMemoryMap::EErecOffset + HostMemoryMap::EErecSize); } + __fi static u8* GetIOPRec() { return GetCodePtr(HostMemoryMap::IOPrecOffset); } + __fi static u8* GetIOPRecEnd() { return GetCodePtr(HostMemoryMap::IOPrecOffset + HostMemoryMap::IOPrecSize); } + __fi static u8* GetVU0Rec() { return GetCodePtr(HostMemoryMap::mVU0recOffset); } + __fi static u8* GetVU0RecEnd() { return GetCodePtr(HostMemoryMap::mVU0recOffset + HostMemoryMap::mVU0recSize); } + __fi static u8* GetVU1Rec() { return GetCodePtr(HostMemoryMap::mVU1recOffset); } + __fi static u8* GetVU1RecEnd() { return GetCodePtr(HostMemoryMap::mVU1recOffset + HostMemoryMap::mVU1recSize); } + __fi static u8* GetVIFUnpackRec() { return GetCodePtr(HostMemoryMap::VIFUnpackRecOffset); } + __fi static u8* GetVIFUnpackRecEnd() { return GetCodePtr(HostMemoryMap::VIFUnpackRecOffset + HostMemoryMap::VIFUnpackRecSize); } + __fi static u8* GetSWRec() { return GetCodePtr(HostMemoryMap::SWrecOffset); } + __fi static u8* GetSWRecEnd() { return GetCodePtr(HostMemoryMap::SWrecOffset + HostMemoryMap::SWrecSize); } + + // clang-format on +} // namespace SysMemory + // -------------------------------------------------------------------------------------- // SysCpuProviderPack @@ -131,10 +170,8 @@ public: // implemented by the provisioning interface. extern SysCpuProviderPack& GetCpuProviders(); -extern void SysLogMachineCaps(); // Detects cpu type and fills cpuInfo structs. -extern void SysClearExecutionCache(); // clears recompiled execution caches! - -extern SysMainMemory& GetVmMemory(); +extern void SysLogMachineCaps(); // Detects cpu type and fills cpuInfo structs. +extern void SysClearExecutionCache(); // clears recompiled execution caches! extern void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVU0MXCSR, SSE_MXCSR sseVU1MXCSR); extern SSE_MXCSR g_sseVU0MXCSR, g_sseVU1MXCSR, g_sseMXCSR; diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 02aac482b6..ec0d0633bd 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -147,7 +147,6 @@ namespace VMManager static constexpr u32 SETTINGS_VERSION = 1; -static std::unique_ptr s_vm_memory; static std::unique_ptr s_cpu_provider_pack; static std::unique_ptr s_game_settings_interface; static std::unique_ptr s_input_settings_interface; @@ -349,15 +348,15 @@ bool VMManager::Internal::CPUThreadInitialize() x86caps.SIMD_EstablishMXCSRmask(); SysLogMachineCaps(); - pxAssert(!s_vm_memory && !s_cpu_provider_pack); - s_vm_memory = std::make_unique(); - s_cpu_provider_pack = std::make_unique(); - if (!s_vm_memory->Allocate()) + if (!SysMemory::Allocate()) { Host::ReportErrorAsync("Error", "Failed to allocate VM memory."); return false; } + pxAssert(!s_cpu_provider_pack); + s_cpu_provider_pack = std::make_unique(); + GSinit(); USBinit(); @@ -388,7 +387,6 @@ void VMManager::Internal::CPUThreadShutdown() WaitForSaveStateFlush(); s_cpu_provider_pack.reset(); - s_vm_memory.reset(); PerformanceMetrics::SetCPUThread(Threading::ThreadHandle()); @@ -397,16 +395,13 @@ void VMManager::Internal::CPUThreadShutdown() MTGS::ShutdownThread(); + SysMemory::Release(); + #ifdef _WIN32 CoUninitialize(); #endif } -SysMainMemory& GetVmMemory() -{ - return *s_vm_memory; -} - SysCpuProviderPack& GetCpuProviders() { return *s_cpu_provider_pack; @@ -1296,8 +1291,9 @@ bool VMManager::Initialize(VMBootParameters boot_params) SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVU0MXCSR, EmuConfig.Cpu.sseVU1MXCSR); SysClearExecutionCache(); memBindConditionalHandlers(); - + SysMemory::Reset(); cpuReset(); + hwReset(); Console.WriteLn("VM subsystems initialized in %.2f ms", init_timer.GetTimeMilliseconds()); s_state.store(VMState::Paused, std::memory_order_release); @@ -1438,7 +1434,9 @@ void VMManager::Reset() SysClearExecutionCache(); memBindConditionalHandlers(); + SysMemory::Reset(); cpuReset(); + hwReset(); if (g_InputRecording.isActive()) { diff --git a/pcsx2/VU.h b/pcsx2/VU.h index fc06085412..f350fa5ff5 100644 --- a/pcsx2/VU.h +++ b/pcsx2/VU.h @@ -233,4 +233,7 @@ static VURegs& VU1 = vuRegs[1]; inline bool VURegs::IsVU1() const { return this == &vuRegs[1]; } inline bool VURegs::IsVU0() const { return this == &vuRegs[0]; } +extern void vuMemAllocate(); +extern void vuMemReset(); +extern void vuMemRelease(); extern u32* GET_VU_MEM(VURegs* VU, u32 addr); diff --git a/pcsx2/VUmicroMem.cpp b/pcsx2/VUmicroMem.cpp index cde1914ae5..2aea8bc7fe 100644 --- a/pcsx2/VUmicroMem.cpp +++ b/pcsx2/VUmicroMem.cpp @@ -21,42 +21,23 @@ alignas(16) VURegs vuRegs[2]; - -vuMemoryReserve::vuMemoryReserve() - : _parent("VU0/1 on-chip memory") +void vuMemAllocate() { -} - -vuMemoryReserve::~vuMemoryReserve() -{ - Release(); -} - -void vuMemoryReserve::Assign(VirtualMemoryManagerPtr allocator) -{ - static constexpr u32 VU_MEMORY_RESERVE_SIZE = VU1_PROGSIZE + VU1_MEMSIZE + VU0_PROGSIZE + VU0_MEMSIZE; - - _parent::Assign(std::move(allocator), HostMemoryMap::VUmemOffset, VU_MEMORY_RESERVE_SIZE); - - u8* curpos = GetPtr(); + u8* curpos = SysMemory::GetDataPtr(HostMemoryMap::VUmemOffset); VU0.Micro = curpos; curpos += VU0_PROGSIZE; VU0.Mem = curpos; curpos += VU0_MEMSIZE; VU1.Micro = curpos; curpos += VU1_PROGSIZE; VU1.Mem = curpos; curpos += VU1_MEMSIZE; } -void vuMemoryReserve::Release() +void vuMemRelease() { - _parent::Release(); - VU0.Micro = VU0.Mem = nullptr; VU1.Micro = VU1.Mem = nullptr; } -void vuMemoryReserve::Reset() +void vuMemReset() { - _parent::Reset(); - pxAssert( VU0.Mem ); pxAssert( VU1.Mem ); diff --git a/pcsx2/VirtualMemory.cpp b/pcsx2/VirtualMemory.cpp deleted file mode 100644 index c8a27b4aa5..0000000000 --- a/pcsx2/VirtualMemory.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#include "VirtualMemory.h" - -#include "common/BitUtils.h" -#include "common/Console.h" -#include "common/Perf.h" - -#include "fmt/core.h" - -#include - -// -------------------------------------------------------------------------------------- -// VirtualMemoryManager (implementations) -// -------------------------------------------------------------------------------------- - -VirtualMemoryManager::VirtualMemoryManager(std::string name, const char* file_mapping_name, uptr base, size_t size, uptr upper_bounds, bool strict) - : m_name(std::move(name)) - , m_file_handle(nullptr) - , m_baseptr(0) - , m_pageuse(nullptr) - , m_pages_reserved(0) -{ - if (!size) - return; - - size_t reserved_bytes = Common::PageAlign(size); - m_pages_reserved = reserved_bytes / __pagesize; - - if (file_mapping_name && file_mapping_name[0]) - { - std::string real_file_mapping_name(HostSys::GetFileMappingName(file_mapping_name)); - m_file_handle = HostSys::CreateSharedMemory(real_file_mapping_name.c_str(), reserved_bytes); - if (!m_file_handle) - return; - - m_baseptr = static_cast(HostSys::MapSharedMemory(m_file_handle, 0, (void*)base, reserved_bytes, PageAccess_ReadWrite())); - if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))) - { - DevCon.Warning("%s: host memory @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " is unavailable; attempting to map elsewhere...", - m_name.c_str(), base, base + size); - - SafeSysMunmap(m_baseptr, reserved_bytes); - - if (base) - { - // Let's try again at an OS-picked memory area, and then hope it meets needed - // boundschecking criteria below. - m_baseptr = static_cast(HostSys::MapSharedMemory(m_file_handle, 0, nullptr, reserved_bytes, PageAccess_ReadWrite())); - } - } - } - else - { - m_baseptr = static_cast(HostSys::Mmap((void*)base, reserved_bytes, PageAccess_Any())); - - if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))) - { - DevCon.Warning("%s: host memory @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " is unavailable; attempting to map elsewhere...", - m_name.c_str(), base, base + size); - - SafeSysMunmap(m_baseptr, reserved_bytes); - - if (base) - { - // Let's try again at an OS-picked memory area, and then hope it meets needed - // boundschecking criteria below. - m_baseptr = static_cast(HostSys::Mmap(0, reserved_bytes, PageAccess_Any())); - } - } - } - - bool fulfillsRequirements = true; - if (strict && (uptr)m_baseptr != base) - fulfillsRequirements = false; - if ((upper_bounds != 0) && ((uptr)(m_baseptr + reserved_bytes) > upper_bounds)) - fulfillsRequirements = false; - if (!fulfillsRequirements) - { - if (m_file_handle) - { - if (m_baseptr) - HostSys::UnmapSharedMemory(m_baseptr, reserved_bytes); - m_baseptr = 0; - - HostSys::DestroySharedMemory(m_file_handle); - m_file_handle = nullptr; - } - else - { - SafeSysMunmap(m_baseptr, reserved_bytes); - } - } - - if (!m_baseptr) - return; - - m_pageuse = new std::atomic[m_pages_reserved](); - - std::string mbkb; - uint mbytes = reserved_bytes / _1mb; - if (mbytes) - mbkb = fmt::format("[{}mb]", mbytes); - else - mbkb = fmt::format("[{}kb]", reserved_bytes / 1024); - - DevCon.WriteLn(Color_Gray, "%-32s @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " %s", m_name.c_str(), - m_baseptr, (uptr)m_baseptr + reserved_bytes, mbkb.c_str()); -} - -VirtualMemoryManager::~VirtualMemoryManager() -{ - if (m_pageuse) - delete[] m_pageuse; - if (m_baseptr) - { - if (m_file_handle) - HostSys::UnmapSharedMemory((void*)m_baseptr, m_pages_reserved * __pagesize); - else - HostSys::Munmap(m_baseptr, m_pages_reserved * __pagesize); - } - if (m_file_handle) - HostSys::DestroySharedMemory(m_file_handle); -} - -static bool VMMMarkPagesAsInUse(std::atomic* begin, std::atomic* end) -{ - for (auto current = begin; current < end; current++) - { - bool expected = false; - if (!current->compare_exchange_strong(expected, true, std::memory_order_relaxed)) - { - // This was already allocated! Undo the things we've set until this point - while (--current >= begin) - { - if (!current->compare_exchange_strong(expected, false, std::memory_order_relaxed)) - { - // In the time we were doing this, someone set one of the things we just set to true back to false - // This should never happen, but if it does we'll just stop and hope nothing bad happens - pxAssert(0); - return false; - } - } - return false; - } - } - return true; -} - -u8* VirtualMemoryManager::Alloc(uptr offsetLocation, size_t size) const -{ - size = Common::PageAlign(size); - if (!pxAssertDev(offsetLocation % __pagesize == 0, "(VirtualMemoryManager) alloc at unaligned offsetLocation")) - return nullptr; - if (!pxAssertDev(size + offsetLocation <= m_pages_reserved * __pagesize, "(VirtualMemoryManager) alloc outside reserved area")) - return nullptr; - if (m_baseptr == 0) - return nullptr; - auto puStart = &m_pageuse[offsetLocation / __pagesize]; - auto puEnd = &m_pageuse[(offsetLocation + size) / __pagesize]; - if (!pxAssertDev(VMMMarkPagesAsInUse(puStart, puEnd), "(VirtualMemoryManager) allocation requests overlapped")) - return nullptr; - return m_baseptr + offsetLocation; -} - -void VirtualMemoryManager::Free(void* address, size_t size) const -{ - uptr offsetLocation = (uptr)address - (uptr)m_baseptr; - if (!pxAssertDev(offsetLocation % __pagesize == 0, "(VirtualMemoryManager) free at unaligned address")) - { - uptr newLoc = Common::PageAlign(offsetLocation); - size -= (offsetLocation - newLoc); - offsetLocation = newLoc; - } - if (!pxAssertDev(size % __pagesize == 0, "(VirtualMemoryManager) free with unaligned size")) - size -= size % __pagesize; - if (!pxAssertDev(size + offsetLocation <= m_pages_reserved * __pagesize, "(VirtualMemoryManager) free outside reserved area")) - return; - auto puStart = &m_pageuse[offsetLocation / __pagesize]; - auto puEnd = &m_pageuse[(offsetLocation + size) / __pagesize]; - for (; puStart < puEnd; puStart++) - { - bool expected = true; - if (!puStart->compare_exchange_strong(expected, false, std::memory_order_relaxed)) - { - pxAssertDev(0, "(VirtaulMemoryManager) double-free"); - } - } -} - -// -------------------------------------------------------------------------------------- -// VirtualMemoryBumpAllocator (implementations) -// -------------------------------------------------------------------------------------- -VirtualMemoryBumpAllocator::VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, uptr offsetLocation, size_t size) - : m_allocator(std::move(allocator)) - , m_baseptr(m_allocator->Alloc(offsetLocation, size)) - , m_endptr(m_baseptr + size) -{ - if (m_baseptr.load() == 0) - pxAssertDev(0, "(VirtualMemoryBumpAllocator) tried to construct from bad VirtualMemoryManager"); -} - -u8* VirtualMemoryBumpAllocator::Alloc(size_t size) -{ - if (m_baseptr.load() == 0) // True if constructed from bad VirtualMemoryManager (assertion was on initialization) - return nullptr; - - size_t reservedSize = Common::PageAlign(size); - - u8* out = m_baseptr.fetch_add(reservedSize, std::memory_order_relaxed); - - if (!pxAssertDev(out - reservedSize + size <= m_endptr, "(VirtualMemoryBumpAllocator) ran out of memory")) - return nullptr; - - return out; -} - -// -------------------------------------------------------------------------------------- -// VirtualMemoryReserve (implementations) -// -------------------------------------------------------------------------------------- -VirtualMemoryReserve::VirtualMemoryReserve(std::string name) - : m_name(std::move(name)) -{ -} - -VirtualMemoryReserve::~VirtualMemoryReserve() -{ - pxAssertRel(!m_baseptr, "VirtualMemoryReserve has not been released."); -} - -// Notes: -// * This method should be called if the object is already in an released (unreserved) state. -// Subsequent calls will be ignored, and the existing reserve will be returned. -// -// Parameters: -// baseptr - the new base pointer that's about to be assigned -// size - size of the region pointed to by baseptr -// -void VirtualMemoryReserve::Assign(VirtualMemoryManagerPtr allocator, u8* baseptr, size_t size) -{ - pxAssertRel(size > 0 && Common::IsAlignedPow2(size, __pagesize), "VM allocation is not page aligned"); - pxAssertRel(!m_baseptr, "Virtual memory reserve has already been assigned"); - - m_allocator = std::move(allocator); - m_baseptr = baseptr; - m_size = size; - - std::string mbkb; - uint mbytes = size / _1mb; - if (mbytes) - mbkb = fmt::format("[{}mb]", mbytes); - else - mbkb = fmt::format("[{}kb]", size / 1024); - - DevCon.WriteLn(Color_Gray, "%-32s @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " %s", m_name.c_str(), - m_baseptr, (uptr)m_baseptr + size, mbkb.c_str()); -} - -u8* VirtualMemoryReserve::BumpAllocate(VirtualMemoryBumpAllocator& allocator, size_t size) -{ - u8* base = allocator.Alloc(size); - if (base) - Assign(allocator.GetAllocator(), base, size); - - return base; -} - -void VirtualMemoryReserve::Release() -{ - if (!m_baseptr) - return; - - m_allocator->Free(m_baseptr, m_size); - m_baseptr = nullptr; - m_size = 0; -} - -// -------------------------------------------------------------------------------------- -// RecompiledCodeReserve (implementations) -// -------------------------------------------------------------------------------------- - -// Constructor! -// Parameters: -// name - a nice long name that accurately describes the contents of this reserve. -RecompiledCodeReserve::RecompiledCodeReserve(std::string name) - : VirtualMemoryReserve(std::move(name)) -{ -} - -RecompiledCodeReserve::~RecompiledCodeReserve() -{ - Release(); -} - -void RecompiledCodeReserve::Assign(VirtualMemoryManagerPtr allocator, size_t offset, size_t size) -{ - // Anything passed to the memory allocator must be page aligned. - size = Common::PageAlign(size); - - // Since the memory has already been allocated as part of the main memory map, this should never fail. - u8* base = allocator->Alloc(offset, size); - if (!base) - { - Console.WriteLn("(RecompiledCodeReserve) Failed to allocate %zu bytes for %s at offset %zu", size, m_name.c_str(), offset); - pxFailRel("RecompiledCodeReserve allocation failed."); - } - - VirtualMemoryReserve::Assign(std::move(allocator), base, size); -} - -void RecompiledCodeReserve::Reset() -{ - if (IsDevBuild && m_baseptr) - { - // Clear the recompiled code block to 0xcc (INT3) -- this helps disasm tools show - // the assembly dump more cleanly. We don't clear the block on Release builds since - // it can add a noticeable amount of overhead to large block recompilations. - - std::memset(m_baseptr, 0xCC, m_size); - } -} diff --git a/pcsx2/VirtualMemory.h b/pcsx2/VirtualMemory.h deleted file mode 100644 index d425da2116..0000000000 --- a/pcsx2/VirtualMemory.h +++ /dev/null @@ -1,166 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "common/General.h" -#include "common/Assertions.h" -#include -#include -#include -#include - -// -------------------------------------------------------------------------------------- -// VirtualMemoryManager: Manages the allocation of PCSX2 VM -// Ensures that all memory is close enough together for rip-relative addressing -// -------------------------------------------------------------------------------------- -class VirtualMemoryManager -{ - DeclareNoncopyableObject(VirtualMemoryManager); - - std::string m_name; - - void* m_file_handle; - u8* m_baseptr; - - // An array to track page usage (to trigger asserts if things try to overlap) - std::atomic* m_pageuse; - - // reserved memory (in pages) - u32 m_pages_reserved; - -public: - // If upper_bounds is nonzero and the OS fails to allocate memory that is below it, - // calls to IsOk() will return false and Alloc() will always return null pointers - // strict indicates that the allocation should quietly fail if the memory can't be mapped at `base` - VirtualMemoryManager(std::string name, const char* file_mapping_name, uptr base, size_t size, uptr upper_bounds = 0, bool strict = false); - ~VirtualMemoryManager(); - - bool IsSharedMemory() const { return (m_file_handle != nullptr); } - void* GetFileHandle() const { return m_file_handle; } - u8* GetBase() const { return m_baseptr; } - u8* GetEnd() const { return (m_baseptr + m_pages_reserved * __pagesize); } - - // Request the use of the memory at offsetLocation bytes from the start of the reserved memory area - // offsetLocation must be page-aligned - u8* Alloc(uptr offsetLocation, size_t size) const; - - u8* AllocAtAddress(void* address, size_t size) const - { - return Alloc(size, static_cast(address) - m_baseptr); - } - - void Free(void* address, size_t size) const; - - // Was this VirtualMemoryManager successfully able to get its memory mapping? - // (If not, calls to Alloc will return null pointers) - bool IsOk() const { return m_baseptr != 0; } -}; - -typedef std::shared_ptr VirtualMemoryManagerPtr; - -// -------------------------------------------------------------------------------------- -// VirtualMemoryBumpAllocator: Allocates memory for things that don't have explicitly-reserved spots -// -------------------------------------------------------------------------------------- -class VirtualMemoryBumpAllocator -{ - const VirtualMemoryManagerPtr m_allocator; - std::atomic m_baseptr{0}; - const u8* m_endptr = 0; - -public: - VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, size_t size, uptr offsetLocation); - u8* Alloc(size_t size); - const VirtualMemoryManagerPtr& GetAllocator() { return m_allocator; } -}; - -// -------------------------------------------------------------------------------------- -// VirtualMemoryReserve -// -------------------------------------------------------------------------------------- -class VirtualMemoryReserve -{ - DeclareNoncopyableObject(VirtualMemoryReserve); - -protected: - std::string m_name; - - // Where the memory came from (so we can return it) - VirtualMemoryManagerPtr m_allocator; - - u8* m_baseptr = nullptr; - size_t m_size = 0; - -public: - VirtualMemoryReserve(std::string name); - virtual ~VirtualMemoryReserve(); - - // Initialize with the given piece of memory - // Note: The memory is already allocated, the allocator is for future use to free the region - // It may be null in which case there is no way to free the memory in a way it will be usable again - void Assign(VirtualMemoryManagerPtr allocator, u8* baseptr, size_t size); - - u8* BumpAllocate(VirtualMemoryBumpAllocator& allocator, size_t size); - - void Release(); - - bool IsOk() const { return m_baseptr != NULL; } - const std::string& GetName() const { return m_name; } - - u8* GetPtr() { return m_baseptr; } - const u8* GetPtr() const { return m_baseptr; } - u8* GetPtrEnd() { return m_baseptr + m_size; } - const u8* GetPtrEnd() const { return m_baseptr + m_size; } - - size_t GetSize() const { return m_size; } - - operator void*() { return m_baseptr; } - operator const void*() const { return m_baseptr; } - - operator u8*() { return (u8*)m_baseptr; } - operator const u8*() const { return (u8*)m_baseptr; } - - u8& operator[](uint idx) - { - pxAssert(idx < m_size); - return *((u8*)m_baseptr + idx); - } - - const u8& operator[](uint idx) const - { - pxAssert(idx < m_size); - return *((u8*)m_baseptr + idx); - } -}; - -// -------------------------------------------------------------------------------------- -// RecompiledCodeReserve -// -------------------------------------------------------------------------------------- -// A recompiled code reserve is a simple sequential-growth block of memory which is auto- -// cleared to INT 3 (0xcc) as needed. -// -class RecompiledCodeReserve : public VirtualMemoryReserve -{ - typedef VirtualMemoryReserve _parent; - -public: - RecompiledCodeReserve(std::string name); - ~RecompiledCodeReserve(); - - void Assign(VirtualMemoryManagerPtr allocator, size_t offset, size_t size); - void Reset(); - - operator u8*() { return m_baseptr; } - operator const u8*() const { return m_baseptr; } -}; \ No newline at end of file diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index aa821ffaa9..0e25c2a884 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -352,7 +352,6 @@ - @@ -723,7 +722,6 @@ - diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index a9f5261dad..a555125fee 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -1265,9 +1265,6 @@ Tools - - System - System\Ps2\GS\Renderers\Direct3D11 @@ -2210,9 +2207,6 @@ System\Ps2\GS\GIF - - System - System\Ps2\GS\Renderers\Direct3D11 diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index e63c02d385..b470043281 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -842,7 +842,6 @@ static bool vtlb_IsHostCoalesced(u32 page) static bool vtlb_GetMainMemoryOffsetFromPtr(uptr ptr, u32* mainmem_offset, u32* mainmem_size, PageProtectionMode* prot) { const uptr page_end = ptr + VTLB_PAGE_SIZE; - SysMainMemory& vmmem = GetVmMemory(); // EE memory and ROMs. if (ptr >= (uptr)eeMem->Main && page_end <= (uptr)eeMem->ZeroRead) @@ -867,11 +866,11 @@ static bool vtlb_GetMainMemoryOffsetFromPtr(uptr ptr, u32* mainmem_offset, u32* // VU memory - this includes both data and code for VU0/VU1. // Practically speaking, this is only data, because the code goes through a handler. - if (ptr >= (uptr)vmmem.VUMemory().GetPtr() && page_end <= (uptr)vmmem.VUMemory().GetPtrEnd()) + if (ptr >= (uptr)SysMemory::GetVUMem() && page_end <= (uptr)SysMemory::GetVUMemEnd()) { - const u32 vumem_offset = static_cast(ptr - (uptr)vmmem.VUMemory().GetPtr()); + const u32 vumem_offset = static_cast(ptr - (uptr)SysMemory::GetVUMem()); *mainmem_offset = vumem_offset + HostMemoryMap::VUmemOffset; - *mainmem_size = vmmem.VUMemory().GetSize() - vumem_offset; + *mainmem_size = HostMemoryMap::VUmemSize - vumem_offset; *prot = PageProtectionMode().Read().Write(); return true; } @@ -932,7 +931,7 @@ static void vtlb_CreateFastmemMapping(u32 vaddr, u32 mainmem_offset, const PageP const u32 host_page = vtlb_HostPage(page); const u32 host_offset = vtlb_HostAlignOffset(mainmem_offset); - if (!s_fastmem_area->Map(GetVmMemory().MainMemory()->GetFileHandle(), host_offset, + if (!s_fastmem_area->Map(SysMemory::GetDataFileHandle(), host_offset, s_fastmem_area->PagePointer(host_page), __pagesize, mode)) { Console.Error("Failed to map vaddr %08X to mainmem offset %08X", vtlb_HostAlignOffset(vaddr), host_offset); @@ -1023,7 +1022,7 @@ bool vtlb_ResolveFastmemMapping(uptr* addr) const u32 mainmem_offset = s_fastmem_virtual_mapping[vpage] + (vaddr & VTLB_PAGE_MASK); FASTMEM_LOG("Resolved %p (vaddr %08X) to mainmem offset %08X", uaddr, vaddr, mainmem_offset); - *addr = ((uptr)GetVmMemory().MainMemory()->GetBase()) + mainmem_offset; + *addr = ((uptr)SysMemory::GetDataPtr(0)) + mainmem_offset; return true; } @@ -1293,47 +1292,31 @@ void vtlb_ResetFastmem() } } -static constexpr size_t VMAP_SIZE = sizeof(VTLBVirtual) * VTLB_VMAP_ITEMS; - // Reserves the vtlb core allocation used by various emulation components! // [TODO] basemem - request allocating memory at the specified virtual location, which can allow // for easier debugging and/or 3rd party cheat programs. If 0, the operating system // default is used. bool vtlb_Core_Alloc() { - // Can't return regions to the bump allocator - static VTLBVirtual* vmap = nullptr; - if (!vmap) + static constexpr size_t VMAP_SIZE = sizeof(VTLBVirtual) * VTLB_VMAP_ITEMS; + static_assert(HostMemoryMap::VTLBVirtualMapSize == VMAP_SIZE); + + pxAssert(!vtlbdata.vmap && !vtlbdata.fastmem_base && !s_fastmem_area); + + vtlbdata.vmap = reinterpret_cast(SysMemory::GetVTLBVirtualMap()); + + pxAssert(!s_fastmem_area); + s_fastmem_area = SharedMemoryMappingArea::Create(FASTMEM_AREA_SIZE); + if (!s_fastmem_area) { - vmap = (VTLBVirtual*)GetVmMemory().BumpAllocator().Alloc(VMAP_SIZE); - if (!vmap) - { - Host::ReportErrorAsync("Error", "Failed to allocate vtlb vmap"); - return false; - } + Host::ReportErrorAsync("Error", "Failed to allocate fastmem area"); + return false; } - if (!vtlbdata.vmap) - { - HostSys::MemProtect(vmap, VMAP_SIZE, PageProtectionMode().Read().Write()); - vtlbdata.vmap = vmap; - } - - if (!vtlbdata.fastmem_base) - { - pxAssert(!s_fastmem_area); - s_fastmem_area = SharedMemoryMappingArea::Create(FASTMEM_AREA_SIZE); - if (!s_fastmem_area) - { - Host::ReportErrorAsync("Error", "Failed to allocate fastmem area"); - return false; - } - - s_fastmem_virtual_mapping.resize(FASTMEM_PAGE_COUNT, NO_FASTMEM_MAPPING); - vtlbdata.fastmem_base = (uptr)s_fastmem_area->BasePointer(); - Console.WriteLn(Color_StrongGreen, "Fastmem area: %p - %p", - vtlbdata.fastmem_base, vtlbdata.fastmem_base + (FASTMEM_AREA_SIZE - 1)); - } + s_fastmem_virtual_mapping.resize(FASTMEM_PAGE_COUNT, NO_FASTMEM_MAPPING); + vtlbdata.fastmem_base = (uptr)s_fastmem_area->BasePointer(); + DevCon.WriteLn(Color_StrongGreen, "Fastmem area: %p - %p", + vtlbdata.fastmem_base, vtlbdata.fastmem_base + (FASTMEM_AREA_SIZE - 1)); if (!HostSys::InstallPageFaultHandler(&vtlb_private::PageFaultHandler)) { @@ -1344,22 +1327,17 @@ bool vtlb_Core_Alloc() return true; } -static constexpr size_t PPMAP_SIZE = sizeof(*vtlbdata.ppmap) * VTLB_VMAP_ITEMS; - // The LUT is only used for 1 game so we allocate it only when the gamefix is enabled (save 4MB) // However automatic gamefix is done after the standard init so a new init function was done. void vtlb_Alloc_Ppmap() { + static constexpr size_t PPMAP_SIZE = sizeof(*vtlbdata.ppmap) * VTLB_VMAP_ITEMS; + static_assert(HostMemoryMap::VTLBAddressMapSize == PPMAP_SIZE); + if (vtlbdata.ppmap) return; - static u32* ppmap = nullptr; - - if (!ppmap) - ppmap = (u32*)GetVmMemory().BumpAllocator().Alloc(PPMAP_SIZE); - - HostSys::MemProtect(ppmap, PPMAP_SIZE, PageProtectionMode().Read().Write()); - vtlbdata.ppmap = ppmap; + vtlbdata.ppmap = reinterpret_cast(SysMemory::GetVTLBAddressMap()); // By default a 1:1 virtual to physical mapping for (u32 i = 0; i < VTLB_VMAP_ITEMS; i++) @@ -1370,16 +1348,8 @@ void vtlb_Core_Free() { HostSys::RemovePageFaultHandler(&vtlb_private::PageFaultHandler); - if (vtlbdata.vmap) - { - HostSys::MemProtect(vtlbdata.vmap, VMAP_SIZE, PageProtectionMode()); - vtlbdata.vmap = nullptr; - } - if (vtlbdata.ppmap) - { - HostSys::MemProtect(vtlbdata.ppmap, PPMAP_SIZE, PageProtectionMode()); - vtlbdata.ppmap = nullptr; - } + vtlbdata.vmap = nullptr; + vtlbdata.ppmap = nullptr; vtlb_RemoveFastmemMappings(); vtlb_ClearLoadStoreInfo(); @@ -1390,36 +1360,6 @@ void vtlb_Core_Free() s_fastmem_area.reset(); } -// -------------------------------------------------------------------------------------- -// VtlbMemoryReserve (implementations) -// -------------------------------------------------------------------------------------- -VtlbMemoryReserve::VtlbMemoryReserve(std::string name) - : VirtualMemoryReserve(std::move(name)) -{ -} - -void VtlbMemoryReserve::Assign(VirtualMemoryManagerPtr allocator, size_t offset, size_t size) -{ - // Anything passed to the memory allocator must be page aligned. - size = Common::PageAlign(size); - - // Since the memory has already been allocated as part of the main memory map, this should never fail. - u8* base = allocator->Alloc(offset, size); - if (!base) - { - Console.WriteLn("(VtlbMemoryReserve) Failed to allocate %zu bytes for %s at offset %zu", size, m_name.c_str(), offset); - pxFailRel("VtlbMemoryReserve allocation failed."); - } - - VirtualMemoryReserve::Assign(std::move(allocator), base, size); -} - -void VtlbMemoryReserve::Reset() -{ - std::memset(GetPtr(), 0, GetSize()); -} - - // =========================================================================================== // Memory Protection and Block Checking, vtlb Style! // =========================================================================================== diff --git a/pcsx2/vtlb.h b/pcsx2/vtlb.h index f72f4ef3f0..432c9e5444 100644 --- a/pcsx2/vtlb.h +++ b/pcsx2/vtlb.h @@ -17,7 +17,7 @@ #include "MemoryTypes.h" #include "SingleRegisterTypes.h" -#include "VirtualMemory.h" +#include "System.h" static const uptr VTLB_AllocUpperBounds = _1gb * 2; @@ -126,70 +126,6 @@ extern void vtlb_DynGenWrite_Const(u32 bits, bool xmm, u32 addr_const, int value extern void vtlb_DynGenDispatchers(); -// -------------------------------------------------------------------------------------- -// VtlbMemoryReserve -// -------------------------------------------------------------------------------------- -class VtlbMemoryReserve : public VirtualMemoryReserve -{ -public: - VtlbMemoryReserve(std::string name); - - void Assign(VirtualMemoryManagerPtr allocator, size_t offset, size_t size); - - virtual void Reset(); -}; - -// -------------------------------------------------------------------------------------- -// eeMemoryReserve -// -------------------------------------------------------------------------------------- -class eeMemoryReserve : public VtlbMemoryReserve -{ - typedef VtlbMemoryReserve _parent; - -public: - eeMemoryReserve(); - ~eeMemoryReserve(); - - void Assign(VirtualMemoryManagerPtr allocator); - void Release(); - - void Reset() override; -}; - -// -------------------------------------------------------------------------------------- -// iopMemoryReserve -// -------------------------------------------------------------------------------------- -class iopMemoryReserve : public VtlbMemoryReserve -{ - typedef VtlbMemoryReserve _parent; - -public: - iopMemoryReserve(); - ~iopMemoryReserve(); - - void Assign(VirtualMemoryManagerPtr allocator); - void Release(); - - void Reset() override; -}; - -// -------------------------------------------------------------------------------------- -// vuMemoryReserve -// -------------------------------------------------------------------------------------- -class vuMemoryReserve : public VtlbMemoryReserve -{ - typedef VtlbMemoryReserve _parent; - -public: - vuMemoryReserve(); - ~vuMemoryReserve(); - - void Assign(VirtualMemoryManagerPtr allocator); - void Release(); - - void Reset() override; -}; - namespace vtlb_private { static const uint VTLB_PAGE_BITS = 12; diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index cc72ed7218..78187667f5 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -27,7 +27,7 @@ #include "IopBios.h" #include "IopHw.h" #include "Common.h" -#include "VirtualMemory.h" +#include "System.h" #include "VMManager.h" #include @@ -72,23 +72,22 @@ u32 psxhwLUT[0x10000]; static __fi u32 HWADDR(u32 mem) { return psxhwLUT[mem >> 16] + mem; } -static RecompiledCodeReserve* recMem = NULL; - -static BASEBLOCK* recRAM = NULL; // and the ptr to the blocks here -static BASEBLOCK* recROM = NULL; // and here -static BASEBLOCK* recROM1 = NULL; // also here -static BASEBLOCK* recROM2 = NULL; // also here +static BASEBLOCK* recRAM = nullptr; // and the ptr to the blocks here +static BASEBLOCK* recROM = nullptr; // and here +static BASEBLOCK* recROM1 = nullptr; // also here +static BASEBLOCK* recROM2 = nullptr; // also here static BaseBlocks recBlocks; -static u8* recPtr = NULL; +static u8* recPtr = nullptr; +static u8* recPtrEnd = nullptr; u32 psxpc; // recompiler psxpc int psxbranch; // set for branch u32 g_iopCyclePenalty; -static EEINST* s_pInstCache = NULL; +static EEINST* s_pInstCache = nullptr; static u32 s_nInstCacheSize = 0; -static BASEBLOCK* s_pCurBlock = NULL; -static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pCurBlock = nullptr; +static BASEBLOCKEX* s_pCurBlockEx = nullptr; static u32 s_nEndBlock = 0; // what psxpc the current block ends static u32 s_branchTo; @@ -96,7 +95,7 @@ static bool s_nBlockFF; static u32 s_saveConstRegs[32]; static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; -static EEINST* s_psaveInstInfo = NULL; +static EEINST* s_psaveInstInfo = nullptr; u32 s_psxBlockCycles = 0; // cycles of current block recompiling static u32 s_savenBlockCycles = 0; @@ -879,15 +878,9 @@ static const uint m_recBlockAllocSize = static void recReserve() { - if (recMem) - return; + recPtr = SysMemory::GetIOPRec(); + recPtrEnd = SysMemory::GetIOPRecEnd() - _64kb; - recMem = new RecompiledCodeReserve("R3000A Recompiler Cache"); - recMem->Assign(GetVmMemory().CodeMemory(), HostMemoryMap::IOPrecOffset, 32 * _1mb); -} - -static void recAlloc() -{ // Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory. // Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are // always 4 bytes long). @@ -910,23 +903,18 @@ static void recAlloc() recROM2 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom2 / 4) * sizeof(BASEBLOCK); - + pxAssertRel(!s_pInstCache, "InstCache not allocated"); + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST) * s_nInstCacheSize); if (!s_pInstCache) - { - s_nInstCacheSize = 128; - s_pInstCache = (EEINST*)malloc(sizeof(EEINST) * s_nInstCacheSize); - if (!s_pInstCache) - pxFailRel("Failed to allocate R3000 InstCache array."); - } + pxFailRel("Failed to allocate R3000 InstCache array."); } void recResetIOP() { DevCon.WriteLn("iR3000A Recompiler reset."); - recAlloc(); - recMem->Reset(); - xSetPtr(*recMem); + xSetPtr(SysMemory::GetIOPRec()); _DynGen_Dispatchers(); recPtr = xGetPtr(); @@ -983,12 +971,13 @@ void recResetIOP() static void recShutdown() { - safe_delete(recMem); - safe_aligned_free(m_recBlockAlloc); safe_free(s_pInstCache); s_nInstCacheSize = 0; + + recPtr = nullptr; + recPtrEnd = nullptr; } static void iopClearRecLUT(BASEBLOCK* base, int count) @@ -1561,7 +1550,7 @@ static void iopRecRecompile(const u32 startpc) pxAssert(startpc); // if recPtr reached the mem limit reset whole mem - if (recPtr >= (recMem->GetPtrEnd() - _64kb)) + if (recPtr >= recPtrEnd) { recResetIOP(); } @@ -1754,7 +1743,7 @@ StartRecomp: } } - pxAssert(xGetPtr() < recMem->GetPtrEnd()); + pxAssert(xGetPtr() < recPtrEnd); pxAssert(xGetPtr() - recPtr < _64kb); s_pCurBlockEx->x86size = xGetPtr() - recPtr; diff --git a/pcsx2/x86/ix86-32/iR5900.cpp b/pcsx2/x86/ix86-32/iR5900.cpp index c0c429c81c..6a5be74f0b 100644 --- a/pcsx2/x86/ix86-32/iR5900.cpp +++ b/pcsx2/x86/ix86-32/iR5900.cpp @@ -22,10 +22,10 @@ #include "GS.h" #include "Memory.h" #include "Patch.h" +#include "System.h" #include "R3000A.h" #include "R5900OpcodeTables.h" #include "VMManager.h" -#include "VirtualMemory.h" #include "vtlb.h" #include "x86/BaseblockEx.h" #include "x86/iR5900.h" @@ -83,23 +83,23 @@ eeProfiler EE::Profiler; #define X86 -static RecompiledCodeReserve* recMem = NULL; -static u8* recRAMCopy = NULL; -static u8* recLutReserve_RAM = NULL; +static u8* recRAMCopy = nullptr; +static u8* recLutReserve_RAM = nullptr; static const size_t recLutSize = (Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) * wordsize / 4; -static BASEBLOCK* recRAM = NULL; // and the ptr to the blocks here -static BASEBLOCK* recROM = NULL; // and here -static BASEBLOCK* recROM1 = NULL; // also here -static BASEBLOCK* recROM2 = NULL; // also here +static BASEBLOCK* recRAM = nullptr; // and the ptr to the blocks here +static BASEBLOCK* recROM = nullptr; // and here +static BASEBLOCK* recROM1 = nullptr; // also here +static BASEBLOCK* recROM2 = nullptr; // also here static BaseBlocks recBlocks; -static u8* recPtr = NULL; -EEINST* s_pInstCache = NULL; +static u8* recPtr = nullptr; +static u8* recPtrEnd = nullptr; +EEINST* s_pInstCache = nullptr; static u32 s_nInstCacheSize = 0; -static BASEBLOCK* s_pCurBlock = NULL; -static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pCurBlock = nullptr; +static BASEBLOCKEX* s_pCurBlockEx = nullptr; u32 s_nEndBlock = 0; // what pc the current block ends u32 s_branchTo; static bool s_nBlockFF; @@ -107,7 +107,7 @@ static bool s_nBlockFF; // save states for branches GPR_reg64 s_saveConstRegs[32]; static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; -static EEINST* s_psaveInstInfo = NULL; +static EEINST* s_psaveInstInfo = nullptr; static u32 s_savenBlockCycles = 0; @@ -512,15 +512,9 @@ static __ri void ClearRecLUT(BASEBLOCK* base, int memsize) static void recReserve() { - if (recMem) - return; + recPtr = SysMemory::GetEERec(); + recPtrEnd = SysMemory::GetEERecEnd() - _64kb; - recMem = new RecompiledCodeReserve("R5900 Recompiler Cache"); - recMem->Assign(GetVmMemory().CodeMemory(), HostMemoryMap::EErecOffset, 64 * _1mb); -} - -static void recAlloc() -{ if (!recRAMCopy) { recRAMCopy = (u8*)_aligned_malloc(Ps2MemSize::MainRam, 4096); @@ -577,13 +571,11 @@ static void recAlloc() recLUT_SetPage(recLUT, hwLUT, recROM2, 0xa000, i, i - 0x1e40); } - if (s_pInstCache == NULL) - { - s_nInstCacheSize = 128; - s_pInstCache = (EEINST*)malloc(sizeof(EEINST) * s_nInstCacheSize); - if (!s_pInstCache) - pxFailRel("Failed to allocate R5900 InstCache array"); - } + pxAssertRel(!s_pInstCache, "InstCache not allocated"); + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST) * s_nInstCacheSize); + if (!s_pInstCache) + pxFailRel("Failed to allocate R5900 InstCache array"); } alignas(16) static u16 manual_page[Ps2MemSize::MainRam >> 12]; @@ -596,10 +588,7 @@ static void recResetRaw() EE::Profiler.Reset(); - recAlloc(); - - recMem->Reset(); - xSetPtr(*recMem); + xSetPtr(SysMemory::GetEERec()); _DynGen_Dispatchers(); vtlb_DynGenDispatchers(); recPtr = xGetPtr(); @@ -620,9 +609,8 @@ static void recResetRaw() g_resetEeScalingStats = true; } -static void recShutdown() +void recShutdown() { - safe_delete(recMem); safe_aligned_free(recRAMCopy); safe_aligned_free(recLutReserve_RAM); @@ -632,6 +620,9 @@ static void recShutdown() safe_free(s_pInstCache); s_nInstCacheSize = 0; + + recPtr = nullptr; + recPtrEnd = nullptr; } void recStep() @@ -909,7 +900,7 @@ void SetBranchImm(u32 imm) u8* recBeginThunk() { // if recPtr reached the mem limit reset whole mem - if (recPtr >= (recMem->GetPtrEnd() - _64kb)) + if (recPtr >= recPtrEnd) eeRecNeedsReset = true; xSetPtr(recPtr); @@ -923,7 +914,7 @@ u8* recEndThunk() { u8* block_end = x86Ptr; - pxAssert(block_end < recMem->GetPtrEnd()); + pxAssert(block_end < recPtrEnd); recPtr = block_end; return block_end; } @@ -2208,7 +2199,7 @@ static void recRecompile(const u32 startpc) pxAssert(startpc); // if recPtr reached the mem limit reset whole mem - if (recPtr >= (recMem->GetPtrEnd() - _64kb)) + if (recPtr >= recPtrEnd) eeRecNeedsReset = true; if (HWADDR(startpc) == VMManager::Internal::GetCurrentELFEntryPoint()) @@ -2741,7 +2732,7 @@ StartRecomp: } } - pxAssert(xGetPtr() < recMem->GetPtrEnd()); + pxAssert(xGetPtr() < recPtrEnd); s_pCurBlockEx->x86size = static_cast(xGetPtr() - recPtr); @@ -2757,8 +2748,8 @@ StartRecomp: pxAssert((g_cpuHasConstReg & g_cpuFlushedConstReg) == g_cpuHasConstReg); - s_pCurBlock = NULL; - s_pCurBlockEx = NULL; + s_pCurBlock = nullptr; + s_pCurBlockEx = nullptr; } R5900cpu recCpu = { diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index b0fd8ea1dd..a4a32158e3 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -26,15 +26,6 @@ // Micro VU - Main Functions //------------------------------------------------------------------ -void mVUreserveCache(microVU& mVU) -{ - mVU.cache_reserve = new RecompiledCodeReserve(StringUtil::StdStringFromFormat("Micro VU%u Recompiler Cache", mVU.index)); - - const size_t alloc_offset = mVU.index ? HostMemoryMap::mVU0recOffset : HostMemoryMap::mVU1recOffset; - mVU.cache_reserve->Assign(GetVmMemory().CodeMemory(), alloc_offset, mVU.cacheSize * _1mb); - mVU.cache = mVU.cache_reserve->GetPtr(); -} - // Only run this once per VU! ;) void mVUinit(microVU& mVU, uint vuIndex) { @@ -46,12 +37,8 @@ void mVUinit(microVU& mVU, uint vuIndex) mVU.microMemSize = (mVU.index ? 0x4000 : 0x1000); mVU.progSize = (mVU.index ? 0x4000 : 0x1000) / 4; mVU.progMemMask = mVU.progSize-1; - mVU.cacheSize = mVUcacheReserve; - mVU.cache = nullptr; - mVU.startFunct = nullptr; - mVU.exitFunct = nullptr; - - mVUreserveCache(mVU); + mVU.cache = vuIndex ? SysMemory::GetVU1Rec() : SysMemory::GetVU0Rec(); + mVU.prog.x86end = (vuIndex ? SysMemory::GetVU1RecEnd() : SysMemory::GetVU0RecEnd()) - (mVUcacheSafeZone * _1mb); mVU.regAlloc.reset(new microRegAlloc(mVU.index)); } @@ -59,7 +46,6 @@ void mVUinit(microVU& mVU, uint vuIndex) // Resets Rec Data void mVUreset(microVU& mVU, bool resetReserve) { - if (THREAD_VU1) { DevCon.Warning("mVU Reset"); @@ -70,9 +56,6 @@ void mVUreset(microVU& mVU, bool resetReserve) } VU0.VI[REG_VPU_STAT].UL &= ~0x100; } - // Restore reserve to uncommitted state - if (resetReserve) - mVU.cache_reserve->Reset(); xSetPtr(mVU.cache); mVUdispatcherAB(mVU); @@ -95,7 +78,6 @@ void mVUreset(microVU& mVU, bool resetReserve) // Setup Dynarec Cache Limits for Each Program mVU.prog.x86start = xGetAlignedCallTarget(); mVU.prog.x86ptr = mVU.prog.x86start; - mVU.prog.x86end = mVU.cache + ((mVU.cacheSize - mVUcacheSafeZone) * _1mb); for (u32 i = 0; i < (mVU.progSize / 2); i++) { @@ -118,9 +100,6 @@ void mVUreset(microVU& mVU, bool resetReserve) // Free Allocated Resources void mVUclose(microVU& mVU) { - - safe_delete(mVU.cache_reserve); - // Delete Programs and Block Managers for (u32 i = 0; i < (mVU.progSize / 2); i++) { diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index a03e77e478..469b3d3e46 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -30,7 +30,7 @@ using namespace x86Emitter; #include "Gif_Unit.h" #include "iR5900.h" #include "R5900OpcodeTables.h" -#include "VirtualMemory.h" +#include "System.h" #include "common/emitter/x86emitter.h" #include "microVU_Misc.h" #include "microVU_IR.h" @@ -91,9 +91,7 @@ struct microProgManager microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution) }; -static const uint mVUdispCacheSize = __pagesize; // Dispatcher Cache Size (in bytes) static const uint mVUcacheSafeZone = 3; // Safe-Zone for program recompilation (in megabytes) -static const uint mVUcacheReserve = 64; // mVU0, mVU1 Reserve Cache Size (in megabytes) struct microVU { @@ -117,7 +115,6 @@ struct microVU std::unique_ptr regAlloc; // Reg Alloc Class std::FILE* logFile; // Log File Pointer - RecompiledCodeReserve* cache_reserve; u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) u8* startFunct; // Function Ptr to the recompiler dispatcher (start) u8* exitFunct; // Function Ptr to the recompiler dispatcher (exit) diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index a4572b227b..7151c402ac 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -17,7 +17,6 @@ #include "Vif.h" #include "VU.h" -#include "VirtualMemory.h" #include "common/emitter/x86emitter.h" @@ -32,12 +31,10 @@ typedef void (*nVifrecCall)(uptr dest, uptr src); extern void mVUmergeRegs(const xRegisterSSE& dest, const xRegisterSSE& src, int xyzw, bool modXYZW = 0); extern void mVUsaveReg(const xRegisterSSE& reg, xAddressVoid ptr, int xyzw, bool modXYZW); extern void _nVifUnpack (int idx, const u8* data, uint mode, bool isFill); -extern void dVifReserve (int idx); extern void dVifReset (int idx); extern void dVifClose (int idx); extern void dVifRelease (int idx); extern void VifUnpackSSE_Init(); -extern void VifUnpackSSE_Destroy(); _vifT extern void dVifUnpack(const u8* data, bool isFill); @@ -64,8 +61,8 @@ struct nVifStruct // (templates are used for most or all VIF indexing) u32 idx; - RecompiledCodeReserve* recReserve; u8* recWritePtr; // current write pos into the reserve + u8* recEndPtr; HashBucket vifBlocks; // Vif Blocks diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index ee404fbf1c..46ec0cef9f 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -24,42 +24,19 @@ #include "common/StringUtil.h" #include "fmt/core.h" -static void recReset(int idx) +void dVifReset(int idx) { nVif[idx].vifBlocks.reset(); - nVif[idx].recReserve->Reset(); - - nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr(); -} - -void dVifReserve(int idx) -{ - if (nVif[idx].recReserve) - return; - const size_t offset = idx ? HostMemoryMap::VIF1recOffset : HostMemoryMap::VIF0recOffset; - nVif[idx].recReserve = new RecompiledCodeReserve(StringUtil::StdStringFromFormat("VIF%u Unpack Recompiler Cache", idx)); - nVif[idx].recReserve->Assign(GetVmMemory().CodeMemory(), offset, 8 * _1mb); -} - -void dVifReset(int idx) -{ - pxAssertDev(nVif[idx].recReserve, "Dynamic VIF recompiler reserve must be created prior to VIF use or reset!"); - - recReset(idx); -} - -void dVifClose(int idx) -{ - if (nVif[idx].recReserve) - nVif[idx].recReserve->Reset(); + const size_t size = idx ? HostMemoryMap::VIF1recSize : HostMemoryMap::VIF0recSize; + nVif[idx].recWritePtr = SysMemory::GetCodePtr(offset); + nVif[idx].recEndPtr = nVif[idx].recWritePtr + (size - _256kb); } void dVifRelease(int idx) { - dVifClose(idx); - safe_delete(nVif[idx].recReserve); + nVif[idx].vifBlocks.clear(); } VifUnpackSSE_Dynarec::VifUnpackSSE_Dynarec(const nVifStruct& vif_, const nVifBlock& vifBlock_) @@ -368,11 +345,11 @@ _vifT __fi nVifBlock* dVifCompile(nVifBlock& block, bool isFill) nVifStruct& v = nVif[idx]; // Check size before the compilation - if (v.recWritePtr > (v.recReserve->GetPtrEnd() - _256kb)) + if (v.recWritePtr >= v.recEndPtr) { DevCon.WriteLn("nVif Recompiler Cache Reset! [0x%016" PRIXPTR " > 0x%016" PRIXPTR "]", - v.recWritePtr, v.recReserve->GetPtrEnd()); - recReset(idx); + v.recWritePtr, v.recEndPtr); + dVifReset(idx); } // Compile the block now diff --git a/pcsx2/x86/newVif_UnpackSSE.cpp b/pcsx2/x86/newVif_UnpackSSE.cpp index f7cfe0373c..6c9e7e6f4c 100644 --- a/pcsx2/x86/newVif_UnpackSSE.cpp +++ b/pcsx2/x86/newVif_UnpackSSE.cpp @@ -24,9 +24,6 @@ #define xMOV64(regX, loc) xMOVUPS (regX, loc) #define xMOV128(regX, loc) xMOVUPS (regX, loc) -//alignas(__pagesize) static u8 nVifUpkExec[__pagesize*4]; -static RecompiledCodeReserve* nVifUpkExec = NULL; - // ===================================================================================================== // VifUnpackSSE_Base Section // ===================================================================================================== @@ -376,14 +373,9 @@ static void nVifGen(int usn, int mask, int curCycle) void VifUnpackSSE_Init() { - if (nVifUpkExec) - return; - DevCon.WriteLn("Generating SSE-optimized unpacking functions for VIF interpreters..."); - nVifUpkExec = new RecompiledCodeReserve("VIF SSE-optimized Unpacking Functions"); - nVifUpkExec->Assign(GetVmMemory().CodeMemory(), HostMemoryMap::VIFUnpackRecOffset, _1mb); - xSetPtr(*nVifUpkExec); + xSetPtr(SysMemory::GetVIFUnpackRec()); for (int a = 0; a < 2; a++) for (int b = 0; b < 2; b++) @@ -392,17 +384,12 @@ void VifUnpackSSE_Init() DevCon.WriteLn("Unpack function generation complete. Generated function statistics:"); DevCon.Indent().WriteLn( - "Reserved buffer : %u bytes @ 0x%016" PRIXPTR "\n" - "x86 code generated : %u bytes\n", - (uint)nVifUpkExec->GetSize(), - nVifUpkExec->GetPtr(), - (uint)(xGetPtr() - nVifUpkExec->GetPtr()) + "Reserved buffer : %zu bytes @ 0x%016" PRIXPTR "\n" + "x86 code generated : %zu bytes\n", + SysMemory::GetVIFUnpackRecEnd() - SysMemory::GetVIFUnpackRec(), + SysMemory::GetVIFUnpackRec(), + xGetPtr() - SysMemory::GetVIFUnpackRec() ); - Perf::any.Register(nVifUpkExec->GetPtr(), xGetPtr() - nVifUpkExec->GetPtr(), "VIF Unpack"); -} - -void VifUnpackSSE_Destroy() -{ - safe_delete(nVifUpkExec); + Perf::any.Register(SysMemory::GetVIFUnpackRec(), xGetPtr() - SysMemory::GetVIFUnpackRec(), "VIF Unpack"); }