Merge pull request #11166 from AdmiralCurtiss/mmio-system

HW: Pass System to MMIO handlers.
This commit is contained in:
Mai 2022-11-24 00:58:45 +00:00 committed by GitHub
commit 7be4c90f67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 280 additions and 241 deletions

View File

@ -1168,10 +1168,10 @@ public:
} }
template <typename T, typename... Args> template <typename T, typename... Args>
void ABI_CallLambdaC(const std::function<T(Args...)>* f, u32 p1) void ABI_CallLambdaPC(const std::function<T(Args...)>* f, void* p1, u32 p2)
{ {
auto trampoline = &XEmitter::CallLambdaTrampoline<T, Args...>; auto trampoline = &XEmitter::CallLambdaTrampoline<T, Args...>;
ABI_CallFunctionPC(trampoline, reinterpret_cast<const void*>(f), p1); ABI_CallFunctionPPC(trampoline, reinterpret_cast<const void*>(f), p1, p2);
} }
}; // class XEmitter }; // class XEmitter

View File

@ -282,10 +282,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register( mmio->Register(
base | AI_CONTROL_REGISTER, MMIO::DirectRead<u32>(&state.control.hex), base | AI_CONTROL_REGISTER, MMIO::DirectRead<u32>(&state.control.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
const AICR tmp_ai_ctrl(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) if (state.control.AIINTMSK != tmp_ai_ctrl.AIINTMSK)
{ {
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AIINTMSK to {}", 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<u32>(&state.volume.hex), mmio->Register(base | AI_VOLUME_REGISTER, MMIO::DirectRead<u32>(&state.volume.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); auto& state = system.GetAudioInterfaceState().GetData();
state.volume.hex = val; state.volume.hex = val;
auto& system = Core::System::GetInstance();
SoundStream* sound_stream = system.GetSoundStream(); SoundStream* sound_stream = system.GetSoundStream();
sound_stream->GetMixer()->SetStreamingVolume(state.volume.left, sound_stream->GetMixer()->SetStreamingVolume(state.volume.left,
state.volume.right); state.volume.right);
})); }));
mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead<u32>([](u32) { mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); auto& state = system.GetAudioInterfaceState().GetData();
const u64 cycles_streamed = IsPlaying() ? const u64 cycles_streamed = IsPlaying() ?
(CoreTiming::GetTicks() - state.last_cpu_time) : (CoreTiming::GetTicks() - state.last_cpu_time) :
state.last_cpu_time; state.last_cpu_time;
return state.sample_counter + return state.sample_counter +
static_cast<u32>(cycles_streamed / state.cpu_cycles_per_sample); static_cast<u32>(cycles_streamed / state.cpu_cycles_per_sample);
}), }),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); auto& state = system.GetAudioInterfaceState().GetData();
state.sample_counter = val; state.sample_counter = val;
state.last_cpu_time = CoreTiming::GetTicks(); state.last_cpu_time = CoreTiming::GetTicks();
CoreTiming::RemoveEvent(state.event_type_ai); 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<u32>(&state.interrupt_timing), mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead<u32>(&state.interrupt_timing),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData(); auto& state = system.GetAudioInterfaceState().GetData();
DEBUG_LOG_FMT(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING={:08x} at PC: {:08x}", val, DEBUG_LOG_FMT(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING={:08x} at PC: {:08x}", val,
PowerPC::ppcState.pc); PowerPC::ppcState.pc);
state.interrupt_timing = val; state.interrupt_timing = val;

View File

