MMU: Use templates for Read/Write functions

This commit is contained in:
Martino Fontana
2025-10-08 11:27:06 +02:00
parent 03ef9b4995
commit 8a97ce9124
32 changed files with 487 additions and 775 deletions
+11
View File
@@ -5,6 +5,8 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
namespace Common namespace Common
{ {
@@ -141,4 +143,13 @@ concept TypedEnum = std::is_same_v<std::underlying_type_t<T>, Underlying>;
template <typename T> template <typename T>
concept BooleanEnum = TypedEnum<T, bool>; concept BooleanEnum = TypedEnum<T, bool>;
template <typename T>
requires(sizeof(T) <= sizeof(u64) && std::has_single_bit(sizeof(T)))
using MakeUnsignedSameSize =
std::tuple_element_t<MathUtil::IntLog2(sizeof(T)), std::tuple<u8, u16, u32, u64>>;
template <std::unsigned_integral T>
using MakeAtLeastU32 = std::conditional_t<std::is_same_v<T, u64>, u64, u32>;
} // namespace Common } // namespace Common
+2 -2
View File
@@ -1370,8 +1370,8 @@ u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_
address += (MEM2_START - MEM1_SIZE); address += (MEM2_START - MEM1_SIZE);
for (u32 num_read = 0; num_read < num_bytes; num_read++) for (u32 num_read = 0; num_read < num_bytes; num_read++)
{ {
auto value = system.GetMMU().HostTryReadU8(thread_guard, address + num_read, auto value = system.GetMMU().HostTryRead<u8>(thread_guard, address + num_read,
PowerPC::RequestedAddressSpace::Physical); PowerPC::RequestedAddressSpace::Physical);
if (!value.has_value()) if (!value.has_value())
return num_read; return num_read;
buffer[num_read] = value.value().value; buffer[num_read] = value.value().value;
+19 -17
View File
@@ -434,7 +434,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd
const u32 data) const u32 data)
{ {
const u32 new_addr = addr.GCAddress(); const u32 new_addr = addr.GCAddress();
const u32 ptr = PowerPC::MMU::HostRead_U32(guard, new_addr); const u32 ptr = PowerPC::MMU::HostRead<u32>(guard, new_addr);
LogInfo("Hardware Address: {:08x}", new_addr); LogInfo("Hardware Address: {:08x}", new_addr);
LogInfo("Size: {:08x}", addr.size); LogInfo("Size: {:08x}", addr.size);
@@ -503,16 +503,17 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add
case DATATYPE_8BIT: case DATATYPE_8BIT:
LogInfo("8-bit Add"); LogInfo("8-bit Add");
LogInfo("--------"); LogInfo("--------");
ApplyMemoryPatch<u8>(guard, PowerPC::MMU::HostRead_U8(guard, new_addr) + data, new_addr); ApplyMemoryPatch<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("Wrote {:02x} to address {:08x}", PowerPC::MMU::HostRead<u8>(guard, new_addr),
new_addr);
LogInfo("--------"); LogInfo("--------");
break; break;
case DATATYPE_16BIT: case DATATYPE_16BIT:
LogInfo("16-bit Add"); LogInfo("16-bit Add");
LogInfo("--------"); LogInfo("--------");
ApplyMemoryPatch<u16>(guard, PowerPC::MMU::HostRead_U16(guard, new_addr) + data, new_addr); ApplyMemoryPatch<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), LogInfo("Wrote {:04x} to address {:08x}", PowerPC::MMU::HostRead<u16>(guard, new_addr),
new_addr); new_addr);
LogInfo("--------"); LogInfo("--------");
break; break;
@@ -520,8 +521,8 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add
case DATATYPE_32BIT: case DATATYPE_32BIT:
LogInfo("32-bit Add"); LogInfo("32-bit Add");
LogInfo("--------"); LogInfo("--------");
ApplyMemoryPatch<u32>(guard, PowerPC::MMU::HostRead_U32(guard, new_addr) + data, new_addr); ApplyMemoryPatch<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), LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead<u32>(guard, new_addr),
new_addr); new_addr);
LogInfo("--------"); LogInfo("--------");
break; break;
@@ -531,7 +532,7 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add
LogInfo("32-bit floating Add"); LogInfo("32-bit floating Add");
LogInfo("--------"); LogInfo("--------");
const u32 read = PowerPC::MMU::HostRead_U32(guard, new_addr); const u32 read = PowerPC::MMU::HostRead<u32>(guard, new_addr);
const float read_float = std::bit_cast<float>(read); const float read_float = std::bit_cast<float>(read);
// data contains an (unsigned?) integer value // data contains an (unsigned?) integer value
const float fread = read_float + static_cast<float>(data); const float fread = read_float + static_cast<float>(data);
@@ -666,14 +667,14 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val
{ // Memory Copy With Pointers Support { // Memory Copy With Pointers Support
LogInfo("Memory Copy With Pointers Support"); LogInfo("Memory Copy With Pointers Support");
LogInfo("--------"); LogInfo("--------");
const u32 ptr_dest = PowerPC::MMU::HostRead_U32(guard, addr_dest); const u32 ptr_dest = PowerPC::MMU::HostRead<u32>(guard, addr_dest);
LogInfo("Resolved Dest Address to: {:08x}", ptr_dest); LogInfo("Resolved Dest Address to: {:08x}", ptr_dest);
const u32 ptr_src = PowerPC::MMU::HostRead_U32(guard, addr_src); const u32 ptr_src = PowerPC::MMU::HostRead<u32>(guard, addr_src);
LogInfo("Resolved Src Address to: {:08x}", ptr_src); LogInfo("Resolved Src Address to: {:08x}", ptr_src);
for (int i = 0; i < num_bytes; ++i) for (int i = 0; i < num_bytes; ++i)
{ {
ApplyMemoryPatch<u8>(guard, PowerPC::MMU::HostRead_U8(guard, ptr_src + i), ptr_dest + i); ApplyMemoryPatch<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), LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead<u8>(guard, ptr_src + i),
ptr_dest + i); ptr_dest + i);
} }
LogInfo("--------"); LogInfo("--------");
@@ -684,8 +685,8 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val
LogInfo("--------"); LogInfo("--------");
for (int i = 0; i < num_bytes; ++i) for (int i = 0; i < num_bytes; ++i)
{ {
ApplyMemoryPatch<u8>(guard, PowerPC::MMU::HostRead_U8(guard, addr_src + i), addr_dest + i); ApplyMemoryPatch<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), LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead<u8>(guard, addr_src + i),
addr_dest + i); addr_dest + i);
} }
LogInfo("--------"); LogInfo("--------");
@@ -793,16 +794,17 @@ static bool ConditionalCode(const Core::CPUThreadGuard& guard, const ARAddr& add
switch (addr.size) switch (addr.size)
{ {
case DATATYPE_8BIT: case DATATYPE_8BIT:
result = CompareValues(PowerPC::MMU::HostRead_U8(guard, new_addr), (data & 0xFF), addr.type); result = CompareValues(PowerPC::MMU::HostRead<u8>(guard, new_addr), (data & 0xFF), addr.type);
break; break;
case DATATYPE_16BIT: case DATATYPE_16BIT:
result = CompareValues(PowerPC::MMU::HostRead_U16(guard, new_addr), (data & 0xFFFF), addr.type); result =
CompareValues(PowerPC::MMU::HostRead<u16>(guard, new_addr), (data & 0xFFFF), addr.type);
break; break;
case DATATYPE_32BIT_FLOAT: case DATATYPE_32BIT_FLOAT:
case DATATYPE_32BIT: case DATATYPE_32BIT:
result = CompareValues(PowerPC::MMU::HostRead_U32(guard, new_addr), data, addr.type); result = CompareValues(PowerPC::MMU::HostRead<u32>(guard, new_addr), data, addr.type);
break; break;
default: default:
+22 -21
View File
@@ -52,7 +52,7 @@ void PresetTimeBaseTicks(Core::System& system, const Core::CPUThreadGuard& guard
const u64 time_base_ticks = emulated_time * 40500000ULL; const u64 time_base_ticks = emulated_time * 40500000ULL;
PowerPC::MMU::HostWrite_U64(guard, time_base_ticks, 0x800030D8); PowerPC::MMU::HostWrite<u64>(guard, time_base_ticks, 0x800030D8);
} }
} // Anonymous namespace } // Anonymous namespace
@@ -172,14 +172,14 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard
ppc_state.gpr[4] = iAppLoaderFuncAddr + 4; ppc_state.gpr[4] = iAppLoaderFuncAddr + 4;
ppc_state.gpr[5] = iAppLoaderFuncAddr + 8; ppc_state.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(system, *entry); RunFunction(system, *entry);
const u32 iAppLoaderInit = mmu.Read_U32(iAppLoaderFuncAddr + 0); const u32 iAppLoaderInit = mmu.Read<u32>(iAppLoaderFuncAddr + 0);
const u32 iAppLoaderMain = mmu.Read_U32(iAppLoaderFuncAddr + 4); const u32 iAppLoaderMain = mmu.Read<u32>(iAppLoaderFuncAddr + 4);
const u32 iAppLoaderClose = mmu.Read_U32(iAppLoaderFuncAddr + 8); const u32 iAppLoaderClose = mmu.Read<u32>(iAppLoaderFuncAddr + 8);
// iAppLoaderInit // iAppLoaderInit
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit"); DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit");
PowerPC::MMU::HostWrite_U32(guard, 0x4E800020, 0x81300000); // Write BLR PowerPC::MMU::HostWrite<u32>(guard, 0x4E800020, 0x81300000); // Write BLR
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
ppc_state.gpr[3] = 0x81300000; ppc_state.gpr[3] = 0x81300000;
RunFunction(system, iAppLoaderInit); RunFunction(system, iAppLoaderInit);
@@ -200,9 +200,9 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard
// iAppLoaderMain returns 0 when there are no more sections to copy. // iAppLoaderMain returns 0 when there are no more sections to copy.
while (ppc_state.gpr[3] != 0x00) while (ppc_state.gpr[3] != 0x00)
{ {
const u32 ram_address = mmu.Read_U32(0x81300004); const u32 ram_address = mmu.Read<u32>(0x81300004);
const u32 length = mmu.Read_U32(0x81300008); const u32 length = mmu.Read<u32>(0x81300008);
const u32 dvd_offset = mmu.Read_U32(0x8130000c) << (is_wii ? 2 : 0); const u32 dvd_offset = mmu.Read<u32>(0x8130000c) << (is_wii ? 2 : 0);
INFO_LOG_FMT(BOOT, "DVDRead: offset: {:08x} memOffset: {:08x} length: {}", dvd_offset, INFO_LOG_FMT(BOOT, "DVDRead: offset: {:08x} memOffset: {:08x} length: {}", dvd_offset,
ram_address, length); ram_address, length);
@@ -243,35 +243,36 @@ void CBoot::SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guar
auto& memory = system.GetMemory(); auto& memory = system.GetMemory();
// Booted from bootrom. 0xE5207C22 = booted from jtag // Booted from bootrom. 0xE5207C22 = booted from jtag
PowerPC::MMU::HostWrite_U32(guard, 0x0D15EA5E, 0x80000020); PowerPC::MMU::HostWrite<u32>(guard, 0x0D15EA5E, 0x80000020);
// Physical Memory Size (24MB on retail) // Physical Memory Size (24MB on retail)
PowerPC::MMU::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 // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
// TODO: determine why some games fail when using a retail ID. // TODO: determine why some games fail when using a retail ID.
// (Seem to take different EXI paths, see Ikaruga for example) // (Seem to take different EXI paths, see Ikaruga for example)
const u32 console_type = static_cast<u32>(Core::ConsoleType::LatestDevkit); const u32 console_type = static_cast<u32>(Core::ConsoleType::LatestDevkit);
PowerPC::MMU::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) // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
PowerPC::MMU::HostWrite_U32(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, PowerPC::MMU::HostWrite<u32>(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1,
0x800000CC); 0x800000CC);
// ARAM Size. 16MB main + 4/16/32MB external. (retail consoles have no external ARAM) // ARAM Size. 16MB main + 4/16/32MB external. (retail consoles have no external ARAM)
PowerPC::MMU::HostWrite_U32(guard, 0x01000000, 0x800000d0); PowerPC::MMU::HostWrite<u32>(guard, 0x01000000, 0x800000d0);
PowerPC::MMU::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed PowerPC::MMU::HostWrite<u32>(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed
PowerPC::MMU::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed PowerPC::MMU::HostWrite<u32>(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed
PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI 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, 0x80000800); // Write default FPU Handler: rfi
PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi PowerPC::MMU::HostWrite<u32>(guard, 0x4c000064,
0x80000C00); // Write default Syscall Handler: rfi
PresetTimeBaseTicks(system, guard); PresetTimeBaseTicks(system, guard);
// HIO checks this // HIO checks this
// PowerPC::MMU::HostWrite_U16(0x8200, 0x000030e6); // Console type // PowerPC::MMU::HostWrite<u16>(guard, 0x8200, 0x000030e6); // Console type
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
+1 -93
View File
@@ -100,106 +100,14 @@ std::vector<u8> Cheats::GetValueAsByteVector(const Cheats::SearchValue& value)
} }
} }
namespace
{
template <typename T> template <typename T>
static std::optional<PowerPC::ReadResult<T>> static std::optional<PowerPC::ReadResult<T>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space);
template <>
std::optional<PowerPC::ReadResult<u8>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr, TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space) PowerPC::RequestedAddressSpace space)
{ {
return PowerPC::MMU::HostTryReadU8(guard, addr, space); return PowerPC::MMU::HostTryRead<T>(guard, addr, space);
} }
template <>
std::optional<PowerPC::ReadResult<u16>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::MMU::HostTryReadU16(guard, addr, space);
}
template <>
std::optional<PowerPC::ReadResult<u32>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::MMU::HostTryReadU32(guard, addr, space);
}
template <>
std::optional<PowerPC::ReadResult<u64>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::MMU::HostTryReadU64(guard, addr, space);
}
template <>
std::optional<PowerPC::ReadResult<s8>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::MMU::HostTryReadU8(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s8>(tmp->translated, std::bit_cast<s8>(tmp->value));
}
template <>
std::optional<PowerPC::ReadResult<s16>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::MMU::HostTryReadU16(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s16>(tmp->translated, std::bit_cast<s16>(tmp->value));
}
template <>
std::optional<PowerPC::ReadResult<s32>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::MMU::HostTryReadU32(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s32>(tmp->translated, std::bit_cast<s32>(tmp->value));
}
template <>
std::optional<PowerPC::ReadResult<s64>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::MMU::HostTryReadU64(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s64>(tmp->translated, std::bit_cast<s64>(tmp->value));
}
template <>
std::optional<PowerPC::ReadResult<float>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::MMU::HostTryReadF32(guard, addr, space);
}
template <>
std::optional<PowerPC::ReadResult<double>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::MMU::HostTryReadF64(guard, addr, space);
}
} // namespace
template <typename T> template <typename T>
Common::Result<Cheats::SearchErrorCode, std::vector<Cheats::SearchResult<T>>> Common::Result<Cheats::SearchErrorCode, std::vector<Cheats::SearchResult<T>>>
Cheats::NewSearch(const Core::CPUThreadGuard& guard, Cheats::NewSearch(const Core::CPUThreadGuard& guard,
@@ -34,18 +34,18 @@ static void WalkTheStack(const Core::CPUThreadGuard& guard,
if (!IsStackBottom(guard, ppc_state.gpr[1])) if (!IsStackBottom(guard, ppc_state.gpr[1]))
{ {
u32 addr = PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[1]); // SP u32 addr = PowerPC::MMU::HostRead<u32>(guard, ppc_state.gpr[1]); // SP
// Walk the stack chain // Walk the stack chain
for (int count = 0; !IsStackBottom(guard, addr + 4) && (count < 20); ++count) for (int count = 0; !IsStackBottom(guard, addr + 4) && (count < 20); ++count)
{ {
u32 func_addr = PowerPC::MMU::HostRead_U32(guard, addr + 4); u32 func_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 4);
stack_step(func_addr); stack_step(func_addr);
if (IsStackBottom(guard, addr)) if (IsStackBottom(guard, addr))
break; break;
addr = PowerPC::MMU::HostRead_U32(guard, addr); addr = PowerPC::MMU::HostRead<u32>(guard, addr);
} }
} }
} }
+41 -41
View File
@@ -19,23 +19,23 @@ namespace Core::Debug
void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr) void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr)
{ {
for (std::size_t i = 0; i < gpr.size(); i++) for (std::size_t i = 0; i < gpr.size(); i++)
gpr[i] = PowerPC::MMU::HostRead_U32(guard, addr + u32(i * sizeof(int))); gpr[i] = PowerPC::MMU::HostRead<u32>(guard, addr + u32(i * sizeof(int)));
cr = PowerPC::MMU::HostRead_U32(guard, addr + 0x80); cr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x80);
lr = PowerPC::MMU::HostRead_U32(guard, addr + 0x84); lr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x84);
ctr = PowerPC::MMU::HostRead_U32(guard, addr + 0x88); ctr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x88);
xer = PowerPC::MMU::HostRead_U32(guard, addr + 0x8C); xer = PowerPC::MMU::HostRead<u32>(guard, addr + 0x8C);
for (std::size_t i = 0; i < fpr.size(); i++) for (std::size_t i = 0; i < fpr.size(); i++)
fpr[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double))); fpr[i] = PowerPC::MMU::HostRead<double>(guard, addr + 0x90 + u32(i * sizeof(double)));
fpscr = PowerPC::MMU::HostRead_U64(guard, addr + 0x190); fpscr = PowerPC::MMU::HostRead<u64>(guard, addr + 0x190);
srr0 = PowerPC::MMU::HostRead_U32(guard, addr + 0x198); srr0 = PowerPC::MMU::HostRead<u32>(guard, addr + 0x198);
srr1 = PowerPC::MMU::HostRead_U32(guard, addr + 0x19c); srr1 = PowerPC::MMU::HostRead<u32>(guard, addr + 0x19c);
dummy = PowerPC::MMU::HostRead_U16(guard, addr + 0x1a0); dummy = PowerPC::MMU::HostRead<u16>(guard, addr + 0x1a0);
state = static_cast<OSContext::State>(PowerPC::MMU::HostRead_U16(guard, addr + 0x1a2)); state = static_cast<OSContext::State>(PowerPC::MMU::HostRead<u16>(guard, addr + 0x1a2));
for (std::size_t i = 0; i < gqr.size(); i++) for (std::size_t i = 0; i < gqr.size(); i++)
gqr[i] = PowerPC::MMU::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; psf_padding = 0;
for (std::size_t i = 0; i < psf.size(); i++) for (std::size_t i = 0; i < psf.size(); i++)
psf[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double))); psf[i] = PowerPC::MMU::HostRead<double>(guard, addr + 0x1c8 + u32(i * sizeof(double)));
} }
// Mutex offsets based on the following functions: // Mutex offsets based on the following functions:
@@ -44,12 +44,12 @@ void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr)
// - __OSUnlockAllMutex // - __OSUnlockAllMutex
void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr) void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr)
{ {
thread_queue.head = PowerPC::MMU::HostRead_U32(guard, addr); thread_queue.head = PowerPC::MMU::HostRead<u32>(guard, addr);
thread_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x4); thread_queue.tail = PowerPC::MMU::HostRead<u32>(guard, addr + 0x4);
owner_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x8); owner_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x8);
lock_count = PowerPC::MMU::HostRead_U32(guard, addr + 0xc); lock_count = PowerPC::MMU::HostRead<u32>(guard, addr + 0xc);
link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x10); link.next = PowerPC::MMU::HostRead<u32>(guard, addr + 0x10);
link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x14); link.prev = PowerPC::MMU::HostRead<u32>(guard, addr + 0x14);
} }
// Thread offsets based on the following functions: // 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) void OSThread::Read(const Core::CPUThreadGuard& guard, u32 addr)
{ {
context.Read(guard, addr); context.Read(guard, addr);
state = PowerPC::MMU::HostRead_U16(guard, addr + 0x2c8); state = PowerPC::MMU::HostRead<u16>(guard, addr + 0x2c8);
is_detached = PowerPC::MMU::HostRead_U16(guard, addr + 0x2ca); is_detached = PowerPC::MMU::HostRead<u16>(guard, addr + 0x2ca);
suspend = PowerPC::MMU::HostRead_U32(guard, addr + 0x2cc); suspend = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2cc);
effective_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d0); effective_priority = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2d0);
base_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d4); base_priority = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2d4);
exit_code_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d8); exit_code_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2d8);
queue_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2dc); queue_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2dc);
queue_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e0); queue_link.next = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2e0);
queue_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e4); queue_link.prev = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2e4);
join_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e8); join_queue.head = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2e8);
join_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2ec); join_queue.tail = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2ec);
mutex_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f0); mutex_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2f0);
mutex_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f4); mutex_queue.head = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2f4);
mutex_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f8); mutex_queue.tail = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2f8);
thread_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2fc); thread_link.next = PowerPC::MMU::HostRead<u32>(guard, addr + 0x2fc);
thread_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x300); thread_link.prev = PowerPC::MMU::HostRead<u32>(guard, addr + 0x300);
stack_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x304); stack_addr = PowerPC::MMU::HostRead<u32>(guard, addr + 0x304);
stack_end = PowerPC::MMU::HostRead_U32(guard, addr + 0x308); stack_end = PowerPC::MMU::HostRead<u32>(guard, addr + 0x308);
error = PowerPC::MMU::HostRead_U32(guard, addr + 0x30c); error = PowerPC::MMU::HostRead<u32>(guard, addr + 0x30c);
specific[0] = PowerPC::MMU::HostRead_U32(guard, addr + 0x310); specific[0] = PowerPC::MMU::HostRead<u32>(guard, addr + 0x310);
specific[1] = PowerPC::MMU::HostRead_U32(guard, addr + 0x314); specific[1] = PowerPC::MMU::HostRead<u32>(guard, addr + 0x314);
} }
bool OSThread::IsValid(const Core::CPUThreadGuard& guard) const bool OSThread::IsValid(const Core::CPUThreadGuard& guard) const
{ {
return PowerPC::MMU::HostIsRAMAddress(guard, stack_end) && return PowerPC::MMU::HostIsRAMAddress(guard, stack_end) &&
PowerPC::MMU::HostRead_U32(guard, stack_end) == STACK_MAGIC; PowerPC::MMU::HostRead<u32>(guard, stack_end) == STACK_MAGIC;
} }
OSThreadView::OSThreadView(const Core::CPUThreadGuard& guard, u32 addr) OSThreadView::OSThreadView(const Core::CPUThreadGuard& guard, u32 addr)
@@ -47,10 +47,10 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, std::span<u8> value, co
bool should_invalidate_cache = false; bool should_invalidate_cache = false;
for (u32 offset = 0; offset < size; ++offset) for (u32 offset = 0; offset < size; ++offset)
{ {
u8 old_value = PowerPC::MMU::HostRead_U8(guard, address + offset); u8 old_value = PowerPC::MMU::HostRead<u8>(guard, address + offset);
if (old_value != value[offset]) if (old_value != value[offset])
{ {
PowerPC::MMU::HostWrite_U8(guard, value[offset], address + offset); PowerPC::MMU::HostWrite<u8>(guard, value[offset], address + offset);
should_invalidate_cache = true; should_invalidate_cache = true;
if (store_existing_value) if (store_existing_value)
value[offset] = old_value; value[offset] = old_value;
@@ -245,7 +245,7 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc; constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc;
if (!PowerPC::MMU::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR)) if (!PowerPC::MMU::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR))
return threads; return threads;
const u32 active_queue_head = PowerPC::MMU::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR); const u32 active_queue_head = PowerPC::MMU::HostRead<u32>(guard, ACTIVE_QUEUE_HEAD_ADDR);
if (!PowerPC::MMU::HostIsRAMAddress(guard, active_queue_head)) if (!PowerPC::MMU::HostIsRAMAddress(guard, active_queue_head))
return threads; return threads;
@@ -326,7 +326,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu
u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const
{ {
return PowerPC::MMU::HostRead_U32(guard, address); return PowerPC::MMU::HostRead<u32>(guard, address);
} }
u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory, u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory,
@@ -335,7 +335,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me
switch (memory) switch (memory)
{ {
case 0: case 0:
return PowerPC::MMU::HostRead_U32(guard, address); return PowerPC::MMU::HostRead<u32>(guard, address);
case 1: case 1:
{ {
const auto& dsp = guard.GetSystem().GetDSP(); const auto& dsp = guard.GetSystem().GetDSP();
+41 -40
View File
@@ -17,31 +17,32 @@
void RSOHeaderView::Load(const Core::CPUThreadGuard& guard, u32 address) void RSOHeaderView::Load(const Core::CPUThreadGuard& guard, u32 address)
{ {
m_address = address; m_address = address;
m_header.entry.next_entry = PowerPC::MMU::HostRead_U32(guard, address); 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.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_count = PowerPC::MMU::HostRead<u32>(guard, address + 0x08);
m_header.entry.section_table_offset = PowerPC::MMU::HostRead_U32(guard, address + 0xC); 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_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x10);
m_header.entry.name_size = PowerPC::MMU::HostRead_U32(guard, address + 0x14); 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.version = PowerPC::MMU::HostRead<u32>(guard, address + 0x18);
m_header.entry.bss_size = PowerPC::MMU::HostRead_U32(guard, address + 0x1C); 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.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.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.unresolved_section_index =
m_header.section_info.bss_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x23); PowerPC::MMU::HostRead<u8>(guard, address + 0x22);
m_header.section_info.prolog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x24); m_header.section_info.bss_section_index = PowerPC::MMU::HostRead<u8>(guard, address + 0x23);
m_header.section_info.epilog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x28); m_header.section_info.prolog_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x24);
m_header.section_info.unresolved_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x2C); m_header.section_info.epilog_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x28);
m_header.relocation_tables.internals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x30); m_header.section_info.unresolved_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x2C);
m_header.relocation_tables.internals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x34); m_header.relocation_tables.internals_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x30);
m_header.relocation_tables.externals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x38); m_header.relocation_tables.internals_size = PowerPC::MMU::HostRead<u32>(guard, address + 0x34);
m_header.relocation_tables.externals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x3C); m_header.relocation_tables.externals_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x38);
m_header.symbol_tables.exports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x40); m_header.relocation_tables.externals_size = PowerPC::MMU::HostRead<u32>(guard, address + 0x3C);
m_header.symbol_tables.exports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x44); m_header.symbol_tables.exports_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x40);
m_header.symbol_tables.exports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x48); m_header.symbol_tables.exports_size = PowerPC::MMU::HostRead<u32>(guard, address + 0x44);
m_header.symbol_tables.imports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x4C); m_header.symbol_tables.exports_name_table = PowerPC::MMU::HostRead<u32>(guard, address + 0x48);
m_header.symbol_tables.imports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x50); m_header.symbol_tables.imports_offset = PowerPC::MMU::HostRead<u32>(guard, address + 0x4C);
m_header.symbol_tables.imports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x54); 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 // Prevent an invalid name going wild
if (m_header.entry.name_size < 0x100) if (m_header.entry.name_size < 0x100)
@@ -181,8 +182,8 @@ void RSOSectionsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
RSOSection section; RSOSection section;
section.offset = PowerPC::MMU::HostRead_U32(guard, address); section.offset = PowerPC::MMU::HostRead<u32>(guard, address);
section.size = PowerPC::MMU::HostRead_U32(guard, address + 4); section.size = PowerPC::MMU::HostRead<u32>(guard, address + 4);
m_sections.emplace_back(std::move(section)); m_sections.emplace_back(std::move(section));
address += sizeof(RSOSection); address += sizeof(RSOSection);
} }
@@ -209,9 +210,9 @@ void RSOImportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
RSOImport rso_import; RSOImport rso_import;
rso_import.name_offset = PowerPC::MMU::HostRead_U32(guard, address); rso_import.name_offset = PowerPC::MMU::HostRead<u32>(guard, address);
rso_import.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4); rso_import.code_offset = PowerPC::MMU::HostRead<u32>(guard, address + 4);
rso_import.entry_offset = PowerPC::MMU::HostRead_U32(guard, address + 8); rso_import.entry_offset = PowerPC::MMU::HostRead<u32>(guard, address + 8);
m_imports.emplace_back(std::move(rso_import)); m_imports.emplace_back(std::move(rso_import));
address += sizeof(RSOImport); address += sizeof(RSOImport);
} }
@@ -238,10 +239,10 @@ void RSOExportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
RSOExport rso_export; RSOExport rso_export;
rso_export.name_offset = PowerPC::MMU::HostRead_U32(guard, address); rso_export.name_offset = PowerPC::MMU::HostRead<u32>(guard, address);
rso_export.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4); rso_export.code_offset = PowerPC::MMU::HostRead<u32>(guard, address + 4);
rso_export.section_index = PowerPC::MMU::HostRead_U32(guard, address + 8); rso_export.section_index = PowerPC::MMU::HostRead<u32>(guard, address + 8);
rso_export.hash = PowerPC::MMU::HostRead_U32(guard, address + 12); rso_export.hash = PowerPC::MMU::HostRead<u32>(guard, address + 12);
m_exports.emplace_back(std::move(rso_export)); m_exports.emplace_back(std::move(rso_export));
address += sizeof(RSOExport); address += sizeof(RSOExport);
} }
@@ -268,9 +269,9 @@ void RSOInternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std:
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
RSOInternalsEntry entry; RSOInternalsEntry entry;
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address); entry.r_offset = PowerPC::MMU::HostRead<u32>(guard, address);
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4); entry.r_info = PowerPC::MMU::HostRead<u32>(guard, address + 4);
entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8); entry.r_addend = PowerPC::MMU::HostRead<u32>(guard, address + 8);
m_entries.emplace_back(std::move(entry)); m_entries.emplace_back(std::move(entry));
address += sizeof(RSOInternalsEntry); address += sizeof(RSOInternalsEntry);
} }
@@ -297,9 +298,9 @@ void RSOExternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std:
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
RSOExternalsEntry entry; RSOExternalsEntry entry;
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address); entry.r_offset = PowerPC::MMU::HostRead<u32>(guard, address);
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4); entry.r_info = PowerPC::MMU::HostRead<u32>(guard, address + 4);
entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8); entry.r_addend = PowerPC::MMU::HostRead<u32>(guard, address + 8);
m_entries.emplace_back(std::move(entry)); m_entries.emplace_back(std::move(entry));
address += sizeof(RSOExternalsEntry); address += sizeof(RSOExternalsEntry);
} }
+4 -4
View File
@@ -706,12 +706,12 @@ void FifoPlayer::LoadTextureMemory()
void FifoPlayer::WriteCP(u32 address, u16 value) void FifoPlayer::WriteCP(u32 address, u16 value)
{ {
m_system.GetMMU().Write_U16(value, 0xCC000000 | address); m_system.GetMMU().Write<u16>(value, 0xCC000000 | address);
} }
void FifoPlayer::WritePI(u32 address, u32 value) void FifoPlayer::WritePI(u32 address, u32 value)
{ {
m_system.GetMMU().Write_U32(value, 0xCC003000 | address); m_system.GetMMU().Write<u32>(value, 0xCC003000 | address);
} }
void FifoPlayer::FlushWGP() void FifoPlayer::FlushWGP()
@@ -810,13 +810,13 @@ bool FifoPlayer::ShouldLoadXF(u8 reg)
bool FifoPlayer::IsIdleSet() const bool FifoPlayer::IsIdleSet() const
{ {
CommandProcessor::UCPStatusReg status = CommandProcessor::UCPStatusReg status =
m_system.GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); m_system.GetMMU().Read<u16>(0xCC000000 | CommandProcessor::STATUS_REGISTER);
return status.CommandIdle; return status.CommandIdle;
} }
bool FifoPlayer::IsHighWatermarkSet() const bool FifoPlayer::IsHighWatermarkSet() const
{ {
CommandProcessor::UCPStatusReg status = CommandProcessor::UCPStatusReg status =
m_system.GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER); m_system.GetMMU().Read<u16>(0xCC000000 | CommandProcessor::STATUS_REGISTER);
return status.OverflowHiWatermark; return status.OverflowHiWatermark;
} }
+20 -20
View File
@@ -139,17 +139,17 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
// Install code handler // Install code handler
for (u32 i = 0; i < data.size(); ++i) for (u32 i = 0; i < data.size(); ++i)
PowerPC::MMU::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) // Patch the code handler to the current system type (Gamecube/Wii)
for (u32 h = 0; h < data.length(); h += 4) for (u32 h = 0; h < data.length(); h += 4)
{ {
// Patch MMIO address // Patch MMIO address
if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) == if (PowerPC::MMU::HostRead<u32>(guard, INSTALLER_BASE_ADDRESS + h) ==
(0x3f000000u | ((mmio_addr ^ 1) << 8))) (0x3f000000u | ((mmio_addr ^ 1) << 8)))
{ {
NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h); NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h);
PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h); PowerPC::MMU::HostWrite<u32>(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h);
} }
} }
@@ -159,11 +159,11 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
// Write a magic value to 'gameid' (codehandleronly does not actually read this). // 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. // This value will be read back and modified over time by HLE_Misc::GeckoCodeHandlerICacheFlush.
PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS); PowerPC::MMU::HostWrite<u32>(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS);
// Create GCT in memory // Create GCT in memory
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); PowerPC::MMU::HostWrite<u32>(guard, 0x00d0c0de, codelist_base_address);
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); 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. // 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; const u32 start_address = codelist_base_address + CODE_SIZE;
@@ -186,8 +186,8 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
for (const GeckoCode::Code& code : active_code.codes) for (const GeckoCode::Code& code : active_code.codes)
{ {
PowerPC::MMU::HostWrite_U32(guard, code.address, next_address); PowerPC::MMU::HostWrite<u32>(guard, code.address, next_address);
PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4); PowerPC::MMU::HostWrite<u32>(guard, code.data, next_address + 4);
next_address += CODE_SIZE; next_address += CODE_SIZE;
} }
} }
@@ -196,12 +196,12 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
end_address - start_address); end_address - start_address);
// Stop code. Tells the handler that this is the end of the list. // Stop code. Tells the handler that this is the end of the list.
PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address); PowerPC::MMU::HostWrite<u32>(guard, 0xF0000000, next_address);
PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4); PowerPC::MMU::HostWrite<u32>(guard, 0x00000000, next_address + 4);
PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); PowerPC::MMU::HostWrite<u32>(guard, 0, HLE_TRAMPOLINE_ADDRESS);
// Turn on codes // Turn on codes
PowerPC::MMU::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7); PowerPC::MMU::HostWrite<u8>(guard, 1, INSTALLER_BASE_ADDRESS + 7);
// Invalidate the icache and any asm codes // Invalidate the icache and any asm codes
auto& ppc_state = guard.GetSystem().GetPPCState(); auto& ppc_state = guard.GetSystem().GetPPCState();
@@ -271,18 +271,18 @@ void RunCodeHandler(const Core::CPUThreadGuard& guard)
ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler
ppc_state.gpr[1] &= 0xFFFFFFF0; // Align stack to 16bytes ppc_state.gpr[1] &= 0xFFFFFFF0; // Align stack to 16bytes
u32 SP = ppc_state.gpr[1]; // Stack Pointer u32 SP = ppc_state.gpr[1]; // Stack Pointer
PowerPC::MMU::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. // SP + 4 is reserved for the codehandler to save LR to the stack.
PowerPC::MMU::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame 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, ppc_state.pc, SP + 12);
PowerPC::MMU::HostWrite_U32(guard, LR(ppc_state), SP + 16); PowerPC::MMU::HostWrite<u32>(guard, LR(ppc_state), SP + 16);
PowerPC::MMU::HostWrite_U32(guard, ppc_state.cr.Get(), SP + 20); PowerPC::MMU::HostWrite<u32>(guard, ppc_state.cr.Get(), SP + 20);
// Registers FPR0->13 are volatile // Registers FPR0->13 are volatile
for (u32 i = 0; i < 14; ++i) for (u32 i = 0; i < 14; ++i)
{ {
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].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64));
PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(), PowerPC::MMU::HostWrite<u64>(guard, ppc_state.ps[i].PS1AsU64(),
SP + 24 + (2 * i + 1) * sizeof(u64)); SP + 24 + (2 * i + 1) * sizeof(u64));
} }
DEBUG_LOG_FMT(ACTIONREPLAY, DEBUG_LOG_FMT(ACTIONREPLAY,
"GeckoCodes: Initiating phantom branch-and-link. " "GeckoCodes: Initiating phantom branch-and-link. "
+9 -8
View File
@@ -44,7 +44,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard)
// been read into memory, or such, so we do the first 5 frames. More // 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 // robust alternative would be to actually detect memory writes, but that
// would be even uglier.) // would be even uglier.)
u32 gch_gameid = PowerPC::MMU::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) if (gch_gameid - Gecko::MAGIC_GAMEID == 5)
{ {
return; return;
@@ -53,7 +53,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard)
{ {
gch_gameid = Gecko::MAGIC_GAMEID; gch_gameid = Gecko::MAGIC_GAMEID;
} }
PowerPC::MMU::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(jit_interface); ppc_state.iCache.Reset(jit_interface);
} }
@@ -69,14 +69,15 @@ void GeckoReturnTrampoline(const Core::CPUThreadGuard& guard)
// Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler. // Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler.
const u32 SP = ppc_state.gpr[1]; const u32 SP = ppc_state.gpr[1];
ppc_state.gpr[1] = PowerPC::MMU::HostRead_U32(guard, SP + 8); ppc_state.gpr[1] = PowerPC::MMU::HostRead<u32>(guard, SP + 8);
ppc_state.npc = PowerPC::MMU::HostRead_U32(guard, SP + 12); ppc_state.npc = PowerPC::MMU::HostRead<u32>(guard, SP + 12);
LR(ppc_state) = PowerPC::MMU::HostRead_U32(guard, SP + 16); LR(ppc_state) = PowerPC::MMU::HostRead<u32>(guard, SP + 16);
ppc_state.cr.Set(PowerPC::MMU::HostRead_U32(guard, SP + 20)); ppc_state.cr.Set(PowerPC::MMU::HostRead<u32>(guard, SP + 20));
for (int i = 0; i < 14; ++i) for (int i = 0; i < 14; ++i)
{ {
ppc_state.ps[i].SetBoth(PowerPC::MMU::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)), ppc_state.ps[i].SetBoth(
PowerPC::MMU::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64))); 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 } // namespace HLE_Misc
+6 -5
View File
@@ -62,8 +62,9 @@ static void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterTy
// Is gpr3 pointing to a pointer (including nullptr) rather than an ASCII string // Is gpr3 pointing to a pointer (including nullptr) rather than an ASCII string
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) && if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
(PowerPC::MMU::HostIsRAMAddress(guard, PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3])) || (PowerPC::MMU::HostIsRAMAddress(guard,
PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3]) == 0)) PowerPC::MMU::HostRead<u32>(guard, ppc_state.gpr[3])) ||
PowerPC::MMU::HostRead<u32>(guard, ppc_state.gpr[3]) == 0))
{ {
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[4])) if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[4]))
{ {
@@ -117,7 +118,7 @@ void HLE_write_console(const Core::CPUThreadGuard& guard)
std::string report_message = GetStringVA(system, guard, 4); std::string report_message = GetStringVA(system, guard, 4);
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5])) if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5]))
{ {
const u32 size = system.GetMMU().Read_U32(ppc_state.gpr[5]); const u32 size = system.GetMMU().Read<u32>(ppc_state.gpr[5]);
if (size > report_message.size()) if (size > report_message.size())
WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size); WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size);
else if (size == 0) else if (size == 0)
@@ -178,12 +179,12 @@ static void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType param
PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF)) PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF))
{ {
// The fd is stored as a short at FILE+0xE. // The fd is stored as a short at FILE+0xE.
fd = static_cast<short>(PowerPC::MMU::HostRead_U16(guard, ppc_state.gpr[3] + 0xE)); fd = static_cast<short>(PowerPC::MMU::HostRead<u16>(guard, ppc_state.gpr[3] + 0xE));
} }
if (fd != 1 && fd != 2) if (fd != 1 && fd != 2)
{ {
// On RVL SDK it seems stored at FILE+0x2. // On RVL SDK it seems stored at FILE+0x2.
fd = static_cast<short>(PowerPC::MMU::HostRead_U16(guard, ppc_state.gpr[3] + 0x2)); fd = static_cast<short>(PowerPC::MMU::HostRead<u16>(guard, ppc_state.gpr[3] + 0x2));
} }
if (fd != 1 && fd != 2) if (fd != 1 && fd != 2)
return; return;
+6 -6
View File
@@ -21,10 +21,10 @@ double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const
} }
HLE::SystemVABI::VAListStruct::VAListStruct(const Core::CPUThreadGuard& guard, u32 address) HLE::SystemVABI::VAListStruct::VAListStruct(const Core::CPUThreadGuard& guard, u32 address)
: VAList(guard, 0), m_va_list{PowerPC::MMU::HostRead_U8(guard, address), : VAList(guard, 0), m_va_list{PowerPC::MMU::HostRead<u8>(guard, address),
PowerPC::MMU::HostRead_U8(guard, address + 1), PowerPC::MMU::HostRead<u8>(guard, address + 1),
PowerPC::MMU::HostRead_U32(guard, address + 4), PowerPC::MMU::HostRead<u32>(guard, address + 4),
PowerPC::MMU::HostRead_U32(guard, address + 8)}, PowerPC::MMU::HostRead<u32>(guard, address + 8)},
m_address(address), m_has_fpr_area(guard.GetSystem().GetPPCState().cr.GetBit(6) == 1) m_address(address), m_has_fpr_area(guard.GetSystem().GetPPCState().cr.GetBit(6) == 1)
{ {
m_stack = m_va_list.overflow_arg_area; m_stack = m_va_list.overflow_arg_area;
@@ -50,7 +50,7 @@ u32 HLE::SystemVABI::VAListStruct::GetGPR(u32 gpr) const
return 0; return 0;
} }
const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4); const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4);
return PowerPC::MMU::HostRead_U32(m_guard, gpr_address); return PowerPC::MMU::HostRead<u32>(m_guard, gpr_address);
} }
double HLE::SystemVABI::VAListStruct::GetFPR(u32 fpr) const double HLE::SystemVABI::VAListStruct::GetFPR(u32 fpr) const
@@ -61,5 +61,5 @@ double HLE::SystemVABI::VAListStruct::GetFPR(u32 fpr) const
return 0.0; return 0.0;
} }
const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8); const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8);
return PowerPC::MMU::HostRead_F64(m_guard, fpr_address); return PowerPC::MMU::HostRead<double>(m_guard, fpr_address);
} }
+4 -4
View File
@@ -55,7 +55,7 @@ public:
for (size_t i = 0; i < sizeof(T); i += 1, addr += 1) for (size_t i = 0; i < sizeof(T); i += 1, addr += 1)
{ {
reinterpret_cast<u8*>(&obj)[i] = PowerPC::MMU::HostRead_U8(m_guard, addr); reinterpret_cast<u8*>(&obj)[i] = PowerPC::MMU::HostRead<u8>(m_guard, addr);
} }
return obj; return obj;
@@ -76,7 +76,7 @@ public:
else else
{ {
m_stack = Common::AlignUp(m_stack, 4); m_stack = Common::AlignUp(m_stack, 4);
value = PowerPC::MMU::HostRead_U32(m_guard, m_stack); value = PowerPC::MMU::HostRead<u32>(m_guard, m_stack);
m_stack += 4; m_stack += 4;
} }
@@ -99,7 +99,7 @@ public:
else else
{ {
m_stack = Common::AlignUp(m_stack, 8); m_stack = Common::AlignUp(m_stack, 8);
value = PowerPC::MMU::HostRead_U64(m_guard, m_stack); value = PowerPC::MMU::HostRead<u64>(m_guard, m_stack);
m_stack += 8; m_stack += 8;
} }
@@ -120,7 +120,7 @@ public:
else else
{ {
m_stack = Common::AlignUp(m_stack, 8); m_stack = Common::AlignUp(m_stack, 8);
value = PowerPC::MMU::HostRead_F64(m_guard, m_stack); value = PowerPC::MMU::HostRead<double>(m_guard, m_stack);
m_stack += 8; m_stack += 8;
} }
+9 -9
View File
@@ -87,39 +87,39 @@ struct EffectiveAddressSpaceAccessors : Accessors
} }
u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override
{ {
return PowerPC::MMU::HostRead_U8(guard, address); return PowerPC::MMU::HostRead<u8>(guard, address);
} }
void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override
{ {
PowerPC::MMU::HostWrite_U8(guard, value, address); PowerPC::MMU::HostWrite<u8>(guard, value, address);
} }
u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override
{ {
return PowerPC::MMU::HostRead_U16(guard, address); return PowerPC::MMU::HostRead<u16>(guard, address);
} }
void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override
{ {
PowerPC::MMU::HostWrite_U16(guard, value, address); PowerPC::MMU::HostWrite<u16>(guard, value, address);
} }
u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override
{ {
return PowerPC::MMU::HostRead_U32(guard, address); return PowerPC::MMU::HostRead<u32>(guard, address);
} }
void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override
{ {
PowerPC::MMU::HostWrite_U32(guard, value, address); PowerPC::MMU::HostWrite<u32>(guard, value, address);
} }
u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override
{ {
return PowerPC::MMU::HostRead_U64(guard, address); return PowerPC::MMU::HostRead<u64>(guard, address);
} }
void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override
{ {
PowerPC::MMU::HostWrite_U64(guard, value, address); PowerPC::MMU::HostWrite<u64>(guard, value, address);
} }
float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override
{ {
return PowerPC::MMU::HostRead_F32(guard, address); return PowerPC::MMU::HostRead<float>(guard, address);
} }
bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start, bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start,
+1 -1
View File
@@ -72,7 +72,7 @@ u32 MemoryWatcher::ChasePointer(const Core::CPUThreadGuard& guard, const std::st
u32 value = 0; u32 value = 0;
for (u32 offset : m_addresses[line]) for (u32 offset : m_addresses[line])
{ {
value = PowerPC::MMU::HostRead_U32(guard, value + offset); value = PowerPC::MMU::HostRead<u32>(guard, value + offset);
if (!PowerPC::MMU::HostIsRAMAddress(guard, value)) if (!PowerPC::MMU::HostIsRAMAddress(guard, value))
break; break;
} }
+5 -5
View File
@@ -230,20 +230,20 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector<Pa
{ {
case PatchType::Patch8Bit: case PatchType::Patch8Bit:
if (!entry.conditional || if (!entry.conditional ||
PowerPC::MMU::HostRead_U8(guard, addr) == static_cast<u8>(comparand)) PowerPC::MMU::HostRead<u8>(guard, addr) == static_cast<u8>(comparand))
{ {
ApplyMemoryPatch<u8>(guard, static_cast<u8>(value), addr); ApplyMemoryPatch<u8>(guard, static_cast<u8>(value), addr);
} }
break; break;
case PatchType::Patch16Bit: case PatchType::Patch16Bit:
if (!entry.conditional || if (!entry.conditional ||
PowerPC::MMU::HostRead_U16(guard, addr) == static_cast<u16>(comparand)) PowerPC::MMU::HostRead<u16>(guard, addr) == static_cast<u16>(comparand))
{ {
ApplyMemoryPatch<u16>(guard, static_cast<u16>(value), addr); ApplyMemoryPatch<u16>(guard, static_cast<u16>(value), addr);
} }
break; break;
case PatchType::Patch32Bit: case PatchType::Patch32Bit:
if (!entry.conditional || PowerPC::MMU::HostRead_U32(guard, addr) == comparand) if (!entry.conditional || PowerPC::MMU::HostRead<u32>(guard, addr) == comparand)
ApplyMemoryPatch<u32>(guard, value, addr); ApplyMemoryPatch<u32>(guard, value, addr);
break; break;
default: default:
@@ -280,7 +280,7 @@ static bool IsStackValid(const Core::CPUThreadGuard& guard)
return false; return false;
// Read the frame pointer from the stack (find 2nd frame from top), assert that it makes sense // Read the frame pointer from the stack (find 2nd frame from top), assert that it makes sense
const u32 next_SP = PowerPC::MMU::HostRead_U32(guard, SP); const u32 next_SP = PowerPC::MMU::HostRead<u32>(guard, SP);
if (next_SP <= SP || !PowerPC::MMU::HostIsRAMAddress(guard, next_SP) || if (next_SP <= SP || !PowerPC::MMU::HostIsRAMAddress(guard, next_SP) ||
!PowerPC::MMU::HostIsRAMAddress(guard, next_SP + 4)) !PowerPC::MMU::HostIsRAMAddress(guard, next_SP + 4))
{ {
@@ -288,7 +288,7 @@ static bool IsStackValid(const Core::CPUThreadGuard& guard)
} }
// Check the link register makes sense (that it points to a valid IBAT address) // Check the link register makes sense (that it points to a valid IBAT address)
const u32 address = PowerPC::MMU::HostRead_U32(guard, next_SP + 4); const u32 address = PowerPC::MMU::HostRead<u32>(guard, next_SP + 4);
return PowerPC::MMU::HostIsInstructionRAMAddress(guard, address) && return PowerPC::MMU::HostIsInstructionRAMAddress(guard, address) &&
0 != PowerPC::MMU::HostRead_Instruction(guard, address); 0 != PowerPC::MMU::HostRead_Instruction(guard, address);
} }
+6 -48
View File
@@ -35,57 +35,15 @@ using std::isnan;
#include "Core/System.h" #include "Core/System.h"
template <typename T> template <typename T>
static T HostRead(const Core::CPUThreadGuard& guard, u32 address); static T HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::MMU::HostRead<T>(guard, address);
}
template <typename T> template <typename T>
static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address); static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address)
template <>
u8 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{ {
return PowerPC::MMU::HostRead_U8(guard, address); PowerPC::MMU::HostWrite<T>(guard, var, address);
}
template <>
u16 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::MMU::HostRead_U16(guard, address);
}
template <>
u32 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::MMU::HostRead_U32(guard, address);
}
template <>
u64 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::MMU::HostRead_U64(guard, address);
}
template <>
void HostWrite(const Core::CPUThreadGuard& guard, u8 var, u32 address)
{
PowerPC::MMU::HostWrite_U8(guard, var, address);
}
template <>
void HostWrite(const Core::CPUThreadGuard& guard, u16 var, u32 address)
{
PowerPC::MMU::HostWrite_U16(guard, var, address);
}
template <>
void HostWrite(const Core::CPUThreadGuard& guard, u32 var, u32 address)
{
PowerPC::MMU::HostWrite_U32(guard, var, address);
}
template <>
void HostWrite(const Core::CPUThreadGuard& guard, u64 var, u32 address)
{
PowerPC::MMU::HostWrite_U64(guard, var, address);
} }
template <typename T, typename U = T> template <typename T, typename U = T>
@@ -293,7 +293,7 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio
Core::CPUThreadGuard guard(system); Core::CPUThreadGuard guard(system);
const u32 last_pc = interpreter.m_last_pc; const u32 last_pc = interpreter.m_last_pc;
const u32 opcode = PowerPC::MMU::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); const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc);
NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm); NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm);
Dolphin_Debugger::PrintCallstack(guard, Common::Log::LogType::POWERPC, Dolphin_Debugger::PrintCallstack(guard, Common::Log::LogType::POWERPC,
@@ -41,7 +41,7 @@ static u32 Helper_Get_EA_UX(const PowerPC::PowerPCState& ppcs, const UGeckoInstr
void Interpreter::lbz(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lbz(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
ppc_state.gpr[inst.RD] = temp; ppc_state.gpr[inst.RD] = temp;
@@ -51,7 +51,7 @@ void Interpreter::lbzu(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U8(address); const u32 temp = interpreter.m_mmu.Read<u8>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -71,7 +71,7 @@ void Interpreter::lfd(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u64 temp = interpreter.m_mmu.Read_U64(address); const u64 temp = interpreter.m_mmu.Read<u64>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
ppc_state.ps[inst.FD].SetPS0(temp); ppc_state.ps[inst.FD].SetPS0(temp);
@@ -88,7 +88,7 @@ void Interpreter::lfdu(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u64 temp = interpreter.m_mmu.Read_U64(address); const u64 temp = interpreter.m_mmu.Read<u64>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -108,7 +108,7 @@ void Interpreter::lfdux(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u64 temp = interpreter.m_mmu.Read_U64(address); const u64 temp = interpreter.m_mmu.Read<u64>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -128,7 +128,7 @@ void Interpreter::lfdx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u64 temp = interpreter.m_mmu.Read_U64(address); const u64 temp = interpreter.m_mmu.Read<u64>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
ppc_state.ps[inst.FD].SetPS0(temp); ppc_state.ps[inst.FD].SetPS0(temp);
@@ -145,7 +145,7 @@ void Interpreter::lfs(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -165,7 +165,7 @@ void Interpreter::lfsu(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -186,7 +186,7 @@ void Interpreter::lfsux(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -207,7 +207,7 @@ void Interpreter::lfsx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -219,7 +219,7 @@ void Interpreter::lfsx(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lha(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lha(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = u32(s32(s16(interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -231,7 +231,7 @@ void Interpreter::lhau(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
const u32 temp = u32(s32(s16(interpreter.m_mmu.Read_U16(address)))); const u32 temp = u32(s32(s16(interpreter.m_mmu.Read<u16>(address))));
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -243,7 +243,7 @@ void Interpreter::lhau(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lhz(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhz(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -255,7 +255,7 @@ void Interpreter::lhzu(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U16(address); const u32 temp = interpreter.m_mmu.Read<u16>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) 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) for (u32 i = inst.RD; i <= 31; i++, address += 4)
{ {
const u32 temp_reg = interpreter.m_mmu.Read_U32(address); const u32 temp_reg = interpreter.m_mmu.Read<u32>(address);
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) 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) for (u32 i = inst.RS; i <= 31; i++, address += 4)
{ {
interpreter.m_mmu.Write_U32(ppc_state.gpr[i], address); interpreter.m_mmu.Write<u32>(ppc_state.gpr[i], address);
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{ {
PanicAlertFmt("DSI exception in stmw"); PanicAlertFmt("DSI exception in stmw");
@@ -321,7 +321,7 @@ void Interpreter::lwz(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA(ppc_state, inst); const u32 address = Helper_Get_EA(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -333,7 +333,7 @@ void Interpreter::lwzu(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -345,7 +345,7 @@ void Interpreter::lwzu(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::stb(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stb(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
interpreter.m_mmu.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) 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; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -371,7 +371,7 @@ void Interpreter::stfd(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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) void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst)
@@ -385,7 +385,7 @@ void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -403,7 +403,7 @@ void Interpreter::stfs(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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) void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
@@ -417,7 +417,7 @@ void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -427,7 +427,7 @@ void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::sth(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::sth(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
interpreter.m_mmu.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) 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; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -445,7 +445,7 @@ void Interpreter::sthu(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::stw(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stw(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
interpreter.m_mmu.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) 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; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_U(ppc_state, inst); const u32 address = Helper_Get_EA_U(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -595,7 +595,7 @@ void Interpreter::eciwx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
ppc_state.gpr[inst.RD] = interpreter.m_mmu.Read_U32(EA); ppc_state.gpr[inst.RD] = interpreter.m_mmu.Read<u32>(EA);
} }
void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst)
@@ -615,7 +615,7 @@ void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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) void Interpreter::eieio(Interpreter& interpreter, UGeckoInstruction inst)
@@ -640,7 +640,7 @@ void Interpreter::lbzux(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U8(address); const u32 temp = interpreter.m_mmu.Read<u8>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -652,7 +652,7 @@ void Interpreter::lbzux(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lbzx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lbzx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -664,7 +664,7 @@ void Interpreter::lhaux(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
const s32 temp = s32{s16(interpreter.m_mmu.Read_U16(address))}; const s32 temp = s32{s16(interpreter.m_mmu.Read<u16>(address))};
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -676,7 +676,7 @@ void Interpreter::lhaux(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lhax(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhax(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const s32 temp = s32{s16(interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -687,7 +687,7 @@ void Interpreter::lhax(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lhbrx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhbrx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = Common::swap16(interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -699,7 +699,7 @@ void Interpreter::lhzux(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U16(address); const u32 temp = interpreter.m_mmu.Read<u16>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -711,7 +711,7 @@ void Interpreter::lhzux(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lhzx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lhzx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -740,7 +740,7 @@ void Interpreter::lswx(Interpreter& interpreter, UGeckoInstruction inst)
if ((n & 0b11) == 0) if ((n & 0b11) == 0)
ppc_state.gpr[reg] = 0; ppc_state.gpr[reg] = 0;
const u32 temp_value = interpreter.m_mmu.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. // Not64 (Homebrew N64 Emulator for Wii) triggers the following case.
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{ {
@@ -756,7 +756,7 @@ void Interpreter::lswx(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::lwbrx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::lwbrx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 temp = Common::swap32(interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -768,7 +768,7 @@ void Interpreter::lwzux(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -781,7 +781,7 @@ void Interpreter::lwzx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_X(ppc_state, inst); const u32 address = Helper_Get_EA_X(ppc_state, inst);
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -794,7 +794,7 @@ void Interpreter::stbux(Interpreter& interpreter, UGeckoInstruction inst)
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -804,7 +804,7 @@ void Interpreter::stbux(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::stbx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::stbx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
interpreter.m_mmu.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) void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst)
@@ -818,7 +818,7 @@ void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -836,7 +836,7 @@ void Interpreter::stfdx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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 // Stores Floating points into Integers indeXed
@@ -851,7 +851,7 @@ void Interpreter::stfiwx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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) void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst)
@@ -865,7 +865,7 @@ void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -883,7 +883,7 @@ void Interpreter::stfsx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
interpreter.m_mmu.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) void Interpreter::sthbrx(Interpreter& interpreter, UGeckoInstruction inst)
@@ -897,7 +897,7 @@ void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst)
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -907,7 +907,7 @@ void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst)
void Interpreter::sthx(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::sthx(Interpreter& interpreter, UGeckoInstruction inst)
{ {
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
interpreter.m_mmu.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 // lswi - bizarro string instruction
@@ -940,7 +940,7 @@ void Interpreter::lswi(Interpreter& interpreter, UGeckoInstruction inst)
ppc_state.gpr[r] = 0; ppc_state.gpr[r] = 0;
} }
const u32 temp_value = interpreter.m_mmu.Read_U8(EA) << (24 - i); const u32 temp_value = interpreter.m_mmu.Read<u8>(EA) << (24 - i);
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{ {
PanicAlertFmt("DSI exception in lsw."); PanicAlertFmt("DSI exception in lsw.");
@@ -1007,7 +1007,7 @@ void Interpreter::Helper_StoreString(Interpreter& interpreter, const u32 EA, u32
if (misalignment_bytes != 0) if (misalignment_bytes != 0)
{ {
// Handle misalignment at start // Handle misalignment at start
current_value = interpreter.m_mmu.Read_U32(current_address); current_value = interpreter.m_mmu.Read<u32>(current_address);
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
return; return;
current_value <<= misalignment_bits; current_value <<= misalignment_bits;
@@ -1018,8 +1018,8 @@ void Interpreter::Helper_StoreString(Interpreter& interpreter, const u32 EA, u32
while (n >= 4) while (n >= 4)
{ {
current_value |= ppc_state.gpr[r]; current_value |= ppc_state.gpr[r];
interpreter.m_mmu.Write_U32(static_cast<u32>(current_value >> misalignment_bits), interpreter.m_mmu.Write<u32>(static_cast<u32>(current_value >> misalignment_bits),
current_address); current_address);
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
return; return;
@@ -1042,10 +1042,10 @@ void Interpreter::Helper_StoreString(Interpreter& interpreter, const u32 EA, u32
current_value >>= (misalignment_bytes - n) * 8; current_value >>= (misalignment_bytes - n) * 8;
} }
current_value &= 0xFFFF'FFFF'0000'0000; current_value &= 0xFFFF'FFFF'0000'0000;
current_value |= (interpreter.m_mmu.Read_U32(current_address) << (n * 8)) & 0xFFFF'FFFF; current_value |= (interpreter.m_mmu.Read<u32>(current_address) << (n * 8)) & 0xFFFF'FFFF;
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
return; return;
interpreter.m_mmu.Write_U32(static_cast<u32>(current_value >> (n * 8)), current_address); interpreter.m_mmu.Write<u32>(static_cast<u32>(current_value >> (n * 8)), current_address);
} }
} }
@@ -1071,7 +1071,7 @@ void Interpreter::lwarx(Interpreter& interpreter, UGeckoInstruction inst)
return; return;
} }
const u32 temp = interpreter.m_mmu.Read_U32(address); const u32 temp = interpreter.m_mmu.Read<u32>(address);
if (!(ppc_state.Exceptions & EXCEPTION_DSI)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
@@ -1097,7 +1097,7 @@ void Interpreter::stwcxd(Interpreter& interpreter, UGeckoInstruction inst)
{ {
if (address == ppc_state.reserve_address) if (address == ppc_state.reserve_address)
{ {
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.reserve = false; ppc_state.reserve = false;
@@ -1115,7 +1115,7 @@ void Interpreter::stwux(Interpreter& interpreter, UGeckoInstruction inst)
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_UX(ppc_state, inst); const u32 address = Helper_Get_EA_UX(ppc_state, inst);
interpreter.m_mmu.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)) if (!(ppc_state.Exceptions & EXCEPTION_DSI))
{ {
ppc_state.gpr[inst.RA] = address; ppc_state.gpr[inst.RA] = address;
@@ -1127,7 +1127,7 @@ void Interpreter::stwx(Interpreter& interpreter, UGeckoInstruction inst)
auto& ppc_state = interpreter.m_ppc_state; auto& ppc_state = interpreter.m_ppc_state;
const u32 address = Helper_Get_EA_X(ppc_state, inst); const u32 address = Helper_Get_EA_X(ppc_state, inst);
interpreter.m_mmu.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) void Interpreter::sync(Interpreter& interpreter, UGeckoInstruction inst)
@@ -69,24 +69,9 @@ SType ScaleAndClamp(double ps, u32 st_scale)
} }
template <typename T> template <typename T>
static T ReadUnpaired(PowerPC::MMU& mmu, u32 addr); static T ReadUnpaired(PowerPC::MMU& mmu, u32 addr)
template <>
u8 ReadUnpaired<u8>(PowerPC::MMU& mmu, u32 addr)
{ {
return mmu.Read_U8(addr); return mmu.Read<T>(addr);
}
template <>
u16 ReadUnpaired<u16>(PowerPC::MMU& mmu, u32 addr)
{
return mmu.Read_U16(addr);
}
template <>
u32 ReadUnpaired<u32>(PowerPC::MMU& mmu, u32 addr)
{
return mmu.Read_U32(addr);
} }
template <typename T> template <typename T>
@@ -95,43 +80,28 @@ static std::pair<T, T> ReadPair(PowerPC::MMU& mmu, u32 addr);
template <> template <>
std::pair<u8, u8> ReadPair<u8>(PowerPC::MMU& mmu, u32 addr) std::pair<u8, u8> ReadPair<u8>(PowerPC::MMU& mmu, u32 addr)
{ {
const u16 val = mmu.Read_U16(addr); const u16 val = mmu.Read<u16>(addr);
return {u8(val >> 8), u8(val)}; return {u8(val >> 8), u8(val)};
} }
template <> template <>
std::pair<u16, u16> ReadPair<u16>(PowerPC::MMU& mmu, u32 addr) std::pair<u16, u16> ReadPair<u16>(PowerPC::MMU& mmu, u32 addr)
{ {
const u32 val = mmu.Read_U32(addr); const u32 val = mmu.Read<u32>(addr);
return {u16(val >> 16), u16(val)}; return {u16(val >> 16), u16(val)};
} }
template <> template <>
std::pair<u32, u32> ReadPair<u32>(PowerPC::MMU& mmu, u32 addr) std::pair<u32, u32> ReadPair<u32>(PowerPC::MMU& mmu, u32 addr)
{ {
const u64 val = mmu.Read_U64(addr); const u64 val = mmu.Read<u64>(addr);
return {u32(val >> 32), u32(val)}; return {u32(val >> 32), u32(val)};
} }
template <typename T> template <typename T>
static void WriteUnpaired(PowerPC::MMU& mmu, T val, u32 addr); static void WriteUnpaired(PowerPC::MMU& mmu, T val, u32 addr)
template <>
void WriteUnpaired<u8>(PowerPC::MMU& mmu, u8 val, u32 addr)
{ {
mmu.Write_U8(val, addr); mmu.Write<T>(val, addr);
}
template <>
void WriteUnpaired<u16>(PowerPC::MMU& mmu, u16 val, u32 addr)
{
mmu.Write_U16(val, addr);
}
template <>
void WriteUnpaired<u32>(PowerPC::MMU& mmu, u32 val, u32 addr)
{
mmu.Write_U32(val, addr);
} }
template <typename T> template <typename T>
@@ -140,19 +110,19 @@ static void WritePair(PowerPC::MMU& mmu, T val1, T val2, u32 addr);
template <> template <>
void WritePair<u8>(PowerPC::MMU& mmu, u8 val1, u8 val2, u32 addr) void WritePair<u8>(PowerPC::MMU& mmu, u8 val1, u8 val2, u32 addr)
{ {
mmu.Write_U16((u16{val1} << 8) | u16{val2}, addr); mmu.Write<u16>((u16{val1} << 8) | u16{val2}, addr);
} }
template <> template <>
void WritePair<u16>(PowerPC::MMU& mmu, u16 val1, u16 val2, u32 addr) void WritePair<u16>(PowerPC::MMU& mmu, u16 val1, u16 val2, u32 addr)
{ {
mmu.Write_U32((u32{val1} << 16) | u32{val2}, addr); mmu.Write<u32>((u32{val1} << 16) | u32{val2}, addr);
} }
template <> template <>
void WritePair<u32>(PowerPC::MMU& mmu, u32 val1, u32 val2, u32 addr) void WritePair<u32>(PowerPC::MMU& mmu, u32 val1, u32 val2, u32 addr)
{ {
mmu.Write_U64((u64{val1} << 32) | u64{val2}, addr); mmu.Write<u64>((u64{val1} << 32) | u64{val2}, addr);
} }
template <typename T> template <typename T>
@@ -405,16 +405,16 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
switch (accessSize) switch (accessSize)
{ {
case 64: case 64:
ABI_CallFunctionPR(PowerPC::ReadU64FromJit, &m_jit.m_mmu, reg_addr); ABI_CallFunctionPR(PowerPC::ReadFromJit<u64>, &m_jit.m_mmu, reg_addr);
break; break;
case 32: case 32:
ABI_CallFunctionPR(PowerPC::ReadU32FromJit, &m_jit.m_mmu, reg_addr); ABI_CallFunctionPR(PowerPC::ReadFromJit<u32>, &m_jit.m_mmu, reg_addr);
break; break;
case 16: case 16:
ABI_CallFunctionPR(PowerPC::ReadU16FromJit, &m_jit.m_mmu, reg_addr); ABI_CallFunctionPR(PowerPC::ReadFromJit<u16>, &m_jit.m_mmu, reg_addr);
break; break;
case 8: case 8:
ABI_CallFunctionPR(PowerPC::ReadU8FromJit, &m_jit.m_mmu, reg_addr); ABI_CallFunctionPR(PowerPC::ReadFromJit<u8>, &m_jit.m_mmu, reg_addr);
break; break;
} }
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment); ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
@@ -468,16 +468,16 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
switch (accessSize) switch (accessSize)
{ {
case 64: case 64:
ABI_CallFunctionPC(PowerPC::ReadU64FromJit, &m_jit.m_mmu, address); ABI_CallFunctionPC(PowerPC::ReadFromJit<u64>, &m_jit.m_mmu, address);
break; break;
case 32: case 32:
ABI_CallFunctionPC(PowerPC::ReadU32FromJit, &m_jit.m_mmu, address); ABI_CallFunctionPC(PowerPC::ReadFromJit<u32>, &m_jit.m_mmu, address);
break; break;
case 16: case 16:
ABI_CallFunctionPC(PowerPC::ReadU16FromJit, &m_jit.m_mmu, address); ABI_CallFunctionPC(PowerPC::ReadFromJit<u16>, &m_jit.m_mmu, address);
break; break;
case 8: case 8:
ABI_CallFunctionPC(PowerPC::ReadU8FromJit, &m_jit.m_mmu, address); ABI_CallFunctionPC(PowerPC::ReadFromJit<u8>, &m_jit.m_mmu, address);
break; break;
} }
ABI_PopRegistersAndAdjustStack(registersInUse, 0); ABI_PopRegistersAndAdjustStack(registersInUse, 0);
@@ -588,19 +588,19 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
switch (accessSize) switch (accessSize)
{ {
case 64: case 64:
ABI_CallFunctionPRR(swap ? PowerPC::WriteU64FromJit : PowerPC::WriteU64SwapFromJit, ABI_CallFunctionPRR(swap ? PowerPC::WriteFromJit<u64> : PowerPC::WriteU64SwapFromJit,
&m_jit.m_mmu, reg, reg_addr); &m_jit.m_mmu, reg, reg_addr);
break; break;
case 32: case 32:
ABI_CallFunctionPRR(swap ? PowerPC::WriteU32FromJit : PowerPC::WriteU32SwapFromJit, ABI_CallFunctionPRR(swap ? PowerPC::WriteFromJit<u32> : PowerPC::WriteU32SwapFromJit,
&m_jit.m_mmu, reg, reg_addr); &m_jit.m_mmu, reg, reg_addr);
break; break;
case 16: case 16:
ABI_CallFunctionPRR(swap ? PowerPC::WriteU16FromJit : PowerPC::WriteU16SwapFromJit, ABI_CallFunctionPRR(swap ? PowerPC::WriteFromJit<u16> : PowerPC::WriteU16SwapFromJit,
&m_jit.m_mmu, reg, reg_addr); &m_jit.m_mmu, reg, reg_addr);
break; break;
case 8: case 8:
ABI_CallFunctionPRR(PowerPC::WriteU8FromJit, &m_jit.m_mmu, reg, reg_addr); ABI_CallFunctionPRR(PowerPC::WriteFromJit<u8>, &m_jit.m_mmu, reg, reg_addr);
break; break;
} }
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment); ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
@@ -669,16 +669,16 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
switch (accessSize) switch (accessSize)
{ {
case 64: case 64:
ABI_CallFunctionPAC(64, PowerPC::WriteU64FromJit, &m_jit.m_mmu, arg, address); ABI_CallFunctionPAC(64, PowerPC::WriteFromJit<u64>, &m_jit.m_mmu, arg, address);
break; break;
case 32: case 32:
ABI_CallFunctionPAC(32, PowerPC::WriteU32FromJit, &m_jit.m_mmu, arg, address); ABI_CallFunctionPAC(32, PowerPC::WriteFromJit<u32>, &m_jit.m_mmu, arg, address);
break; break;
case 16: case 16:
ABI_CallFunctionPAC(16, PowerPC::WriteU16FromJit, &m_jit.m_mmu, arg, address); ABI_CallFunctionPAC(16, PowerPC::WriteFromJit<u16>, &m_jit.m_mmu, arg, address);
break; break;
case 8: case 8:
ABI_CallFunctionPAC(8, PowerPC::WriteU8FromJit, &m_jit.m_mmu, arg, address); ABI_CallFunctionPAC(8, PowerPC::WriteFromJit<u8>, &m_jit.m_mmu, arg, address);
break; break;
} }
ABI_PopRegistersAndAdjustStack(registersInUse, 0); ABI_PopRegistersAndAdjustStack(registersInUse, 0);
@@ -222,22 +222,22 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
if (access_size == 64) if (access_size == 64)
{ {
ABI_CallFunction(reverse ? &PowerPC::WriteU64SwapFromJit : &PowerPC::WriteU64FromJit, ABI_CallFunction(reverse ? &PowerPC::WriteU64SwapFromJit : &PowerPC::WriteFromJit<u64>,
&m_mmu, src_reg, ARM64Reg::W2); &m_mmu, src_reg, ARM64Reg::W2);
} }
else if (access_size == 32) else if (access_size == 32)
{ {
ABI_CallFunction(reverse ? &PowerPC::WriteU32SwapFromJit : &PowerPC::WriteU32FromJit, ABI_CallFunction(reverse ? &PowerPC::WriteU32SwapFromJit : &PowerPC::WriteFromJit<u32>,
&m_mmu, src_reg, ARM64Reg::W2); &m_mmu, src_reg, ARM64Reg::W2);
} }
else if (access_size == 16) else if (access_size == 16)
{ {
ABI_CallFunction(reverse ? &PowerPC::WriteU16SwapFromJit : &PowerPC::WriteU16FromJit, ABI_CallFunction(reverse ? &PowerPC::WriteU16SwapFromJit : &PowerPC::WriteFromJit<u16>,
&m_mmu, src_reg, ARM64Reg::W2); &m_mmu, src_reg, ARM64Reg::W2);
} }
else else
{ {
ABI_CallFunction(&PowerPC::WriteU8FromJit, &m_mmu, src_reg, ARM64Reg::W2); ABI_CallFunction(&PowerPC::WriteFromJit<u8>, &m_mmu, src_reg, ARM64Reg::W2);
} }
} }
else if (flags & BackPatchInfo::FLAG_ZERO_256) else if (flags & BackPatchInfo::FLAG_ZERO_256)
@@ -247,13 +247,13 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
else else
{ {
if (access_size == 64) if (access_size == 64)
ABI_CallFunction(&PowerPC::ReadU64FromJit, &m_mmu, ARM64Reg::W1); ABI_CallFunction(&PowerPC::ReadFromJit<u64>, &m_mmu, ARM64Reg::W1);
else if (access_size == 32) else if (access_size == 32)
ABI_CallFunction(&PowerPC::ReadU32FromJit, &m_mmu, ARM64Reg::W1); ABI_CallFunction(&PowerPC::ReadFromJit<u32>, &m_mmu, ARM64Reg::W1);
else if (access_size == 16) else if (access_size == 16)
ABI_CallFunction(&PowerPC::ReadU16FromJit, &m_mmu, ARM64Reg::W1); ABI_CallFunction(&PowerPC::ReadFromJit<u16>, &m_mmu, ARM64Reg::W1);
else else
ABI_CallFunction(&PowerPC::ReadU8FromJit, &m_mmu, ARM64Reg::W1); ABI_CallFunction(&PowerPC::ReadFromJit<u8>, &m_mmu, ARM64Reg::W1);
} }
m_float_emit.ABI_PopRegisters(fprs_to_push, ARM64Reg::X30); m_float_emit.ABI_PopRegisters(fprs_to_push, ARM64Reg::X30);
+2 -1
View File
@@ -330,7 +330,8 @@ void JitInterface::CompileExceptionCheck(ExceptionType type)
// Check in case the code has been replaced since: do we need to do this? // Check in case the code has been replaced since: do we need to do this?
const OpType optype = const OpType optype =
PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, ppc_state.pc), ppc_state.pc)->type; PPCTables::GetOpInfo(PowerPC::MMU::HostRead<u32>(guard, ppc_state.pc), ppc_state.pc)
->type;
if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS) if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS)
return; return;
} }
+102 -233
View File
@@ -144,7 +144,7 @@ static void EFB_Write(u32 data, u32 addr)
} }
} }
template <XCheckTLBFlag flag, typename T, bool never_translate> template <XCheckTLBFlag flag, std::unsigned_integral T, bool never_translate>
T MMU::ReadFromHardware(u32 em_address) T MMU::ReadFromHardware(u32 em_address)
{ {
// ReadFromHardware is currently used with XCheckTLBFlag::OpcodeNoException by host instruction // ReadFromHardware is currently used with XCheckTLBFlag::OpcodeNoException by host instruction
@@ -161,12 +161,12 @@ T MMU::ReadFromHardware(u32 em_address)
// way isn't too terrible. // way isn't too terrible.
// TODO: floats on non-word-aligned boundaries should technically cause alignment exceptions. // TODO: floats on non-word-aligned boundaries should technically cause alignment exceptions.
// Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned! // Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned!
u64 var = 0; T var = 0;
for (u32 i = 0; i < sizeof(T); ++i) for (u32 i = 0; i < sizeof(T); ++i)
{ {
var = (var << 8) | ReadFromHardware<flag, u8, never_translate>(em_address + i); var = (var << 8) | ReadFromHardware<flag, u8, never_translate>(em_address + i);
} }
return static_cast<T>(var); return var;
} }
bool wi = false; bool wi = false;
@@ -577,37 +577,21 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size)
m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT;
} }
u8 MMU::Read_U8(const u32 address) template <std::unsigned_integral T>
T MMU::Read(const u32 address)
{ {
u8 var = ReadFromHardware<XCheckTLBFlag::Read, u8>(address); T var = ReadFromHardware<XCheckTLBFlag::Read, T>(address);
Memcheck(address, var, false, 1); Memcheck(address, var, false, sizeof(T));
return var; return var;
} }
template u8 MMU::Read<u8>(const u32 address);
template u16 MMU::Read<u16>(const u32 address);
template u32 MMU::Read<u32>(const u32 address);
template u64 MMU::Read<u64>(const u32 address);
u16 MMU::Read_U16(const u32 address) template <std::unsigned_integral T>
{ std::optional<ReadResult<T>> MMU::HostTryRead(const Core::CPUThreadGuard& guard, const u32 address,
u16 var = ReadFromHardware<XCheckTLBFlag::Read, u16>(address); RequestedAddressSpace space)
Memcheck(address, var, false, 2);
return var;
}
u32 MMU::Read_U32(const u32 address)
{
u32 var = ReadFromHardware<XCheckTLBFlag::Read, u32>(address);
Memcheck(address, var, false, 4);
return var;
}
u64 MMU::Read_U64(const u32 address)
{
u64 var = ReadFromHardware<XCheckTLBFlag::Read, u64>(address);
Memcheck(address, var, false, 8);
return var;
}
template <typename T>
std::optional<ReadResult<T>> MMU::HostTryReadUX(const Core::CPUThreadGuard& guard,
const u32 address, RequestedAddressSpace space)
{ {
if (!HostIsRAMAddress(guard, address, space)) if (!HostIsRAMAddress(guard, address, space))
return std::nullopt; return std::nullopt;
@@ -637,167 +621,88 @@ std::optional<ReadResult<T>> MMU::HostTryReadUX(const Core::CPUThreadGuard& guar
ASSERT(false); ASSERT(false);
return std::nullopt; return std::nullopt;
} }
template std::optional<ReadResult<u8>> MMU::HostTryRead<u8>(const Core::CPUThreadGuard& guard,
const u32 address,
RequestedAddressSpace space);
template std::optional<ReadResult<u16>> MMU::HostTryRead<u16>(const Core::CPUThreadGuard& guard,
const u32 address,
RequestedAddressSpace space);
template std::optional<ReadResult<u32>> MMU::HostTryRead<u32>(const Core::CPUThreadGuard& guard,
const u32 address,
RequestedAddressSpace space);
template std::optional<ReadResult<u64>> MMU::HostTryRead<u64>(const Core::CPUThreadGuard& guard,
const u32 address,
RequestedAddressSpace space);
std::optional<ReadResult<u8>> MMU::HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, template <std::unsigned_integral T>
RequestedAddressSpace space) void MMU::Write(const Common::MakeAtLeastU32<T> var, const u32 address)
{ {
return HostTryReadUX<u8>(guard, address, space); Memcheck(address, var, true, sizeof(T));
WriteToHardware<XCheckTLBFlag::Write>(address, var, sizeof(T));
} }
template void MMU::Write<u8>(const u32 var, const u32 address);
std::optional<ReadResult<u16>> MMU::HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, template void MMU::Write<u16>(const u32 var, const u32 address);
RequestedAddressSpace space) template void MMU::Write<u32>(const u32 var, const u32 address);
{ template <>
return HostTryReadUX<u16>(guard, address, space); void MMU::Write<u64>(const u64 var, const u32 address)
}
std::optional<ReadResult<u32>> MMU::HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address,
RequestedAddressSpace space)
{
return HostTryReadUX<u32>(guard, address, space);
}
std::optional<ReadResult<u64>> MMU::HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address,
RequestedAddressSpace space)
{
return HostTryReadUX<u64>(guard, address, space);
}
std::optional<ReadResult<float>> MMU::HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address,
RequestedAddressSpace space)
{
const auto result = HostTryReadUX<u32>(guard, address, space);
if (!result)
return std::nullopt;
return ReadResult<float>(result->translated, std::bit_cast<float>(result->value));
}
std::optional<ReadResult<double>> MMU::HostTryReadF64(const Core::CPUThreadGuard& guard,
u32 address, RequestedAddressSpace space)
{
const auto result = HostTryReadUX<u64>(guard, address, space);
if (!result)
return std::nullopt;
return ReadResult<double>(result->translated, std::bit_cast<double>(result->value));
}
void MMU::Write_U8(const u32 var, const u32 address)
{
Memcheck(address, var, true, 1);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 1);
}
void MMU::Write_U16(const u32 var, const u32 address)
{
Memcheck(address, var, true, 2);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 2);
}
void MMU::Write_U16_Swap(const u32 var, const u32 address)
{
Write_U16((var & 0xFFFF0000) | Common::swap16(static_cast<u16>(var)), address);
}
void MMU::Write_U32(const u32 var, const u32 address)
{
Memcheck(address, var, true, 4);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 4);
}
void MMU::Write_U32_Swap(const u32 var, const u32 address)
{
Write_U32(Common::swap32(var), address);
}
void MMU::Write_U64(const u64 var, const u32 address)
{ {
Memcheck(address, var, true, 8); Memcheck(address, var, true, 8);
WriteToHardware<XCheckTLBFlag::Write>(address, static_cast<u32>(var >> 32), 4); WriteToHardware<XCheckTLBFlag::Write>(address, static_cast<u32>(var >> 32), 4);
WriteToHardware<XCheckTLBFlag::Write>(address + sizeof(u32), static_cast<u32>(var), 4); WriteToHardware<XCheckTLBFlag::Write>(address + sizeof(u32), static_cast<u32>(var), 4);
} }
void MMU::Write_U16_Swap(const u32 var, const u32 address)
{
Write<u16>((var & 0xFFFF0000) | Common::swap16(static_cast<u16>(var)), address);
}
void MMU::Write_U32_Swap(const u32 var, const u32 address)
{
Write<u32>(Common::swap32(var), address);
}
void MMU::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); Write<u64>(Common::swap64(var), address);
} }
u8 MMU::HostRead_U8(const Core::CPUThreadGuard& guard, const u32 address) template <std::unsigned_integral T>
T MMU::HostRead(const Core::CPUThreadGuard& guard, const u32 address)
{ {
auto& mmu = guard.GetSystem().GetMMU(); auto& mmu = guard.GetSystem().GetMMU();
return mmu.ReadFromHardware<XCheckTLBFlag::NoException, u8>(address); return mmu.ReadFromHardware<XCheckTLBFlag::NoException, T>(address);
} }
template u8 MMU::HostRead<u8>(const Core::CPUThreadGuard& guard, const u32 address);
template u16 MMU::HostRead<u16>(const Core::CPUThreadGuard& guard, const u32 address);
template u32 MMU::HostRead<u32>(const Core::CPUThreadGuard& guard, const u32 address);
template u64 MMU::HostRead<u64>(const Core::CPUThreadGuard& guard, const u32 address);
u16 MMU::HostRead_U16(const Core::CPUThreadGuard& guard, const u32 address) template <std::unsigned_integral T>
void MMU::HostWrite(const Core::CPUThreadGuard& guard, const Common::MakeAtLeastU32<T> var,
const u32 address)
{ {
auto& mmu = guard.GetSystem().GetMMU(); auto& mmu = guard.GetSystem().GetMMU();
return mmu.ReadFromHardware<XCheckTLBFlag::NoException, u16>(address); mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, var, sizeof(T));
} }
template void MMU::HostWrite<u8>(const Core::CPUThreadGuard& guard, const u32 var,
u32 MMU::HostRead_U32(const Core::CPUThreadGuard& guard, const u32 address) const u32 address);
{ template void MMU::HostWrite<u16>(const Core::CPUThreadGuard& guard, const u32 var,
auto& mmu = guard.GetSystem().GetMMU(); const u32 address);
return mmu.ReadFromHardware<XCheckTLBFlag::NoException, u32>(address); template void MMU::HostWrite<u32>(const Core::CPUThreadGuard& guard, const u32 var,
} const u32 address);
template <>
u64 MMU::HostRead_U64(const Core::CPUThreadGuard& guard, const u32 address) void MMU::HostWrite<u64>(const Core::CPUThreadGuard& guard, const u64 var, const u32 address)
{
auto& mmu = guard.GetSystem().GetMMU();
return mmu.ReadFromHardware<XCheckTLBFlag::NoException, u64>(address);
}
float MMU::HostRead_F32(const Core::CPUThreadGuard& guard, const u32 address)
{
const u32 integral = HostRead_U32(guard, address);
return std::bit_cast<float>(integral);
}
double MMU::HostRead_F64(const Core::CPUThreadGuard& guard, const u32 address)
{
const u64 integral = HostRead_U64(guard, address);
return std::bit_cast<double>(integral);
}
void MMU::HostWrite_U8(const Core::CPUThreadGuard& guard, const u32 var, const u32 address)
{
auto& mmu = guard.GetSystem().GetMMU();
mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, var, 1);
}
void MMU::HostWrite_U16(const Core::CPUThreadGuard& guard, const u32 var, const u32 address)
{
auto& mmu = guard.GetSystem().GetMMU();
mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, var, 2);
}
void MMU::HostWrite_U32(const Core::CPUThreadGuard& guard, const u32 var, const u32 address)
{
auto& mmu = guard.GetSystem().GetMMU();
mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, var, 4);
}
void MMU::HostWrite_U64(const Core::CPUThreadGuard& guard, const u64 var, const u32 address)
{ {
auto& mmu = guard.GetSystem().GetMMU(); auto& mmu = guard.GetSystem().GetMMU();
mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, static_cast<u32>(var >> 32), 4); mmu.WriteToHardware<XCheckTLBFlag::NoException>(address, static_cast<u32>(var >> 32), 4);
mmu.WriteToHardware<XCheckTLBFlag::NoException>(address + sizeof(u32), static_cast<u32>(var), 4); mmu.WriteToHardware<XCheckTLBFlag::NoException>(address + sizeof(u32), static_cast<u32>(var), 4);
} }
void MMU::HostWrite_F32(const Core::CPUThreadGuard& guard, const float var, const u32 address) template <std::unsigned_integral T>
std::optional<WriteResult> MMU::HostTryWrite(const Core::CPUThreadGuard& guard,
const Common::MakeAtLeastU32<T> var, const u32 address,
RequestedAddressSpace space)
{ {
const u32 integral = std::bit_cast<u32>(var); constexpr auto size = sizeof(T);
HostWrite_U32(guard, integral, address);
}
void MMU::HostWrite_F64(const Core::CPUThreadGuard& guard, const double var, const u32 address)
{
const u64 integral = std::bit_cast<u64>(var);
HostWrite_U64(guard, integral, address);
}
std::optional<WriteResult> MMU::HostTryWriteUX(const Core::CPUThreadGuard& guard, const u32 var,
const u32 address, const u32 size,
RequestedAddressSpace space)
{
if (!HostIsRAMAddress(guard, address, space)) if (!HostIsRAMAddress(guard, address, space))
return std::nullopt; return std::nullopt;
@@ -820,47 +725,24 @@ std::optional<WriteResult> MMU::HostTryWriteUX(const Core::CPUThreadGuard& guard
ASSERT(false); ASSERT(false);
return std::nullopt; return std::nullopt;
} }
template std::optional<WriteResult> MMU::HostTryWrite<u8>(const Core::CPUThreadGuard& guard,
std::optional<WriteResult> MMU::HostTryWriteU8(const Core::CPUThreadGuard& guard, const u32 var, const u32 var, const u32 address,
const u32 address, RequestedAddressSpace space) RequestedAddressSpace space);
template std::optional<WriteResult> MMU::HostTryWrite<u16>(const Core::CPUThreadGuard& guard,
const u32 var, const u32 address,
RequestedAddressSpace space);
template std::optional<WriteResult> MMU::HostTryWrite<u32>(const Core::CPUThreadGuard& guard,
const u32 var, const u32 address,
RequestedAddressSpace space);
template <>
std::optional<WriteResult> MMU::HostTryWrite<u64>(const Core::CPUThreadGuard& guard, const u64 var,
const u32 address, RequestedAddressSpace space)
{ {
return HostTryWriteUX(guard, var, address, 1, space); const auto result = HostTryWrite<u32>(guard, static_cast<u32>(var >> 32), address, space);
}
std::optional<WriteResult> MMU::HostTryWriteU16(const Core::CPUThreadGuard& guard, const u32 var,
const u32 address, RequestedAddressSpace space)
{
return HostTryWriteUX(guard, var, address, 2, space);
}
std::optional<WriteResult> MMU::HostTryWriteU32(const Core::CPUThreadGuard& guard, const u32 var,
const u32 address, RequestedAddressSpace space)
{
return HostTryWriteUX(guard, var, address, 4, space);
}
std::optional<WriteResult> MMU::HostTryWriteU64(const Core::CPUThreadGuard& guard, const u64 var,
const u32 address, RequestedAddressSpace space)
{
const auto result = HostTryWriteUX(guard, static_cast<u32>(var >> 32), address, 4, space);
if (!result) if (!result)
return result; return result;
return HostTryWriteUX(guard, static_cast<u32>(var), address + 4, 4, space); return HostTryWrite<u32>(guard, static_cast<u32>(var), address + 4, space);
}
std::optional<WriteResult> MMU::HostTryWriteF32(const Core::CPUThreadGuard& guard, const float var,
const u32 address, RequestedAddressSpace space)
{
const u32 integral = std::bit_cast<u32>(var);
return HostTryWriteU32(guard, integral, address, space);
}
std::optional<WriteResult> MMU::HostTryWriteF64(const Core::CPUThreadGuard& guard, const double var,
const u32 address, RequestedAddressSpace space)
{
const u64 integral = std::bit_cast<u64>(var);
return HostTryWriteU64(guard, integral, address, space);
} }
std::string MMU::HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size) std::string MMU::HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size)
@@ -870,7 +752,7 @@ std::string MMU::HostGetString(const Core::CPUThreadGuard& guard, u32 address, s
{ {
if (!HostIsRAMAddress(guard, address)) if (!HostIsRAMAddress(guard, address))
break; break;
u8 res = HostRead_U8(guard, address); u8 res = HostRead<u8>(guard, address);
if (!res) if (!res)
break; break;
s += static_cast<char>(res); s += static_cast<char>(res);
@@ -886,7 +768,7 @@ std::u16string MMU::HostGetU16String(const Core::CPUThreadGuard& guard, u32 addr
{ {
if (!HostIsRAMAddress(guard, address) || !HostIsRAMAddress(guard, address + 1)) if (!HostIsRAMAddress(guard, address) || !HostIsRAMAddress(guard, address + 1))
break; break;
const u16 res = HostRead_U16(guard, address); const u16 res = HostRead<u16>(guard, address);
if (!res) if (!res)
break; break;
s += static_cast<char16_t>(res); s += static_cast<char16_t>(res);
@@ -899,7 +781,7 @@ std::optional<ReadResult<std::string>> MMU::HostTryReadString(const Core::CPUThr
u32 address, size_t size, u32 address, size_t size,
RequestedAddressSpace space) RequestedAddressSpace space)
{ {
auto c = HostTryReadU8(guard, address, space); auto c = HostTryRead<u8>(guard, address, space);
if (!c) if (!c)
return std::nullopt; return std::nullopt;
if (c->value == 0) if (c->value == 0)
@@ -910,7 +792,7 @@ std::optional<ReadResult<std::string>> MMU::HostTryReadString(const Core::CPUThr
while (size == 0 || s.length() < size) while (size == 0 || s.length() < size)
{ {
++address; ++address;
const auto res = HostTryReadU8(guard, address, space); const auto res = HostTryRead<u8>(guard, address, space);
if (!res || res->value == 0) if (!res || res->value == 0)
break; break;
s += static_cast<char>(res->value); s += static_cast<char>(res->value);
@@ -1703,38 +1585,25 @@ void ClearDCacheLineFromJit(MMU& mmu, u32 address)
{ {
mmu.ClearDCacheLine(address); mmu.ClearDCacheLine(address);
} }
u32 ReadU8FromJit(MMU& mmu, u32 address) template <std::unsigned_integral T>
Common::MakeAtLeastU32<T> ReadFromJit(MMU& mmu, u32 address)
{ {
return mmu.Read_U8(address); return mmu.Read<T>(address);
} }
u32 ReadU16FromJit(MMU& mmu, u32 address) template u32 ReadFromJit<u8>(MMU& mmu, u32 address);
template u32 ReadFromJit<u16>(MMU& mmu, u32 address);
template u32 ReadFromJit<u32>(MMU& mmu, u32 address);
template u64 ReadFromJit<u64>(MMU& mmu, u32 address);
template <std::unsigned_integral T>
void WriteFromJit(MMU& mmu, Common::MakeAtLeastU32<T> var, u32 address)
{ {
return mmu.Read_U16(address); mmu.Write<T>(var, address);
}
u32 ReadU32FromJit(MMU& mmu, u32 address)
{
return mmu.Read_U32(address);
}
u64 ReadU64FromJit(MMU& mmu, u32 address)
{
return mmu.Read_U64(address);
}
void WriteU8FromJit(MMU& mmu, u32 var, u32 address)
{
mmu.Write_U8(var, address);
}
void WriteU16FromJit(MMU& mmu, u32 var, u32 address)
{
mmu.Write_U16(var, address);
}
void WriteU32FromJit(MMU& mmu, u32 var, u32 address)
{
mmu.Write_U32(var, address);
}
void WriteU64FromJit(MMU& mmu, u64 var, u32 address)
{
mmu.Write_U64(var, address);
} }
template void WriteFromJit<u8>(MMU& mmu, u32 var, u32 address);
template void WriteFromJit<u16>(MMU& mmu, u32 var, u32 address);
template void WriteFromJit<u32>(MMU& mmu, u32 var, u32 address);
template void WriteFromJit<u64>(MMU& mmu, u64 var, u32 address);
void WriteU16SwapFromJit(MMU& mmu, u32 var, u32 address) void WriteU16SwapFromJit(MMU& mmu, u32 var, u32 address)
{ {
mmu.Write_U16_Swap(var, address); mmu.Write_U16_Swap(var, address);
+59 -70
View File
@@ -10,6 +10,7 @@
#include "Common/BitField.h" #include "Common/BitField.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/TypeUtils.h"
namespace Core namespace Core
{ {
@@ -124,12 +125,17 @@ public:
// If the read fails (eg. address does not correspond to a mapped address in the current address // 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 // space), a PanicAlert will be shown to the user and zero (or an empty string for the string
// case) will be returned. // case) will be returned.
static u8 HostRead_U8(const Core::CPUThreadGuard& guard, u32 address); template <std::unsigned_integral T>
static u16 HostRead_U16(const Core::CPUThreadGuard& guard, u32 address); static T HostRead(const Core::CPUThreadGuard& guard, const u32 address);
static u32 HostRead_U32(const Core::CPUThreadGuard& guard, u32 address); template <typename T>
static u64 HostRead_U64(const Core::CPUThreadGuard& guard, u32 address); requires(!std::unsigned_integral<T>)
static float HostRead_F32(const Core::CPUThreadGuard& guard, u32 address); static T HostRead(const Core::CPUThreadGuard& guard, const u32 address)
static double HostRead_F64(const Core::CPUThreadGuard& guard, u32 address); {
using U = Common::MakeUnsignedSameSize<T>;
U result = HostRead<U>(guard, address);
return std::bit_cast<T>(result);
}
static u32 HostRead_Instruction(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); static std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0);
static std::u16string HostGetU16String(const Core::CPUThreadGuard& guard, u32 address, static std::u16string HostGetU16String(const Core::CPUThreadGuard& guard, u32 address,
@@ -139,24 +145,20 @@ public:
// If the read succeeds, the returned value will be present and the ReadResult contains the read // 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 // 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. // HostRead functions, this does not raise a user-visible alert on failure.
static std::optional<ReadResult<u8>> template <std::unsigned_integral T>
HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address, static std::optional<ReadResult<T>>
RequestedAddressSpace space = RequestedAddressSpace::Effective); HostTryRead(const Core::CPUThreadGuard& guard, u32 address,
static std::optional<ReadResult<u16>> RequestedAddressSpace space = RequestedAddressSpace::Effective);
HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address, template <typename T>
RequestedAddressSpace space = RequestedAddressSpace::Effective); static std::optional<ReadResult<T>>
static std::optional<ReadResult<u32>> HostTryRead(const Core::CPUThreadGuard& guard, u32 address,
HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective)
RequestedAddressSpace space = RequestedAddressSpace::Effective); requires(!std::unsigned_integral<T>)
static std::optional<ReadResult<u64>> {
HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address, using U = Common::MakeUnsignedSameSize<T>;
RequestedAddressSpace space = RequestedAddressSpace::Effective); std::optional<ReadResult<U>> result = HostTryRead<U>(guard, address);
static std::optional<ReadResult<float>> return std::bit_cast<std::optional<ReadResult<T>>>(result);
HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address, }
RequestedAddressSpace space = RequestedAddressSpace::Effective);
static std::optional<ReadResult<double>>
HostTryReadF64(const Core::CPUThreadGuard& guard, u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
static std::optional<ReadResult<u32>> static std::optional<ReadResult<u32>>
HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address, HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective); RequestedAddressSpace space = RequestedAddressSpace::Effective);
@@ -167,35 +169,36 @@ public:
// Writes a value to emulated memory using the currently active MMU settings. // 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 // 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. // space), a PanicAlert will be shown to the user.
static void HostWrite_U8(const Core::CPUThreadGuard& guard, u32 var, u32 address); template <std::unsigned_integral T>
static void HostWrite_U16(const Core::CPUThreadGuard& guard, u32 var, u32 address); static void HostWrite(const Core::CPUThreadGuard& guard, Common::MakeAtLeastU32<T> var,
static void HostWrite_U32(const Core::CPUThreadGuard& guard, u32 var, u32 address); u32 address);
static void HostWrite_U64(const Core::CPUThreadGuard& guard, u64 var, u32 address); template <typename T>
static void HostWrite_F32(const Core::CPUThreadGuard& guard, float var, u32 address); static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address)
static void HostWrite_F64(const Core::CPUThreadGuard& guard, double var, u32 address); requires(!std::unsigned_integral<T>)
{
using U = Common::MakeUnsignedSameSize<T>;
U cast_var = std::bit_cast<U>(var);
return HostWrite<U>(guard, cast_var, address);
}
// Try to a write a value to memory at the given address in the given memory space. // 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 // 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 // address had to be translated or not. Unlike the HostWrite functions, this does not raise a
// user-visible alert on failure. // user-visible alert on failure.
template <std::unsigned_integral T>
static std::optional<WriteResult> static std::optional<WriteResult>
HostTryWriteU8(const Core::CPUThreadGuard& guard, u32 var, const u32 address, HostTryWrite(const Core::CPUThreadGuard& guard, const Common::MakeAtLeastU32<T> var,
RequestedAddressSpace space = RequestedAddressSpace::Effective); const u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
template <typename T>
static std::optional<WriteResult> static std::optional<WriteResult>
HostTryWriteU16(const Core::CPUThreadGuard& guard, u32 var, const u32 address, HostTryWrite(const Core::CPUThreadGuard& guard, const T var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective); RequestedAddressSpace space = RequestedAddressSpace::Effective)
static std::optional<WriteResult> requires(!std::unsigned_integral<T>)
HostTryWriteU32(const Core::CPUThreadGuard& guard, u32 var, const u32 address, {
RequestedAddressSpace space = RequestedAddressSpace::Effective); using U = Common::MakeUnsignedSameSize<T>;
static std::optional<WriteResult> U cast_var = std::bit_cast<U>(var);
HostTryWriteU64(const Core::CPUThreadGuard& guard, u64 var, const u32 address, return HostTryWrite<U>(guard, cast_var, address, space);
RequestedAddressSpace space = RequestedAddressSpace::Effective); }
static std::optional<WriteResult>
HostTryWriteF32(const Core::CPUThreadGuard& guard, float var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
static std::optional<WriteResult>
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 // Returns whether a read or write to the given address will resolve to a RAM access in the given
// address space. // address space.
@@ -213,15 +216,11 @@ public:
u32 Read_Opcode(u32 address); u32 Read_Opcode(u32 address);
TryReadInstResult TryReadInstruction(u32 address); TryReadInstResult TryReadInstruction(u32 address);
u8 Read_U8(u32 address); template <std::unsigned_integral T>
u16 Read_U16(u32 address); T Read(const u32 address);
u32 Read_U32(u32 address);
u64 Read_U64(u32 address);
void Write_U8(u32 var, u32 address); template <std::unsigned_integral T>
void Write_U16(u32 var, u32 address); void Write(const Common::MakeAtLeastU32<T> var, const 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_U16_Swap(u32 var, u32 address);
void Write_U32_Swap(u32 var, u32 address); void Write_U32_Swap(u32 var, u32 address);
@@ -305,7 +304,7 @@ private:
void UpdateBATs(BatTable& bat_table, u32 base_spr); void UpdateBATs(BatTable& bat_table, u32 base_spr);
void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr); void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr);
template <XCheckTLBFlag flag, typename T, bool never_translate = false> template <XCheckTLBFlag flag, std::unsigned_integral T, bool never_translate = false>
T ReadFromHardware(u32 em_address); T ReadFromHardware(u32 em_address);
template <XCheckTLBFlag flag, bool never_translate = false> template <XCheckTLBFlag flag, bool never_translate = false>
void WriteToHardware(u32 em_address, const u32 data, const u32 size); void WriteToHardware(u32 em_address, const u32 data, const u32 size);
@@ -313,13 +312,6 @@ private:
bool IsEffectiveRAMAddress(u32 address); bool IsEffectiveRAMAddress(u32 address);
bool IsPhysicalRAMAddress(u32 address) const; bool IsPhysicalRAMAddress(u32 address) const;
template <typename T>
static std::optional<ReadResult<T>> HostTryReadUX(const Core::CPUThreadGuard& guard,
const u32 address, RequestedAddressSpace space);
static std::optional<WriteResult> HostTryWriteUX(const Core::CPUThreadGuard& guard, const u32 var,
const u32 address, const u32 size,
RequestedAddressSpace space);
Core::System& m_system; Core::System& m_system;
Memory::MemoryManager& m_memory; Memory::MemoryManager& m_memory;
PowerPC::PowerPCManager& m_power_pc; PowerPC::PowerPCManager& m_power_pc;
@@ -330,14 +322,11 @@ private:
}; };
void ClearDCacheLineFromJit(MMU& mmu, u32 address); void ClearDCacheLineFromJit(MMU& mmu, u32 address);
u32 ReadU8FromJit(MMU& mmu, u32 address); // Returns zero-extended 32bit value template <std::unsigned_integral T>
u32 ReadU16FromJit(MMU& mmu, u32 address); // Returns zero-extended 32bit value // Returns zero-extended value
u32 ReadU32FromJit(MMU& mmu, u32 address); Common::MakeAtLeastU32<T> ReadFromJit(MMU& mmu, u32 address);
u64 ReadU64FromJit(MMU& mmu, u32 address); template <std::unsigned_integral T>
void WriteU8FromJit(MMU& mmu, u32 var, u32 address); void WriteFromJit(MMU& mmu, Common::MakeAtLeastU32<T> var, u32 address);
void WriteU16FromJit(MMU& mmu, u32 var, u32 address);
void WriteU32FromJit(MMU& mmu, u32 var, u32 address);
void WriteU64FromJit(MMU& mmu, u64 var, u32 address);
void WriteU16SwapFromJit(MMU& mmu, u32 var, u32 address); void WriteU16SwapFromJit(MMU& mmu, u32 var, u32 address);
void WriteU32SwapFromJit(MMU& mmu, u32 var, u32 address); void WriteU32SwapFromJit(MMU& mmu, u32 var, u32 address);
void WriteU64SwapFromJit(MMU& mmu, u64 var, u32 address); void WriteU64SwapFromJit(MMU& mmu, u64 var, u32 address);
@@ -108,7 +108,7 @@ bool Compare(const Core::CPUThreadGuard& guard, u32 address, u32 size, const MEG
for (size_t i = 0; i < sig.code.size(); ++i) for (size_t i = 0; i < sig.code.size(); ++i)
{ {
if (sig.code[i] != 0 && PowerPC::MMU::HostRead_U32( if (sig.code[i] != 0 && PowerPC::MMU::HostRead<u32>(
guard, static_cast<u32>(address + i * sizeof(u32))) != sig.code[i]) guard, static_cast<u32>(address + i * sizeof(u32))) != sig.code[i])
{ {
return false; return false;
+4 -4
View File
@@ -510,7 +510,7 @@ static bool MemoryMatchesAt(const Core::CPUThreadGuard& guard, u32 offset,
{ {
for (u32 i = 0; i < value.size(); ++i) for (u32 i = 0; i < value.size(); ++i)
{ {
auto result = PowerPC::MMU::HostTryReadU8(guard, offset + i); auto result = PowerPC::MMU::HostTryRead<u8>(guard, offset + i);
if (!result || result->value != value[i]) if (!result || result->value != value[i])
return false; return false;
} }
@@ -532,7 +532,7 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset,
auto& system = guard.GetSystem(); auto& system = guard.GetSystem();
const u32 size = static_cast<u32>(value.size()); const u32 size = static_cast<u32>(value.size());
for (u32 i = 0; i < size; ++i) for (u32 i = 0; i < size; ++i)
PowerPC::MMU::HostTryWriteU8(guard, value[i], offset + i); PowerPC::MMU::HostTryWrite<u8>(guard, value[i], offset + i);
const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size); const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size);
if (overlapping_hook_count != 0) if (overlapping_hook_count != 0)
{ {
@@ -596,13 +596,13 @@ static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Pat
{ {
// from the pattern find the next blr instruction // from the pattern find the next blr instruction
const u32 blr_address = ram_start + i; const u32 blr_address = ram_start + i;
auto blr = PowerPC::MMU::HostTryReadU32(guard, blr_address); auto blr = PowerPC::MMU::HostTryRead<u32>(guard, blr_address);
if (blr && blr->value == 0x4e800020) if (blr && blr->value == 0x4e800020)
{ {
// and replace it with a jump to the given offset // and replace it with a jump to the given offset
const u32 target = memory_patch.m_offset | 0x80000000; const u32 target = memory_patch.m_offset | 0x80000000;
const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000; const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000;
PowerPC::MMU::HostTryWriteU32(guard, jmp, blr_address); PowerPC::MMU::HostTryWrite<u32>(guard, jmp, blr_address);
const u32 overlapping_hook_count = const u32 overlapping_hook_count =
HLE::UnpatchRange(system, blr_address, blr_address + 4); HLE::UnpatchRange(system, blr_address, blr_address + 4);
if (overlapping_hook_count != 0) if (overlapping_hook_count != 0)
@@ -277,7 +277,7 @@ void ThreadWidget::Update()
}; };
const auto format_hex_from = [&format_hex](const Core::CPUThreadGuard& guard, u32 addr) { const auto format_hex_from = [&format_hex](const Core::CPUThreadGuard& guard, u32 addr) {
addr = addr =
PowerPC::MMU::HostIsRAMAddress(guard, addr) ? PowerPC::MMU::HostRead_U32(guard, addr) : 0; PowerPC::MMU::HostIsRAMAddress(guard, addr) ? PowerPC::MMU::HostRead<u32>(guard, addr) : 0;
return format_hex(addr); return format_hex(addr);
}; };
const auto get_state = [](u16 thread_state) { const auto get_state = [](u16 thread_state) {
@@ -463,7 +463,7 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp))); m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp)));
if (PowerPC::MMU::HostIsRAMAddress(guard, sp + 4)) if (PowerPC::MMU::HostIsRAMAddress(guard, sp + 4))
{ {
const u32 lr_save = PowerPC::MMU::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, 2, new QTableWidgetItem(format_hex(lr_save)));
m_callstack_table->setItem( m_callstack_table->setItem(
i, 3, i, 3,
@@ -474,7 +474,7 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
{ {
m_callstack_table->setItem(i, 2, new QTableWidgetItem(QStringLiteral("--------"))); m_callstack_table->setItem(i, 2, new QTableWidgetItem(QStringLiteral("--------")));
} }
sp = PowerPC::MMU::HostRead_U32(guard, sp); sp = PowerPC::MMU::HostRead<u32>(guard, sp);
m_callstack_table->setItem(i, 1, new QTableWidgetItem(format_hex(sp))); m_callstack_table->setItem(i, 1, new QTableWidgetItem(format_hex(sp)));
} }
} }
@@ -203,12 +203,12 @@ void WatchWidget::Update()
{ {
if (PowerPC::MMU::HostIsRAMAddress(guard, entry.address)) if (PowerPC::MMU::HostIsRAMAddress(guard, entry.address))
{ {
hex->setText(QStringLiteral("%1").arg(PowerPC::MMU::HostRead_U32(guard, entry.address), 8, hex->setText(QStringLiteral("%1").arg(PowerPC::MMU::HostRead<u32>(guard, entry.address), 8,
16, QLatin1Char('0'))); 16, QLatin1Char('0')));
decimal->setText(QString::number(PowerPC::MMU::HostRead_U32(guard, entry.address))); decimal->setText(QString::number(PowerPC::MMU::HostRead<u32>(guard, entry.address)));
string->setText( string->setText(
QString::fromStdString(PowerPC::MMU::HostGetString(guard, entry.address, 32))); QString::fromStdString(PowerPC::MMU::HostGetString(guard, entry.address, 32)));
floatValue->setText(QString::number(PowerPC::MMU::HostRead_F32(guard, entry.address))); floatValue->setText(QString::number(PowerPC::MMU::HostRead<float>(guard, entry.address)));
lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked); lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked);
} }
} }
@@ -425,7 +425,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
} }
else else
{ {
PowerPC::MMU::HostWrite_U32(guard, value, debug_interface.GetWatch(row).address); PowerPC::MMU::HostWrite<u32>(guard, value, debug_interface.GetWatch(row).address);
} }
} }
else else
+2 -2
View File
@@ -1644,7 +1644,7 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress)
for (; len < MODULE_NAME_MAX_LENGTH; ++len) for (; len < MODULE_NAME_MAX_LENGTH; ++len)
{ {
const auto res = PowerPC::MMU::HostRead_U8(guard, *found_addr - (len + 1)); const auto res = PowerPC::MMU::HostRead<u8>(guard, *found_addr - (len + 1));
if (!std::isprint(res)) if (!std::isprint(res))
{ {
break; break;
@@ -1988,7 +1988,7 @@ void MenuBar::SearchInstruction()
for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal(); for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal();
addr += 4) addr += 4)
{ {
if (op_std == PPCTables::GetInstructionName(PowerPC::MMU::HostRead_U32(guard, addr), addr)) if (op_std == PPCTables::GetInstructionName(PowerPC::MMU::HostRead<u32>(guard, addr), addr))
{ {
NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op_std, addr); NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op_std, addr);
found = true; found = true;