VMManager: Remove and merge System.cpp

This commit is contained in:
Stenzek 2023-12-26 21:05:33 +10:00 committed by Connor McLaughlin
parent 308f8c5112
commit fb15893521
34 changed files with 642 additions and 699 deletions

View File

@ -11,8 +11,6 @@
#include "common/Path.h"
#include "common/StringUtil.h"
#include "pcsx2/System.h"
MemoryCardConvertDialog::MemoryCardConvertDialog(QWidget* parent, QString selectedCard)
: QDialog(parent)
{

View File

@ -11,7 +11,6 @@
#include "Settings/MemoryCardCreateDialog.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
#include "pcsx2/System.h"
MemoryCardCreateDialog::MemoryCardCreateDialog(QWidget* parent /* = nullptr */)
: QDialog(parent)

View File

@ -131,7 +131,6 @@ set(pcsx2Sources
SourceLog.cpp
SPR.cpp
StateWrapper.cpp
System.cpp
Vif0_Dma.cpp
Vif1_Dma.cpp
Vif1_MFIFO.cpp
@ -209,7 +208,6 @@ set(pcsx2Headers
SPR.h
StateWrapper.h
SysForwardDefs.h
System.h
Vif_Dma.h
Vif.h
Vif_Unpack.h

View File

@ -10,7 +10,6 @@ static const u32 PS2CLK = 294912000; //hz /* 294.912 mhz */
extern s64 PSXCLK; /* 36.864 Mhz */
#include "System.h"
#include "Memory.h"
#include "R5900.h"
#include "Hw.h"

View File

@ -7,7 +7,6 @@
#include <cstdio>
#include "R5900.h"
#include "R3000A.h"
#include "System.h"
std::vector<BreakPoint> CBreakPoints::breakPoints_;
u32 CBreakPoints::breakSkipFirstAtEE_ = 0;

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0+
#include "GS/Renderers/Common/GSFunctionMap.h"
#include "System.h"
#include "Memory.h"
namespace GSCodeReserve
{

View File

@ -5,7 +5,6 @@
#include "GS/GSExtra.h"
#include "GS/Renderers/SW/GSScanlineEnvironment.h"
#include "System.h"
template <class KEY, class VALUE>
class GSFunctionMap

View File

@ -8,22 +8,22 @@
namespace GSDumpReplayer
{
bool IsReplayingDump();
bool IsReplayingDump();
/// If set, playback will repeat once it reaches the last frame.
void SetLoopCount(s32 loop_count = 0);
int GetLoopCount();
bool IsRunner();
void SetIsDumpRunner(bool is_runner);
/// If set, playback will repeat once it reaches the last frame.
void SetLoopCount(s32 loop_count = 0);
int GetLoopCount();
bool IsRunner();
void SetIsDumpRunner(bool is_runner);
bool Initialize(const char* filename);
bool ChangeDump(const char* filename);
void Shutdown();
bool Initialize(const char* filename);
bool ChangeDump(const char* filename);
void Shutdown();
std::string GetDumpSerial();
u32 GetDumpCRC();
std::string GetDumpSerial();
u32 GetDumpCRC();
u32 GetFrameNumber();
u32 GetFrameNumber();
void RenderUI();
}
void RenderUI();
} // namespace GSDumpReplayer

View File

@ -22,16 +22,18 @@ BIOS
0xBFC00000 - 0xBFFFFFFF un-cached
*/
#include "IopHw.h"
#include "GS.h"
#include "VUmicro.h"
#include "MTVU.h"
#include "DEV9/DEV9.h"
#include "IopHw.h"
#include "GS/Renderers/Common/GSFunctionMap.h"
#include "GS.h"
#include "Host.h"
#include "MTVU.h"
#include "SPU2/spu2.h"
#include "SaveState.h"
#include "VUmicro.h"
#include "ps2/HwInternal.h"
#include "ps2/BiosTools.h"
#include "SPU2/spu2.h"
#include "common/AlignedMalloc.h"
@ -39,6 +41,24 @@ BIOS
#include "Cache.h"
#endif
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
static void memAllocate();
static void memReset();
static void memRelease();
int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode
static u16 s_ba[0xff];
@ -47,6 +67,225 @@ static bool s_ba_command_executing = false;
static bool s_ba_error_detected = false;
static u16 s_ba_current_reg = 0;
namespace HostMemoryMap
{
// For debuggers
extern "C" {
#ifdef _WIN32
_declspec(dllexport) uptr EEmem, IOPmem, VUmem;
#else
__attribute__((visibility("default"), used)) uptr EEmem, IOPmem, VUmem;
#endif
}
} // namespace HostMemoryMap
u8* SysMemory::TryAllocateVirtualMemory(const char* name, void* file_handle, uptr base, size_t size)
{
u8* baseptr;
if (file_handle)
baseptr = static_cast<u8*>(HostSys::MapSharedMemory(file_handle, 0, (void*)base, size, PageAccess_ReadWrite()));
else
baseptr = static_cast<u8*>(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*)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)
// On x86-64, code can reach 8*2^28 from its address [-6*2^28, 4*2^28] is the region that allows for code in the 640mb allocation to reach 512mb of code that either starts at codeBase or 256mb before it.
// We start high and count down because on macOS code starts at the beginning of useable address space, so starting as far ahead as possible reduces address variations due to code size. Not sure about other platforms. Obviously this only actually affects what shows up in a debugger and won't affect performance or correctness of anything.
for (int offset = 4; offset >= -6; offset--)
{
uptr base = codeBase + (offset << 28) + offset_from_base;
if ((sptr)base < 0 || (sptr)(base + size - 1) < 0)
{
// VTLB will throw a fit if we try to put EE main memory here
continue;
}
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);
}
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)
{
Host::ReportErrorAsync("Error", "Failed to create shared memory file.");
ReleaseMemoryMap();
return false;
}
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;
}
void SysMemory::DumpMemoryMap()
{
#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
}
void SysMemory::ReleaseMemoryMap()
{
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 SysMemory::Allocate()
{
DevCon.WriteLn(Color_StrongBlue, "Allocating host memory for virtual systems...");
ConsoleIndentScope indent(1);
if (!AllocateMemoryMap())
return false;
memAllocate();
iopMemAlloc();
vuMemAllocate();
if (!vtlb_Core_Alloc())
return false;
return true;
}
void SysMemory::Reset()
{
DevCon.WriteLn(Color_StrongBlue, "Resetting host memory for virtual systems...");
ConsoleIndentScope indent(1);
memReset();
iopMemReset();
vuMemReset();
// Note: newVif is reset as part of other VIF structures.
// Software is reset on the GS thread.
}
void SysMemory::Release()
{
Console.WriteLn(Color_Blue, "Releasing host memory for virtual systems...");
ConsoleIndentScope indent(1);
vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit).
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;
}
void memSetKernelMode() {
//Do something here
MemMode = 0;

View File

@ -5,64 +5,197 @@
#include "vtlb.h"
#define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D
// 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.
#define psHs8(mem) (*(s8 *)&eeHw[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&eeHw[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&eeHw[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&eeHw[(mem) & 0xffff])
#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])
// 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.
#define psMs8(mem) (*(s8 *)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs16(mem) (*(s16*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs32(mem) (*(s32*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs64(mem) (*(s64*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu8(mem) (*(u8 *)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu16(mem) (*(u16*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu32(mem) (*(u32*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu64(mem) (*(u64*)&eeMem->Main[(mem) & 0x1ffffff])
namespace HostMemoryMap
{
//////////////////////////////////////////////////////////////////////////
// Main
//////////////////////////////////////////////////////////////////////////
#define psRs8(mem) (*(s8 *)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs16(mem) (*(s16*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs32(mem) (*(s32*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs64(mem) (*(s64*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu8(mem) (*(u8 *)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu16(mem) (*(u16*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu32(mem) (*(u32*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu64(mem) (*(u64*)&eeMem->ROM[(mem) & 0x3fffff])
// 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;
#define psR1s8(mem) (*(s8 *)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1s16(mem) (*(s16*)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1s32(mem) (*(s32*)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1s64(mem) (*(s64*)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1u8(mem) (*(u8 *)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1u16(mem) (*(u16*)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1u32(mem) (*(u32*)&eeMem->ROM1[(mem) & 0x3fffff])
#define psR1u64(mem) (*(u64*)&eeMem->ROM1[(mem) & 0x3fffff])
// IOP main memory (2MB + 64K + 256b, rounded up to 3MB for simplicity).
static constexpr u32 IOPmemOffset = EEmemOffset + EEmemSize;
static constexpr u32 IOPmemSize = 0x300000;
#define psR2s8(mem) (*(s8 *)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2s16(mem) (*(s16*)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2s32(mem) (*(s32*)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2s64(mem) (*(s64*)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2u8(mem) (*(u8 *)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2u16(mem) (*(u16*)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2u32(mem) (*(u32*)&eeMem->ROM2[(mem) & 0x7ffff])
#define psR2u64(mem) (*(u64*)&eeMem->ROM2[(mem) & 0x7ffff])
// VU0 and VU1 memory (40KB, rounded up to 1MB for simplicity).
static constexpr u32 VUmemOffset = IOPmemOffset + IOPmemSize;
static constexpr u32 VUmemSize = 0x100000;
#define psSs32(mem) (*(s32 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSs64(mem) (*(s64 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSs128(mem) (*(s128*)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu32(mem) (*(u32 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff])
// VTLB virtual map ((4GB / 4096) * sizeof(ptr))
static constexpr u32 VTLBVirtualMapOffset = VUmemOffset + VUmemSize;
static constexpr u32 VTLBVirtualMapSize = (0x100000000ULL / 4096) * sizeof(void*);
extern void memAllocate();
extern void memReset();
extern void memRelease();
// 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
{
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
#define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff))
#define psHs8(mem) (*(s8*)&eeHw[(mem)&0xffff])
#define psHs16(mem) (*(s16*)&eeHw[(mem)&0xffff])
#define psHs32(mem) (*(s32*)&eeHw[(mem)&0xffff])
#define psHs64(mem) (*(s64*)&eeHw[(mem)&0xffff])
#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 psMs8(mem) (*(s8*)&eeMem->Main[(mem)&0x1ffffff])
#define psMs16(mem) (*(s16*)&eeMem->Main[(mem)&0x1ffffff])
#define psMs32(mem) (*(s32*)&eeMem->Main[(mem)&0x1ffffff])
#define psMs64(mem) (*(s64*)&eeMem->Main[(mem)&0x1ffffff])
#define psMu8(mem) (*(u8*)&eeMem->Main[(mem)&0x1ffffff])
#define psMu16(mem) (*(u16*)&eeMem->Main[(mem)&0x1ffffff])
#define psMu32(mem) (*(u32*)&eeMem->Main[(mem)&0x1ffffff])
#define psMu64(mem) (*(u64*)&eeMem->Main[(mem)&0x1ffffff])
#define psRs8(mem) (*(s8*)&eeMem->ROM[(mem)&0x3fffff])
#define psRs16(mem) (*(s16*)&eeMem->ROM[(mem)&0x3fffff])
#define psRs32(mem) (*(s32*)&eeMem->ROM[(mem)&0x3fffff])
#define psRs64(mem) (*(s64*)&eeMem->ROM[(mem)&0x3fffff])
#define psRu8(mem) (*(u8*)&eeMem->ROM[(mem)&0x3fffff])
#define psRu16(mem) (*(u16*)&eeMem->ROM[(mem)&0x3fffff])
#define psRu32(mem) (*(u32*)&eeMem->ROM[(mem)&0x3fffff])
#define psRu64(mem) (*(u64*)&eeMem->ROM[(mem)&0x3fffff])
#define psR1s8(mem) (*(s8*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1s16(mem) (*(s16*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1s32(mem) (*(s32*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1s64(mem) (*(s64*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1u8(mem) (*(u8*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1u16(mem) (*(u16*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1u32(mem) (*(u32*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR1u64(mem) (*(u64*)&eeMem->ROM1[(mem)&0x3fffff])
#define psR2s8(mem) (*(s8*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2s16(mem) (*(s16*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2s32(mem) (*(s32*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2s64(mem) (*(s64*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2u8(mem) (*(u8*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2u16(mem) (*(u16*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2u32(mem) (*(u32*)&eeMem->ROM2[(mem)&0x7ffff])
#define psR2u64(mem) (*(u64*)&eeMem->ROM2[(mem)&0x7ffff])
#define psSs32(mem) (*(s32*)&eeMem->Scratch[(mem)&0x3fff])
#define psSs64(mem) (*(s64*)&eeMem->Scratch[(mem)&0x3fff])
#define psSs128(mem) (*(s128*)&eeMem->Scratch[(mem)&0x3fff])
#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();
@ -83,11 +216,14 @@ extern void memMapVUmicro();
#define memWrite32 vtlb_memWrite<mem32_t>
#define memWrite64 vtlb_memWrite<mem64_t>
static __fi void memRead128(u32 mem, mem128_t* out) { r128_store(out, vtlb_memRead128(mem)); }
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)); }
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);