@ -301,8 +301,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
// DSP mail MMIOs call DSP emulator functions to get results or write data. // DSP mail MMIOs call DSP emulator functions to get results or write data.
mmio->Register(base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle) if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle)
{ {
state.dsp_emulator->DSP_Update(DSP_MAIL_SLICE); 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); return state.dsp_emulator->DSP_ReadMailBoxHigh(true);
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
state.dsp_emulator->DSP_WriteMailBoxHigh(true, val); state.dsp_emulator->DSP_WriteMailBoxHigh(true, val);
})); }));
mmio->Register(base | DSP_MAIL_TO_DSP_LO, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | DSP_MAIL_TO_DSP_LO, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
return state.dsp_emulator->DSP_ReadMailBoxLow(true); return state.dsp_emulator->DSP_ReadMailBoxLow(true);
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
state.dsp_emulator->DSP_WriteMailBoxLow(true, val); state.dsp_emulator->DSP_WriteMailBoxLow(true, val);
})); }));
mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle) if (state.dsp_slice > DSP_MAIL_SLICE && state.is_lle)
{ {
state.dsp_emulator->DSP_Update(DSP_MAIL_SLICE); 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); return state.dsp_emulator->DSP_ReadMailBoxHigh(false);
}), }),
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
return state.dsp_emulator->DSP_ReadMailBoxLow(false); return state.dsp_emulator->DSP_ReadMailBoxLow(false);
}), }),
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
mmio->Register( mmio->Register(
base | DSP_CONTROL, MMIO::ComplexRead<u16>([](u32) { base | DSP_CONTROL, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
return (state.dsp_control.Hex & ~DSP_CONTROL_MASK) | return (state.dsp_control.Hex & ~DSP_CONTROL_MASK) |
(state.dsp_emulator->DSP_ReadControlRegister() & DSP_CONTROL_MASK); (state.dsp_emulator->DSP_ReadControlRegister() & DSP_CONTROL_MASK);
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
UDSPControl tmpControl; UDSPControl tmpControl;
tmpControl.Hex = (val & ~DSP_CONTROL_MASK) | tmpControl.Hex = (val & ~DSP_CONTROL_MASK) |
@ -394,8 +394,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// ARAM MMIO controlling the DMA start. // ARAM MMIO controlling the DMA start.
mmio->Register(base | AR_DMA_CNT_L, mmio->Register(base | AR_DMA_CNT_L,
MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&state.aram_dma.Cnt.Hex)), MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&state.aram_dma.Cnt.Hex)),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
state.aram_dma.Cnt.Hex = state.aram_dma.Cnt.Hex =
(state.aram_dma.Cnt.Hex & 0xFFFF0000) | (val & WMASK_LO_ALIGN_32BIT); (state.aram_dma.Cnt.Hex & 0xFFFF0000) | (val & WMASK_LO_ALIGN_32BIT);
Do_ARAM_DMA(); Do_ARAM_DMA();
@ -403,8 +403,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | AUDIO_DMA_START_HI, mmio->Register(base | AUDIO_DMA_START_HI,
MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&state.audio_dma.SourceAddress)), MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&state.audio_dma.SourceAddress)),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
*MMIO::Utils::HighPart(&state.audio_dma.SourceAddress) = *MMIO::Utils::HighPart(&state.audio_dma.SourceAddress) =
val & (SConfig::GetInstance().bWii ? WMASK_AUDIO_HI_RESTRICT_WII : val & (SConfig::GetInstance().bWii ? WMASK_AUDIO_HI_RESTRICT_WII :
WMASK_AUDIO_HI_RESTRICT_GCN); WMASK_AUDIO_HI_RESTRICT_GCN);
@ -413,8 +413,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// Audio DMA MMIO controlling the DMA start. // Audio DMA MMIO controlling the DMA start.
mmio->Register( mmio->Register(
base | AUDIO_DMA_CONTROL_LEN, MMIO::DirectRead<u16>(&state.audio_dma.AudioDMAControl.Hex), base | AUDIO_DMA_CONTROL_LEN, MMIO::DirectRead<u16>(&state.audio_dma.AudioDMAControl.Hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& system = Core::System::GetInstance();
auto& state = system.GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
bool already_enabled = state.audio_dma.AudioDMAControl.Enable; bool already_enabled = state.audio_dma.AudioDMAControl.Enable;
state.audio_dma.AudioDMAControl.Hex = val; 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 // Audio DMA blocks remaining is invalid to write to, and requires logic on
// the read side. // the read side.
mmio->Register(base | AUDIO_DMA_BLOCKS_LEFT, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | AUDIO_DMA_BLOCKS_LEFT,
MMIO::ComplexRead<u16>([](Core::System& system, u32) {
// remaining_blocks_count is zero-based. DreamMix World Fighters will hang if it // remaining_blocks_count is zero-based. DreamMix World Fighters will hang if it
// never reaches zero. // never reaches zero.
auto& state = Core::System::GetInstance().GetDSPState().GetData(); auto& state = system.GetDSPState().GetData();
return (state.audio_dma.remaining_blocks_count > 0 ? return (state.audio_dma.remaining_blocks_count > 0 ?
state.audio_dma.remaining_blocks_count - 1 : state.audio_dma.remaining_blocks_count - 1 :
0); 0);

View File

@ -640,8 +640,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii)
{ {
auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData();
mmio->Register(base | DI_STATUS_REGISTER, MMIO::DirectRead<u32>(&state.DISR.Hex), mmio->Register(base | DI_STATUS_REGISTER, MMIO::DirectRead<u32>(&state.DISR.Hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); auto& state = system.GetDVDInterfaceState().GetData();
const UDISR tmp_status_reg(val); const UDISR tmp_status_reg(val);
state.DISR.DEINTMASK = tmp_status_reg.DEINTMASK.Value(); 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<u32>(&state.DICVR.Hex), mmio->Register(base | DI_COVER_REGISTER, MMIO::DirectRead<u32>(&state.DICVR.Hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); auto& state = system.GetDVDInterfaceState().GetData();
const UDICVR tmp_cover_reg(val); const UDICVR tmp_cover_reg(val);
state.DICVR.CVRINTMASK = tmp_cover_reg.CVRINTMASK.Value(); 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<u32>(&state.DILENGTH), mmio->Register(base | DI_DMA_LENGTH_REGISTER, MMIO::DirectRead<u32>(&state.DILENGTH),
MMIO::DirectWrite<u32>(&state.DILENGTH, ~0x1F)); MMIO::DirectWrite<u32>(&state.DILENGTH, ~0x1F));
mmio->Register(base | DI_DMA_CONTROL_REGISTER, MMIO::DirectRead<u32>(&state.DICR.Hex), mmio->Register(base | DI_DMA_CONTROL_REGISTER, MMIO::DirectRead<u32>(&state.DICR.Hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetDVDInterfaceState().GetData(); auto& state = system.GetDVDInterfaceState().GetData();
state.DICR.Hex = val & 7; state.DICR.Hex = val & 7;
if (state.DICR.TSTART) if (state.DICR.TSTART)
{ {

View File

@ -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 | // 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 +. // to select a register address, instead we need to use +.
mmio->Register(base + EXI_STATUS, MMIO::ComplexRead<u32>([this](u32) { mmio->Register(base + EXI_STATUS, MMIO::ComplexRead<u32>([this](Core::System&, u32) {
// check if external device is present // check if external device is present
// pretty sure it is memcard only, not entirely sure // pretty sure it is memcard only, not entirely sure
if (m_channel_id == 2) if (m_channel_id == 2)
@ -61,7 +61,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
return m_status.Hex; return m_status.Hex;
}), }),
MMIO::ComplexWrite<u32>([this](u32, u32 val) { MMIO::ComplexWrite<u32>([this](Core::System&, u32, u32 val) {
UEXI_STATUS new_status(val); UEXI_STATUS new_status(val);
m_status.EXIINTMASK = new_status.EXIINTMASK; 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<u32>(&m_dma_length), mmio->Register(base + EXI_DMA_LENGTH, MMIO::DirectRead<u32>(&m_dma_length),
MMIO::DirectWrite<u32>(&m_dma_length)); MMIO::DirectWrite<u32>(&m_dma_length));
mmio->Register(base + EXI_DMA_CONTROL, MMIO::DirectRead<u32>(&m_control.Hex), mmio->Register(base + EXI_DMA_CONTROL, MMIO::DirectRead<u32>(&m_control.Hex),
MMIO::ComplexWrite<u32>([this](u32, u32 val) { MMIO::ComplexWrite<u32>([this](Core::System&, u32, u32 val) {
m_control.Hex = val; m_control.Hex = val;
if (m_control.TSTART) if (m_control.TSTART)

View File

@ -112,12 +112,12 @@ template <typename T>
class ComplexHandlingMethod : public ReadHandlingMethod<T>, public WriteHandlingMethod<T> class ComplexHandlingMethod : public ReadHandlingMethod<T>, public WriteHandlingMethod<T>
{ {
public: public:
explicit ComplexHandlingMethod(std::function<T(u32)> read_lambda) explicit ComplexHandlingMethod(std::function<T(Core::System&, u32)> read_lambda)
: read_lambda_(read_lambda), write_lambda_(InvalidWriteLambda()) : read_lambda_(read_lambda), write_lambda_(InvalidWriteLambda())
{ {
} }
explicit ComplexHandlingMethod(std::function<void(u32, T)> write_lambda) explicit ComplexHandlingMethod(std::function<void(Core::System&, u32, T)> write_lambda)
: read_lambda_(InvalidReadLambda()), write_lambda_(write_lambda) : read_lambda_(InvalidReadLambda()), write_lambda_(write_lambda)
{ {
} }
@ -134,9 +134,9 @@ public:
} }
private: private:
std::function<T(u32)> InvalidReadLambda() const std::function<T(Core::System&, u32)> InvalidReadLambda() const
{ {
return [](u32) { return [](Core::System&, u32) {
DEBUG_ASSERT_MSG(MEMMAP, 0, DEBUG_ASSERT_MSG(MEMMAP, 0,
"Called the read lambda on a write " "Called the read lambda on a write "
"complex handler."); "complex handler.");
@ -144,25 +144,25 @@ private:
}; };
} }
std::function<void(u32, T)> InvalidWriteLambda() const std::function<void(Core::System&, u32, T)> InvalidWriteLambda() const
{ {
return [](u32, T) { return [](Core::System&, u32, T) {
DEBUG_ASSERT_MSG(MEMMAP, 0, DEBUG_ASSERT_MSG(MEMMAP, 0,
"Called the write lambda on a read " "Called the write lambda on a read "
"complex handler."); "complex handler.");
}; };
} }
std::function<T(u32)> read_lambda_; std::function<T(Core::System&, u32)> read_lambda_;
std::function<void(u32, T)> write_lambda_; std::function<void(Core::System&, u32, T)> write_lambda_;
}; };
template <typename T> template <typename T>
ReadHandlingMethod<T>* ComplexRead(std::function<T(u32)> lambda) ReadHandlingMethod<T>* ComplexRead(std::function<T(Core::System&, u32)> lambda)
{ {
return new ComplexHandlingMethod<T>(lambda); return new ComplexHandlingMethod<T>(lambda);
} }
template <typename T> template <typename T>
WriteHandlingMethod<T>* ComplexWrite(std::function<void(u32, T)> lambda) WriteHandlingMethod<T>* ComplexWrite(std::function<void(Core::System&, u32, T)> lambda)
{ {
return new ComplexHandlingMethod<T>(lambda); return new ComplexHandlingMethod<T>(lambda);
} }
@ -172,7 +172,7 @@ WriteHandlingMethod<T>* ComplexWrite(std::function<void(u32, T)> lambda)
template <typename T> template <typename T>
ReadHandlingMethod<T>* InvalidRead() ReadHandlingMethod<T>* InvalidRead()
{ {
return ComplexRead<T>([](u32 addr) { return ComplexRead<T>([](Core::System&, u32 addr) {
ERROR_LOG_FMT(MEMMAP, "Trying to read {} bits from an invalid MMIO (addr={:08x})", ERROR_LOG_FMT(MEMMAP, "Trying to read {} bits from an invalid MMIO (addr={:08x})",
8 * sizeof(T), addr); 8 * sizeof(T), addr);
return -1; return -1;
@ -181,7 +181,7 @@ ReadHandlingMethod<T>* InvalidRead()
template <typename T> template <typename T>
WriteHandlingMethod<T>* InvalidWrite() WriteHandlingMethod<T>* InvalidWrite()
{ {
return ComplexWrite<T>([](u32 addr, T val) { return ComplexWrite<T>([](Core::System&, u32 addr, T val) {
ERROR_LOG_FMT(MEMMAP, "Trying to write {} bits to an invalid MMIO (addr={:08x}, val={:08x})", ERROR_LOG_FMT(MEMMAP, "Trying to write {} bits to an invalid MMIO (addr={:08x}, val={:08x})",
8 * sizeof(T), addr, val); 8 * sizeof(T), addr, val);
}); });
@ -229,8 +229,9 @@ ReadHandlingMethod<T>* ReadToSmaller(Mapping* mmio, u32 high_part_addr, u32 low_
ReadHandler<ST>* low_part = &mmio->GetHandlerForRead<ST>(low_part_addr); ReadHandler<ST>* low_part = &mmio->GetHandlerForRead<ST>(low_part_addr);
// TODO(delroth): optimize // TODO(delroth): optimize
return ComplexRead<T>([=](u32 addr) { return ComplexRead<T>([=](Core::System& system, u32 addr) {
return ((T)high_part->Read(high_part_addr) << (8 * sizeof(ST))) | low_part->Read(low_part_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<T>* WriteToSmaller(Mapping* mmio, u32 high_part_addr, u32 lo
WriteHandler<ST>* low_part = &mmio->GetHandlerForWrite<ST>(low_part_addr); WriteHandler<ST>* low_part = &mmio->GetHandlerForWrite<ST>(low_part_addr);
// TODO(delroth): optimize // TODO(delroth): optimize
return ComplexWrite<T>([=](u32 addr, T val) { return ComplexWrite<T>([=](Core::System& system, u32 addr, T val) {
high_part->Write(high_part_addr, val >> (8 * sizeof(ST))); high_part->Write(system, high_part_addr, val >> (8 * sizeof(ST)));
low_part->Write(low_part_addr, (ST)val); low_part->Write(system, low_part_addr, (ST)val);
}); });
} }
@ -257,8 +258,9 @@ ReadHandlingMethod<T>* ReadToLarger(Mapping* mmio, u32 larger_addr, u32 shift)
ReadHandler<LT>* large = &mmio->GetHandlerForRead<LT>(larger_addr); ReadHandler<LT>* large = &mmio->GetHandlerForRead<LT>(larger_addr);
// TODO(delroth): optimize // TODO(delroth): optimize
return ComplexRead<T>( return ComplexRead<T>([large, shift](Core::System& system, u32 addr) {
[large, shift](u32 addr) { return large->Read(addr & ~(sizeof(LT) - 1)) >> shift; }); return large->Read(system, addr & ~(sizeof(LT) - 1)) >> shift;
});
} }
// Inplementation of the ReadHandler and WriteHandler class. There is a lot of // Inplementation of the ReadHandler and WriteHandler class. There is a lot of
@ -290,7 +292,7 @@ void ReadHandler<T>::Visit(ReadHandlingMethodVisitor<T>& visitor)
} }
template <typename T> template <typename T>
T ReadHandler<T>::Read(u32 addr) T ReadHandler<T>::Read(Core::System& system, u32 addr)
{ {
// Check if the handler has already been initialized. For real // Check if the handler has already been initialized. For real
// handlers, this will always be the case, so this branch should be // handlers, this will always be the case, so this branch should be
@ -298,7 +300,7 @@ T ReadHandler<T>::Read(u32 addr)
if (!m_Method) if (!m_Method)
InitializeInvalid(); InitializeInvalid();
return m_ReadFunc(addr); return m_ReadFunc(system, addr);
} }
template <typename T> template <typename T>
@ -310,19 +312,22 @@ void ReadHandler<T>::ResetMethod(ReadHandlingMethod<T>* method)
{ {
virtual ~FuncCreatorVisitor() = default; virtual ~FuncCreatorVisitor() = default;
std::function<T(u32)> ret; std::function<T(Core::System&, u32)> ret;
void VisitConstant(T value) override 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 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<T(u32)>* lambda) override { ret = *lambda; } void VisitComplex(const std::function<T(Core::System&, u32)>* lambda) override
{
ret = *lambda;
}
}; };
FuncCreatorVisitor v; FuncCreatorVisitor v;
@ -362,7 +367,7 @@ void WriteHandler<T>::Visit(WriteHandlingMethodVisitor<T>& visitor)
} }
template <typename T> template <typename T>
void WriteHandler<T>::Write(u32 addr, T val) void WriteHandler<T>::Write(Core::System& system, u32 addr, T val)
{ {
// Check if the handler has already been initialized. For real // Check if the handler has already been initialized. For real
// handlers, this will always be the case, so this branch should be // handlers, this will always be the case, so this branch should be
@ -370,7 +375,7 @@ void WriteHandler<T>::Write(u32 addr, T val)
if (!m_Method) if (!m_Method)
InitializeInvalid(); InitializeInvalid();
m_WriteFunc(addr, val); m_WriteFunc(system, addr, val);
} }
template <typename T> template <typename T>
@ -382,19 +387,22 @@ void WriteHandler<T>::ResetMethod(WriteHandlingMethod<T>* method)
{ {
virtual ~FuncCreatorVisitor() = default; virtual ~FuncCreatorVisitor() = default;
std::function<void(u32, T)> ret; std::function<void(Core::System&, u32, T)> ret;
void VisitNop() override void VisitNop() override
{ {
ret = [](u32, T) {}; ret = [](Core::System&, u32, T) {};
} }
void VisitDirect(T* ptr, u32 mask) override 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<void(u32, T)>* lambda) override { ret = *lambda; } void VisitComplex(const std::function<void(Core::System&, u32, T)>* lambda) override
{
ret = *lambda;
}
}; };
FuncCreatorVisitor v; FuncCreatorVisitor v;

View File

@ -15,6 +15,7 @@
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/HW/GPFifo.h" #include "Core/HW/GPFifo.h"
#include "Core/HW/MMIOHandlers.h" #include "Core/HW/MMIOHandlers.h"
#include "Core/System.h"
namespace MMIO namespace MMIO
{ {
@ -132,13 +133,13 @@ public:
template <typename Unit> template <typename Unit>
Unit Read(u32 addr) Unit Read(u32 addr)
{ {
return GetHandlerForRead<Unit>(addr).Read(addr); return GetHandlerForRead<Unit>(addr).Read(Core::System::GetInstance(), addr);
} }
template <typename Unit> template <typename Unit>
void Write(u32 addr, Unit val) void Write(u32 addr, Unit val)
{ {
GetHandlerForWrite<Unit>(addr).Write(addr, val); GetHandlerForWrite<Unit>(addr).Write(Core::System::GetInstance(), addr, val);
} }
// Handlers access interface. // Handlers access interface.

View File

@ -18,6 +18,10 @@
// u8/u16/u32 with the same code while providing type safety: it is impossible // 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. // to mix code from these types, and the type system enforces it.
namespace Core
{
class System;
}
namespace MMIO namespace MMIO
{ {
class Mapping; class Mapping;
@ -51,9 +55,9 @@ WriteHandlingMethod<T>* DirectWrite(T* addr, u32 mask = 0xFFFFFFFF);
// to directly provide a function that will be called when a read/write needs // to directly provide a function that will be called when a read/write needs
// to be done. // to be done.
template <typename T> template <typename T>
ReadHandlingMethod<T>* ComplexRead(std::function<T(u32)>); ReadHandlingMethod<T>* ComplexRead(std::function<T(Core::System&, u32)>);
template <typename T> template <typename T>
WriteHandlingMethod<T>* ComplexWrite(std::function<void(u32, T)>); WriteHandlingMethod<T>* ComplexWrite(std::function<void(Core::System&, u32, T)>);
// Invalid: log an error and return -1 in case of a read. These are the default // Invalid: log an error and return -1 in case of a read. These are the default
// handlers set for all MMIO types. // handlers set for all MMIO types.
@ -97,7 +101,7 @@ class ReadHandlingMethodVisitor
public: public:
virtual void VisitConstant(T value) = 0; virtual void VisitConstant(T value) = 0;
virtual void VisitDirect(const T* addr, u32 mask) = 0; virtual void VisitDirect(const T* addr, u32 mask) = 0;
virtual void VisitComplex(const std::function<T(u32)>* lambda) = 0; virtual void VisitComplex(const std::function<T(Core::System&, u32)>* lambda) = 0;
}; };
template <typename T> template <typename T>
class WriteHandlingMethodVisitor class WriteHandlingMethodVisitor
@ -105,7 +109,7 @@ class WriteHandlingMethodVisitor
public: public:
virtual void VisitNop() = 0; virtual void VisitNop() = 0;
virtual void VisitDirect(T* addr, u32 mask) = 0; virtual void VisitDirect(T* addr, u32 mask) = 0;
virtual void VisitComplex(const std::function<void(u32, T)>* lambda) = 0; virtual void VisitComplex(const std::function<void(Core::System&, u32, T)>* lambda) = 0;
}; };
// These classes are INTERNAL. Do not use outside of the MMIO implementation // These classes are INTERNAL. Do not use outside of the MMIO implementation
@ -126,7 +130,7 @@ public:
// Entry point for read handling method visitors. // Entry point for read handling method visitors.
void Visit(ReadHandlingMethodVisitor<T>& visitor); void Visit(ReadHandlingMethodVisitor<T>& visitor);
T Read(u32 addr); T Read(Core::System& system, u32 addr);
// Internal method called when changing the internal method object. Its // 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. // main role is to make sure the read function is updated at the same time.
@ -137,7 +141,7 @@ private:
// useless initialization of thousands of unused handler objects. // useless initialization of thousands of unused handler objects.
void InitializeInvalid(); void InitializeInvalid();
std::unique_ptr<ReadHandlingMethod<T>> m_Method; std::unique_ptr<ReadHandlingMethod<T>> m_Method;
std::function<T(u32)> m_ReadFunc; std::function<T(Core::System&, u32)> m_ReadFunc;
}; };
template <typename T> template <typename T>
class WriteHandler class WriteHandler
@ -153,7 +157,7 @@ public:
// Entry point for write handling method visitors. // Entry point for write handling method visitors.
void Visit(WriteHandlingMethodVisitor<T>& visitor); void Visit(WriteHandlingMethodVisitor<T>& 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 // Internal method called when changing the internal method object. Its
// main role is to make sure the write function is updated at the same // main role is to make sure the write function is updated at the same
@ -165,7 +169,7 @@ private:
// useless initialization of thousands of unused handler objects. // useless initialization of thousands of unused handler objects.
void InitializeInvalid(); void InitializeInvalid();
std::unique_ptr<WriteHandlingMethod<T>> m_Method; std::unique_ptr<WriteHandlingMethod<T>> m_Method;
std::function<void(u32, T)> m_WriteFunc; std::function<void(Core::System&, u32, T)> m_WriteFunc;
}; };
// Boilerplate boilerplate boilerplate. // Boilerplate boilerplate boilerplate.
@ -182,8 +186,10 @@ private:
MaybeExtern template WriteHandlingMethod<T>* Nop<T>(); \ MaybeExtern template WriteHandlingMethod<T>* Nop<T>(); \
MaybeExtern template ReadHandlingMethod<T>* DirectRead(const T* addr, u32 mask); \ MaybeExtern template ReadHandlingMethod<T>* DirectRead(const T* addr, u32 mask); \
MaybeExtern template WriteHandlingMethod<T>* DirectWrite(T* addr, u32 mask); \ MaybeExtern template WriteHandlingMethod<T>* DirectWrite(T* addr, u32 mask); \
MaybeExtern template ReadHandlingMethod<T>* ComplexRead<T>(std::function<T(u32)>); \ MaybeExtern template ReadHandlingMethod<T>* ComplexRead<T>( \
MaybeExtern template WriteHandlingMethod<T>* ComplexWrite<T>(std::function<void(u32, T)>); \ std::function<T(Core::System&, u32)>); \
MaybeExtern template WriteHandlingMethod<T>* ComplexWrite<T>( \
std::function<void(Core::System&, u32, T)>); \
MaybeExtern template ReadHandlingMethod<T>* InvalidRead<T>(); \ MaybeExtern template ReadHandlingMethod<T>* InvalidRead<T>(); \
MaybeExtern template WriteHandlingMethod<T>* InvalidWrite<T>(); \ MaybeExtern template WriteHandlingMethod<T>* InvalidWrite<T>(); \
MaybeExtern template class ReadHandler<T>; \ MaybeExtern template class ReadHandler<T>; \

View File

@ -82,13 +82,13 @@ void Init()
void RegisterMMIO(MMIO::Mapping* mmio, u32 base) void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{ {
mmio->Register(base | PI_INTERRUPT_CAUSE, MMIO::DirectRead<u32>(&m_InterruptCause), mmio->Register(base | PI_INTERRUPT_CAUSE, MMIO::DirectRead<u32>(&m_InterruptCause),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
m_InterruptCause &= ~val; m_InterruptCause &= ~val;
UpdateException(); UpdateException();
})); }));
mmio->Register(base | PI_INTERRUPT_MASK, MMIO::DirectRead<u32>(&m_InterruptMask), mmio->Register(base | PI_INTERRUPT_MASK, MMIO::DirectRead<u32>(&m_InterruptMask),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
m_InterruptMask = val; m_InterruptMask = val;
UpdateException(); UpdateException();
})); }));
@ -103,7 +103,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::DirectWrite<u32>(&Fifo_CPUWritePointer, 0xFFFFFFE0)); MMIO::DirectWrite<u32>(&Fifo_CPUWritePointer, 0xFFFFFFE0));
mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(), mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
// Used by GXAbortFrame // Used by GXAbortFrame
INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val); INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val);
if ((val & 1) != 0) if ((val & 1) != 0)
@ -125,11 +125,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
})); }));
mmio->Register(base | PI_RESET_CODE, MMIO::ComplexRead<u32>([](u32) { mmio->Register(base | PI_RESET_CODE, MMIO::ComplexRead<u32>([](Core::System&, u32) {
DEBUG_LOG_FMT(PROCESSORINTERFACE, "Read PI_RESET_CODE: {:08x}", m_ResetCode); DEBUG_LOG_FMT(PROCESSORINTERFACE, "Read PI_RESET_CODE: {:08x}", m_ResetCode);
return m_ResetCode; return m_ResetCode;
}), }),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
m_ResetCode = val; m_ResetCode = val;
INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_RESET_CODE: {:08x}", m_ResetCode); INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_RESET_CODE: {:08x}", m_ResetCode);
if (!SConfig::GetInstance().bWii && ~m_ResetCode & 0x4) if (!SConfig::GetInstance().bWii && ~m_ResetCode & 0x4)

View File

@ -490,14 +490,14 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{ {
const u32 address = base | static_cast<u32>(io_buffer_base + i); const u32 address = base | static_cast<u32>(io_buffer_base + i);
mmio->Register(address, MMIO::ComplexRead<u32>([i](u32) { mmio->Register(address, MMIO::ComplexRead<u32>([i](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
u32 val; u32 val;
std::memcpy(&val, &state.si_buffer[i], sizeof(val)); std::memcpy(&val, &state.si_buffer[i], sizeof(val));
return Common::swap32(val); return Common::swap32(val);
}), }),
MMIO::ComplexWrite<u32>([i](u32, u32 val) { MMIO::ComplexWrite<u32>([i](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
val = Common::swap32(val); val = Common::swap32(val);
std::memcpy(&state.si_buffer[i], &val, sizeof(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<u32>(io_buffer_base + i); const u32 address = base | static_cast<u32>(io_buffer_base + i);
mmio->Register(address, MMIO::ComplexRead<u16>([i](u32) { mmio->Register(address, MMIO::ComplexRead<u16>([i](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
u16 val; u16 val;
std::memcpy(&val, &state.si_buffer[i], sizeof(val)); std::memcpy(&val, &state.si_buffer[i], sizeof(val));
return Common::swap16(val); return Common::swap16(val);
}), }),
MMIO::ComplexWrite<u16>([i](u32, u16 val) { MMIO::ComplexWrite<u16>([i](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
val = Common::swap16(val); val = Common::swap16(val);
std::memcpy(&state.si_buffer[i], &val, sizeof(val)); std::memcpy(&state.si_buffer[i], &val, sizeof(val));
})); }));
@ -533,16 +533,16 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::DirectRead<u32>(&state.channel[i].out.hex), MMIO::DirectRead<u32>(&state.channel[i].out.hex),
MMIO::DirectWrite<u32>(&state.channel[i].out.hex)); MMIO::DirectWrite<u32>(&state.channel[i].out.hex));
mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i), mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i),
MMIO::ComplexRead<u32>([i, rdst_bit](u32) { MMIO::ComplexRead<u32>([i, rdst_bit](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
state.status_reg.hex &= ~(1U << rdst_bit); state.status_reg.hex &= ~(1U << rdst_bit);
UpdateInterrupts(); UpdateInterrupts();
return state.channel[i].in_hi.hex; return state.channel[i].in_hi.hex;
}), }),
MMIO::DirectWrite<u32>(&state.channel[i].in_hi.hex)); MMIO::DirectWrite<u32>(&state.channel[i].in_hi.hex));
mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i), mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i),
MMIO::ComplexRead<u32>([i, rdst_bit](u32) { MMIO::ComplexRead<u32>([i, rdst_bit](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
state.status_reg.hex &= ~(1U << rdst_bit); state.status_reg.hex &= ~(1U << rdst_bit);
UpdateInterrupts(); UpdateInterrupts();
return state.channel[i].in_lo.hex; return state.channel[i].in_lo.hex;
@ -554,8 +554,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::DirectWrite<u32>(&state.poll.hex)); MMIO::DirectWrite<u32>(&state.poll.hex));
mmio->Register(base | SI_COM_CSR, MMIO::DirectRead<u32>(&state.com_csr.hex), mmio->Register(base | SI_COM_CSR, MMIO::DirectRead<u32>(&state.com_csr.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& system = Core::System::GetInstance();
auto& state = system.GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
const USIComCSR tmp_com_csr(val); 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<u32>(&state.status_reg.hex), mmio->Register(base | SI_STATUS_REG, MMIO::DirectRead<u32>(&state.status_reg.hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state = Core::System::GetInstance().GetSerialInterfaceState().GetData(); auto& state = system.GetSerialInterfaceState().GetData();
const USIStatusReg tmp_status(val); const USIStatusReg tmp_status(val);
// clear bits ( if (tmp.bit) SISR.bit=0 ) // clear bits ( if (tmp.bit) SISR.bit=0 )

View File

@ -266,7 +266,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
for (auto& mapped_var : update_params_on_read_vars) for (auto& mapped_var : update_params_on_read_vars)
{ {
mmio->Register(base | mapped_var.addr, MMIO::DirectRead<u16>(mapped_var.ptr), mmio->Register(base | mapped_var.addr, MMIO::DirectRead<u16>(mapped_var.ptr),
MMIO::ComplexWrite<u16>([mapped_var](u32, u16 val) { MMIO::ComplexWrite<u16>([mapped_var](Core::System&, u32, u16 val) {
*mapped_var.ptr = val; *mapped_var.ptr = val;
UpdateParameters(); UpdateParameters();
})); }));
@ -274,29 +274,29 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// XFB related MMIOs that require special handling on writes. // XFB related MMIOs that require special handling on writes.
mmio->Register(base | VI_FB_LEFT_TOP_HI, MMIO::DirectRead<u16>(&state.xfb_info_top.Hi), mmio->Register(base | VI_FB_LEFT_TOP_HI, MMIO::DirectRead<u16>(&state.xfb_info_top.Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.xfb_info_top.Hi = val; state.xfb_info_top.Hi = val;
if (state.xfb_info_top.CLRPOFF) if (state.xfb_info_top.CLRPOFF)
state.xfb_info_top.POFF = 0; state.xfb_info_top.POFF = 0;
})); }));
mmio->Register(base | VI_FB_LEFT_BOTTOM_HI, MMIO::DirectRead<u16>(&state.xfb_info_bottom.Hi), mmio->Register(base | VI_FB_LEFT_BOTTOM_HI, MMIO::DirectRead<u16>(&state.xfb_info_bottom.Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.xfb_info_bottom.Hi = val; state.xfb_info_bottom.Hi = val;
if (state.xfb_info_bottom.CLRPOFF) if (state.xfb_info_bottom.CLRPOFF)
state.xfb_info_bottom.POFF = 0; state.xfb_info_bottom.POFF = 0;
})); }));
mmio->Register(base | VI_FB_RIGHT_TOP_HI, MMIO::DirectRead<u16>(&state.xfb_3d_info_top.Hi), mmio->Register(base | VI_FB_RIGHT_TOP_HI, MMIO::DirectRead<u16>(&state.xfb_3d_info_top.Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.xfb_3d_info_top.Hi = val; state.xfb_3d_info_top.Hi = val;
if (state.xfb_3d_info_top.CLRPOFF) if (state.xfb_3d_info_top.CLRPOFF)
state.xfb_3d_info_top.POFF = 0; state.xfb_3d_info_top.POFF = 0;
})); }));
mmio->Register(base | VI_FB_RIGHT_BOTTOM_HI, MMIO::DirectRead<u16>(&state.xfb_3d_info_bottom.Hi), mmio->Register(base | VI_FB_RIGHT_BOTTOM_HI, MMIO::DirectRead<u16>(&state.xfb_3d_info_bottom.Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.xfb_3d_info_bottom.Hi = val; state.xfb_3d_info_bottom.Hi = val;
if (state.xfb_3d_info_bottom.CLRPOFF) if (state.xfb_3d_info_bottom.CLRPOFF)
state.xfb_3d_info_bottom.POFF = 0; 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. // MMIOs with unimplemented writes that trigger warnings.
mmio->Register( mmio->Register(
base | VI_VERTICAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](u32) { base | VI_VERTICAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
return 1 + (state.half_line_count) / 2; return 1 + (state.half_line_count) / 2;
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
WARN_LOG_FMT( WARN_LOG_FMT(
VIDEOINTERFACE, VIDEOINTERFACE,
"Changing vertical beam position to {:#06x} - not documented or implemented yet", val); "Changing vertical beam position to {:#06x} - not documented or implemented yet", val);
})); }));
mmio->Register( mmio->Register(
base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](u32) { base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
u16 value = static_cast<u16>( u16 value = static_cast<u16>(
1 + state.h_timing_0.HLW * (CoreTiming::GetTicks() - state.ticks_last_line_start) / 1 + state.h_timing_0.HLW * (CoreTiming::GetTicks() - state.ticks_last_line_start) /
(GetTicksPerHalfLine())); (GetTicksPerHalfLine()));
return std::clamp<u16>(value, 1, state.h_timing_0.HLW * 2); return std::clamp<u16>(value, 1, state.h_timing_0.HLW * 2);
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
WARN_LOG_FMT( WARN_LOG_FMT(
VIDEOINTERFACE, VIDEOINTERFACE,
"Changing horizontal beam position to {:#06x} - not documented or implemented yet", "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 // The following MMIOs are interrupts related and update interrupt status
// on writes. // on writes.
mmio->Register(base | VI_PRERETRACE_HI, MMIO::DirectRead<u16>(&state.interrupt_register[0].Hi), mmio->Register(base | VI_PRERETRACE_HI, MMIO::DirectRead<u16>(&state.interrupt_register[0].Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.interrupt_register[0].Hi = val; state.interrupt_register[0].Hi = val;
UpdateInterrupts(); UpdateInterrupts();
})); }));
mmio->Register(base | VI_POSTRETRACE_HI, MMIO::DirectRead<u16>(&state.interrupt_register[1].Hi), mmio->Register(base | VI_POSTRETRACE_HI, MMIO::DirectRead<u16>(&state.interrupt_register[1].Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.interrupt_register[1].Hi = val; state.interrupt_register[1].Hi = val;
UpdateInterrupts(); UpdateInterrupts();
})); }));
mmio->Register(base | VI_DISPLAY_INTERRUPT_2_HI, mmio->Register(base | VI_DISPLAY_INTERRUPT_2_HI,
MMIO::DirectRead<u16>(&state.interrupt_register[2].Hi), MMIO::DirectRead<u16>(&state.interrupt_register[2].Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.interrupt_register[2].Hi = val; state.interrupt_register[2].Hi = val;
UpdateInterrupts(); UpdateInterrupts();
})); }));
mmio->Register(base | VI_DISPLAY_INTERRUPT_3_HI, mmio->Register(base | VI_DISPLAY_INTERRUPT_3_HI,
MMIO::DirectRead<u16>(&state.interrupt_register[3].Hi), MMIO::DirectRead<u16>(&state.interrupt_register[3].Hi),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.interrupt_register[3].Hi = val; state.interrupt_register[3].Hi = val;
UpdateInterrupts(); UpdateInterrupts();
})); }));
// Unknown anti-aliasing related MMIO register: puts a warning on log and // Unknown anti-aliasing related MMIO register: puts a warning on log and
// needs to shift/mask when reading/writing. // needs to shift/mask when reading/writing.
mmio->Register(base | VI_UNK_AA_REG_HI, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | VI_UNK_AA_REG_HI, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
return state.unknown_aa_register >> 16; return state.unknown_aa_register >> 16;
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.unknown_aa_register = state.unknown_aa_register =
(state.unknown_aa_register & 0x0000FFFF) | ((u32)val << 16); (state.unknown_aa_register & 0x0000FFFF) | ((u32)val << 16);
WARN_LOG_FMT(VIDEOINTERFACE, "Writing to the unknown AA register (hi)"); WARN_LOG_FMT(VIDEOINTERFACE, "Writing to the unknown AA register (hi)");
})); }));
mmio->Register(base | VI_UNK_AA_REG_LO, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | VI_UNK_AA_REG_LO, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
return state.unknown_aa_register & 0xFFFF; return state.unknown_aa_register & 0xFFFF;
}), }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
state.unknown_aa_register = (state.unknown_aa_register & 0xFFFF0000) | val; state.unknown_aa_register = (state.unknown_aa_register & 0xFFFF0000) | val;
WARN_LOG_FMT(VIDEOINTERFACE, "Writing to the unknown AA register (lo)"); 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. // processing needs to be done if a reset is requested.
mmio->Register(base | VI_CONTROL_REGISTER, mmio->Register(base | VI_CONTROL_REGISTER,
MMIO::DirectRead<u16>(&state.display_control_register.Hex), MMIO::DirectRead<u16>(&state.display_control_register.Hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
auto& state = Core::System::GetInstance().GetVideoInterfaceState().GetData(); auto& state = system.GetVideoInterfaceState().GetData();
UVIDisplayControlRegister tmpConfig(val); UVIDisplayControlRegister tmpConfig(val);
state.display_control_register.ENB = tmpConfig.ENB; state.display_control_register.ENB = tmpConfig.ENB;

View File

@ -174,8 +174,9 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{ {
mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead<u32>(), MMIO::DirectWrite<u32>(&ppc_msg)); mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead<u32>(), MMIO::DirectWrite<u32>(&ppc_msg));
mmio->Register(base | IPC_PPCCTRL, MMIO::ComplexRead<u32>([](u32) { return ctrl.ppc(); }), mmio->Register(base | IPC_PPCCTRL,
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexRead<u32>([](Core::System&, u32) { return ctrl.ppc(); }),
MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
ctrl.ppc(val); ctrl.ppc(val);
// The IPC interrupt is triggered when IY1/IY2 is set and // The IPC interrupt is triggered when IY1/IY2 is set and
// Y1/Y2 is written to -- even when this results in clearing the bit. // 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<u32>(&arm_msg), MMIO::InvalidWrite<u32>()); mmio->Register(base | IPC_ARMMSG, MMIO::DirectRead<u32>(&arm_msg), MMIO::InvalidWrite<u32>());
mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(), mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
ppc_irq_flags &= ~val; ppc_irq_flags &= ~val;
HLE::GetIOS()->UpdateIPC(); HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0); CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
})); }));
mmio->Register(base | PPC_IRQMASK, MMIO::InvalidRead<u32>(), mmio->Register(base | PPC_IRQMASK, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
ppc_irq_masks = val; ppc_irq_masks = val;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf? if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset(); Reset();
@ -206,7 +207,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
})); }));
mmio->Register(base | GPIOB_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex), mmio->Register(base | GPIOB_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
g_gpio_out.m_hex = g_gpio_out.m_hex =
(val & gpio_owner.m_hex) | (g_gpio_out.m_hex & ~gpio_owner.m_hex); (val & gpio_owner.m_hex) | (g_gpio_out.m_hex & ~gpio_owner.m_hex);
if (g_gpio_out[GPIO::DO_EJECT]) if (g_gpio_out[GPIO::DO_EJECT])
@ -218,10 +219,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// TODO: AVE, SLOT_LED // TODO: AVE, SLOT_LED
})); }));
mmio->Register(base | GPIOB_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex), mmio->Register(base | GPIOB_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
gpio_dir.m_hex = (val & gpio_owner.m_hex) | (gpio_dir.m_hex & ~gpio_owner.m_hex); 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>([](u32) { mmio->Register(base | GPIOB_IN, MMIO::ComplexRead<u32>([](Core::System&, u32) {
Common::Flags<GPIO> gpio_in; Common::Flags<GPIO> gpio_in;
gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside(); gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside();
return gpio_in.m_hex; 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 // go through the HW_GPIOB registers if the corresponding bit is set in the HW_GPIO_OWNER
// register. // register.
mmio->Register(base | GPIO_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex), mmio->Register(base | GPIO_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
g_gpio_out.m_hex = g_gpio_out.m_hex =
(g_gpio_out.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex); (g_gpio_out.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex);
if (g_gpio_out[GPIO::DO_EJECT]) if (g_gpio_out[GPIO::DO_EJECT])
@ -251,10 +252,10 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// TODO: AVE, SLOT_LED // TODO: AVE, SLOT_LED
})); }));
mmio->Register(base | GPIO_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex), mmio->Register(base | GPIO_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
gpio_dir.m_hex = (gpio_dir.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex); 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>([](u32) { mmio->Register(base | GPIO_IN, MMIO::ComplexRead<u32>([](Core::System&, u32) {
Common::Flags<GPIO> gpio_in; Common::Flags<GPIO> gpio_in;
gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside(); gpio_in[GPIO::SLOT_IN] = DVDInterface::IsDiscInside();
return gpio_in.m_hex; return gpio_in.m_hex;
@ -262,7 +263,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::Nop<u32>()); MMIO::Nop<u32>());
mmio->Register(base | HW_RESETS, MMIO::DirectRead<u32>(&resets), mmio->Register(base | HW_RESETS, MMIO::DirectRead<u32>(&resets),
MMIO::ComplexWrite<u32>([](u32, u32 val) { MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
// A reset occurs when the corresponding bit is cleared // A reset occurs when the corresponding bit is cleared
const bool di_reset_triggered = (resets & 0x400) && !(val & 0x400); const bool di_reset_triggered = (resets & 0x400) && !(val & 0x400);
resets = val; resets = val;

View File

@ -19,6 +19,7 @@
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
#include "Core/PowerPC/MMU.h" #include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
using namespace Gen; using namespace Gen;
@ -220,7 +221,7 @@ public:
{ {
LoadAddrMaskToReg(8 * sizeof(T), addr, mask); LoadAddrMaskToReg(8 * sizeof(T), addr, mask);
} }
void VisitComplex(const std::function<T(u32)>* lambda) override void VisitComplex(const std::function<T(Core::System&, u32)>* lambda) override
{ {
CallLambda(8 * sizeof(T), lambda); CallLambda(8 * sizeof(T), lambda);
} }
@ -269,10 +270,10 @@ private:
} }
} }
void CallLambda(int sbits, const std::function<T(u32)>* lambda) void CallLambda(int sbits, const std::function<T(Core::System&, u32)>* lambda)
{ {
m_code->ABI_PushRegistersAndAdjustStack(m_registers_in_use, 0); 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); m_code->ABI_PopRegistersAndAdjustStack(m_registers_in_use, 0);
MoveOpArgToReg(sbits, R(ABI_RETURN)); MoveOpArgToReg(sbits, R(ABI_RETURN));
} }

View File

@ -7,8 +7,8 @@
#include "Common/Common.h" #include "Common/Common.h"
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/System.h"
using namespace Arm64Gen; using namespace Arm64Gen;
@ -28,7 +28,7 @@ public:
// Do nothing // Do nothing
} }
void VisitDirect(T* addr, u32 mask) override { WriteRegToAddr(8 * sizeof(T), addr, mask); } void VisitDirect(T* addr, u32 mask) override { WriteRegToAddr(8 * sizeof(T), addr, mask); }
void VisitComplex(const std::function<void(u32, T)>* lambda) override void VisitComplex(const std::function<void(Core::System&, u32, T)>* lambda) override
{ {
CallLambda(8 * sizeof(T), lambda); CallLambda(8 * sizeof(T), lambda);
} }
@ -72,15 +72,15 @@ private:
} }
} }
void CallLambda(int sbits, const std::function<void(u32, T)>* lambda) void CallLambda(int sbits, const std::function<void(Core::System&, u32, T)>* lambda)
{ {
ARM64FloatEmitter float_emit(m_emit); ARM64FloatEmitter float_emit(m_emit);
m_emit->ABI_PushRegisters(m_gprs_in_use); m_emit->ABI_PushRegisters(m_gprs_in_use);
float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1); float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1);
m_emit->MOVP2R(ARM64Reg::X1, &Core::System::GetInstance());
m_emit->MOVI2R(ARM64Reg::W1, m_address); m_emit->MOVI2R(ARM64Reg::W2, m_address);
m_emit->MOV(ARM64Reg::W2, m_src_reg); m_emit->MOV(ARM64Reg::W3, m_src_reg);
m_emit->BLR(m_emit->ABI_SetupLambda(lambda)); m_emit->BLR(m_emit->ABI_SetupLambda(lambda));
float_emit.ABI_PopRegisters(m_fprs_in_use, ARM64Reg::X1); float_emit.ABI_PopRegisters(m_fprs_in_use, ARM64Reg::X1);
@ -110,7 +110,7 @@ public:
{ {
LoadAddrMaskToReg(8 * sizeof(T), addr, mask); LoadAddrMaskToReg(8 * sizeof(T), addr, mask);
} }
void VisitComplex(const std::function<T(u32)>* lambda) override void VisitComplex(const std::function<T(Core::System&, u32)>* lambda) override
{ {
CallLambda(8 * sizeof(T), lambda); CallLambda(8 * sizeof(T), lambda);
} }
@ -169,14 +169,14 @@ private:
} }
} }
void CallLambda(int sbits, const std::function<T(u32)>* lambda) void CallLambda(int sbits, const std::function<T(Core::System&, u32)>* lambda)
{ {
ARM64FloatEmitter float_emit(m_emit); ARM64FloatEmitter float_emit(m_emit);
m_emit->ABI_PushRegisters(m_gprs_in_use); m_emit->ABI_PushRegisters(m_gprs_in_use);
float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1); float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1);
m_emit->MOVP2R(ARM64Reg::X1, &Core::System::GetInstance());
m_emit->MOVI2R(ARM64Reg::W1, m_address); m_emit->MOVI2R(ARM64Reg::W2, m_address);
m_emit->BLR(m_emit->ABI_SetupLambda(lambda)); m_emit->BLR(m_emit->ABI_SetupLambda(lambda));
if (m_sign_extend) if (m_sign_extend)
m_emit->SBFM(m_dst_reg, ARM64Reg::W0, 0, sbits - 1); m_emit->SBFM(m_dst_reg, ARM64Reg::W0, 0, sbits - 1);

