From fbcaf83d30f4a467517058b3ec395961c23b69ec Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Thu, 5 Jan 2023 05:18:24 +0100 Subject: [PATCH] HW/GPFifo: Refactor to class, move to Core::System. --- Source/Core/Core/FifoPlayer/FifoPlayer.cpp | 51 +++++++++----- Source/Core/Core/HW/GPFifo.cpp | 66 +++++++++++-------- Source/Core/Core/HW/GPFifo.h | 66 +++++++++++++------ Source/Core/Core/HW/HW.cpp | 4 +- Source/Core/Core/HW/ProcessorInterface.cpp | 4 +- .../Interpreter_SystemRegisters.cpp | 5 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 4 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 6 +- Source/Core/Core/PowerPC/MMU.cpp | 9 +-- Source/Core/Core/System.cpp | 11 +++- Source/Core/Core/System.h | 5 ++ 11 files changed, 150 insertions(+), 81 deletions(-) diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index d077b0060f..e85cc84cc6 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -511,7 +511,9 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end) u32 written = start; u32 lastBurstEnd = end - 1; - auto& core_timing = Core::System::GetInstance().GetCoreTiming(); + auto& system = Core::System::GetInstance(); + auto& core_timing = system.GetCoreTiming(); + auto& gpfifo = system.GetGPFifo(); // Write up to 256 bytes at a time while (written < end) @@ -530,7 +532,7 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end) PowerPC::ppcState.gather_pipe_ptr += burstEnd - written; written = burstEnd; - GPFifo::Write8(data[written++]); + gpfifo.Write8(data[written++]); // Advance core timing u32 elapsedCycles = u32(((u64)written * m_CyclesPerFrame) / m_FrameFifoSize); @@ -706,13 +708,16 @@ void FifoPlayer::WritePI(u32 address, u32 value) void FifoPlayer::FlushWGP() { + auto& system = Core::System::GetInstance(); + auto& gpfifo = system.GetGPFifo(); + // Send 31 0s through the WGP for (int i = 0; i < 7; ++i) - GPFifo::Write32(0); - GPFifo::Write16(0); - GPFifo::Write8(0); + gpfifo.Write32(0); + gpfifo.Write16(0); + gpfifo.Write8(0); - GPFifo::ResetGatherPipe(); + gpfifo.ResetGatherPipe(); } void FifoPlayer::WaitForGPUInactive() @@ -729,34 +734,46 @@ void FifoPlayer::WaitForGPUInactive() void FifoPlayer::LoadBPReg(u8 reg, u32 value) { - GPFifo::Write8(0x61); // load BP reg + auto& system = Core::System::GetInstance(); + auto& gpfifo = system.GetGPFifo(); + + gpfifo.Write8(0x61); // load BP reg u32 cmd = (reg << 24) & 0xff000000; cmd |= (value & 0x00ffffff); - GPFifo::Write32(cmd); + gpfifo.Write32(cmd); } void FifoPlayer::LoadCPReg(u8 reg, u32 value) { - GPFifo::Write8(0x08); // load CP reg - GPFifo::Write8(reg); - GPFifo::Write32(value); + auto& system = Core::System::GetInstance(); + auto& gpfifo = system.GetGPFifo(); + + gpfifo.Write8(0x08); // load CP reg + gpfifo.Write8(reg); + gpfifo.Write32(value); } void FifoPlayer::LoadXFReg(u16 reg, u32 value) { - GPFifo::Write8(0x10); // load XF reg - GPFifo::Write32((reg & 0x0fff) | 0x1000); // load 4 bytes into reg - GPFifo::Write32(value); + auto& system = Core::System::GetInstance(); + auto& gpfifo = system.GetGPFifo(); + + gpfifo.Write8(0x10); // load XF reg + gpfifo.Write32((reg & 0x0fff) | 0x1000); // load 4 bytes into reg + gpfifo.Write32(value); } void FifoPlayer::LoadXFMem16(u16 address, const u32* data) { + auto& system = Core::System::GetInstance(); + auto& gpfifo = system.GetGPFifo(); + // Loads 16 * 4 bytes in xf memory starting at address - GPFifo::Write8(0x10); // load XF reg - GPFifo::Write32(0x000f0000 | (address & 0xffff)); // load 16 * 4 bytes into address + gpfifo.Write8(0x10); // load XF reg + gpfifo.Write32(0x000f0000 | (address & 0xffff)); // load 16 * 4 bytes into address for (int i = 0; i < 16; ++i) - GPFifo::Write32(data[i]); + gpfifo.Write32(data[i]); } bool FifoPlayer::ShouldLoadBP(u8 address) diff --git a/Source/Core/Core/HW/GPFifo.cpp b/Source/Core/Core/HW/GPFifo.cpp index 7c0e4d2805..923f6310ac 100644 --- a/Source/Core/Core/HW/GPFifo.cpp +++ b/Source/Core/Core/HW/GPFifo.cpp @@ -18,6 +18,10 @@ namespace GPFifo { +GPFifoManager::GPFifoManager(Core::System& system) : m_system(system) +{ +} + // 32 Byte gather pipe with extra space // Overfilling is no problem (up to the real limit), CheckGatherPipe will blast the // contents in nicely sized chunks @@ -29,35 +33,32 @@ namespace GPFifo // Both of these should actually work! Only problem is that we have to decide at run time, // the same function could use both methods. Compile 2 different versions of each such block? -// More room for the fastmodes -alignas(GATHER_PIPE_SIZE) static u8 s_gather_pipe[GATHER_PIPE_EXTRA_SIZE]; - -static size_t GetGatherPipeCount() +size_t GPFifoManager::GetGatherPipeCount() { - return PowerPC::ppcState.gather_pipe_ptr - s_gather_pipe; + return PowerPC::ppcState.gather_pipe_ptr - m_gather_pipe; } -static void SetGatherPipeCount(size_t size) +void GPFifoManager::SetGatherPipeCount(size_t size) { - PowerPC::ppcState.gather_pipe_ptr = s_gather_pipe + size; + PowerPC::ppcState.gather_pipe_ptr = m_gather_pipe + size; } -void DoState(PointerWrap& p) +void GPFifoManager::DoState(PointerWrap& p) { - p.Do(s_gather_pipe); + p.Do(m_gather_pipe); u32 pipe_count = static_cast(GetGatherPipeCount()); p.Do(pipe_count); SetGatherPipeCount(pipe_count); } -void Init() +void GPFifoManager::Init() { ResetGatherPipe(); - PowerPC::ppcState.gather_pipe_base_ptr = s_gather_pipe; - memset(s_gather_pipe, 0, sizeof(s_gather_pipe)); + PowerPC::ppcState.gather_pipe_base_ptr = m_gather_pipe; + memset(m_gather_pipe, 0, sizeof(m_gather_pipe)); } -bool IsBNE() +bool GPFifoManager::IsBNE() const { // TODO: It's not clear exactly when the BNE (buffer not empty) bit is set. // The PPC 750cl manual says in section 2.1.2.12 "Write Pipe Address Register (WPAR)" (page 78): @@ -76,14 +77,14 @@ bool IsBNE() return false; } -void ResetGatherPipe() +void GPFifoManager::ResetGatherPipe() { SetGatherPipeCount(0); } -void UpdateGatherPipe() +void GPFifoManager::UpdateGatherPipe() { - auto& system = Core::System::GetInstance(); + auto& system = m_system; auto& memory = system.GetMemory(); auto& processor_interface = system.GetProcessorInterface(); @@ -93,7 +94,7 @@ void UpdateGatherPipe() for (processed = 0; pipe_count >= GATHER_PIPE_SIZE; processed += GATHER_PIPE_SIZE) { // copy the GatherPipe - memcpy(cur_mem, s_gather_pipe + processed, GATHER_PIPE_SIZE); + memcpy(cur_mem, m_gather_pipe + processed, GATHER_PIPE_SIZE); pipe_count -= GATHER_PIPE_SIZE; // increase the CPUWritePointer @@ -112,11 +113,11 @@ void UpdateGatherPipe() } // move back the spill bytes - memmove(s_gather_pipe, s_gather_pipe + processed, pipe_count); + memmove(m_gather_pipe, m_gather_pipe + processed, pipe_count); SetGatherPipeCount(pipe_count); } -void FastCheckGatherPipe() +void GPFifoManager::FastCheckGatherPipe() { if (GetGatherPipeCount() >= GATHER_PIPE_SIZE) { @@ -124,7 +125,7 @@ void FastCheckGatherPipe() } } -void CheckGatherPipe() +void GPFifoManager::CheckGatherPipe() { if (GetGatherPipeCount() >= GATHER_PIPE_SIZE) { @@ -135,55 +136,64 @@ void CheckGatherPipe() } } -void Write8(const u8 value) +void GPFifoManager::Write8(const u8 value) { FastWrite8(value); CheckGatherPipe(); } -void Write16(const u16 value) +void GPFifoManager::Write16(const u16 value) { FastWrite16(value); CheckGatherPipe(); } -void Write32(const u32 value) +void GPFifoManager::Write32(const u32 value) { FastWrite32(value); CheckGatherPipe(); } -void Write64(const u64 value) +void GPFifoManager::Write64(const u64 value) { FastWrite64(value); CheckGatherPipe(); } -void FastWrite8(const u8 value) +void GPFifoManager::FastWrite8(const u8 value) { *PowerPC::ppcState.gather_pipe_ptr = value; PowerPC::ppcState.gather_pipe_ptr += sizeof(u8); } -void FastWrite16(u16 value) +void GPFifoManager::FastWrite16(u16 value) { value = Common::swap16(value); std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u16)); PowerPC::ppcState.gather_pipe_ptr += sizeof(u16); } -void FastWrite32(u32 value) +void GPFifoManager::FastWrite32(u32 value) { value = Common::swap32(value); std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u32)); PowerPC::ppcState.gather_pipe_ptr += sizeof(u32); } -void FastWrite64(u64 value) +void GPFifoManager::FastWrite64(u64 value) { value = Common::swap64(value); std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u64)); PowerPC::ppcState.gather_pipe_ptr += sizeof(u64); } +void UpdateGatherPipe(GPFifoManager& gpfifo) +{ + gpfifo.UpdateGatherPipe(); +} + +void FastCheckGatherPipe(GPFifoManager& gpfifo) +{ + gpfifo.FastCheckGatherPipe(); +} } // namespace GPFifo diff --git a/Source/Core/Core/HW/GPFifo.h b/Source/Core/Core/HW/GPFifo.h index 4ba023117f..6ca8eeecf8 100644 --- a/Source/Core/Core/HW/GPFifo.h +++ b/Source/Core/Core/HW/GPFifo.h @@ -7,6 +7,11 @@ class PointerWrap; +namespace Core +{ +class System; +} + namespace GPFifo { // This address is configurable in the WPAR SPR, but all games put it at this address @@ -16,29 +21,48 @@ constexpr u32 GATHER_PIPE_PHYSICAL_ADDRESS = 0x0C008000; constexpr u32 GATHER_PIPE_SIZE = 32; constexpr u32 GATHER_PIPE_EXTRA_SIZE = GATHER_PIPE_SIZE * 16; -// Init -void Init(); -void DoState(PointerWrap& p); +class GPFifoManager final +{ +public: + explicit GPFifoManager(Core::System& system); -// ResetGatherPipe -void ResetGatherPipe(); -void UpdateGatherPipe(); -void CheckGatherPipe(); -void FastCheckGatherPipe(); + // Init + void Init(); + void DoState(PointerWrap& p); -bool IsBNE(); + // ResetGatherPipe + void ResetGatherPipe(); + void UpdateGatherPipe(); + void CheckGatherPipe(); + void FastCheckGatherPipe(); -// Write -void Write8(u8 value); -void Write16(u16 value); -void Write32(u32 value); -void Write64(u64 value); + bool IsBNE() const; -// These expect pre-byteswapped values -// Also there's an upper limit of about 512 per batch -// Most likely these should be inlined into JIT instead -void FastWrite8(u8 value); -void FastWrite16(u16 value); -void FastWrite32(u32 value); -void FastWrite64(u64 value); + // Write + void Write8(u8 value); + void Write16(u16 value); + void Write32(u32 value); + void Write64(u64 value); + + // These expect pre-byteswapped values + // Also there's an upper limit of about 512 per batch + // Most likely these should be inlined into JIT instead + void FastWrite8(u8 value); + void FastWrite16(u16 value); + void FastWrite32(u32 value); + void FastWrite64(u64 value); + +private: + size_t GetGatherPipeCount(); + void SetGatherPipeCount(size_t size); + + // More room for the fastmodes + alignas(GATHER_PIPE_SIZE) u8 m_gather_pipe[GATHER_PIPE_EXTRA_SIZE]; + + Core::System& m_system; +}; + +// For use from the JIT. +void UpdateGatherPipe(GPFifoManager& gpfifo); +void FastCheckGatherPipe(GPFifoManager& gpfifo); } // namespace GPFifo diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp index 759e6fd632..f6fe73bd1b 100644 --- a/Source/Core/Core/HW/HW.cpp +++ b/Source/Core/Core/HW/HW.cpp @@ -51,7 +51,7 @@ void Init(const Sram* override_sram) MemoryInterface::Init(); DSP::Init(Config::Get(Config::MAIN_DSP_HLE)); DVDInterface::Init(); - GPFifo::Init(); + system.GetGPFifo().Init(); CPU::Init(Config::Get(Config::MAIN_CPU_CORE)); SystemTimers::Init(); @@ -103,7 +103,7 @@ void DoState(PointerWrap& p) p.DoMarker("DSP"); DVDInterface::DoState(p); p.DoMarker("DVDInterface"); - GPFifo::DoState(p); + system.GetGPFifo().DoState(p); p.DoMarker("GPFifo"); ExpansionInterface::DoState(p); p.DoMarker("ExpansionInterface"); diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index ebb7a9620f..a93b4342cc 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -85,12 +85,12 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::DirectWrite(&m_fifo_cpu_write_pointer, 0xFFFFFFE0)); mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead(), - MMIO::ComplexWrite([](Core::System&, u32, u32 val) { + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { // Used by GXAbortFrame INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val); if ((val & 1) != 0) { - GPFifo::ResetGatherPipe(); + system.GetGPFifo().ResetGatherPipe(); // Call Fifo::ResetVideoBuffer() from the video thread. Since that function // resets various pointers used by the video thread, we can't call it directly diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 8699f05b75..f70d75d09f 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -12,6 +12,7 @@ #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" /* @@ -244,7 +245,7 @@ void Interpreter::mfspr(UGeckoInstruction inst) // GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS)). // Currently, we always treat the buffer as not empty, as the exact behavior is unclear // (and games that use display lists will hang if the bit doesn't eventually become zero). - if (GPFifo::IsBNE()) + if (Core::System::GetInstance().GetGPFifo().IsBNE()) rSPR(index) |= 1; else rSPR(index) &= ~1; @@ -346,7 +347,7 @@ void Interpreter::mtspr(UGeckoInstruction inst) case SPR_WPAR: ASSERT_MSG(POWERPC, rSPR(SPR_WPAR) == GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS, "Gather pipe changed to unexpected address {:08x} @ PC {:08x}", rSPR(SPR_WPAR), PC); - GPFifo::ResetGatherPipe(); + Core::System::GetInstance().GetGPFifo().ResetGatherPipe(); break; // Graphics Quantization Registers diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 2c7aeee92b..8014b8d4e0 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -527,7 +527,7 @@ bool Jit64::Cleanup() CMP(64, R(RSCRATCH), Imm32(GPFifo::GATHER_PIPE_SIZE)); FixupBranch exit = J_CC(CC_L); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(GPFifo::UpdateGatherPipe); + ABI_CallFunctionP(GPFifo::UpdateGatherPipe, &Core::System::GetInstance().GetGPFifo()); ABI_PopRegistersAndAdjustStack({}, 0); SetJumpTarget(exit); did_something = true; @@ -1027,7 +1027,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) js.mustCheckFifo = false; BitSet32 registersInUse = CallerSavedRegistersInUse(); ABI_PushRegistersAndAdjustStack(registersInUse, 0); - ABI_CallFunction(GPFifo::FastCheckGatherPipe); + ABI_CallFunctionP(GPFifo::FastCheckGatherPipe, &Core::System::GetInstance().GetGPFifo()); ABI_PopRegistersAndAdjustStack(registersInUse, 0); gatherPipeIntCheck = true; } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 3ed46c1482..e52bbe2931 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -281,8 +281,9 @@ void JitArm64::Cleanup() SUB(ARM64Reg::X0, ARM64Reg::X0, ARM64Reg::X1); CMP(ARM64Reg::X0, GPFifo::GATHER_PIPE_SIZE); FixupBranch exit = B(CC_LT); - MOVP2R(ARM64Reg::X0, &GPFifo::UpdateGatherPipe); - BLR(ARM64Reg::X0); + MOVP2R(ARM64Reg::X1, &GPFifo::UpdateGatherPipe); + MOVP2R(ARM64Reg::X0, &Core::System::GetInstance().GetGPFifo()); + BLR(ARM64Reg::X1); SetJumpTarget(exit); } @@ -965,6 +966,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) ABI_PushRegisters(regs_in_use); m_float_emit.ABI_PushRegisters(fprs_in_use, ARM64Reg::X30); MOVP2R(ARM64Reg::X8, &GPFifo::FastCheckGatherPipe); + MOVP2R(ARM64Reg::X0, &Core::System::GetInstance().GetGPFifo()); BLR(ARM64Reg::X8); m_float_emit.ABI_PopRegisters(fprs_in_use, ARM64Reg::X30); ABI_PopRegisters(regs_in_use); diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 150b6673ec..29a5e24472 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -307,20 +307,21 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, switch (size) { case 1: - GPFifo::Write8(static_cast(data)); + system.GetGPFifo().Write8(static_cast(data)); return; case 2: - GPFifo::Write16(static_cast(data)); + system.GetGPFifo().Write16(static_cast(data)); return; case 4: - GPFifo::Write32(data); + system.GetGPFifo().Write32(data); return; default: // Some kind of misaligned write. TODO: Does this match how the actual hardware handles it? + auto& gpfifo = system.GetGPFifo(); for (size_t i = size * 8; i > 0;) { i -= 8; - GPFifo::Write8(static_cast(data >> i)); + gpfifo.Write8(static_cast(data >> i)); } return; } diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index a52996667a..a03d3958be 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -13,6 +13,7 @@ #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/DVD/DVDThread.h" #include "Core/HW/EXI/EXI.h" +#include "Core/HW/GPFifo.h" #include "Core/HW/Memmap.h" #include "Core/HW/MemoryInterface.h" #include "Core/HW/ProcessorInterface.h" @@ -30,6 +31,8 @@ namespace Core { struct System::Impl { + explicit Impl(System& system) : m_gp_fifo(system) {} + std::unique_ptr m_sound_stream; bool m_sound_stream_running = false; bool m_audio_dump_started = false; @@ -43,6 +46,7 @@ struct System::Impl ExpansionInterface::ExpansionInterfaceState m_expansion_interface_state; Fifo::FifoManager m_fifo; GeometryShaderManager m_geometry_shader_manager; + GPFifo::GPFifoManager m_gp_fifo; Memory::MemoryManager m_memory; MemoryInterface::MemoryInterfaceState m_memory_interface_state; PixelEngine::PixelEngineManager m_pixel_engine; @@ -54,7 +58,7 @@ struct System::Impl VideoInterface::VideoInterfaceState m_video_interface_state; }; -System::System() : m_impl{std::make_unique()} +System::System() : m_impl{std::make_unique(*this)} { } @@ -142,6 +146,11 @@ GeometryShaderManager& System::GetGeometryShaderManager() const return m_impl->m_geometry_shader_manager; } +GPFifo::GPFifoManager& System::GetGPFifo() const +{ + return m_impl->m_gp_fifo; +} + Memory::MemoryManager& System::GetMemory() const { return m_impl->m_memory; diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 0d6a9dbd92..410da6d697 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -43,6 +43,10 @@ namespace Fifo { class FifoManager; } +namespace GPFifo +{ +class GPFifoManager; +} namespace Memory { class MemoryManager; @@ -111,6 +115,7 @@ public: ExpansionInterface::ExpansionInterfaceState& GetExpansionInterfaceState() const; Fifo::FifoManager& GetFifo() const; GeometryShaderManager& GetGeometryShaderManager() const; + GPFifo::GPFifoManager& GetGPFifo() const; Memory::MemoryManager& GetMemory() const; MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const; PixelEngine::PixelEngineManager& GetPixelEngine() const;