View File

@ -34,6 +34,8 @@ static constexpr FPControlRegister DEFAULT_VU_FP_CONTROL_REGISTER = FPControlReg
.SetFlushToZero(true)
.SetRoundMode(FPRoundMode::ChopZero);
Pcsx2Config EmuConfig;
const char* SettingInfo::StringDefaultValue() const
{
return default_value ? default_value : "";

View File

@ -8,7 +8,6 @@
#include "common/Threading.h"
#include "PerformanceMetrics.h"
#include "System.h"
#include "GS.h"
#include "GS/GSCapture.h"

View File

@ -3,9 +3,14 @@
#pragma once
#include "System.h"
#include "PadData.h"
#include "common/Pcsx2Defs.h"
#include <optional>
#include <string>
#include <vector>
// NOTE / TODOs for Version 2
// - Move fromSavestate, undoCount, and total frames into the header

View File

@ -3,6 +3,10 @@
#pragma once
#include "common/Pcsx2Defs.h"
#include <tuple>
class PadData
{
public:

View File

@ -15,7 +15,6 @@
#include <array>
#include <chrono>
#include "System.h"
#include "Config.h"
#include "Host.h"
#include "IconsFontAwesome5.h"

View File

@ -7,7 +7,6 @@
#include "common/Assertions.h"
#include "common/Path.h"
#include "System.h"
#include "Config.h"
#include "Host.h"
#include "IconsFontAwesome5.h"

View File

@ -58,7 +58,7 @@ static void PreLoadPrep()
// clear protected pages, since we don't want to fault loading EE memory
mmap_ResetBlockTracking();
SysClearExecutionCache();
VMManager::Internal::ClearCPUExecutionCaches();
}
static void PostLoadPrep()
@ -515,7 +515,6 @@ public:
virtual bool FreezeIn(zip_file_t* zf) const override
{
SysClearExecutionCache();
return MemorySavestateEntry::FreezeIn(zf);
}
};