View File

@ -239,7 +239,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
} }
mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead<u16>([](Core::System&, u32) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
SetCpStatusRegister(); SetCpStatusRegister();
return m_CPStatusReg.Hex; return m_CPStatusReg.Hex;
@ -247,7 +247,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
mmio->Register(base | CTRL_REGISTER, MMIO::DirectRead<u16>(&m_CPCtrlReg.Hex), mmio->Register(base | CTRL_REGISTER, MMIO::DirectRead<u16>(&m_CPCtrlReg.Hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System&, u32, u16 val) {
UCPCtrlReg tmp(val); UCPCtrlReg tmp(val);
m_CPCtrlReg.Hex = tmp.Hex; m_CPCtrlReg.Hex = tmp.Hex;
SetCpControlRegister(); SetCpControlRegister();
@ -255,7 +255,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
})); }));
mmio->Register(base | CLEAR_REGISTER, MMIO::DirectRead<u16>(&m_CPClearReg.Hex), mmio->Register(base | CLEAR_REGISTER, MMIO::DirectRead<u16>(&m_CPClearReg.Hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System&, u32, u16 val) {
UCPClearReg tmp(val); UCPClearReg tmp(val);
m_CPClearReg.Hex = tmp.Hex; m_CPClearReg.Hex = tmp.Hex;
SetCpClearRegister(); SetCpClearRegister();
@ -265,9 +265,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | PERF_SELECT, MMIO::InvalidRead<u16>(), MMIO::Nop<u16>()); mmio->Register(base | PERF_SELECT, MMIO::InvalidRead<u16>(), MMIO::Nop<u16>());
// Some MMIOs have different handlers for single core vs. dual core mode. // Some MMIOs have different handlers for single core vs. dual core mode.
mmio->Register( const bool is_on_thread = IsOnThread();
base | FIFO_RW_DISTANCE_LO, MMIO::ReadHandlingMethod<u16>* fifo_rw_distance_lo_r;
IsOnThread() ? MMIO::ComplexRead<u16>([](u32) { if (is_on_thread)
{
fifo_rw_distance_lo_r = MMIO::ComplexRead<u16>([](Core::System&, u32) {
if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= if (fifo.CPWritePointer.load(std::memory_order_relaxed) >=
fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) fifo.SafeCPReadPointer.load(std::memory_order_relaxed))
{ {
@ -281,13 +283,20 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
fifo.CPWritePointer.load(std::memory_order_relaxed) - fifo.CPWritePointer.load(std::memory_order_relaxed) -
fifo.CPBase.load(std::memory_order_relaxed) + 32); fifo.CPBase.load(std::memory_order_relaxed) + 32);
} }
}) : });
MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance)), }
else
{
fifo_rw_distance_lo_r = MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance));
}
mmio->Register(base | FIFO_RW_DISTANCE_LO, fifo_rw_distance_lo_r,
MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance),
WMASK_LO_ALIGN_32BIT)); WMASK_LO_ALIGN_32BIT));
mmio->Register(base | FIFO_RW_DISTANCE_HI,
IsOnThread() ? MMIO::ReadHandlingMethod<u16>* fifo_rw_distance_hi_r;
MMIO::ComplexRead<u16>([](u32) { if (is_on_thread)
{
fifo_rw_distance_hi_r = MMIO::ComplexRead<u16>([](Core::System&, u32) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
if (fifo.CPWritePointer.load(std::memory_order_relaxed) >= if (fifo.CPWritePointer.load(std::memory_order_relaxed) >=
fifo.SafeCPReadPointer.load(std::memory_order_relaxed)) fifo.SafeCPReadPointer.load(std::memory_order_relaxed))
@ -304,40 +313,55 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
fifo.CPBase.load(std::memory_order_relaxed) + 32) >> fifo.CPBase.load(std::memory_order_relaxed) + 32) >>
16; 16;
} }
}) : });
MMIO::ComplexRead<u16>([](u32) { }
else
{
fifo_rw_distance_hi_r = MMIO::ComplexRead<u16>([](Core::System&, u32) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
return fifo.CPReadWriteDistance.load(std::memory_order_relaxed) >> 16; return fifo.CPReadWriteDistance.load(std::memory_order_relaxed) >> 16;
}), });
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) { }
mmio->Register(base | FIFO_RW_DISTANCE_HI, fifo_rw_distance_hi_r,
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT);
Fifo::RunGpu(); Fifo::RunGpu();
})); }));
mmio->Register( mmio->Register(
base | FIFO_READ_POINTER_LO, base | FIFO_READ_POINTER_LO,
IsOnThread() ? MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : is_on_thread ? MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) :
MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer)), MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer)),
MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT));
mmio->Register(base | FIFO_READ_POINTER_HI,
IsOnThread() ? MMIO::ComplexRead<u16>([](u32) { MMIO::ReadHandlingMethod<u16>* fifo_read_hi_r;
MMIO::WriteHandlingMethod<u16>* fifo_read_hi_w;
if (is_on_thread)
{
fifo_read_hi_r = MMIO::ComplexRead<u16>([](Core::System&, u32) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16; return fifo.SafeCPReadPointer.load(std::memory_order_relaxed) >> 16;
}) : });
MMIO::ComplexRead<u16>([](u32) { fifo_read_hi_w = MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) {
Fifo::SyncGPUForRegisterAccess();
return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16;
}),
IsOnThread() ? MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT);
fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed), fifo.SafeCPReadPointer.store(fifo.CPReadPointer.load(std::memory_order_relaxed),
std::memory_order_relaxed); std::memory_order_relaxed);
}) : });
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) { }
else
{
fifo_read_hi_r = MMIO::ComplexRead<u16>([](Core::System&, u32) {
Fifo::SyncGPUForRegisterAccess();
return fifo.CPReadPointer.load(std::memory_order_relaxed) >> 16;
});
fifo_read_hi_w = MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](Core::System&, u32, u16 val) {
Fifo::SyncGPUForRegisterAccess(); Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT);
})); });
}
mmio->Register(base | FIFO_READ_POINTER_HI, fifo_read_hi_r, fifo_read_hi_w);
} }
void GatherPipeBursted() void GatherPipeBursted()

