PowerPC/MMU: Refactor to class, move to System.
This commit is contained in:
parent
012044eb64
commit
8dabd1a025
|
@ -1137,6 +1137,17 @@ public:
|
||||||
ABI_CallFunction(func);
|
ABI_CallFunction(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename FunctionPointer>
|
||||||
|
void ABI_CallFunctionPAC(int bits, FunctionPointer func, const void* ptr1, const Gen::OpArg& arg2,
|
||||||
|
u32 param3)
|
||||||
|
{
|
||||||
|
if (!arg2.IsSimpleReg(ABI_PARAM2))
|
||||||
|
MOV(bits, R(ABI_PARAM2), arg2);
|
||||||
|
MOV(32, R(ABI_PARAM3), Imm32(param3));
|
||||||
|
MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(ptr1)));
|
||||||
|
ABI_CallFunction(func);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename FunctionPointer>
|
template <typename FunctionPointer>
|
||||||
void ABI_CallFunctionA(int bits, FunctionPointer func, const Gen::OpArg& arg1)
|
void ABI_CallFunctionA(int bits, FunctionPointer func, const Gen::OpArg& arg1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -375,7 +375,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA
|
||||||
const u32 repeat = data >> 8;
|
const u32 repeat = data >> 8;
|
||||||
for (u32 i = 0; i <= repeat; ++i)
|
for (u32 i = 0; i <= repeat; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, data & 0xFF, new_addr + i);
|
PowerPC::MMU::HostWrite_U8(guard, data & 0xFF, new_addr + i);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFF, new_addr + i);
|
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFF, new_addr + i);
|
||||||
}
|
}
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
|
@ -389,7 +389,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA
|
||||||
const u32 repeat = data >> 16;
|
const u32 repeat = data >> 16;
|
||||||
for (u32 i = 0; i <= repeat; ++i)
|
for (u32 i = 0; i <= repeat; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2);
|
PowerPC::MMU::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFFFF, new_addr + i * 2);
|
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFFFF, new_addr + i * 2);
|
||||||
}
|
}
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
|
@ -400,7 +400,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA
|
||||||
case DATATYPE_32BIT: // Dword write
|
case DATATYPE_32BIT: // Dword write
|
||||||
LogInfo("32-bit Write");
|
LogInfo("32-bit Write");
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
PowerPC::HostWrite_U32(guard, data, new_addr);
|
PowerPC::MMU::HostWrite_U32(guard, data, new_addr);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", data, new_addr);
|
LogInfo("Wrote {:08x} to address {:08x}", data, new_addr);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
@ -420,7 +420,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::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);
|
||||||
|
@ -436,7 +436,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd
|
||||||
LogInfo("Pointer: {:08x}", ptr);
|
LogInfo("Pointer: {:08x}", ptr);
|
||||||
LogInfo("Byte: {:08x}", thebyte);
|
LogInfo("Byte: {:08x}", thebyte);
|
||||||
LogInfo("Offset: {:08x}", offset);
|
LogInfo("Offset: {:08x}", offset);
|
||||||
PowerPC::HostWrite_U8(guard, thebyte, ptr + offset);
|
PowerPC::MMU::HostWrite_U8(guard, thebyte, ptr + offset);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", thebyte, ptr + offset);
|
LogInfo("Wrote {:08x} to address {:08x}", thebyte, ptr + offset);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
@ -451,7 +451,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd
|
||||||
LogInfo("Pointer: {:08x}", ptr);
|
LogInfo("Pointer: {:08x}", ptr);
|
||||||
LogInfo("Byte: {:08x}", theshort);
|
LogInfo("Byte: {:08x}", theshort);
|
||||||
LogInfo("Offset: {:08x}", offset);
|
LogInfo("Offset: {:08x}", offset);
|
||||||
PowerPC::HostWrite_U16(guard, theshort, ptr + offset);
|
PowerPC::MMU::HostWrite_U16(guard, theshort, ptr + offset);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", theshort, ptr + offset);
|
LogInfo("Wrote {:08x} to address {:08x}", theshort, ptr + offset);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
@ -461,7 +461,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd
|
||||||
case DATATYPE_32BIT:
|
case DATATYPE_32BIT:
|
||||||
LogInfo("Write 32-bit to pointer");
|
LogInfo("Write 32-bit to pointer");
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
PowerPC::HostWrite_U32(guard, data, ptr);
|
PowerPC::MMU::HostWrite_U32(guard, data, ptr);
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", data, ptr);
|
LogInfo("Wrote {:08x} to address {:08x}", data, ptr);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
@ -489,24 +489,28 @@ 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("--------");
|
||||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, new_addr) + data, new_addr);
|
PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, new_addr) + data, new_addr);
|
||||||
LogInfo("Wrote {:02x} to address {:08x}", PowerPC::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("--------");
|
||||||
PowerPC::HostWrite_U16(guard, PowerPC::HostRead_U16(guard, new_addr) + data, new_addr);
|
PowerPC::MMU::HostWrite_U16(guard, PowerPC::MMU::HostRead_U16(guard, new_addr) + data,
|
||||||
LogInfo("Wrote {:04x} to address {:08x}", PowerPC::HostRead_U16(guard, new_addr), new_addr);
|
new_addr);
|
||||||
|
LogInfo("Wrote {:04x} to address {:08x}", PowerPC::MMU::HostRead_U16(guard, new_addr),
|
||||||
|
new_addr);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATATYPE_32BIT:
|
case DATATYPE_32BIT:
|
||||||
LogInfo("32-bit Add");
|
LogInfo("32-bit Add");
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
PowerPC::HostWrite_U32(guard, PowerPC::HostRead_U32(guard, new_addr) + data, new_addr);
|
PowerPC::MMU::HostWrite_U32(guard, PowerPC::MMU::HostRead_U32(guard, new_addr) + data,
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U32(guard, new_addr), new_addr);
|
new_addr);
|
||||||
|
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U32(guard, new_addr),
|
||||||
|
new_addr);
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -515,12 +519,12 @@ 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::HostRead_U32(guard, new_addr);
|
const u32 read = PowerPC::MMU::HostRead_U32(guard, new_addr);
|
||||||
const float read_float = Common::BitCast<float>(read);
|
const float read_float = Common::BitCast<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);
|
||||||
const u32 newval = Common::BitCast<u32>(fread);
|
const u32 newval = Common::BitCast<u32>(fread);
|
||||||
PowerPC::HostWrite_U32(guard, newval, new_addr);
|
PowerPC::MMU::HostWrite_U32(guard, newval, new_addr);
|
||||||
LogInfo("Old Value {:08x}", read);
|
LogInfo("Old Value {:08x}", read);
|
||||||
LogInfo("Increment {:08x}", data);
|
LogInfo("Increment {:08x}", data);
|
||||||
LogInfo("New value {:08x}", newval);
|
LogInfo("New value {:08x}", newval);
|
||||||
|
@ -578,7 +582,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
for (int i = 0; i < write_num; ++i)
|
for (int i = 0; i < write_num; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, val & 0xFF, curr_addr);
|
PowerPC::MMU::HostWrite_U8(guard, val & 0xFF, curr_addr);
|
||||||
curr_addr += addr_incr;
|
curr_addr += addr_incr;
|
||||||
val += val_incr;
|
val += val_incr;
|
||||||
LogInfo("Write {:08x} to address {:08x}", val & 0xFF, curr_addr);
|
LogInfo("Write {:08x} to address {:08x}", val & 0xFF, curr_addr);
|
||||||
|
@ -594,7 +598,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
for (int i = 0; i < write_num; ++i)
|
for (int i = 0; i < write_num; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U16(guard, val & 0xFFFF, curr_addr);
|
PowerPC::MMU::HostWrite_U16(guard, val & 0xFFFF, curr_addr);
|
||||||
LogInfo("Write {:08x} to address {:08x}", val & 0xFFFF, curr_addr);
|
LogInfo("Write {:08x} to address {:08x}", val & 0xFFFF, curr_addr);
|
||||||
curr_addr += addr_incr * 2;
|
curr_addr += addr_incr * 2;
|
||||||
val += val_incr;
|
val += val_incr;
|
||||||
|
@ -609,7 +613,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
for (int i = 0; i < write_num; ++i)
|
for (int i = 0; i < write_num; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U32(guard, val, curr_addr);
|
PowerPC::MMU::HostWrite_U32(guard, val, curr_addr);
|
||||||
LogInfo("Write {:08x} to address {:08x}", val, curr_addr);
|
LogInfo("Write {:08x} to address {:08x}", val, curr_addr);
|
||||||
curr_addr += addr_incr * 4;
|
curr_addr += addr_incr * 4;
|
||||||
val += val_incr;
|
val += val_incr;
|
||||||
|
@ -650,14 +654,15 @@ 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::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::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)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, ptr_src + i), ptr_dest + i);
|
PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, ptr_src + i),
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, ptr_src + i),
|
ptr_dest + i);
|
||||||
|
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, ptr_src + i),
|
||||||
ptr_dest + i);
|
ptr_dest + i);
|
||||||
}
|
}
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
|
@ -668,8 +673,9 @@ 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)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, addr_src + i), addr_dest + i);
|
PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, addr_src + i),
|
||||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, addr_src + i),
|
addr_dest + i);
|
||||||
|
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, addr_src + i),
|
||||||
addr_dest + i);
|
addr_dest + i);
|
||||||
}
|
}
|
||||||
LogInfo("--------");
|
LogInfo("--------");
|
||||||
|
@ -777,16 +783,16 @@ 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::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::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::HostRead_U32(guard, new_addr), data, addr.type);
|
result = CompareValues(PowerPC::MMU::HostRead_U32(guard, new_addr), data, addr.type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -51,7 +51,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::HostWrite_U64(guard, time_base_ticks, 0x800030D8);
|
PowerPC::MMU::HostWrite_U64(guard, time_base_ticks, 0x800030D8);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -127,8 +127,10 @@ void CBoot::SetupBAT(Core::System& system, bool is_wii)
|
||||||
ppc_state.spr[SPR_DBAT5L] = 0x1000002a;
|
ppc_state.spr[SPR_DBAT5L] = 0x1000002a;
|
||||||
HID4(ppc_state).SBE = 1;
|
HID4(ppc_state).SBE = 1;
|
||||||
}
|
}
|
||||||
PowerPC::DBATUpdated();
|
|
||||||
PowerPC::IBATUpdated();
|
auto& mmu = system.GetMMU();
|
||||||
|
mmu.DBATUpdated();
|
||||||
|
mmu.IBATUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
||||||
|
@ -153,6 +155,7 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard
|
||||||
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
|
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
|
||||||
|
|
||||||
auto& ppc_state = system.GetPPCState();
|
auto& ppc_state = system.GetPPCState();
|
||||||
|
auto& mmu = system.GetMMU();
|
||||||
|
|
||||||
// Call iAppLoaderEntry.
|
// Call iAppLoaderEntry.
|
||||||
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderEntry");
|
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderEntry");
|
||||||
|
@ -161,13 +164,13 @@ 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 = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
const u32 iAppLoaderInit = mmu.Read_U32(iAppLoaderFuncAddr + 0);
|
||||||
const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
const u32 iAppLoaderMain = mmu.Read_U32(iAppLoaderFuncAddr + 4);
|
||||||
const u32 iAppLoaderClose = PowerPC::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::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);
|
||||||
|
@ -189,9 +192,9 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard
|
||||||
// iAppLoaderMain returns 0 when there are no more sections to copy.
|
// 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 = PowerPC::Read_U32(0x81300004);
|
const u32 ram_address = mmu.Read_U32(0x81300004);
|
||||||
const u32 length = PowerPC::Read_U32(0x81300008);
|
const u32 length = mmu.Read_U32(0x81300008);
|
||||||
const u32 dvd_offset = PowerPC::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);
|
||||||
|
@ -223,35 +226,35 @@ 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::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::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::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::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::HostWrite_U32(guard, 0x01000000, 0x800000d0);
|
PowerPC::MMU::HostWrite_U32(guard, 0x01000000, 0x800000d0);
|
||||||
|
|
||||||
PowerPC::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
PowerPC::MMU::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||||
PowerPC::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
PowerPC::MMU::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||||
|
|
||||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi
|
PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi
|
||||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
PowerPC::MMU::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||||
|
|
||||||
PresetTimeBaseTicks(system, guard);
|
PresetTimeBaseTicks(system, guard);
|
||||||
|
|
||||||
// HIO checks this
|
// HIO checks this
|
||||||
// PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
// PowerPC::MMU::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||||
}
|
}
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
|
|
|
@ -111,7 +111,7 @@ 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::HostTryReadU8(guard, addr, space);
|
return PowerPC::MMU::HostTryReadU8(guard, addr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -119,7 +119,7 @@ std::optional<PowerPC::ReadResult<u16>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
return PowerPC::HostTryReadU16(guard, addr, space);
|
return PowerPC::MMU::HostTryReadU16(guard, addr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -127,7 +127,7 @@ std::optional<PowerPC::ReadResult<u32>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
return PowerPC::HostTryReadU32(guard, addr, space);
|
return PowerPC::MMU::HostTryReadU32(guard, addr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -135,7 +135,7 @@ std::optional<PowerPC::ReadResult<u64>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
return PowerPC::HostTryReadU64(guard, addr, space);
|
return PowerPC::MMU::HostTryReadU64(guard, addr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -143,7 +143,7 @@ std::optional<PowerPC::ReadResult<s8>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
auto tmp = PowerPC::HostTryReadU8(guard, addr, space);
|
auto tmp = PowerPC::MMU::HostTryReadU8(guard, addr, space);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return PowerPC::ReadResult<s8>(tmp->translated, Common::BitCast<s8>(tmp->value));
|
return PowerPC::ReadResult<s8>(tmp->translated, Common::BitCast<s8>(tmp->value));
|
||||||
|
@ -154,7 +154,7 @@ std::optional<PowerPC::ReadResult<s16>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
auto tmp = PowerPC::HostTryReadU16(guard, addr, space);
|
auto tmp = PowerPC::MMU::HostTryReadU16(guard, addr, space);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return PowerPC::ReadResult<s16>(tmp->translated, Common::BitCast<s16>(tmp->value));
|
return PowerPC::ReadResult<s16>(tmp->translated, Common::BitCast<s16>(tmp->value));
|
||||||
|
@ -165,7 +165,7 @@ std::optional<PowerPC::ReadResult<s32>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
auto tmp = PowerPC::HostTryReadU32(guard, addr, space);
|
auto tmp = PowerPC::MMU::HostTryReadU32(guard, addr, space);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return PowerPC::ReadResult<s32>(tmp->translated, Common::BitCast<s32>(tmp->value));
|
return PowerPC::ReadResult<s32>(tmp->translated, Common::BitCast<s32>(tmp->value));
|
||||||
|
@ -176,7 +176,7 @@ std::optional<PowerPC::ReadResult<s64>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
auto tmp = PowerPC::HostTryReadU64(guard, addr, space);
|
auto tmp = PowerPC::MMU::HostTryReadU64(guard, addr, space);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return PowerPC::ReadResult<s64>(tmp->translated, Common::BitCast<s64>(tmp->value));
|
return PowerPC::ReadResult<s64>(tmp->translated, Common::BitCast<s64>(tmp->value));
|
||||||
|
@ -187,7 +187,7 @@ std::optional<PowerPC::ReadResult<float>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
return PowerPC::HostTryReadF32(guard, addr, space);
|
return PowerPC::MMU::HostTryReadF32(guard, addr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -195,7 +195,7 @@ std::optional<PowerPC::ReadResult<double>>
|
||||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||||
PowerPC::RequestedAddressSpace space)
|
PowerPC::RequestedAddressSpace space)
|
||||||
{
|
{
|
||||||
return PowerPC::HostTryReadF64(guard, addr, space);
|
return PowerPC::MMU::HostTryReadF64(guard, addr, space);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ void AddAutoBreakpoints()
|
||||||
// Returns true if the address is not a valid RAM address or NULL.
|
// Returns true if the address is not a valid RAM address or NULL.
|
||||||
static bool IsStackBottom(const Core::CPUThreadGuard& guard, u32 addr)
|
static bool IsStackBottom(const Core::CPUThreadGuard& guard, u32 addr)
|
||||||
{
|
{
|
||||||
return !addr || !PowerPC::HostIsRAMAddress(guard, addr);
|
return !addr || !PowerPC::MMU::HostIsRAMAddress(guard, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard,
|
static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||||
|
@ -51,18 +51,18 @@ static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard
|
||||||
|
|
||||||
if (!IsStackBottom(guard, ppc_state.gpr[1]))
|
if (!IsStackBottom(guard, ppc_state.gpr[1]))
|
||||||
{
|
{
|
||||||
u32 addr = PowerPC::HostRead_U32(guard, ppc_state.gpr[1]); // SP
|
u32 addr = PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[1]); // SP
|
||||||
|
|
||||||
// Walk the stack chain
|
// 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::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::HostRead_U32(guard, addr);
|
addr = PowerPC::MMU::HostRead_U32(guard, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ bool GetCallstack(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||||
{
|
{
|
||||||
auto& ppc_state = system.GetPPCState();
|
auto& ppc_state = system.GetPPCState();
|
||||||
|
|
||||||
if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[1]))
|
if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[1]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (LR(ppc_state) == 0)
|
if (LR(ppc_state) == 0)
|
||||||
|
|
|
@ -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::HostRead_U32(guard, addr + u32(i * sizeof(int)));
|
gpr[i] = PowerPC::MMU::HostRead_U32(guard, addr + u32(i * sizeof(int)));
|
||||||
cr = PowerPC::HostRead_U32(guard, addr + 0x80);
|
cr = PowerPC::MMU::HostRead_U32(guard, addr + 0x80);
|
||||||
lr = PowerPC::HostRead_U32(guard, addr + 0x84);
|
lr = PowerPC::MMU::HostRead_U32(guard, addr + 0x84);
|
||||||
ctr = PowerPC::HostRead_U32(guard, addr + 0x88);
|
ctr = PowerPC::MMU::HostRead_U32(guard, addr + 0x88);
|
||||||
xer = PowerPC::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::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double)));
|
fpr[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double)));
|
||||||
fpscr = PowerPC::HostRead_U64(guard, addr + 0x190);
|
fpscr = PowerPC::MMU::HostRead_U64(guard, addr + 0x190);
|
||||||
srr0 = PowerPC::HostRead_U32(guard, addr + 0x198);
|
srr0 = PowerPC::MMU::HostRead_U32(guard, addr + 0x198);
|
||||||
srr1 = PowerPC::HostRead_U32(guard, addr + 0x19c);
|
srr1 = PowerPC::MMU::HostRead_U32(guard, addr + 0x19c);
|
||||||
dummy = PowerPC::HostRead_U16(guard, addr + 0x1a0);
|
dummy = PowerPC::MMU::HostRead_U16(guard, addr + 0x1a0);
|
||||||
state = static_cast<OSContext::State>(PowerPC::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::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::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double)));
|
psf[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutex offsets based on the following functions:
|
// 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::HostRead_U32(guard, addr);
|
thread_queue.head = PowerPC::MMU::HostRead_U32(guard, addr);
|
||||||
thread_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x4);
|
thread_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x4);
|
||||||
owner_addr = PowerPC::HostRead_U32(guard, addr + 0x8);
|
owner_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x8);
|
||||||
lock_count = PowerPC::HostRead_U32(guard, addr + 0xc);
|
lock_count = PowerPC::MMU::HostRead_U32(guard, addr + 0xc);
|
||||||
link.next = PowerPC::HostRead_U32(guard, addr + 0x10);
|
link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x10);
|
||||||
link.prev = PowerPC::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::HostRead_U16(guard, addr + 0x2c8);
|
state = PowerPC::MMU::HostRead_U16(guard, addr + 0x2c8);
|
||||||
is_detached = PowerPC::HostRead_U16(guard, addr + 0x2ca);
|
is_detached = PowerPC::MMU::HostRead_U16(guard, addr + 0x2ca);
|
||||||
suspend = PowerPC::HostRead_U32(guard, addr + 0x2cc);
|
suspend = PowerPC::MMU::HostRead_U32(guard, addr + 0x2cc);
|
||||||
effective_priority = PowerPC::HostRead_U32(guard, addr + 0x2d0);
|
effective_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d0);
|
||||||
base_priority = PowerPC::HostRead_U32(guard, addr + 0x2d4);
|
base_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d4);
|
||||||
exit_code_addr = PowerPC::HostRead_U32(guard, addr + 0x2d8);
|
exit_code_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d8);
|
||||||
|
|
||||||
queue_addr = PowerPC::HostRead_U32(guard, addr + 0x2dc);
|
queue_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2dc);
|
||||||
queue_link.next = PowerPC::HostRead_U32(guard, addr + 0x2e0);
|
queue_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e0);
|
||||||
queue_link.prev = PowerPC::HostRead_U32(guard, addr + 0x2e4);
|
queue_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e4);
|
||||||
|
|
||||||
join_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2e8);
|
join_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e8);
|
||||||
join_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2ec);
|
join_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2ec);
|
||||||
|
|
||||||
mutex_addr = PowerPC::HostRead_U32(guard, addr + 0x2f0);
|
mutex_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f0);
|
||||||
mutex_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2f4);
|
mutex_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f4);
|
||||||
mutex_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2f8);
|
mutex_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f8);
|
||||||
|
|
||||||
thread_link.next = PowerPC::HostRead_U32(guard, addr + 0x2fc);
|
thread_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2fc);
|
||||||
thread_link.prev = PowerPC::HostRead_U32(guard, addr + 0x300);
|
thread_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x300);
|
||||||
|
|
||||||
stack_addr = PowerPC::HostRead_U32(guard, addr + 0x304);
|
stack_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x304);
|
||||||
stack_end = PowerPC::HostRead_U32(guard, addr + 0x308);
|
stack_end = PowerPC::MMU::HostRead_U32(guard, addr + 0x308);
|
||||||
error = PowerPC::HostRead_U32(guard, addr + 0x30c);
|
error = PowerPC::MMU::HostRead_U32(guard, addr + 0x30c);
|
||||||
specific[0] = PowerPC::HostRead_U32(guard, addr + 0x310);
|
specific[0] = PowerPC::MMU::HostRead_U32(guard, addr + 0x310);
|
||||||
specific[1] = PowerPC::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::HostIsRAMAddress(guard, stack_end) &&
|
return PowerPC::MMU::HostIsRAMAddress(guard, stack_end) &&
|
||||||
PowerPC::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)
|
||||||
|
@ -192,9 +192,9 @@ std::string OSThreadView::GetSpecific(const Core::CPUThreadGuard& guard) const
|
||||||
|
|
||||||
for (u32 addr : m_thread.specific)
|
for (u32 addr : m_thread.specific)
|
||||||
{
|
{
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, addr))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
|
||||||
break;
|
break;
|
||||||
specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(guard, addr));
|
specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::MMU::HostGetString(guard, addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return specific;
|
return specific;
|
||||||
|
|
|
@ -33,20 +33,20 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa
|
||||||
|
|
||||||
const u32 address = patch.address;
|
const u32 address = patch.address;
|
||||||
const std::size_t size = patch.value.size();
|
const std::size_t size = patch.value.size();
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, address))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, address))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (u32 offset = 0; offset < size; ++offset)
|
for (u32 offset = 0; offset < size; ++offset)
|
||||||
{
|
{
|
||||||
if (store_existing_value)
|
if (store_existing_value)
|
||||||
{
|
{
|
||||||
const u8 value = PowerPC::HostRead_U8(guard, address + offset);
|
const u8 value = PowerPC::MMU::HostRead_U8(guard, address + offset);
|
||||||
PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset);
|
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset);
|
||||||
patch.value[offset] = value;
|
patch.value[offset] = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset);
|
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((address + offset) % 4) == 3)
|
if (((address + offset) % 4) == 3)
|
||||||
|
@ -231,10 +231,10 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
|
||||||
Common::Debug::Threads threads;
|
Common::Debug::Threads threads;
|
||||||
|
|
||||||
constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc;
|
constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc;
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR))
|
||||||
return threads;
|
return threads;
|
||||||
const u32 active_queue_head = PowerPC::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR);
|
const u32 active_queue_head = PowerPC::MMU::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR);
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, active_queue_head))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, active_queue_head))
|
||||||
return threads;
|
return threads;
|
||||||
|
|
||||||
auto active_thread = std::make_unique<Core::Debug::OSThreadView>(guard, active_queue_head);
|
auto active_thread = std::make_unique<Core::Debug::OSThreadView>(guard, active_queue_head);
|
||||||
|
@ -243,7 +243,7 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
|
||||||
|
|
||||||
std::vector<u32> visited_addrs{active_thread->GetAddress()};
|
std::vector<u32> visited_addrs{active_thread->GetAddress()};
|
||||||
const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) {
|
const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) {
|
||||||
while (addr != 0 && PowerPC::HostIsRAMAddress(guard, addr))
|
while (addr != 0 && PowerPC::MMU::HostIsRAMAddress(guard, addr))
|
||||||
{
|
{
|
||||||
if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end())
|
if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end())
|
||||||
break;
|
break;
|
||||||
|
@ -271,12 +271,12 @@ std::string PPCDebugInterface::Disassemble(const Core::CPUThreadGuard* guard, u3
|
||||||
{
|
{
|
||||||
if (guard)
|
if (guard)
|
||||||
{
|
{
|
||||||
if (!PowerPC::HostIsRAMAddress(*guard, address))
|
if (!PowerPC::MMU::HostIsRAMAddress(*guard, address))
|
||||||
{
|
{
|
||||||
return "(No RAM here)";
|
return "(No RAM here)";
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 op = PowerPC::HostRead_Instruction(*guard, address);
|
const u32 op = PowerPC::MMU::HostRead_Instruction(*guard, address);
|
||||||
std::string disasm = Common::GekkoDisassembler::Disassemble(op, address);
|
std::string disasm = Common::GekkoDisassembler::Disassemble(op, address);
|
||||||
const UGeckoInstruction inst{op};
|
const UGeckoInstruction inst{op};
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu
|
||||||
{
|
{
|
||||||
const bool is_aram = memory != 0;
|
const bool is_aram = memory != 0;
|
||||||
|
|
||||||
if (is_aram || PowerPC::HostIsRAMAddress(guard, address))
|
if (is_aram || PowerPC::MMU::HostIsRAMAddress(guard, address))
|
||||||
{
|
{
|
||||||
return fmt::format("{:08X}{}", ReadExtraMemory(guard, memory, address),
|
return fmt::format("{:08X}{}", ReadExtraMemory(guard, memory, address),
|
||||||
is_aram ? " (ARAM)" : "");
|
is_aram ? " (ARAM)" : "");
|
||||||
|
@ -314,7 +314,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu
|
||||||
|
|
||||||
u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const
|
u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U32(guard, address);
|
return PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory,
|
u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory,
|
||||||
|
@ -323,7 +323,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me
|
||||||
switch (memory)
|
switch (memory)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return PowerPC::HostRead_U32(guard, address);
|
return PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
auto& dsp = Core::System::GetInstance().GetDSP();
|
auto& dsp = Core::System::GetInstance().GetDSP();
|
||||||
|
@ -337,7 +337,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me
|
||||||
|
|
||||||
u32 PPCDebugInterface::ReadInstruction(const Core::CPUThreadGuard& guard, u32 address) const
|
u32 PPCDebugInterface::ReadInstruction(const Core::CPUThreadGuard& guard, u32 address) const
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_Instruction(guard, address);
|
return PowerPC::MMU::HostRead_Instruction(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PPCDebugInterface::IsAlive() const
|
bool PPCDebugInterface::IsAlive() const
|
||||||
|
@ -412,7 +412,7 @@ u32 PPCDebugInterface::GetColor(const Core::CPUThreadGuard* guard, u32 address)
|
||||||
{
|
{
|
||||||
if (!guard || !IsAlive())
|
if (!guard || !IsAlive())
|
||||||
return 0xFFFFFF;
|
return 0xFFFFFF;
|
||||||
if (!PowerPC::HostIsRAMAddress(*guard, address))
|
if (!PowerPC::MMU::HostIsRAMAddress(*guard, address))
|
||||||
return 0xeeeeee;
|
return 0xeeeeee;
|
||||||
|
|
||||||
Common::Symbol* symbol = g_symbolDB.GetSymbolFromAddr(address);
|
Common::Symbol* symbol = g_symbolDB.GetSymbolFromAddr(address);
|
||||||
|
|
|
@ -17,37 +17,42 @@
|
||||||
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::HostRead_U32(guard, address);
|
m_header.entry.next_entry = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
m_header.entry.prev_entry = PowerPC::HostRead_U32(guard, address + 0x04);
|
m_header.entry.prev_entry = PowerPC::MMU::HostRead_U32(guard, address + 0x04);
|
||||||
m_header.entry.section_count = PowerPC::HostRead_U32(guard, address + 0x08);
|
m_header.entry.section_count = PowerPC::MMU::HostRead_U32(guard, address + 0x08);
|
||||||
m_header.entry.section_table_offset = PowerPC::HostRead_U32(guard, address + 0xC);
|
m_header.entry.section_table_offset = PowerPC::MMU::HostRead_U32(guard, address + 0xC);
|
||||||
m_header.entry.name_offset = PowerPC::HostRead_U32(guard, address + 0x10);
|
m_header.entry.name_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x10);
|
||||||
m_header.entry.name_size = PowerPC::HostRead_U32(guard, address + 0x14);
|
m_header.entry.name_size = PowerPC::MMU::HostRead_U32(guard, address + 0x14);
|
||||||
m_header.entry.version = PowerPC::HostRead_U32(guard, address + 0x18);
|
m_header.entry.version = PowerPC::MMU::HostRead_U32(guard, address + 0x18);
|
||||||
m_header.entry.bss_size = PowerPC::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::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::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::HostRead_U8(guard, address + 0x22);
|
m_header.section_info.unresolved_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x22);
|
||||||
m_header.section_info.bss_section_index = PowerPC::HostRead_U8(guard, address + 0x23);
|
m_header.section_info.bss_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x23);
|
||||||
m_header.section_info.prolog_offset = PowerPC::HostRead_U32(guard, address + 0x24);
|
m_header.section_info.prolog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x24);
|
||||||
m_header.section_info.epilog_offset = PowerPC::HostRead_U32(guard, address + 0x28);
|
m_header.section_info.epilog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x28);
|
||||||
m_header.section_info.unresolved_offset = PowerPC::HostRead_U32(guard, address + 0x2C);
|
m_header.section_info.unresolved_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x2C);
|
||||||
m_header.relocation_tables.internals_offset = PowerPC::HostRead_U32(guard, address + 0x30);
|
m_header.relocation_tables.internals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x30);
|
||||||
m_header.relocation_tables.internals_size = PowerPC::HostRead_U32(guard, address + 0x34);
|
m_header.relocation_tables.internals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x34);
|
||||||
m_header.relocation_tables.externals_offset = PowerPC::HostRead_U32(guard, address + 0x38);
|
m_header.relocation_tables.externals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x38);
|
||||||
m_header.relocation_tables.externals_size = PowerPC::HostRead_U32(guard, address + 0x3C);
|
m_header.relocation_tables.externals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x3C);
|
||||||
m_header.symbol_tables.exports_offset = PowerPC::HostRead_U32(guard, address + 0x40);
|
m_header.symbol_tables.exports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x40);
|
||||||
m_header.symbol_tables.exports_size = PowerPC::HostRead_U32(guard, address + 0x44);
|
m_header.symbol_tables.exports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x44);
|
||||||
m_header.symbol_tables.exports_name_table = PowerPC::HostRead_U32(guard, address + 0x48);
|
m_header.symbol_tables.exports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x48);
|
||||||
m_header.symbol_tables.imports_offset = PowerPC::HostRead_U32(guard, address + 0x4C);
|
m_header.symbol_tables.imports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x4C);
|
||||||
m_header.symbol_tables.imports_size = PowerPC::HostRead_U32(guard, address + 0x50);
|
m_header.symbol_tables.imports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x50);
|
||||||
m_header.symbol_tables.imports_name_table = PowerPC::HostRead_U32(guard, address + 0x54);
|
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)
|
||||||
m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size);
|
{
|
||||||
|
m_name =
|
||||||
|
PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, 0x100);
|
{
|
||||||
|
m_name = PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, 0x100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 RSOHeaderView::GetNextEntry() const
|
u32 RSOHeaderView::GetNextEntry() const
|
||||||
|
@ -176,8 +181,8 @@ void RSOSectionsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::
|
||||||
for (std::size_t i = 0; i < count; ++i)
|
for (std::size_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
RSOSection section;
|
RSOSection section;
|
||||||
section.offset = PowerPC::HostRead_U32(guard, address);
|
section.offset = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
section.size = PowerPC::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);
|
||||||
}
|
}
|
||||||
|
@ -204,9 +209,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::HostRead_U32(guard, address);
|
rso_import.name_offset = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
rso_import.code_offset = PowerPC::HostRead_U32(guard, address + 4);
|
rso_import.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4);
|
||||||
rso_import.entry_offset = PowerPC::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);
|
||||||
}
|
}
|
||||||
|
@ -233,10 +238,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::HostRead_U32(guard, address);
|
rso_export.name_offset = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
rso_export.code_offset = PowerPC::HostRead_U32(guard, address + 4);
|
rso_export.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4);
|
||||||
rso_export.section_index = PowerPC::HostRead_U32(guard, address + 8);
|
rso_export.section_index = PowerPC::MMU::HostRead_U32(guard, address + 8);
|
||||||
rso_export.hash = PowerPC::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);
|
||||||
}
|
}
|
||||||
|
@ -263,9 +268,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::HostRead_U32(guard, address);
|
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
entry.r_info = PowerPC::HostRead_U32(guard, address + 4);
|
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4);
|
||||||
entry.r_addend = PowerPC::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);
|
||||||
}
|
}
|
||||||
|
@ -292,9 +297,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::HostRead_U32(guard, address);
|
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
entry.r_info = PowerPC::HostRead_U32(guard, address + 4);
|
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4);
|
||||||
entry.r_addend = PowerPC::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);
|
||||||
}
|
}
|
||||||
|
@ -443,7 +448,8 @@ const RSOImport& RSOView::GetImport(std::size_t index) const
|
||||||
std::string RSOView::GetImportName(const Core::CPUThreadGuard& guard,
|
std::string RSOView::GetImportName(const Core::CPUThreadGuard& guard,
|
||||||
const RSOImport& rso_import) const
|
const RSOImport& rso_import) const
|
||||||
{
|
{
|
||||||
return PowerPC::HostGetString(guard, m_header.GetImportsNameTable() + rso_import.name_offset);
|
return PowerPC::MMU::HostGetString(guard,
|
||||||
|
m_header.GetImportsNameTable() + rso_import.name_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<RSOImport>& RSOView::GetImports() const
|
const std::vector<RSOImport>& RSOView::GetImports() const
|
||||||
|
@ -464,7 +470,8 @@ const RSOExport& RSOView::GetExport(std::size_t index) const
|
||||||
std::string RSOView::GetExportName(const Core::CPUThreadGuard& guard,
|
std::string RSOView::GetExportName(const Core::CPUThreadGuard& guard,
|
||||||
const RSOExport& rso_export) const
|
const RSOExport& rso_export) const
|
||||||
{
|
{
|
||||||
return PowerPC::HostGetString(guard, m_header.GetExportsNameTable() + rso_export.name_offset);
|
return PowerPC::MMU::HostGetString(guard,
|
||||||
|
m_header.GetExportsNameTable() + rso_export.name_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 RSOView::GetExportAddress(const RSOExport& rso_export) const
|
u32 RSOView::GetExportAddress(const RSOExport& rso_export) const
|
||||||
|
|
|
@ -654,8 +654,10 @@ void FifoPlayer::LoadMemory()
|
||||||
ppc_state.spr[SPR_DBAT0L] = 0x00000002;
|
ppc_state.spr[SPR_DBAT0L] = 0x00000002;
|
||||||
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
|
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||||
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
|
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
|
||||||
PowerPC::DBATUpdated();
|
|
||||||
PowerPC::IBATUpdated();
|
auto& mmu = system.GetMMU();
|
||||||
|
mmu.DBATUpdated();
|
||||||
|
mmu.IBATUpdated();
|
||||||
|
|
||||||
SetupFifo();
|
SetupFifo();
|
||||||
LoadRegisters();
|
LoadRegisters();
|
||||||
|
@ -713,12 +715,12 @@ void FifoPlayer::LoadTextureMemory()
|
||||||
|
|
||||||
void FifoPlayer::WriteCP(u32 address, u16 value)
|
void FifoPlayer::WriteCP(u32 address, u16 value)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U16(value, 0xCC000000 | address);
|
Core::System::GetInstance().GetMMU().Write_U16(value, 0xCC000000 | address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::WritePI(u32 address, u32 value)
|
void FifoPlayer::WritePI(u32 address, u32 value)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U32(value, 0xCC003000 | address);
|
Core::System::GetInstance().GetMMU().Write_U32(value, 0xCC003000 | address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::FlushWGP()
|
void FifoPlayer::FlushWGP()
|
||||||
|
@ -823,13 +825,13 @@ bool FifoPlayer::ShouldLoadXF(u8 reg)
|
||||||
bool FifoPlayer::IsIdleSet()
|
bool FifoPlayer::IsIdleSet()
|
||||||
{
|
{
|
||||||
CommandProcessor::UCPStatusReg status =
|
CommandProcessor::UCPStatusReg status =
|
||||||
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
|
Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
|
||||||
return status.CommandIdle;
|
return status.CommandIdle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FifoPlayer::IsHighWatermarkSet()
|
bool FifoPlayer::IsHighWatermarkSet()
|
||||||
{
|
{
|
||||||
CommandProcessor::UCPStatusReg status =
|
CommandProcessor::UCPStatusReg status =
|
||||||
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
|
Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
|
||||||
return status.OverflowHiWatermark;
|
return status.OverflowHiWatermark;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,17 +142,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::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 (unsigned int h = 0; h < data.length(); h += 4)
|
for (unsigned int h = 0; h < data.length(); h += 4)
|
||||||
{
|
{
|
||||||
// Patch MMIO address
|
// Patch MMIO address
|
||||||
if (PowerPC::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) ==
|
if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) ==
|
||||||
(0x3f000000u | ((mmio_addr ^ 1) << 8)))
|
(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::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h);
|
PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +162,11 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
|
||||||
|
|
||||||
// Write a magic value to 'gameid' (codehandleronly does not actually read this).
|
// 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::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::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address);
|
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address);
|
||||||
PowerPC::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4);
|
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 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;
|
||||||
|
@ -189,8 +189,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::HostWrite_U32(guard, code.address, next_address);
|
PowerPC::MMU::HostWrite_U32(guard, code.address, next_address);
|
||||||
PowerPC::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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,12 +199,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::HostWrite_U32(guard, 0xF0000000, next_address);
|
PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address);
|
||||||
PowerPC::HostWrite_U32(guard, 0x00000000, next_address + 4);
|
PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4);
|
||||||
PowerPC::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS);
|
PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS);
|
||||||
|
|
||||||
// Turn on codes
|
// Turn on codes
|
||||||
PowerPC::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7);
|
PowerPC::MMU::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
auto& ppc_state = system.GetPPCState();
|
auto& ppc_state = system.GetPPCState();
|
||||||
|
@ -274,17 +274,18 @@ void RunCodeHandler(const Core::CPUThreadGuard& guard)
|
||||||
ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler
|
ppc_state.gpr[1] -= 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::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::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame
|
PowerPC::MMU::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame
|
||||||
PowerPC::HostWrite_U32(guard, ppc_state.pc, SP + 12);
|
PowerPC::MMU::HostWrite_U32(guard, ppc_state.pc, SP + 12);
|
||||||
PowerPC::HostWrite_U32(guard, LR(ppc_state), SP + 16);
|
PowerPC::MMU::HostWrite_U32(guard, LR(ppc_state), SP + 16);
|
||||||
PowerPC::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 (int i = 0; i < 14; ++i)
|
for (int i = 0; i < 14; ++i)
|
||||||
{
|
{
|
||||||
PowerPC::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::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(), SP + 24 + (2 * i + 1) * sizeof(u64));
|
PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(),
|
||||||
|
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. "
|
||||||
|
|
|
@ -42,7 +42,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::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;
|
||||||
|
@ -51,7 +51,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard)
|
||||||
{
|
{
|
||||||
gch_gameid = Gecko::MAGIC_GAMEID;
|
gch_gameid = Gecko::MAGIC_GAMEID;
|
||||||
}
|
}
|
||||||
PowerPC::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS);
|
PowerPC::MMU::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS);
|
||||||
|
|
||||||
ppc_state.iCache.Reset();
|
ppc_state.iCache.Reset();
|
||||||
}
|
}
|
||||||
|
@ -67,14 +67,14 @@ void GeckoReturnTrampoline(const Core::CPUThreadGuard& guard)
|
||||||
|
|
||||||
// Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler.
|
// Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler.
|
||||||
u32 SP = ppc_state.gpr[1];
|
u32 SP = ppc_state.gpr[1];
|
||||||
ppc_state.gpr[1] = PowerPC::HostRead_U32(guard, SP + 8);
|
ppc_state.gpr[1] = PowerPC::MMU::HostRead_U32(guard, SP + 8);
|
||||||
ppc_state.npc = PowerPC::HostRead_U32(guard, SP + 12);
|
ppc_state.npc = PowerPC::MMU::HostRead_U32(guard, SP + 12);
|
||||||
LR(ppc_state) = PowerPC::HostRead_U32(guard, SP + 16);
|
LR(ppc_state) = PowerPC::MMU::HostRead_U32(guard, SP + 16);
|
||||||
ppc_state.cr.Set(PowerPC::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::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)),
|
ppc_state.ps[i].SetBoth(PowerPC::MMU::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)),
|
||||||
PowerPC::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64)));
|
PowerPC::MMU::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace HLE_Misc
|
} // namespace HLE_Misc
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/HLE/HLE_VarArgs.h"
|
#include "Core/HLE/HLE_VarArgs.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
@ -56,11 +57,11 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para
|
||||||
std::string report_message;
|
std::string report_message;
|
||||||
|
|
||||||
// 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::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
|
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
|
||||||
(PowerPC::HostIsRAMAddress(guard, PowerPC::HostRead_U32(guard, ppc_state.gpr[3])) ||
|
(PowerPC::MMU::HostIsRAMAddress(guard, PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3])) ||
|
||||||
PowerPC::HostRead_U32(guard, ppc_state.gpr[3]) == 0))
|
PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3]) == 0))
|
||||||
{
|
{
|
||||||
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[4]))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[4]))
|
||||||
{
|
{
|
||||||
// ___blank(void* this, const char* fmt, ...);
|
// ___blank(void* this, const char* fmt, ...);
|
||||||
report_message = GetStringVA(system, guard, 4, parameter_type);
|
report_message = GetStringVA(system, guard, 4, parameter_type);
|
||||||
|
@ -73,7 +74,7 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]))
|
||||||
{
|
{
|
||||||
// ___blank(const char* fmt, ...);
|
// ___blank(const char* fmt, ...);
|
||||||
report_message = GetStringVA(system, guard, 3, parameter_type);
|
report_message = GetStringVA(system, guard, 3, parameter_type);
|
||||||
|
@ -106,13 +107,13 @@ void HLE_GeneralDebugVPrint(const Core::CPUThreadGuard& guard)
|
||||||
// __write_console(int fd, const void* buffer, const u32* size)
|
// __write_console(int fd, const void* buffer, const u32* size)
|
||||||
void HLE_write_console(const Core::CPUThreadGuard& guard)
|
void HLE_write_console(const Core::CPUThreadGuard& guard)
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = guard.GetSystem();
|
||||||
auto& ppc_state = system.GetPPCState();
|
auto& ppc_state = system.GetPPCState();
|
||||||
|
|
||||||
std::string report_message = GetStringVA(system, guard, 4);
|
std::string report_message = GetStringVA(system, guard, 4);
|
||||||
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[5]))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5]))
|
||||||
{
|
{
|
||||||
const u32 size = PowerPC::Read_U32(ppc_state.gpr[5]);
|
const u32 size = system.GetMMU().Read_U32(ppc_state.gpr[5]);
|
||||||
if (size > report_message.size())
|
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)
|
||||||
|
@ -169,16 +170,16 @@ void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_ty
|
||||||
// The structure FILE is implementation defined.
|
// The structure FILE is implementation defined.
|
||||||
// Both libogc and Dolphin SDK seem to store the fd at the same address.
|
// Both libogc and Dolphin SDK seem to store the fd at the same address.
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
|
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
|
||||||
PowerPC::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::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::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;
|
||||||
|
@ -210,7 +211,7 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||||
|
|
||||||
std::string ArgumentBuffer;
|
std::string ArgumentBuffer;
|
||||||
std::string result;
|
std::string result;
|
||||||
std::string string = PowerPC::HostGetString(guard, ppc_state.gpr[str_reg]);
|
std::string string = PowerPC::MMU::HostGetString(guard, ppc_state.gpr[str_reg]);
|
||||||
auto ap =
|
auto ap =
|
||||||
parameter_type == ParameterType::VariableArgumentList ?
|
parameter_type == ParameterType::VariableArgumentList ?
|
||||||
std::make_unique<HLE::SystemVABI::VAListStruct>(system, guard,
|
std::make_unique<HLE::SystemVABI::VAListStruct>(system, guard,
|
||||||
|
@ -242,8 +243,9 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||||
switch (string[i])
|
switch (string[i])
|
||||||
{
|
{
|
||||||
case 's':
|
case 's':
|
||||||
result += StringFromFormat(ArgumentBuffer.c_str(),
|
result +=
|
||||||
PowerPC::HostGetString(guard, ap->GetArgT<u32>(guard)).c_str());
|
StringFromFormat(ArgumentBuffer.c_str(),
|
||||||
|
PowerPC::MMU::HostGetString(guard, ap->GetArgT<u32>(guard)).c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
|
|
|
@ -20,10 +20,10 @@ double HLE::SystemVABI::VAList::GetFPR(const Core::CPUThreadGuard&, u32 fpr) con
|
||||||
|
|
||||||
HLE::SystemVABI::VAListStruct::VAListStruct(Core::System& system, const Core::CPUThreadGuard& guard,
|
HLE::SystemVABI::VAListStruct::VAListStruct(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||||
u32 address)
|
u32 address)
|
||||||
: VAList(system, 0), m_va_list{PowerPC::HostRead_U8(guard, address),
|
: VAList(system, 0), m_va_list{PowerPC::MMU::HostRead_U8(guard, address),
|
||||||
PowerPC::HostRead_U8(guard, address + 1),
|
PowerPC::MMU::HostRead_U8(guard, address + 1),
|
||||||
PowerPC::HostRead_U32(guard, address + 4),
|
PowerPC::MMU::HostRead_U32(guard, address + 4),
|
||||||
PowerPC::HostRead_U32(guard, address + 8)},
|
PowerPC::MMU::HostRead_U32(guard, address + 8)},
|
||||||
m_address(address), m_has_fpr_area(system.GetPPCState().cr.GetBit(6) == 1)
|
m_address(address), m_has_fpr_area(system.GetPPCState().cr.GetBit(6) == 1)
|
||||||
{
|
{
|
||||||
m_stack = m_va_list.overflow_arg_area;
|
m_stack = m_va_list.overflow_arg_area;
|
||||||
|
@ -49,7 +49,7 @@ u32 HLE::SystemVABI::VAListStruct::GetGPR(const Core::CPUThreadGuard& guard, u32
|
||||||
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::HostRead_U32(guard, gpr_address);
|
return PowerPC::MMU::HostRead_U32(guard, gpr_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard, u32 fpr) const
|
double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard, u32 fpr) const
|
||||||
|
@ -60,5 +60,5 @@ double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard,
|
||||||
return 0.0;
|
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::HostRead_F64(guard, fpr_address);
|
return PowerPC::MMU::HostRead_F64(guard, fpr_address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::HostRead_U8(guard, addr);
|
reinterpret_cast<u8*>(&obj)[i] = PowerPC::MMU::HostRead_U8(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::HostRead_U32(guard, m_stack);
|
value = PowerPC::MMU::HostRead_U32(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::HostRead_U64(guard, m_stack);
|
value = PowerPC::MMU::HostRead_U64(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::HostRead_F64(guard, m_stack);
|
value = PowerPC::MMU::HostRead_F64(guard, m_stack);
|
||||||
m_stack += 8;
|
m_stack += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,43 +84,43 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
||||||
{
|
{
|
||||||
bool IsValidAddress(const Core::CPUThreadGuard& guard, u32 address) const override
|
bool IsValidAddress(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostIsRAMAddress(guard, address);
|
return PowerPC::MMU::HostIsRAMAddress(guard, address);
|
||||||
}
|
}
|
||||||
u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override
|
u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U8(guard, address);
|
return PowerPC::MMU::HostRead_U8(guard, address);
|
||||||
}
|
}
|
||||||
void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override
|
void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, value, address);
|
PowerPC::MMU::HostWrite_U8(guard, value, address);
|
||||||
}
|
}
|
||||||
u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override
|
u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U16(guard, address);
|
return PowerPC::MMU::HostRead_U16(guard, address);
|
||||||
}
|
}
|
||||||
void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override
|
void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U16(guard, value, address);
|
PowerPC::MMU::HostWrite_U16(guard, value, address);
|
||||||
}
|
}
|
||||||
u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override
|
u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U32(guard, address);
|
return PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
}
|
}
|
||||||
void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override
|
void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U32(guard, value, address);
|
PowerPC::MMU::HostWrite_U32(guard, value, address);
|
||||||
}
|
}
|
||||||
u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override
|
u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U64(guard, address);
|
return PowerPC::MMU::HostRead_U64(guard, address);
|
||||||
}
|
}
|
||||||
void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override
|
void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U64(guard, value, address);
|
PowerPC::MMU::HostWrite_U64(guard, value, address);
|
||||||
}
|
}
|
||||||
float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override
|
float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_F32(guard, address);
|
return PowerPC::MMU::HostRead_F32(guard, address);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start,
|
bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start,
|
||||||
|
@ -128,16 +128,17 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
||||||
{
|
{
|
||||||
auto& system = guard.GetSystem();
|
auto& system = guard.GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
auto& mmu = system.GetMMU();
|
||||||
|
|
||||||
u32 page_base = haystack_start & 0xfffff000;
|
u32 page_base = haystack_start & 0xfffff000;
|
||||||
u32 offset = haystack_start & 0x0000fff;
|
u32 offset = haystack_start & 0x0000fff;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, page_base))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, page_base))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto page_physical_address = PowerPC::GetTranslatedAddress(page_base);
|
auto page_physical_address = mmu.GetTranslatedAddress(page_base);
|
||||||
if (!page_physical_address.has_value())
|
if (!page_physical_address.has_value())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -184,7 +185,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
||||||
const u32 haystack_offset_change = forward ? 1 : -1;
|
const u32 haystack_offset_change = forward ? 1 : -1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (PowerPC::HostIsRAMAddress(guard, haystack_address))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, haystack_address))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,8 +72,8 @@ 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::HostRead_U32(guard, value + offset);
|
value = PowerPC::MMU::HostRead_U32(guard, value + offset);
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, value))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, value))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -245,17 +245,22 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector<Pa
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
{
|
{
|
||||||
case PatchType::Patch8Bit:
|
case PatchType::Patch8Bit:
|
||||||
if (!entry.conditional || PowerPC::HostRead_U8(guard, addr) == static_cast<u8>(comparand))
|
if (!entry.conditional ||
|
||||||
PowerPC::HostWrite_U8(guard, static_cast<u8>(value), addr);
|
PowerPC::MMU::HostRead_U8(guard, addr) == static_cast<u8>(comparand))
|
||||||
|
{
|
||||||
|
PowerPC::MMU::HostWrite_U8(guard, static_cast<u8>(value), addr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PatchType::Patch16Bit:
|
case PatchType::Patch16Bit:
|
||||||
if (!entry.conditional ||
|
if (!entry.conditional ||
|
||||||
PowerPC::HostRead_U16(guard, addr) == static_cast<u16>(comparand))
|
PowerPC::MMU::HostRead_U16(guard, addr) == static_cast<u16>(comparand))
|
||||||
PowerPC::HostWrite_U16(guard, static_cast<u16>(value), addr);
|
{
|
||||||
|
PowerPC::MMU::HostWrite_U16(guard, static_cast<u16>(value), addr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PatchType::Patch32Bit:
|
case PatchType::Patch32Bit:
|
||||||
if (!entry.conditional || PowerPC::HostRead_U32(guard, addr) == comparand)
|
if (!entry.conditional || PowerPC::MMU::HostRead_U32(guard, addr) == comparand)
|
||||||
PowerPC::HostWrite_U32(guard, value, addr);
|
PowerPC::MMU::HostWrite_U32(guard, value, addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// unknown patchtype
|
// unknown patchtype
|
||||||
|
@ -288,19 +293,19 @@ static bool IsStackValid(const Core::CPUThreadGuard& guard)
|
||||||
|
|
||||||
// Check the stack pointer
|
// Check the stack pointer
|
||||||
u32 SP = ppc_state.gpr[1];
|
u32 SP = ppc_state.gpr[1];
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, SP))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, SP))
|
||||||
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
|
||||||
u32 next_SP = PowerPC::HostRead_U32(guard, SP);
|
u32 next_SP = PowerPC::MMU::HostRead_U32(guard, SP);
|
||||||
if (next_SP <= SP || !PowerPC::HostIsRAMAddress(guard, next_SP) ||
|
if (next_SP <= SP || !PowerPC::MMU::HostIsRAMAddress(guard, next_SP) ||
|
||||||
!PowerPC::HostIsRAMAddress(guard, next_SP + 4))
|
!PowerPC::MMU::HostIsRAMAddress(guard, next_SP + 4))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 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::HostRead_U32(guard, next_SP + 4);
|
const u32 address = PowerPC::MMU::HostRead_U32(guard, next_SP + 4);
|
||||||
return PowerPC::HostIsInstructionRAMAddress(guard, address) &&
|
return PowerPC::MMU::HostIsInstructionRAMAddress(guard, address) &&
|
||||||
0 != PowerPC::HostRead_Instruction(guard, address);
|
0 != PowerPC::MMU::HostRead_Instruction(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddMemoryPatch(std::size_t index)
|
void AddMemoryPatch(std::size_t index)
|
||||||
|
|
|
@ -280,7 +280,7 @@ void MemChecks::Add(TMemCheck memory_check)
|
||||||
// watchpoint-compatible code.
|
// watchpoint-compatible code.
|
||||||
if (!had_any)
|
if (!had_any)
|
||||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||||
PowerPC::DBATUpdated();
|
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ void MemChecks::Remove(u32 address)
|
||||||
m_mem_checks.erase(iter);
|
m_mem_checks.erase(iter);
|
||||||
if (!HasAny())
|
if (!HasAny())
|
||||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||||
PowerPC::DBATUpdated();
|
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ void MemChecks::Clear()
|
||||||
Core::RunAsCPUThread([&] {
|
Core::RunAsCPUThread([&] {
|
||||||
m_mem_checks.clear();
|
m_mem_checks.clear();
|
||||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||||
PowerPC::DBATUpdated();
|
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,49 +31,49 @@ static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address);
|
||||||
template <>
|
template <>
|
||||||
u8 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
u8 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U8(guard, address);
|
return PowerPC::MMU::HostRead_U8(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u16 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
u16 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U16(guard, address);
|
return PowerPC::MMU::HostRead_U16(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u32 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
u32 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U32(guard, address);
|
return PowerPC::MMU::HostRead_U32(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u64 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
u64 HostRead(const Core::CPUThreadGuard& guard, u32 address)
|
||||||
{
|
{
|
||||||
return PowerPC::HostRead_U64(guard, address);
|
return PowerPC::MMU::HostRead_U64(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void HostWrite(const Core::CPUThreadGuard& guard, u8 var, u32 address)
|
void HostWrite(const Core::CPUThreadGuard& guard, u8 var, u32 address)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U8(guard, var, address);
|
PowerPC::MMU::HostWrite_U8(guard, var, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void HostWrite(const Core::CPUThreadGuard& guard, u16 var, u32 address)
|
void HostWrite(const Core::CPUThreadGuard& guard, u16 var, u32 address)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U16(guard, var, address);
|
PowerPC::MMU::HostWrite_U16(guard, var, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void HostWrite(const Core::CPUThreadGuard& guard, u32 var, u32 address)
|
void HostWrite(const Core::CPUThreadGuard& guard, u32 var, u32 address)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U32(guard, var, address);
|
PowerPC::MMU::HostWrite_U32(guard, var, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void HostWrite(const Core::CPUThreadGuard& guard, u64 var, u32 address)
|
void HostWrite(const Core::CPUThreadGuard& guard, u64 var, u32 address)
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U64(guard, var, address);
|
PowerPC::MMU::HostWrite_U64(guard, var, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U = T>
|
template <typename T, typename U = T>
|
||||||
|
@ -146,7 +146,7 @@ static std::optional<std::string> ReadStringArg(const Core::CPUThreadGuard& guar
|
||||||
if (!std::isnan(num))
|
if (!std::isnan(num))
|
||||||
{
|
{
|
||||||
u32 address = static_cast<u32>(num);
|
u32 address = static_cast<u32>(num);
|
||||||
return PowerPC::HostGetString(guard, address);
|
return PowerPC::MMU::HostGetString(guard, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* cstr = expr_get_str(e);
|
const char* cstr = expr_get_str(e);
|
||||||
|
|
|
@ -821,7 +821,7 @@ static void ReadMemory(const Core::CPUThreadGuard& guard)
|
||||||
if (len * 2 > sizeof reply)
|
if (len * 2 > sizeof reply)
|
||||||
SendReply("E01");
|
SendReply("E01");
|
||||||
|
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, addr))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
|
||||||
return SendReply("E00");
|
return SendReply("E00");
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
|
@ -848,7 +848,7 @@ static void WriteMemory(const Core::CPUThreadGuard& guard)
|
||||||
len = (len << 4) | Hex2char(s_cmd_bfr[i++]);
|
len = (len << 4) | Hex2char(s_cmd_bfr[i++]);
|
||||||
INFO_LOG_FMT(GDB_STUB, "gdb: write memory: {:08x} bytes to {:08x}", len, addr);
|
INFO_LOG_FMT(GDB_STUB, "gdb: write memory: {:08x} bytes to {:08x}", len, addr);
|
||||||
|
|
||||||
if (!PowerPC::HostIsRAMAddress(guard, addr))
|
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
|
||||||
return SendReply("E00");
|
return SendReply("E00");
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
|
|
|
@ -64,8 +64,8 @@ void Interpreter::UpdatePC()
|
||||||
m_ppc_state.pc = m_ppc_state.npc;
|
m_ppc_state.pc = m_ppc_state.npc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state)
|
Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu)
|
||||||
: m_system(system), m_ppc_state(ppc_state)
|
: m_system(system), m_ppc_state(ppc_state), m_mmu(mmu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ int Interpreter::SingleStepInner()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction);
|
m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction);
|
||||||
m_prev_inst.hex = PowerPC::Read_Opcode(m_ppc_state.pc);
|
m_prev_inst.hex = m_mmu.Read_Opcode(m_ppc_state.pc);
|
||||||
|
|
||||||
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
|
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
|
||||||
|
|
||||||
|
@ -316,7 +316,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::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(system, guard, Common::Log::LogType::POWERPC,
|
Dolphin_Debugger::PrintCallstack(system, guard, Common::Log::LogType::POWERPC,
|
||||||
|
|
|
@ -15,13 +15,14 @@ class System;
|
||||||
}
|
}
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
|
class MMU;
|
||||||
struct PowerPCState;
|
struct PowerPCState;
|
||||||
}
|
} // namespace PowerPC
|
||||||
|
|
||||||
class Interpreter : public CPUCoreBase
|
class Interpreter : public CPUCoreBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state);
|
Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu);
|
||||||
Interpreter(const Interpreter&) = delete;
|
Interpreter(const Interpreter&) = delete;
|
||||||
Interpreter(Interpreter&&) = delete;
|
Interpreter(Interpreter&&) = delete;
|
||||||
Interpreter& operator=(const Interpreter&) = delete;
|
Interpreter& operator=(const Interpreter&) = delete;
|
||||||
|
@ -312,6 +313,7 @@ private:
|
||||||
|
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
PowerPC::PowerPCState& m_ppc_state;
|
PowerPC::PowerPCState& m_ppc_state;
|
||||||
|
PowerPC::MMU& m_mmu;
|
||||||
|
|
||||||
UGeckoInstruction m_prev_inst{};
|
UGeckoInstruction m_prev_inst{};
|
||||||
u32 m_last_pc = 0;
|
u32 m_last_pc = 0;
|
||||||
|
|
|
@ -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 = PowerPC::Read_U8(Helper_Get_EA(ppc_state, inst));
|
const u32 temp = interpreter.m_mmu.Read_U8(Helper_Get_EA(ppc_state, inst));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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 = PowerPC::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(PowerPC::Read_U16(Helper_Get_EA(ppc_state, inst)))));
|
const u32 temp = u32(s32(s16(interpreter.m_mmu.Read_U16(Helper_Get_EA(ppc_state, inst)))));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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(PowerPC::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 = PowerPC::Read_U16(Helper_Get_EA(ppc_state, inst));
|
const u32 temp = interpreter.m_mmu.Read_U16(Helper_Get_EA(ppc_state, inst));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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 = PowerPC::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 = PowerPC::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)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U32(ppc_state.gpr[i], address);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[i], address);
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
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 = PowerPC::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 = PowerPC::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;
|
||||||
PowerPC::Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stbu(Interpreter& interpreter, UGeckoInstruction inst)
|
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);
|
||||||
|
|
||||||
PowerPC::Write_U8(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -385,7 +385,7 @@ void Interpreter::stfdu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -417,7 +417,7 @@ void Interpreter::stfsu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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;
|
||||||
PowerPC::Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sthu(Interpreter& interpreter, UGeckoInstruction inst)
|
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);
|
||||||
|
|
||||||
PowerPC::Write_U16(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
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;
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], Helper_Get_EA(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stwu(Interpreter& interpreter, UGeckoInstruction inst)
|
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);
|
||||||
|
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -478,7 +478,7 @@ void Interpreter::dcbf(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::FlushDCacheLine(address);
|
interpreter.m_mmu.FlushDCacheLine(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dcbi(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::dcbi(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -500,7 +500,7 @@ void Interpreter::dcbi(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::InvalidateDCacheLine(address);
|
interpreter.m_mmu.InvalidateDCacheLine(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dcbst(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::dcbst(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -516,7 +516,7 @@ void Interpreter::dcbst(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::StoreDCacheLine(address);
|
interpreter.m_mmu.StoreDCacheLine(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These instructions hint that it might be optimal to prefetch the specified cache line into the
|
// These instructions hint that it might be optimal to prefetch the specified cache line into the
|
||||||
|
@ -553,7 +553,7 @@ void Interpreter::dcbz(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::ClearDCacheLine(dcbz_addr & (~31));
|
interpreter.m_mmu.ClearDCacheLine(dcbz_addr & (~31));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dcbz_l(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::dcbz_l(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -573,7 +573,7 @@ void Interpreter::dcbz_l(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::ClearDCacheLine(address & (~31));
|
interpreter.m_mmu.ClearDCacheLine(address & (~31));
|
||||||
}
|
}
|
||||||
|
|
||||||
// eciwx/ecowx technically should access the specified device
|
// eciwx/ecowx technically should access the specified device
|
||||||
|
@ -595,7 +595,7 @@ void Interpreter::eciwx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppc_state.gpr[inst.RD] = PowerPC::Read_U32(EA);
|
ppc_state.gpr[inst.RD] = interpreter.m_mmu.Read_U32(EA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -615,7 +615,7 @@ void Interpreter::ecowx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], EA);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], EA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::eieio(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::eieio(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -638,7 +638,7 @@ void Interpreter::lbzux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
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 = PowerPC::Read_U8(address);
|
const u32 temp = interpreter.m_mmu.Read_U8(address);
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -650,7 +650,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 = PowerPC::Read_U8(Helper_Get_EA_X(ppc_state, inst));
|
const u32 temp = interpreter.m_mmu.Read_U8(Helper_Get_EA_X(ppc_state, inst));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -662,7 +662,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(PowerPC::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))
|
||||||
{
|
{
|
||||||
|
@ -674,7 +674,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(PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst)))};
|
const s32 temp = s32{s16(interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst)))};
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -685,7 +685,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(PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst)));
|
const u32 temp = Common::swap16(interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst)));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -697,7 +697,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 = PowerPC::Read_U16(address);
|
const u32 temp = interpreter.m_mmu.Read_U16(address);
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -709,7 +709,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 = PowerPC::Read_U16(Helper_Get_EA_X(ppc_state, inst));
|
const u32 temp = interpreter.m_mmu.Read_U16(Helper_Get_EA_X(ppc_state, inst));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -738,7 +738,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 = PowerPC::Read_U8(EA) << (24 - offset);
|
const u32 temp_value = interpreter.m_mmu.Read_U8(EA) << (24 - offset);
|
||||||
// Not64 (Homebrew N64 Emulator for Wii) triggers the following case.
|
// Not64 (Homebrew N64 Emulator for Wii) triggers the following case.
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
@ -754,7 +754,7 @@ void Interpreter::lswx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
void Interpreter::lwbrx(Interpreter& interpreter, UGeckoInstruction inst)
|
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(PowerPC::Read_U32(Helper_Get_EA_X(ppc_state, inst)));
|
const u32 temp = Common::swap32(interpreter.m_mmu.Read_U32(Helper_Get_EA_X(ppc_state, inst)));
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -766,7 +766,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 = PowerPC::Read_U32(address);
|
const u32 temp = interpreter.m_mmu.Read_U32(address);
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -779,7 +779,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 = PowerPC::Read_U32(address);
|
const u32 temp = interpreter.m_mmu.Read_U32(address);
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -792,7 +792,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);
|
||||||
|
|
||||||
PowerPC::Write_U8(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -802,7 +802,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;
|
||||||
PowerPC::Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
interpreter.m_mmu.Write_U8(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -816,7 +816,7 @@ void Interpreter::stfdux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -834,7 +834,7 @@ void Interpreter::stfdx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
interpreter.m_mmu.Write_U64(ppc_state.ps[inst.FS].PS0AsU64(), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores Floating points into Integers indeXed
|
// Stores Floating points into Integers indeXed
|
||||||
|
@ -849,7 +849,7 @@ void Interpreter::stfiwx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ppc_state.ps[inst.FS].PS0AsU32(), address);
|
interpreter.m_mmu.Write_U32(ppc_state.ps[inst.FS].PS0AsU32(), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -863,7 +863,7 @@ void Interpreter::stfsux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -881,13 +881,13 @@ void Interpreter::stfsx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
interpreter.m_mmu.Write_U32(ConvertToSingle(ppc_state.ps[inst.FS].PS0AsU64()), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sthbrx(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::sthbrx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
auto& ppc_state = interpreter.m_ppc_state;
|
||||||
PowerPC::Write_U16_Swap(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
interpreter.m_mmu.Write_U16_Swap(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -895,7 +895,7 @@ void Interpreter::sthux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
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);
|
||||||
|
|
||||||
PowerPC::Write_U16(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -905,7 +905,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;
|
||||||
PowerPC::Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
interpreter.m_mmu.Write_U16(ppc_state.gpr[inst.RS], Helper_Get_EA_X(ppc_state, inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
// lswi - bizarro string instruction
|
// lswi - bizarro string instruction
|
||||||
|
@ -938,7 +938,7 @@ void Interpreter::lswi(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
ppc_state.gpr[r] = 0;
|
ppc_state.gpr[r] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 temp_value = PowerPC::Read_U8(EA) << (24 - i);
|
const u32 temp_value = interpreter.m_mmu.Read_U8(EA) << (24 - i);
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
PanicAlertFmt("DSI exception in lsw.");
|
PanicAlertFmt("DSI exception in lsw.");
|
||||||
|
@ -984,7 +984,7 @@ void Interpreter::stswi(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
r++;
|
r++;
|
||||||
r &= 31;
|
r &= 31;
|
||||||
}
|
}
|
||||||
PowerPC::Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA);
|
interpreter.m_mmu.Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA);
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1016,7 +1016,7 @@ void Interpreter::stswx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
|
||||||
while (n > 0)
|
while (n > 0)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA);
|
interpreter.m_mmu.Write_U8((ppc_state.gpr[r] >> (24 - i)) & 0xFF, EA);
|
||||||
|
|
||||||
EA++;
|
EA++;
|
||||||
n--;
|
n--;
|
||||||
|
@ -1034,7 +1034,7 @@ void Interpreter::stwbrx(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);
|
||||||
|
|
||||||
PowerPC::Write_U32_Swap(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U32_Swap(ppc_state.gpr[inst.RS], address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following two instructions are for SMP communications. On a single
|
// The following two instructions are for SMP communications. On a single
|
||||||
|
@ -1051,7 +1051,7 @@ void Interpreter::lwarx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 temp = PowerPC::Read_U32(address);
|
const u32 temp = interpreter.m_mmu.Read_U32(address);
|
||||||
|
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
|
@ -1077,7 +1077,7 @@ void Interpreter::stwcxd(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (address == ppc_state.reserve_address)
|
if (address == ppc_state.reserve_address)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.reserve = false;
|
ppc_state.reserve = false;
|
||||||
|
@ -1095,7 +1095,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);
|
||||||
|
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address);
|
||||||
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
if (!(ppc_state.Exceptions & EXCEPTION_DSI))
|
||||||
{
|
{
|
||||||
ppc_state.gpr[inst.RA] = address;
|
ppc_state.gpr[inst.RA] = address;
|
||||||
|
@ -1107,7 +1107,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);
|
||||||
|
|
||||||
PowerPC::Write_U32(ppc_state.gpr[inst.RS], address);
|
interpreter.m_mmu.Write_U32(ppc_state.gpr[inst.RS], address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sync(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::sync(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -1127,7 +1127,7 @@ void Interpreter::tlbie(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
// Invalidate TLB entry
|
// Invalidate TLB entry
|
||||||
const u32 address = ppc_state.gpr[inst.RB];
|
const u32 address = ppc_state.gpr[inst.RB];
|
||||||
|
|
||||||
PowerPC::InvalidateTLBEntry(address);
|
interpreter.m_mmu.InvalidateTLBEntry(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::tlbsync(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::tlbsync(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
// dequantize table
|
// dequantize table
|
||||||
const float m_dequantizeTable[] = {
|
const float m_dequantizeTable[] = {
|
||||||
|
@ -68,111 +69,111 @@ SType ScaleAndClamp(double ps, u32 st_scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static T ReadUnpaired(u32 addr);
|
static T ReadUnpaired(PowerPC::MMU& mmu, u32 addr);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u8 ReadUnpaired<u8>(u32 addr)
|
u8 ReadUnpaired<u8>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
return PowerPC::Read_U8(addr);
|
return mmu.Read_U8(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u16 ReadUnpaired<u16>(u32 addr)
|
u16 ReadUnpaired<u16>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
return PowerPC::Read_U16(addr);
|
return mmu.Read_U16(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
u32 ReadUnpaired<u32>(u32 addr)
|
u32 ReadUnpaired<u32>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
return PowerPC::Read_U32(addr);
|
return mmu.Read_U32(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::pair<T, T> ReadPair(u32 addr);
|
static std::pair<T, T> ReadPair(PowerPC::MMU& mmu, u32 addr);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::pair<u8, u8> ReadPair<u8>(u32 addr)
|
std::pair<u8, u8> ReadPair<u8>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
const u16 val = PowerPC::Read_U16(addr);
|
const u16 val = mmu.Read_U16(addr);
|
||||||
return {u8(val >> 8), u8(val)};
|
return {u8(val >> 8), u8(val)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::pair<u16, u16> ReadPair<u16>(u32 addr)
|
std::pair<u16, u16> ReadPair<u16>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
const u32 val = PowerPC::Read_U32(addr);
|
const u32 val = mmu.Read_U32(addr);
|
||||||
return {u16(val >> 16), u16(val)};
|
return {u16(val >> 16), u16(val)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::pair<u32, u32> ReadPair<u32>(u32 addr)
|
std::pair<u32, u32> ReadPair<u32>(PowerPC::MMU& mmu, u32 addr)
|
||||||
{
|
{
|
||||||
const u64 val = PowerPC::Read_U64(addr);
|
const u64 val = mmu.Read_U64(addr);
|
||||||
return {u32(val >> 32), u32(val)};
|
return {u32(val >> 32), u32(val)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void WriteUnpaired(T val, u32 addr);
|
static void WriteUnpaired(PowerPC::MMU& mmu, T val, u32 addr);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WriteUnpaired<u8>(u8 val, u32 addr)
|
void WriteUnpaired<u8>(PowerPC::MMU& mmu, u8 val, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U8(val, addr);
|
mmu.Write_U8(val, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WriteUnpaired<u16>(u16 val, u32 addr)
|
void WriteUnpaired<u16>(PowerPC::MMU& mmu, u16 val, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U16(val, addr);
|
mmu.Write_U16(val, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WriteUnpaired<u32>(u32 val, u32 addr)
|
void WriteUnpaired<u32>(PowerPC::MMU& mmu, u32 val, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U32(val, addr);
|
mmu.Write_U32(val, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void WritePair(T val1, T val2, u32 addr);
|
static void WritePair(PowerPC::MMU& mmu, T val1, T val2, u32 addr);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WritePair<u8>(u8 val1, u8 val2, u32 addr)
|
void WritePair<u8>(PowerPC::MMU& mmu, u8 val1, u8 val2, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U16((u16{val1} << 8) | u16{val2}, addr);
|
mmu.Write_U16((u16{val1} << 8) | u16{val2}, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WritePair<u16>(u16 val1, u16 val2, u32 addr)
|
void WritePair<u16>(PowerPC::MMU& mmu, u16 val1, u16 val2, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U32((u32{val1} << 16) | u32{val2}, addr);
|
mmu.Write_U32((u32{val1} << 16) | u32{val2}, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void WritePair<u32>(u32 val1, u32 val2, u32 addr)
|
void WritePair<u32>(PowerPC::MMU& mmu, u32 val1, u32 val2, u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::Write_U64((u64{val1} << 32) | u64{val2}, addr);
|
mmu.Write_U64((u64{val1} << 32) | u64{val2}, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void QuantizeAndStore(double ps0, double ps1, u32 addr, u32 instW, u32 st_scale)
|
void QuantizeAndStore(PowerPC::MMU& mmu, double ps0, double ps1, u32 addr, u32 instW, u32 st_scale)
|
||||||
{
|
{
|
||||||
using U = std::make_unsigned_t<T>;
|
using U = std::make_unsigned_t<T>;
|
||||||
|
|
||||||
const U conv_ps0 = U(ScaleAndClamp<T>(ps0, st_scale));
|
const U conv_ps0 = U(ScaleAndClamp<T>(ps0, st_scale));
|
||||||
if (instW)
|
if (instW)
|
||||||
{
|
{
|
||||||
WriteUnpaired<U>(conv_ps0, addr);
|
WriteUnpaired<U>(mmu, conv_ps0, addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const U conv_ps1 = U(ScaleAndClamp<T>(ps1, st_scale));
|
const U conv_ps1 = U(ScaleAndClamp<T>(ps1, st_scale));
|
||||||
WritePair<U>(conv_ps0, conv_ps1, addr);
|
WritePair<U>(mmu, conv_ps0, conv_ps1, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRS,
|
static void Helper_Quantize(PowerPC::MMU& mmu, const PowerPC::PowerPCState* ppcs, u32 addr,
|
||||||
u32 instW)
|
u32 instI, u32 instRS, u32 instW)
|
||||||
{
|
{
|
||||||
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
|
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
|
||||||
const EQuantizeType st_type = gqr.st_type;
|
const EQuantizeType st_type = gqr.st_type;
|
||||||
|
@ -190,32 +191,32 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
|
||||||
|
|
||||||
if (instW != 0)
|
if (instW != 0)
|
||||||
{
|
{
|
||||||
WriteUnpaired<u32>(conv_ps0, addr);
|
WriteUnpaired<u32>(mmu, conv_ps0, addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u64 integral_ps1 = Common::BitCast<u64>(ps1);
|
const u64 integral_ps1 = Common::BitCast<u64>(ps1);
|
||||||
const u32 conv_ps1 = ConvertToSingleFTZ(integral_ps1);
|
const u32 conv_ps1 = ConvertToSingleFTZ(integral_ps1);
|
||||||
|
|
||||||
WritePair<u32>(conv_ps0, conv_ps1, addr);
|
WritePair<u32>(mmu, conv_ps0, conv_ps1, addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case QUANTIZE_U8:
|
case QUANTIZE_U8:
|
||||||
QuantizeAndStore<u8>(ps0, ps1, addr, instW, st_scale);
|
QuantizeAndStore<u8>(mmu, ps0, ps1, addr, instW, st_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_U16:
|
case QUANTIZE_U16:
|
||||||
QuantizeAndStore<u16>(ps0, ps1, addr, instW, st_scale);
|
QuantizeAndStore<u16>(mmu, ps0, ps1, addr, instW, st_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_S8:
|
case QUANTIZE_S8:
|
||||||
QuantizeAndStore<s8>(ps0, ps1, addr, instW, st_scale);
|
QuantizeAndStore<s8>(mmu, ps0, ps1, addr, instW, st_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_S16:
|
case QUANTIZE_S16:
|
||||||
QuantizeAndStore<s16>(ps0, ps1, addr, instW, st_scale);
|
QuantizeAndStore<s16>(mmu, ps0, ps1, addr, instW, st_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_INVALID1:
|
case QUANTIZE_INVALID1:
|
||||||
|
@ -227,20 +228,20 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::pair<double, double> LoadAndDequantize(u32 addr, u32 instW, u32 ld_scale)
|
std::pair<double, double> LoadAndDequantize(PowerPC::MMU& mmu, u32 addr, u32 instW, u32 ld_scale)
|
||||||
{
|
{
|
||||||
using U = std::make_unsigned_t<T>;
|
using U = std::make_unsigned_t<T>;
|
||||||
|
|
||||||
float ps0, ps1;
|
float ps0, ps1;
|
||||||
if (instW != 0)
|
if (instW != 0)
|
||||||
{
|
{
|
||||||
const U value = ReadUnpaired<U>(addr);
|
const U value = ReadUnpaired<U>(mmu, addr);
|
||||||
ps0 = float(T(value)) * m_dequantizeTable[ld_scale];
|
ps0 = float(T(value)) * m_dequantizeTable[ld_scale];
|
||||||
ps1 = 1.0f;
|
ps1 = 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto [first, second] = ReadPair<U>(addr);
|
const auto [first, second] = ReadPair<U>(mmu, addr);
|
||||||
ps0 = float(T(first)) * m_dequantizeTable[ld_scale];
|
ps0 = float(T(first)) * m_dequantizeTable[ld_scale];
|
||||||
ps1 = float(T(second)) * m_dequantizeTable[ld_scale];
|
ps1 = float(T(second)) * m_dequantizeTable[ld_scale];
|
||||||
}
|
}
|
||||||
|
@ -248,8 +249,8 @@ std::pair<double, double> LoadAndDequantize(u32 addr, u32 instW, u32 ld_scale)
|
||||||
return {static_cast<double>(ps0), static_cast<double>(ps1)};
|
return {static_cast<double>(ps0), static_cast<double>(ps1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRD,
|
static void Helper_Dequantize(PowerPC::MMU& mmu, PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
|
||||||
u32 instW)
|
u32 instRD, u32 instW)
|
||||||
{
|
{
|
||||||
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
|
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
|
||||||
const EQuantizeType ld_type = gqr.ld_type;
|
const EQuantizeType ld_type = gqr.ld_type;
|
||||||
|
@ -263,32 +264,32 @@ static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
|
||||||
case QUANTIZE_FLOAT:
|
case QUANTIZE_FLOAT:
|
||||||
if (instW != 0)
|
if (instW != 0)
|
||||||
{
|
{
|
||||||
const u32 value = ReadUnpaired<u32>(addr);
|
const u32 value = ReadUnpaired<u32>(mmu, addr);
|
||||||
ps0 = Common::BitCast<double>(ConvertToDouble(value));
|
ps0 = Common::BitCast<double>(ConvertToDouble(value));
|
||||||
ps1 = 1.0;
|
ps1 = 1.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto [first, second] = ReadPair<u32>(addr);
|
const auto [first, second] = ReadPair<u32>(mmu, addr);
|
||||||
ps0 = Common::BitCast<double>(ConvertToDouble(first));
|
ps0 = Common::BitCast<double>(ConvertToDouble(first));
|
||||||
ps1 = Common::BitCast<double>(ConvertToDouble(second));
|
ps1 = Common::BitCast<double>(ConvertToDouble(second));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_U8:
|
case QUANTIZE_U8:
|
||||||
std::tie(ps0, ps1) = LoadAndDequantize<u8>(addr, instW, ld_scale);
|
std::tie(ps0, ps1) = LoadAndDequantize<u8>(mmu, addr, instW, ld_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_U16:
|
case QUANTIZE_U16:
|
||||||
std::tie(ps0, ps1) = LoadAndDequantize<u16>(addr, instW, ld_scale);
|
std::tie(ps0, ps1) = LoadAndDequantize<u16>(mmu, addr, instW, ld_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_S8:
|
case QUANTIZE_S8:
|
||||||
std::tie(ps0, ps1) = LoadAndDequantize<s8>(addr, instW, ld_scale);
|
std::tie(ps0, ps1) = LoadAndDequantize<s8>(mmu, addr, instW, ld_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_S16:
|
case QUANTIZE_S16:
|
||||||
std::tie(ps0, ps1) = LoadAndDequantize<s16>(addr, instW, ld_scale);
|
std::tie(ps0, ps1) = LoadAndDequantize<s16>(mmu, addr, instW, ld_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUANTIZE_INVALID1:
|
case QUANTIZE_INVALID1:
|
||||||
|
@ -318,7 +319,7 @@ void Interpreter::psq_l(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
|
const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
|
||||||
Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W);
|
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -331,7 +332,7 @@ void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
|
const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
|
||||||
Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W);
|
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W);
|
||||||
|
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +352,7 @@ void Interpreter::psq_st(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
|
const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
|
||||||
Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W);
|
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -364,7 +365,7 @@ void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
|
const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
|
||||||
Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W);
|
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W);
|
||||||
|
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +380,7 @@ void Interpreter::psq_lx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
auto& ppc_state = interpreter.m_ppc_state;
|
||||||
const u32 EA =
|
const u32 EA =
|
||||||
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
|
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
|
||||||
Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
|
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
@ -387,14 +388,14 @@ void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
auto& ppc_state = interpreter.m_ppc_state;
|
||||||
const u32 EA =
|
const u32 EA =
|
||||||
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
|
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
|
||||||
Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
|
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::psq_lux(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::psq_lux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
auto& ppc_state = interpreter.m_ppc_state;
|
||||||
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
|
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
|
||||||
Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
|
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
|
||||||
|
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
@ -408,7 +409,7 @@ void Interpreter::psq_stux(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
auto& ppc_state = interpreter.m_ppc_state;
|
auto& ppc_state = interpreter.m_ppc_state;
|
||||||
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
|
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
|
||||||
Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
|
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
|
||||||
|
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -379,8 +379,8 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
if (old_value != ppc_state.spr[index])
|
if (old_value != ppc_state.spr[index])
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(POWERPC, "HID4 updated {:x} {:x}", old_value, ppc_state.spr[index]);
|
INFO_LOG_FMT(POWERPC, "HID4 updated {:x} {:x}", old_value, ppc_state.spr[index]);
|
||||||
PowerPC::IBATUpdated();
|
interpreter.m_mmu.IBATUpdated();
|
||||||
PowerPC::DBATUpdated();
|
interpreter.m_mmu.DBATUpdated();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -414,9 +414,9 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
length = 128;
|
length = 128;
|
||||||
if (DMAL(ppc_state).DMA_LD)
|
if (DMAL(ppc_state).DMA_LD)
|
||||||
PowerPC::DMA_MemoryToLC(cache_address, mem_address, length);
|
interpreter.m_mmu.DMA_MemoryToLC(cache_address, mem_address, length);
|
||||||
else
|
else
|
||||||
PowerPC::DMA_LCToMemory(mem_address, cache_address, length);
|
interpreter.m_mmu.DMA_LCToMemory(mem_address, cache_address, length);
|
||||||
}
|
}
|
||||||
DMAL(ppc_state).DMA_T = 0;
|
DMAL(ppc_state).DMA_T = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -436,7 +436,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
|
|
||||||
// Page table base etc
|
// Page table base etc
|
||||||
case SPR_SDR:
|
case SPR_SDR:
|
||||||
PowerPC::SDRUpdated();
|
interpreter.m_mmu.SDRUpdated();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPR_XER:
|
case SPR_XER:
|
||||||
|
@ -462,7 +462,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
if (old_value != ppc_state.spr[index])
|
if (old_value != ppc_state.spr[index])
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(POWERPC, "DBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
|
INFO_LOG_FMT(POWERPC, "DBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
|
||||||
PowerPC::DBATUpdated();
|
interpreter.m_mmu.DBATUpdated();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
if (old_value != ppc_state.spr[index])
|
if (old_value != ppc_state.spr[index])
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(POWERPC, "IBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
|
INFO_LOG_FMT(POWERPC, "IBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
|
||||||
PowerPC::IBATUpdated();
|
interpreter.m_mmu.IBATUpdated();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1183,8 +1183,8 @@ void Jit64::IntializeSpeculativeConstants()
|
||||||
for (auto i : code_block.m_gpr_inputs)
|
for (auto i : code_block.m_gpr_inputs)
|
||||||
{
|
{
|
||||||
u32 compileTimeValue = m_ppc_state.gpr[i];
|
u32 compileTimeValue = m_ppc_state.gpr[i];
|
||||||
if (PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue) ||
|
if (m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue) ||
|
||||||
PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) ||
|
m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) ||
|
||||||
compileTimeValue == 0xCC000000)
|
compileTimeValue == 0xCC000000)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
|
|
|
@ -324,7 +324,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
|
||||||
if (m_ppc_state.msr.IR)
|
if (m_ppc_state.msr.IR)
|
||||||
{
|
{
|
||||||
// Translate effective address to physical address.
|
// Translate effective address to physical address.
|
||||||
bat_lookup_failed = BATAddressLookup(addr, tmp, PowerPC::ibat_table.data());
|
bat_lookup_failed = BATAddressLookup(addr, tmp, m_jit.m_mmu.GetIBATTable().data());
|
||||||
MOV(32, R(tmp), R(effective_address));
|
MOV(32, R(tmp), R(effective_address));
|
||||||
AND(32, R(tmp), Imm32(0x0001ffff));
|
AND(32, R(tmp), Imm32(0x0001ffff));
|
||||||
AND(32, R(addr), Imm32(0xfffe0000));
|
AND(32, R(addr), Imm32(0xfffe0000));
|
||||||
|
@ -430,7 +430,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||||
if (emit_fast_path)
|
if (emit_fast_path)
|
||||||
{
|
{
|
||||||
// Perform lookup to see if we can use fast path.
|
// Perform lookup to see if we can use fast path.
|
||||||
MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0]));
|
MOV(64, R(RSCRATCH2), ImmPtr(m_mmu.GetDBATTable().data()));
|
||||||
PUSH(RSCRATCH);
|
PUSH(RSCRATCH);
|
||||||
SHR(32, R(RSCRATCH), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
SHR(32, R(RSCRATCH), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||||
TEST(32, MComplex(RSCRATCH2, RSCRATCH, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
TEST(32, MComplex(RSCRATCH2, RSCRATCH, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
||||||
|
@ -449,7 +449,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||||
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
|
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
|
||||||
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
||||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||||
ABI_CallFunctionR(PowerPC::ClearDCacheLine, RSCRATCH);
|
ABI_CallFunctionPR(PowerPC::ClearDCacheLineFromJit64, &m_mmu, RSCRATCH);
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
|
||||||
if (emit_fast_path)
|
if (emit_fast_path)
|
||||||
|
|
|
@ -119,7 +119,7 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_
|
||||||
MOV(32, R(RSCRATCH_EXTRA), R(reg_addr));
|
MOV(32, R(RSCRATCH_EXTRA), R(reg_addr));
|
||||||
|
|
||||||
// Perform lookup to see if we can use fast path.
|
// Perform lookup to see if we can use fast path.
|
||||||
MOV(64, R(RSCRATCH), ImmPtr(&PowerPC::dbat_table[0]));
|
MOV(64, R(RSCRATCH), ImmPtr(m_jit.m_mmu.GetDBATTable().data()));
|
||||||
SHR(32, R(RSCRATCH_EXTRA), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
SHR(32, R(RSCRATCH_EXTRA), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||||
TEST(32, MComplex(RSCRATCH, RSCRATCH_EXTRA, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
TEST(32, MComplex(RSCRATCH, RSCRATCH_EXTRA, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
||||||
|
|
||||||
|
@ -396,16 +396,16 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
||||||
switch (accessSize)
|
switch (accessSize)
|
||||||
{
|
{
|
||||||
case 64:
|
case 64:
|
||||||
ABI_CallFunctionR(PowerPC::Read_U64, reg_addr);
|
ABI_CallFunctionPR(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
ABI_CallFunctionR(PowerPC::Read_U32, reg_addr);
|
ABI_CallFunctionPR(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
ABI_CallFunctionR(PowerPC::Read_U16_ZX, reg_addr);
|
ABI_CallFunctionPR(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
ABI_CallFunctionR(PowerPC::Read_U8_ZX, reg_addr);
|
ABI_CallFunctionPR(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, reg_addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
||||||
|
@ -436,14 +436,14 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
|
||||||
BitSet32 registersInUse, bool signExtend)
|
BitSet32 registersInUse, bool signExtend)
|
||||||
{
|
{
|
||||||
// If the address is known to be RAM, just load it directly.
|
// If the address is known to be RAM, just load it directly.
|
||||||
if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address))
|
if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address))
|
||||||
{
|
{
|
||||||
UnsafeLoadToReg(reg_value, Imm32(address), accessSize, 0, signExtend);
|
UnsafeLoadToReg(reg_value, Imm32(address), accessSize, 0, signExtend);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the address maps to an MMIO register, inline MMIO read code.
|
// If the address maps to an MMIO register, inline MMIO read code.
|
||||||
u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize);
|
u32 mmioAddress = m_jit.m_mmu.IsOptimizableMMIOAccess(address, accessSize);
|
||||||
if (accessSize != 64 && mmioAddress)
|
if (accessSize != 64 && mmioAddress)
|
||||||
{
|
{
|
||||||
auto& memory = m_jit.m_system.GetMemory();
|
auto& memory = m_jit.m_system.GetMemory();
|
||||||
|
@ -460,16 +460,16 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
|
||||||
switch (accessSize)
|
switch (accessSize)
|
||||||
{
|
{
|
||||||
case 64:
|
case 64:
|
||||||
ABI_CallFunctionC(PowerPC::Read_U64, address);
|
ABI_CallFunctionPC(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, address);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
ABI_CallFunctionC(PowerPC::Read_U32, address);
|
ABI_CallFunctionPC(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, address);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
ABI_CallFunctionC(PowerPC::Read_U16_ZX, address);
|
ABI_CallFunctionPC(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, address);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
ABI_CallFunctionC(PowerPC::Read_U8_ZX, address);
|
ABI_CallFunctionPC(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
@ -578,16 +578,19 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||||
switch (accessSize)
|
switch (accessSize)
|
||||||
{
|
{
|
||||||
case 64:
|
case 64:
|
||||||
ABI_CallFunctionRR(swap ? PowerPC::Write_U64 : PowerPC::Write_U64_Swap, reg, reg_addr);
|
ABI_CallFunctionPRR(swap ? PowerPC::WriteU64FromJit64 : PowerPC::WriteU64SwapFromJit64,
|
||||||
|
&m_jit.m_mmu, reg, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
ABI_CallFunctionRR(swap ? PowerPC::Write_U32 : PowerPC::Write_U32_Swap, reg, reg_addr);
|
ABI_CallFunctionPRR(swap ? PowerPC::WriteU32FromJit64 : PowerPC::WriteU32SwapFromJit64,
|
||||||
|
&m_jit.m_mmu, reg, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
ABI_CallFunctionRR(swap ? PowerPC::Write_U16 : PowerPC::Write_U16_Swap, reg, reg_addr);
|
ABI_CallFunctionPRR(swap ? PowerPC::WriteU16FromJit64 : PowerPC::WriteU16SwapFromJit64,
|
||||||
|
&m_jit.m_mmu, reg, reg_addr);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
ABI_CallFunctionRR(PowerPC::Write_U8, reg, reg_addr);
|
ABI_CallFunctionPRR(PowerPC::WriteU8FromJit64, &m_jit.m_mmu, reg, reg_addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
||||||
|
@ -623,7 +626,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
|
||||||
|
|
||||||
// If we already know the address through constant folding, we can do some
|
// If we already know the address through constant folding, we can do some
|
||||||
// fun tricks...
|
// fun tricks...
|
||||||
if (m_jit.jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(address))
|
if (m_jit.jo.optimizeGatherPipe && m_jit.m_mmu.IsOptimizableGatherPipeWrite(address))
|
||||||
{
|
{
|
||||||
X64Reg arg_reg = RSCRATCH;
|
X64Reg arg_reg = RSCRATCH;
|
||||||
|
|
||||||
|
@ -643,7 +646,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
|
||||||
m_jit.js.fifoBytesSinceCheck += accessSize >> 3;
|
m_jit.js.fifoBytesSinceCheck += accessSize >> 3;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address))
|
else if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address))
|
||||||
{
|
{
|
||||||
WriteToConstRamAddress(accessSize, arg, address);
|
WriteToConstRamAddress(accessSize, arg, address);
|
||||||
return false;
|
return false;
|
||||||
|
@ -657,16 +660,16 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
|
||||||
switch (accessSize)
|
switch (accessSize)
|
||||||
{
|
{
|
||||||
case 64:
|
case 64:
|
||||||
ABI_CallFunctionAC(64, PowerPC::Write_U64, arg, address);
|
ABI_CallFunctionPAC(64, PowerPC::WriteU64FromJit64, &m_jit.m_mmu, arg, address);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
ABI_CallFunctionAC(32, PowerPC::Write_U32, arg, address);
|
ABI_CallFunctionPAC(32, PowerPC::WriteU32FromJit64, &m_jit.m_mmu, arg, address);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
ABI_CallFunctionAC(16, PowerPC::Write_U16, arg, address);
|
ABI_CallFunctionPAC(16, PowerPC::WriteU16FromJit64, &m_jit.m_mmu, arg, address);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
ABI_CallFunctionAC(8, PowerPC::Write_U8, arg, address);
|
ABI_CallFunctionPAC(8, PowerPC::WriteU8FromJit64, &m_jit.m_mmu, arg, address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
|
|
@ -317,8 +317,8 @@ void JitArm64::IntializeSpeculativeConstants()
|
||||||
for (auto i : code_block.m_gpr_inputs)
|
for (auto i : code_block.m_gpr_inputs)
|
||||||
{
|
{
|
||||||
u32 compile_time_value = m_ppc_state.gpr[i];
|
u32 compile_time_value = m_ppc_state.gpr[i];
|
||||||
if (PowerPC::IsOptimizableGatherPipeWrite(compile_time_value) ||
|
if (m_mmu.IsOptimizableGatherPipeWrite(compile_time_value) ||
|
||||||
PowerPC::IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) ||
|
m_mmu.IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) ||
|
||||||
compile_time_value == 0xCC000000)
|
compile_time_value == 0xCC000000)
|
||||||
{
|
{
|
||||||
if (!fail)
|
if (!fail)
|
||||||
|
|
|
@ -216,32 +216,48 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
|
||||||
|
|
||||||
const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0;
|
const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0;
|
||||||
|
|
||||||
|
MOVP2R(ARM64Reg::X2, &m_mmu);
|
||||||
|
|
||||||
if (access_size == 64)
|
if (access_size == 64)
|
||||||
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U64_Swap : &PowerPC::Write_U64);
|
{
|
||||||
|
MOVP2R(ARM64Reg::X8,
|
||||||
|
reverse ? &PowerPC::WriteU64SwapFromJitArm64 : &PowerPC::WriteU64FromJitArm64);
|
||||||
|
}
|
||||||
else if (access_size == 32)
|
else if (access_size == 32)
|
||||||
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U32_Swap : &PowerPC::Write_U32);
|
{
|
||||||
|
MOVP2R(ARM64Reg::X8,
|
||||||
|
reverse ? &PowerPC::WriteU32SwapFromJitArm64 : &PowerPC::WriteU32FromJitArm64);
|
||||||
|
}
|
||||||
else if (access_size == 16)
|
else if (access_size == 16)
|
||||||
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U16_Swap : &PowerPC::Write_U16);
|
{
|
||||||
|
MOVP2R(ARM64Reg::X8,
|
||||||
|
reverse ? &PowerPC::WriteU16SwapFromJitArm64 : &PowerPC::WriteU16FromJitArm64);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U8);
|
{
|
||||||
|
MOVP2R(ARM64Reg::X8, &PowerPC::WriteU8FromJitArm64);
|
||||||
|
}
|
||||||
|
|
||||||
BLR(ARM64Reg::X8);
|
BLR(ARM64Reg::X8);
|
||||||
}
|
}
|
||||||
else if (flags & BackPatchInfo::FLAG_ZERO_256)
|
else if (flags & BackPatchInfo::FLAG_ZERO_256)
|
||||||
{
|
{
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLine);
|
MOVP2R(ARM64Reg::X1, &m_mmu);
|
||||||
|
MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLineFromJitArm64);
|
||||||
BLR(ARM64Reg::X8);
|
BLR(ARM64Reg::X8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
MOVP2R(ARM64Reg::X1, &m_mmu);
|
||||||
|
|
||||||
if (access_size == 64)
|
if (access_size == 64)
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U64);
|
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU64FromJitArm64);
|
||||||
else if (access_size == 32)
|
else if (access_size == 32)
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U32);
|
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU32FromJitArm64);
|
||||||
else if (access_size == 16)
|
else if (access_size == 16)
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U16);
|
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU16FromJitArm64);
|
||||||
else
|
else
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U8);
|
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU8FromJitArm64);
|
||||||
|
|
||||||
BLR(ARM64Reg::X8);
|
BLR(ARM64Reg::X8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,9 +132,9 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
||||||
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
||||||
u32 mmio_address = 0;
|
u32 mmio_address = 0;
|
||||||
if (is_immediate)
|
if (is_immediate)
|
||||||
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);
|
mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size);
|
||||||
|
|
||||||
if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
|
if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
|
||||||
{
|
{
|
||||||
set_addr_reg_if_needed();
|
set_addr_reg_if_needed();
|
||||||
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, dest_reg, XA, regs_in_use,
|
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, dest_reg, XA, regs_in_use,
|
||||||
|
@ -278,9 +278,9 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
||||||
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
||||||
u32 mmio_address = 0;
|
u32 mmio_address = 0;
|
||||||
if (is_immediate)
|
if (is_immediate)
|
||||||
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);
|
mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size);
|
||||||
|
|
||||||
if (is_immediate && jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr))
|
if (is_immediate && jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr))
|
||||||
{
|
{
|
||||||
int accessSize;
|
int accessSize;
|
||||||
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
||||||
|
@ -306,7 +306,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
||||||
|
|
||||||
js.fifoBytesSinceCheck += accessSize >> 3;
|
js.fifoBytesSinceCheck += accessSize >> 3;
|
||||||
}
|
}
|
||||||
else if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
|
else if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
|
||||||
{
|
{
|
||||||
set_addr_reg_if_needed();
|
set_addr_reg_if_needed();
|
||||||
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, RS, XA, regs_in_use, fprs_in_use);
|
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, RS, XA, regs_in_use, fprs_in_use);
|
||||||
|
@ -358,7 +358,7 @@ FixupBranch JitArm64::CheckIfSafeAddress(Arm64Gen::ARM64Reg addr, Arm64Gen::ARM6
|
||||||
{
|
{
|
||||||
tmp2 = EncodeRegTo64(tmp2);
|
tmp2 = EncodeRegTo64(tmp2);
|
||||||
|
|
||||||
MOVP2R(tmp2, PowerPC::dbat_table.data());
|
MOVP2R(tmp2, m_mmu.GetDBATTable().data());
|
||||||
LSR(tmp1, addr, PowerPC::BAT_INDEX_SHIFT);
|
LSR(tmp1, addr, PowerPC::BAT_INDEX_SHIFT);
|
||||||
LDR(tmp1, tmp2, ArithOption(tmp1, true));
|
LDR(tmp1, tmp2, ArithOption(tmp1, true));
|
||||||
FixupBranch pass = TBNZ(tmp1, IntLog2(PowerPC::BAT_PHYSICAL_BIT));
|
FixupBranch pass = TBNZ(tmp1, IntLog2(PowerPC::BAT_PHYSICAL_BIT));
|
||||||
|
@ -730,7 +730,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
||||||
if (m_ppc_state.msr.IR)
|
if (m_ppc_state.msr.IR)
|
||||||
{
|
{
|
||||||
bat_lookup_failed =
|
bat_lookup_failed =
|
||||||
BATAddressLookup(physical_addr, effective_addr, WA, PowerPC::ibat_table.data());
|
BATAddressLookup(physical_addr, effective_addr, WA, m_mmu.GetIBATTable().data());
|
||||||
BFI(physical_addr, effective_addr, 0, PowerPC::BAT_INDEX_SHIFT);
|
BFI(physical_addr, effective_addr, 0, PowerPC::BAT_INDEX_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
fprs_in_use[DecodeReg(VD)] = 0;
|
fprs_in_use[DecodeReg(VD)] = 0;
|
||||||
|
|
||||||
if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
|
if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
|
||||||
{
|
{
|
||||||
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, VD, XA, regs_in_use, fprs_in_use);
|
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, VD, XA, regs_in_use, fprs_in_use);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
||||||
|
|
||||||
if (is_immediate)
|
if (is_immediate)
|
||||||
{
|
{
|
||||||
if (jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr))
|
if (jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr))
|
||||||
{
|
{
|
||||||
int accessSize;
|
int accessSize;
|
||||||
if (flags & BackPatchInfo::FLAG_SIZE_64)
|
if (flags & BackPatchInfo::FLAG_SIZE_64)
|
||||||
|
@ -399,7 +399,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
||||||
STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
|
STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
|
||||||
js.fifoBytesSinceCheck += accessSize >> 3;
|
js.fifoBytesSinceCheck += accessSize >> 3;
|
||||||
}
|
}
|
||||||
else if (PowerPC::IsOptimizableRAMAddress(imm_addr))
|
else if (m_mmu.IsOptimizableRAMAddress(imm_addr))
|
||||||
{
|
{
|
||||||
set_addr_reg_if_needed();
|
set_addr_reg_if_needed();
|
||||||
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, V0, XA, regs_in_use, fprs_in_use);
|
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, V0, XA, regs_in_use, fprs_in_use);
|
||||||
|
|
|
@ -61,7 +61,8 @@ void JitTrampoline(JitBase& jit, u32 em_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBase::JitBase(Core::System& system)
|
JitBase::JitBase(Core::System& system)
|
||||||
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState())
|
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()),
|
||||||
|
m_mmu(system.GetMMU())
|
||||||
{
|
{
|
||||||
m_registered_config_callback_id = Config::AddConfigChangedCallback(
|
m_registered_config_callback_id = Config::AddConfigChangedCallback(
|
||||||
[this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); });
|
[this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); });
|
||||||
|
|
|
@ -198,6 +198,7 @@ public:
|
||||||
|
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
PowerPC::PowerPCState& m_ppc_state;
|
PowerPC::PowerPCState& m_ppc_state;
|
||||||
|
PowerPC::MMU& m_mmu;
|
||||||
};
|
};
|
||||||
|
|
||||||
void JitTrampoline(JitBase& jit, u32 em_address);
|
void JitTrampoline(JitBase& jit, u32 em_address);
|
||||||
|
|
|
@ -92,7 +92,7 @@ void JitBaseBlockCache::RunOnBlocks(std::function<void(const JitBlock&)> f)
|
||||||
|
|
||||||
JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
||||||
{
|
{
|
||||||
const u32 physical_address = PowerPC::JitCache_TranslateAddress(em_address).address;
|
const u32 physical_address = m_jit.m_mmu.JitCache_TranslateAddress(em_address).address;
|
||||||
JitBlock& b = block_map.emplace(physical_address, JitBlock())->second;
|
JitBlock& b = block_map.emplace(physical_address, JitBlock())->second;
|
||||||
b.effectiveAddress = em_address;
|
b.effectiveAddress = em_address;
|
||||||
b.physicalAddress = physical_address;
|
b.physicalAddress = physical_address;
|
||||||
|
@ -147,7 +147,7 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
||||||
u32 translated_addr = addr;
|
u32 translated_addr = addr;
|
||||||
if (UReg_MSR(msr).IR)
|
if (UReg_MSR(msr).IR)
|
||||||
{
|
{
|
||||||
auto translated = PowerPC::JitCache_TranslateAddress(addr);
|
auto translated = m_jit.m_mmu.JitCache_TranslateAddress(addr);
|
||||||
if (!translated.valid)
|
if (!translated.valid)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -186,7 +186,7 @@ const u8* JitBaseBlockCache::Dispatch()
|
||||||
void JitBaseBlockCache::InvalidateICacheLine(u32 address)
|
void JitBaseBlockCache::InvalidateICacheLine(u32 address)
|
||||||
{
|
{
|
||||||
const u32 cache_line_address = address & ~0x1f;
|
const u32 cache_line_address = address & ~0x1f;
|
||||||
const auto translated = PowerPC::JitCache_TranslateAddress(cache_line_address);
|
const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(cache_line_address);
|
||||||
if (translated.valid)
|
if (translated.valid)
|
||||||
InvalidateICacheInternal(translated.address, cache_line_address, 32, false);
|
InvalidateICacheInternal(translated.address, cache_line_address, 32, false);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ void JitBaseBlockCache::InvalidateICache(u32 initial_address, u32 initial_length
|
||||||
u32 length = initial_length;
|
u32 length = initial_length;
|
||||||
while (length > 0)
|
while (length > 0)
|
||||||
{
|
{
|
||||||
const auto translated = PowerPC::JitCache_TranslateAddress(address);
|
const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(address);
|
||||||
|
|
||||||
const bool address_from_bat = translated.valid && translated.translated && translated.from_bat;
|
const bool address_from_bat = translated.valid && translated.translated && translated.from_bat;
|
||||||
const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT;
|
const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT;
|
||||||
|
|
|
@ -297,7 +297,7 @@ 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::HostRead_U32(guard, PowerPC::ppcState.pc))->type;
|
PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, PowerPC::ppcState.pc))->type;
|
||||||
if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS)
|
if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,18 +8,22 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Common/BitField.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
class CPUThreadGuard;
|
class CPUThreadGuard;
|
||||||
|
class System;
|
||||||
|
}; // namespace Core
|
||||||
|
namespace Memory
|
||||||
|
{
|
||||||
|
class MemoryManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
// Routines for debugger UI, cheats, etc. to access emulated memory from the
|
struct PowerPCState;
|
||||||
// perspective of the CPU. Not for use by core emulation routines.
|
|
||||||
// Use "Host" prefix.
|
|
||||||
|
|
||||||
enum class RequestedAddressSpace
|
enum class RequestedAddressSpace
|
||||||
{
|
{
|
||||||
|
@ -28,19 +32,6 @@ enum class RequestedAddressSpace
|
||||||
Virtual, // specifically want MMU turned on, fails if off
|
Virtual, // specifically want MMU turned on, fails if off
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reads a value from emulated memory using the currently active MMU settings.
|
|
||||||
// If the read fails (eg. address does not correspond to a mapped address in the current address
|
|
||||||
// space), a PanicAlert will be shown to the user and zero (or an empty string for the string case)
|
|
||||||
// will be returned.
|
|
||||||
u8 HostRead_U8(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
u16 HostRead_U16(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
u32 HostRead_U32(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
u64 HostRead_U64(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
float HostRead_F32(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
double HostRead_F64(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, u32 address);
|
|
||||||
std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0);
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ReadResult
|
struct ReadResult
|
||||||
{
|
{
|
||||||
|
@ -57,45 +48,6 @@ struct ReadResult
|
||||||
ReadResult(bool translated_, const T& value_) : translated(translated_), value(value_) {}
|
ReadResult(bool translated_, const T& value_) : translated(translated_), value(value_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to read a value from emulated memory at the given address in the given memory space.
|
|
||||||
// If the read succeeds, the returned value will be present and the ReadResult contains the read
|
|
||||||
// value and information on whether the given address had to be translated or not. Unlike the
|
|
||||||
// HostRead functions, this does not raise a user-visible alert on failure.
|
|
||||||
std::optional<ReadResult<u8>>
|
|
||||||
HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<u16>>
|
|
||||||
HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<u32>>
|
|
||||||
HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<u64>>
|
|
||||||
HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<float>>
|
|
||||||
HostTryReadF32(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<double>>
|
|
||||||
HostTryReadF64(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<u32>>
|
|
||||||
HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<ReadResult<std::string>>
|
|
||||||
HostTryReadString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
|
|
||||||
// Writes a value to emulated memory using the currently active MMU settings.
|
|
||||||
// If the write fails (eg. address does not correspond to a mapped address in the current address
|
|
||||||
// space), a PanicAlert will be shown to the user.
|
|
||||||
void HostWrite_U8(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
|
||||||
void HostWrite_U16(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
|
||||||
void HostWrite_U32(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
|
||||||
void HostWrite_U64(const Core::CPUThreadGuard& guard, u64 var, u32 address);
|
|
||||||
void HostWrite_F32(const Core::CPUThreadGuard& guard, float var, u32 address);
|
|
||||||
void HostWrite_F64(const Core::CPUThreadGuard& guard, double var, u32 address);
|
|
||||||
|
|
||||||
struct WriteResult
|
struct WriteResult
|
||||||
{
|
{
|
||||||
// whether the address had to be translated (given address was treated as virtual) or not (given
|
// whether the address had to be translated (given address was treated as virtual) or not (given
|
||||||
|
@ -105,42 +57,21 @@ struct WriteResult
|
||||||
explicit WriteResult(bool translated_) : translated(translated_) {}
|
explicit WriteResult(bool translated_) : translated(translated_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to a write a value to memory at the given address in the given memory space.
|
constexpr int BAT_INDEX_SHIFT = 17;
|
||||||
// If the write succeeds, the returned TryWriteResult contains information on whether the given
|
constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT;
|
||||||
// address had to be translated or not. Unlike the HostWrite functions, this does not raise a
|
constexpr u32 BAT_PAGE_COUNT = 1 << (32 - BAT_INDEX_SHIFT);
|
||||||
// user-visible alert on failure.
|
constexpr u32 BAT_MAPPED_BIT = 0x1;
|
||||||
std::optional<WriteResult>
|
constexpr u32 BAT_PHYSICAL_BIT = 0x2;
|
||||||
HostTryWriteU8(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
constexpr u32 BAT_WI_BIT = 0x4;
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x7);
|
||||||
std::optional<WriteResult>
|
using BatTable = std::array<u32, BAT_PAGE_COUNT>; // 128 KB
|
||||||
HostTryWriteU16(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<WriteResult>
|
|
||||||
HostTryWriteU32(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<WriteResult>
|
|
||||||
HostTryWriteU64(const Core::CPUThreadGuard& guard, u64 var, const u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
std::optional<WriteResult>
|
|
||||||
HostTryWriteF32(const Core::CPUThreadGuard& guard, float var, const u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
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
|
constexpr size_t HW_PAGE_SIZE = 4096;
|
||||||
// address space.
|
constexpr size_t HW_PAGE_MASK = HW_PAGE_SIZE - 1;
|
||||||
bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address,
|
constexpr u32 HW_PAGE_INDEX_SHIFT = 12;
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
constexpr u32 HW_PAGE_INDEX_MASK = 0x3f;
|
||||||
|
|
||||||
// Same as HostIsRAMAddress, but uses IBAT instead of DBAT.
|
// Return value of MMU::TryReadInstruction().
|
||||||
bool HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address,
|
|
||||||
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
|
||||||
|
|
||||||
// Routines for the CPU core to access memory.
|
|
||||||
|
|
||||||
// Used by interpreter to read instructions, uses iCache
|
|
||||||
u32 Read_Opcode(u32 address);
|
|
||||||
struct TryReadInstResult
|
struct TryReadInstResult
|
||||||
{
|
{
|
||||||
bool valid;
|
bool valid;
|
||||||
|
@ -148,55 +79,8 @@ struct TryReadInstResult
|
||||||
u32 hex;
|
u32 hex;
|
||||||
u32 physical_address;
|
u32 physical_address;
|
||||||
};
|
};
|
||||||
TryReadInstResult TryReadInstruction(u32 address);
|
|
||||||
|
|
||||||
u8 Read_U8(u32 address);
|
|
||||||
u16 Read_U16(u32 address);
|
|
||||||
u32 Read_U32(u32 address);
|
|
||||||
u64 Read_U64(u32 address);
|
|
||||||
|
|
||||||
// Useful helper functions, used by ARM JIT
|
|
||||||
float Read_F32(u32 address);
|
|
||||||
double Read_F64(u32 address);
|
|
||||||
|
|
||||||
// used by JIT. Return zero-extended 32bit values
|
|
||||||
u32 Read_U8_ZX(u32 address);
|
|
||||||
u32 Read_U16_ZX(u32 address);
|
|
||||||
|
|
||||||
void Write_U8(u32 var, u32 address);
|
|
||||||
void Write_U16(u32 var, u32 address);
|
|
||||||
void Write_U32(u32 var, u32 address);
|
|
||||||
void Write_U64(u64 var, u32 address);
|
|
||||||
|
|
||||||
void Write_U16_Swap(u32 var, u32 address);
|
|
||||||
void Write_U32_Swap(u32 var, u32 address);
|
|
||||||
void Write_U64_Swap(u64 var, u32 address);
|
|
||||||
|
|
||||||
// Useful helper functions, used by ARM JIT
|
|
||||||
void Write_F64(double var, u32 address);
|
|
||||||
|
|
||||||
void DMA_LCToMemory(u32 mem_address, u32 cache_address, u32 num_blocks);
|
|
||||||
void DMA_MemoryToLC(u32 cache_address, u32 mem_address, u32 num_blocks);
|
|
||||||
|
|
||||||
void ClearDCacheLine(u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned
|
|
||||||
void StoreDCacheLine(u32 address);
|
|
||||||
void InvalidateDCacheLine(u32 address);
|
|
||||||
void FlushDCacheLine(u32 address);
|
|
||||||
void TouchDCacheLine(u32 address, bool store);
|
|
||||||
|
|
||||||
// TLB functions
|
|
||||||
void SDRUpdated();
|
|
||||||
void InvalidateTLBEntry(u32 address);
|
|
||||||
void DBATUpdated();
|
|
||||||
void IBATUpdated();
|
|
||||||
|
|
||||||
// Result changes based on the BAT registers and MSR.DR. Returns whether
|
|
||||||
// it's safe to optimize a read or write to this address to an unguarded
|
|
||||||
// memory access. Does not consider page tables.
|
|
||||||
bool IsOptimizableRAMAddress(u32 address);
|
|
||||||
u32 IsOptimizableMMIOAccess(u32 address, u32 access_size);
|
|
||||||
bool IsOptimizableGatherPipeWrite(u32 address);
|
|
||||||
|
|
||||||
|
// Return value of MMU::JitCache_TranslateAddress().
|
||||||
struct TranslateResult
|
struct TranslateResult
|
||||||
{
|
{
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
@ -211,32 +95,261 @@ struct TranslateResult
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
TranslateResult JitCache_TranslateAddress(u32 address);
|
|
||||||
|
|
||||||
constexpr int BAT_INDEX_SHIFT = 17;
|
enum class XCheckTLBFlag
|
||||||
constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT;
|
|
||||||
constexpr u32 BAT_PAGE_COUNT = 1 << (32 - BAT_INDEX_SHIFT);
|
|
||||||
constexpr u32 BAT_MAPPED_BIT = 0x1;
|
|
||||||
constexpr u32 BAT_PHYSICAL_BIT = 0x2;
|
|
||||||
constexpr u32 BAT_WI_BIT = 0x4;
|
|
||||||
constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x7);
|
|
||||||
using BatTable = std::array<u32, BAT_PAGE_COUNT>; // 128 KB
|
|
||||||
extern BatTable ibat_table;
|
|
||||||
extern BatTable dbat_table;
|
|
||||||
inline bool TranslateBatAddess(const BatTable& bat_table, u32* address, bool* wi)
|
|
||||||
{
|
{
|
||||||
u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT];
|
NoException,
|
||||||
if ((bat_result & BAT_MAPPED_BIT) == 0)
|
Read,
|
||||||
return false;
|
Write,
|
||||||
*address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1));
|
Opcode,
|
||||||
*wi = (bat_result & BAT_WI_BIT) != 0;
|
OpcodeNoException
|
||||||
return true;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
constexpr size_t HW_PAGE_SIZE = 4096;
|
class MMU
|
||||||
constexpr size_t HW_PAGE_MASK = HW_PAGE_SIZE - 1;
|
{
|
||||||
constexpr u32 HW_PAGE_INDEX_SHIFT = 12;
|
public:
|
||||||
constexpr u32 HW_PAGE_INDEX_MASK = 0x3f;
|
MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state);
|
||||||
|
MMU(const MMU& other) = delete;
|
||||||
|
MMU(MMU&& other) = delete;
|
||||||
|
MMU& operator=(const MMU& other) = delete;
|
||||||
|
MMU& operator=(MMU&& other) = delete;
|
||||||
|
~MMU();
|
||||||
|
|
||||||
std::optional<u32> GetTranslatedAddress(u32 address);
|
// Routines for debugger UI, cheats, etc. to access emulated memory from the
|
||||||
|
// perspective of the CPU. Not for use by core emulation routines.
|
||||||
|
// Use "Host" prefix.
|
||||||
|
|
||||||
|
// Reads a value from emulated memory using the currently active MMU settings.
|
||||||
|
// If the read fails (eg. address does not correspond to a mapped address in the current address
|
||||||
|
// space), a PanicAlert will be shown to the user and zero (or an empty string for the string
|
||||||
|
// case) will be returned.
|
||||||
|
static u8 HostRead_U8(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static u16 HostRead_U16(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static u32 HostRead_U32(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static u64 HostRead_U64(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static float HostRead_F32(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static double HostRead_F64(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, u32 address);
|
||||||
|
static std::string HostGetString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0);
|
||||||
|
|
||||||
|
// Try to read a value from emulated memory at the given address in the given memory space.
|
||||||
|
// If the read succeeds, the returned value will be present and the ReadResult contains the read
|
||||||
|
// value and information on whether the given address had to be translated or not. Unlike the
|
||||||
|
// HostRead functions, this does not raise a user-visible alert on failure.
|
||||||
|
static std::optional<ReadResult<u8>>
|
||||||
|
HostTryReadU8(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<ReadResult<u16>>
|
||||||
|
HostTryReadU16(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<ReadResult<u32>>
|
||||||
|
HostTryReadU32(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<ReadResult<u64>>
|
||||||
|
HostTryReadU64(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<ReadResult<float>>
|
||||||
|
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>>
|
||||||
|
HostTryReadInstruction(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<ReadResult<std::string>>
|
||||||
|
HostTryReadString(const Core::CPUThreadGuard& guard, u32 address, size_t size = 0,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
|
||||||
|
// Writes a value to emulated memory using the currently active MMU settings.
|
||||||
|
// If the write fails (eg. address does not correspond to a mapped address in the current address
|
||||||
|
// space), a PanicAlert will be shown to the user.
|
||||||
|
static void HostWrite_U8(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
||||||
|
static void HostWrite_U16(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
||||||
|
static void HostWrite_U32(const Core::CPUThreadGuard& guard, u32 var, u32 address);
|
||||||
|
static void HostWrite_U64(const Core::CPUThreadGuard& guard, u64 var, u32 address);
|
||||||
|
static void HostWrite_F32(const Core::CPUThreadGuard& guard, float var, u32 address);
|
||||||
|
static void HostWrite_F64(const Core::CPUThreadGuard& guard, double var, u32 address);
|
||||||
|
|
||||||
|
// Try to a write a value to memory at the given address in the given memory space.
|
||||||
|
// If the write succeeds, the returned TryWriteResult contains information on whether the given
|
||||||
|
// address had to be translated or not. Unlike the HostWrite functions, this does not raise a
|
||||||
|
// user-visible alert on failure.
|
||||||
|
static std::optional<WriteResult>
|
||||||
|
HostTryWriteU8(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<WriteResult>
|
||||||
|
HostTryWriteU16(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<WriteResult>
|
||||||
|
HostTryWriteU32(const Core::CPUThreadGuard& guard, u32 var, const u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
static std::optional<WriteResult>
|
||||||
|
HostTryWriteU64(const Core::CPUThreadGuard& guard, u64 var, const u32 address,
|
||||||
|
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
|
||||||
|
// address space.
|
||||||
|
static bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
|
||||||
|
// Same as HostIsRAMAddress, but uses IBAT instead of DBAT.
|
||||||
|
static bool
|
||||||
|
HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address,
|
||||||
|
RequestedAddressSpace space = RequestedAddressSpace::Effective);
|
||||||
|
|
||||||
|
// Routines for the CPU core to access memory.
|
||||||
|
|
||||||
|
// Used by interpreter to read instructions, uses iCache
|
||||||
|
u32 Read_Opcode(u32 address);
|
||||||
|
TryReadInstResult TryReadInstruction(u32 address);
|
||||||
|
|
||||||
|
u8 Read_U8(u32 address);
|
||||||
|
u16 Read_U16(u32 address);
|
||||||
|
u32 Read_U32(u32 address);
|
||||||
|
u64 Read_U64(u32 address);
|
||||||
|
|
||||||
|
void Write_U8(u32 var, u32 address);
|
||||||
|
void Write_U16(u32 var, u32 address);
|
||||||
|
void Write_U32(u32 var, u32 address);
|
||||||
|
void Write_U64(u64 var, u32 address);
|
||||||
|
|
||||||
|
void Write_U16_Swap(u32 var, u32 address);
|
||||||
|
void Write_U32_Swap(u32 var, u32 address);
|
||||||
|
void Write_U64_Swap(u64 var, u32 address);
|
||||||
|
|
||||||
|
void DMA_LCToMemory(u32 mem_address, u32 cache_address, u32 num_blocks);
|
||||||
|
void DMA_MemoryToLC(u32 cache_address, u32 mem_address, u32 num_blocks);
|
||||||
|
|
||||||
|
void ClearDCacheLine(u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned
|
||||||
|
void StoreDCacheLine(u32 address);
|
||||||
|
void InvalidateDCacheLine(u32 address);
|
||||||
|
void FlushDCacheLine(u32 address);
|
||||||
|
void TouchDCacheLine(u32 address, bool store);
|
||||||
|
|
||||||
|
// TLB functions
|
||||||
|
void SDRUpdated();
|
||||||
|
void InvalidateTLBEntry(u32 address);
|
||||||
|
void DBATUpdated();
|
||||||
|
void IBATUpdated();
|
||||||
|
|
||||||
|
// Result changes based on the BAT registers and MSR.DR. Returns whether
|
||||||
|
// it's safe to optimize a read or write to this address to an unguarded
|
||||||
|
// memory access. Does not consider page tables.
|
||||||
|
bool IsOptimizableRAMAddress(u32 address) const;
|
||||||
|
u32 IsOptimizableMMIOAccess(u32 address, u32 access_size) const;
|
||||||
|
bool IsOptimizableGatherPipeWrite(u32 address) const;
|
||||||
|
|
||||||
|
TranslateResult JitCache_TranslateAddress(u32 address);
|
||||||
|
|
||||||
|
std::optional<u32> GetTranslatedAddress(u32 address);
|
||||||
|
|
||||||
|
BatTable& GetIBATTable() { return m_ibat_table; }
|
||||||
|
BatTable& GetDBATTable() { return m_dbat_table; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class TranslateAddressResultEnum : u8
|
||||||
|
{
|
||||||
|
BAT_TRANSLATED,
|
||||||
|
PAGE_TABLE_TRANSLATED,
|
||||||
|
DIRECT_STORE_SEGMENT,
|
||||||
|
PAGE_FAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TranslateAddressResult
|
||||||
|
{
|
||||||
|
u32 address;
|
||||||
|
TranslateAddressResultEnum result;
|
||||||
|
bool wi; // Set to true if the view of memory is either write-through or cache-inhibited
|
||||||
|
|
||||||
|
TranslateAddressResult(TranslateAddressResultEnum result_, u32 address_, bool wi_ = false)
|
||||||
|
: address(address_), result(result_), wi(wi_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool Success() const { return result <= TranslateAddressResultEnum::PAGE_TABLE_TRANSLATED; }
|
||||||
|
};
|
||||||
|
|
||||||
|
union EffectiveAddress
|
||||||
|
{
|
||||||
|
BitField<0, 12, u32> offset;
|
||||||
|
BitField<12, 16, u32> page_index;
|
||||||
|
BitField<22, 6, u32> API;
|
||||||
|
BitField<28, 4, u32> SR;
|
||||||
|
|
||||||
|
u32 Hex = 0;
|
||||||
|
|
||||||
|
EffectiveAddress() = default;
|
||||||
|
explicit EffectiveAddress(u32 address) : Hex{address} {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <const XCheckTLBFlag flag>
|
||||||
|
TranslateAddressResult TranslateAddress(u32 address);
|
||||||
|
|
||||||
|
TranslateAddressResult TranslatePageAddress(const EffectiveAddress address,
|
||||||
|
const XCheckTLBFlag flag, bool* wi);
|
||||||
|
|
||||||
|
void GenerateDSIException(u32 effective_address, bool write);
|
||||||
|
void GenerateISIException(u32 effective_address);
|
||||||
|
|
||||||
|
void Memcheck(u32 address, u64 var, bool write, size_t size);
|
||||||
|
|
||||||
|
void UpdateBATs(BatTable& bat_table, u32 base_spr);
|
||||||
|
void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr);
|
||||||
|
|
||||||
|
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
||||||
|
T ReadFromHardware(u32 em_address);
|
||||||
|
template <XCheckTLBFlag flag, bool never_translate = false>
|
||||||
|
void WriteToHardware(u32 em_address, const u32 data, const u32 size);
|
||||||
|
template <XCheckTLBFlag flag>
|
||||||
|
bool IsRAMAddress(u32 address, bool translate);
|
||||||
|
|
||||||
|
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;
|
||||||
|
Memory::MemoryManager& m_memory;
|
||||||
|
PowerPC::PowerPCState& m_ppc_state;
|
||||||
|
|
||||||
|
BatTable m_ibat_table;
|
||||||
|
BatTable m_dbat_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ClearDCacheLineFromJit64(MMU& mmu, u32 address);
|
||||||
|
u32 ReadU8ZXFromJit64(MMU& mmu, u32 address); // Returns zero-extended 32bit value
|
||||||
|
u32 ReadU16ZXFromJit64(MMU& mmu, u32 address); // Returns zero-extended 32bit value
|
||||||
|
u32 ReadU32FromJit64(MMU& mmu, u32 address);
|
||||||
|
u64 ReadU64FromJit64(MMU& mmu, u32 address);
|
||||||
|
void WriteU8FromJit64(MMU& mmu, u32 var, u32 address);
|
||||||
|
void WriteU16FromJit64(MMU& mmu, u32 var, u32 address);
|
||||||
|
void WriteU32FromJit64(MMU& mmu, u32 var, u32 address);
|
||||||
|
void WriteU64FromJit64(MMU& mmu, u64 var, u32 address);
|
||||||
|
void WriteU16SwapFromJit64(MMU& mmu, u32 var, u32 address);
|
||||||
|
void WriteU32SwapFromJit64(MMU& mmu, u32 var, u32 address);
|
||||||
|
void WriteU64SwapFromJit64(MMU& mmu, u64 var, u32 address);
|
||||||
|
|
||||||
|
// The JitArm64 function that calls these has very specific register allocation that's difficult to
|
||||||
|
// change, so we have a separate set of functions here for it. This can probably be refactored in
|
||||||
|
// the future.
|
||||||
|
void ClearDCacheLineFromJitArm64(u32 address, MMU& mmu);
|
||||||
|
u8 ReadU8FromJitArm64(u32 address, MMU& mmu);
|
||||||
|
u16 ReadU16FromJitArm64(u32 address, MMU& mmu);
|
||||||
|
u32 ReadU32FromJitArm64(u32 address, MMU& mmu);
|
||||||
|
u64 ReadU64FromJitArm64(u32 address, MMU& mmu);
|
||||||
|
void WriteU8FromJitArm64(u32 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU16FromJitArm64(u32 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU32FromJitArm64(u32 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU64FromJitArm64(u64 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU16SwapFromJitArm64(u32 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU32SwapFromJitArm64(u32 var, u32 address, MMU& mmu);
|
||||||
|
void WriteU64SwapFromJitArm64(u64 var, u32 address, MMU& mmu);
|
||||||
} // namespace PowerPC
|
} // namespace PowerPC
|
||||||
|
|
|
@ -17,12 +17,14 @@
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||||
#include "Core/PowerPC/PPCTables.h"
|
#include "Core/PowerPC/PPCTables.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
// Analyzes PowerPC code in memory to find functions
|
// Analyzes PowerPC code in memory to find functions
|
||||||
// After running, for each function we will know what functions it calls
|
// After running, for each function we will know what functions it calls
|
||||||
|
@ -82,6 +84,8 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
|
||||||
if (func.analyzed)
|
if (func.analyzed)
|
||||||
return true; // No error, just already did it.
|
return true; // No error, just already did it.
|
||||||
|
|
||||||
|
auto& mmu = guard.GetSystem().GetMMU();
|
||||||
|
|
||||||
func.calls.clear();
|
func.calls.clear();
|
||||||
func.callers.clear();
|
func.callers.clear();
|
||||||
func.size = 0;
|
func.size = 0;
|
||||||
|
@ -93,7 +97,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
|
||||||
{
|
{
|
||||||
func.size += 4;
|
func.size += 4;
|
||||||
if (func.size >= JitBase::code_buffer_size * 4 ||
|
if (func.size >= JitBase::code_buffer_size * 4 ||
|
||||||
!PowerPC::HostIsInstructionRAMAddress(guard, addr))
|
!PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +112,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
|
||||||
func.flags |= Common::FFLAG_STRAIGHT;
|
func.flags |= Common::FFLAG_STRAIGHT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
|
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
|
||||||
const UGeckoInstruction instr = read_result.hex;
|
const UGeckoInstruction instr = read_result.hex;
|
||||||
if (read_result.valid && PPCTables::IsValidInstruction(instr))
|
if (read_result.valid && PPCTables::IsValidInstruction(instr))
|
||||||
{
|
{
|
||||||
|
@ -264,9 +268,10 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const
|
||||||
static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 startAddr, u32 endAddr,
|
static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 startAddr, u32 endAddr,
|
||||||
Common::SymbolDB* func_db)
|
Common::SymbolDB* func_db)
|
||||||
{
|
{
|
||||||
|
auto& mmu = guard.GetSystem().GetMMU();
|
||||||
for (u32 addr = startAddr; addr < endAddr; addr += 4)
|
for (u32 addr = startAddr; addr < endAddr; addr += 4)
|
||||||
{
|
{
|
||||||
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
|
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
|
||||||
const UGeckoInstruction instr = read_result.hex;
|
const UGeckoInstruction instr = read_result.hex;
|
||||||
|
|
||||||
if (read_result.valid && PPCTables::IsValidInstruction(instr))
|
if (read_result.valid && PPCTables::IsValidInstruction(instr))
|
||||||
|
@ -280,7 +285,7 @@ static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 sta
|
||||||
u32 target = SignExt26(instr.LI << 2);
|
u32 target = SignExt26(instr.LI << 2);
|
||||||
if (!instr.AA)
|
if (!instr.AA)
|
||||||
target += addr;
|
target += addr;
|
||||||
if (PowerPC::HostIsRAMAddress(guard, target))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, target))
|
||||||
{
|
{
|
||||||
func_db->AddFunction(guard, target);
|
func_db->AddFunction(guard, target);
|
||||||
}
|
}
|
||||||
|
@ -314,9 +319,10 @@ static void FindFunctionsFromHandlers(const Core::CPUThreadGuard& guard, PPCSymb
|
||||||
{0x80001400, "system_management_interrupt_handler"},
|
{0x80001400, "system_management_interrupt_handler"},
|
||||||
{0x80001700, "thermal_management_interrupt_exception_handler"}};
|
{0x80001700, "thermal_management_interrupt_exception_handler"}};
|
||||||
|
|
||||||
|
auto& mmu = guard.GetSystem().GetMMU();
|
||||||
for (const auto& entry : handlers)
|
for (const auto& entry : handlers)
|
||||||
{
|
{
|
||||||
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(entry.first);
|
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(entry.first);
|
||||||
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
|
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
|
||||||
{
|
{
|
||||||
// Check if this function is already mapped
|
// Check if this function is already mapped
|
||||||
|
@ -336,19 +342,20 @@ static void FindFunctionsAfterReturnInstruction(const Core::CPUThreadGuard& guar
|
||||||
for (const auto& func : func_db->Symbols())
|
for (const auto& func : func_db->Symbols())
|
||||||
funcAddrs.push_back(func.second.address + func.second.size);
|
funcAddrs.push_back(func.second.address + func.second.size);
|
||||||
|
|
||||||
|
auto& mmu = guard.GetSystem().GetMMU();
|
||||||
for (u32& location : funcAddrs)
|
for (u32& location : funcAddrs)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Skip zeroes (e.g. Donkey Kong Country Returns) and nop (e.g. libogc)
|
// Skip zeroes (e.g. Donkey Kong Country Returns) and nop (e.g. libogc)
|
||||||
// that sometimes pad function to 16 byte boundary.
|
// that sometimes pad function to 16 byte boundary.
|
||||||
PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(location);
|
PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(location);
|
||||||
while (read_result.valid && (location & 0xf) != 0)
|
while (read_result.valid && (location & 0xf) != 0)
|
||||||
{
|
{
|
||||||
if (read_result.hex != 0 && read_result.hex != 0x60000000)
|
if (read_result.hex != 0 && read_result.hex != 0x60000000)
|
||||||
break;
|
break;
|
||||||
location += 4;
|
location += 4;
|
||||||
read_result = PowerPC::TryReadInstruction(location);
|
read_result = mmu.TryReadInstruction(location);
|
||||||
}
|
}
|
||||||
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
|
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
|
||||||
{
|
{
|
||||||
|
@ -757,9 +764,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
||||||
|
|
||||||
const bool enable_follow = m_enable_branch_following;
|
const bool enable_follow = m_enable_branch_following;
|
||||||
|
|
||||||
|
auto& mmu = Core::System::GetInstance().GetMMU();
|
||||||
for (std::size_t i = 0; i < block_size; ++i)
|
for (std::size_t i = 0; i < block_size; ++i)
|
||||||
{
|
{
|
||||||
auto result = PowerPC::TryReadInstruction(address);
|
auto result = mmu.TryReadInstruction(address);
|
||||||
if (!result.valid)
|
if (!result.valid)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
|
|
@ -18,10 +18,12 @@
|
||||||
#include "Common/IOFile.h"
|
#include "Common/IOFile.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
PPCSymbolDB g_symbolDB;
|
PPCSymbolDB g_symbolDB;
|
||||||
|
|
||||||
|
@ -407,16 +409,17 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
|
||||||
if (strlen(name) > 0)
|
if (strlen(name) > 0)
|
||||||
{
|
{
|
||||||
// Can't compute the checksum if not in RAM
|
// Can't compute the checksum if not in RAM
|
||||||
bool good = !bad && PowerPC::HostIsInstructionRAMAddress(guard, vaddress) &&
|
bool good = !bad && PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress) &&
|
||||||
PowerPC::HostIsInstructionRAMAddress(guard, vaddress + size - 4);
|
PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress + size - 4);
|
||||||
if (!good)
|
if (!good)
|
||||||
{
|
{
|
||||||
// check for BLR before function
|
// check for BLR before function
|
||||||
PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(vaddress - 4);
|
PowerPC::TryReadInstResult read_result =
|
||||||
|
guard.GetSystem().GetMMU().TryReadInstruction(vaddress - 4);
|
||||||
if (read_result.valid && read_result.hex == 0x4e800020)
|
if (read_result.valid && read_result.hex == 0x4e800020)
|
||||||
{
|
{
|
||||||
// check for BLR at end of function
|
// check for BLR at end of function
|
||||||
read_result = PowerPC::TryReadInstruction(vaddress + size - 4);
|
read_result = guard.GetSystem().GetMMU().TryReadInstruction(vaddress + size - 4);
|
||||||
good = read_result.valid && read_result.hex == 0x4e800020;
|
good = read_result.valid && read_result.hex == 0x4e800020;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,8 +146,10 @@ void DoState(PointerWrap& p)
|
||||||
}
|
}
|
||||||
|
|
||||||
RoundingModeUpdated();
|
RoundingModeUpdated();
|
||||||
IBATUpdated();
|
|
||||||
DBATUpdated();
|
auto& mmu = Core::System::GetInstance().GetMMU();
|
||||||
|
mmu.IBATUpdated();
|
||||||
|
mmu.DBATUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemTimers::DecrementerSet();
|
// SystemTimers::DecrementerSet();
|
||||||
|
@ -202,8 +204,10 @@ static void ResetRegisters()
|
||||||
ppcState.SetXER({});
|
ppcState.SetXER({});
|
||||||
|
|
||||||
RoundingModeUpdated();
|
RoundingModeUpdated();
|
||||||
DBATUpdated();
|
|
||||||
IBATUpdated();
|
auto& mmu = Core::System::GetInstance().GetMMU();
|
||||||
|
mmu.DBATUpdated();
|
||||||
|
mmu.IBATUpdated();
|
||||||
|
|
||||||
TL(PowerPC::ppcState) = 0;
|
TL(PowerPC::ppcState) = 0;
|
||||||
TU(PowerPC::ppcState) = 0;
|
TU(PowerPC::ppcState) = 0;
|
||||||
|
|
|
@ -108,8 +108,8 @@ bool Compare(const Core::CPUThreadGuard& guard, u32 address, u32 size, const MEG
|
||||||
|
|
||||||
for (size_t i = 0; i < sig.code.size(); ++i)
|
for (size_t i = 0; i < sig.code.size(); ++i)
|
||||||
{
|
{
|
||||||
if (sig.code[i] != 0 &&
|
if (sig.code[i] != 0 && PowerPC::MMU::HostRead_U32(
|
||||||
PowerPC::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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ u32 HashSignatureDB::ComputeCodeChecksum(const Core::CPUThreadGuard& guard, u32
|
||||||
u32 sum = 0;
|
u32 sum = 0;
|
||||||
for (u32 offset = offsetStart; offset <= offsetEnd; offset += 4)
|
for (u32 offset = offsetStart; offset <= offsetEnd; offset += 4)
|
||||||
{
|
{
|
||||||
u32 opcode = PowerPC::HostRead_Instruction(guard, offset);
|
u32 opcode = PowerPC::MMU::HostRead_Instruction(guard, offset);
|
||||||
u32 op = opcode & 0xFC000000;
|
u32 op = opcode & 0xFC000000;
|
||||||
u32 op2 = 0;
|
u32 op2 = 0;
|
||||||
u32 op3 = 0;
|
u32 op3 = 0;
|
||||||
|
|
|
@ -40,8 +40,9 @@ struct System::Impl
|
||||||
explicit Impl(System& system)
|
explicit Impl(System& system)
|
||||||
: m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system),
|
: m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system),
|
||||||
m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system),
|
m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system),
|
||||||
m_ppc_state(PowerPC::ppcState), m_processor_interface(system), m_serial_interface(system),
|
m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state),
|
||||||
m_video_interface(system), m_interpreter(system, m_ppc_state), m_jit_interface(system)
|
m_processor_interface(system), m_serial_interface(system), m_video_interface(system),
|
||||||
|
m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +68,7 @@ struct System::Impl
|
||||||
PixelEngine::PixelEngineManager m_pixel_engine;
|
PixelEngine::PixelEngineManager m_pixel_engine;
|
||||||
PixelShaderManager m_pixel_shader_manager;
|
PixelShaderManager m_pixel_shader_manager;
|
||||||
PowerPC::PowerPCState& m_ppc_state;
|
PowerPC::PowerPCState& m_ppc_state;
|
||||||
|
PowerPC::MMU m_mmu;
|
||||||
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
|
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
|
||||||
SerialInterface::SerialInterfaceManager m_serial_interface;
|
SerialInterface::SerialInterfaceManager m_serial_interface;
|
||||||
Sram m_sram;
|
Sram m_sram;
|
||||||
|
@ -204,6 +206,11 @@ MemoryInterface::MemoryInterfaceManager& System::GetMemoryInterface() const
|
||||||
return m_impl->m_memory_interface;
|
return m_impl->m_memory_interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PowerPC::MMU& System::GetMMU() const
|
||||||
|
{
|
||||||
|
return m_impl->m_mmu;
|
||||||
|
}
|
||||||
|
|
||||||
PixelEngine::PixelEngineManager& System::GetPixelEngine() const
|
PixelEngine::PixelEngineManager& System::GetPixelEngine() const
|
||||||
{
|
{
|
||||||
return m_impl->m_pixel_engine;
|
return m_impl->m_pixel_engine;
|
||||||
|
|
|
@ -72,8 +72,9 @@ class PixelEngineManager;
|
||||||
};
|
};
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
|
class MMU;
|
||||||
struct PowerPCState;
|
struct PowerPCState;
|
||||||
}
|
} // namespace PowerPC
|
||||||
namespace ProcessorInterface
|
namespace ProcessorInterface
|
||||||
{
|
{
|
||||||
class ProcessorInterfaceManager;
|
class ProcessorInterfaceManager;
|
||||||
|
@ -138,6 +139,7 @@ public:
|
||||||
IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const;
|
IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const;
|
||||||
Memory::MemoryManager& GetMemory() const;
|
Memory::MemoryManager& GetMemory() const;
|
||||||
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;
|
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;
|
||||||
|
PowerPC::MMU& GetMMU() const;
|
||||||
PixelEngine::PixelEngineManager& GetPixelEngine() const;
|
PixelEngine::PixelEngineManager& GetPixelEngine() const;
|
||||||
PixelShaderManager& GetPixelShaderManager() const;
|
PixelShaderManager& GetPixelShaderManager() const;
|
||||||
PowerPC::PowerPCState& GetPPCState() const;
|
PowerPC::PowerPCState& GetPPCState() const;
|
||||||
|
|
|
@ -502,7 +502,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::HostTryReadU8(guard, offset + i);
|
auto result = PowerPC::MMU::HostTryReadU8(guard, offset + i);
|
||||||
if (!result || result->value != value[i])
|
if (!result || result->value != value[i])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -521,7 +521,7 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset,
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
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::HostTryWriteU8(guard, value[i], offset + i);
|
PowerPC::MMU::HostTryWriteU8(guard, value[i], offset + i);
|
||||||
const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size);
|
const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size);
|
||||||
if (overlapping_hook_count != 0)
|
if (overlapping_hook_count != 0)
|
||||||
{
|
{
|
||||||
|
@ -585,13 +585,13 @@ static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Pat
|
||||||
{
|
{
|
||||||
// from the pattern find the next blr instruction
|
// 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::HostTryReadU32(guard, blr_address);
|
auto blr = PowerPC::MMU::HostTryReadU32(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::HostTryWriteU32(guard, jmp, blr_address);
|
PowerPC::MMU::HostTryWriteU32(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)
|
||||||
|
|
|
@ -987,10 +987,11 @@ void CodeViewWidget::OnReplaceInstruction()
|
||||||
|
|
||||||
const u32 addr = GetContextAddress();
|
const u32 addr = GetContextAddress();
|
||||||
|
|
||||||
if (!PowerPC::HostIsInstructionRAMAddress(guard, addr))
|
if (!PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
|
const PowerPC::TryReadInstResult read_result =
|
||||||
|
guard.GetSystem().GetMMU().TryReadInstruction(addr);
|
||||||
if (!read_result.valid)
|
if (!read_result.valid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ void CodeWidget::StepOver()
|
||||||
|
|
||||||
const UGeckoInstruction inst = [&] {
|
const UGeckoInstruction inst = [&] {
|
||||||
Core::CPUThreadGuard guard(system);
|
Core::CPUThreadGuard guard(system);
|
||||||
return PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
return PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (inst.LK)
|
if (inst.LK)
|
||||||
|
@ -516,7 +516,7 @@ void CodeWidget::StepOut()
|
||||||
// Loop until either the current instruction is a return instruction with no Link flag
|
// Loop until either the current instruction is a return instruction with no Link flag
|
||||||
// or a breakpoint is detected so it can step at the breakpoint. If the PC is currently
|
// or a breakpoint is detected so it can step at the breakpoint. If the PC is currently
|
||||||
// on a breakpoint, skip it.
|
// on a breakpoint, skip it.
|
||||||
UGeckoInstruction inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
UGeckoInstruction inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (WillInstructionReturn(inst))
|
if (WillInstructionReturn(inst))
|
||||||
|
@ -540,7 +540,7 @@ void CodeWidget::StepOut()
|
||||||
PowerPC::SingleStep();
|
PowerPC::SingleStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
|
||||||
} while (clock::now() < timeout &&
|
} while (clock::now() < timeout &&
|
||||||
!PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc));
|
!PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc));
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,8 @@ void ThreadWidget::Update()
|
||||||
return QStringLiteral("%1").arg(value, 8, 16, QLatin1Char('0'));
|
return QStringLiteral("%1").arg(value, 8, 16, QLatin1Char('0'));
|
||||||
};
|
};
|
||||||
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 = PowerPC::HostIsRAMAddress(guard, addr) ? PowerPC::HostRead_U32(guard, addr) : 0;
|
addr =
|
||||||
|
PowerPC::MMU::HostIsRAMAddress(guard, addr) ? PowerPC::MMU::HostRead_U32(guard, addr) : 0;
|
||||||
return format_hex(addr);
|
return format_hex(addr);
|
||||||
};
|
};
|
||||||
const auto get_state = [](u16 thread_state) {
|
const auto get_state = [](u16 thread_state) {
|
||||||
|
@ -449,13 +450,13 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
|
||||||
u32 sp = context.gpr->at(1);
|
u32 sp = context.gpr->at(1);
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
if (sp == 0 || sp == 0xffffffff || !PowerPC::HostIsRAMAddress(guard, sp))
|
if (sp == 0 || sp == 0xffffffff || !PowerPC::MMU::HostIsRAMAddress(guard, sp))
|
||||||
break;
|
break;
|
||||||
m_callstack_table->insertRow(i);
|
m_callstack_table->insertRow(i);
|
||||||
m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp)));
|
m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp)));
|
||||||
if (PowerPC::HostIsRAMAddress(guard, sp + 4))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, sp + 4))
|
||||||
{
|
{
|
||||||
const u32 lr_save = PowerPC::HostRead_U32(guard, sp + 4);
|
const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4);
|
||||||
m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save)));
|
m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save)));
|
||||||
m_callstack_table->setItem(i, 3,
|
m_callstack_table->setItem(i, 3,
|
||||||
new QTableWidgetItem(QString::fromStdString(
|
new QTableWidgetItem(QString::fromStdString(
|
||||||
|
@ -465,7 +466,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::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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,18 +193,19 @@ void WatchWidget::Update()
|
||||||
|
|
||||||
QBrush brush = QPalette().brush(QPalette::Text);
|
QBrush brush = QPalette().brush(QPalette::Text);
|
||||||
|
|
||||||
if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, entry.address))
|
if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, entry.address))
|
||||||
brush.setColor(Qt::red);
|
brush.setColor(Qt::red);
|
||||||
|
|
||||||
if (Core::IsRunning())
|
if (Core::IsRunning())
|
||||||
{
|
{
|
||||||
if (PowerPC::HostIsRAMAddress(guard, entry.address))
|
if (PowerPC::MMU::HostIsRAMAddress(guard, entry.address))
|
||||||
{
|
{
|
||||||
hex->setText(QStringLiteral("%1").arg(PowerPC::HostRead_U32(guard, entry.address), 8, 16,
|
hex->setText(QStringLiteral("%1").arg(PowerPC::MMU::HostRead_U32(guard, entry.address), 8,
|
||||||
QLatin1Char('0')));
|
16, QLatin1Char('0')));
|
||||||
decimal->setText(QString::number(PowerPC::HostRead_U32(guard, entry.address)));
|
decimal->setText(QString::number(PowerPC::MMU::HostRead_U32(guard, entry.address)));
|
||||||
string->setText(QString::fromStdString(PowerPC::HostGetString(guard, entry.address, 32)));
|
string->setText(
|
||||||
floatValue->setText(QString::number(PowerPC::HostRead_F32(guard, entry.address)));
|
QString::fromStdString(PowerPC::MMU::HostGetString(guard, entry.address, 32)));
|
||||||
|
floatValue->setText(QString::number(PowerPC::MMU::HostRead_F32(guard, entry.address)));
|
||||||
lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked);
|
lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,7 +419,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PowerPC::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address);
|
PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -446,7 +447,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
|
||||||
|
|
||||||
void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 address)
|
void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 address)
|
||||||
{
|
{
|
||||||
const std::string memory_data_as_string = PowerPC::HostGetString(guard, address, 4);
|
const std::string memory_data_as_string = PowerPC::MMU::HostGetString(guard, address, 4);
|
||||||
|
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
for (const char c : memory_data_as_string)
|
for (const char c : memory_data_as_string)
|
||||||
|
|
|
@ -1351,7 +1351,7 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress)
|
||||||
|
|
||||||
for (; len < MODULE_NAME_MAX_LENGTH; ++len)
|
for (; len < MODULE_NAME_MAX_LENGTH; ++len)
|
||||||
{
|
{
|
||||||
const auto res = PowerPC::HostRead_U8(guard, *found_addr - (len + 1));
|
const auto res = PowerPC::MMU::HostRead_U8(guard, *found_addr - (len + 1));
|
||||||
if (!std::isprint(res))
|
if (!std::isprint(res))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -1406,8 +1406,8 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress)
|
||||||
const auto module_name_offset = accessors->ReadU32(guard, *found_addr);
|
const auto module_name_offset = accessors->ReadU32(guard, *found_addr);
|
||||||
|
|
||||||
// Go to the beginning of the RSO header
|
// Go to the beginning of the RSO header
|
||||||
matches.emplace_back(*found_addr - 16,
|
matches.emplace_back(*found_addr - 16, PowerPC::MMU::HostGetString(guard, module_name_offset,
|
||||||
PowerPC::HostGetString(guard, module_name_offset, module_name_length));
|
module_name_length));
|
||||||
|
|
||||||
progress.SetLabelText(tr("Modules found: %1").arg(matches.size()));
|
progress.SetLabelText(tr("Modules found: %1").arg(matches.size()));
|
||||||
}
|
}
|
||||||
|
@ -1698,8 +1698,8 @@ void MenuBar::SearchInstruction()
|
||||||
for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal();
|
for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal();
|
||||||
addr += 4)
|
addr += 4)
|
||||||
{
|
{
|
||||||
const auto ins_name =
|
const auto ins_name = QString::fromStdString(
|
||||||
QString::fromStdString(PPCTables::GetInstructionName(PowerPC::HostRead_U32(guard, addr)));
|
PPCTables::GetInstructionName(PowerPC::MMU::HostRead_U32(guard, addr)));
|
||||||
if (op == ins_name)
|
if (op == ins_name)
|
||||||
{
|
{
|
||||||
NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op.toStdString(), addr);
|
NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op.toStdString(), addr);
|
||||||
|
|
Loading…
Reference in New Issue