View File

@ -5,9 +5,9 @@
#include <deque>
#include <memory>
#include <string>
#include <vector>
#include "System.h"
#include "common/Assertions.h"
class Error;

View File

@ -11,7 +11,6 @@
#include "DebugTools/Debug.h"
#include "R3000A.h"
#include "System.h"
#include "x86/iR5900.h"
#include "fmt/core.h"

View File

@ -1,409 +0,0 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
#include "Common.h"
#include "GS/Renderers/Common/GSFunctionMap.h"
#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"
#include "ps2/BiosTools.h"
#include "svnrev.h"
#include "SysForwardDefs.h"
#include "x86/newVif.h"
#include "cpuinfo.h"
#include "common/BitUtils.h"
#include "common/Perf.h"
#include "common/StringUtil.h"
extern R5900cpu GSDumpReplayerCpu;
Pcsx2Config EmuConfig;
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
// This function should be called once during program execution.
void SysLogMachineCaps()
{
if (!PCSX2_isReleaseVersion)
{
if (GIT_TAGGED_COMMIT) // Nightly builds
{
// tagged commit - more modern implementation of dev build versioning
// - there is no need to include the commit - that is associated with the tag,
// - git is implied and the tag is timestamped
Console.WriteLn(Color_StrongGreen, "PCSX2 Nightly - %s Compiled on %s", GIT_TAG, __DATE__);
}
else
{
Console.WriteLn(Color_StrongGreen, "PCSX2 %u.%u.%u-%lld"
#ifndef DISABLE_BUILD_DATE
"- compiled on " __DATE__
#endif
,
PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
SVN_REV);
}
}
else
{ // shorter release version string
Console.WriteLn(Color_StrongGreen, "PCSX2 %u.%u.%u-%lld"
#ifndef DISABLE_BUILD_DATE
"- compiled on " __DATE__
#endif
,
PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
SVN_REV);
}
Console.WriteLn("Savestate version: 0x%x", g_SaveVersion);
Console.Newline();
Console.WriteLn(Color_StrongBlack, "Host Machine Init:");
Console.Indent().WriteLn(
"Operating System = %s\n"
"Physical RAM = %u MB",
GetOSVersionString().c_str(),
(u32)(GetPhysicalMemory() / _1mb));
Console.Indent().WriteLn("Processor = %s", cpuinfo_get_package(0)->name);
Console.Indent().WriteLn("Core Count = %u cores", cpuinfo_get_cores_count());
Console.Indent().WriteLn("Thread Count = %u threads", cpuinfo_get_processors_count());
Console.Newline();
std::string features;
if (cpuinfo_has_x86_avx())
features += "AVX ";
if (cpuinfo_has_x86_avx2())
features += "AVX2 ";
StringUtil::StripWhitespace(&features);
Console.WriteLn(Color_StrongBlack, "x86 Features Detected:");
Console.Indent().WriteLn("%s", features.c_str());
Console.Newline();
}
namespace HostMemoryMap
{
// For debuggers
extern "C" {
#ifdef _WIN32
_declspec(dllexport) uptr EEmem, IOPmem, VUmem;
#else
__attribute__((visibility("default"), used)) uptr EEmem, IOPmem, VUmem;
#endif
}
} // namespace HostMemoryMap
u8* SysMemory::TryAllocateVirtualMemory(const char* name, void* file_handle, uptr base, size_t size)
{
u8* baseptr;
if (file_handle)
baseptr = static_cast<u8*>(HostSys::MapSharedMemory(file_handle, 0, (void*)base, size, PageAccess_ReadWrite()));
else
baseptr = static_cast<u8*>(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*)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)
// On x86-64, code can reach 8*2^28 from its address [-6*2^28, 4*2^28] is the region that allows for code in the 640mb allocation to reach 512mb of code that either starts at codeBase or 256mb before it.
// We start high and count down because on macOS code starts at the beginning of useable address space, so starting as far ahead as possible reduces address variations due to code size. Not sure about other platforms. Obviously this only actually affects what shows up in a debugger and won't affect performance or correctness of anything.
for (int offset = 4; offset >= -6; offset--)
{
uptr base = codeBase + (offset << 28) + offset_from_base;
if ((sptr)base < 0 || (sptr)(base + size - 1) < 0)
{
// VTLB will throw a fit if we try to put EE main memory here
continue;
}
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);
}
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)
{
Host::ReportErrorAsync("Error", "Failed to create shared memory file.");
ReleaseMemoryMap();
return false;
}
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;
}
void SysMemory::DumpMemoryMap()
{
#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
}
void SysMemory::ReleaseMemoryMap()
{
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 SysMemory::Allocate()
{
DevCon.WriteLn(Color_StrongBlue, "Allocating host memory for virtual systems...");
ConsoleIndentScope indent(1);
if (!AllocateMemoryMap())
return false;
memAllocate();
iopMemAlloc();
vuMemAllocate();
if (!vtlb_Core_Alloc())
return false;
return true;
}
void SysMemory::Reset()
{
DevCon.WriteLn(Color_StrongBlue, "Resetting host memory for virtual systems...");
ConsoleIndentScope indent(1);
memReset();
iopMemReset();
vuMemReset();
// Note: newVif is reset as part of other VIF structures.
// Software is reset on the GS thread.
}
void SysMemory::Release()
{
Console.WriteLn(Color_Blue, "Releasing host memory for virtual systems...");
ConsoleIndentScope indent(1);
vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit).
releaseNewVif(0);
releaseNewVif(1);
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()
{
recCpu.Reserve();
psxRec.Reserve();
CpuMicroVU0.Reserve();
CpuMicroVU1.Reserve();
VifUnpackSSE_Init();
}
SysCpuProviderPack::~SysCpuProviderPack()
{
if (newVifDynaRec)
{
dVifRelease(1);
dVifRelease(0);
}
CpuMicroVU1.Shutdown();
CpuMicroVU0.Shutdown();
psxRec.Shutdown();
recCpu.Shutdown();
}
BaseVUmicroCPU* CpuVU0 = nullptr;
BaseVUmicroCPU* CpuVU1 = nullptr;
void SysCpuProviderPack::ApplyConfig() const
{
if (GSDumpReplayer::IsReplayingDump())
{
Cpu = &GSDumpReplayerCpu;
psxCpu = &psxInt;
CpuVU0 = &CpuIntVU0;
CpuVU1 = &CpuIntVU1;
return;
}
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
CpuVU0 = &CpuIntVU0;
CpuVU1 = &CpuIntVU1;
if (EmuConfig.Cpu.Recompiler.EnableVU0)
CpuVU0 = &CpuMicroVU0;
if (EmuConfig.Cpu.Recompiler.EnableVU1)
CpuVU1 = &CpuMicroVU1;
}
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
// This can be called at any time outside the context of a Cpu->Execute() block without
// bad things happening (recompilers will slow down for a brief moment since rec code blocks
// are dumped).
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
void SysClearExecutionCache()
{
Cpu->Reset();
psxCpu->Reset();
// mVU's VU0 needs to be properly initialized for macro mode even if it's not used for micro mode!
if (CHECK_EEREC && !EmuConfig.Cpu.Recompiler.EnableVU0)
CpuMicroVU0.Reset();
CpuVU0->Reset();
CpuVU1->Reset();
if (newVifDynaRec)
{
dVifReset(0);
dVifReset(1);
}
}

View File

@ -1,163 +0,0 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
#pragma once
#include "Config.h"
#include "vtlb.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 138.5MB, but we round up to 139MB for simplicity).
static constexpr u32 EEmemOffset = 0x00000000;
static constexpr u32 EEmemSize = 0x8B00000;
// 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 (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
{
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
// --------------------------------------------------------------------------------------
class SysCpuProviderPack
{
public:
SysCpuProviderPack();
~SysCpuProviderPack();
void ApplyConfig() const;
};
// GetCpuProviders - this function is not implemented by PCSX2 core -- it must be
// implemented by the provisioning interface.
// TODO: Purge this and the class above
extern SysCpuProviderPack& GetCpuProviders();
extern void SysLogMachineCaps(); // Detects cpu type and fills cpuInfo structs.
extern void SysClearExecutionCache(); // clears recompiled execution caches!

View File

@ -27,6 +27,7 @@
#include "PINE.h"
#include "Patch.h"
#include "PerformanceMetrics.h"
#include "R3000A.h"
#include "R5900.h"
#include "Recording/InputRecording.h"
#include "Recording/InputRecordingControls.h"
@ -36,9 +37,11 @@
#include "SIO/Sio0.h"
#include "SIO/Sio2.h"
#include "SPU2/spu2.h"
#include "SysForwardDefs.h"
#include "USB/USB.h"
#include "VMManager.h"
#include "ps2/BiosTools.h"
#include "svnrev.h"
#include "common/Console.h"
#include "common/Error.h"
@ -70,8 +73,17 @@
#include "common/Darwin/DarwinMisc.h"
#endif
#ifdef _M_X86
#include "x86/newVif.h"
#endif
namespace VMManager
{
static void LogCPUCapabilities();
static void InitializeCPUProviders();
static void ShutdownCPUProviders();
static void UpdateCPUImplementations();
static void ApplyGameFixes();
static bool UpdateGameSettingsLayer();
static void CheckForConfigChanges(const Pcsx2Config& old_config);
@ -130,7 +142,6 @@ namespace VMManager
static constexpr u32 SETTINGS_VERSION = 1;
static std::unique_ptr<SysCpuProviderPack> s_cpu_provider_pack;
static std::unique_ptr<INISettingsInterface> s_game_settings_interface;
static std::unique_ptr<INISettingsInterface> s_input_settings_interface;
@ -176,6 +187,9 @@ static PINEServer s_pine_server;
static bool s_discord_presence_active = false;
static time_t s_discord_presence_time_epoch;
// Making GSDumpReplayer.h dependent on R5900.h is a no-no, since the GS uses it.
extern R5900cpu GSDumpReplayerCpu;
bool VMManager::PerformEarlyHardwareChecks(const char** error)
{
#define COMMON_DOWNLOAD_MESSAGE "PCSX2 builds can be downloaded from https://pcsx2.net/downloads/"
@ -344,7 +358,7 @@ bool VMManager::Internal::CPUThreadInitialize()
if (!cpuinfo_initialize())
Console.Error("cpuinfo_initialize() failed.");
SysLogMachineCaps();
LogCPUCapabilities();
if (!SysMemory::Allocate())
{
@ -352,8 +366,7 @@ bool VMManager::Internal::CPUThreadInitialize()
return false;
}
pxAssert(!s_cpu_provider_pack);
s_cpu_provider_pack = std::make_unique<SysCpuProviderPack>();
InitializeCPUProviders();
GSinit();
USBinit();
@ -384,8 +397,6 @@ void VMManager::Internal::CPUThreadShutdown()
InputManager::CloseSources();
WaitForSaveStateFlush();
s_cpu_provider_pack.reset();
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle());
USBshutdown();
@ -393,6 +404,8 @@ void VMManager::Internal::CPUThreadShutdown()
MTGS::ShutdownThread();
ShutdownCPUProviders();
SysMemory::Release();
#ifdef _WIN32
@ -400,11 +413,6 @@ void VMManager::Internal::CPUThreadShutdown()
#endif
}
SysCpuProviderPack& GetCpuProviders()
{
return *s_cpu_provider_pack;
}
bool VMManager::Internal::CheckSettingsVersion()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
@ -1232,9 +1240,9 @@ bool VMManager::Initialize(VMBootParameters boot_params)
s_use_vsync_for_timing = false;
s_cpu_implementation_changed = false;
s_cpu_provider_pack->ApplyConfig();
UpdateCPUImplementations();
Internal::ClearCPUExecutionCaches();
FPControlRegister::SetCurrent(EmuConfig.Cpu.FPUFPCR);
SysClearExecutionCache();
memBindConditionalHandlers();
SysMemory::Reset();
cpuReset();
@ -1468,7 +1476,7 @@ void VMManager::Reset()
if (elf_was_changed)
HandleELFChange(false);
SysClearExecutionCache();
Internal::ClearCPUExecutionCaches();
memBindConditionalHandlers();
SysMemory::Reset();
cpuReset();
@ -2110,14 +2118,150 @@ bool VMManager::IsLoadableFileName(const std::string_view& path)
return IsDiscFileName(path) || IsElfFileName(path) || IsGSDumpFileName(path) || IsBlockDumpFileName(path);
}
void VMManager::LogCPUCapabilities()
{
if (!PCSX2_isReleaseVersion)
{
if (GIT_TAGGED_COMMIT) // Nightly builds
{
// tagged commit - more modern implementation of dev build versioning
// - there is no need to include the commit - that is associated with the tag,
// - git is implied and the tag is timestamped
Console.WriteLn(Color_StrongGreen, "PCSX2 Nightly - %s Compiled on %s", GIT_TAG, __DATE__);
}
else
{
Console.WriteLn(Color_StrongGreen, "PCSX2 %u.%u.%u-%lld"
#ifndef DISABLE_BUILD_DATE
"- compiled on " __DATE__
#endif
,
PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
SVN_REV);
}
}
else
{ // shorter release version string
Console.WriteLn(Color_StrongGreen, "PCSX2 %u.%u.%u-%lld"
#ifndef DISABLE_BUILD_DATE
"- compiled on " __DATE__
#endif
,
PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
SVN_REV);
}
Console.WriteLn("Savestate version: 0x%x", g_SaveVersion);
Console.Newline();
Console.WriteLn(Color_StrongBlack, "Host Machine Init:");
Console.Indent().WriteLn(
"Operating System = %s\n"
"Physical RAM = %u MB",
GetOSVersionString().c_str(),
(u32)(GetPhysicalMemory() / _1mb));
Console.Indent().WriteLn("Processor = %s", cpuinfo_get_package(0)->name);
Console.Indent().WriteLn("Core Count = %u cores", cpuinfo_get_cores_count());
Console.Indent().WriteLn("Thread Count = %u threads", cpuinfo_get_processors_count());
Console.Newline();
std::string features;
if (cpuinfo_has_x86_avx())
features += "AVX ";
if (cpuinfo_has_x86_avx2())
features += "AVX2 ";
StringUtil::StripWhitespace(&features);
Console.WriteLn(Color_StrongBlack, "x86 Features Detected:");
Console.Indent().WriteLn("%s", features.c_str());
Console.Newline();
}
void VMManager::InitializeCPUProviders()
{
recCpu.Reserve();
psxRec.Reserve();
CpuMicroVU0.Reserve();
CpuMicroVU1.Reserve();
VifUnpackSSE_Init();
}
void VMManager::ShutdownCPUProviders()
{
if (newVifDynaRec)
{
dVifRelease(1);
dVifRelease(0);
}
CpuMicroVU1.Shutdown();
CpuMicroVU0.Shutdown();
psxRec.Shutdown();
recCpu.Shutdown();
}
void VMManager::UpdateCPUImplementations()
{
if (GSDumpReplayer::IsReplayingDump())
{
Cpu = &GSDumpReplayerCpu;
psxCpu = &psxInt;
CpuVU0 = &CpuIntVU0;
CpuVU1 = &CpuIntVU1;
return;
}
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
CpuVU0 = &CpuIntVU0;
CpuVU1 = &CpuIntVU1;
if (EmuConfig.Cpu.Recompiler.EnableVU0)
CpuVU0 = &CpuMicroVU0;
if (EmuConfig.Cpu.Recompiler.EnableVU1)
CpuVU1 = &CpuMicroVU1;
}
void VMManager::Internal::ClearCPUExecutionCaches()
{
Cpu->Reset();
psxCpu->Reset();
// mVU's VU0 needs to be properly initialized for macro mode even if it's not used for micro mode!
if (CHECK_EEREC && !EmuConfig.Cpu.Recompiler.EnableVU0)
CpuMicroVU0.Reset();
CpuVU0->Reset();
CpuVU1->Reset();
if constexpr (newVifDynaRec)
{
dVifReset(0);
dVifReset(1);
}
}
void VMManager::Execute()
{
// Check for interpreter<->recompiler switches.
if (std::exchange(s_cpu_implementation_changed, false))
{
// We need to switch the cpus out, and reset the new ones if so.
s_cpu_provider_pack->ApplyConfig();
SysClearExecutionCache();
UpdateCPUImplementations();
Internal::ClearCPUExecutionCaches();
vtlb_ResetFastmem();
}
@ -2232,8 +2376,10 @@ void VMManager::Internal::EntryPointCompilingOnCPUThread()
// If the config changes at this point, it's a reset, so the game doesn't currently know about the memcard
// so there's no need to leave the eject running.
FileMcd_CancelEject();
// Toss all the recs, we're going to be executing new code.
SysClearExecutionCache();
mmap_ResetBlockTracking();
ClearCPUExecutionCaches();
}
void VMManager::Internal::VSyncOnCPUThread()
@ -2291,7 +2437,7 @@ void VMManager::CheckForCPUConfigChanges(const Pcsx2Config& old_config)
Console.WriteLn("Updating CPU configuration...");
FPControlRegister::SetCurrent(EmuConfig.Cpu.FPUFPCR);
SysClearExecutionCache();
Internal::ClearCPUExecutionCaches();
memBindConditionalHandlers();
if (EmuConfig.Cpu.Recompiler.EnableFastmem != old_config.Cpu.Recompiler.EnableFastmem)

View File

@ -252,6 +252,9 @@ namespace VMManager
/// Throttles execution, or limits the frame rate.
void Throttle();
/// Resets/clears all execution/code caches.
void ClearCPUExecutionCaches();
const std::string& GetELFOverride();
bool IsExecutionInterrupted();
void ELFLoadingOnCPUThread(std::string elf_path);

View File

@ -7,6 +7,9 @@
#include "GS.h"
#include "Gif_Unit.h"
BaseVUmicroCPU* CpuVU0 = nullptr;
BaseVUmicroCPU* CpuVU1 = nullptr;
__inline u32 CalculateMinRunCycles(u32 cycles, bool requiresAccurateCycles)
{
// If we're running an interlocked COP2 operation

View File

@ -360,7 +360,6 @@
</ClCompile>
<ClCompile Include="SaveState.cpp" />
<ClCompile Include="SourceLog.cpp" />
<ClCompile Include="System.cpp" />
<ClCompile Include="Elfheader.cpp" />
<ClCompile Include="CDVD\InputIsoFile.cpp" />
<ClCompile Include="x86\BaseblockEx.cpp" />
@ -710,7 +709,6 @@
<ClInclude Include="Common.h" />
<ClInclude Include="Config.h" />
<ClInclude Include="SaveState.h" />
<ClInclude Include="System.h" />
<ClInclude Include="Counters.h" />
<ClInclude Include="Dmac.h" />
<ClInclude Include="Hardware.h" />

View File

@ -416,9 +416,6 @@
<ClCompile Include="SourceLog.cpp">
<Filter>System</Filter>
</ClCompile>
<ClCompile Include="System.cpp">
<Filter>System</Filter>
</ClCompile>
<ClCompile Include="Elfheader.cpp">
<Filter>System\ISO</Filter>
</ClCompile>
@ -1439,9 +1436,6 @@
<ClInclude Include="SaveState.h">
<Filter>System\Include</Filter>
</ClInclude>
<ClInclude Include="System.h">
<Filter>System\Include</Filter>
</ClInclude>
<ClInclude Include="Dmac.h">
<Filter>System\Ps2\EmotionEngine\Hardware</Filter>
</ClInclude>

View File

@ -4,8 +4,8 @@
#pragma once
#include "MemoryTypes.h"
#include "System.h"
#include "common/General.h"
#include "common/SingleRegisterTypes.h"
static const uptr VTLB_AllocUpperBounds = _1gb * 2;

View File

@ -1,11 +1,12 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
#include "System.h"
#include "iR5900.h"
#include "Config.h"
#include "R3000A.h"
#include "Vif.h"
#include "VU.h"
#include "R3000A.h"
#include "x86/iCore.h"
#include "x86/iR5900.h"
using namespace x86Emitter;

View File

@ -8,7 +8,6 @@
#include "IopBios.h"
#include "IopHw.h"
#include "Common.h"
#include "System.h"
#include "VMManager.h"
#include <time.h>

View File

@ -3,11 +3,13 @@
#pragma once
#include "common/emitter/x86emitter.h"
#include "Config.h"
#include "R5900.h"
#include "R5900_Profiler.h"
#include "VU.h"
#include "iCore.h"
#include "R5900_Profiler.h"
#include "common/emitter/x86emitter.h"
// Register containing a pointer to our fastmem (4GB) area
#define RFASTMEMBASE x86Emitter::rbp

View File

@ -2,7 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0+
#include "R3000A.h"
#include "System.h"
#include "VU.h"
#include "Vif.h"
#include "x86/iR3000A.h"

View File

@ -8,7 +8,6 @@
#include "GS.h"
#include "Memory.h"
#include "Patch.h"
#include "System.h"
#include "R3000A.h"
#include "R5900OpcodeTables.h"
#include "VMManager.h"

View File

@ -16,7 +16,6 @@
#include "Gif_Unit.h"
#include "iR5900.h"
#include "R5900OpcodeTables.h"
#include "System.h"
#include "common/emitter/x86emitter.h"
#include "microVU_Misc.h"
#include "microVU_IR.h"

View File

@ -59,7 +59,6 @@ struct nVifStruct
};
extern void resetNewVif(int idx);
extern void releaseNewVif(int idx);
alignas(16) extern nVifStruct nVif[2];
alignas(16) extern nVifCall nVifUpk[(2 * 2 * 16) * 4]; // ([USN][Masking][Unpack Type]) [curCycle]