From 0a6fdb9c133666c7c038a4933e24ee6e4346100f Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 14 Oct 2022 02:17:09 +0200 Subject: [PATCH 1/2] HW: Pass System to MMIO handlers. --- Source/Core/Common/x64Emitter.h | 4 +- Source/Core/Core/HW/AudioInterface.cpp | 21 +++--- Source/Core/Core/HW/DSP.cpp | 48 ++++++------- Source/Core/Core/HW/DVD/DVDInterface.cpp | 12 ++-- Source/Core/Core/HW/EXI/EXI_Channel.cpp | 6 +- Source/Core/Core/HW/MMIO.cpp | 70 +++++++++++-------- Source/Core/Core/HW/MMIO.h | 5 +- Source/Core/Core/HW/MMIOHandlers.h | 26 ++++--- Source/Core/Core/HW/ProcessorInterface.cpp | 10 +-- Source/Core/Core/HW/SI/SI.cpp | 31 ++++---- Source/Core/Core/HW/VideoInterface.cpp | 66 ++++++++--------- Source/Core/Core/HW/WII_IPC.cpp | 23 +++--- .../Core/PowerPC/Jit64Common/EmuCodeBlock.cpp | 7 +- .../Core/Core/PowerPC/JitArm64/Jit_Util.cpp | 20 +++--- Source/Core/VideoCommon/CommandProcessor.cpp | 53 +++++++------- Source/Core/VideoCommon/PixelEngine.cpp | 8 +-- Source/UnitTests/Core/MMIOTest.cpp | 4 +- 17 files changed, 215 insertions(+), 199 deletions(-) diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 9e078a0e1ec6..d027a1a9ef28 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -1168,10 +1168,10 @@ class XEmitter } template - void ABI_CallLambdaC(const std::function* f, u32 p1) + void ABI_CallLambdaPC(const std::function* f, void* p1, u32 p2) { auto trampoline = &XEmitter::CallLambdaTrampoline; - ABI_CallFunctionPC(trampoline, reinterpret_cast(f), p1); + ABI_CallFunctionPPC(trampoline, reinterpret_cast(f), p1, p2); } }; // class XEmitter diff --git a/Source/Core/Core/HW/AudioInterface.cpp b/Source/Core/Core/HW/AudioInterface.cpp index 4a3f4cd25493..48dcfe932339 100644 --- a/Source/Core/Core/HW/AudioInterface.cpp +++ b/Source/Core/Core/HW/AudioInterface.cpp @@ -282,10 +282,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register( base | AI_CONTROL_REGISTER, MMIO::DirectRead(&state.control.hex), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { const AICR tmp_ai_ctrl(val); - auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); + auto& state = system.GetAudioInterfaceState().GetData(); if (state.control.AIINTMSK != tmp_ai_ctrl.AIINTMSK) { DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AIINTMSK to {}", tmp_ai_ctrl.AIINTMSK); @@ -347,25 +347,24 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) })); mmio->Register(base | AI_VOLUME_REGISTER, MMIO::DirectRead(&state.volume.hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetAudioInterfaceState().GetData(); state.volume.hex = val; - auto& system = Core::System::GetInstance(); SoundStream* sound_stream = system.GetSoundStream(); sound_stream->GetMixer()->SetStreamingVolume(state.volume.left, state.volume.right); })); - mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); + mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetAudioInterfaceState().GetData(); const u64 cycles_streamed = IsPlaying() ? (CoreTiming::GetTicks() - state.last_cpu_time) : state.last_cpu_time; return state.sample_counter + static_cast(cycles_streamed / state.cpu_cycles_per_sample); }), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetAudioInterfaceState().GetData(); state.sample_counter = val; state.last_cpu_time = CoreTiming::GetTicks(); CoreTiming::RemoveEvent(state.event_type_ai); @@ -373,8 +372,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) })); mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead(&state.interrupt_timing), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetAudioInterfaceState().GetData(); DEBUG_LOG_FMT(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING={:08x} at PC: {:08x}", val, PowerPC::ppcState.pc); state.interrupt_timing = val; diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index a64e7bf88e2d..b474ea5558fc 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -301,8 +301,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } // DSP mail MMIOs call DSP emulator functions to get results or write data. - mmio->Register(base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + mmio->Register(base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetDSPState().GetData(); if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle) { state.dsp_emulator->DSP_Update(DSP_MAIL_SLICE); @@ -310,20 +310,20 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } return state.dsp_emulator->DSP_ReadMailBoxHigh(true); }), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetDSPState().GetData(); state.dsp_emulator->DSP_WriteMailBoxHigh(true, val); })); - mmio->Register(base | DSP_MAIL_TO_DSP_LO, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + mmio->Register(base | DSP_MAIL_TO_DSP_LO, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetDSPState().GetData(); return state.dsp_emulator->DSP_ReadMailBoxLow(true); }), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetDSPState().GetData(); state.dsp_emulator->DSP_WriteMailBoxLow(true, val); })); - mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetDSPState().GetData(); if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle) { state.dsp_emulator->DSP_Update(DSP_MAIL_SLICE); @@ -332,20 +332,20 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) return state.dsp_emulator->DSP_ReadMailBoxHigh(false); }), MMIO::InvalidWrite()); - mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetDSPState().GetData(); return state.dsp_emulator->DSP_ReadMailBoxLow(false); }), MMIO::InvalidWrite()); mmio->Register( - base | DSP_CONTROL, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + base | DSP_CONTROL, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetDSPState().GetData(); return (state.dsp_control.Hex & ~DSP_CONTROL_MASK) | (state.dsp_emulator->DSP_ReadControlRegister() & DSP_CONTROL_MASK); }), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetDSPState().GetData(); UDSPControl tmpControl; tmpControl.Hex = (val & ~DSP_CONTROL_MASK) | @@ -394,8 +394,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // ARAM MMIO controlling the DMA start. mmio->Register(base | AR_DMA_CNT_L, MMIO::DirectRead(MMIO::Utils::LowPart(&state.aram_dma.Cnt.Hex)), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetDSPState().GetData(); state.aram_dma.Cnt.Hex = (state.aram_dma.Cnt.Hex & 0xFFFF0000) | (val & WMASK_LO_ALIGN_32BIT); Do_ARAM_DMA(); @@ -403,8 +403,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | AUDIO_DMA_START_HI, MMIO::DirectRead(MMIO::Utils::HighPart(&state.audio_dma.SourceAddress)), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetDSPState().GetData(); *MMIO::Utils::HighPart(&state.audio_dma.SourceAddress) = val & (SConfig::GetInstance().bWii ? WMASK_AUDIO_HI_RESTRICT_WII : WMASK_AUDIO_HI_RESTRICT_GCN); @@ -413,8 +413,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Audio DMA MMIO controlling the DMA start. mmio->Register( base | AUDIO_DMA_CONTROL_LEN, MMIO::DirectRead(&state.audio_dma.AudioDMAControl.Hex), - MMIO::ComplexWrite([](u32, u16 val) { - auto& system = Core::System::GetInstance(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { auto& state = system.GetDSPState().GetData(); bool already_enabled = state.audio_dma.AudioDMAControl.Enable; state.audio_dma.AudioDMAControl.Hex = val; @@ -439,10 +438,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Audio DMA blocks remaining is invalid to write to, and requires logic on // the read side. - mmio->Register(base | AUDIO_DMA_BLOCKS_LEFT, MMIO::ComplexRead([](u32) { + mmio->Register(base | AUDIO_DMA_BLOCKS_LEFT, + MMIO::ComplexRead([](Core::System& system, u32) { // remaining_blocks_count is zero-based. DreamMix World Fighters will hang if it // never reaches zero. - auto& state = Core::System::GetInstance().GetDSPState().GetData(); + auto& state = system.GetDSPState().GetData(); return (state.audio_dma.remaining_blocks_count > 0 ? state.audio_dma.remaining_blocks_count - 1 : 0); diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index ac90fd4d767e..cc743d822009 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -640,8 +640,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii) { auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); mmio->Register(base | DI_STATUS_REGISTER, MMIO::DirectRead(&state.DISR.Hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetDVDInterfaceState().GetData(); const UDISR tmp_status_reg(val); state.DISR.DEINTMASK = tmp_status_reg.DEINTMASK.Value(); @@ -667,8 +667,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii) })); mmio->Register(base | DI_COVER_REGISTER, MMIO::DirectRead(&state.DICVR.Hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetDVDInterfaceState().GetData(); const UDICVR tmp_cover_reg(val); state.DICVR.CVRINTMASK = tmp_cover_reg.CVRINTMASK.Value(); @@ -705,8 +705,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii) mmio->Register(base | DI_DMA_LENGTH_REGISTER, MMIO::DirectRead(&state.DILENGTH), MMIO::DirectWrite(&state.DILENGTH, ~0x1F)); mmio->Register(base | DI_DMA_CONTROL_REGISTER, MMIO::DirectRead(&state.DICR.Hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetDVDInterfaceState().GetData(); state.DICR.Hex = val & 7; if (state.DICR.TSTART) { diff --git a/Source/Core/Core/HW/EXI/EXI_Channel.cpp b/Source/Core/Core/HW/EXI/EXI_Channel.cpp index 53d0417da135..63256d661b5c 100644 --- a/Source/Core/Core/HW/EXI/EXI_Channel.cpp +++ b/Source/Core/Core/HW/EXI/EXI_Channel.cpp @@ -47,7 +47,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Warning: the base is not aligned on a page boundary here. We can't use | // to select a register address, instead we need to use +. - mmio->Register(base + EXI_STATUS, MMIO::ComplexRead([this](u32) { + mmio->Register(base + EXI_STATUS, MMIO::ComplexRead([this](Core::System&, u32) { // check if external device is present // pretty sure it is memcard only, not entirely sure if (m_channel_id == 2) @@ -61,7 +61,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) return m_status.Hex; }), - MMIO::ComplexWrite([this](u32, u32 val) { + MMIO::ComplexWrite([this](Core::System&, u32, u32 val) { UEXI_STATUS new_status(val); m_status.EXIINTMASK = new_status.EXIINTMASK; @@ -98,7 +98,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base + EXI_DMA_LENGTH, MMIO::DirectRead(&m_dma_length), MMIO::DirectWrite(&m_dma_length)); mmio->Register(base + EXI_DMA_CONTROL, MMIO::DirectRead(&m_control.Hex), - MMIO::ComplexWrite([this](u32, u32 val) { + MMIO::ComplexWrite([this](Core::System&, u32, u32 val) { m_control.Hex = val; if (m_control.TSTART) diff --git a/Source/Core/Core/HW/MMIO.cpp b/Source/Core/Core/HW/MMIO.cpp index 0686b477e890..fad11055324d 100644 --- a/Source/Core/Core/HW/MMIO.cpp +++ b/Source/Core/Core/HW/MMIO.cpp @@ -112,12 +112,12 @@ template class ComplexHandlingMethod : public ReadHandlingMethod, public WriteHandlingMethod { public: - explicit ComplexHandlingMethod(std::function read_lambda) + explicit ComplexHandlingMethod(std::function read_lambda) : read_lambda_(read_lambda), write_lambda_(InvalidWriteLambda()) { } - explicit ComplexHandlingMethod(std::function write_lambda) + explicit ComplexHandlingMethod(std::function write_lambda) : read_lambda_(InvalidReadLambda()), write_lambda_(write_lambda) { } @@ -134,9 +134,9 @@ class ComplexHandlingMethod : public ReadHandlingMethod, public WriteHandling } private: - std::function InvalidReadLambda() const + std::function InvalidReadLambda() const { - return [](u32) { + return [](Core::System&, u32) { DEBUG_ASSERT_MSG(MEMMAP, 0, "Called the read lambda on a write " "complex handler."); @@ -144,25 +144,25 @@ class ComplexHandlingMethod : public ReadHandlingMethod, public WriteHandling }; } - std::function InvalidWriteLambda() const + std::function InvalidWriteLambda() const { - return [](u32, T) { + return [](Core::System&, u32, T) { DEBUG_ASSERT_MSG(MEMMAP, 0, "Called the write lambda on a read " "complex handler."); }; } - std::function read_lambda_; - std::function write_lambda_; + std::function read_lambda_; + std::function write_lambda_; }; template -ReadHandlingMethod* ComplexRead(std::function lambda) +ReadHandlingMethod* ComplexRead(std::function lambda) { return new ComplexHandlingMethod(lambda); } template -WriteHandlingMethod* ComplexWrite(std::function lambda) +WriteHandlingMethod* ComplexWrite(std::function lambda) { return new ComplexHandlingMethod(lambda); } @@ -172,7 +172,7 @@ WriteHandlingMethod* ComplexWrite(std::function lambda) template ReadHandlingMethod* InvalidRead() { - return ComplexRead([](u32 addr) { + return ComplexRead([](Core::System&, u32 addr) { ERROR_LOG_FMT(MEMMAP, "Trying to read {} bits from an invalid MMIO (addr={:08x})", 8 * sizeof(T), addr); return -1; @@ -181,7 +181,7 @@ ReadHandlingMethod* InvalidRead() template WriteHandlingMethod* InvalidWrite() { - return ComplexWrite([](u32 addr, T val) { + return ComplexWrite([](Core::System&, u32 addr, T val) { ERROR_LOG_FMT(MEMMAP, "Trying to write {} bits to an invalid MMIO (addr={:08x}, val={:08x})", 8 * sizeof(T), addr, val); }); @@ -229,8 +229,9 @@ ReadHandlingMethod* ReadToSmaller(Mapping* mmio, u32 high_part_addr, u32 low_ ReadHandler* low_part = &mmio->GetHandlerForRead(low_part_addr); // TODO(delroth): optimize - return ComplexRead([=](u32 addr) { - return ((T)high_part->Read(high_part_addr) << (8 * sizeof(ST))) | low_part->Read(low_part_addr); + return ComplexRead([=](Core::System& system, u32 addr) { + return ((T)high_part->Read(system, high_part_addr) << (8 * sizeof(ST))) | + low_part->Read(system, low_part_addr); }); } @@ -243,9 +244,9 @@ WriteHandlingMethod* WriteToSmaller(Mapping* mmio, u32 high_part_addr, u32 lo WriteHandler* low_part = &mmio->GetHandlerForWrite(low_part_addr); // TODO(delroth): optimize - return ComplexWrite([=](u32 addr, T val) { - high_part->Write(high_part_addr, val >> (8 * sizeof(ST))); - low_part->Write(low_part_addr, (ST)val); + return ComplexWrite([=](Core::System& system, u32 addr, T val) { + high_part->Write(system, high_part_addr, val >> (8 * sizeof(ST))); + low_part->Write(system, low_part_addr, (ST)val); }); } @@ -257,8 +258,9 @@ ReadHandlingMethod* ReadToLarger(Mapping* mmio, u32 larger_addr, u32 shift) ReadHandler* large = &mmio->GetHandlerForRead(larger_addr); // TODO(delroth): optimize - return ComplexRead( - [large, shift](u32 addr) { return large->Read(addr & ~(sizeof(LT) - 1)) >> shift; }); + return ComplexRead([large, shift](Core::System& system, u32 addr) { + return large->Read(system, addr & ~(sizeof(LT) - 1)) >> shift; + }); } // Inplementation of the ReadHandler and WriteHandler class. There is a lot of @@ -290,7 +292,7 @@ void ReadHandler::Visit(ReadHandlingMethodVisitor& visitor) } template -T ReadHandler::Read(u32 addr) +T ReadHandler::Read(Core::System& system, u32 addr) { // Check if the handler has already been initialized. For real // handlers, this will always be the case, so this branch should be @@ -298,7 +300,7 @@ T ReadHandler::Read(u32 addr) if (!m_Method) InitializeInvalid(); - return m_ReadFunc(addr); + return m_ReadFunc(system, addr); } template @@ -310,19 +312,22 @@ void ReadHandler::ResetMethod(ReadHandlingMethod* method) { virtual ~FuncCreatorVisitor() = default; - std::function ret; + std::function ret; void VisitConstant(T value) override { - ret = [value](u32) { return value; }; + ret = [value](Core::System&, u32) { return value; }; } void VisitDirect(const T* addr, u32 mask) override { - ret = [addr, mask](u32) { return *addr & mask; }; + ret = [addr, mask](Core::System&, u32) { return *addr & mask; }; } - void VisitComplex(const std::function* lambda) override { ret = *lambda; } + void VisitComplex(const std::function* lambda) override + { + ret = *lambda; + } }; FuncCreatorVisitor v; @@ -362,7 +367,7 @@ void WriteHandler::Visit(WriteHandlingMethodVisitor& visitor) } template -void WriteHandler::Write(u32 addr, T val) +void WriteHandler::Write(Core::System& system, u32 addr, T val) { // Check if the handler has already been initialized. For real // handlers, this will always be the case, so this branch should be @@ -370,7 +375,7 @@ void WriteHandler::Write(u32 addr, T val) if (!m_Method) InitializeInvalid(); - m_WriteFunc(addr, val); + m_WriteFunc(system, addr, val); } template @@ -382,19 +387,22 @@ void WriteHandler::ResetMethod(WriteHandlingMethod* method) { virtual ~FuncCreatorVisitor() = default; - std::function ret; + std::function ret; void VisitNop() override { - ret = [](u32, T) {}; + ret = [](Core::System&, u32, T) {}; } void VisitDirect(T* ptr, u32 mask) override { - ret = [ptr, mask](u32, T val) { *ptr = val & mask; }; + ret = [ptr, mask](Core::System&, u32, T val) { *ptr = val & mask; }; } - void VisitComplex(const std::function* lambda) override { ret = *lambda; } + void VisitComplex(const std::function* lambda) override + { + ret = *lambda; + } }; FuncCreatorVisitor v; diff --git a/Source/Core/Core/HW/MMIO.h b/Source/Core/Core/HW/MMIO.h index 92c35bc5f354..1b7a6476c60b 100644 --- a/Source/Core/Core/HW/MMIO.h +++ b/Source/Core/Core/HW/MMIO.h @@ -15,6 +15,7 @@ #include "Core/ConfigManager.h" #include "Core/HW/GPFifo.h" #include "Core/HW/MMIOHandlers.h" +#include "Core/System.h" namespace MMIO { @@ -132,13 +133,13 @@ class Mapping template Unit Read(u32 addr) { - return GetHandlerForRead(addr).Read(addr); + return GetHandlerForRead(addr).Read(Core::System::GetInstance(), addr); } template void Write(u32 addr, Unit val) { - GetHandlerForWrite(addr).Write(addr, val); + GetHandlerForWrite(addr).Write(Core::System::GetInstance(), addr, val); } // Handlers access interface. diff --git a/Source/Core/Core/HW/MMIOHandlers.h b/Source/Core/Core/HW/MMIOHandlers.h index beaac7d09fdd..45eb9d3c5a8b 100644 --- a/Source/Core/Core/HW/MMIOHandlers.h +++ b/Source/Core/Core/HW/MMIOHandlers.h @@ -18,6 +18,10 @@ // u8/u16/u32 with the same code while providing type safety: it is impossible // to mix code from these types, and the type system enforces it. +namespace Core +{ +class System; +} namespace MMIO { class Mapping; @@ -51,9 +55,9 @@ WriteHandlingMethod* DirectWrite(T* addr, u32 mask = 0xFFFFFFFF); // to directly provide a function that will be called when a read/write needs // to be done. template -ReadHandlingMethod* ComplexRead(std::function); +ReadHandlingMethod* ComplexRead(std::function); template -WriteHandlingMethod* ComplexWrite(std::function); +WriteHandlingMethod* ComplexWrite(std::function); // Invalid: log an error and return -1 in case of a read. These are the default // handlers set for all MMIO types. @@ -97,7 +101,7 @@ class ReadHandlingMethodVisitor public: virtual void VisitConstant(T value) = 0; virtual void VisitDirect(const T* addr, u32 mask) = 0; - virtual void VisitComplex(const std::function* lambda) = 0; + virtual void VisitComplex(const std::function* lambda) = 0; }; template class WriteHandlingMethodVisitor @@ -105,7 +109,7 @@ class WriteHandlingMethodVisitor public: virtual void VisitNop() = 0; virtual void VisitDirect(T* addr, u32 mask) = 0; - virtual void VisitComplex(const std::function* lambda) = 0; + virtual void VisitComplex(const std::function* lambda) = 0; }; // These classes are INTERNAL. Do not use outside of the MMIO implementation @@ -126,7 +130,7 @@ class ReadHandler // Entry point for read handling method visitors. void Visit(ReadHandlingMethodVisitor& visitor); - T Read(u32 addr); + T Read(Core::System& system, u32 addr); // Internal method called when changing the internal method object. Its // main role is to make sure the read function is updated at the same time. @@ -137,7 +141,7 @@ class ReadHandler // useless initialization of thousands of unused handler objects. void InitializeInvalid(); std::unique_ptr> m_Method; - std::function m_ReadFunc; + std::function m_ReadFunc; }; template class WriteHandler @@ -153,7 +157,7 @@ class WriteHandler // Entry point for write handling method visitors. void Visit(WriteHandlingMethodVisitor& visitor); - void Write(u32 addr, T val); + void Write(Core::System& system, u32 addr, T val); // Internal method called when changing the internal method object. Its // main role is to make sure the write function is updated at the same @@ -165,7 +169,7 @@ class WriteHandler // useless initialization of thousands of unused handler objects. void InitializeInvalid(); std::unique_ptr> m_Method; - std::function m_WriteFunc; + std::function m_WriteFunc; }; // Boilerplate boilerplate boilerplate. @@ -182,8 +186,10 @@ class WriteHandler MaybeExtern template WriteHandlingMethod* Nop(); \ MaybeExtern template ReadHandlingMethod* DirectRead(const T* addr, u32 mask); \ MaybeExtern template WriteHandlingMethod* DirectWrite(T* addr, u32 mask); \ - MaybeExtern template ReadHandlingMethod* ComplexRead(std::function); \ - MaybeExtern template WriteHandlingMethod* ComplexWrite(std::function); \ + MaybeExtern template ReadHandlingMethod* ComplexRead( \ + std::function); \ + MaybeExtern template WriteHandlingMethod* ComplexWrite( \ + std::function); \ MaybeExtern template ReadHandlingMethod* InvalidRead(); \ MaybeExtern template WriteHandlingMethod* InvalidWrite(); \ MaybeExtern template class ReadHandler; \ diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index 698069a26102..efb324dee2dc 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -82,13 +82,13 @@ void Init() void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { mmio->Register(base | PI_INTERRUPT_CAUSE, MMIO::DirectRead(&m_InterruptCause), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { m_InterruptCause &= ~val; UpdateException(); })); mmio->Register(base | PI_INTERRUPT_MASK, MMIO::DirectRead(&m_InterruptMask), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { m_InterruptMask = val; UpdateException(); })); @@ -103,7 +103,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::DirectWrite(&Fifo_CPUWritePointer, 0xFFFFFFE0)); mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead(), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { // Used by GXAbortFrame INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val); if ((val & 1) != 0) @@ -125,11 +125,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } })); - mmio->Register(base | PI_RESET_CODE, MMIO::ComplexRead([](u32) { + mmio->Register(base | PI_RESET_CODE, MMIO::ComplexRead([](Core::System&, u32) { DEBUG_LOG_FMT(PROCESSORINTERFACE, "Read PI_RESET_CODE: {:08x}", m_ResetCode); return m_ResetCode; }), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { m_ResetCode = val; INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_RESET_CODE: {:08x}", m_ResetCode); if (!SConfig::GetInstance().bWii && ~m_ResetCode & 0x4) diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp index ef0be4f19c9c..edd64c69f319 100644 --- a/Source/Core/Core/HW/SI/SI.cpp +++ b/Source/Core/Core/HW/SI/SI.cpp @@ -490,14 +490,14 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { const u32 address = base | static_cast(io_buffer_base + i); - mmio->Register(address, MMIO::ComplexRead([i](u32) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + mmio->Register(address, MMIO::ComplexRead([i](Core::System& system, u32) { + auto& state = system.GetSerialInterfaceState().GetData(); u32 val; std::memcpy(&val, &state.si_buffer[i], sizeof(val)); return Common::swap32(val); }), - MMIO::ComplexWrite([i](u32, u32 val) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + MMIO::ComplexWrite([i](Core::System& system, u32, u32 val) { + auto& state = system.GetSerialInterfaceState().GetData(); val = Common::swap32(val); std::memcpy(&state.si_buffer[i], &val, sizeof(val)); })); @@ -506,14 +506,14 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { const u32 address = base | static_cast(io_buffer_base + i); - mmio->Register(address, MMIO::ComplexRead([i](u32) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + mmio->Register(address, MMIO::ComplexRead([i](Core::System& system, u32) { + auto& state = system.GetSerialInterfaceState().GetData(); u16 val; std::memcpy(&val, &state.si_buffer[i], sizeof(val)); return Common::swap16(val); }), - MMIO::ComplexWrite([i](u32, u16 val) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + MMIO::ComplexWrite([i](Core::System& system, u32, u16 val) { + auto& state = system.GetSerialInterfaceState().GetData(); val = Common::swap16(val); std::memcpy(&state.si_buffer[i], &val, sizeof(val)); })); @@ -533,16 +533,16 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::DirectRead(&state.channel[i].out.hex), MMIO::DirectWrite(&state.channel[i].out.hex)); mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i), - MMIO::ComplexRead([i, rdst_bit](u32) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + MMIO::ComplexRead([i, rdst_bit](Core::System& system, u32) { + auto& state = system.GetSerialInterfaceState().GetData(); state.status_reg.hex &= ~(1U << rdst_bit); UpdateInterrupts(); return state.channel[i].in_hi.hex; }), MMIO::DirectWrite(&state.channel[i].in_hi.hex)); mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i), - MMIO::ComplexRead([i, rdst_bit](u32) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + MMIO::ComplexRead([i, rdst_bit](Core::System& system, u32) { + auto& state = system.GetSerialInterfaceState().GetData(); state.status_reg.hex &= ~(1U << rdst_bit); UpdateInterrupts(); return state.channel[i].in_lo.hex; @@ -554,8 +554,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::DirectWrite(&state.poll.hex)); mmio->Register(base | SI_COM_CSR, MMIO::DirectRead(&state.com_csr.hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& system = Core::System::GetInstance(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { auto& state = system.GetSerialInterfaceState().GetData(); const USIComCSR tmp_com_csr(val); @@ -584,8 +583,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) })); mmio->Register(base | SI_STATUS_REG, MMIO::DirectRead(&state.status_reg.hex), - MMIO::ComplexWrite([](u32, u32 val) { - auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { + auto& state = system.GetSerialInterfaceState().GetData(); const USIStatusReg tmp_status(val); // clear bits ( if (tmp.bit) SISR.bit=0 ) diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index 6fc36b6a9d46..db195644cdd9 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -266,7 +266,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) for (auto& mapped_var : update_params_on_read_vars) { mmio->Register(base | mapped_var.addr, MMIO::DirectRead(mapped_var.ptr), - MMIO::ComplexWrite([mapped_var](u32, u16 val) { + MMIO::ComplexWrite([mapped_var](Core::System&, u32, u16 val) { *mapped_var.ptr = val; UpdateParameters(); })); @@ -274,29 +274,29 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // XFB related MMIOs that require special handling on writes. mmio->Register(base | VI_FB_LEFT_TOP_HI, MMIO::DirectRead(&state.xfb_info_top.Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.xfb_info_top.Hi = val; if (state.xfb_info_top.CLRPOFF) state.xfb_info_top.POFF = 0; })); mmio->Register(base | VI_FB_LEFT_BOTTOM_HI, MMIO::DirectRead(&state.xfb_info_bottom.Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.xfb_info_bottom.Hi = val; if (state.xfb_info_bottom.CLRPOFF) state.xfb_info_bottom.POFF = 0; })); mmio->Register(base | VI_FB_RIGHT_TOP_HI, MMIO::DirectRead(&state.xfb_3d_info_top.Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.xfb_3d_info_top.Hi = val; if (state.xfb_3d_info_top.CLRPOFF) state.xfb_3d_info_top.POFF = 0; })); mmio->Register(base | VI_FB_RIGHT_BOTTOM_HI, MMIO::DirectRead(&state.xfb_3d_info_bottom.Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.xfb_3d_info_bottom.Hi = val; if (state.xfb_3d_info_bottom.CLRPOFF) state.xfb_3d_info_bottom.POFF = 0; @@ -304,24 +304,24 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // MMIOs with unimplemented writes that trigger warnings. mmio->Register( - base | VI_VERTICAL_BEAM_POSITION, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + base | VI_VERTICAL_BEAM_POSITION, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetVideoInterfaceState().GetData(); return 1 + (state.half_line_count) / 2; }), - MMIO::ComplexWrite([](u32, u16 val) { + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { WARN_LOG_FMT( VIDEOINTERFACE, "Changing vertical beam position to {:#06x} - not documented or implemented yet", val); })); mmio->Register( - base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetVideoInterfaceState().GetData(); u16 value = static_cast( 1 + state.h_timing_0.HLW * (CoreTiming::GetTicks() - state.ticks_last_line_start) / (GetTicksPerHalfLine())); return std::clamp(value, 1, state.h_timing_0.HLW * 2); }), - MMIO::ComplexWrite([](u32, u16 val) { + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { WARN_LOG_FMT( VIDEOINTERFACE, "Changing horizontal beam position to {:#06x} - not documented or implemented yet", @@ -331,50 +331,50 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // The following MMIOs are interrupts related and update interrupt status // on writes. mmio->Register(base | VI_PRERETRACE_HI, MMIO::DirectRead(&state.interrupt_register[0].Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.interrupt_register[0].Hi = val; UpdateInterrupts(); })); mmio->Register(base | VI_POSTRETRACE_HI, MMIO::DirectRead(&state.interrupt_register[1].Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.interrupt_register[1].Hi = val; UpdateInterrupts(); })); mmio->Register(base | VI_DISPLAY_INTERRUPT_2_HI, MMIO::DirectRead(&state.interrupt_register[2].Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.interrupt_register[2].Hi = val; UpdateInterrupts(); })); mmio->Register(base | VI_DISPLAY_INTERRUPT_3_HI, MMIO::DirectRead(&state.interrupt_register[3].Hi), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.interrupt_register[3].Hi = val; UpdateInterrupts(); })); // Unknown anti-aliasing related MMIO register: puts a warning on log and // needs to shift/mask when reading/writing. - mmio->Register(base | VI_UNK_AA_REG_HI, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + mmio->Register(base | VI_UNK_AA_REG_HI, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetVideoInterfaceState().GetData(); return state.unknown_aa_register >> 16; }), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.unknown_aa_register = (state.unknown_aa_register & 0x0000FFFF) | ((u32)val << 16); WARN_LOG_FMT(VIDEOINTERFACE, "Writing to the unknown AA register (hi)"); })); - mmio->Register(base | VI_UNK_AA_REG_LO, MMIO::ComplexRead([](u32) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + mmio->Register(base | VI_UNK_AA_REG_LO, MMIO::ComplexRead([](Core::System& system, u32) { + auto& state = system.GetVideoInterfaceState().GetData(); return state.unknown_aa_register & 0xFFFF; }), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); state.unknown_aa_register = (state.unknown_aa_register & 0xFFFF0000) | val; WARN_LOG_FMT(VIDEOINTERFACE, "Writing to the unknown AA register (lo)"); })); @@ -383,8 +383,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // processing needs to be done if a reset is requested. mmio->Register(base | VI_CONTROL_REGISTER, MMIO::DirectRead(&state.display_control_register.Hex), - MMIO::ComplexWrite([](u32, u16 val) { - auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); + MMIO::ComplexWrite([](Core::System& system, u32, u16 val) { + auto& state = system.GetVideoInterfaceState().GetData(); UVIDisplayControlRegister tmpConfig(val); state.display_control_register.ENB = tmpConfig.ENB; diff --git a/Source/Core/Core/HW/WII_IPC.cpp b/Source/Core/Core/HW/WII_IPC.cpp index aac45c68a13a..933ed40c5c8f 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -174,8 +174,9 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead(), MMIO::DirectWrite(&ppc_msg)); - mmio->Register(base | IPC_PPCCTRL, MMIO::ComplexRead([](u32) { return ctrl.ppc(); }), - MMIO::ComplexWrite([](u32, u32 val) { + mmio->Register(base | IPC_PPCCTRL, + MMIO::ComplexRead([](Core::System&, u32) { return ctrl.ppc(); }), + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { ctrl.ppc(val); // The IPC interrupt is triggered when IY1/IY2 is set and // Y1/Y2 is written to -- even when this results in clearing the bit. @@ -190,14 +191,14 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | IPC_ARMMSG, MMIO::DirectRead(&arm_msg), MMIO::InvalidWrite()); mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead(), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { ppc_irq_flags &= ~val; HLE::GetIOS()->UpdateIPC(); CoreTiming::ScheduleEvent(0, updateInterrupts, 0); })); mmio->Register(base | PPC_IRQMASK, MMIO::InvalidRead(), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { ppc_irq_masks = val; if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf? Reset(); @@ -206,7 +207,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) })); mmio->Register(base | GPIOB_OUT, MMIO::DirectRead(&g_gpio_out.m_hex), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { g_gpio_out.m_hex = (val & gpio_owner.m_hex) | (g_gpio_out.m_hex & ~gpio_owner.m_hex); if (g_gpio_out[GPIO::DO_EJECT]) @@ -218,10 +219,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // TODO: AVE, SLOT_LED })); mmio->Register(base | GPIOB_DIR, MMIO::DirectRead(&gpio_dir.m_hex), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { gpio_dir.m_hex = (val & gpio_owner.m_hex) | (gpio_dir.m_hex & ~gpio_owner.m_hex); })); - mmio->Register(base | GPIOB_IN, MMIO::ComplexRead([](u32) { + mmio->Register(base | GPIOB_IN, MMIO::ComplexRead([](Core::System&, u32) { Common::Flags gpio_in; gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside(); return gpio_in.m_hex; @@ -239,7 +240,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // go through the HW_GPIOB registers if the corresponding bit is set in the HW_GPIO_OWNER // register. mmio->Register(base | GPIO_OUT, MMIO::DirectRead(&g_gpio_out.m_hex), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { g_gpio_out.m_hex = (g_gpio_out.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex); if (g_gpio_out[GPIO::DO_EJECT]) @@ -251,10 +252,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // TODO: AVE, SLOT_LED })); mmio->Register(base | GPIO_DIR, MMIO::DirectRead(&gpio_dir.m_hex), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { gpio_dir.m_hex = (gpio_dir.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex); })); - mmio->Register(base | GPIO_IN, MMIO::ComplexRead([](u32) { + mmio->Register(base | GPIO_IN, MMIO::ComplexRead([](Core::System&, u32) { Common::Flags gpio_in; gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside(); return gpio_in.m_hex; @@ -262,7 +263,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::Nop()); mmio->Register(base | HW_RESETS, MMIO::DirectRead(&resets), - MMIO::ComplexWrite([](u32, u32 val) { + MMIO::ComplexWrite([](Core::System&, u32, u32 val) { // A reset occurs when the corresponding bit is cleared const bool di_reset_triggered = (resets & 0x400) && !(val & 0x400); resets = val; diff --git a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp index ccdb448663c9..7398e6c8b022 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp @@ -19,6 +19,7 @@ #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" using namespace Gen; @@ -220,7 +221,7 @@ class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor { LoadAddrMaskToReg(8 * sizeof(T), addr, mask); } - void VisitComplex(const std::function* lambda) override + void VisitComplex(const std::function* lambda) override { CallLambda(8 * sizeof(T), lambda); } @@ -269,10 +270,10 @@ class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor } } - void CallLambda(int sbits, const std::function* lambda) + void CallLambda(int sbits, const std::function* lambda) { m_code->ABI_PushRegistersAndAdjustStack(m_registers_in_use, 0); - m_code->ABI_CallLambdaC(lambda, m_address); + m_code->ABI_CallLambdaPC(lambda, &Core::System::GetInstance(), m_address); m_code->ABI_PopRegistersAndAdjustStack(m_registers_in_use, 0); MoveOpArgToReg(sbits, R(ABI_RETURN)); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit_Util.cpp index 1674687a5f16..1e0ff978221c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit_Util.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit_Util.cpp @@ -7,8 +7,8 @@ #include "Common/Common.h" #include "Core/HW/MMIO.h" - #include "Core/PowerPC/JitArm64/Jit.h" +#include "Core/System.h" using namespace Arm64Gen; @@ -28,7 +28,7 @@ class MMIOWriteCodeGenerator : public MMIO::WriteHandlingMethodVisitor // Do nothing } void VisitDirect(T* addr, u32 mask) override { WriteRegToAddr(8 * sizeof(T), addr, mask); } - void VisitComplex(const std::function* lambda) override + void VisitComplex(const std::function* lambda) override { CallLambda(8 * sizeof(T), lambda); } @@ -72,15 +72,15 @@ class MMIOWriteCodeGenerator : public MMIO::WriteHandlingMethodVisitor } } - void CallLambda(int sbits, const std::function* lambda) + void CallLambda(int sbits, const std::function* lambda) { ARM64FloatEmitter float_emit(m_emit); m_emit->ABI_PushRegisters(m_gprs_in_use); float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1); - - m_emit->MOVI2R(ARM64Reg::W1, m_address); - m_emit->MOV(ARM64Reg::W2, m_src_reg); + m_emit->MOVP2R(ARM64Reg::X1, &Core::System::GetInstance()); + m_emit->MOVI2R(ARM64Reg::W2, m_address); + m_emit->MOV(ARM64Reg::W3, m_src_reg); m_emit->BLR(m_emit->ABI_SetupLambda(lambda)); float_emit.ABI_PopRegisters(m_fprs_in_use, ARM64Reg::X1); @@ -110,7 +110,7 @@ class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor { LoadAddrMaskToReg(8 * sizeof(T), addr, mask); } - void VisitComplex(const std::function* lambda) override + void VisitComplex(const std::function* lambda) override { CallLambda(8 * sizeof(T), lambda); } @@ -169,14 +169,14 @@ class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor } } - void CallLambda(int sbits, const std::function* lambda) + void CallLambda(int sbits, const std::function* lambda) { ARM64FloatEmitter float_emit(m_emit); m_emit->ABI_PushRegisters(m_gprs_in_use); float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1); - - m_emit->MOVI2R(ARM64Reg::W1, m_address); + m_emit->MOVP2R(ARM64Reg::X1, &Core::System::GetInstance()); + m_emit->MOVI2R(ARM64Reg::W2, m_address); m_emit->BLR(m_emit->ABI_SetupLambda(lambda)); if (m_sign_extend) m_emit->SBFM(m_dst_reg, ARM64Reg::W0, 0, sbits - 1); diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index a5e5591276b4..ded0260b1138 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -239,7 +239,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::InvalidWrite()); } - mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead([](u32) { + mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead([](Core::System&, u32) { Fifo::SyncGPUForRegisterAccess(); SetCpStatusRegister(); return m_CPStatusReg.Hex; @@ -247,7 +247,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::InvalidWrite()); mmio->Register(base | CTRL_REGISTER, MMIO::DirectRead(&m_CPCtrlReg.Hex), - MMIO::ComplexWrite([](u32, u16 val) { + MMIO::ComplexWrite([](Core::System&, u32, u16 val) { UCPCtrlReg tmp(val); m_CPCtrlReg.Hex = tmp.Hex; SetCpControlRegister(); @@ -255,7 +255,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) })); mmio->Register(base | CLEAR_REGISTER, MMIO::DirectRead(&m_CPClearReg.Hex), - MMIO::ComplexWrite([](u32, u16 val) { + MMIO::ComplexWrite([](Core::System&, u32, u16 val) { UCPClearReg tmp(val); m_CPClearReg.Hex = tmp.Hex; SetCpClearRegister(); @@ -267,7 +267,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Some MMIOs have different handlers for single core vs. dual core mode. mmio->Register( base | FIFO_RW_DISTANCE_LO, - IsOnThread() ? MMIO::ComplexRead([](u32) { + IsOnThread() ? MMIO::ComplexRead([](Core::System&, u32) { if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) { @@ -287,7 +287,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) WMASK_LO_ALIGN_32BIT)); mmio->Register(base | FIFO_RW_DISTANCE_HI, IsOnThread() ? - MMIO::ComplexRead([](u32) { + MMIO::ComplexRead([](Core::System&, u32) { Fifo::SyncGPUForRegisterAccess(); if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) @@ -305,11 +305,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) 16; } }) : - MMIO::ComplexRead([](u32) { + MMIO::ComplexRead([](Core::System&, u32) { Fifo::SyncGPUForRegisterAccess(); return fifo.CPReadWriteDistance.load(std::memory_order_relaxed) >> 16; }), - MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { + MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { Fifo::SyncGPUForRegisterAccess(); WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); Fifo::RunGpu(); @@ -319,25 +319,26 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) IsOnThread() ? MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadPointer)), MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); - mmio->Register(base | FIFO_READ_POINTER_HI, - IsOnThread() ? MMIO::ComplexRead([](u32) { - Fifo::SyncGPUForRegisterAccess(); - return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16; - }) : - MMIO::ComplexRead([](u32) { - Fifo::SyncGPUForRegisterAccess(); - return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16; - }), - IsOnThread() ? MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { - Fifo::SyncGPUForRegisterAccess(); - WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); - fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed), - std::memory_order_relaxed); - }) : - MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { - Fifo::SyncGPUForRegisterAccess(); - WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); - })); + mmio->Register( + base | FIFO_READ_POINTER_HI, + IsOnThread() ? MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16; + }) : + MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16; + }), + IsOnThread() ? MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed), + std::memory_order_relaxed); + }) : + MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + })); } void GatherPipeBursted() diff --git a/Source/Core/VideoCommon/PixelEngine.cpp b/Source/Core/VideoCommon/PixelEngine.cpp index c110ffa28490..af8a7a01c28d 100644 --- a/Source/Core/VideoCommon/PixelEngine.cpp +++ b/Source/Core/VideoCommon/PixelEngine.cpp @@ -242,11 +242,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) }; for (auto& pq_reg : pq_regs) { - mmio->Register(base | pq_reg.addr, MMIO::ComplexRead([pq_reg](u32) { + mmio->Register(base | pq_reg.addr, MMIO::ComplexRead([pq_reg](Core::System&, u32) { return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) & 0xFFFF; }), MMIO::InvalidWrite()); - mmio->Register(base | (pq_reg.addr + 2), MMIO::ComplexRead([pq_reg](u32) { + mmio->Register(base | (pq_reg.addr + 2), MMIO::ComplexRead([pq_reg](Core::System&, u32) { return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) >> 16; }), MMIO::InvalidWrite()); @@ -254,7 +254,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Control register mmio->Register(base | PE_CTRL_REGISTER, MMIO::DirectRead(&m_Control.hex), - MMIO::ComplexWrite([](u32, u16 val) { + MMIO::ComplexWrite([](Core::System&, u32, u16 val) { UPECtrlReg tmpCtrl{.hex = val}; if (tmpCtrl.pe_token) @@ -278,7 +278,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // BBOX registers, readonly and need to update a flag. for (int i = 0; i < 4; ++i) { - mmio->Register(base | (PE_BBOX_LEFT + 2 * i), MMIO::ComplexRead([i](u32) { + mmio->Register(base | (PE_BBOX_LEFT + 2 * i), MMIO::ComplexRead([i](Core::System&, u32) { g_renderer->BBoxDisable(); return g_video_backend->Video_GetBoundingBox(i); }), diff --git a/Source/UnitTests/Core/MMIOTest.cpp b/Source/UnitTests/Core/MMIOTest.cpp index e10ee4e0ce5e..a92cdcbc4e0c 100644 --- a/Source/UnitTests/Core/MMIOTest.cpp +++ b/Source/UnitTests/Core/MMIOTest.cpp @@ -121,12 +121,12 @@ TEST_F(MappingTest, ReadWriteComplex) { bool read_called = false, write_called = false; - m_mapping->Register(0x0C001234, MMIO::ComplexRead([&read_called](u32 addr) { + m_mapping->Register(0x0C001234, MMIO::ComplexRead([&read_called](Core::System&, u32 addr) { EXPECT_EQ(0x0C001234u, addr); read_called = true; return 0x12; }), - MMIO::ComplexWrite([&write_called](u32 addr, u8 val) { + MMIO::ComplexWrite([&write_called](Core::System&, u32 addr, u8 val) { EXPECT_EQ(0x0C001234u, addr); EXPECT_EQ(0x34, val); write_called = true; From 545fee9c94c2671f6ae55fa54b1ab734c2ad8b91 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 23 Nov 2022 21:58:18 +0100 Subject: [PATCH 2/2] Core/CommandProcessor: Reformat single/dual core dependent MMIO handlers. --- Source/Core/VideoCommon/CommandProcessor.cpp | 153 +++++++++++-------- 1 file changed, 88 insertions(+), 65 deletions(-) diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index ded0260b1138..ada2d02904d0 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -265,80 +265,103 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | PERF_SELECT, MMIO::InvalidRead(), MMIO::Nop()); // Some MMIOs have different handlers for single core vs. dual core mode. - mmio->Register( - base | FIFO_RW_DISTANCE_LO, - IsOnThread() ? MMIO::ComplexRead([](Core::System&, u32) { - if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= - fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) - { - return static_cast(fifo.CPWritePointer.load(std::memory_order_relaxed) - - fifo.SafeCPReadPointer.load(std::memory_order_relaxed)); - } - else - { - return static_cast(fifo.CPEnd.load(std::memory_order_relaxed) - - fifo.SafeCPReadPointer.load(std::memory_order_relaxed) + - fifo.CPWritePointer.load(std::memory_order_relaxed) - - fifo.CPBase.load(std::memory_order_relaxed) + 32); - } - }) : - MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance)), - MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), - WMASK_LO_ALIGN_32BIT)); - mmio->Register(base | FIFO_RW_DISTANCE_HI, - IsOnThread() ? - MMIO::ComplexRead([](Core::System&, u32) { - Fifo::SyncGPUForRegisterAccess(); - if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= - fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) - { - return (fifo.CPWritePointer.load(std::memory_order_relaxed) - - fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) >> - 16; - } - else - { - return (fifo.CPEnd.load(std::memory_order_relaxed) - - fifo.SafeCPReadPointer.load(std::memory_order_relaxed) + - fifo.CPWritePointer.load(std::memory_order_relaxed) - - fifo.CPBase.load(std::memory_order_relaxed) + 32) >> - 16; - } - }) : - MMIO::ComplexRead([](Core::System&, u32) { - Fifo::SyncGPUForRegisterAccess(); - return fifo.CPReadWriteDistance.load(std::memory_order_relaxed) >> 16; - }), + const bool is_on_thread = IsOnThread(); + MMIO::ReadHandlingMethod* fifo_rw_distance_lo_r; + if (is_on_thread) + { + fifo_rw_distance_lo_r = MMIO::ComplexRead([](Core::System&, u32) { + if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= + fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) + { + return static_cast(fifo.CPWritePointer.load(std::memory_order_relaxed) - + fifo.SafeCPReadPointer.load(std::memory_order_relaxed)); + } + else + { + return static_cast(fifo.CPEnd.load(std::memory_order_relaxed) - + fifo.SafeCPReadPointer.load(std::memory_order_relaxed) + + fifo.CPWritePointer.load(std::memory_order_relaxed) - + fifo.CPBase.load(std::memory_order_relaxed) + 32); + } + }); + } + else + { + fifo_rw_distance_lo_r = MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance)); + } + mmio->Register(base | FIFO_RW_DISTANCE_LO, fifo_rw_distance_lo_r, + MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), + WMASK_LO_ALIGN_32BIT)); + + MMIO::ReadHandlingMethod* fifo_rw_distance_hi_r; + if (is_on_thread) + { + fifo_rw_distance_hi_r = MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= + fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) + { + return (fifo.CPWritePointer.load(std::memory_order_relaxed) - + fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) >> + 16; + } + else + { + return (fifo.CPEnd.load(std::memory_order_relaxed) - + fifo.SafeCPReadPointer.load(std::memory_order_relaxed) + + fifo.CPWritePointer.load(std::memory_order_relaxed) - + fifo.CPBase.load(std::memory_order_relaxed) + 32) >> + 16; + } + }); + } + else + { + fifo_rw_distance_hi_r = MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + return fifo.CPReadWriteDistance.load(std::memory_order_relaxed) >> 16; + }); + } + mmio->Register(base | FIFO_RW_DISTANCE_HI, fifo_rw_distance_hi_r, MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { Fifo::SyncGPUForRegisterAccess(); WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); Fifo::RunGpu(); })); + mmio->Register( base | FIFO_READ_POINTER_LO, - IsOnThread() ? MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : + is_on_thread ? MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadPointer)), MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); - mmio->Register( - base | FIFO_READ_POINTER_HI, - IsOnThread() ? MMIO::ComplexRead([](Core::System&, u32) { - Fifo::SyncGPUForRegisterAccess(); - return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16; - }) : - MMIO::ComplexRead([](Core::System&, u32) { - Fifo::SyncGPUForRegisterAccess(); - return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16; - }), - IsOnThread() ? MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { - Fifo::SyncGPUForRegisterAccess(); - WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); - fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed), - std::memory_order_relaxed); - }) : - MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { - Fifo::SyncGPUForRegisterAccess(); - WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); - })); + + MMIO::ReadHandlingMethod* fifo_read_hi_r; + MMIO::WriteHandlingMethod* fifo_read_hi_w; + if (is_on_thread) + { + fifo_read_hi_r = MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16; + }); + fifo_read_hi_w = MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed), + std::memory_order_relaxed); + }); + } + else + { + fifo_read_hi_r = MMIO::ComplexRead([](Core::System&, u32) { + Fifo::SyncGPUForRegisterAccess(); + return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16; + }); + fifo_read_hi_w = MMIO::ComplexWrite([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + }); + } + mmio->Register(base | FIFO_READ_POINTER_HI, fifo_read_hi_r, fifo_read_hi_w); } void GatherPipeBursted()