// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team // SPDX-License-Identifier: GPL-3.0+ #pragma once #include "vtlb.h" #include "MemoryTypes.h" #include "common/BitUtils.h" #include "common/MemoryInterface.h" // This is a table of default virtual map addresses for ps2vm components. These locations // are provided and used to assist in debugging and possibly hacking; as it makes it possible // for a programmer to know exactly where to look (consistently!) for the base address of // the various virtual machine components. These addresses can be keyed directly into the // debugger's disasm window to get disassembly of recompiled code, and they can be used to help // identify recompiled code addresses in the callstack. // All of these areas should be reserved as soon as possible during program startup, and its // important that none of the areas overlap. In all but superVU's case, failure due to overlap // or other conflict will result in the operating system picking a preferred address for the mapping. namespace HostMemoryMap { ////////////////////////////////////////////////////////////////////////// // Main ////////////////////////////////////////////////////////////////////////// // PS2 main memory, SPR, and ROMs (approximately 143MB). // Needs to be big enough to fit the EEVM_MemoryAllocMess struct static constexpr u32 EEmemOffset = 0x00000000; static constexpr u32 EEmemSize = Common::AlignUp(sizeof(EEVM_MemoryAllocMess), _1mb); // IOP main memory (approximately 3MB). // Needs to be big enough to fit the IopVM_MemoryAllocMess struct static constexpr u32 IOPmemOffset = EEmemOffset + EEmemSize; static constexpr u32 IOPmemSize = Common::AlignUp(sizeof(IopVM_MemoryAllocMess), _1mb); // VU0 and VU1 memory (40KB, rounded up to 1MB for simplicity). static constexpr u32 VUmemOffset = IOPmemOffset + IOPmemSize; static constexpr u32 VUmemSize = 0x100000; // 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 ////////////////////////////////////////////////////////////////////////// // EE recompiler code cache area (64mb) static constexpr u32 EErecOffset = 0x00000000; static constexpr u32 EErecSize = 0x4000000; // IOP recompiler code cache area (32mb) static constexpr u32 IOPrecOffset = EErecOffset + EErecSize; static constexpr u32 IOPrecSize = 0x2000000; // newVif0 recompiler code cache area (8mb) static constexpr u32 VIF0recOffset = IOPrecOffset + IOPrecSize; static constexpr u32 VIF0recSize = 0x800000; // newVif1 recompiler code cache area (8mb) static constexpr u32 VIF1recOffset = VIF0recOffset + VIF0recSize; static constexpr u32 VIF1recSize = 0x800000; // microVU1 recompiler code cache area (64mb) static constexpr u32 mVU0recOffset = VIF1recOffset + VIF1recSize; static constexpr u32 mVU0recSize = 0x4000000; // microVU0 recompiler code cache area (64mb) static constexpr u32 mVU1recOffset = mVU0recOffset + mVU0recSize; static constexpr u32 mVU1recSize = 0x4000000; // SSE-optimized VIF unpack functions (1mb) static constexpr u32 VIFUnpackRecOffset = mVU1recOffset + mVU1recSize; static constexpr u32 VIFUnpackRecSize = 0x100000; // Software Renderer JIT buffer (64mb) static constexpr u32 SWrecOffset = VIFUnpackRecOffset + VIFUnpackRecSize; static constexpr u32 SWrecSize = 0x04000000; // Overall size. static constexpr u32 CodeSize = SWrecOffset + SWrecSize; // 305 mb } // namespace HostMemoryMap // -------------------------------------------------------------------------------------- // HostMemory // -------------------------------------------------------------------------------------- // This class provides the main memory for the virtual machines. namespace SysMemory { /// Reserve the host memory map (and, on arm64, the constant-VA arena) early, /// before other allocations could squat on the fixed base. Idempotent — a /// later Allocate() reuses the same reservation. Used by headless runners and /// SDL frontends that need the deterministic arena claimed before any /// heap/mmap could squat on the fixed base. void ReserveMemory(); bool Allocate(); void Reset(); void Release(); /// Returns true after the VM data-memory map has been allocated. bool IsAllocated(); /// Returns true when an executable code-cache mapping is available. bool HasCodeMemory(); /// Returns data memory (Main in Memory Map). u8* GetDataPtr(size_t offset); /// Returns memory used for the recompilers, or nullptr when no code mapping exists. 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 #define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) #define psHu8(mem) (*(u8*)&eeHw[(mem)&0xffff]) #define psHu16(mem) (*(u16*)&eeHw[(mem)&0xffff]) #define psHu32(mem) (*(u32*)&eeHw[(mem)&0xffff]) #define psHu64(mem) (*(u64*)&eeHw[(mem)&0xffff]) #define psHu128(mem) (*(u128*)&eeHw[(mem)&0xffff]) #define psSu32(mem) (*(u32*)&eeMem->Scratch[(mem)&0x3fff]) #define psSu64(mem) (*(u64*)&eeMem->Scratch[(mem)&0x3fff]) #define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem)&0x3fff]) extern void memSetKernelMode(); //extern void memSetSupervisorMode(); extern void memSetUserMode(); extern void memSetPageAddr(u32 vaddr, u32 paddr); extern void memClearPageAddr(u32 vaddr); extern void memBindConditionalHandlers(); extern bool memGetExtraMemMode(); extern void memSetExtraMemMode(bool mode); extern void memMapVUmicro(); #define memRead8 vtlb_memRead #define memRead16 vtlb_memRead #define memRead32 vtlb_memRead #define memRead64 vtlb_memRead #define memWrite8 vtlb_memWrite #define memWrite16 vtlb_memWrite #define memWrite32 vtlb_memWrite #define memWrite64 vtlb_memWrite static __fi void memRead128(u32 mem, mem128_t* out) { r128_store(out, vtlb_memRead128(mem)); } static __fi void memRead128(u32 mem, mem128_t& out) { memRead128(mem, &out); } static __fi void memWrite128(u32 mem, const mem128_t* val) { vtlb_memWrite128(mem, r128_load(val)); } static __fi void memWrite128(u32 mem, const mem128_t& val) { vtlb_memWrite128(mem, r128_load(&val)); } extern void ba0W16(u32 mem, u16 value); extern u16 ba0R16(u32 mem); class EEMemoryInterface final : public MemoryInterface { public: u8 Read8(u32 address, bool* valid = nullptr) override; u16 Read16(u32 address, bool* valid = nullptr) override; u32 Read32(u32 address, bool* valid = nullptr) override; u64 Read64(u32 address, bool* valid = nullptr) override; u128 Read128(u32 address, bool* valid = nullptr) override; bool ReadBytes(u32 address, void* dest, u32 size) override; bool Write8(u32 address, u8 value) override; bool Write16(u32 address, u16 value) override; bool Write32(u32 address, u32 value) override; bool Write64(u32 address, u64 value) override; bool Write128(u32 address, u128 value) override; bool WriteBytes(u32 address, const void* src, u32 size) override; bool CompareBytes(u32 address, const void* src, u32 size) override; };