From 8dabd1a0256e4761ad88494280d74397e16af9f5 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 12 Mar 2023 20:31:10 +0100 Subject: [PATCH] PowerPC/MMU: Refactor to class, move to System. --- Source/Core/Common/x64Emitter.h | 11 + Source/Core/Core/ActionReplay.cpp | 60 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 49 +- Source/Core/Core/CheatSearch.cpp | 20 +- .../Core/Core/Debugger/Debugger_SymbolMap.cpp | 10 +- Source/Core/Core/Debugger/OSThread.cpp | 88 +- .../Core/Core/Debugger/PPCDebugInterface.cpp | 30 +- Source/Core/Core/Debugger/RSO.cpp | 95 +- Source/Core/Core/FifoPlayer/FifoPlayer.cpp | 14 +- Source/Core/Core/GeckoCode.cpp | 39 +- Source/Core/Core/HLE/HLE_Misc.cpp | 16 +- Source/Core/Core/HLE/HLE_OS.cpp | 32 +- Source/Core/Core/HLE/HLE_VarArgs.cpp | 12 +- Source/Core/Core/HLE/HLE_VarArgs.h | 8 +- Source/Core/Core/HW/AddressSpace.cpp | 27 +- Source/Core/Core/MemoryWatcher.cpp | 4 +- Source/Core/Core/PatchEngine.cpp | 31 +- Source/Core/Core/PowerPC/BreakPoints.cpp | 6 +- Source/Core/Core/PowerPC/Expression.cpp | 18 +- Source/Core/Core/PowerPC/GDBStub.cpp | 4 +- .../Core/PowerPC/Interpreter/Interpreter.cpp | 8 +- .../Core/PowerPC/Interpreter/Interpreter.h | 6 +- .../Interpreter/Interpreter_LoadStore.cpp | 130 +-- .../Interpreter_LoadStorePaired.cpp | 117 +-- .../Interpreter_SystemRegisters.cpp | 14 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 4 +- .../Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 6 +- .../Core/PowerPC/Jit64Common/EmuCodeBlock.cpp | 45 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 4 +- .../PowerPC/JitArm64/JitArm64_BackPatch.cpp | 34 +- .../PowerPC/JitArm64/JitArm64_LoadStore.cpp | 14 +- .../JitArm64/JitArm64_LoadStoreFloating.cpp | 6 +- .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 3 +- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 1 + .../Core/Core/PowerPC/JitCommon/JitCache.cpp | 8 +- Source/Core/Core/PowerPC/JitInterface.cpp | 2 +- Source/Core/Core/PowerPC/MMU.cpp | 925 +++++++++--------- Source/Core/Core/PowerPC/MMU.h | 435 +++++--- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 24 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 11 +- Source/Core/Core/PowerPC/PowerPC.cpp | 12 +- .../PowerPC/SignatureDB/MEGASignatureDB.cpp | 4 +- .../Core/PowerPC/SignatureDB/SignatureDB.cpp | 2 +- Source/Core/Core/System.cpp | 11 +- Source/Core/Core/System.h | 4 +- Source/Core/DiscIO/RiivolutionPatcher.cpp | 8 +- .../DolphinQt/Debugger/CodeViewWidget.cpp | 5 +- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 6 +- .../Core/DolphinQt/Debugger/ThreadWidget.cpp | 11 +- .../Core/DolphinQt/Debugger/WatchWidget.cpp | 19 +- Source/Core/DolphinQt/MenuBar.cpp | 10 +- 51 files changed, 1314 insertions(+), 1149 deletions(-) diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index d027a1a9ef..6bf034b455 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -1137,6 +1137,17 @@ public: ABI_CallFunction(func); } + template + void ABI_CallFunctionPAC(int bits, FunctionPointer func, const void* ptr1, const Gen::OpArg& arg2, + u32 param3) + { + if (!arg2.IsSimpleReg(ABI_PARAM2)) + MOV(bits, R(ABI_PARAM2), arg2); + MOV(32, R(ABI_PARAM3), Imm32(param3)); + MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast(ptr1))); + ABI_CallFunction(func); + } + template void ABI_CallFunctionA(int bits, FunctionPointer func, const Gen::OpArg& arg1) { diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 6d2f1c476e..05b87e11b4 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -375,7 +375,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA const u32 repeat = data >> 8; for (u32 i = 0; i <= repeat; ++i) { - PowerPC::HostWrite_U8(guard, data & 0xFF, new_addr + i); + PowerPC::MMU::HostWrite_U8(guard, data & 0xFF, new_addr + i); LogInfo("Wrote {:08x} to address {:08x}", data & 0xFF, new_addr + i); } LogInfo("--------"); @@ -389,7 +389,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA const u32 repeat = data >> 16; for (u32 i = 0; i <= repeat; ++i) { - PowerPC::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2); + PowerPC::MMU::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2); LogInfo("Wrote {:08x} to address {:08x}", data & 0xFFFF, new_addr + i * 2); } LogInfo("--------"); @@ -400,7 +400,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA case DATATYPE_32BIT: // Dword write LogInfo("32-bit Write"); LogInfo("--------"); - PowerPC::HostWrite_U32(guard, data, new_addr); + PowerPC::MMU::HostWrite_U32(guard, data, new_addr); LogInfo("Wrote {:08x} to address {:08x}", data, new_addr); LogInfo("--------"); break; @@ -420,7 +420,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd const u32 data) { const u32 new_addr = addr.GCAddress(); - const u32 ptr = PowerPC::HostRead_U32(guard, new_addr); + const u32 ptr = PowerPC::MMU::HostRead_U32(guard, new_addr); LogInfo("Hardware Address: {:08x}", new_addr); LogInfo("Size: {:08x}", addr.size); @@ -436,7 +436,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd LogInfo("Pointer: {:08x}", ptr); LogInfo("Byte: {:08x}", thebyte); LogInfo("Offset: {:08x}", offset); - PowerPC::HostWrite_U8(guard, thebyte, ptr + offset); + PowerPC::MMU::HostWrite_U8(guard, thebyte, ptr + offset); LogInfo("Wrote {:08x} to address {:08x}", thebyte, ptr + offset); LogInfo("--------"); break; @@ -451,7 +451,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd LogInfo("Pointer: {:08x}", ptr); LogInfo("Byte: {:08x}", theshort); LogInfo("Offset: {:08x}", offset); - PowerPC::HostWrite_U16(guard, theshort, ptr + offset); + PowerPC::MMU::HostWrite_U16(guard, theshort, ptr + offset); LogInfo("Wrote {:08x} to address {:08x}", theshort, ptr + offset); LogInfo("--------"); break; @@ -461,7 +461,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd case DATATYPE_32BIT: LogInfo("Write 32-bit to pointer"); LogInfo("--------"); - PowerPC::HostWrite_U32(guard, data, ptr); + PowerPC::MMU::HostWrite_U32(guard, data, ptr); LogInfo("Wrote {:08x} to address {:08x}", data, ptr); LogInfo("--------"); break; @@ -489,24 +489,28 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add case DATATYPE_8BIT: LogInfo("8-bit Add"); LogInfo("--------"); - PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, new_addr) + data, new_addr); - LogInfo("Wrote {:02x} to address {:08x}", PowerPC::HostRead_U8(guard, new_addr), new_addr); + PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, new_addr) + data, new_addr); + LogInfo("Wrote {:02x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, new_addr), new_addr); LogInfo("--------"); break; case DATATYPE_16BIT: LogInfo("16-bit Add"); LogInfo("--------"); - PowerPC::HostWrite_U16(guard, PowerPC::HostRead_U16(guard, new_addr) + data, new_addr); - LogInfo("Wrote {:04x} to address {:08x}", PowerPC::HostRead_U16(guard, new_addr), new_addr); + PowerPC::MMU::HostWrite_U16(guard, PowerPC::MMU::HostRead_U16(guard, new_addr) + data, + new_addr); + LogInfo("Wrote {:04x} to address {:08x}", PowerPC::MMU::HostRead_U16(guard, new_addr), + new_addr); LogInfo("--------"); break; case DATATYPE_32BIT: LogInfo("32-bit Add"); LogInfo("--------"); - PowerPC::HostWrite_U32(guard, PowerPC::HostRead_U32(guard, new_addr) + data, new_addr); - LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U32(guard, new_addr), new_addr); + PowerPC::MMU::HostWrite_U32(guard, PowerPC::MMU::HostRead_U32(guard, new_addr) + data, + new_addr); + LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U32(guard, new_addr), + new_addr); LogInfo("--------"); break; @@ -515,12 +519,12 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add LogInfo("32-bit floating Add"); LogInfo("--------"); - const u32 read = PowerPC::HostRead_U32(guard, new_addr); + const u32 read = PowerPC::MMU::HostRead_U32(guard, new_addr); const float read_float = Common::BitCast(read); // data contains an (unsigned?) integer value const float fread = read_float + static_cast(data); const u32 newval = Common::BitCast(fread); - PowerPC::HostWrite_U32(guard, newval, new_addr); + PowerPC::MMU::HostWrite_U32(guard, newval, new_addr); LogInfo("Old Value {:08x}", read); LogInfo("Increment {:08x}", data); LogInfo("New value {:08x}", newval); @@ -578,7 +582,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::HostWrite_U8(guard, val & 0xFF, curr_addr); + PowerPC::MMU::HostWrite_U8(guard, val & 0xFF, curr_addr); curr_addr += addr_incr; val += val_incr; LogInfo("Write {:08x} to address {:08x}", val & 0xFF, curr_addr); @@ -594,7 +598,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::HostWrite_U16(guard, val & 0xFFFF, curr_addr); + PowerPC::MMU::HostWrite_U16(guard, val & 0xFFFF, curr_addr); LogInfo("Write {:08x} to address {:08x}", val & 0xFFFF, curr_addr); curr_addr += addr_incr * 2; val += val_incr; @@ -609,7 +613,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::HostWrite_U32(guard, val, curr_addr); + PowerPC::MMU::HostWrite_U32(guard, val, curr_addr); LogInfo("Write {:08x} to address {:08x}", val, curr_addr); curr_addr += addr_incr * 4; val += val_incr; @@ -650,14 +654,15 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val { // Memory Copy With Pointers Support LogInfo("Memory Copy With Pointers Support"); LogInfo("--------"); - const u32 ptr_dest = PowerPC::HostRead_U32(guard, addr_dest); + const u32 ptr_dest = PowerPC::MMU::HostRead_U32(guard, addr_dest); LogInfo("Resolved Dest Address to: {:08x}", ptr_dest); - const u32 ptr_src = PowerPC::HostRead_U32(guard, addr_src); + const u32 ptr_src = PowerPC::MMU::HostRead_U32(guard, addr_src); LogInfo("Resolved Src Address to: {:08x}", ptr_src); for (int i = 0; i < num_bytes; ++i) { - PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, ptr_src + i), ptr_dest + i); - LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, ptr_src + i), + PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, ptr_src + i), + ptr_dest + i); + LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, ptr_src + i), ptr_dest + i); } LogInfo("--------"); @@ -668,8 +673,9 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val LogInfo("--------"); for (int i = 0; i < num_bytes; ++i) { - PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, addr_src + i), addr_dest + i); - LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, addr_src + i), + PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, addr_src + i), + addr_dest + i); + LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, addr_src + i), addr_dest + i); } LogInfo("--------"); @@ -777,16 +783,16 @@ static bool ConditionalCode(const Core::CPUThreadGuard& guard, const ARAddr& add switch (addr.size) { case DATATYPE_8BIT: - result = CompareValues(PowerPC::HostRead_U8(guard, new_addr), (data & 0xFF), addr.type); + result = CompareValues(PowerPC::MMU::HostRead_U8(guard, new_addr), (data & 0xFF), addr.type); break; case DATATYPE_16BIT: - result = CompareValues(PowerPC::HostRead_U16(guard, new_addr), (data & 0xFFFF), addr.type); + result = CompareValues(PowerPC::MMU::HostRead_U16(guard, new_addr), (data & 0xFFFF), addr.type); break; case DATATYPE_32BIT_FLOAT: case DATATYPE_32BIT: - result = CompareValues(PowerPC::HostRead_U32(guard, new_addr), data, addr.type); + result = CompareValues(PowerPC::MMU::HostRead_U32(guard, new_addr), data, addr.type); break; default: diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index 222490d95c..be799ab1a2 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -51,7 +51,7 @@ void PresetTimeBaseTicks(Core::System& system, const Core::CPUThreadGuard& guard const u64 time_base_ticks = emulated_time * 40500000ULL; - PowerPC::HostWrite_U64(guard, time_base_ticks, 0x800030D8); + PowerPC::MMU::HostWrite_U64(guard, time_base_ticks, 0x800030D8); } } // Anonymous namespace @@ -127,8 +127,10 @@ void CBoot::SetupBAT(Core::System& system, bool is_wii) ppc_state.spr[SPR_DBAT5L] = 0x1000002a; HID4(ppc_state).SBE = 1; } - PowerPC::DBATUpdated(); - PowerPC::IBATUpdated(); + + auto& mmu = system.GetMMU(); + mmu.DBATUpdated(); + mmu.IBATUpdated(); } bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii, @@ -153,6 +155,7 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard // TODO - Make Apploader(or just RunFunction()) debuggable!!! auto& ppc_state = system.GetPPCState(); + auto& mmu = system.GetMMU(); // Call iAppLoaderEntry. DEBUG_LOG_FMT(BOOT, "Call iAppLoaderEntry"); @@ -161,14 +164,14 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard ppc_state.gpr[4] = iAppLoaderFuncAddr + 4; ppc_state.gpr[5] = iAppLoaderFuncAddr + 8; RunFunction(system, *entry); - const u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0); - const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4); - const u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8); + const u32 iAppLoaderInit = mmu.Read_U32(iAppLoaderFuncAddr + 0); + const u32 iAppLoaderMain = mmu.Read_U32(iAppLoaderFuncAddr + 4); + const u32 iAppLoaderClose = mmu.Read_U32(iAppLoaderFuncAddr + 8); // iAppLoaderInit DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit"); - PowerPC::HostWrite_U32(guard, 0x4E800020, 0x81300000); // Write BLR - HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader + PowerPC::MMU::HostWrite_U32(guard, 0x4E800020, 0x81300000); // Write BLR + HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader ppc_state.gpr[3] = 0x81300000; RunFunction(system, iAppLoaderInit); @@ -189,9 +192,9 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard // iAppLoaderMain returns 0 when there are no more sections to copy. while (ppc_state.gpr[3] != 0x00) { - const u32 ram_address = PowerPC::Read_U32(0x81300004); - const u32 length = PowerPC::Read_U32(0x81300008); - const u32 dvd_offset = PowerPC::Read_U32(0x8130000c) << (is_wii ? 2 : 0); + const u32 ram_address = mmu.Read_U32(0x81300004); + const u32 length = mmu.Read_U32(0x81300008); + const u32 dvd_offset = mmu.Read_U32(0x8130000c) << (is_wii ? 2 : 0); INFO_LOG_FMT(BOOT, "DVDRead: offset: {:08x} memOffset: {:08x} length: {}", dvd_offset, ram_address, length); @@ -223,35 +226,35 @@ void CBoot::SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guar auto& memory = system.GetMemory(); // Booted from bootrom. 0xE5207C22 = booted from jtag - PowerPC::HostWrite_U32(guard, 0x0D15EA5E, 0x80000020); + PowerPC::MMU::HostWrite_U32(guard, 0x0D15EA5E, 0x80000020); // Physical Memory Size (24MB on retail) - PowerPC::HostWrite_U32(guard, memory.GetRamSizeReal(), 0x80000028); + PowerPC::MMU::HostWrite_U32(guard, memory.GetRamSizeReal(), 0x80000028); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2 // TODO: determine why some games fail when using a retail ID. // (Seem to take different EXI paths, see Ikaruga for example) const u32 console_type = static_cast(Core::ConsoleType::LatestDevkit); - PowerPC::HostWrite_U32(guard, console_type, 0x8000002C); + PowerPC::MMU::HostWrite_U32(guard, console_type, 0x8000002C); // Fake the VI Init of the IPL (YAGCD 4.2.1.4) - PowerPC::HostWrite_U32(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, - 0x800000CC); + PowerPC::MMU::HostWrite_U32(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, + 0x800000CC); // ARAM Size. 16MB main + 4/16/32MB external. (retail consoles have no external ARAM) - PowerPC::HostWrite_U32(guard, 0x01000000, 0x800000d0); + PowerPC::MMU::HostWrite_U32(guard, 0x01000000, 0x800000d0); - PowerPC::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed - PowerPC::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed + PowerPC::MMU::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed + PowerPC::MMU::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed - PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi - PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi - PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi + PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi + PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi + PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi PresetTimeBaseTicks(system, guard); // HIO checks this - // PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type + // PowerPC::MMU::HostWrite_U16(0x8200, 0x000030e6); // Console type } // __________________________________________________________________________________________________ diff --git a/Source/Core/Core/CheatSearch.cpp b/Source/Core/Core/CheatSearch.cpp index 8fbfd86c14..2f75998ae8 100644 --- a/Source/Core/Core/CheatSearch.cpp +++ b/Source/Core/Core/CheatSearch.cpp @@ -111,7 +111,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadU8(guard, addr, space); + return PowerPC::MMU::HostTryReadU8(guard, addr, space); } template <> @@ -119,7 +119,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadU16(guard, addr, space); + return PowerPC::MMU::HostTryReadU16(guard, addr, space); } template <> @@ -127,7 +127,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadU32(guard, addr, space); + return PowerPC::MMU::HostTryReadU32(guard, addr, space); } template <> @@ -135,7 +135,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadU64(guard, addr, space); + return PowerPC::MMU::HostTryReadU64(guard, addr, space); } template <> @@ -143,7 +143,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - auto tmp = PowerPC::HostTryReadU8(guard, addr, space); + auto tmp = PowerPC::MMU::HostTryReadU8(guard, addr, space); if (!tmp) return std::nullopt; return PowerPC::ReadResult(tmp->translated, Common::BitCast(tmp->value)); @@ -154,7 +154,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - auto tmp = PowerPC::HostTryReadU16(guard, addr, space); + auto tmp = PowerPC::MMU::HostTryReadU16(guard, addr, space); if (!tmp) return std::nullopt; return PowerPC::ReadResult(tmp->translated, Common::BitCast(tmp->value)); @@ -165,7 +165,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - auto tmp = PowerPC::HostTryReadU32(guard, addr, space); + auto tmp = PowerPC::MMU::HostTryReadU32(guard, addr, space); if (!tmp) return std::nullopt; return PowerPC::ReadResult(tmp->translated, Common::BitCast(tmp->value)); @@ -176,7 +176,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - auto tmp = PowerPC::HostTryReadU64(guard, addr, space); + auto tmp = PowerPC::MMU::HostTryReadU64(guard, addr, space); if (!tmp) return std::nullopt; return PowerPC::ReadResult(tmp->translated, Common::BitCast(tmp->value)); @@ -187,7 +187,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadF32(guard, addr, space); + return PowerPC::MMU::HostTryReadF32(guard, addr, space); } template <> @@ -195,7 +195,7 @@ std::optional> TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, PowerPC::RequestedAddressSpace space) { - return PowerPC::HostTryReadF64(guard, addr, space); + return PowerPC::MMU::HostTryReadF64(guard, addr, space); } } // namespace diff --git a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp index 023c004897..cab601c83d 100644 --- a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp +++ b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp @@ -41,7 +41,7 @@ void AddAutoBreakpoints() // Returns true if the address is not a valid RAM address or NULL. static bool IsStackBottom(const Core::CPUThreadGuard& guard, u32 addr) { - return !addr || !PowerPC::HostIsRAMAddress(guard, addr); + return !addr || !PowerPC::MMU::HostIsRAMAddress(guard, addr); } static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard, @@ -51,18 +51,18 @@ static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard if (!IsStackBottom(guard, ppc_state.gpr[1])) { - u32 addr = PowerPC::HostRead_U32(guard, ppc_state.gpr[1]); // SP + u32 addr = PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[1]); // SP // Walk the stack chain for (int count = 0; !IsStackBottom(guard, addr + 4) && (count++ < 20); ++count) { - u32 func_addr = PowerPC::HostRead_U32(guard, addr + 4); + u32 func_addr = PowerPC::MMU::HostRead_U32(guard, addr + 4); stack_step(func_addr); if (IsStackBottom(guard, addr)) break; - addr = PowerPC::HostRead_U32(guard, addr); + addr = PowerPC::MMU::HostRead_U32(guard, addr); } } } @@ -75,7 +75,7 @@ bool GetCallstack(Core::System& system, const Core::CPUThreadGuard& guard, { auto& ppc_state = system.GetPPCState(); - if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[1])) + if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[1])) return false; if (LR(ppc_state) == 0) diff --git a/Source/Core/Core/Debugger/OSThread.cpp b/Source/Core/Core/Debugger/OSThread.cpp index b8f3e25b6d..d4cee37d26 100644 --- a/Source/Core/Core/Debugger/OSThread.cpp +++ b/Source/Core/Core/Debugger/OSThread.cpp @@ -19,23 +19,23 @@ namespace Core::Debug void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr) { for (std::size_t i = 0; i < gpr.size(); i++) - gpr[i] = PowerPC::HostRead_U32(guard, addr + u32(i * sizeof(int))); - cr = PowerPC::HostRead_U32(guard, addr + 0x80); - lr = PowerPC::HostRead_U32(guard, addr + 0x84); - ctr = PowerPC::HostRead_U32(guard, addr + 0x88); - xer = PowerPC::HostRead_U32(guard, addr + 0x8C); + gpr[i] = PowerPC::MMU::HostRead_U32(guard, addr + u32(i * sizeof(int))); + cr = PowerPC::MMU::HostRead_U32(guard, addr + 0x80); + lr = PowerPC::MMU::HostRead_U32(guard, addr + 0x84); + ctr = PowerPC::MMU::HostRead_U32(guard, addr + 0x88); + xer = PowerPC::MMU::HostRead_U32(guard, addr + 0x8C); for (std::size_t i = 0; i < fpr.size(); i++) - fpr[i] = PowerPC::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double))); - fpscr = PowerPC::HostRead_U64(guard, addr + 0x190); - srr0 = PowerPC::HostRead_U32(guard, addr + 0x198); - srr1 = PowerPC::HostRead_U32(guard, addr + 0x19c); - dummy = PowerPC::HostRead_U16(guard, addr + 0x1a0); - state = static_cast(PowerPC::HostRead_U16(guard, addr + 0x1a2)); + fpr[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double))); + fpscr = PowerPC::MMU::HostRead_U64(guard, addr + 0x190); + srr0 = PowerPC::MMU::HostRead_U32(guard, addr + 0x198); + srr1 = PowerPC::MMU::HostRead_U32(guard, addr + 0x19c); + dummy = PowerPC::MMU::HostRead_U16(guard, addr + 0x1a0); + state = static_cast(PowerPC::MMU::HostRead_U16(guard, addr + 0x1a2)); for (std::size_t i = 0; i < gqr.size(); i++) - gqr[i] = PowerPC::HostRead_U32(guard, addr + 0x1a4 + u32(i * sizeof(int))); + gqr[i] = PowerPC::MMU::HostRead_U32(guard, addr + 0x1a4 + u32(i * sizeof(int))); psf_padding = 0; for (std::size_t i = 0; i < psf.size(); i++) - psf[i] = PowerPC::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double))); + psf[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double))); } // Mutex offsets based on the following functions: @@ -44,12 +44,12 @@ void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr) // - __OSUnlockAllMutex void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr) { - thread_queue.head = PowerPC::HostRead_U32(guard, addr); - thread_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x4); - owner_addr = PowerPC::HostRead_U32(guard, addr + 0x8); - lock_count = PowerPC::HostRead_U32(guard, addr + 0xc); - link.next = PowerPC::HostRead_U32(guard, addr + 0x10); - link.prev = PowerPC::HostRead_U32(guard, addr + 0x14); + thread_queue.head = PowerPC::MMU::HostRead_U32(guard, addr); + thread_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x4); + owner_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x8); + lock_count = PowerPC::MMU::HostRead_U32(guard, addr + 0xc); + link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x10); + link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x14); } // Thread offsets based on the following functions: @@ -67,38 +67,38 @@ void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr) void OSThread::Read(const Core::CPUThreadGuard& guard, u32 addr) { context.Read(guard, addr); - state = PowerPC::HostRead_U16(guard, addr + 0x2c8); - is_detached = PowerPC::HostRead_U16(guard, addr + 0x2ca); - suspend = PowerPC::HostRead_U32(guard, addr + 0x2cc); - effective_priority = PowerPC::HostRead_U32(guard, addr + 0x2d0); - base_priority = PowerPC::HostRead_U32(guard, addr + 0x2d4); - exit_code_addr = PowerPC::HostRead_U32(guard, addr + 0x2d8); + state = PowerPC::MMU::HostRead_U16(guard, addr + 0x2c8); + is_detached = PowerPC::MMU::HostRead_U16(guard, addr + 0x2ca); + suspend = PowerPC::MMU::HostRead_U32(guard, addr + 0x2cc); + effective_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d0); + base_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d4); + exit_code_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d8); - queue_addr = PowerPC::HostRead_U32(guard, addr + 0x2dc); - queue_link.next = PowerPC::HostRead_U32(guard, addr + 0x2e0); - queue_link.prev = PowerPC::HostRead_U32(guard, addr + 0x2e4); + queue_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2dc); + queue_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e0); + queue_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e4); - join_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2e8); - join_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2ec); + join_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e8); + join_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2ec); - mutex_addr = PowerPC::HostRead_U32(guard, addr + 0x2f0); - mutex_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2f4); - mutex_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2f8); + mutex_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f0); + mutex_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f4); + mutex_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f8); - thread_link.next = PowerPC::HostRead_U32(guard, addr + 0x2fc); - thread_link.prev = PowerPC::HostRead_U32(guard, addr + 0x300); + thread_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2fc); + thread_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x300); - stack_addr = PowerPC::HostRead_U32(guard, addr + 0x304); - stack_end = PowerPC::HostRead_U32(guard, addr + 0x308); - error = PowerPC::HostRead_U32(guard, addr + 0x30c); - specific[0] = PowerPC::HostRead_U32(guard, addr + 0x310); - specific[1] = PowerPC::HostRead_U32(guard, addr + 0x314); + stack_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x304); + stack_end = PowerPC::MMU::HostRead_U32(guard, addr + 0x308); + error = PowerPC::MMU::HostRead_U32(guard, addr + 0x30c); + specific[0] = PowerPC::MMU::HostRead_U32(guard, addr + 0x310); + specific[1] = PowerPC::MMU::HostRead_U32(guard, addr + 0x314); } bool OSThread::IsValid(const Core::CPUThreadGuard& guard) const { - return PowerPC::HostIsRAMAddress(guard, stack_end) && - PowerPC::HostRead_U32(guard, stack_end) == STACK_MAGIC; + return PowerPC::MMU::HostIsRAMAddress(guard, stack_end) && + PowerPC::MMU::HostRead_U32(guard, stack_end) == STACK_MAGIC; } OSThreadView::OSThreadView(const Core::CPUThreadGuard& guard, u32 addr) @@ -192,9 +192,9 @@ std::string OSThreadView::GetSpecific(const Core::CPUThreadGuard& guard) const for (u32 addr : m_thread.specific) { - if (!PowerPC::HostIsRAMAddress(guard, addr)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, addr)) break; - specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(guard, addr)); + specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::MMU::HostGetString(guard, addr)); } return specific; diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index d5311ee936..6d363fd6bf 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -33,20 +33,20 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa const u32 address = patch.address; const std::size_t size = patch.value.size(); - if (!PowerPC::HostIsRAMAddress(guard, address)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, address)) return; for (u32 offset = 0; offset < size; ++offset) { if (store_existing_value) { - const u8 value = PowerPC::HostRead_U8(guard, address + offset); - PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset); + const u8 value = PowerPC::MMU::HostRead_U8(guard, address + offset); + PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset); patch.value[offset] = value; } else { - PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset); + PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset); } if (((address + offset) % 4) == 3) @@ -231,10 +231,10 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard& Common::Debug::Threads threads; constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc; - if (!PowerPC::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR)) return threads; - const u32 active_queue_head = PowerPC::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR); - if (!PowerPC::HostIsRAMAddress(guard, active_queue_head)) + const u32 active_queue_head = PowerPC::MMU::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR); + if (!PowerPC::MMU::HostIsRAMAddress(guard, active_queue_head)) return threads; auto active_thread = std::make_unique(guard, active_queue_head); @@ -243,7 +243,7 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard& std::vector visited_addrs{active_thread->GetAddress()}; const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) { - while (addr != 0 && PowerPC::HostIsRAMAddress(guard, addr)) + while (addr != 0 && PowerPC::MMU::HostIsRAMAddress(guard, addr)) { if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end()) break; @@ -271,12 +271,12 @@ std::string PPCDebugInterface::Disassemble(const Core::CPUThreadGuard* guard, u3 { if (guard) { - if (!PowerPC::HostIsRAMAddress(*guard, address)) + if (!PowerPC::MMU::HostIsRAMAddress(*guard, address)) { return "(No RAM here)"; } - const u32 op = PowerPC::HostRead_Instruction(*guard, address); + const u32 op = PowerPC::MMU::HostRead_Instruction(*guard, address); std::string disasm = Common::GekkoDisassembler::Disassemble(op, address); const UGeckoInstruction inst{op}; @@ -300,7 +300,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu { const bool is_aram = memory != 0; - if (is_aram || PowerPC::HostIsRAMAddress(guard, address)) + if (is_aram || PowerPC::MMU::HostIsRAMAddress(guard, address)) { return fmt::format("{:08X}{}", ReadExtraMemory(guard, memory, address), is_aram ? " (ARAM)" : ""); @@ -314,7 +314,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const { - return PowerPC::HostRead_U32(guard, address); + return PowerPC::MMU::HostRead_U32(guard, address); } u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory, @@ -323,7 +323,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me switch (memory) { case 0: - return PowerPC::HostRead_U32(guard, address); + return PowerPC::MMU::HostRead_U32(guard, address); case 1: { auto& dsp = Core::System::GetInstance().GetDSP(); @@ -337,7 +337,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me u32 PPCDebugInterface::ReadInstruction(const Core::CPUThreadGuard& guard, u32 address) const { - return PowerPC::HostRead_Instruction(guard, address); + return PowerPC::MMU::HostRead_Instruction(guard, address); } bool PPCDebugInterface::IsAlive() const @@ -412,7 +412,7 @@ u32 PPCDebugInterface::GetColor(const Core::CPUThreadGuard* guard, u32 address) { if (!guard || !IsAlive()) return 0xFFFFFF; - if (!PowerPC::HostIsRAMAddress(*guard, address)) + if (!PowerPC::MMU::HostIsRAMAddress(*guard, address)) return 0xeeeeee; Common::Symbol* symbol = g_symbolDB.GetSymbolFromAddr(address); diff --git a/Source/Core/Core/Debugger/RSO.cpp b/Source/Core/Core/Debugger/RSO.cpp index 319e1962c8..71070f21a9 100644 --- a/Source/Core/Core/Debugger/RSO.cpp +++ b/Source/Core/Core/Debugger/RSO.cpp @@ -17,37 +17,42 @@ void RSOHeaderView::Load(const Core::CPUThreadGuard& guard, u32 address) { m_address = address; - m_header.entry.next_entry = PowerPC::HostRead_U32(guard, address); - m_header.entry.prev_entry = PowerPC::HostRead_U32(guard, address + 0x04); - m_header.entry.section_count = PowerPC::HostRead_U32(guard, address + 0x08); - m_header.entry.section_table_offset = PowerPC::HostRead_U32(guard, address + 0xC); - m_header.entry.name_offset = PowerPC::HostRead_U32(guard, address + 0x10); - m_header.entry.name_size = PowerPC::HostRead_U32(guard, address + 0x14); - m_header.entry.version = PowerPC::HostRead_U32(guard, address + 0x18); - m_header.entry.bss_size = PowerPC::HostRead_U32(guard, address + 0x1C); - m_header.section_info.prolog_section_index = PowerPC::HostRead_U8(guard, address + 0x20); - m_header.section_info.epilog_section_index = PowerPC::HostRead_U8(guard, address + 0x21); - m_header.section_info.unresolved_section_index = PowerPC::HostRead_U8(guard, address + 0x22); - m_header.section_info.bss_section_index = PowerPC::HostRead_U8(guard, address + 0x23); - m_header.section_info.prolog_offset = PowerPC::HostRead_U32(guard, address + 0x24); - m_header.section_info.epilog_offset = PowerPC::HostRead_U32(guard, address + 0x28); - m_header.section_info.unresolved_offset = PowerPC::HostRead_U32(guard, address + 0x2C); - m_header.relocation_tables.internals_offset = PowerPC::HostRead_U32(guard, address + 0x30); - m_header.relocation_tables.internals_size = PowerPC::HostRead_U32(guard, address + 0x34); - m_header.relocation_tables.externals_offset = PowerPC::HostRead_U32(guard, address + 0x38); - m_header.relocation_tables.externals_size = PowerPC::HostRead_U32(guard, address + 0x3C); - m_header.symbol_tables.exports_offset = PowerPC::HostRead_U32(guard, address + 0x40); - m_header.symbol_tables.exports_size = PowerPC::HostRead_U32(guard, address + 0x44); - m_header.symbol_tables.exports_name_table = PowerPC::HostRead_U32(guard, address + 0x48); - m_header.symbol_tables.imports_offset = PowerPC::HostRead_U32(guard, address + 0x4C); - m_header.symbol_tables.imports_size = PowerPC::HostRead_U32(guard, address + 0x50); - m_header.symbol_tables.imports_name_table = PowerPC::HostRead_U32(guard, address + 0x54); + m_header.entry.next_entry = PowerPC::MMU::HostRead_U32(guard, address); + m_header.entry.prev_entry = PowerPC::MMU::HostRead_U32(guard, address + 0x04); + m_header.entry.section_count = PowerPC::MMU::HostRead_U32(guard, address + 0x08); + m_header.entry.section_table_offset = PowerPC::MMU::HostRead_U32(guard, address + 0xC); + m_header.entry.name_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x10); + m_header.entry.name_size = PowerPC::MMU::HostRead_U32(guard, address + 0x14); + m_header.entry.version = PowerPC::MMU::HostRead_U32(guard, address + 0x18); + m_header.entry.bss_size = PowerPC::MMU::HostRead_U32(guard, address + 0x1C); + m_header.section_info.prolog_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x20); + m_header.section_info.epilog_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x21); + m_header.section_info.unresolved_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x22); + m_header.section_info.bss_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x23); + m_header.section_info.prolog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x24); + m_header.section_info.epilog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x28); + m_header.section_info.unresolved_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x2C); + m_header.relocation_tables.internals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x30); + m_header.relocation_tables.internals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x34); + m_header.relocation_tables.externals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x38); + m_header.relocation_tables.externals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x3C); + m_header.symbol_tables.exports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x40); + m_header.symbol_tables.exports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x44); + m_header.symbol_tables.exports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x48); + m_header.symbol_tables.imports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x4C); + m_header.symbol_tables.imports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x50); + m_header.symbol_tables.imports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x54); // Prevent an invalid name going wild if (m_header.entry.name_size < 0x100) - m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size); + { + m_name = + PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size); + } else - m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, 0x100); + { + m_name = PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, 0x100); + } } u32 RSOHeaderView::GetNextEntry() const @@ -176,8 +181,8 @@ void RSOSectionsView::Load(const Core::CPUThreadGuard& guard, u32 address, std:: for (std::size_t i = 0; i < count; ++i) { RSOSection section; - section.offset = PowerPC::HostRead_U32(guard, address); - section.size = PowerPC::HostRead_U32(guard, address + 4); + section.offset = PowerPC::MMU::HostRead_U32(guard, address); + section.size = PowerPC::MMU::HostRead_U32(guard, address + 4); m_sections.emplace_back(std::move(section)); address += sizeof(RSOSection); } @@ -204,9 +209,9 @@ void RSOImportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s for (std::size_t i = 0; i < count; ++i) { RSOImport rso_import; - rso_import.name_offset = PowerPC::HostRead_U32(guard, address); - rso_import.code_offset = PowerPC::HostRead_U32(guard, address + 4); - rso_import.entry_offset = PowerPC::HostRead_U32(guard, address + 8); + rso_import.name_offset = PowerPC::MMU::HostRead_U32(guard, address); + rso_import.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4); + rso_import.entry_offset = PowerPC::MMU::HostRead_U32(guard, address + 8); m_imports.emplace_back(std::move(rso_import)); address += sizeof(RSOImport); } @@ -233,10 +238,10 @@ void RSOExportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s for (std::size_t i = 0; i < count; ++i) { RSOExport rso_export; - rso_export.name_offset = PowerPC::HostRead_U32(guard, address); - rso_export.code_offset = PowerPC::HostRead_U32(guard, address + 4); - rso_export.section_index = PowerPC::HostRead_U32(guard, address + 8); - rso_export.hash = PowerPC::HostRead_U32(guard, address + 12); + rso_export.name_offset = PowerPC::MMU::HostRead_U32(guard, address); + rso_export.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4); + rso_export.section_index = PowerPC::MMU::HostRead_U32(guard, address + 8); + rso_export.hash = PowerPC::MMU::HostRead_U32(guard, address + 12); m_exports.emplace_back(std::move(rso_export)); address += sizeof(RSOExport); } @@ -263,9 +268,9 @@ void RSOInternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std: for (std::size_t i = 0; i < count; ++i) { RSOInternalsEntry entry; - entry.r_offset = PowerPC::HostRead_U32(guard, address); - entry.r_info = PowerPC::HostRead_U32(guard, address + 4); - entry.r_addend = PowerPC::HostRead_U32(guard, address + 8); + entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address); + entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4); + entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8); m_entries.emplace_back(std::move(entry)); address += sizeof(RSOInternalsEntry); } @@ -292,9 +297,9 @@ void RSOExternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std: for (std::size_t i = 0; i < count; ++i) { RSOExternalsEntry entry; - entry.r_offset = PowerPC::HostRead_U32(guard, address); - entry.r_info = PowerPC::HostRead_U32(guard, address + 4); - entry.r_addend = PowerPC::HostRead_U32(guard, address + 8); + entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address); + entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4); + entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8); m_entries.emplace_back(std::move(entry)); address += sizeof(RSOExternalsEntry); } @@ -443,7 +448,8 @@ const RSOImport& RSOView::GetImport(std::size_t index) const std::string RSOView::GetImportName(const Core::CPUThreadGuard& guard, const RSOImport& rso_import) const { - return PowerPC::HostGetString(guard, m_header.GetImportsNameTable() + rso_import.name_offset); + return PowerPC::MMU::HostGetString(guard, + m_header.GetImportsNameTable() + rso_import.name_offset); } const std::vector& RSOView::GetImports() const @@ -464,7 +470,8 @@ const RSOExport& RSOView::GetExport(std::size_t index) const std::string RSOView::GetExportName(const Core::CPUThreadGuard& guard, const RSOExport& rso_export) const { - return PowerPC::HostGetString(guard, m_header.GetExportsNameTable() + rso_export.name_offset); + return PowerPC::MMU::HostGetString(guard, + m_header.GetExportsNameTable() + rso_export.name_offset); } u32 RSOView::GetExportAddress(const RSOExport& rso_export) const diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index 61905d98ae..baf7b87760 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -654,8 +654,10 @@ void FifoPlayer::LoadMemory() ppc_state.spr[SPR_DBAT0L] = 0x00000002; ppc_state.spr[SPR_DBAT1U] = 0xc0001fff; ppc_state.spr[SPR_DBAT1L] = 0x0000002a; - PowerPC::DBATUpdated(); - PowerPC::IBATUpdated(); + + auto& mmu = system.GetMMU(); + mmu.DBATUpdated(); + mmu.IBATUpdated(); SetupFifo(); LoadRegisters(); @@ -713,12 +715,12 @@ void FifoPlayer::LoadTextureMemory() void FifoPlayer::WriteCP(u32 address, u16 value) { - PowerPC::Write_U16(value, 0xCC000000 | address); + Core::System::GetInstance().GetMMU().Write_U16(value, 0xCC000000 | address); } void FifoPlayer::WritePI(u32 address, u32 value) { - PowerPC::Write_U32(value, 0xCC003000 | address); + Core::System::GetInstance().GetMMU().Write_U32(value, 0xCC003000 | address); } void FifoPlayer::FlushWGP() @@ -823,13 +825,13 @@ bool FifoPlayer::ShouldLoadXF(u8 reg) bool FifoPlayer::IsIdleSet() { CommandProcessor::UCPStatusReg status = - PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); + Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); return status.CommandIdle; } bool FifoPlayer::IsHighWatermarkSet() { CommandProcessor::UCPStatusReg status = - PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); + Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); return status.OverflowHiWatermark; } diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index f77f09203f..c28178ae8e 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -142,17 +142,17 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) // Install code handler for (u32 i = 0; i < data.size(); ++i) - PowerPC::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i); + PowerPC::MMU::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i); // Patch the code handler to the current system type (Gamecube/Wii) for (unsigned int h = 0; h < data.length(); h += 4) { // Patch MMIO address - if (PowerPC::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) == + if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) == (0x3f000000u | ((mmio_addr ^ 1) << 8))) { NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h); - PowerPC::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h); + PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h); } } @@ -162,11 +162,11 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) // Write a magic value to 'gameid' (codehandleronly does not actually read this). // This value will be read back and modified over time by HLE_Misc::GeckoCodeHandlerICacheFlush. - PowerPC::HostWrite_U32(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS); + PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS); // Create GCT in memory - PowerPC::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); - PowerPC::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); + PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); + PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); // Each code is 8 bytes (2 words) wide. There is a starter code and an end code. const u32 start_address = codelist_base_address + CODE_SIZE; @@ -189,8 +189,8 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) for (const GeckoCode::Code& code : active_code.codes) { - PowerPC::HostWrite_U32(guard, code.address, next_address); - PowerPC::HostWrite_U32(guard, code.data, next_address + 4); + PowerPC::MMU::HostWrite_U32(guard, code.address, next_address); + PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4); next_address += CODE_SIZE; } } @@ -199,12 +199,12 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) end_address - start_address); // Stop code. Tells the handler that this is the end of the list. - PowerPC::HostWrite_U32(guard, 0xF0000000, next_address); - PowerPC::HostWrite_U32(guard, 0x00000000, next_address + 4); - PowerPC::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); + PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address); + PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4); + PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); // Turn on codes - PowerPC::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7); + PowerPC::MMU::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7); auto& system = Core::System::GetInstance(); auto& ppc_state = system.GetPPCState(); @@ -274,17 +274,18 @@ void RunCodeHandler(const Core::CPUThreadGuard& guard) ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler ppc_state.gpr[1] &= 0xFFFFFFF0; // Align stack to 16bytes u32 SP = ppc_state.gpr[1]; // Stack Pointer - PowerPC::HostWrite_U32(guard, SP + 8, SP); + PowerPC::MMU::HostWrite_U32(guard, SP + 8, SP); // SP + 4 is reserved for the codehandler to save LR to the stack. - PowerPC::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame - PowerPC::HostWrite_U32(guard, ppc_state.pc, SP + 12); - PowerPC::HostWrite_U32(guard, LR(ppc_state), SP + 16); - PowerPC::HostWrite_U32(guard, ppc_state.cr.Get(), SP + 20); + PowerPC::MMU::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame + PowerPC::MMU::HostWrite_U32(guard, ppc_state.pc, SP + 12); + PowerPC::MMU::HostWrite_U32(guard, LR(ppc_state), SP + 16); + PowerPC::MMU::HostWrite_U32(guard, ppc_state.cr.Get(), SP + 20); // Registers FPR0->13 are volatile for (int i = 0; i < 14; ++i) { - PowerPC::HostWrite_U64(guard, ppc_state.ps[i].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64)); - PowerPC::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(), SP + 24 + (2 * i + 1) * sizeof(u64)); + PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64)); + PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(), + SP + 24 + (2 * i + 1) * sizeof(u64)); } DEBUG_LOG_FMT(ACTIONREPLAY, "GeckoCodes: Initiating phantom branch-and-link. " diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index bcc1bec512..e2adaffebb 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -42,7 +42,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) // been read into memory, or such, so we do the first 5 frames. More // robust alternative would be to actually detect memory writes, but that // would be even uglier.) - u32 gch_gameid = PowerPC::HostRead_U32(guard, Gecko::INSTALLER_BASE_ADDRESS); + u32 gch_gameid = PowerPC::MMU::HostRead_U32(guard, Gecko::INSTALLER_BASE_ADDRESS); if (gch_gameid - Gecko::MAGIC_GAMEID == 5) { return; @@ -51,7 +51,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) { gch_gameid = Gecko::MAGIC_GAMEID; } - PowerPC::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS); + PowerPC::MMU::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS); ppc_state.iCache.Reset(); } @@ -67,14 +67,14 @@ void GeckoReturnTrampoline(const Core::CPUThreadGuard& guard) // Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler. u32 SP = ppc_state.gpr[1]; - ppc_state.gpr[1] = PowerPC::HostRead_U32(guard, SP + 8); - ppc_state.npc = PowerPC::HostRead_U32(guard, SP + 12); - LR(ppc_state) = PowerPC::HostRead_U32(guard, SP + 16); - ppc_state.cr.Set(PowerPC::HostRead_U32(guard, SP + 20)); + ppc_state.gpr[1] = PowerPC::MMU::HostRead_U32(guard, SP + 8); + ppc_state.npc = PowerPC::MMU::HostRead_U32(guard, SP + 12); + LR(ppc_state) = PowerPC::MMU::HostRead_U32(guard, SP + 16); + ppc_state.cr.Set(PowerPC::MMU::HostRead_U32(guard, SP + 20)); for (int i = 0; i < 14; ++i) { - ppc_state.ps[i].SetBoth(PowerPC::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)), - PowerPC::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64))); + ppc_state.ps[i].SetBoth(PowerPC::MMU::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)), + PowerPC::MMU::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64))); } } } // namespace HLE_Misc diff --git a/Source/Core/Core/HLE/HLE_OS.cpp b/Source/Core/Core/HLE/HLE_OS.cpp index 7630b42430..71a27a4ec8 100644 --- a/Source/Core/Core/HLE/HLE_OS.cpp +++ b/Source/Core/Core/HLE/HLE_OS.cpp @@ -10,6 +10,7 @@ #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" +#include "Core/Core.h" #include "Core/HLE/HLE_VarArgs.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" @@ -56,11 +57,11 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para std::string report_message; // Is gpr3 pointing to a pointer (including nullptr) rather than an ASCII string - if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]) && - (PowerPC::HostIsRAMAddress(guard, PowerPC::HostRead_U32(guard, ppc_state.gpr[3])) || - PowerPC::HostRead_U32(guard, ppc_state.gpr[3]) == 0)) + if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) && + (PowerPC::MMU::HostIsRAMAddress(guard, PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3])) || + PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3]) == 0)) { - if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[4])) + if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[4])) { // ___blank(void* this, const char* fmt, ...); report_message = GetStringVA(system, guard, 4, parameter_type); @@ -73,7 +74,7 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para } else { - if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3])) + if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3])) { // ___blank(const char* fmt, ...); report_message = GetStringVA(system, guard, 3, parameter_type); @@ -106,13 +107,13 @@ void HLE_GeneralDebugVPrint(const Core::CPUThreadGuard& guard) // __write_console(int fd, const void* buffer, const u32* size) void HLE_write_console(const Core::CPUThreadGuard& guard) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); std::string report_message = GetStringVA(system, guard, 4); - if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[5])) + if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5])) { - const u32 size = PowerPC::Read_U32(ppc_state.gpr[5]); + const u32 size = system.GetMMU().Read_U32(ppc_state.gpr[5]); if (size > report_message.size()) WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size); else if (size == 0) @@ -169,16 +170,16 @@ void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_ty // The structure FILE is implementation defined. // Both libogc and Dolphin SDK seem to store the fd at the same address. int fd = -1; - if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]) && - PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF)) + if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) && + PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF)) { // The fd is stored as a short at FILE+0xE. - fd = static_cast(PowerPC::HostRead_U16(guard, ppc_state.gpr[3] + 0xE)); + fd = static_cast(PowerPC::MMU::HostRead_U16(guard, ppc_state.gpr[3] + 0xE)); } if (fd != 1 && fd != 2) { // On RVL SDK it seems stored at FILE+0x2. - fd = static_cast(PowerPC::HostRead_U16(guard, ppc_state.gpr[3] + 0x2)); + fd = static_cast(PowerPC::MMU::HostRead_U16(guard, ppc_state.gpr[3] + 0x2)); } if (fd != 1 && fd != 2) return; @@ -210,7 +211,7 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, std::string ArgumentBuffer; std::string result; - std::string string = PowerPC::HostGetString(guard, ppc_state.gpr[str_reg]); + std::string string = PowerPC::MMU::HostGetString(guard, ppc_state.gpr[str_reg]); auto ap = parameter_type == ParameterType::VariableArgumentList ? std::make_unique(system, guard, @@ -242,8 +243,9 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, switch (string[i]) { case 's': - result += StringFromFormat(ArgumentBuffer.c_str(), - PowerPC::HostGetString(guard, ap->GetArgT(guard)).c_str()); + result += + StringFromFormat(ArgumentBuffer.c_str(), + PowerPC::MMU::HostGetString(guard, ap->GetArgT(guard)).c_str()); break; case 'a': diff --git a/Source/Core/Core/HLE/HLE_VarArgs.cpp b/Source/Core/Core/HLE/HLE_VarArgs.cpp index 0e7e65561b..4c792e973e 100644 --- a/Source/Core/Core/HLE/HLE_VarArgs.cpp +++ b/Source/Core/Core/HLE/HLE_VarArgs.cpp @@ -20,10 +20,10 @@ double HLE::SystemVABI::VAList::GetFPR(const Core::CPUThreadGuard&, u32 fpr) con HLE::SystemVABI::VAListStruct::VAListStruct(Core::System& system, const Core::CPUThreadGuard& guard, u32 address) - : VAList(system, 0), m_va_list{PowerPC::HostRead_U8(guard, address), - PowerPC::HostRead_U8(guard, address + 1), - PowerPC::HostRead_U32(guard, address + 4), - PowerPC::HostRead_U32(guard, address + 8)}, + : VAList(system, 0), m_va_list{PowerPC::MMU::HostRead_U8(guard, address), + PowerPC::MMU::HostRead_U8(guard, address + 1), + PowerPC::MMU::HostRead_U32(guard, address + 4), + PowerPC::MMU::HostRead_U32(guard, address + 8)}, m_address(address), m_has_fpr_area(system.GetPPCState().cr.GetBit(6) == 1) { m_stack = m_va_list.overflow_arg_area; @@ -49,7 +49,7 @@ u32 HLE::SystemVABI::VAListStruct::GetGPR(const Core::CPUThreadGuard& guard, u32 return 0; } const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4); - return PowerPC::HostRead_U32(guard, gpr_address); + return PowerPC::MMU::HostRead_U32(guard, gpr_address); } double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard, u32 fpr) const @@ -60,5 +60,5 @@ double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard, return 0.0; } const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8); - return PowerPC::HostRead_F64(guard, fpr_address); + return PowerPC::MMU::HostRead_F64(guard, fpr_address); } diff --git a/Source/Core/Core/HLE/HLE_VarArgs.h b/Source/Core/Core/HLE/HLE_VarArgs.h index 6ed4919a69..eecf231425 100644 --- a/Source/Core/Core/HLE/HLE_VarArgs.h +++ b/Source/Core/Core/HLE/HLE_VarArgs.h @@ -55,7 +55,7 @@ public: for (size_t i = 0; i < sizeof(T); i += 1, addr += 1) { - reinterpret_cast(&obj)[i] = PowerPC::HostRead_U8(guard, addr); + reinterpret_cast(&obj)[i] = PowerPC::MMU::HostRead_U8(guard, addr); } return obj; @@ -76,7 +76,7 @@ public: else { m_stack = Common::AlignUp(m_stack, 4); - value = PowerPC::HostRead_U32(guard, m_stack); + value = PowerPC::MMU::HostRead_U32(guard, m_stack); m_stack += 4; } @@ -99,7 +99,7 @@ public: else { m_stack = Common::AlignUp(m_stack, 8); - value = PowerPC::HostRead_U64(guard, m_stack); + value = PowerPC::MMU::HostRead_U64(guard, m_stack); m_stack += 8; } @@ -120,7 +120,7 @@ public: else { m_stack = Common::AlignUp(m_stack, 8); - value = PowerPC::HostRead_F64(guard, m_stack); + value = PowerPC::MMU::HostRead_F64(guard, m_stack); m_stack += 8; } diff --git a/Source/Core/Core/HW/AddressSpace.cpp b/Source/Core/Core/HW/AddressSpace.cpp index 0bacf52c2d..5556135146 100644 --- a/Source/Core/Core/HW/AddressSpace.cpp +++ b/Source/Core/Core/HW/AddressSpace.cpp @@ -84,43 +84,43 @@ struct EffectiveAddressSpaceAccessors : Accessors { bool IsValidAddress(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostIsRAMAddress(guard, address); + return PowerPC::MMU::HostIsRAMAddress(guard, address); } u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostRead_U8(guard, address); + return PowerPC::MMU::HostRead_U8(guard, address); } void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override { - PowerPC::HostWrite_U8(guard, value, address); + PowerPC::MMU::HostWrite_U8(guard, value, address); } u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostRead_U16(guard, address); + return PowerPC::MMU::HostRead_U16(guard, address); } void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override { - PowerPC::HostWrite_U16(guard, value, address); + PowerPC::MMU::HostWrite_U16(guard, value, address); } u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostRead_U32(guard, address); + return PowerPC::MMU::HostRead_U32(guard, address); } void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override { - PowerPC::HostWrite_U32(guard, value, address); + PowerPC::MMU::HostWrite_U32(guard, value, address); } u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostRead_U64(guard, address); + return PowerPC::MMU::HostRead_U64(guard, address); } void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override { - PowerPC::HostWrite_U64(guard, value, address); + PowerPC::MMU::HostWrite_U64(guard, value, address); } float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override { - return PowerPC::HostRead_F32(guard, address); + return PowerPC::MMU::HostRead_F32(guard, address); }; bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start, @@ -128,16 +128,17 @@ struct EffectiveAddressSpaceAccessors : Accessors { auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); + auto& mmu = system.GetMMU(); u32 page_base = haystack_start & 0xfffff000; u32 offset = haystack_start & 0x0000fff; do { - if (!PowerPC::HostIsRAMAddress(guard, page_base)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, page_base)) { return false; } - auto page_physical_address = PowerPC::GetTranslatedAddress(page_base); + auto page_physical_address = mmu.GetTranslatedAddress(page_base); if (!page_physical_address.has_value()) { return false; @@ -184,7 +185,7 @@ struct EffectiveAddressSpaceAccessors : Accessors const u32 haystack_offset_change = forward ? 1 : -1; do { - if (PowerPC::HostIsRAMAddress(guard, haystack_address)) + if (PowerPC::MMU::HostIsRAMAddress(guard, haystack_address)) { do { diff --git a/Source/Core/Core/MemoryWatcher.cpp b/Source/Core/Core/MemoryWatcher.cpp index f2456f6d57..38cdebe1b4 100644 --- a/Source/Core/Core/MemoryWatcher.cpp +++ b/Source/Core/Core/MemoryWatcher.cpp @@ -72,8 +72,8 @@ u32 MemoryWatcher::ChasePointer(const Core::CPUThreadGuard& guard, const std::st u32 value = 0; for (u32 offset : m_addresses[line]) { - value = PowerPC::HostRead_U32(guard, value + offset); - if (!PowerPC::HostIsRAMAddress(guard, value)) + value = PowerPC::MMU::HostRead_U32(guard, value + offset); + if (!PowerPC::MMU::HostIsRAMAddress(guard, value)) break; } return value; diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index 4f4f9b9090..b180991522 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -245,17 +245,22 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector(comparand)) - PowerPC::HostWrite_U8(guard, static_cast(value), addr); + if (!entry.conditional || + PowerPC::MMU::HostRead_U8(guard, addr) == static_cast(comparand)) + { + PowerPC::MMU::HostWrite_U8(guard, static_cast(value), addr); + } break; case PatchType::Patch16Bit: if (!entry.conditional || - PowerPC::HostRead_U16(guard, addr) == static_cast(comparand)) - PowerPC::HostWrite_U16(guard, static_cast(value), addr); + PowerPC::MMU::HostRead_U16(guard, addr) == static_cast(comparand)) + { + PowerPC::MMU::HostWrite_U16(guard, static_cast(value), addr); + } break; case PatchType::Patch32Bit: - if (!entry.conditional || PowerPC::HostRead_U32(guard, addr) == comparand) - PowerPC::HostWrite_U32(guard, value, addr); + if (!entry.conditional || PowerPC::MMU::HostRead_U32(guard, addr) == comparand) + PowerPC::MMU::HostWrite_U32(guard, value, addr); break; default: // unknown patchtype @@ -288,19 +293,19 @@ static bool IsStackValid(const Core::CPUThreadGuard& guard) // Check the stack pointer u32 SP = ppc_state.gpr[1]; - if (!PowerPC::HostIsRAMAddress(guard, SP)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, SP)) return false; // Read the frame pointer from the stack (find 2nd frame from top), assert that it makes sense - u32 next_SP = PowerPC::HostRead_U32(guard, SP); - if (next_SP <= SP || !PowerPC::HostIsRAMAddress(guard, next_SP) || - !PowerPC::HostIsRAMAddress(guard, next_SP + 4)) + u32 next_SP = PowerPC::MMU::HostRead_U32(guard, SP); + if (next_SP <= SP || !PowerPC::MMU::HostIsRAMAddress(guard, next_SP) || + !PowerPC::MMU::HostIsRAMAddress(guard, next_SP + 4)) return false; // Check the link register makes sense (that it points to a valid IBAT address) - const u32 address = PowerPC::HostRead_U32(guard, next_SP + 4); - return PowerPC::HostIsInstructionRAMAddress(guard, address) && - 0 != PowerPC::HostRead_Instruction(guard, address); + const u32 address = PowerPC::MMU::HostRead_U32(guard, next_SP + 4); + return PowerPC::MMU::HostIsInstructionRAMAddress(guard, address) && + 0 != PowerPC::MMU::HostRead_Instruction(guard, address); } void AddMemoryPatch(std::size_t index) diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index a3615afb2e..fd30da2b91 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -280,7 +280,7 @@ void MemChecks::Add(TMemCheck memory_check) // watchpoint-compatible code. if (!had_any) Core::System::GetInstance().GetJitInterface().ClearCache(); - PowerPC::DBATUpdated(); + Core::System::GetInstance().GetMMU().DBATUpdated(); }); } @@ -309,7 +309,7 @@ void MemChecks::Remove(u32 address) m_mem_checks.erase(iter); if (!HasAny()) Core::System::GetInstance().GetJitInterface().ClearCache(); - PowerPC::DBATUpdated(); + Core::System::GetInstance().GetMMU().DBATUpdated(); }); } @@ -318,7 +318,7 @@ void MemChecks::Clear() Core::RunAsCPUThread([&] { m_mem_checks.clear(); Core::System::GetInstance().GetJitInterface().ClearCache(); - PowerPC::DBATUpdated(); + Core::System::GetInstance().GetMMU().DBATUpdated(); }); } diff --git a/Source/Core/Core/PowerPC/Expression.cpp b/Source/Core/Core/PowerPC/Expression.cpp index 597c77c985..bd089e3a01 100644 --- a/Source/Core/Core/PowerPC/Expression.cpp +++ b/Source/Core/Core/PowerPC/Expression.cpp @@ -31,49 +31,49 @@ static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address); template <> u8 HostRead(const Core::CPUThreadGuard& guard, u32 address) { - return PowerPC::HostRead_U8(guard, address); + return PowerPC::MMU::HostRead_U8(guard, address); } template <> u16 HostRead(const Core::CPUThreadGuard& guard, u32 address) { - return PowerPC::HostRead_U16(guard, address); + return PowerPC::MMU::HostRead_U16(guard, address); } template <> u32 HostRead(const Core::CPUThreadGuard& guard, u32 address) { - return PowerPC::HostRead_U32(guard, address); + return PowerPC::MMU::HostRead_U32(guard, address); } template <> u64 HostRead(const Core::CPUThreadGuard& guard, u32 address) { - return PowerPC::HostRead_U64(guard, address); + return PowerPC::MMU::HostRead_U64(guard, address); } template <> void HostWrite(const Core::CPUThreadGuard& guard, u8 var, u32 address) { - PowerPC::HostWrite_U8(guard, var, address); + PowerPC::MMU::HostWrite_U8(guard, var, address); } template <> void HostWrite(const Core::CPUThreadGuard& guard, u16 var, u32 address) { - PowerPC::HostWrite_U16(guard, var, address); + PowerPC::MMU::HostWrite_U16(guard, var, address); } template <> void HostWrite(const Core::CPUThreadGuard& guard, u32 var, u32 address) { - PowerPC::HostWrite_U32(guard, var, address); + PowerPC::MMU::HostWrite_U32(guard, var, address); } template <> void HostWrite(const Core::CPUThreadGuard& guard, u64 var, u32 address) { - PowerPC::HostWrite_U64(guard, var, address); + PowerPC::MMU::HostWrite_U64(guard, var, address); } template @@ -146,7 +146,7 @@ static std::optional ReadStringArg(const Core::CPUThreadGuard& guar if (!std::isnan(num)) { u32 address = static_cast(num); - return PowerPC::HostGetString(guard, address); + return PowerPC::MMU::HostGetString(guard, address); } const char* cstr = expr_get_str(e); diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 94d3e2e060..7a702e7188 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -821,7 +821,7 @@ static void ReadMemory(const Core::CPUThreadGuard& guard) if (len * 2 > sizeof reply) SendReply("E01"); - if (!PowerPC::HostIsRAMAddress(guard, addr)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, addr)) return SendReply("E00"); auto& system = Core::System::GetInstance(); @@ -848,7 +848,7 @@ static void WriteMemory(const Core::CPUThreadGuard& guard) len = (len << 4) | Hex2char(s_cmd_bfr[i++]); INFO_LOG_FMT(GDB_STUB, "gdb: write memory: {:08x} bytes to {:08x}", len, addr); - if (!PowerPC::HostIsRAMAddress(guard, addr)) + if (!PowerPC::MMU::HostIsRAMAddress(guard, addr)) return SendReply("E00"); auto& system = Core::System::GetInstance(); diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 561367eae0..c41635c7e6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -64,8 +64,8 @@ void Interpreter::UpdatePC() m_ppc_state.pc = m_ppc_state.npc; } -Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state) - : m_system(system), m_ppc_state(ppc_state) +Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu) + : m_system(system), m_ppc_state(ppc_state), m_mmu(mmu) { } @@ -124,7 +124,7 @@ int Interpreter::SingleStepInner() } m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction); - m_prev_inst.hex = PowerPC::Read_Opcode(m_ppc_state.pc); + m_prev_inst.hex = m_mmu.Read_Opcode(m_ppc_state.pc); const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst); @@ -316,7 +316,7 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio Core::CPUThreadGuard guard(system); const u32 last_pc = interpreter.m_last_pc; - const u32 opcode = PowerPC::HostRead_U32(guard, last_pc); + const u32 opcode = PowerPC::MMU::HostRead_U32(guard, last_pc); const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc); NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm); Dolphin_Debugger::PrintCallstack(system, guard, Common::Log::LogType::POWERPC, diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter.h index 686557461f..90595de068 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.h @@ -15,13 +15,14 @@ class System; } namespace PowerPC { +class MMU; struct PowerPCState; -} +} // namespace PowerPC class Interpreter : public CPUCoreBase { public: - Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state); + Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu); Interpreter(const Interpreter&) = delete; Interpreter(Interpreter&&) = delete; Interpreter& operator=(const Interpreter&) = delete; @@ -312,6 +313,7 @@ private: Core::System& m_system; PowerPC::PowerPCState& m_ppc_state; + PowerPC::MMU& m_mmu; UGeckoInstruction m_prev_inst{}; u32 m_last_pc = 0; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 73b0c848b1..f046fadb98 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -41,7 +41,7 @@ static u32 Helper_Get_EA_UX(const PowerPC::PowerPCState& ppcs, const UGeckoInstr void Interpreter::lbz(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = PowerPC::Read_U8(Helper_Get_EA(ppc_state, inst)); + const u32 temp = interpreter.m_mmu.Read_U8(Helper_Get_EA(ppc_state, inst)); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) ppc_state.gpr[inst.RD] = temp; @@ -51,7 +51,7 @@ void Interpreter::lbzu(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - const u32 temp = PowerPC::Read_U8(address); + const u32 temp = interpreter.m_mmu.Read_U8(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -71,7 +71,7 @@ void Interpreter::lfd(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u64 temp = PowerPC::Read_U64(address); + const u64 temp = interpreter.m_mmu.Read_U64(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) ppc_state.ps[inst.FD].SetPS0(temp); @@ -88,7 +88,7 @@ void Interpreter::lfdu(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u64 temp = PowerPC::Read_U64(address); + const u64 temp = interpreter.m_mmu.Read_U64(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -108,7 +108,7 @@ void Interpreter::lfdux(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u64 temp = PowerPC::Read_U64(address); + const u64 temp = interpreter.m_mmu.Read_U64(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -128,7 +128,7 @@ void Interpreter::lfdx(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u64 temp = PowerPC::Read_U64(address); + const u64 temp = interpreter.m_mmu.Read_U64(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) ppc_state.ps[inst.FD].SetPS0(temp); @@ -145,7 +145,7 @@ void Interpreter::lfs(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -165,7 +165,7 @@ void Interpreter::lfsu(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -186,7 +186,7 @@ void Interpreter::lfsux(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -207,7 +207,7 @@ void Interpreter::lfsx(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -219,7 +219,7 @@ void Interpreter::lfsx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lha(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = u32(s32(s16(PowerPC::Read_U16(Helper_Get_EA(ppc_state, inst))))); + const u32 temp = u32(s32(s16(interpreter.m_mmu.Read_U16(Helper_Get_EA(ppc_state, inst))))); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -231,7 +231,7 @@ void Interpreter::lhau(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - const u32 temp = u32(s32(s16(PowerPC::Read_U16(address)))); + const u32 temp = u32(s32(s16(interpreter.m_mmu.Read_U16(address)))); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -243,7 +243,7 @@ void Interpreter::lhau(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhz(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = PowerPC::Read_U16(Helper_Get_EA(ppc_state, inst)); + const u32 temp = interpreter.m_mmu.Read_U16(Helper_Get_EA(ppc_state, inst)); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -255,7 +255,7 @@ void Interpreter::lhzu(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - const u32 temp = PowerPC::Read_U16(address); + const u32 temp = interpreter.m_mmu.Read_U16(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -278,7 +278,7 @@ void Interpreter::lmw(Interpreter& interpreter, UGeckoInstruction inst) for (u32 i = inst.RD; i <= 31; i++, address += 4) { - const u32 temp_reg = PowerPC::Read_U32(address); + const u32 temp_reg = interpreter.m_mmu.Read_U32(address); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { @@ -307,7 +307,7 @@ void Interpreter::stmw(Interpreter& interpreter, UGeckoInstruction inst) for (u32 i = inst.RS; i <= 31; i++, address += 4) { - PowerPC::Write_U32(ppc_state.gpr[i], address); + interpreter.m_mmu.Write_U32(ppc_state.gpr[i], address); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { PanicAlertFmt("DSI exception in stmw"); @@ -321,7 +321,7 @@ void Interpreter::lwz(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA(ppc_state, inst); - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -333,7 +333,7 @@ void Interpreter::lwzu(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -345,7 +345,7 @@ void Interpreter::lwzu(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stb(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); + interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); } void Interpreter::stbu(Interpreter& interpreter, UGeckoInstruction inst) @@ -353,7 +353,7 @@ void Interpreter::stbu(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - PowerPC::Write_U8(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -371,7 +371,7 @@ void Interpreter::stfd(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); + interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); } void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst) @@ -385,7 +385,7 @@ void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); + interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -403,7 +403,7 @@ void Interpreter::stfs(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); + interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); } void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst) @@ -417,7 +417,7 @@ void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); + interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -427,7 +427,7 @@ void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::sth(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); + interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); } void Interpreter::sthu(Interpreter& interpreter, UGeckoInstruction inst) @@ -435,7 +435,7 @@ void Interpreter::sthu(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - PowerPC::Write_U16(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -445,7 +445,7 @@ void Interpreter::sthu(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stw(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U32(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst)); } void Interpreter::stwu(Interpreter& interpreter, UGeckoInstruction inst) @@ -453,7 +453,7 @@ void Interpreter::stwu(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_U(ppc_state, inst); - PowerPC::Write_U32(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -478,7 +478,7 @@ void Interpreter::dcbf(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::FlushDCacheLine(address); + interpreter.m_mmu.FlushDCacheLine(address); } void Interpreter::dcbi(Interpreter& interpreter, UGeckoInstruction inst) @@ -500,7 +500,7 @@ void Interpreter::dcbi(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::InvalidateDCacheLine(address); + interpreter.m_mmu.InvalidateDCacheLine(address); } void Interpreter::dcbst(Interpreter& interpreter, UGeckoInstruction inst) @@ -516,7 +516,7 @@ void Interpreter::dcbst(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::StoreDCacheLine(address); + interpreter.m_mmu.StoreDCacheLine(address); } // These instructions hint that it might be optimal to prefetch the specified cache line into the @@ -553,7 +553,7 @@ void Interpreter::dcbz(Interpreter& interpreter, UGeckoInstruction inst) } } - PowerPC::ClearDCacheLine(dcbz_addr & (~31)); + interpreter.m_mmu.ClearDCacheLine(dcbz_addr & (~31)); } void Interpreter::dcbz_l(Interpreter& interpreter, UGeckoInstruction inst) @@ -573,7 +573,7 @@ void Interpreter::dcbz_l(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::ClearDCacheLine(address & (~31)); + interpreter.m_mmu.ClearDCacheLine(address & (~31)); } // eciwx/ecowx technically should access the specified device @@ -595,7 +595,7 @@ void Interpreter::eciwx(Interpreter& interpreter, UGeckoInstruction inst) return; } - ppc_state.gpr[inst.RD] = PowerPC::Read_U32(EA); + ppc_state.gpr[inst.RD] = interpreter.m_mmu.Read_U32(EA); } void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst) @@ -615,7 +615,7 @@ void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ppc_state.gpr[inst.RS], EA); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], EA); } void Interpreter::eieio(Interpreter& interpreter, UGeckoInstruction inst) @@ -638,7 +638,7 @@ void Interpreter::lbzux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - const u32 temp = PowerPC::Read_U8(address); + const u32 temp = interpreter.m_mmu.Read_U8(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -650,7 +650,7 @@ void Interpreter::lbzux(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lbzx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = PowerPC::Read_U8(Helper_Get_EA_X(ppc_state, inst)); + const u32 temp = interpreter.m_mmu.Read_U8(Helper_Get_EA_X(ppc_state, inst)); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -662,7 +662,7 @@ void Interpreter::lhaux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - const s32 temp = s32{s16(PowerPC::Read_U16(address))}; + const s32 temp = s32{s16(interpreter.m_mmu.Read_U16(address))}; if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -674,7 +674,7 @@ void Interpreter::lhaux(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhax(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const s32 temp = s32{s16(PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst)))}; + const s32 temp = s32{s16(interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst)))}; if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -685,7 +685,7 @@ void Interpreter::lhax(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhbrx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = Common::swap16(PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst))); + const u32 temp = Common::swap16(interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst))); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -697,7 +697,7 @@ void Interpreter::lhzux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - const u32 temp = PowerPC::Read_U16(address); + const u32 temp = interpreter.m_mmu.Read_U16(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -709,7 +709,7 @@ void Interpreter::lhzux(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhzx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst)); + const u32 temp = interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst)); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -738,7 +738,7 @@ void Interpreter::lswx(Interpreter& interpreter, UGeckoInstruction inst) if ((n & 0b11) == 0) ppc_state.gpr[reg] = 0; - const u32 temp_value = PowerPC::Read_U8(EA) << (24 - offset); + const u32 temp_value = interpreter.m_mmu.Read_U8(EA) << (24 - offset); // Not64 (Homebrew N64 Emulator for Wii) triggers the following case. if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { @@ -754,7 +754,7 @@ void Interpreter::lswx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lwbrx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - const u32 temp = Common::swap32(PowerPC::Read_U32(Helper_Get_EA_X(ppc_state, inst))); + const u32 temp = Common::swap32(interpreter.m_mmu.Read_U32(Helper_Get_EA_X(ppc_state, inst))); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -766,7 +766,7 @@ void Interpreter::lwzux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -779,7 +779,7 @@ void Interpreter::lwzx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_X(ppc_state, inst); - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -792,7 +792,7 @@ void Interpreter::stbux(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - PowerPC::Write_U8(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -802,7 +802,7 @@ void Interpreter::stbux(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stbx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); + interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); } void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst) @@ -816,7 +816,7 @@ void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); + interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -834,7 +834,7 @@ void Interpreter::stfdx(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); + interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address); } // Stores Floating points into Integers indeXed @@ -849,7 +849,7 @@ void Interpreter::stfiwx(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ppc_state.ps[inst.FS].PS0AsU32(), address); + interpreter.m_mmu.Write_U32(ppc_state.ps[inst.FS].PS0AsU32(), address); } void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst) @@ -863,7 +863,7 @@ void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); + interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -881,13 +881,13 @@ void Interpreter::stfsx(Interpreter& interpreter, UGeckoInstruction inst) return; } - PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); + interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address); } void Interpreter::sthbrx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U16_Swap(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); + interpreter.m_mmu.Write_U16_Swap(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); } void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst) @@ -895,7 +895,7 @@ void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - PowerPC::Write_U16(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -905,7 +905,7 @@ void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::sthx(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; - PowerPC::Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); + interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst)); } // lswi - bizarro string instruction @@ -938,7 +938,7 @@ void Interpreter::lswi(Interpreter& interpreter, UGeckoInstruction inst) ppc_state.gpr[r] = 0; } - const u32 temp_value = PowerPC::Read_U8(EA) << (24 - i); + const u32 temp_value = interpreter.m_mmu.Read_U8(EA) << (24 - i); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { PanicAlertFmt("DSI exception in lsw."); @@ -984,7 +984,7 @@ void Interpreter::stswi(Interpreter& interpreter, UGeckoInstruction inst) r++; r &= 31; } - PowerPC::Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA); + interpreter.m_mmu.Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { return; @@ -1016,7 +1016,7 @@ void Interpreter::stswx(Interpreter& interpreter, UGeckoInstruction inst) while (n > 0) { - PowerPC::Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA); + interpreter.m_mmu.Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA); EA++; n--; @@ -1034,7 +1034,7 @@ void Interpreter::stwbrx(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_X(ppc_state, inst); - PowerPC::Write_U32_Swap(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U32_Swap(ppc_state.gpr[inst.RS], address); } // The following two instructions are for SMP communications. On a single @@ -1051,7 +1051,7 @@ void Interpreter::lwarx(Interpreter& interpreter, UGeckoInstruction inst) return; } - const u32 temp = PowerPC::Read_U32(address); + const u32 temp = interpreter.m_mmu.Read_U32(address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { @@ -1077,7 +1077,7 @@ void Interpreter::stwcxd(Interpreter& interpreter, UGeckoInstruction inst) { if (address == ppc_state.reserve_address) { - PowerPC::Write_U32(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.reserve = false; @@ -1095,7 +1095,7 @@ void Interpreter::stwux(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_UX(ppc_state, inst); - PowerPC::Write_U32(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address); if (!(ppc_state.Exceptions & EXCEPTION_DSI)) { ppc_state.gpr[inst.RA] = address; @@ -1107,7 +1107,7 @@ void Interpreter::stwx(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 address = Helper_Get_EA_X(ppc_state, inst); - PowerPC::Write_U32(ppc_state.gpr[inst.RS], address); + interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address); } void Interpreter::sync(Interpreter& interpreter, UGeckoInstruction inst) @@ -1127,7 +1127,7 @@ void Interpreter::tlbie(Interpreter& interpreter, UGeckoInstruction inst) // Invalidate TLB entry const u32 address = ppc_state.gpr[inst.RB]; - PowerPC::InvalidateTLBEntry(address); + interpreter.m_mmu.InvalidateTLBEntry(address); } void Interpreter::tlbsync(Interpreter& interpreter, UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp index 11e0cc178c..29f0561033 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp @@ -16,6 +16,7 @@ #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" // dequantize table const float m_dequantizeTable[] = { @@ -68,111 +69,111 @@ SType ScaleAndClamp(double ps, u32 st_scale) } template -static T ReadUnpaired(u32 addr); +static T ReadUnpaired(PowerPC::MMU& mmu, u32 addr); template <> -u8 ReadUnpaired(u32 addr) +u8 ReadUnpaired(PowerPC::MMU& mmu, u32 addr) { - return PowerPC::Read_U8(addr); + return mmu.Read_U8(addr); } template <> -u16 ReadUnpaired(u32 addr) +u16 ReadUnpaired(PowerPC::MMU& mmu, u32 addr) { - return PowerPC::Read_U16(addr); + return mmu.Read_U16(addr); } template <> -u32 ReadUnpaired(u32 addr) +u32 ReadUnpaired(PowerPC::MMU& mmu, u32 addr) { - return PowerPC::Read_U32(addr); + return mmu.Read_U32(addr); } template -static std::pair ReadPair(u32 addr); +static std::pair ReadPair(PowerPC::MMU& mmu, u32 addr); template <> -std::pair ReadPair(u32 addr) +std::pair ReadPair(PowerPC::MMU& mmu, u32 addr) { - const u16 val = PowerPC::Read_U16(addr); + const u16 val = mmu.Read_U16(addr); return {u8(val >> 8), u8(val)}; } template <> -std::pair ReadPair(u32 addr) +std::pair ReadPair(PowerPC::MMU& mmu, u32 addr) { - const u32 val = PowerPC::Read_U32(addr); + const u32 val = mmu.Read_U32(addr); return {u16(val >> 16), u16(val)}; } template <> -std::pair ReadPair(u32 addr) +std::pair ReadPair(PowerPC::MMU& mmu, u32 addr) { - const u64 val = PowerPC::Read_U64(addr); + const u64 val = mmu.Read_U64(addr); return {u32(val >> 32), u32(val)}; } template -static void WriteUnpaired(T val, u32 addr); +static void WriteUnpaired(PowerPC::MMU& mmu, T val, u32 addr); template <> -void WriteUnpaired(u8 val, u32 addr) +void WriteUnpaired(PowerPC::MMU& mmu, u8 val, u32 addr) { - PowerPC::Write_U8(val, addr); + mmu.Write_U8(val, addr); } template <> -void WriteUnpaired(u16 val, u32 addr) +void WriteUnpaired(PowerPC::MMU& mmu, u16 val, u32 addr) { - PowerPC::Write_U16(val, addr); + mmu.Write_U16(val, addr); } template <> -void WriteUnpaired(u32 val, u32 addr) +void WriteUnpaired(PowerPC::MMU& mmu, u32 val, u32 addr) { - PowerPC::Write_U32(val, addr); + mmu.Write_U32(val, addr); } template -static void WritePair(T val1, T val2, u32 addr); +static void WritePair(PowerPC::MMU& mmu, T val1, T val2, u32 addr); template <> -void WritePair(u8 val1, u8 val2, u32 addr) +void WritePair(PowerPC::MMU& mmu, u8 val1, u8 val2, u32 addr) { - PowerPC::Write_U16((u16{val1} << 8) | u16{val2}, addr); + mmu.Write_U16((u16{val1} << 8) | u16{val2}, addr); } template <> -void WritePair(u16 val1, u16 val2, u32 addr) +void WritePair(PowerPC::MMU& mmu, u16 val1, u16 val2, u32 addr) { - PowerPC::Write_U32((u32{val1} << 16) | u32{val2}, addr); + mmu.Write_U32((u32{val1} << 16) | u32{val2}, addr); } template <> -void WritePair(u32 val1, u32 val2, u32 addr) +void WritePair(PowerPC::MMU& mmu, u32 val1, u32 val2, u32 addr) { - PowerPC::Write_U64((u64{val1} << 32) | u64{val2}, addr); + mmu.Write_U64((u64{val1} << 32) | u64{val2}, addr); } template -void QuantizeAndStore(double ps0, double ps1, u32 addr, u32 instW, u32 st_scale) +void QuantizeAndStore(PowerPC::MMU& mmu, double ps0, double ps1, u32 addr, u32 instW, u32 st_scale) { using U = std::make_unsigned_t; const U conv_ps0 = U(ScaleAndClamp(ps0, st_scale)); if (instW) { - WriteUnpaired(conv_ps0, addr); + WriteUnpaired(mmu, conv_ps0, addr); } else { const U conv_ps1 = U(ScaleAndClamp(ps1, st_scale)); - WritePair(conv_ps0, conv_ps1, addr); + WritePair(mmu, conv_ps0, conv_ps1, addr); } } -static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRS, - u32 instW) +static void Helper_Quantize(PowerPC::MMU& mmu, const PowerPC::PowerPCState* ppcs, u32 addr, + u32 instI, u32 instRS, u32 instW) { const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]); const EQuantizeType st_type = gqr.st_type; @@ -190,32 +191,32 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins if (instW != 0) { - WriteUnpaired(conv_ps0, addr); + WriteUnpaired(mmu, conv_ps0, addr); } else { const u64 integral_ps1 = Common::BitCast(ps1); const u32 conv_ps1 = ConvertToSingleFTZ(integral_ps1); - WritePair(conv_ps0, conv_ps1, addr); + WritePair(mmu, conv_ps0, conv_ps1, addr); } break; } case QUANTIZE_U8: - QuantizeAndStore(ps0, ps1, addr, instW, st_scale); + QuantizeAndStore(mmu, ps0, ps1, addr, instW, st_scale); break; case QUANTIZE_U16: - QuantizeAndStore(ps0, ps1, addr, instW, st_scale); + QuantizeAndStore(mmu, ps0, ps1, addr, instW, st_scale); break; case QUANTIZE_S8: - QuantizeAndStore(ps0, ps1, addr, instW, st_scale); + QuantizeAndStore(mmu, ps0, ps1, addr, instW, st_scale); break; case QUANTIZE_S16: - QuantizeAndStore(ps0, ps1, addr, instW, st_scale); + QuantizeAndStore(mmu, ps0, ps1, addr, instW, st_scale); break; case QUANTIZE_INVALID1: @@ -227,20 +228,20 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins } template -std::pair LoadAndDequantize(u32 addr, u32 instW, u32 ld_scale) +std::pair LoadAndDequantize(PowerPC::MMU& mmu, u32 addr, u32 instW, u32 ld_scale) { using U = std::make_unsigned_t; float ps0, ps1; if (instW != 0) { - const U value = ReadUnpaired(addr); + const U value = ReadUnpaired(mmu, addr); ps0 = float(T(value)) * m_dequantizeTable[ld_scale]; ps1 = 1.0f; } else { - const auto [first, second] = ReadPair(addr); + const auto [first, second] = ReadPair(mmu, addr); ps0 = float(T(first)) * m_dequantizeTable[ld_scale]; ps1 = float(T(second)) * m_dequantizeTable[ld_scale]; } @@ -248,8 +249,8 @@ std::pair LoadAndDequantize(u32 addr, u32 instW, u32 ld_scale) return {static_cast(ps0), static_cast(ps1)}; } -static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRD, - u32 instW) +static void Helper_Dequantize(PowerPC::MMU& mmu, PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, + u32 instRD, u32 instW) { const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]); const EQuantizeType ld_type = gqr.ld_type; @@ -263,32 +264,32 @@ static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, case QUANTIZE_FLOAT: if (instW != 0) { - const u32 value = ReadUnpaired(addr); + const u32 value = ReadUnpaired(mmu, addr); ps0 = Common::BitCast(ConvertToDouble(value)); ps1 = 1.0; } else { - const auto [first, second] = ReadPair(addr); + const auto [first, second] = ReadPair(mmu, addr); ps0 = Common::BitCast(ConvertToDouble(first)); ps1 = Common::BitCast(ConvertToDouble(second)); } break; case QUANTIZE_U8: - std::tie(ps0, ps1) = LoadAndDequantize(addr, instW, ld_scale); + std::tie(ps0, ps1) = LoadAndDequantize(mmu, addr, instW, ld_scale); break; case QUANTIZE_U16: - std::tie(ps0, ps1) = LoadAndDequantize(addr, instW, ld_scale); + std::tie(ps0, ps1) = LoadAndDequantize(mmu, addr, instW, ld_scale); break; case QUANTIZE_S8: - std::tie(ps0, ps1) = LoadAndDequantize(addr, instW, ld_scale); + std::tie(ps0, ps1) = LoadAndDequantize(mmu, addr, instW, ld_scale); break; case QUANTIZE_S16: - std::tie(ps0, ps1) = LoadAndDequantize(addr, instW, ld_scale); + std::tie(ps0, ps1) = LoadAndDequantize(mmu, addr, instW, ld_scale); break; case QUANTIZE_INVALID1: @@ -318,7 +319,7 @@ void Interpreter::psq_l(Interpreter& interpreter, UGeckoInstruction inst) } const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12); - Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W); + Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W); } void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst) @@ -331,7 +332,7 @@ void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst) } const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12); - Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W); + Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { @@ -351,7 +352,7 @@ void Interpreter::psq_st(Interpreter& interpreter, UGeckoInstruction inst) } const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12); - Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W); + Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W); } void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst) @@ -364,7 +365,7 @@ void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst) } const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12); - Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W); + Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { @@ -379,7 +380,7 @@ void Interpreter::psq_lx(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB]; - Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx); + Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx); } void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst) @@ -387,14 +388,14 @@ void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB]; - Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx); + Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx); } void Interpreter::psq_lux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]; - Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx); + Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { @@ -408,7 +409,7 @@ void Interpreter::psq_stux(Interpreter& interpreter, UGeckoInstruction inst) { auto& ppc_state = interpreter.m_ppc_state; const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]; - Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx); + Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx); if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) { diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 91c66e08db..88314990da 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -379,8 +379,8 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst) if (old_value != ppc_state.spr[index]) { INFO_LOG_FMT(POWERPC, "HID4 updated {:x} {:x}", old_value, ppc_state.spr[index]); - PowerPC::IBATUpdated(); - PowerPC::DBATUpdated(); + interpreter.m_mmu.IBATUpdated(); + interpreter.m_mmu.DBATUpdated(); } break; @@ -414,9 +414,9 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst) if (length == 0) length = 128; if (DMAL(ppc_state).DMA_LD) - PowerPC::DMA_MemoryToLC(cache_address, mem_address, length); + interpreter.m_mmu.DMA_MemoryToLC(cache_address, mem_address, length); else - PowerPC::DMA_LCToMemory(mem_address, cache_address, length); + interpreter.m_mmu.DMA_LCToMemory(mem_address, cache_address, length); } DMAL(ppc_state).DMA_T = 0; break; @@ -436,7 +436,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst) // Page table base etc case SPR_SDR: - PowerPC::SDRUpdated(); + interpreter.m_mmu.SDRUpdated(); break; case SPR_XER: @@ -462,7 +462,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst) if (old_value != ppc_state.spr[index]) { INFO_LOG_FMT(POWERPC, "DBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]); - PowerPC::DBATUpdated(); + interpreter.m_mmu.DBATUpdated(); } break; @@ -485,7 +485,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst) if (old_value != ppc_state.spr[index]) { INFO_LOG_FMT(POWERPC, "IBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]); - PowerPC::IBATUpdated(); + interpreter.m_mmu.IBATUpdated(); } break; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 7783f58c78..145a2c9d7e 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -1183,8 +1183,8 @@ void Jit64::IntializeSpeculativeConstants() for (auto i : code_block.m_gpr_inputs) { u32 compileTimeValue = m_ppc_state.gpr[i]; - if (PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue) || - PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) || + if (m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue) || + m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) || compileTimeValue == 0xCC000000) { if (!target) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index ca287c80cc..65ac5dab21 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -324,7 +324,7 @@ void Jit64::dcbx(UGeckoInstruction inst) if (m_ppc_state.msr.IR) { // Translate effective address to physical address. - bat_lookup_failed = BATAddressLookup(addr, tmp, PowerPC::ibat_table.data()); + bat_lookup_failed = BATAddressLookup(addr, tmp, m_jit.m_mmu.GetIBATTable().data()); MOV(32, R(tmp), R(effective_address)); AND(32, R(tmp), Imm32(0x0001ffff)); AND(32, R(addr), Imm32(0xfffe0000)); @@ -430,7 +430,7 @@ void Jit64::dcbz(UGeckoInstruction inst) if (emit_fast_path) { // Perform lookup to see if we can use fast path. - MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0])); + MOV(64, R(RSCRATCH2), ImmPtr(m_mmu.GetDBATTable().data())); PUSH(RSCRATCH); SHR(32, R(RSCRATCH), Imm8(PowerPC::BAT_INDEX_SHIFT)); TEST(32, MComplex(RSCRATCH2, RSCRATCH, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT)); @@ -449,7 +449,7 @@ void Jit64::dcbz(UGeckoInstruction inst) MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); BitSet32 registersInUse = CallerSavedRegistersInUse(); ABI_PushRegistersAndAdjustStack(registersInUse, 0); - ABI_CallFunctionR(PowerPC::ClearDCacheLine, RSCRATCH); + ABI_CallFunctionPR(PowerPC::ClearDCacheLineFromJit64, &m_mmu, RSCRATCH); ABI_PopRegistersAndAdjustStack(registersInUse, 0); if (emit_fast_path) diff --git a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp index d767454b14..006e3d6227 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp @@ -119,7 +119,7 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_ MOV(32, R(RSCRATCH_EXTRA), R(reg_addr)); // Perform lookup to see if we can use fast path. - MOV(64, R(RSCRATCH), ImmPtr(&PowerPC::dbat_table[0])); + MOV(64, R(RSCRATCH), ImmPtr(m_jit.m_mmu.GetDBATTable().data())); SHR(32, R(RSCRATCH_EXTRA), Imm8(PowerPC::BAT_INDEX_SHIFT)); TEST(32, MComplex(RSCRATCH, RSCRATCH_EXTRA, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT)); @@ -396,16 +396,16 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, switch (accessSize) { case 64: - ABI_CallFunctionR(PowerPC::Read_U64, reg_addr); + ABI_CallFunctionPR(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, reg_addr); break; case 32: - ABI_CallFunctionR(PowerPC::Read_U32, reg_addr); + ABI_CallFunctionPR(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, reg_addr); break; case 16: - ABI_CallFunctionR(PowerPC::Read_U16_ZX, reg_addr); + ABI_CallFunctionPR(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, reg_addr); break; case 8: - ABI_CallFunctionR(PowerPC::Read_U8_ZX, reg_addr); + ABI_CallFunctionPR(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, reg_addr); break; } ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment); @@ -436,14 +436,14 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc BitSet32 registersInUse, bool signExtend) { // If the address is known to be RAM, just load it directly. - if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address)) + if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address)) { UnsafeLoadToReg(reg_value, Imm32(address), accessSize, 0, signExtend); return; } // If the address maps to an MMIO register, inline MMIO read code. - u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize); + u32 mmioAddress = m_jit.m_mmu.IsOptimizableMMIOAccess(address, accessSize); if (accessSize != 64 && mmioAddress) { auto& memory = m_jit.m_system.GetMemory(); @@ -460,16 +460,16 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc switch (accessSize) { case 64: - ABI_CallFunctionC(PowerPC::Read_U64, address); + ABI_CallFunctionPC(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, address); break; case 32: - ABI_CallFunctionC(PowerPC::Read_U32, address); + ABI_CallFunctionPC(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, address); break; case 16: - ABI_CallFunctionC(PowerPC::Read_U16_ZX, address); + ABI_CallFunctionPC(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, address); break; case 8: - ABI_CallFunctionC(PowerPC::Read_U8_ZX, address); + ABI_CallFunctionPC(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, address); break; } ABI_PopRegistersAndAdjustStack(registersInUse, 0); @@ -578,16 +578,19 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces switch (accessSize) { case 64: - ABI_CallFunctionRR(swap ? PowerPC::Write_U64 : PowerPC::Write_U64_Swap, reg, reg_addr); + ABI_CallFunctionPRR(swap ? PowerPC::WriteU64FromJit64 : PowerPC::WriteU64SwapFromJit64, + &m_jit.m_mmu, reg, reg_addr); break; case 32: - ABI_CallFunctionRR(swap ? PowerPC::Write_U32 : PowerPC::Write_U32_Swap, reg, reg_addr); + ABI_CallFunctionPRR(swap ? PowerPC::WriteU32FromJit64 : PowerPC::WriteU32SwapFromJit64, + &m_jit.m_mmu, reg, reg_addr); break; case 16: - ABI_CallFunctionRR(swap ? PowerPC::Write_U16 : PowerPC::Write_U16_Swap, reg, reg_addr); + ABI_CallFunctionPRR(swap ? PowerPC::WriteU16FromJit64 : PowerPC::WriteU16SwapFromJit64, + &m_jit.m_mmu, reg, reg_addr); break; case 8: - ABI_CallFunctionRR(PowerPC::Write_U8, reg, reg_addr); + ABI_CallFunctionPRR(PowerPC::WriteU8FromJit64, &m_jit.m_mmu, reg, reg_addr); break; } ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment); @@ -623,7 +626,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address, // If we already know the address through constant folding, we can do some // fun tricks... - if (m_jit.jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(address)) + if (m_jit.jo.optimizeGatherPipe && m_jit.m_mmu.IsOptimizableGatherPipeWrite(address)) { X64Reg arg_reg = RSCRATCH; @@ -643,7 +646,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address, m_jit.js.fifoBytesSinceCheck += accessSize >> 3; return false; } - else if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address)) + else if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address)) { WriteToConstRamAddress(accessSize, arg, address); return false; @@ -657,16 +660,16 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address, switch (accessSize) { case 64: - ABI_CallFunctionAC(64, PowerPC::Write_U64, arg, address); + ABI_CallFunctionPAC(64, PowerPC::WriteU64FromJit64, &m_jit.m_mmu, arg, address); break; case 32: - ABI_CallFunctionAC(32, PowerPC::Write_U32, arg, address); + ABI_CallFunctionPAC(32, PowerPC::WriteU32FromJit64, &m_jit.m_mmu, arg, address); break; case 16: - ABI_CallFunctionAC(16, PowerPC::Write_U16, arg, address); + ABI_CallFunctionPAC(16, PowerPC::WriteU16FromJit64, &m_jit.m_mmu, arg, address); break; case 8: - ABI_CallFunctionAC(8, PowerPC::Write_U8, arg, address); + ABI_CallFunctionPAC(8, PowerPC::WriteU8FromJit64, &m_jit.m_mmu, arg, address); break; } ABI_PopRegistersAndAdjustStack(registersInUse, 0); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 7e0735f85d..ce01d560e2 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -317,8 +317,8 @@ void JitArm64::IntializeSpeculativeConstants() for (auto i : code_block.m_gpr_inputs) { u32 compile_time_value = m_ppc_state.gpr[i]; - if (PowerPC::IsOptimizableGatherPipeWrite(compile_time_value) || - PowerPC::IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) || + if (m_mmu.IsOptimizableGatherPipeWrite(compile_time_value) || + m_mmu.IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) || compile_time_value == 0xCC000000) { if (!fail) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp index 3d34afab4d..8e14e694c4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp @@ -216,32 +216,48 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS, const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0; + MOVP2R(ARM64Reg::X2, &m_mmu); + if (access_size == 64) - MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U64_Swap : &PowerPC::Write_U64); + { + MOVP2R(ARM64Reg::X8, + reverse ? &PowerPC::WriteU64SwapFromJitArm64 : &PowerPC::WriteU64FromJitArm64); + } else if (access_size == 32) - MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U32_Swap : &PowerPC::Write_U32); + { + MOVP2R(ARM64Reg::X8, + reverse ? &PowerPC::WriteU32SwapFromJitArm64 : &PowerPC::WriteU32FromJitArm64); + } else if (access_size == 16) - MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U16_Swap : &PowerPC::Write_U16); + { + MOVP2R(ARM64Reg::X8, + reverse ? &PowerPC::WriteU16SwapFromJitArm64 : &PowerPC::WriteU16FromJitArm64); + } else - MOVP2R(ARM64Reg::X8, &PowerPC::Write_U8); + { + MOVP2R(ARM64Reg::X8, &PowerPC::WriteU8FromJitArm64); + } BLR(ARM64Reg::X8); } else if (flags & BackPatchInfo::FLAG_ZERO_256) { - MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLine); + MOVP2R(ARM64Reg::X1, &m_mmu); + MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLineFromJitArm64); BLR(ARM64Reg::X8); } else { + MOVP2R(ARM64Reg::X1, &m_mmu); + if (access_size == 64) - MOVP2R(ARM64Reg::X8, &PowerPC::Read_U64); + MOVP2R(ARM64Reg::X8, &PowerPC::ReadU64FromJitArm64); else if (access_size == 32) - MOVP2R(ARM64Reg::X8, &PowerPC::Read_U32); + MOVP2R(ARM64Reg::X8, &PowerPC::ReadU32FromJitArm64); else if (access_size == 16) - MOVP2R(ARM64Reg::X8, &PowerPC::Read_U16); + MOVP2R(ARM64Reg::X8, &PowerPC::ReadU16FromJitArm64); else - MOVP2R(ARM64Reg::X8, &PowerPC::Read_U8); + MOVP2R(ARM64Reg::X8, &PowerPC::ReadU8FromJitArm64); BLR(ARM64Reg::X8); } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index d3f920b588..9bc573ddd5 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -132,9 +132,9 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o u32 access_size = BackPatchInfo::GetFlagSize(flags); u32 mmio_address = 0; if (is_immediate) - mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size); + mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size); - if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) + if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr)) { set_addr_reg_if_needed(); EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, dest_reg, XA, regs_in_use, @@ -278,9 +278,9 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s u32 access_size = BackPatchInfo::GetFlagSize(flags); u32 mmio_address = 0; if (is_immediate) - mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size); + mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size); - if (is_immediate && jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr)) + if (is_immediate && jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr)) { int accessSize; if (flags & BackPatchInfo::FLAG_SIZE_32) @@ -306,7 +306,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s js.fifoBytesSinceCheck += accessSize >> 3; } - else if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) + else if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr)) { set_addr_reg_if_needed(); EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, RS, XA, regs_in_use, fprs_in_use); @@ -358,7 +358,7 @@ FixupBranch JitArm64::CheckIfSafeAddress(Arm64Gen::ARM64Reg addr, Arm64Gen::ARM6 { tmp2 = EncodeRegTo64(tmp2); - MOVP2R(tmp2, PowerPC::dbat_table.data()); + MOVP2R(tmp2, m_mmu.GetDBATTable().data()); LSR(tmp1, addr, PowerPC::BAT_INDEX_SHIFT); LDR(tmp1, tmp2, ArithOption(tmp1, true)); FixupBranch pass = TBNZ(tmp1, IntLog2(PowerPC::BAT_PHYSICAL_BIT)); @@ -730,7 +730,7 @@ void JitArm64::dcbx(UGeckoInstruction inst) if (m_ppc_state.msr.IR) { bat_lookup_failed = - BATAddressLookup(physical_addr, effective_addr, WA, PowerPC::ibat_table.data()); + BATAddressLookup(physical_addr, effective_addr, WA, m_mmu.GetIBATTable().data()); BFI(physical_addr, effective_addr, 0, PowerPC::BAT_INDEX_SHIFT); } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp index 281593d4a7..f83a6bf71d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp @@ -174,7 +174,7 @@ void JitArm64::lfXX(UGeckoInstruction inst) if (!jo.memcheck) fprs_in_use[DecodeReg(VD)] = 0; - if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) + if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr)) { EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, VD, XA, regs_in_use, fprs_in_use); } @@ -378,7 +378,7 @@ void JitArm64::stfXX(UGeckoInstruction inst) if (is_immediate) { - if (jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr)) + if (jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr)) { int accessSize; if (flags & BackPatchInfo::FLAG_SIZE_64) @@ -399,7 +399,7 @@ void JitArm64::stfXX(UGeckoInstruction inst) STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr)); js.fifoBytesSinceCheck += accessSize >> 3; } - else if (PowerPC::IsOptimizableRAMAddress(imm_addr)) + else if (m_mmu.IsOptimizableRAMAddress(imm_addr)) { set_addr_reg_if_needed(); EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, V0, XA, regs_in_use, fprs_in_use); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index 7717751747..d0c32c743b 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -61,7 +61,8 @@ void JitTrampoline(JitBase& jit, u32 em_address) } JitBase::JitBase(Core::System& system) - : m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()) + : m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()), + m_mmu(system.GetMMU()) { m_registered_config_callback_id = Config::AddConfigChangedCallback( [this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); }); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index 44a76dd451..fe9c7341b8 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -198,6 +198,7 @@ public: Core::System& m_system; PowerPC::PowerPCState& m_ppc_state; + PowerPC::MMU& m_mmu; }; void JitTrampoline(JitBase& jit, u32 em_address); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 56e8d95534..2718dc3921 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -92,7 +92,7 @@ void JitBaseBlockCache::RunOnBlocks(std::function f) JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address) { - const u32 physical_address = PowerPC::JitCache_TranslateAddress(em_address).address; + const u32 physical_address = m_jit.m_mmu.JitCache_TranslateAddress(em_address).address; JitBlock& b = block_map.emplace(physical_address, JitBlock())->second; b.effectiveAddress = em_address; b.physicalAddress = physical_address; @@ -147,7 +147,7 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr) u32 translated_addr = addr; if (UReg_MSR(msr).IR) { - auto translated = PowerPC::JitCache_TranslateAddress(addr); + auto translated = m_jit.m_mmu.JitCache_TranslateAddress(addr); if (!translated.valid) { return nullptr; @@ -186,7 +186,7 @@ const u8* JitBaseBlockCache::Dispatch() void JitBaseBlockCache::InvalidateICacheLine(u32 address) { const u32 cache_line_address = address & ~0x1f; - const auto translated = PowerPC::JitCache_TranslateAddress(cache_line_address); + const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(cache_line_address); if (translated.valid) InvalidateICacheInternal(translated.address, cache_line_address, 32, false); } @@ -197,7 +197,7 @@ void JitBaseBlockCache::InvalidateICache(u32 initial_address, u32 initial_length u32 length = initial_length; while (length > 0) { - const auto translated = PowerPC::JitCache_TranslateAddress(address); + const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(address); const bool address_from_bat = translated.valid && translated.translated && translated.from_bat; const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT; diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index beec9559e6..c2875ec82e 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -297,7 +297,7 @@ void JitInterface::CompileExceptionCheck(ExceptionType type) // Check in case the code has been replaced since: do we need to do this? const OpType optype = - PPCTables::GetOpInfo(PowerPC::HostRead_U32(guard, PowerPC::ppcState.pc))->type; + PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, PowerPC::ppcState.pc))->type; if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS) return; } diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 5a255c1c22..92786beec6 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -52,41 +52,39 @@ namespace PowerPC { +MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state) + : m_system(system), m_memory(memory), m_ppc_state(ppc_state) +{ +} + +MMU::~MMU() = default; + // Overloaded byteswap functions, for use within the templated functions below. -inline u8 bswap(u8 val) +[[maybe_unused]] static u8 bswap(u8 val) { return val; } -inline s8 bswap(s8 val) +[[maybe_unused]] static s8 bswap(s8 val) { return val; } -inline u16 bswap(u16 val) +[[maybe_unused]] static u16 bswap(u16 val) { return Common::swap16(val); } -inline s16 bswap(s16 val) +[[maybe_unused]] static s16 bswap(s16 val) { return Common::swap16(val); } -inline u32 bswap(u32 val) +[[maybe_unused]] static u32 bswap(u32 val) { return Common::swap32(val); } -inline u64 bswap(u64 val) +[[maybe_unused]] static u64 bswap(u64 val) { return Common::swap64(val); } -enum class XCheckTLBFlag -{ - NoException, - Read, - Write, - Opcode, - OpcodeNoException -}; - static bool IsOpcodeFlag(XCheckTLBFlag flag) { return flag == XCheckTLBFlag::Opcode || flag == XCheckTLBFlag::OpcodeNoException; @@ -97,29 +95,6 @@ static bool IsNoExceptionFlag(XCheckTLBFlag flag) return flag == XCheckTLBFlag::NoException || flag == XCheckTLBFlag::OpcodeNoException; } -enum class TranslateAddressResultEnum : u8 -{ - BAT_TRANSLATED, - PAGE_TABLE_TRANSLATED, - DIRECT_STORE_SEGMENT, - PAGE_FAULT, -}; - -struct TranslateAddressResult -{ - u32 address; - TranslateAddressResultEnum result; - bool wi; // Set to true if the view of memory is either write-through or cache-inhibited - - TranslateAddressResult(TranslateAddressResultEnum result_, u32 address_, bool wi_ = false) - : address(address_), result(result_), wi(wi_) - { - } - bool Success() const { return result <= TranslateAddressResultEnum::PAGE_TABLE_TRANSLATED; } -}; -template -static TranslateAddressResult TranslateAddress(u32 address); - // Nasty but necessary. Super Mario Galaxy pointer relies on this stuff. static u32 EFB_Read(const u32 addr) { @@ -170,13 +145,8 @@ static void EFB_Write(u32 data, u32 addr) } } -BatTable ibat_table; -BatTable dbat_table; - -static void GenerateDSIException(u32 effective_address, bool write); - -template -static T ReadFromHardware(Core::System& system, Memory::MemoryManager& memory, u32 em_address) +template +T MMU::ReadFromHardware(u32 em_address) { const u32 em_address_start_page = em_address & ~HW_PAGE_MASK; const u32 em_address_end_page = (em_address + sizeof(T) - 1) & ~HW_PAGE_MASK; @@ -189,15 +159,14 @@ static T ReadFromHardware(Core::System& system, Memory::MemoryManager& memory, u u64 var = 0; for (u32 i = 0; i < sizeof(T); ++i) { - var = - (var << 8) | ReadFromHardware(system, memory, em_address + i); + var = (var << 8) | ReadFromHardware(em_address + i); } return static_cast(var); } bool wi = false; - if (!never_translate && PowerPC::ppcState.msr.DR) + if (!never_translate && m_ppc_state.msr.DR) { auto translated_addr = TranslateAddress(em_address); if (!translated_addr.Success()) @@ -215,52 +184,52 @@ static T ReadFromHardware(Core::System& system, Memory::MemoryManager& memory, u if (em_address < 0x0c000000) return EFB_Read(em_address); else - return static_cast(memory.GetMMIOMapping()->Read>(em_address)); + return static_cast(m_memory.GetMMIOMapping()->Read>(em_address)); } // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. - if (memory.GetL1Cache() && (em_address >> 28) == 0xE && - (em_address < (0xE0000000 + memory.GetL1CacheSize()))) + if (m_memory.GetL1Cache() && (em_address >> 28) == 0xE && + (em_address < (0xE0000000 + m_memory.GetL1CacheSize()))) { T value; - std::memcpy(&value, &memory.GetL1Cache()[em_address & 0x0FFFFFFF], sizeof(T)); + std::memcpy(&value, &m_memory.GetL1Cache()[em_address & 0x0FFFFFFF], sizeof(T)); return bswap(value); } - if (memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000) + if (m_memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000) { // Handle RAM; the masking intentionally discards bits (essentially creating // mirrors of memory). T value; - em_address &= memory.GetRamMask(); + em_address &= m_memory.GetRamMask(); - if (!ppcState.m_enable_dcache || wi) + if (!m_ppc_state.m_enable_dcache || wi) { - std::memcpy(&value, &memory.GetRAM()[em_address], sizeof(T)); + std::memcpy(&value, &m_memory.GetRAM()[em_address], sizeof(T)); } else { - ppcState.dCache.Read(em_address, &value, sizeof(T), - HID0(PowerPC::ppcState).DLOCK || flag != XCheckTLBFlag::Read); + m_ppc_state.dCache.Read(em_address, &value, sizeof(T), + HID0(m_ppc_state).DLOCK || flag != XCheckTLBFlag::Read); } return bswap(value); } - if (memory.GetEXRAM() && (em_address >> 28) == 0x1 && - (em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal()) + if (m_memory.GetEXRAM() && (em_address >> 28) == 0x1 && + (em_address & 0x0FFFFFFF) < m_memory.GetExRamSizeReal()) { T value; em_address &= 0x0FFFFFFF; - if (!ppcState.m_enable_dcache || wi) + if (!m_ppc_state.m_enable_dcache || wi) { - std::memcpy(&value, &memory.GetEXRAM()[em_address], sizeof(T)); + std::memcpy(&value, &m_memory.GetEXRAM()[em_address], sizeof(T)); } else { - ppcState.dCache.Read(em_address + 0x10000000, &value, sizeof(T), - HID0(PowerPC::ppcState).DLOCK || flag != XCheckTLBFlag::Read); + m_ppc_state.dCache.Read(em_address + 0x10000000, &value, sizeof(T), + HID0(m_ppc_state).DLOCK || flag != XCheckTLBFlag::Read); } return bswap(value); @@ -269,25 +238,25 @@ static T ReadFromHardware(Core::System& system, Memory::MemoryManager& memory, u // In Fake-VMEM mode, we need to map the memory somewhere into // physical memory for BAT translation to work; we currently use // [0x7E000000, 0x80000000). - if (memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000)) + if (m_memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000)) { T value; - std::memcpy(&value, &memory.GetFakeVMEM()[em_address & memory.GetFakeVMemMask()], sizeof(T)); + std::memcpy(&value, &m_memory.GetFakeVMEM()[em_address & m_memory.GetFakeVMemMask()], + sizeof(T)); return bswap(value); } - PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, PowerPC::ppcState.pc); - if (system.IsPauseOnPanicMode()) + PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, m_ppc_state.pc); + if (m_system.IsPauseOnPanicMode()) { - system.GetCPU().Break(); - ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + m_system.GetCPU().Break(); + m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; } return 0; } -template -static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, u32 em_address, - const u32 data, const u32 size) +template +void MMU::WriteToHardware(u32 em_address, const u32 data, const u32 size) { DEBUG_ASSERT(size <= 4); @@ -300,16 +269,15 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, // Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned! const u32 first_half_size = em_address_end_page - em_address; const u32 second_half_size = size - first_half_size; - WriteToHardware(system, memory, em_address, - std::rotr(data, second_half_size * 8), first_half_size); - WriteToHardware(system, memory, em_address_end_page, data, - second_half_size); + WriteToHardware(em_address, std::rotr(data, second_half_size * 8), + first_half_size); + WriteToHardware(em_address_end_page, data, second_half_size); return; } bool wi = false; - if (!never_translate && PowerPC::ppcState.msr.DR) + if (!never_translate && m_ppc_state.msr.DR) { auto translated_addr = TranslateAddress(em_address); if (!translated_addr.Success()) @@ -338,17 +306,17 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, switch (size) { case 1: - system.GetGPFifo().Write8(static_cast(data)); + m_system.GetGPFifo().Write8(static_cast(data)); return; case 2: - system.GetGPFifo().Write16(static_cast(data)); + m_system.GetGPFifo().Write16(static_cast(data)); return; case 4: - system.GetGPFifo().Write32(data); + m_system.GetGPFifo().Write32(data); return; default: // Some kind of misaligned write. TODO: Does this match how the actual hardware handles it? - auto& gpfifo = system.GetGPFifo(); + auto& gpfifo = m_system.GetGPFifo(); for (size_t i = size * 8; i > 0;) { i -= 8; @@ -369,20 +337,20 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, switch (size) { case 1: - memory.GetMMIOMapping()->Write(em_address, static_cast(data)); + m_memory.GetMMIOMapping()->Write(em_address, static_cast(data)); return; case 2: - memory.GetMMIOMapping()->Write(em_address, static_cast(data)); + m_memory.GetMMIOMapping()->Write(em_address, static_cast(data)); return; case 4: - memory.GetMMIOMapping()->Write(em_address, data); + m_memory.GetMMIOMapping()->Write(em_address, data); return; default: // Some kind of misaligned write. TODO: Does this match how the actual hardware handles it? for (size_t i = size * 8; i > 0; em_address++) { i -= 8; - memory.GetMMIOMapping()->Write(em_address, static_cast(data >> i)); + m_memory.GetMMIOMapping()->Write(em_address, static_cast(data >> i)); } return; } @@ -391,10 +359,10 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, const u32 swapped_data = Common::swap32(std::rotr(data, size * 8)); // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. - if (memory.GetL1Cache() && (em_address >> 28 == 0xE) && - (em_address < (0xE0000000 + memory.GetL1CacheSize()))) + if (m_memory.GetL1Cache() && (em_address >> 28 == 0xE) && + (em_address < (0xE0000000 + m_memory.GetL1CacheSize()))) { - std::memcpy(&memory.GetL1Cache()[em_address & 0x0FFFFFFF], &swapped_data, size); + std::memcpy(&m_memory.GetL1Cache()[em_address & 0x0FFFFFFF], &swapped_data, size); return; } @@ -409,7 +377,7 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, // TODO: This interrupt is supposed to have associated cause and address registers // TODO: This should trigger the hwtest's interrupt handling, but it does not seem to // (https://github.com/dolphin-emu/hwtests/pull/42) - system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_PI); + m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_PI); const u32 rotated_data = std::rotr(data, ((em_address & 0x3) + size) * 8); @@ -417,41 +385,41 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, const u32 end_addr = Common::AlignUp(em_address + size, 8); for (u32 addr = start_addr; addr != end_addr; addr += 8) { - WriteToHardware(system, memory, addr, rotated_data, 4); - WriteToHardware(system, memory, addr + 4, rotated_data, 4); + WriteToHardware(addr, rotated_data, 4); + WriteToHardware(addr + 4, rotated_data, 4); } return; } - if (memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000) + if (m_memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000) { // Handle RAM; the masking intentionally discards bits (essentially creating // mirrors of memory). - em_address &= memory.GetRamMask(); + em_address &= m_memory.GetRamMask(); - if (ppcState.m_enable_dcache && !wi) - ppcState.dCache.Write(em_address, &swapped_data, size, HID0(PowerPC::ppcState).DLOCK); + if (m_ppc_state.m_enable_dcache && !wi) + m_ppc_state.dCache.Write(em_address, &swapped_data, size, HID0(m_ppc_state).DLOCK); - if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write) - std::memcpy(&memory.GetRAM()[em_address], &swapped_data, size); + if (!m_ppc_state.m_enable_dcache || wi || flag != XCheckTLBFlag::Write) + std::memcpy(&m_memory.GetRAM()[em_address], &swapped_data, size); return; } - if (memory.GetEXRAM() && (em_address >> 28) == 0x1 && - (em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal()) + if (m_memory.GetEXRAM() && (em_address >> 28) == 0x1 && + (em_address & 0x0FFFFFFF) < m_memory.GetExRamSizeReal()) { em_address &= 0x0FFFFFFF; - if (ppcState.m_enable_dcache && !wi) + if (m_ppc_state.m_enable_dcache && !wi) { - ppcState.dCache.Write(em_address + 0x10000000, &swapped_data, size, - HID0(PowerPC::ppcState).DLOCK); + m_ppc_state.dCache.Write(em_address + 0x10000000, &swapped_data, size, + HID0(m_ppc_state).DLOCK); } - if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write) - std::memcpy(&memory.GetEXRAM()[em_address], &swapped_data, size); + if (!m_ppc_state.m_enable_dcache || wi || flag != XCheckTLBFlag::Write) + std::memcpy(&m_memory.GetEXRAM()[em_address], &swapped_data, size); return; } @@ -459,17 +427,18 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, // In Fake-VMEM mode, we need to map the memory somewhere into // physical memory for BAT translation to work; we currently use // [0x7E000000, 0x80000000). - if (memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000)) + if (m_memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000)) { - std::memcpy(&memory.GetFakeVMEM()[em_address & memory.GetFakeVMemMask()], &swapped_data, size); + std::memcpy(&m_memory.GetFakeVMEM()[em_address & m_memory.GetFakeVMemMask()], &swapped_data, + size); return; } - PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, PowerPC::ppcState.pc); - if (system.IsPauseOnPanicMode()) + PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, m_ppc_state.pc); + if (m_system.IsPauseOnPanicMode()) { - system.GetCPU().Break(); - ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + m_system.GetCPU().Break(); + m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; } } // ===================== @@ -479,9 +448,7 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory, location through ReadFromHardware and WriteToHardware */ // ---------------- -static void GenerateISIException(u32 effective_address); - -u32 Read_Opcode(u32 address) +u32 MMU::Read_Opcode(u32 address) { TryReadInstResult result = TryReadInstruction(address); if (!result.valid) @@ -492,10 +459,10 @@ u32 Read_Opcode(u32 address) return result.hex; } -TryReadInstResult TryReadInstruction(u32 address) +TryReadInstResult MMU::TryReadInstruction(u32 address) { bool from_bat = true; - if (PowerPC::ppcState.msr.IR) + if (m_ppc_state.msr.IR) { auto tlb_addr = TranslateAddress(address); if (!tlb_addr.Success()) @@ -509,59 +476,50 @@ TryReadInstResult TryReadInstruction(u32 address) } } - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - u32 hex; // TODO: Refactor this. This icache implementation is totally wrong if used with the fake vmem. - if (memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000)) + if (m_memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000)) { - hex = Common::swap32(&memory.GetFakeVMEM()[address & memory.GetFakeVMemMask()]); + hex = Common::swap32(&m_memory.GetFakeVMEM()[address & m_memory.GetFakeVMemMask()]); } else { - hex = PowerPC::ppcState.iCache.ReadInstruction(address); + hex = m_ppc_state.iCache.ReadInstruction(address); } return TryReadInstResult{true, from_bat, hex, address}; } -u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, const u32 address) +u32 MMU::HostRead_Instruction(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - return ReadFromHardware(system, memory, address); + return guard.GetSystem().GetMMU().ReadFromHardware( + address); } -std::optional> HostTryReadInstruction(const Core::CPUThreadGuard& guard, - const u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadInstruction(const Core::CPUThreadGuard& guard, + const u32 address, + RequestedAddressSpace space) { if (!HostIsInstructionRAMAddress(guard, address, space)) return std::nullopt; - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - + auto& mmu = guard.GetSystem().GetMMU(); switch (space) { case RequestedAddressSpace::Effective: { - const u32 value = - ReadFromHardware(system, memory, address); - return ReadResult(!!PowerPC::ppcState.msr.DR, value); + const u32 value = mmu.ReadFromHardware(address); + return ReadResult(!!mmu.m_ppc_state.msr.DR, value); } case RequestedAddressSpace::Physical: { - const u32 value = - ReadFromHardware(system, memory, address); + const u32 value = mmu.ReadFromHardware(address); return ReadResult(false, value); } case RequestedAddressSpace::Virtual: { - if (!PowerPC::ppcState.msr.DR) + if (!mmu.m_ppc_state.msr.DR) return std::nullopt; - const u32 value = - ReadFromHardware(system, memory, address); + const u32 value = mmu.ReadFromHardware(address); return ReadResult(true, value); } } @@ -570,7 +528,7 @@ std::optional> HostTryReadInstruction(const Core::CPUThreadGuard return std::nullopt; } -static void Memcheck(Core::System& system, u32 address, u64 var, bool write, size_t size) +void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) { if (!memchecks.HasAny()) return; @@ -579,7 +537,7 @@ static void Memcheck(Core::System& system, u32 address, u64 var, bool write, siz if (mc == nullptr) return; - if (system.GetCPU().IsStepping()) + if (m_system.GetCPU().IsStepping()) { // Disable when stepping so that resume works. return; @@ -587,11 +545,11 @@ static void Memcheck(Core::System& system, u32 address, u64 var, bool write, siz mc->num_hits++; - const bool pause = mc->Action(&debug_interface, var, address, write, size, PowerPC::ppcState.pc); + const bool pause = mc->Action(&debug_interface, var, address, write, size, m_ppc_state.pc); if (!pause) return; - system.GetCPU().Break(); + m_system.GetCPU().Break(); if (GDBStub::IsActive()) GDBStub::TakeControl(); @@ -603,86 +561,62 @@ static void Memcheck(Core::System& system, u32 address, u64 var, bool write, siz // make sure resuming after that works.) // It doesn't matter if ReadFromHardware triggers its own DSI because // we'll take it after resuming. - ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; } -u8 Read_U8(const u32 address) +u8 MMU::Read_U8(const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - u8 var = ReadFromHardware(system, memory, address); - Memcheck(system, address, var, false, 1); + u8 var = ReadFromHardware(address); + Memcheck(address, var, false, 1); return var; } -u16 Read_U16(const u32 address) +u16 MMU::Read_U16(const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - u16 var = ReadFromHardware(system, memory, address); - Memcheck(system, address, var, false, 2); + u16 var = ReadFromHardware(address); + Memcheck(address, var, false, 2); return var; } -u32 Read_U32(const u32 address) +u32 MMU::Read_U32(const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - u32 var = ReadFromHardware(system, memory, address); - Memcheck(system, address, var, false, 4); + u32 var = ReadFromHardware(address); + Memcheck(address, var, false, 4); return var; } -u64 Read_U64(const u32 address) +u64 MMU::Read_U64(const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - u64 var = ReadFromHardware(system, memory, address); - Memcheck(system, address, var, false, 8); + u64 var = ReadFromHardware(address); + Memcheck(address, var, false, 8); return var; } -double Read_F64(const u32 address) -{ - const u64 integral = Read_U64(address); - - return Common::BitCast(integral); -} - -float Read_F32(const u32 address) -{ - const u32 integral = Read_U32(address); - - return Common::BitCast(integral); -} - template -static std::optional> HostTryReadUX(const Core::CPUThreadGuard& guard, - const u32 address, RequestedAddressSpace space) +std::optional> MMU::HostTryReadUX(const Core::CPUThreadGuard& guard, + const u32 address, RequestedAddressSpace space) { if (!HostIsRAMAddress(guard, address, space)) return std::nullopt; - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - + auto& mmu = guard.GetSystem().GetMMU(); switch (space) { case RequestedAddressSpace::Effective: { - T value = ReadFromHardware(system, memory, address); - return ReadResult(!!PowerPC::ppcState.msr.DR, std::move(value)); + T value = mmu.ReadFromHardware(address); + return ReadResult(!!mmu.m_ppc_state.msr.DR, std::move(value)); } case RequestedAddressSpace::Physical: { - T value = ReadFromHardware(system, memory, address); + T value = mmu.ReadFromHardware(address); return ReadResult(false, std::move(value)); } case RequestedAddressSpace::Virtual: { - if (!PowerPC::ppcState.msr.DR) + if (!mmu.m_ppc_state.msr.DR) return std::nullopt; - T value = ReadFromHardware(system, memory, address); + T value = mmu.ReadFromHardware(address); return ReadResult(true, std::move(value)); } } @@ -691,32 +625,32 @@ static std::optional> HostTryReadUX(const Core::CPUThreadGuard& gu return std::nullopt; } -std::optional> HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { return HostTryReadUX(guard, address, space); } -std::optional> HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { return HostTryReadUX(guard, address, space); } -std::optional> HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { return HostTryReadUX(guard, address, space); } -std::optional> HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { return HostTryReadUX(guard, address, space); } -std::optional> HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { const auto result = HostTryReadUX(guard, address, space); if (!result) @@ -724,8 +658,8 @@ std::optional> HostTryReadF32(const Core::CPUThreadGuard& guar return ReadResult(result->translated, Common::BitCast(result->value)); } -std::optional> HostTryReadF64(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadF64(const Core::CPUThreadGuard& guard, + u32 address, RequestedAddressSpace space) { const auto result = HostTryReadUX(guard, address, space); if (!result) @@ -733,178 +667,140 @@ std::optional> HostTryReadF64(const Core::CPUThreadGuard& gua return ReadResult(result->translated, Common::BitCast(result->value)); } -u32 Read_U8_ZX(const u32 address) +void MMU::Write_U8(const u32 var, const u32 address) { - return Read_U8(address); + Memcheck(address, var, true, 1); + WriteToHardware(address, var, 1); } -u32 Read_U16_ZX(const u32 address) +void MMU::Write_U16(const u32 var, const u32 address) { - return Read_U16(address); + Memcheck(address, var, true, 2); + WriteToHardware(address, var, 2); } - -void Write_U8(const u32 var, const u32 address) -{ - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - Memcheck(system, address, var, true, 1); - WriteToHardware(system, memory, address, var, 1); -} - -void Write_U16(const u32 var, const u32 address) -{ - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - Memcheck(system, address, var, true, 2); - WriteToHardware(system, memory, address, var, 2); -} -void Write_U16_Swap(const u32 var, const u32 address) +void MMU::Write_U16_Swap(const u32 var, const u32 address) { Write_U16((var & 0xFFFF0000) | Common::swap16(static_cast(var)), address); } -void Write_U32(const u32 var, const u32 address) +void MMU::Write_U32(const u32 var, const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - Memcheck(system, address, var, true, 4); - WriteToHardware(system, memory, address, var, 4); + Memcheck(address, var, true, 4); + WriteToHardware(address, var, 4); } -void Write_U32_Swap(const u32 var, const u32 address) +void MMU::Write_U32_Swap(const u32 var, const u32 address) { Write_U32(Common::swap32(var), address); } -void Write_U64(const u64 var, const u32 address) +void MMU::Write_U64(const u64 var, const u32 address) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - Memcheck(system, address, var, true, 8); - WriteToHardware(system, memory, address, static_cast(var >> 32), 4); - WriteToHardware(system, memory, address + sizeof(u32), - static_cast(var), 4); + Memcheck(address, var, true, 8); + WriteToHardware(address, static_cast(var >> 32), 4); + WriteToHardware(address + sizeof(u32), static_cast(var), 4); } -void Write_U64_Swap(const u64 var, const u32 address) +void MMU::Write_U64_Swap(const u64 var, const u32 address) { Write_U64(Common::swap64(var), address); } -void Write_F64(const double var, const u32 address) +u8 MMU::HostRead_U8(const Core::CPUThreadGuard& guard, const u32 address) { - const u64 integral = Common::BitCast(var); - - Write_U64(integral, address); + auto& mmu = guard.GetSystem().GetMMU(); + return mmu.ReadFromHardware(address); } -u8 HostRead_U8(const Core::CPUThreadGuard& guard, const u32 address) +u16 MMU::HostRead_U16(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - return ReadFromHardware(system, memory, address); + auto& mmu = guard.GetSystem().GetMMU(); + return mmu.ReadFromHardware(address); } -u16 HostRead_U16(const Core::CPUThreadGuard& guard, const u32 address) +u32 MMU::HostRead_U32(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - return ReadFromHardware(system, memory, address); + auto& mmu = guard.GetSystem().GetMMU(); + return mmu.ReadFromHardware(address); } -u32 HostRead_U32(const Core::CPUThreadGuard& guard, const u32 address) +u64 MMU::HostRead_U64(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - return ReadFromHardware(system, memory, address); + auto& mmu = guard.GetSystem().GetMMU(); + return mmu.ReadFromHardware(address); } -u64 HostRead_U64(const Core::CPUThreadGuard& guard, const u32 address) -{ - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - return ReadFromHardware(system, memory, address); -} - -float HostRead_F32(const Core::CPUThreadGuard& guard, const u32 address) +float MMU::HostRead_F32(const Core::CPUThreadGuard& guard, const u32 address) { const u32 integral = HostRead_U32(guard, address); return Common::BitCast(integral); } -double HostRead_F64(const Core::CPUThreadGuard& guard, const u32 address) +double MMU::HostRead_F64(const Core::CPUThreadGuard& guard, const u32 address) { const u64 integral = HostRead_U64(guard, address); return Common::BitCast(integral); } -void HostWrite_U8(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) +void MMU::HostWrite_U8(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - WriteToHardware(system, memory, address, var, 1); + auto& mmu = guard.GetSystem().GetMMU(); + mmu.WriteToHardware(address, var, 1); } -void HostWrite_U16(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) +void MMU::HostWrite_U16(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - WriteToHardware(system, memory, address, var, 2); + auto& mmu = guard.GetSystem().GetMMU(); + mmu.WriteToHardware(address, var, 2); } -void HostWrite_U32(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) +void MMU::HostWrite_U32(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - WriteToHardware(system, memory, address, var, 4); + auto& mmu = guard.GetSystem().GetMMU(); + mmu.WriteToHardware(address, var, 4); } -void HostWrite_U64(const Core::CPUThreadGuard& guard, const u64 var, const u32 address) +void MMU::HostWrite_U64(const Core::CPUThreadGuard& guard, const u64 var, const u32 address) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - WriteToHardware(system, memory, address, static_cast(var >> 32), - 4); - WriteToHardware(system, memory, address + sizeof(u32), - static_cast(var), 4); + auto& mmu = guard.GetSystem().GetMMU(); + mmu.WriteToHardware(address, static_cast(var >> 32), 4); + mmu.WriteToHardware(address + sizeof(u32), static_cast(var), 4); } -void HostWrite_F32(const Core::CPUThreadGuard& guard, const float var, const u32 address) +void MMU::HostWrite_F32(const Core::CPUThreadGuard& guard, const float var, const u32 address) { const u32 integral = Common::BitCast(var); HostWrite_U32(guard, integral, address); } -void HostWrite_F64(const Core::CPUThreadGuard& guard, const double var, const u32 address) +void MMU::HostWrite_F64(const Core::CPUThreadGuard& guard, const double var, const u32 address) { const u64 integral = Common::BitCast(var); HostWrite_U64(guard, integral, address); } -static std::optional HostTryWriteUX(const Core::CPUThreadGuard& guard, const u32 var, - const u32 address, const u32 size, - RequestedAddressSpace space) +std::optional MMU::HostTryWriteUX(const Core::CPUThreadGuard& guard, const u32 var, + const u32 address, const u32 size, + RequestedAddressSpace space) { if (!HostIsRAMAddress(guard, address, space)) return std::nullopt; - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - + auto& mmu = guard.GetSystem().GetMMU(); switch (space) { case RequestedAddressSpace::Effective: - WriteToHardware(system, memory, address, var, size); - return WriteResult(!!PowerPC::ppcState.msr.DR); + mmu.WriteToHardware(address, var, size); + return WriteResult(!!mmu.m_ppc_state.msr.DR); case RequestedAddressSpace::Physical: - WriteToHardware(system, memory, address, var, size); + mmu.WriteToHardware(address, var, size); return WriteResult(false); case RequestedAddressSpace::Virtual: - if (!PowerPC::ppcState.msr.DR) + if (!mmu.m_ppc_state.msr.DR) return std::nullopt; - WriteToHardware(system, memory, address, var, size); + mmu.WriteToHardware(address, var, size); return WriteResult(true); } @@ -912,26 +808,26 @@ static std::optional HostTryWriteUX(const Core::CPUThreadGuard& gua return std::nullopt; } -std::optional HostTryWriteU8(const Core::CPUThreadGuard& guard, const u32 var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteU8(const Core::CPUThreadGuard& guard, const u32 var, + const u32 address, RequestedAddressSpace space) { return HostTryWriteUX(guard, var, address, 1, space); } -std::optional HostTryWriteU16(const Core::CPUThreadGuard& guard, const u32 var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteU16(const Core::CPUThreadGuard& guard, const u32 var, + const u32 address, RequestedAddressSpace space) { return HostTryWriteUX(guard, var, address, 2, space); } -std::optional HostTryWriteU32(const Core::CPUThreadGuard& guard, const u32 var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteU32(const Core::CPUThreadGuard& guard, const u32 var, + const u32 address, RequestedAddressSpace space) { return HostTryWriteUX(guard, var, address, 4, space); } -std::optional HostTryWriteU64(const Core::CPUThreadGuard& guard, const u64 var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteU64(const Core::CPUThreadGuard& guard, const u64 var, + const u32 address, RequestedAddressSpace space) { const auto result = HostTryWriteUX(guard, static_cast(var >> 32), address, 4, space); if (!result) @@ -940,21 +836,21 @@ std::optional HostTryWriteU64(const Core::CPUThreadGuard& guard, co return HostTryWriteUX(guard, static_cast(var), address + 4, 4, space); } -std::optional HostTryWriteF32(const Core::CPUThreadGuard& guard, const float var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteF32(const Core::CPUThreadGuard& guard, const float var, + const u32 address, RequestedAddressSpace space) { const u32 integral = Common::BitCast(var); return HostTryWriteU32(guard, integral, address, space); } -std::optional HostTryWriteF64(const Core::CPUThreadGuard& guard, const double var, - const u32 address, RequestedAddressSpace space) +std::optional MMU::HostTryWriteF64(const Core::CPUThreadGuard& guard, const double var, + const u32 address, RequestedAddressSpace space) { const u64 integral = Common::BitCast(var); return HostTryWriteU64(guard, integral, address, space); } -std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size) +std::string MMU::HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size) { std::string s; do @@ -970,9 +866,9 @@ std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t return s; } -std::optional> HostTryReadString(const Core::CPUThreadGuard& guard, - u32 address, size_t size, - RequestedAddressSpace space) +std::optional> MMU::HostTryReadString(const Core::CPUThreadGuard& guard, + u32 address, size_t size, + RequestedAddressSpace space) { auto c = HostTryReadU8(guard, address, space); if (!c) @@ -993,24 +889,24 @@ std::optional> HostTryReadString(const Core::CPUThreadGu return ReadResult(c->translated, std::move(s)); } -bool IsOptimizableRAMAddress(const u32 address) +bool MMU::IsOptimizableRAMAddress(const u32 address) const { if (PowerPC::memchecks.HasAny()) return false; - if (!PowerPC::ppcState.msr.DR) + if (!m_ppc_state.msr.DR) return false; // TODO: This API needs to take an access size // // We store whether an access can be optimized to an unchecked access // in dbat_table. - u32 bat_result = dbat_table[address >> BAT_INDEX_SHIFT]; + u32 bat_result = m_dbat_table[address >> BAT_INDEX_SHIFT]; return (bat_result & BAT_PHYSICAL_BIT) != 0; } template -static bool IsRAMAddress(Memory::MemoryManager& memory, u32 address, bool translate) +bool MMU::IsRAMAddress(u32 address, bool translate) { if (translate) { @@ -1021,80 +917,73 @@ static bool IsRAMAddress(Memory::MemoryManager& memory, u32 address, bool transl } u32 segment = address >> 28; - if (memory.GetRAM() && segment == 0x0 && (address & 0x0FFFFFFF) < memory.GetRamSizeReal()) + if (m_memory.GetRAM() && segment == 0x0 && (address & 0x0FFFFFFF) < m_memory.GetRamSizeReal()) { return true; } - else if (memory.GetEXRAM() && segment == 0x1 && - (address & 0x0FFFFFFF) < memory.GetExRamSizeReal()) + else if (m_memory.GetEXRAM() && segment == 0x1 && + (address & 0x0FFFFFFF) < m_memory.GetExRamSizeReal()) { return true; } - else if (memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000)) + else if (m_memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000)) { return true; } - else if (memory.GetL1Cache() && segment == 0xE && - (address < (0xE0000000 + memory.GetL1CacheSize()))) + else if (m_memory.GetL1Cache() && segment == 0xE && + (address < (0xE0000000 + m_memory.GetL1CacheSize()))) { return true; } return false; } -bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address, RequestedAddressSpace space) +bool MMU::HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - + auto& mmu = guard.GetSystem().GetMMU(); switch (space) { case RequestedAddressSpace::Effective: - return IsRAMAddress(memory, address, PowerPC::ppcState.msr.DR); + return mmu.IsRAMAddress(address, mmu.m_ppc_state.msr.DR); case RequestedAddressSpace::Physical: - return IsRAMAddress(memory, address, false); + return mmu.IsRAMAddress(address, false); case RequestedAddressSpace::Virtual: - if (!PowerPC::ppcState.msr.DR) + if (!mmu.m_ppc_state.msr.DR) return false; - return IsRAMAddress(memory, address, true); + return mmu.IsRAMAddress(address, true); } ASSERT(false); return false; } -bool HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space) +bool MMU::HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space) { // Instructions are always 32bit aligned. if (address & 3) return false; - auto& system = guard.GetSystem(); - auto& memory = system.GetMemory(); - + auto& mmu = guard.GetSystem().GetMMU(); switch (space) { case RequestedAddressSpace::Effective: - return IsRAMAddress(memory, address, - PowerPC::ppcState.msr.IR); + return mmu.IsRAMAddress(address, mmu.m_ppc_state.msr.IR); case RequestedAddressSpace::Physical: - return IsRAMAddress(memory, address, false); + return mmu.IsRAMAddress(address, false); case RequestedAddressSpace::Virtual: - if (!PowerPC::ppcState.msr.IR) + if (!mmu.m_ppc_state.msr.IR) return false; - return IsRAMAddress(memory, address, true); + return mmu.IsRAMAddress(address, true); } ASSERT(false); return false; } -void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 num_blocks) +void MMU::DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 num_blocks) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - // TODO: It's not completely clear this is the right spot for this code; // what would happen if, for example, the DVD drive tried to write to the EFB? // TODO: This is terribly slow. @@ -1104,7 +993,7 @@ void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 nu { for (u32 i = 0; i < 32 * num_blocks; i += 4) { - const u32 data = Common::swap32(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF)); + const u32 data = Common::swap32(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF)); EFB_Write(data, mem_address + i); } return; @@ -1116,27 +1005,24 @@ void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 nu { for (u32 i = 0; i < 32 * num_blocks; i += 4) { - const u32 data = Common::swap32(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF)); - memory.GetMMIOMapping()->Write(mem_address + i, data); + const u32 data = Common::swap32(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF)); + m_memory.GetMMIOMapping()->Write(mem_address + i, data); } return; } - const u8* src = memory.GetL1Cache() + (cache_address & 0x3FFFF); - u8* dst = memory.GetPointer(mem_address); + const u8* src = m_memory.GetL1Cache() + (cache_address & 0x3FFFF); + u8* dst = m_memory.GetPointer(mem_address); if (dst == nullptr) return; memcpy(dst, src, 32 * num_blocks); } -void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 num_blocks) +void MMU::DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 num_blocks) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - - const u8* src = memory.GetPointer(mem_address); - u8* dst = memory.GetL1Cache() + (cache_address & 0x3FFFF); + const u8* src = m_memory.GetPointer(mem_address); + u8* dst = m_memory.GetL1Cache() + (cache_address & 0x3FFFF); // No known game uses this; here for completeness. // TODO: Refactor. @@ -1145,7 +1031,7 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu for (u32 i = 0; i < 32 * num_blocks; i += 4) { const u32 data = Common::swap32(EFB_Read(mem_address + i)); - std::memcpy(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32)); + std::memcpy(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32)); } return; } @@ -1156,8 +1042,8 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu { for (u32 i = 0; i < 32 * num_blocks; i += 4) { - const u32 data = Common::swap32(memory.GetMMIOMapping()->Read(mem_address + i)); - std::memcpy(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32)); + const u32 data = Common::swap32(m_memory.GetMMIOMapping()->Read(mem_address + i)); + std::memcpy(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32)); } return; } @@ -1168,10 +1054,20 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu memcpy(dst, src, 32 * num_blocks); } -void ClearDCacheLine(u32 address) +static bool TranslateBatAddress(const BatTable& bat_table, u32* address, bool* wi) +{ + u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT]; + if ((bat_result & BAT_MAPPED_BIT) == 0) + return false; + *address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1)); + *wi = (bat_result & BAT_WI_BIT) != 0; + return true; +} + +void MMU::ClearDCacheLine(u32 address) { DEBUG_ASSERT((address & 0x1F) == 0); - if (PowerPC::ppcState.msr.DR) + if (m_ppc_state.msr.DR) { auto translated_address = TranslateAddress(address); if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT) @@ -1190,20 +1086,17 @@ void ClearDCacheLine(u32 address) address = translated_address.address; } - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - // TODO: This isn't precisely correct for non-RAM regions, but the difference // is unlikely to matter. for (u32 i = 0; i < 32; i += 4) - WriteToHardware(system, memory, address + i, 0, 4); + WriteToHardware(address + i, 0, 4); } -void StoreDCacheLine(u32 address) +void MMU::StoreDCacheLine(u32 address) { address &= ~0x1F; - if (PowerPC::ppcState.msr.DR) + if (m_ppc_state.msr.DR) { auto translated_address = TranslateAddress(address); if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT) @@ -1219,15 +1112,15 @@ void StoreDCacheLine(u32 address) address = translated_address.address; } - if (ppcState.m_enable_dcache) - ppcState.dCache.Store(address); + if (m_ppc_state.m_enable_dcache) + m_ppc_state.dCache.Store(address); } -void InvalidateDCacheLine(u32 address) +void MMU::InvalidateDCacheLine(u32 address) { address &= ~0x1F; - if (PowerPC::ppcState.msr.DR) + if (m_ppc_state.msr.DR) { auto translated_address = TranslateAddress(address); if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT) @@ -1241,15 +1134,15 @@ void InvalidateDCacheLine(u32 address) address = translated_address.address; } - if (ppcState.m_enable_dcache) - ppcState.dCache.Invalidate(address); + if (m_ppc_state.m_enable_dcache) + m_ppc_state.dCache.Invalidate(address); } -void FlushDCacheLine(u32 address) +void MMU::FlushDCacheLine(u32 address) { address &= ~0x1F; - if (PowerPC::ppcState.msr.DR) + if (m_ppc_state.msr.DR) { auto translated_address = TranslateAddress(address); if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT) @@ -1265,15 +1158,15 @@ void FlushDCacheLine(u32 address) address = translated_address.address; } - if (ppcState.m_enable_dcache) - ppcState.dCache.Flush(address); + if (m_ppc_state.m_enable_dcache) + m_ppc_state.dCache.Flush(address); } -void TouchDCacheLine(u32 address, bool store) +void MMU::TouchDCacheLine(u32 address, bool store) { address &= ~0x1F; - if (PowerPC::ppcState.msr.DR) + if (m_ppc_state.msr.DR) { auto translated_address = TranslateAddress(address); if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT) @@ -1289,23 +1182,23 @@ void TouchDCacheLine(u32 address, bool store) address = translated_address.address; } - if (ppcState.m_enable_dcache) - ppcState.dCache.Touch(address, store); + if (m_ppc_state.m_enable_dcache) + m_ppc_state.dCache.Touch(address, store); } -u32 IsOptimizableMMIOAccess(u32 address, u32 access_size) +u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const { if (PowerPC::memchecks.HasAny()) return 0; - if (!PowerPC::ppcState.msr.DR) + if (!m_ppc_state.msr.DR) return 0; // Translate address // If we also optimize for TLB mappings, we'd have to clear the // JitCache on each TLB invalidation. bool wi = false; - if (!TranslateBatAddess(dbat_table, &address, &wi)) + if (!TranslateBatAddress(m_dbat_table, &address, &wi)) return 0; // Check whether the address is an aligned address of an MMIO register. @@ -1316,28 +1209,28 @@ u32 IsOptimizableMMIOAccess(u32 address, u32 access_size) return address; } -bool IsOptimizableGatherPipeWrite(u32 address) +bool MMU::IsOptimizableGatherPipeWrite(u32 address) const { if (PowerPC::memchecks.HasAny()) return false; - if (!PowerPC::ppcState.msr.DR) + if (!m_ppc_state.msr.DR) return false; // Translate address, only check BAT mapping. // If we also optimize for TLB mappings, we'd have to clear the // JitCache on each TLB invalidation. bool wi = false; - if (!TranslateBatAddess(dbat_table, &address, &wi)) + if (!TranslateBatAddress(m_dbat_table, &address, &wi)) return false; // Check whether the translated address equals the address in WPAR. return address == GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS; } -TranslateResult JitCache_TranslateAddress(u32 address) +TranslateResult MMU::JitCache_TranslateAddress(u32 address) { - if (!PowerPC::ppcState.msr.IR) + if (!m_ppc_state.msr.IR) return TranslateResult{address}; // TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger. @@ -1349,18 +1242,17 @@ TranslateResult JitCache_TranslateAddress(u32 address) return TranslateResult{from_bat, tlb_addr.address}; } -static void GenerateDSIException(u32 effective_address, bool write) +void MMU::GenerateDSIException(u32 effective_address, bool write) { // DSI exceptions are only supported in MMU mode. - auto& system = Core::System::GetInstance(); - if (!system.IsMMUMode()) + if (!m_system.IsMMUMode()) { PanicAlertFmt("Invalid {} {:#010x}, PC = {:#010x}", write ? "write to" : "read from", - effective_address, PowerPC::ppcState.pc); - if (system.IsPauseOnPanicMode()) + effective_address, m_ppc_state.pc); + if (m_system.IsPauseOnPanicMode()) { - system.GetCPU().Break(); - ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + m_system.GetCPU().Break(); + m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; } return; } @@ -1369,27 +1261,27 @@ static void GenerateDSIException(u32 effective_address, bool write) constexpr u32 dsisr_store = 1U << 25; if (effective_address != 0) - ppcState.spr[SPR_DSISR] = dsisr_page | dsisr_store; + m_ppc_state.spr[SPR_DSISR] = dsisr_page | dsisr_store; else - ppcState.spr[SPR_DSISR] = dsisr_page; + m_ppc_state.spr[SPR_DSISR] = dsisr_page; - ppcState.spr[SPR_DAR] = effective_address; + m_ppc_state.spr[SPR_DAR] = effective_address; - ppcState.Exceptions |= EXCEPTION_DSI; + m_ppc_state.Exceptions |= EXCEPTION_DSI; } -static void GenerateISIException(u32 effective_address) +void MMU::GenerateISIException(u32 effective_address) { // Address of instruction could not be translated - PowerPC::ppcState.npc = effective_address; + m_ppc_state.npc = effective_address; - PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; - WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", PowerPC::ppcState.pc); + m_ppc_state.Exceptions |= EXCEPTION_ISI; + WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", m_ppc_state.pc); } -void SDRUpdated() +void MMU::SDRUpdated() { - const auto sdr = UReg_SDR1{ppcState.spr[SPR_SDR]}; + const auto sdr = UReg_SDR1{m_ppc_state.spr[SPR_SDR]}; const u32 htabmask = sdr.htabmask; if (!Common::IsValidLowMask(htabmask)) @@ -1403,8 +1295,8 @@ void SDRUpdated() if ((htaborg & htabmask) != 0) WARN_LOG_FMT(POWERPC, "Invalid HTABORG: htaborg=0x{:08x} htabmask=0x{:08x}", htaborg, htabmask); - ppcState.pagetable_base = htaborg << 16; - ppcState.pagetable_hashmask = ((htabmask << 10) | 0x3ff); + m_ppc_state.pagetable_base = htaborg << 16; + m_ppc_state.pagetable_hashmask = ((htabmask << 10) | 0x3ff); } enum class TLBLookupResult @@ -1414,11 +1306,12 @@ enum class TLBLookupResult UpdateC }; -static TLBLookupResult LookupTLBPageAddress(const XCheckTLBFlag flag, const u32 vpa, u32* paddr, +static TLBLookupResult LookupTLBPageAddress(PowerPC::PowerPCState& ppc_state, + const XCheckTLBFlag flag, const u32 vpa, u32* paddr, bool* wi) { const u32 tag = vpa >> HW_PAGE_INDEX_SHIFT; - TLBEntry& tlbe = ppcState.tlb[IsOpcodeFlag(flag)][tag & HW_PAGE_INDEX_MASK]; + TLBEntry& tlbe = ppc_state.tlb[IsOpcodeFlag(flag)][tag & HW_PAGE_INDEX_MASK]; if (tlbe.tag[0] == tag) { @@ -1469,13 +1362,14 @@ static TLBLookupResult LookupTLBPageAddress(const XCheckTLBFlag flag, const u32 return TLBLookupResult::NotFound; } -static void UpdateTLBEntry(const XCheckTLBFlag flag, UPTE_Hi pte2, const u32 address) +static void UpdateTLBEntry(PowerPC::PowerPCState& ppc_state, const XCheckTLBFlag flag, UPTE_Hi pte2, + const u32 address) { if (IsNoExceptionFlag(flag)) return; const u32 tag = address >> HW_PAGE_INDEX_SHIFT; - TLBEntry& tlbe = ppcState.tlb[IsOpcodeFlag(flag)][tag & HW_PAGE_INDEX_MASK]; + TLBEntry& tlbe = ppc_state.tlb[IsOpcodeFlag(flag)][tag & HW_PAGE_INDEX_MASK]; const u32 index = tlbe.recent == 0 && tlbe.tag[0] != TLBEntry::INVALID_TAG; tlbe.recent = index; tlbe.paddr[index] = pte2.RPN << HW_PAGE_INDEX_SHIFT; @@ -1483,43 +1377,31 @@ static void UpdateTLBEntry(const XCheckTLBFlag flag, UPTE_Hi pte2, const u32 add tlbe.tag[index] = tag; } -void InvalidateTLBEntry(u32 address) +void MMU::InvalidateTLBEntry(u32 address) { const u32 entry_index = (address >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK; - ppcState.tlb[0][entry_index].Invalidate(); - ppcState.tlb[1][entry_index].Invalidate(); + m_ppc_state.tlb[0][entry_index].Invalidate(); + m_ppc_state.tlb[1][entry_index].Invalidate(); } -union EffectiveAddress -{ - BitField<0, 12, u32> offset; - BitField<12, 16, u32> page_index; - BitField<22, 6, u32> API; - BitField<28, 4, u32> SR; - - u32 Hex = 0; - - EffectiveAddress() = default; - explicit EffectiveAddress(u32 address) : Hex{address} {} -}; - // Page Address Translation -static TranslateAddressResult TranslatePageAddress(const EffectiveAddress address, - const XCheckTLBFlag flag, bool* wi) +MMU::TranslateAddressResult MMU::TranslatePageAddress(const EffectiveAddress address, + const XCheckTLBFlag flag, bool* wi) { // TLB cache // This catches 99%+ of lookups in practice, so the actual page table entry code below doesn't // benefit much from optimization. u32 translated_address = 0; - const TLBLookupResult res = LookupTLBPageAddress(flag, address.Hex, &translated_address, wi); + const TLBLookupResult res = + LookupTLBPageAddress(m_ppc_state, flag, address.Hex, &translated_address, wi); if (res == TLBLookupResult::Found) { return TranslateAddressResult{TranslateAddressResultEnum::PAGE_TABLE_TRANSLATED, translated_address}; } - const auto sr = UReg_SR{ppcState.sr[address.SR]}; + const auto sr = UReg_SR{m_ppc_state.sr[address.SR]}; if (sr.T != 0) return TranslateAddressResult{TranslateAddressResultEnum::DIRECT_STORE_SEGMENT, 0}; @@ -1545,9 +1427,6 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres pte1.API = api; pte1.V = 1; - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - for (int hash_func = 0; hash_func < 2; hash_func++) { // hash function no 2 "not" .360 @@ -1557,16 +1436,15 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres pte1.H = 1; } - u32 pteg_addr = - ((hash & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base; + u32 pteg_addr = ((hash & m_ppc_state.pagetable_hashmask) << 6) | m_ppc_state.pagetable_base; for (int i = 0; i < 8; i++, pteg_addr += 8) { - const u32 pteg = memory.Read_U32(pteg_addr); + const u32 pteg = m_memory.Read_U32(pteg_addr); if (pte1.Hex == pteg) { - UPTE_Hi pte2(memory.Read_U32(pteg_addr + 4)); + UPTE_Hi pte2(m_memory.Read_U32(pteg_addr + 4)); // set the access bits switch (flag) @@ -1588,12 +1466,12 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres if (!IsNoExceptionFlag(flag)) { - memory.Write_U32(pte2.Hex, pteg_addr + 4); + m_memory.Write_U32(pte2.Hex, pteg_addr + 4); } // We already updated the TLB entry if this was caused by a C bit. if (res != TLBLookupResult::UpdateC) - UpdateTLBEntry(flag, pte2, address.Hex); + UpdateTLBEntry(m_ppc_state, flag, pte2, address.Hex); *wi = (pte2.WIMG & 0b1100) != 0; @@ -1605,11 +1483,8 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres return TranslateAddressResult{TranslateAddressResultEnum::PAGE_FAULT, 0}; } -static void UpdateBATs(BatTable& bat_table, u32 base_spr) +void MMU::UpdateBATs(BatTable& bat_table, u32 base_spr) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - // TODO: Separate BATs for MSR.PR==0 and MSR.PR==1 // TODO: Handle PP settings. // TODO: Check how hardware reacts to overlapping BATs (including @@ -1618,8 +1493,8 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr) for (int i = 0; i < 4; ++i) { const u32 spr = base_spr + i * 2; - const UReg_BAT_Up batu{ppcState.spr[spr]}; - const UReg_BAT_Lo batl{ppcState.spr[spr + 1]}; + const UReg_BAT_Up batu{m_ppc_state.spr[spr]}; + const UReg_BAT_Lo batl{m_ppc_state.spr[spr + 1]}; if (batu.VS == 0 && batu.VP == 0) continue; @@ -1669,21 +1544,21 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr) // that fastmem doesn't emulate properly (though no normal games are known to rely on them). if (!wi) { - if (memory.GetFakeVMEM() && (physical_address & 0xFE000000) == 0x7E000000) + if (m_memory.GetFakeVMEM() && (physical_address & 0xFE000000) == 0x7E000000) { valid_bit |= BAT_PHYSICAL_BIT; } - else if (physical_address < memory.GetRamSizeReal()) + else if (physical_address < m_memory.GetRamSizeReal()) { valid_bit |= BAT_PHYSICAL_BIT; } - else if (memory.GetEXRAM() && physical_address >> 28 == 0x1 && - (physical_address & 0x0FFFFFFF) < memory.GetExRamSizeReal()) + else if (m_memory.GetEXRAM() && physical_address >> 28 == 0x1 && + (physical_address & 0x0FFFFFFF) < m_memory.GetExRamSizeReal()) { valid_bit |= BAT_PHYSICAL_BIT; } else if (physical_address >> 28 == 0xE && - physical_address < 0xE0000000 + memory.GetL1CacheSize()) + physical_address < 0xE0000000 + m_memory.GetL1CacheSize()) { valid_bit |= BAT_PHYSICAL_BIT; } @@ -1700,17 +1575,14 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr) } } -static void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr) +void MMU::UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr) { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - for (u32 i = 0; i < (0x10000000 >> BAT_INDEX_SHIFT); ++i) { // Map from 0x4XXXXXXX or 0x7XXXXXXX to the range // [0x7E000000,0x80000000). u32 e_address = i + (start_addr >> BAT_INDEX_SHIFT); - u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & memory.GetFakeVMemMask()); + u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & m_memory.GetFakeVMemMask()); u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT; if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE)) @@ -1720,48 +1592,42 @@ static void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr) } } -void DBATUpdated() +void MMU::DBATUpdated() { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - - dbat_table = {}; - UpdateBATs(dbat_table, SPR_DBAT0U); - bool extended_bats = SConfig::GetInstance().bWii && HID4(PowerPC::ppcState).SBE; + m_dbat_table = {}; + UpdateBATs(m_dbat_table, SPR_DBAT0U); + bool extended_bats = SConfig::GetInstance().bWii && HID4(m_ppc_state).SBE; if (extended_bats) - UpdateBATs(dbat_table, SPR_DBAT4U); - if (memory.GetFakeVMEM()) + UpdateBATs(m_dbat_table, SPR_DBAT4U); + if (m_memory.GetFakeVMEM()) { // In Fake-MMU mode, insert some extra entries into the BAT tables. - UpdateFakeMMUBat(dbat_table, 0x40000000); - UpdateFakeMMUBat(dbat_table, 0x70000000); + UpdateFakeMMUBat(m_dbat_table, 0x40000000); + UpdateFakeMMUBat(m_dbat_table, 0x70000000); } #ifndef _ARCH_32 - memory.UpdateLogicalMemory(dbat_table); + m_memory.UpdateLogicalMemory(m_dbat_table); #endif // IsOptimizable*Address and dcbz depends on the BAT mapping, so we need a flush here. - system.GetJitInterface().ClearSafe(); + m_system.GetJitInterface().ClearSafe(); } -void IBATUpdated() +void MMU::IBATUpdated() { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - - ibat_table = {}; - UpdateBATs(ibat_table, SPR_IBAT0U); - bool extended_bats = SConfig::GetInstance().bWii && HID4(PowerPC::ppcState).SBE; + m_ibat_table = {}; + UpdateBATs(m_ibat_table, SPR_IBAT0U); + bool extended_bats = SConfig::GetInstance().bWii && HID4(m_ppc_state).SBE; if (extended_bats) - UpdateBATs(ibat_table, SPR_IBAT4U); - if (memory.GetFakeVMEM()) + UpdateBATs(m_ibat_table, SPR_IBAT4U); + if (m_memory.GetFakeVMEM()) { // In Fake-MMU mode, insert some extra entries into the BAT tables. - UpdateFakeMMUBat(ibat_table, 0x40000000); - UpdateFakeMMUBat(ibat_table, 0x70000000); + UpdateFakeMMUBat(m_ibat_table, 0x40000000); + UpdateFakeMMUBat(m_ibat_table, 0x70000000); } - system.GetJitInterface().ClearSafe(); + m_system.GetJitInterface().ClearSafe(); } // Translate effective address using BAT or PAT. Returns 0 if the address cannot be translated. @@ -1769,17 +1635,17 @@ void IBATUpdated() // So we first check if there is a matching BAT entry, else we look for the TLB in // TranslatePageAddress(). template -static TranslateAddressResult TranslateAddress(u32 address) +MMU::TranslateAddressResult MMU::TranslateAddress(u32 address) { bool wi = false; - if (TranslateBatAddess(IsOpcodeFlag(flag) ? ibat_table : dbat_table, &address, &wi)) + if (TranslateBatAddress(IsOpcodeFlag(flag) ? m_ibat_table : m_dbat_table, &address, &wi)) return TranslateAddressResult{TranslateAddressResultEnum::BAT_TRANSLATED, address, wi}; return TranslatePageAddress(EffectiveAddress{address}, flag, &wi); } -std::optional GetTranslatedAddress(u32 address) +std::optional MMU::GetTranslatedAddress(u32 address) { auto result = TranslateAddress(address); if (!result.Success()) @@ -1789,4 +1655,101 @@ std::optional GetTranslatedAddress(u32 address) return std::optional(result.address); } +void ClearDCacheLineFromJit64(MMU& mmu, u32 address) +{ + mmu.ClearDCacheLine(address); +} +u32 ReadU8ZXFromJit64(MMU& mmu, u32 address) +{ + return mmu.Read_U8(address); +} +u32 ReadU16ZXFromJit64(MMU& mmu, u32 address) +{ + return mmu.Read_U16(address); +} +u32 ReadU32FromJit64(MMU& mmu, u32 address) +{ + return mmu.Read_U32(address); +} +u64 ReadU64FromJit64(MMU& mmu, u32 address) +{ + return mmu.Read_U64(address); +} +void WriteU8FromJit64(MMU& mmu, u32 var, u32 address) +{ + mmu.Write_U8(var, address); +} +void WriteU16FromJit64(MMU& mmu, u32 var, u32 address) +{ + mmu.Write_U16(var, address); +} +void WriteU32FromJit64(MMU& mmu, u32 var, u32 address) +{ + mmu.Write_U32(var, address); +} +void WriteU64FromJit64(MMU& mmu, u64 var, u32 address) +{ + mmu.Write_U64(var, address); +} +void WriteU16SwapFromJit64(MMU& mmu, u32 var, u32 address) +{ + mmu.Write_U16_Swap(var, address); +} +void WriteU32SwapFromJit64(MMU& mmu, u32 var, u32 address) +{ + mmu.Write_U32_Swap(var, address); +} +void WriteU64SwapFromJit64(MMU& mmu, u64 var, u32 address) +{ + mmu.Write_U64_Swap(var, address); +} + +void ClearDCacheLineFromJitArm64(u32 address, MMU& mmu) +{ + mmu.ClearDCacheLine(address); +} +u8 ReadU8FromJitArm64(u32 address, MMU& mmu) +{ + return mmu.Read_U8(address); +} +u16 ReadU16FromJitArm64(u32 address, MMU& mmu) +{ + return mmu.Read_U16(address); +} +u32 ReadU32FromJitArm64(u32 address, MMU& mmu) +{ + return mmu.Read_U32(address); +} +u64 ReadU64FromJitArm64(u32 address, MMU& mmu) +{ + return mmu.Read_U64(address); +} +void WriteU8FromJitArm64(u32 var, u32 address, MMU& mmu) +{ + mmu.Write_U8(var, address); +} +void WriteU16FromJitArm64(u32 var, u32 address, MMU& mmu) +{ + mmu.Write_U16(var, address); +} +void WriteU32FromJitArm64(u32 var, u32 address, MMU& mmu) +{ + mmu.Write_U32(var, address); +} +void WriteU64FromJitArm64(u64 var, u32 address, MMU& mmu) +{ + mmu.Write_U64(var, address); +} +void WriteU16SwapFromJitArm64(u32 var, u32 address, MMU& mmu) +{ + mmu.Write_U16_Swap(var, address); +} +void WriteU32SwapFromJitArm64(u32 var, u32 address, MMU& mmu) +{ + mmu.Write_U32_Swap(var, address); +} +void WriteU64SwapFromJitArm64(u64 var, u32 address, MMU& mmu) +{ + mmu.Write_U64_Swap(var, address); +} } // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/MMU.h b/Source/Core/Core/PowerPC/MMU.h index bf9ee0d926..a5dda345b8 100644 --- a/Source/Core/Core/PowerPC/MMU.h +++ b/Source/Core/Core/PowerPC/MMU.h @@ -8,18 +8,22 @@ #include #include +#include "Common/BitField.h" #include "Common/CommonTypes.h" namespace Core { class CPUThreadGuard; +class System; +}; // namespace Core +namespace Memory +{ +class MemoryManager; }; namespace PowerPC { -// Routines for debugger UI, cheats, etc. to access emulated memory from the -// perspective of the CPU. Not for use by core emulation routines. -// Use "Host" prefix. +struct PowerPCState; enum class RequestedAddressSpace { @@ -28,19 +32,6 @@ enum class RequestedAddressSpace Virtual, // specifically want MMU turned on, fails if off }; -// Reads a value from emulated memory using the currently active MMU settings. -// If the read fails (eg. address does not correspond to a mapped address in the current address -// space), a PanicAlert will be shown to the user and zero (or an empty string for the string case) -// will be returned. -u8 HostRead_U8(const Core::CPUThreadGuard& guard, u32 address); -u16 HostRead_U16(const Core::CPUThreadGuard& guard, u32 address); -u32 HostRead_U32(const Core::CPUThreadGuard& guard, u32 address); -u64 HostRead_U64(const Core::CPUThreadGuard& guard, u32 address); -float HostRead_F32(const Core::CPUThreadGuard& guard, u32 address); -double HostRead_F64(const Core::CPUThreadGuard& guard, u32 address); -u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, u32 address); -std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0); - template struct ReadResult { @@ -57,45 +48,6 @@ struct ReadResult ReadResult(bool translated_, const T& value_) : translated(translated_), value(value_) {} }; -// Try to read a value from emulated memory at the given address in the given memory space. -// If the read succeeds, the returned value will be present and the ReadResult contains the read -// value and information on whether the given address had to be translated or not. Unlike the -// HostRead functions, this does not raise a user-visible alert on failure. -std::optional> -HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadF64(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional> -HostTryReadString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0, - RequestedAddressSpace space = RequestedAddressSpace::Effective); - -// Writes a value to emulated memory using the currently active MMU settings. -// If the write fails (eg. address does not correspond to a mapped address in the current address -// space), a PanicAlert will be shown to the user. -void HostWrite_U8(const Core::CPUThreadGuard& guard, u32 var, u32 address); -void HostWrite_U16(const Core::CPUThreadGuard& guard, u32 var, u32 address); -void HostWrite_U32(const Core::CPUThreadGuard& guard, u32 var, u32 address); -void HostWrite_U64(const Core::CPUThreadGuard& guard, u64 var, u32 address); -void HostWrite_F32(const Core::CPUThreadGuard& guard, float var, u32 address); -void HostWrite_F64(const Core::CPUThreadGuard& guard, double var, u32 address); - struct WriteResult { // whether the address had to be translated (given address was treated as virtual) or not (given @@ -105,42 +57,21 @@ struct WriteResult explicit WriteResult(bool translated_) : translated(translated_) {} }; -// Try to a write a value to memory at the given address in the given memory space. -// If the write succeeds, the returned TryWriteResult contains information on whether the given -// address had to be translated or not. Unlike the HostWrite functions, this does not raise a -// user-visible alert on failure. -std::optional -HostTryWriteU8(const Core::CPUThreadGuard& guard, u32 var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional -HostTryWriteU16(const Core::CPUThreadGuard& guard, u32 var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional -HostTryWriteU32(const Core::CPUThreadGuard& guard, u32 var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional -HostTryWriteU64(const Core::CPUThreadGuard& guard, u64 var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional -HostTryWriteF32(const Core::CPUThreadGuard& guard, float var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); -std::optional -HostTryWriteF64(const Core::CPUThreadGuard& guard, double var, const u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); +constexpr int BAT_INDEX_SHIFT = 17; +constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT; +constexpr u32 BAT_PAGE_COUNT = 1 << (32 - BAT_INDEX_SHIFT); +constexpr u32 BAT_MAPPED_BIT = 0x1; +constexpr u32 BAT_PHYSICAL_BIT = 0x2; +constexpr u32 BAT_WI_BIT = 0x4; +constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x7); +using BatTable = std::array; // 128 KB -// Returns whether a read or write to the given address will resolve to a RAM access in the given -// address space. -bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); +constexpr size_t HW_PAGE_SIZE = 4096; +constexpr size_t HW_PAGE_MASK = HW_PAGE_SIZE - 1; +constexpr u32 HW_PAGE_INDEX_SHIFT = 12; +constexpr u32 HW_PAGE_INDEX_MASK = 0x3f; -// Same as HostIsRAMAddress, but uses IBAT instead of DBAT. -bool HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address, - RequestedAddressSpace space = RequestedAddressSpace::Effective); - -// Routines for the CPU core to access memory. - -// Used by interpreter to read instructions, uses iCache -u32 Read_Opcode(u32 address); +// Return value of MMU::TryReadInstruction(). struct TryReadInstResult { bool valid; @@ -148,55 +79,8 @@ struct TryReadInstResult u32 hex; u32 physical_address; }; -TryReadInstResult TryReadInstruction(u32 address); - -u8 Read_U8(u32 address); -u16 Read_U16(u32 address); -u32 Read_U32(u32 address); -u64 Read_U64(u32 address); - -// Useful helper functions, used by ARM JIT -float Read_F32(u32 address); -double Read_F64(u32 address); - -// used by JIT. Return zero-extended 32bit values -u32 Read_U8_ZX(u32 address); -u32 Read_U16_ZX(u32 address); - -void Write_U8(u32 var, u32 address); -void Write_U16(u32 var, u32 address); -void Write_U32(u32 var, u32 address); -void Write_U64(u64 var, u32 address); - -void Write_U16_Swap(u32 var, u32 address); -void Write_U32_Swap(u32 var, u32 address); -void Write_U64_Swap(u64 var, u32 address); - -// Useful helper functions, used by ARM JIT -void Write_F64(double var, u32 address); - -void DMA_LCToMemory(u32 mem_address, u32 cache_address, u32 num_blocks); -void DMA_MemoryToLC(u32 cache_address, u32 mem_address, u32 num_blocks); - -void ClearDCacheLine(u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned -void StoreDCacheLine(u32 address); -void InvalidateDCacheLine(u32 address); -void FlushDCacheLine(u32 address); -void TouchDCacheLine(u32 address, bool store); - -// TLB functions -void SDRUpdated(); -void InvalidateTLBEntry(u32 address); -void DBATUpdated(); -void IBATUpdated(); - -// Result changes based on the BAT registers and MSR.DR. Returns whether -// it's safe to optimize a read or write to this address to an unguarded -// memory access. Does not consider page tables. -bool IsOptimizableRAMAddress(u32 address); -u32 IsOptimizableMMIOAccess(u32 address, u32 access_size); -bool IsOptimizableGatherPipeWrite(u32 address); +// Return value of MMU::JitCache_TranslateAddress(). struct TranslateResult { bool valid = false; @@ -211,32 +95,261 @@ struct TranslateResult { } }; -TranslateResult JitCache_TranslateAddress(u32 address); -constexpr int BAT_INDEX_SHIFT = 17; -constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT; -constexpr u32 BAT_PAGE_COUNT = 1 << (32 - BAT_INDEX_SHIFT); -constexpr u32 BAT_MAPPED_BIT = 0x1; -constexpr u32 BAT_PHYSICAL_BIT = 0x2; -constexpr u32 BAT_WI_BIT = 0x4; -constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x7); -using BatTable = std::array; // 128 KB -extern BatTable ibat_table; -extern BatTable dbat_table; -inline bool TranslateBatAddess(const BatTable& bat_table, u32* address, bool* wi) +enum class XCheckTLBFlag { - u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT]; - if ((bat_result & BAT_MAPPED_BIT) == 0) - return false; - *address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1)); - *wi = (bat_result & BAT_WI_BIT) != 0; - return true; -} + NoException, + Read, + Write, + Opcode, + OpcodeNoException +}; -constexpr size_t HW_PAGE_SIZE = 4096; -constexpr size_t HW_PAGE_MASK = HW_PAGE_SIZE - 1; -constexpr u32 HW_PAGE_INDEX_SHIFT = 12; -constexpr u32 HW_PAGE_INDEX_MASK = 0x3f; +class MMU +{ +public: + MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state); + MMU(const MMU& other) = delete; + MMU(MMU&& other) = delete; + MMU& operator=(const MMU& other) = delete; + MMU& operator=(MMU&& other) = delete; + ~MMU(); -std::optional GetTranslatedAddress(u32 address); + // Routines for debugger UI, cheats, etc. to access emulated memory from the + // perspective of the CPU. Not for use by core emulation routines. + // Use "Host" prefix. + + // Reads a value from emulated memory using the currently active MMU settings. + // If the read fails (eg. address does not correspond to a mapped address in the current address + // space), a PanicAlert will be shown to the user and zero (or an empty string for the string + // case) will be returned. + static u8 HostRead_U8(const Core::CPUThreadGuard& guard, u32 address); + static u16 HostRead_U16(const Core::CPUThreadGuard& guard, u32 address); + static u32 HostRead_U32(const Core::CPUThreadGuard& guard, u32 address); + static u64 HostRead_U64(const Core::CPUThreadGuard& guard, u32 address); + static float HostRead_F32(const Core::CPUThreadGuard& guard, u32 address); + static double HostRead_F64(const Core::CPUThreadGuard& guard, u32 address); + static u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, u32 address); + static std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0); + + // Try to read a value from emulated memory at the given address in the given memory space. + // If the read succeeds, the returned value will be present and the ReadResult contains the read + // value and information on whether the given address had to be translated or not. Unlike the + // HostRead functions, this does not raise a user-visible alert on failure. + static std::optional> + HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadF64(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional> + HostTryReadString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + + // Writes a value to emulated memory using the currently active MMU settings. + // If the write fails (eg. address does not correspond to a mapped address in the current address + // space), a PanicAlert will be shown to the user. + static void HostWrite_U8(const Core::CPUThreadGuard& guard, u32 var, u32 address); + static void HostWrite_U16(const Core::CPUThreadGuard& guard, u32 var, u32 address); + static void HostWrite_U32(const Core::CPUThreadGuard& guard, u32 var, u32 address); + static void HostWrite_U64(const Core::CPUThreadGuard& guard, u64 var, u32 address); + static void HostWrite_F32(const Core::CPUThreadGuard& guard, float var, u32 address); + static void HostWrite_F64(const Core::CPUThreadGuard& guard, double var, u32 address); + + // Try to a write a value to memory at the given address in the given memory space. + // If the write succeeds, the returned TryWriteResult contains information on whether the given + // address had to be translated or not. Unlike the HostWrite functions, this does not raise a + // user-visible alert on failure. + static std::optional + HostTryWriteU8(const Core::CPUThreadGuard& guard, u32 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional + HostTryWriteU16(const Core::CPUThreadGuard& guard, u32 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional + HostTryWriteU32(const Core::CPUThreadGuard& guard, u32 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional + HostTryWriteU64(const Core::CPUThreadGuard& guard, u64 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional + HostTryWriteF32(const Core::CPUThreadGuard& guard, float var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + static std::optional + HostTryWriteF64(const Core::CPUThreadGuard& guard, double var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + + // Returns whether a read or write to the given address will resolve to a RAM access in the given + // address space. + static bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + + // Same as HostIsRAMAddress, but uses IBAT instead of DBAT. + static bool + HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + + // Routines for the CPU core to access memory. + + // Used by interpreter to read instructions, uses iCache + u32 Read_Opcode(u32 address); + TryReadInstResult TryReadInstruction(u32 address); + + u8 Read_U8(u32 address); + u16 Read_U16(u32 address); + u32 Read_U32(u32 address); + u64 Read_U64(u32 address); + + void Write_U8(u32 var, u32 address); + void Write_U16(u32 var, u32 address); + void Write_U32(u32 var, u32 address); + void Write_U64(u64 var, u32 address); + + void Write_U16_Swap(u32 var, u32 address); + void Write_U32_Swap(u32 var, u32 address); + void Write_U64_Swap(u64 var, u32 address); + + void DMA_LCToMemory(u32 mem_address, u32 cache_address, u32 num_blocks); + void DMA_MemoryToLC(u32 cache_address, u32 mem_address, u32 num_blocks); + + void ClearDCacheLine(u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned + void StoreDCacheLine(u32 address); + void InvalidateDCacheLine(u32 address); + void FlushDCacheLine(u32 address); + void TouchDCacheLine(u32 address, bool store); + + // TLB functions + void SDRUpdated(); + void InvalidateTLBEntry(u32 address); + void DBATUpdated(); + void IBATUpdated(); + + // Result changes based on the BAT registers and MSR.DR. Returns whether + // it's safe to optimize a read or write to this address to an unguarded + // memory access. Does not consider page tables. + bool IsOptimizableRAMAddress(u32 address) const; + u32 IsOptimizableMMIOAccess(u32 address, u32 access_size) const; + bool IsOptimizableGatherPipeWrite(u32 address) const; + + TranslateResult JitCache_TranslateAddress(u32 address); + + std::optional GetTranslatedAddress(u32 address); + + BatTable& GetIBATTable() { return m_ibat_table; } + BatTable& GetDBATTable() { return m_dbat_table; } + +private: + enum class TranslateAddressResultEnum : u8 + { + BAT_TRANSLATED, + PAGE_TABLE_TRANSLATED, + DIRECT_STORE_SEGMENT, + PAGE_FAULT, + }; + + struct TranslateAddressResult + { + u32 address; + TranslateAddressResultEnum result; + bool wi; // Set to true if the view of memory is either write-through or cache-inhibited + + TranslateAddressResult(TranslateAddressResultEnum result_, u32 address_, bool wi_ = false) + : address(address_), result(result_), wi(wi_) + { + } + bool Success() const { return result <= TranslateAddressResultEnum::PAGE_TABLE_TRANSLATED; } + }; + + union EffectiveAddress + { + BitField<0, 12, u32> offset; + BitField<12, 16, u32> page_index; + BitField<22, 6, u32> API; + BitField<28, 4, u32> SR; + + u32 Hex = 0; + + EffectiveAddress() = default; + explicit EffectiveAddress(u32 address) : Hex{address} {} + }; + + template + TranslateAddressResult TranslateAddress(u32 address); + + TranslateAddressResult TranslatePageAddress(const EffectiveAddress address, + const XCheckTLBFlag flag, bool* wi); + + void GenerateDSIException(u32 effective_address, bool write); + void GenerateISIException(u32 effective_address); + + void Memcheck(u32 address, u64 var, bool write, size_t size); + + void UpdateBATs(BatTable& bat_table, u32 base_spr); + void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr); + + template + T ReadFromHardware(u32 em_address); + template + void WriteToHardware(u32 em_address, const u32 data, const u32 size); + template + bool IsRAMAddress(u32 address, bool translate); + + template + static std::optional> HostTryReadUX(const Core::CPUThreadGuard& guard, + const u32 address, RequestedAddressSpace space); + static std::optional HostTryWriteUX(const Core::CPUThreadGuard& guard, const u32 var, + const u32 address, const u32 size, + RequestedAddressSpace space); + + Core::System& m_system; + Memory::MemoryManager& m_memory; + PowerPC::PowerPCState& m_ppc_state; + + BatTable m_ibat_table; + BatTable m_dbat_table; +}; + +void ClearDCacheLineFromJit64(MMU& mmu, u32 address); +u32 ReadU8ZXFromJit64(MMU& mmu, u32 address); // Returns zero-extended 32bit value +u32 ReadU16ZXFromJit64(MMU& mmu, u32 address); // Returns zero-extended 32bit value +u32 ReadU32FromJit64(MMU& mmu, u32 address); +u64 ReadU64FromJit64(MMU& mmu, u32 address); +void WriteU8FromJit64(MMU& mmu, u32 var, u32 address); +void WriteU16FromJit64(MMU& mmu, u32 var, u32 address); +void WriteU32FromJit64(MMU& mmu, u32 var, u32 address); +void WriteU64FromJit64(MMU& mmu, u64 var, u32 address); +void WriteU16SwapFromJit64(MMU& mmu, u32 var, u32 address); +void WriteU32SwapFromJit64(MMU& mmu, u32 var, u32 address); +void WriteU64SwapFromJit64(MMU& mmu, u64 var, u32 address); + +// The JitArm64 function that calls these has very specific register allocation that's difficult to +// change, so we have a separate set of functions here for it. This can probably be refactored in +// the future. +void ClearDCacheLineFromJitArm64(u32 address, MMU& mmu); +u8 ReadU8FromJitArm64(u32 address, MMU& mmu); +u16 ReadU16FromJitArm64(u32 address, MMU& mmu); +u32 ReadU32FromJitArm64(u32 address, MMU& mmu); +u64 ReadU64FromJitArm64(u32 address, MMU& mmu); +void WriteU8FromJitArm64(u32 var, u32 address, MMU& mmu); +void WriteU16FromJitArm64(u32 var, u32 address, MMU& mmu); +void WriteU32FromJitArm64(u32 var, u32 address, MMU& mmu); +void WriteU64FromJitArm64(u64 var, u32 address, MMU& mmu); +void WriteU16SwapFromJitArm64(u32 var, u32 address, MMU& mmu); +void WriteU32SwapFromJitArm64(u32 var, u32 address, MMU& mmu); +void WriteU64SwapFromJitArm64(u64 var, u32 address, MMU& mmu); } // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 0a04b8b9d9..1d4f5fab2f 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -17,12 +17,14 @@ #include "Common/StringUtil.h" #include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PPCTables.h" #include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/SignatureDB/SignatureDB.h" +#include "Core/System.h" // Analyzes PowerPC code in memory to find functions // After running, for each function we will know what functions it calls @@ -82,6 +84,8 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S if (func.analyzed) return true; // No error, just already did it. + auto& mmu = guard.GetSystem().GetMMU(); + func.calls.clear(); func.callers.clear(); func.size = 0; @@ -93,7 +97,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S { func.size += 4; if (func.size >= JitBase::code_buffer_size * 4 || - !PowerPC::HostIsInstructionRAMAddress(guard, addr)) + !PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr)) { return false; } @@ -108,7 +112,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S func.flags |= Common::FFLAG_STRAIGHT; return true; } - const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr); + const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr); const UGeckoInstruction instr = read_result.hex; if (read_result.valid && PPCTables::IsValidInstruction(instr)) { @@ -264,9 +268,10 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 startAddr, u32 endAddr, Common::SymbolDB* func_db) { + auto& mmu = guard.GetSystem().GetMMU(); for (u32 addr = startAddr; addr < endAddr; addr += 4) { - const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr); + const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr); const UGeckoInstruction instr = read_result.hex; if (read_result.valid && PPCTables::IsValidInstruction(instr)) @@ -280,7 +285,7 @@ static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 sta u32 target = SignExt26(instr.LI << 2); if (!instr.AA) target += addr; - if (PowerPC::HostIsRAMAddress(guard, target)) + if (PowerPC::MMU::HostIsRAMAddress(guard, target)) { func_db->AddFunction(guard, target); } @@ -314,9 +319,10 @@ static void FindFunctionsFromHandlers(const Core::CPUThreadGuard& guard, PPCSymb {0x80001400, "system_management_interrupt_handler"}, {0x80001700, "thermal_management_interrupt_exception_handler"}}; + auto& mmu = guard.GetSystem().GetMMU(); for (const auto& entry : handlers) { - const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(entry.first); + const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(entry.first); if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex)) { // Check if this function is already mapped @@ -336,19 +342,20 @@ static void FindFunctionsAfterReturnInstruction(const Core::CPUThreadGuard& guar for (const auto& func : func_db->Symbols()) funcAddrs.push_back(func.second.address + func.second.size); + auto& mmu = guard.GetSystem().GetMMU(); for (u32& location : funcAddrs) { while (true) { // Skip zeroes (e.g. Donkey Kong Country Returns) and nop (e.g. libogc) // that sometimes pad function to 16 byte boundary. - PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(location); + PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(location); while (read_result.valid && (location & 0xf) != 0) { if (read_result.hex != 0 && read_result.hex != 0x60000000) break; location += 4; - read_result = PowerPC::TryReadInstruction(location); + read_result = mmu.TryReadInstruction(location); } if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex)) { @@ -757,9 +764,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, const bool enable_follow = m_enable_branch_following; + auto& mmu = Core::System::GetInstance().GetMMU(); for (std::size_t i = 0; i < block_size; ++i) { - auto result = PowerPC::TryReadInstruction(address); + auto result = mmu.TryReadInstruction(address); if (!result.valid) { if (i == 0) diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index c9ac1e7427..61e620248d 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -18,10 +18,12 @@ #include "Common/IOFile.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" +#include "Core/Core.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/SignatureDB/SignatureDB.h" +#include "Core/System.h" PPCSymbolDB g_symbolDB; @@ -407,16 +409,17 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string& if (strlen(name) > 0) { // Can't compute the checksum if not in RAM - bool good = !bad && PowerPC::HostIsInstructionRAMAddress(guard, vaddress) && - PowerPC::HostIsInstructionRAMAddress(guard, vaddress + size - 4); + bool good = !bad && PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress) && + PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress + size - 4); if (!good) { // check for BLR before function - PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(vaddress - 4); + PowerPC::TryReadInstResult read_result = + guard.GetSystem().GetMMU().TryReadInstruction(vaddress - 4); if (read_result.valid && read_result.hex == 0x4e800020) { // check for BLR at end of function - read_result = PowerPC::TryReadInstruction(vaddress + size - 4); + read_result = guard.GetSystem().GetMMU().TryReadInstruction(vaddress + size - 4); good = read_result.valid && read_result.hex == 0x4e800020; } } diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index b18960f473..fef24a482a 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -146,8 +146,10 @@ void DoState(PointerWrap& p) } RoundingModeUpdated(); - IBATUpdated(); - DBATUpdated(); + + auto& mmu = Core::System::GetInstance().GetMMU(); + mmu.IBATUpdated(); + mmu.DBATUpdated(); } // SystemTimers::DecrementerSet(); @@ -202,8 +204,10 @@ static void ResetRegisters() ppcState.SetXER({}); RoundingModeUpdated(); - DBATUpdated(); - IBATUpdated(); + + auto& mmu = Core::System::GetInstance().GetMMU(); + mmu.DBATUpdated(); + mmu.IBATUpdated(); TL(PowerPC::ppcState) = 0; TU(PowerPC::ppcState) = 0; diff --git a/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp index 4d7c579a01..a6aefc088b 100644 --- a/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp +++ b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp @@ -108,8 +108,8 @@ bool Compare(const Core::CPUThreadGuard& guard, u32 address, u32 size, const MEG for (size_t i = 0; i < sig.code.size(); ++i) { - if (sig.code[i] != 0 && - PowerPC::HostRead_U32(guard, static_cast(address + i * sizeof(u32))) != sig.code[i]) + if (sig.code[i] != 0 && PowerPC::MMU::HostRead_U32( + guard, static_cast(address + i * sizeof(u32))) != sig.code[i]) { return false; } diff --git a/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp b/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp index afe09acfa2..b9cec4a2be 100644 --- a/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp +++ b/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp @@ -166,7 +166,7 @@ u32 HashSignatureDB::ComputeCodeChecksum(const Core::CPUThreadGuard& guard, u32 u32 sum = 0; for (u32 offset = offsetStart; offset <= offsetEnd; offset += 4) { - u32 opcode = PowerPC::HostRead_Instruction(guard, offset); + u32 opcode = PowerPC::MMU::HostRead_Instruction(guard, offset); u32 op = opcode & 0xFC000000; u32 op2 = 0; u32 op3 = 0; diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 1897131041..438b3c3014 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -40,8 +40,9 @@ struct System::Impl explicit Impl(System& system) : m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system), m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system), - m_ppc_state(PowerPC::ppcState), m_processor_interface(system), m_serial_interface(system), - m_video_interface(system), m_interpreter(system, m_ppc_state), m_jit_interface(system) + m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state), + m_processor_interface(system), m_serial_interface(system), m_video_interface(system), + m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system) { } @@ -67,6 +68,7 @@ struct System::Impl PixelEngine::PixelEngineManager m_pixel_engine; PixelShaderManager m_pixel_shader_manager; PowerPC::PowerPCState& m_ppc_state; + PowerPC::MMU m_mmu; ProcessorInterface::ProcessorInterfaceManager m_processor_interface; SerialInterface::SerialInterfaceManager m_serial_interface; Sram m_sram; @@ -204,6 +206,11 @@ MemoryInterface::MemoryInterfaceManager& System::GetMemoryInterface() const return m_impl->m_memory_interface; } +PowerPC::MMU& System::GetMMU() const +{ + return m_impl->m_mmu; +} + PixelEngine::PixelEngineManager& System::GetPixelEngine() const { return m_impl->m_pixel_engine; diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index d25b5ad609..6a6375f0d9 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -72,8 +72,9 @@ class PixelEngineManager; }; namespace PowerPC { +class MMU; struct PowerPCState; -} +} // namespace PowerPC namespace ProcessorInterface { class ProcessorInterfaceManager; @@ -138,6 +139,7 @@ public: IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const; Memory::MemoryManager& GetMemory() const; MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const; + PowerPC::MMU& GetMMU() const; PixelEngine::PixelEngineManager& GetPixelEngine() const; PixelShaderManager& GetPixelShaderManager() const; PowerPC::PowerPCState& GetPPCState() const; diff --git a/Source/Core/DiscIO/RiivolutionPatcher.cpp b/Source/Core/DiscIO/RiivolutionPatcher.cpp index 0f9bbec3ca..309e9e5ea1 100644 --- a/Source/Core/DiscIO/RiivolutionPatcher.cpp +++ b/Source/Core/DiscIO/RiivolutionPatcher.cpp @@ -502,7 +502,7 @@ static bool MemoryMatchesAt(const Core::CPUThreadGuard& guard, u32 offset, { for (u32 i = 0; i < value.size(); ++i) { - auto result = PowerPC::HostTryReadU8(guard, offset + i); + auto result = PowerPC::MMU::HostTryReadU8(guard, offset + i); if (!result || result->value != value[i]) return false; } @@ -521,7 +521,7 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset, auto& system = Core::System::GetInstance(); const u32 size = static_cast(value.size()); for (u32 i = 0; i < size; ++i) - PowerPC::HostTryWriteU8(guard, value[i], offset + i); + PowerPC::MMU::HostTryWriteU8(guard, value[i], offset + i); const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size); if (overlapping_hook_count != 0) { @@ -585,13 +585,13 @@ static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Pat { // from the pattern find the next blr instruction const u32 blr_address = ram_start + i; - auto blr = PowerPC::HostTryReadU32(guard, blr_address); + auto blr = PowerPC::MMU::HostTryReadU32(guard, blr_address); if (blr && blr->value == 0x4e800020) { // and replace it with a jump to the given offset const u32 target = memory_patch.m_offset | 0x80000000; const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000; - PowerPC::HostTryWriteU32(guard, jmp, blr_address); + PowerPC::MMU::HostTryWriteU32(guard, jmp, blr_address); const u32 overlapping_hook_count = HLE::UnpatchRange(system, blr_address, blr_address + 4); if (overlapping_hook_count != 0) diff --git a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp index e4073fb16a..f954f57ccc 100644 --- a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp @@ -987,10 +987,11 @@ void CodeViewWidget::OnReplaceInstruction() const u32 addr = GetContextAddress(); - if (!PowerPC::HostIsInstructionRAMAddress(guard, addr)) + if (!PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr)) return; - const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr); + const PowerPC::TryReadInstResult read_result = + guard.GetSystem().GetMMU().TryReadInstruction(addr); if (!read_result.valid) return; diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index d232fede85..29d72faf18 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -463,7 +463,7 @@ void CodeWidget::StepOver() const UGeckoInstruction inst = [&] { Core::CPUThreadGuard guard(system); - return PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc); + return PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); }(); if (inst.LK) @@ -516,7 +516,7 @@ void CodeWidget::StepOut() // Loop until either the current instruction is a return instruction with no Link flag // or a breakpoint is detected so it can step at the breakpoint. If the PC is currently // on a breakpoint, skip it. - UGeckoInstruction inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc); + UGeckoInstruction inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); do { if (WillInstructionReturn(inst)) @@ -540,7 +540,7 @@ void CodeWidget::StepOut() PowerPC::SingleStep(); } - inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc); + inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); } while (clock::now() < timeout && !PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc)); diff --git a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp index 147efa3779..3905700f2b 100644 --- a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp @@ -268,7 +268,8 @@ void ThreadWidget::Update() return QStringLiteral("%1").arg(value, 8, 16, QLatin1Char('0')); }; const auto format_hex_from = [&format_hex](const Core::CPUThreadGuard& guard, u32 addr) { - addr = PowerPC::HostIsRAMAddress(guard, addr) ? PowerPC::HostRead_U32(guard, addr) : 0; + addr = + PowerPC::MMU::HostIsRAMAddress(guard, addr) ? PowerPC::MMU::HostRead_U32(guard, addr) : 0; return format_hex(addr); }; const auto get_state = [](u16 thread_state) { @@ -449,13 +450,13 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard, u32 sp = context.gpr->at(1); for (int i = 0; i < 16; i++) { - if (sp == 0 || sp == 0xffffffff || !PowerPC::HostIsRAMAddress(guard, sp)) + if (sp == 0 || sp == 0xffffffff || !PowerPC::MMU::HostIsRAMAddress(guard, sp)) break; m_callstack_table->insertRow(i); m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp))); - if (PowerPC::HostIsRAMAddress(guard, sp + 4)) + if (PowerPC::MMU::HostIsRAMAddress(guard, sp + 4)) { - const u32 lr_save = PowerPC::HostRead_U32(guard, sp + 4); + const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4); m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save))); m_callstack_table->setItem(i, 3, new QTableWidgetItem(QString::fromStdString( @@ -465,7 +466,7 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard, { m_callstack_table->setItem(i, 2, new QTableWidgetItem(QStringLiteral("--------"))); } - sp = PowerPC::HostRead_U32(guard, sp); + sp = PowerPC::MMU::HostRead_U32(guard, sp); m_callstack_table->setItem(i, 1, new QTableWidgetItem(format_hex(sp))); } } diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp index 8bab9ed1fb..fdb1279072 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp @@ -193,18 +193,19 @@ void WatchWidget::Update() QBrush brush = QPalette().brush(QPalette::Text); - if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, entry.address)) + if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, entry.address)) brush.setColor(Qt::red); if (Core::IsRunning()) { - if (PowerPC::HostIsRAMAddress(guard, entry.address)) + if (PowerPC::MMU::HostIsRAMAddress(guard, entry.address)) { - hex->setText(QStringLiteral("%1").arg(PowerPC::HostRead_U32(guard, entry.address), 8, 16, - QLatin1Char('0'))); - decimal->setText(QString::number(PowerPC::HostRead_U32(guard, entry.address))); - string->setText(QString::fromStdString(PowerPC::HostGetString(guard, entry.address, 32))); - floatValue->setText(QString::number(PowerPC::HostRead_F32(guard, entry.address))); + hex->setText(QStringLiteral("%1").arg(PowerPC::MMU::HostRead_U32(guard, entry.address), 8, + 16, QLatin1Char('0'))); + decimal->setText(QString::number(PowerPC::MMU::HostRead_U32(guard, entry.address))); + string->setText( + QString::fromStdString(PowerPC::MMU::HostGetString(guard, entry.address, 32))); + floatValue->setText(QString::number(PowerPC::MMU::HostRead_F32(guard, entry.address))); lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked); } } @@ -418,7 +419,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) } else { - PowerPC::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address); + PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address); } } else @@ -446,7 +447,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 address) { - const std::string memory_data_as_string = PowerPC::HostGetString(guard, address, 4); + const std::string memory_data_as_string = PowerPC::MMU::HostGetString(guard, address, 4); std::vector bytes; for (const char c : memory_data_as_string) diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index ea991d1e6f..2677ac27d0 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -1351,7 +1351,7 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress) for (; len < MODULE_NAME_MAX_LENGTH; ++len) { - const auto res = PowerPC::HostRead_U8(guard, *found_addr - (len + 1)); + const auto res = PowerPC::MMU::HostRead_U8(guard, *found_addr - (len + 1)); if (!std::isprint(res)) { break; @@ -1406,8 +1406,8 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress) const auto module_name_offset = accessors->ReadU32(guard, *found_addr); // Go to the beginning of the RSO header - matches.emplace_back(*found_addr - 16, - PowerPC::HostGetString(guard, module_name_offset, module_name_length)); + matches.emplace_back(*found_addr - 16, PowerPC::MMU::HostGetString(guard, module_name_offset, + module_name_length)); progress.SetLabelText(tr("Modules found: %1").arg(matches.size())); } @@ -1698,8 +1698,8 @@ void MenuBar::SearchInstruction() for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal(); addr += 4) { - const auto ins_name = - QString::fromStdString(PPCTables::GetInstructionName(PowerPC::HostRead_U32(guard, addr))); + const auto ins_name = QString::fromStdString( + PPCTables::GetInstructionName(PowerPC::MMU::HostRead_U32(guard, addr))); if (op == ins_name) { NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op.toStdString(), addr);