View File

@ -242,11 +242,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}; };
for (auto& pq_reg : pq_regs) for (auto& pq_reg : pq_regs)
{ {
mmio->Register(base | pq_reg.addr, MMIO::ComplexRead<u16>([pq_reg](u32) { mmio->Register(base | pq_reg.addr, MMIO::ComplexRead<u16>([pq_reg](Core::System&, u32) {
return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) & 0xFFFF; return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) & 0xFFFF;
}), }),
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
mmio->Register(base | (pq_reg.addr + 2), MMIO::ComplexRead<u16>([pq_reg](u32) { mmio->Register(base | (pq_reg.addr + 2), MMIO::ComplexRead<u16>([pq_reg](Core::System&, u32) {
return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) >> 16; return g_video_backend->Video_GetQueryResult(pq_reg.pqtype) >> 16;
}), }),
MMIO::InvalidWrite<u16>()); MMIO::InvalidWrite<u16>());
@ -254,7 +254,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// Control register // Control register
mmio->Register(base | PE_CTRL_REGISTER, MMIO::DirectRead<u16>(&m_Control.hex), mmio->Register(base | PE_CTRL_REGISTER, MMIO::DirectRead<u16>(&m_Control.hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](Core::System&, u32, u16 val) {
UPECtrlReg tmpCtrl{.hex = val}; UPECtrlReg tmpCtrl{.hex = val};
if (tmpCtrl.pe_token) if (tmpCtrl.pe_token)
@ -278,7 +278,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// BBOX registers, readonly and need to update a flag. // BBOX registers, readonly and need to update a flag.
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
mmio->Register(base | (PE_BBOX_LEFT + 2 * i), MMIO::ComplexRead<u16>([i](u32) { mmio->Register(base | (PE_BBOX_LEFT + 2 * i), MMIO::ComplexRead<u16>([i](Core::System&, u32) {
g_renderer->BBoxDisable(); g_renderer->BBoxDisable();
return g_video_backend->Video_GetBoundingBox(i); return g_video_backend->Video_GetBoundingBox(i);
}), }),

View File

@ -121,12 +121,12 @@ TEST_F(MappingTest, ReadWriteComplex)
{ {
bool read_called = false, write_called = false; bool read_called = false, write_called = false;
m_mapping->Register(0x0C001234, MMIO::ComplexRead<u8>([&read_called](u32 addr) { m_mapping->Register(0x0C001234, MMIO::ComplexRead<u8>([&read_called](Core::System&, u32 addr) {
EXPECT_EQ(0x0C001234u, addr); EXPECT_EQ(0x0C001234u, addr);
read_called = true; read_called = true;
return 0x12; return 0x12;
}), }),
MMIO::ComplexWrite<u8>([&write_called](u32 addr, u8 val) { MMIO::ComplexWrite<u8>([&write_called](Core::System&, u32 addr, u8 val) {
EXPECT_EQ(0x0C001234u, addr); EXPECT_EQ(0x0C001234u, addr);
EXPECT_EQ(0x34, val); EXPECT_EQ(0x34, val);
write_called = true; write_called = true;