@@ -111,39 +111,39 @@ std::optional<PowerPC::ReadResult<u8>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU8(guard, addr, space);
return PowerPC::MMU::HostTryReadU8(guard, addr, space);
}

template <>
std::optional<PowerPC::ReadResult<u16>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU16(guard, addr, space);
return PowerPC::MMU::HostTryReadU16(guard, addr, space);
}

template <>
std::optional<PowerPC::ReadResult<u32>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU32(guard, addr, space);
return PowerPC::MMU::HostTryReadU32(guard, addr, space);
}

template <>
std::optional<PowerPC::ReadResult<u64>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU64(guard, addr, space);
return PowerPC::MMU::HostTryReadU64(guard, addr, space);
}

template <>
std::optional<PowerPC::ReadResult<s8>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU8(guard, addr, space);
auto tmp = PowerPC::MMU::HostTryReadU8(guard, addr, space);
if (!tmp)
return std::nullopt;
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,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU16(guard, addr, space);
auto tmp = PowerPC::MMU::HostTryReadU16(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s16>(tmp->translated, Common::BitCast<s16>(tmp->value));
@@ -165,7 +165,7 @@ std::optional<PowerPC::ReadResult<s32>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU32(guard, addr, space);
auto tmp = PowerPC::MMU::HostTryReadU32(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s32>(tmp->translated, Common::BitCast<s32>(tmp->value));
@@ -176,7 +176,7 @@ std::optional<PowerPC::ReadResult<s64>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU64(guard, addr, space);
auto tmp = PowerPC::MMU::HostTryReadU64(guard, addr, space);
if (!tmp)
return std::nullopt;
return PowerPC::ReadResult<s64>(tmp->translated, Common::BitCast<s64>(tmp->value));
@@ -187,15 +187,15 @@ std::optional<PowerPC::ReadResult<float>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadF32(guard, addr, space);
return PowerPC::MMU::HostTryReadF32(guard, addr, space);
}

template <>
std::optional<PowerPC::ReadResult<double>>
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadF64(guard, addr, space);
return PowerPC::MMU::HostTryReadF64(guard, addr, space);
}
} // namespace

@@ -41,7 +41,7 @@ void AddAutoBreakpoints()
// Returns true if the address is not a valid RAM address or NULL.
static bool IsStackBottom(const Core::CPUThreadGuard& guard, u32 addr)
{
return !addr || !PowerPC::HostIsRAMAddress(guard, addr);
return !addr || !PowerPC::MMU::HostIsRAMAddress(guard, addr);
}

static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard,
@@ -51,18 +51,18 @@ static void WalkTheStack(Core::System& system, const Core::CPUThreadGuard& guard

if (!IsStackBottom(guard, ppc_state.gpr[1]))
{
u32 addr = PowerPC::HostRead_U32(guard, ppc_state.gpr[1]); // SP
u32 addr = PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[1]); // SP

// Walk the stack chain
for (int count = 0; !IsStackBottom(guard, addr + 4) && (count++ < 20); ++count)
{
u32 func_addr = PowerPC::HostRead_U32(guard, addr + 4);
u32 func_addr = PowerPC::MMU::HostRead_U32(guard, addr + 4);
stack_step(func_addr);

if (IsStackBottom(guard, addr))
break;

addr = PowerPC::HostRead_U32(guard, addr);
addr = PowerPC::MMU::HostRead_U32(guard, addr);
}
}
}
@@ -75,7 +75,7 @@ bool GetCallstack(Core::System& system, const Core::CPUThreadGuard& guard,
{
auto& ppc_state = system.GetPPCState();

if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[1]))
if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[1]))
return false;

if (LR(ppc_state) == 0)
@@ -19,23 +19,23 @@ namespace Core::Debug
void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr)
{
for (std::size_t i = 0; i < gpr.size(); i++)
gpr[i] = PowerPC::HostRead_U32(guard, addr + u32(i * sizeof(int)));
cr = PowerPC::HostRead_U32(guard, addr + 0x80);
lr = PowerPC::HostRead_U32(guard, addr + 0x84);
ctr = PowerPC::HostRead_U32(guard, addr + 0x88);
xer = PowerPC::HostRead_U32(guard, addr + 0x8C);
gpr[i] = PowerPC::MMU::HostRead_U32(guard, addr + u32(i * sizeof(int)));
cr = PowerPC::MMU::HostRead_U32(guard, addr + 0x80);
lr = PowerPC::MMU::HostRead_U32(guard, addr + 0x84);
ctr = PowerPC::MMU::HostRead_U32(guard, addr + 0x88);
xer = PowerPC::MMU::HostRead_U32(guard, addr + 0x8C);
for (std::size_t i = 0; i < fpr.size(); i++)
fpr[i] = PowerPC::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double)));
fpscr = PowerPC::HostRead_U64(guard, addr + 0x190);
srr0 = PowerPC::HostRead_U32(guard, addr + 0x198);
srr1 = PowerPC::HostRead_U32(guard, addr + 0x19c);
dummy = PowerPC::HostRead_U16(guard, addr + 0x1a0);
state = static_cast<OSContext::State>(PowerPC::HostRead_U16(guard, addr + 0x1a2));
fpr[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x90 + u32(i * sizeof(double)));
fpscr = PowerPC::MMU::HostRead_U64(guard, addr + 0x190);
srr0 = PowerPC::MMU::HostRead_U32(guard, addr + 0x198);
srr1 = PowerPC::MMU::HostRead_U32(guard, addr + 0x19c);
dummy = PowerPC::MMU::HostRead_U16(guard, addr + 0x1a0);
state = static_cast<OSContext::State>(PowerPC::MMU::HostRead_U16(guard, addr + 0x1a2));
for (std::size_t i = 0; i < gqr.size(); i++)
gqr[i] = PowerPC::HostRead_U32(guard, addr + 0x1a4 + u32(i * sizeof(int)));
gqr[i] = PowerPC::MMU::HostRead_U32(guard, addr + 0x1a4 + u32(i * sizeof(int)));
psf_padding = 0;
for (std::size_t i = 0; i < psf.size(); i++)
psf[i] = PowerPC::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double)));
psf[i] = PowerPC::MMU::HostRead_F64(guard, addr + 0x1c8 + u32(i * sizeof(double)));
}

// Mutex offsets based on the following functions:
@@ -44,12 +44,12 @@ void OSContext::Read(const Core::CPUThreadGuard& guard, u32 addr)
// - __OSUnlockAllMutex
void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr)
{
thread_queue.head = PowerPC::HostRead_U32(guard, addr);
thread_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x4);
owner_addr = PowerPC::HostRead_U32(guard, addr + 0x8);
lock_count = PowerPC::HostRead_U32(guard, addr + 0xc);
link.next = PowerPC::HostRead_U32(guard, addr + 0x10);
link.prev = PowerPC::HostRead_U32(guard, addr + 0x14);
thread_queue.head = PowerPC::MMU::HostRead_U32(guard, addr);
thread_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x4);
owner_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x8);
lock_count = PowerPC::MMU::HostRead_U32(guard, addr + 0xc);
link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x10);
link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x14);
}

// Thread offsets based on the following functions:
@@ -67,38 +67,38 @@ void OSMutex::Read(const Core::CPUThreadGuard& guard, u32 addr)
void OSThread::Read(const Core::CPUThreadGuard& guard, u32 addr)
{
context.Read(guard, addr);
state = PowerPC::HostRead_U16(guard, addr + 0x2c8);
is_detached = PowerPC::HostRead_U16(guard, addr + 0x2ca);
suspend = PowerPC::HostRead_U32(guard, addr + 0x2cc);
effective_priority = PowerPC::HostRead_U32(guard, addr + 0x2d0);
base_priority = PowerPC::HostRead_U32(guard, addr + 0x2d4);
exit_code_addr = PowerPC::HostRead_U32(guard, addr + 0x2d8);
state = PowerPC::MMU::HostRead_U16(guard, addr + 0x2c8);
is_detached = PowerPC::MMU::HostRead_U16(guard, addr + 0x2ca);
suspend = PowerPC::MMU::HostRead_U32(guard, addr + 0x2cc);
effective_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d0);
base_priority = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d4);
exit_code_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2d8);

queue_addr = PowerPC::HostRead_U32(guard, addr + 0x2dc);
queue_link.next = PowerPC::HostRead_U32(guard, addr + 0x2e0);
queue_link.prev = PowerPC::HostRead_U32(guard, addr + 0x2e4);
queue_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2dc);
queue_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e0);
queue_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e4);

join_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2e8);
join_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2ec);
join_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2e8);
join_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2ec);

mutex_addr = PowerPC::HostRead_U32(guard, addr + 0x2f0);
mutex_queue.head = PowerPC::HostRead_U32(guard, addr + 0x2f4);
mutex_queue.tail = PowerPC::HostRead_U32(guard, addr + 0x2f8);
mutex_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f0);
mutex_queue.head = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f4);
mutex_queue.tail = PowerPC::MMU::HostRead_U32(guard, addr + 0x2f8);

thread_link.next = PowerPC::HostRead_U32(guard, addr + 0x2fc);
thread_link.prev = PowerPC::HostRead_U32(guard, addr + 0x300);
thread_link.next = PowerPC::MMU::HostRead_U32(guard, addr + 0x2fc);
thread_link.prev = PowerPC::MMU::HostRead_U32(guard, addr + 0x300);

stack_addr = PowerPC::HostRead_U32(guard, addr + 0x304);
stack_end = PowerPC::HostRead_U32(guard, addr + 0x308);
error = PowerPC::HostRead_U32(guard, addr + 0x30c);
specific[0] = PowerPC::HostRead_U32(guard, addr + 0x310);
specific[1] = PowerPC::HostRead_U32(guard, addr + 0x314);
stack_addr = PowerPC::MMU::HostRead_U32(guard, addr + 0x304);
stack_end = PowerPC::MMU::HostRead_U32(guard, addr + 0x308);
error = PowerPC::MMU::HostRead_U32(guard, addr + 0x30c);
specific[0] = PowerPC::MMU::HostRead_U32(guard, addr + 0x310);
specific[1] = PowerPC::MMU::HostRead_U32(guard, addr + 0x314);
}

bool OSThread::IsValid(const Core::CPUThreadGuard& guard) const
{
return PowerPC::HostIsRAMAddress(guard, stack_end) &&
PowerPC::HostRead_U32(guard, stack_end) == STACK_MAGIC;
return PowerPC::MMU::HostIsRAMAddress(guard, stack_end) &&
PowerPC::MMU::HostRead_U32(guard, stack_end) == STACK_MAGIC;
}

OSThreadView::OSThreadView(const Core::CPUThreadGuard& guard, u32 addr)
@@ -192,9 +192,9 @@ std::string OSThreadView::GetSpecific(const Core::CPUThreadGuard& guard) const

for (u32 addr : m_thread.specific)
{
if (!PowerPC::HostIsRAMAddress(guard, addr))
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
break;
specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(guard, addr));
specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::MMU::HostGetString(guard, addr));
}

return specific;
@@ -33,20 +33,20 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa

const u32 address = patch.address;
const std::size_t size = patch.value.size();
if (!PowerPC::HostIsRAMAddress(guard, address))
if (!PowerPC::MMU::HostIsRAMAddress(guard, address))
return;

for (u32 offset = 0; offset < size; ++offset)
{
if (store_existing_value)
{
const u8 value = PowerPC::HostRead_U8(guard, address + offset);
PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset);
const u8 value = PowerPC::MMU::HostRead_U8(guard, address + offset);
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset);
patch.value[offset] = value;
}
else
{
PowerPC::HostWrite_U8(guard, patch.value[offset], address + offset);
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset);
}

if (((address + offset) % 4) == 3)
@@ -231,10 +231,10 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
Common::Debug::Threads threads;

constexpr u32 ACTIVE_QUEUE_HEAD_ADDR = 0x800000dc;
if (!PowerPC::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR))
if (!PowerPC::MMU::HostIsRAMAddress(guard, ACTIVE_QUEUE_HEAD_ADDR))
return threads;
const u32 active_queue_head = PowerPC::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR);
if (!PowerPC::HostIsRAMAddress(guard, active_queue_head))
const u32 active_queue_head = PowerPC::MMU::HostRead_U32(guard, ACTIVE_QUEUE_HEAD_ADDR);
if (!PowerPC::MMU::HostIsRAMAddress(guard, active_queue_head))
return threads;

auto active_thread = std::make_unique<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()};
const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) {
while (addr != 0 && PowerPC::HostIsRAMAddress(guard, addr))
while (addr != 0 && PowerPC::MMU::HostIsRAMAddress(guard, addr))
{
if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end())
break;
@@ -271,12 +271,12 @@ std::string PPCDebugInterface::Disassemble(const Core::CPUThreadGuard* guard, u3
{
if (guard)
{
if (!PowerPC::HostIsRAMAddress(*guard, address))
if (!PowerPC::MMU::HostIsRAMAddress(*guard, address))
{
return "(No RAM here)";
}

const u32 op = PowerPC::HostRead_Instruction(*guard, address);
const u32 op = PowerPC::MMU::HostRead_Instruction(*guard, address);
std::string disasm = Common::GekkoDisassembler::Disassemble(op, address);
const UGeckoInstruction inst{op};

@@ -300,7 +300,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu
{
const bool is_aram = memory != 0;

if (is_aram || PowerPC::HostIsRAMAddress(guard, address))
if (is_aram || PowerPC::MMU::HostIsRAMAddress(guard, address))
{
return fmt::format("{:08X}{}", ReadExtraMemory(guard, memory, address),
is_aram ? " (ARAM)" : "");
@@ -314,7 +314,7 @@ std::string PPCDebugInterface::GetRawMemoryString(const Core::CPUThreadGuard& gu

u32 PPCDebugInterface::ReadMemory(const Core::CPUThreadGuard& guard, u32 address) const
{
return PowerPC::HostRead_U32(guard, address);
return PowerPC::MMU::HostRead_U32(guard, address);
}

u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int memory,
@@ -323,7 +323,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me
switch (memory)
{
case 0:
return PowerPC::HostRead_U32(guard, address);
return PowerPC::MMU::HostRead_U32(guard, address);
case 1:
{
auto& dsp = Core::System::GetInstance().GetDSP();
@@ -337,7 +337,7 @@ u32 PPCDebugInterface::ReadExtraMemory(const Core::CPUThreadGuard& guard, int me

u32 PPCDebugInterface::ReadInstruction(const Core::CPUThreadGuard& guard, u32 address) const
{
return PowerPC::HostRead_Instruction(guard, address);
return PowerPC::MMU::HostRead_Instruction(guard, address);
}

bool PPCDebugInterface::IsAlive() const
@@ -412,7 +412,7 @@ u32 PPCDebugInterface::GetColor(const Core::CPUThreadGuard* guard, u32 address)
{
if (!guard || !IsAlive())
return 0xFFFFFF;
if (!PowerPC::HostIsRAMAddress(*guard, address))
if (!PowerPC::MMU::HostIsRAMAddress(*guard, address))
return 0xeeeeee;

Common::Symbol* symbol = g_symbolDB.GetSymbolFromAddr(address);
@@ -17,37 +17,42 @@
void RSOHeaderView::Load(const Core::CPUThreadGuard& guard, u32 address)
{
m_address = address;
m_header.entry.next_entry = PowerPC::HostRead_U32(guard, address);
m_header.entry.prev_entry = PowerPC::HostRead_U32(guard, address + 0x04);
m_header.entry.section_count = PowerPC::HostRead_U32(guard, address + 0x08);
m_header.entry.section_table_offset = PowerPC::HostRead_U32(guard, address + 0xC);
m_header.entry.name_offset = PowerPC::HostRead_U32(guard, address + 0x10);
m_header.entry.name_size = PowerPC::HostRead_U32(guard, address + 0x14);
m_header.entry.version = PowerPC::HostRead_U32(guard, address + 0x18);
m_header.entry.bss_size = PowerPC::HostRead_U32(guard, address + 0x1C);
m_header.section_info.prolog_section_index = PowerPC::HostRead_U8(guard, address + 0x20);
m_header.section_info.epilog_section_index = PowerPC::HostRead_U8(guard, address + 0x21);
m_header.section_info.unresolved_section_index = PowerPC::HostRead_U8(guard, address + 0x22);
m_header.section_info.bss_section_index = PowerPC::HostRead_U8(guard, address + 0x23);
m_header.section_info.prolog_offset = PowerPC::HostRead_U32(guard, address + 0x24);
m_header.section_info.epilog_offset = PowerPC::HostRead_U32(guard, address + 0x28);
m_header.section_info.unresolved_offset = PowerPC::HostRead_U32(guard, address + 0x2C);
m_header.relocation_tables.internals_offset = PowerPC::HostRead_U32(guard, address + 0x30);
m_header.relocation_tables.internals_size = PowerPC::HostRead_U32(guard, address + 0x34);
m_header.relocation_tables.externals_offset = PowerPC::HostRead_U32(guard, address + 0x38);
m_header.relocation_tables.externals_size = PowerPC::HostRead_U32(guard, address + 0x3C);
m_header.symbol_tables.exports_offset = PowerPC::HostRead_U32(guard, address + 0x40);
m_header.symbol_tables.exports_size = PowerPC::HostRead_U32(guard, address + 0x44);
m_header.symbol_tables.exports_name_table = PowerPC::HostRead_U32(guard, address + 0x48);
m_header.symbol_tables.imports_offset = PowerPC::HostRead_U32(guard, address + 0x4C);
m_header.symbol_tables.imports_size = PowerPC::HostRead_U32(guard, address + 0x50);
m_header.symbol_tables.imports_name_table = PowerPC::HostRead_U32(guard, address + 0x54);
m_header.entry.next_entry = PowerPC::MMU::HostRead_U32(guard, address);
m_header.entry.prev_entry = PowerPC::MMU::HostRead_U32(guard, address + 0x04);
m_header.entry.section_count = PowerPC::MMU::HostRead_U32(guard, address + 0x08);
m_header.entry.section_table_offset = PowerPC::MMU::HostRead_U32(guard, address + 0xC);
m_header.entry.name_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x10);
m_header.entry.name_size = PowerPC::MMU::HostRead_U32(guard, address + 0x14);
m_header.entry.version = PowerPC::MMU::HostRead_U32(guard, address + 0x18);
m_header.entry.bss_size = PowerPC::MMU::HostRead_U32(guard, address + 0x1C);
m_header.section_info.prolog_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x20);
m_header.section_info.epilog_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x21);
m_header.section_info.unresolved_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x22);
m_header.section_info.bss_section_index = PowerPC::MMU::HostRead_U8(guard, address + 0x23);
m_header.section_info.prolog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x24);
m_header.section_info.epilog_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x28);
m_header.section_info.unresolved_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x2C);
m_header.relocation_tables.internals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x30);
m_header.relocation_tables.internals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x34);
m_header.relocation_tables.externals_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x38);
m_header.relocation_tables.externals_size = PowerPC::MMU::HostRead_U32(guard, address + 0x3C);
m_header.symbol_tables.exports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x40);
m_header.symbol_tables.exports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x44);
m_header.symbol_tables.exports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x48);
m_header.symbol_tables.imports_offset = PowerPC::MMU::HostRead_U32(guard, address + 0x4C);
m_header.symbol_tables.imports_size = PowerPC::MMU::HostRead_U32(guard, address + 0x50);
m_header.symbol_tables.imports_name_table = PowerPC::MMU::HostRead_U32(guard, address + 0x54);

// Prevent an invalid name going wild
if (m_header.entry.name_size < 0x100)
m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size);
{
m_name =
PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, m_header.entry.name_size);
}
else
m_name = PowerPC::HostGetString(guard, m_header.entry.name_offset, 0x100);
{
m_name = PowerPC::MMU::HostGetString(guard, m_header.entry.name_offset, 0x100);
}
}

u32 RSOHeaderView::GetNextEntry() const
@@ -176,8 +181,8 @@ void RSOSectionsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::
for (std::size_t i = 0; i < count; ++i)
{
RSOSection section;
section.offset = PowerPC::HostRead_U32(guard, address);
section.size = PowerPC::HostRead_U32(guard, address + 4);
section.offset = PowerPC::MMU::HostRead_U32(guard, address);
section.size = PowerPC::MMU::HostRead_U32(guard, address + 4);
m_sections.emplace_back(std::move(section));
address += sizeof(RSOSection);
}
@@ -204,9 +209,9 @@ void RSOImportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s
for (std::size_t i = 0; i < count; ++i)
{
RSOImport rso_import;
rso_import.name_offset = PowerPC::HostRead_U32(guard, address);
rso_import.code_offset = PowerPC::HostRead_U32(guard, address + 4);
rso_import.entry_offset = PowerPC::HostRead_U32(guard, address + 8);
rso_import.name_offset = PowerPC::MMU::HostRead_U32(guard, address);
rso_import.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4);
rso_import.entry_offset = PowerPC::MMU::HostRead_U32(guard, address + 8);
m_imports.emplace_back(std::move(rso_import));
address += sizeof(RSOImport);
}
@@ -233,10 +238,10 @@ void RSOExportsView::Load(const Core::CPUThreadGuard& guard, u32 address, std::s
for (std::size_t i = 0; i < count; ++i)
{
RSOExport rso_export;
rso_export.name_offset = PowerPC::HostRead_U32(guard, address);
rso_export.code_offset = PowerPC::HostRead_U32(guard, address + 4);
rso_export.section_index = PowerPC::HostRead_U32(guard, address + 8);
rso_export.hash = PowerPC::HostRead_U32(guard, address + 12);
rso_export.name_offset = PowerPC::MMU::HostRead_U32(guard, address);
rso_export.code_offset = PowerPC::MMU::HostRead_U32(guard, address + 4);
rso_export.section_index = PowerPC::MMU::HostRead_U32(guard, address + 8);
rso_export.hash = PowerPC::MMU::HostRead_U32(guard, address + 12);
m_exports.emplace_back(std::move(rso_export));
address += sizeof(RSOExport);
}
@@ -263,9 +268,9 @@ void RSOInternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std:
for (std::size_t i = 0; i < count; ++i)
{
RSOInternalsEntry entry;
entry.r_offset = PowerPC::HostRead_U32(guard, address);
entry.r_info = PowerPC::HostRead_U32(guard, address + 4);
entry.r_addend = PowerPC::HostRead_U32(guard, address + 8);
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address);
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4);
entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8);
m_entries.emplace_back(std::move(entry));
address += sizeof(RSOInternalsEntry);
}
@@ -292,9 +297,9 @@ void RSOExternalsView::Load(const Core::CPUThreadGuard& guard, u32 address, std:
for (std::size_t i = 0; i < count; ++i)
{
RSOExternalsEntry entry;
entry.r_offset = PowerPC::HostRead_U32(guard, address);
entry.r_info = PowerPC::HostRead_U32(guard, address + 4);
entry.r_addend = PowerPC::HostRead_U32(guard, address + 8);
entry.r_offset = PowerPC::MMU::HostRead_U32(guard, address);
entry.r_info = PowerPC::MMU::HostRead_U32(guard, address + 4);
entry.r_addend = PowerPC::MMU::HostRead_U32(guard, address + 8);
m_entries.emplace_back(std::move(entry));
address += sizeof(RSOExternalsEntry);
}
@@ -443,7 +448,8 @@ const RSOImport& RSOView::GetImport(std::size_t index) const
std::string RSOView::GetImportName(const Core::CPUThreadGuard& guard,
const RSOImport& rso_import) const
{
return PowerPC::HostGetString(guard, m_header.GetImportsNameTable() + rso_import.name_offset);
return PowerPC::MMU::HostGetString(guard,
m_header.GetImportsNameTable() + rso_import.name_offset);
}

const std::vector<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,
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
@@ -654,8 +654,10 @@ void FifoPlayer::LoadMemory()
ppc_state.spr[SPR_DBAT0L] = 0x00000002;
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
PowerPC::DBATUpdated();
PowerPC::IBATUpdated();

auto& mmu = system.GetMMU();
mmu.DBATUpdated();
mmu.IBATUpdated();

SetupFifo();
LoadRegisters();
@@ -713,12 +715,12 @@ void FifoPlayer::LoadTextureMemory()

void FifoPlayer::WriteCP(u32 address, u16 value)
{
PowerPC::Write_U16(value, 0xCC000000 | address);
Core::System::GetInstance().GetMMU().Write_U16(value, 0xCC000000 | address);
}

void FifoPlayer::WritePI(u32 address, u32 value)
{
PowerPC::Write_U32(value, 0xCC003000 | address);
Core::System::GetInstance().GetMMU().Write_U32(value, 0xCC003000 | address);
}

void FifoPlayer::FlushWGP()
@@ -823,13 +825,13 @@ bool FifoPlayer::ShouldLoadXF(u8 reg)
bool FifoPlayer::IsIdleSet()
{
CommandProcessor::UCPStatusReg status =
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
return status.CommandIdle;
}

bool FifoPlayer::IsHighWatermarkSet()
{
CommandProcessor::UCPStatusReg status =
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
Core::System::GetInstance().GetMMU().Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
return status.OverflowHiWatermark;
}
@@ -142,17 +142,17 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)

// Install code handler
for (u32 i = 0; i < data.size(); ++i)
PowerPC::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i);
PowerPC::MMU::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i);

// Patch the code handler to the current system type (Gamecube/Wii)
for (unsigned int h = 0; h < data.length(); h += 4)
{
// Patch MMIO address
if (PowerPC::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) ==
if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) ==
(0x3f000000u | ((mmio_addr ^ 1) << 8)))
{
NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h);
PowerPC::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h);
PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h);
}
}

@@ -162,11 +162,11 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)

// Write a magic value to 'gameid' (codehandleronly does not actually read this).
// This value will be read back and modified over time by HLE_Misc::GeckoCodeHandlerICacheFlush.
PowerPC::HostWrite_U32(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS);
PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, INSTALLER_BASE_ADDRESS);

// Create GCT in memory
PowerPC::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address);
PowerPC::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4);
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address);
PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4);

// Each code is 8 bytes (2 words) wide. There is a starter code and an end code.
const u32 start_address = codelist_base_address + CODE_SIZE;
@@ -189,8 +189,8 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)

for (const GeckoCode::Code& code : active_code.codes)
{
PowerPC::HostWrite_U32(guard, code.address, next_address);
PowerPC::HostWrite_U32(guard, code.data, next_address + 4);
PowerPC::MMU::HostWrite_U32(guard, code.address, next_address);
PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4);
next_address += CODE_SIZE;
}
}
@@ -199,12 +199,12 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
end_address - start_address);

// Stop code. Tells the handler that this is the end of the list.
PowerPC::HostWrite_U32(guard, 0xF0000000, next_address);
PowerPC::HostWrite_U32(guard, 0x00000000, next_address + 4);
PowerPC::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS);
PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address);
PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4);
PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS);

// Turn on codes
PowerPC::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7);
PowerPC::MMU::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7);

auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
@@ -274,17 +274,18 @@ void RunCodeHandler(const Core::CPUThreadGuard& guard)
ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler
ppc_state.gpr[1] &= 0xFFFFFFF0; // Align stack to 16bytes
u32 SP = ppc_state.gpr[1]; // Stack Pointer
PowerPC::HostWrite_U32(guard, SP + 8, SP);
PowerPC::MMU::HostWrite_U32(guard, SP + 8, SP);
// SP + 4 is reserved for the codehandler to save LR to the stack.
PowerPC::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame
PowerPC::HostWrite_U32(guard, ppc_state.pc, SP + 12);
PowerPC::HostWrite_U32(guard, LR(ppc_state), SP + 16);
PowerPC::HostWrite_U32(guard, ppc_state.cr.Get(), SP + 20);
PowerPC::MMU::HostWrite_U32(guard, SFP, SP + 8); // Real stack frame
PowerPC::MMU::HostWrite_U32(guard, ppc_state.pc, SP + 12);
PowerPC::MMU::HostWrite_U32(guard, LR(ppc_state), SP + 16);
PowerPC::MMU::HostWrite_U32(guard, ppc_state.cr.Get(), SP + 20);
// Registers FPR0->13 are volatile
for (int i = 0; i < 14; ++i)
{
PowerPC::HostWrite_U64(guard, ppc_state.ps[i].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64));
PowerPC::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(), SP + 24 + (2 * i + 1) * sizeof(u64));
PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64));
PowerPC::MMU::HostWrite_U64(guard, ppc_state.ps[i].PS1AsU64(),
SP + 24 + (2 * i + 1) * sizeof(u64));
}
DEBUG_LOG_FMT(ACTIONREPLAY,
"GeckoCodes: Initiating phantom branch-and-link. "
@@ -42,7 +42,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard)
// been read into memory, or such, so we do the first 5 frames. More
// robust alternative would be to actually detect memory writes, but that
// would be even uglier.)
u32 gch_gameid = PowerPC::HostRead_U32(guard, Gecko::INSTALLER_BASE_ADDRESS);
u32 gch_gameid = PowerPC::MMU::HostRead_U32(guard, Gecko::INSTALLER_BASE_ADDRESS);
if (gch_gameid - Gecko::MAGIC_GAMEID == 5)
{
return;
@@ -51,7 +51,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard)
{
gch_gameid = Gecko::MAGIC_GAMEID;
}
PowerPC::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS);
PowerPC::MMU::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS);

ppc_state.iCache.Reset();
}
@@ -67,14 +67,14 @@ void GeckoReturnTrampoline(const Core::CPUThreadGuard& guard)

// Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler.
u32 SP = ppc_state.gpr[1];
ppc_state.gpr[1] = PowerPC::HostRead_U32(guard, SP + 8);
ppc_state.npc = PowerPC::HostRead_U32(guard, SP + 12);
LR(ppc_state) = PowerPC::HostRead_U32(guard, SP + 16);
ppc_state.cr.Set(PowerPC::HostRead_U32(guard, SP + 20));
ppc_state.gpr[1] = PowerPC::MMU::HostRead_U32(guard, SP + 8);
ppc_state.npc = PowerPC::MMU::HostRead_U32(guard, SP + 12);
LR(ppc_state) = PowerPC::MMU::HostRead_U32(guard, SP + 16);
ppc_state.cr.Set(PowerPC::MMU::HostRead_U32(guard, SP + 20));
for (int i = 0; i < 14; ++i)
{
ppc_state.ps[i].SetBoth(PowerPC::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)),
PowerPC::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64)));
ppc_state.ps[i].SetBoth(PowerPC::MMU::HostRead_U64(guard, SP + 24 + 2 * i * sizeof(u64)),
PowerPC::MMU::HostRead_U64(guard, SP + 24 + (2 * i + 1) * sizeof(u64)));
}
}
} // namespace HLE_Misc
@@ -10,6 +10,7 @@
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Core/Core.h"
#include "Core/HLE/HLE_VarArgs.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
@@ -56,11 +57,11 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para
std::string report_message;

// Is gpr3 pointing to a pointer (including nullptr) rather than an ASCII string
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
(PowerPC::HostIsRAMAddress(guard, PowerPC::HostRead_U32(guard, ppc_state.gpr[3])) ||
PowerPC::HostRead_U32(guard, ppc_state.gpr[3]) == 0))
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
(PowerPC::MMU::HostIsRAMAddress(guard, PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3])) ||
PowerPC::MMU::HostRead_U32(guard, ppc_state.gpr[3]) == 0))
{
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[4]))
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[4]))
{
// ___blank(void* this, const char* fmt, ...);
report_message = GetStringVA(system, guard, 4, parameter_type);
@@ -73,7 +74,7 @@ void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType para
}
else
{
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]))
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]))
{
// ___blank(const char* fmt, ...);
report_message = GetStringVA(system, guard, 3, parameter_type);
@@ -106,13 +107,13 @@ void HLE_GeneralDebugVPrint(const Core::CPUThreadGuard& guard)
// __write_console(int fd, const void* buffer, const u32* size)
void HLE_write_console(const Core::CPUThreadGuard& guard)
{
auto& system = Core::System::GetInstance();
auto& system = guard.GetSystem();
auto& ppc_state = system.GetPPCState();

std::string report_message = GetStringVA(system, guard, 4);
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[5]))
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5]))
{
const u32 size = PowerPC::Read_U32(ppc_state.gpr[5]);
const u32 size = system.GetMMU().Read_U32(ppc_state.gpr[5]);
if (size > report_message.size())
WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size);
else if (size == 0)
@@ -169,16 +170,16 @@ void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_ty
// The structure FILE is implementation defined.
// Both libogc and Dolphin SDK seem to store the fd at the same address.
int fd = -1;
if (PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
PowerPC::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF))
if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3]) &&
PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[3] + 0xF))
{
// The fd is stored as a short at FILE+0xE.
fd = static_cast<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)
{
// 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)
return;
@@ -210,7 +211,7 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard,

std::string ArgumentBuffer;
std::string result;
std::string string = PowerPC::HostGetString(guard, ppc_state.gpr[str_reg]);
std::string string = PowerPC::MMU::HostGetString(guard, ppc_state.gpr[str_reg]);
auto ap =
parameter_type == ParameterType::VariableArgumentList ?
std::make_unique<HLE::SystemVABI::VAListStruct>(system, guard,
@@ -242,8 +243,9 @@ std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard,
switch (string[i])
{
case 's':
result += StringFromFormat(ArgumentBuffer.c_str(),
PowerPC::HostGetString(guard, ap->GetArgT<u32>(guard)).c_str());
result +=
StringFromFormat(ArgumentBuffer.c_str(),
PowerPC::MMU::HostGetString(guard, ap->GetArgT<u32>(guard)).c_str());
break;

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,
u32 address)
: VAList(system, 0), m_va_list{PowerPC::HostRead_U8(guard, address),
PowerPC::HostRead_U8(guard, address + 1),
PowerPC::HostRead_U32(guard, address + 4),
PowerPC::HostRead_U32(guard, address + 8)},
: VAList(system, 0), m_va_list{PowerPC::MMU::HostRead_U8(guard, address),
PowerPC::MMU::HostRead_U8(guard, address + 1),
PowerPC::MMU::HostRead_U32(guard, address + 4),
PowerPC::MMU::HostRead_U32(guard, address + 8)},
m_address(address), m_has_fpr_area(system.GetPPCState().cr.GetBit(6) == 1)
{
m_stack = m_va_list.overflow_arg_area;
@@ -49,7 +49,7 @@ u32 HLE::SystemVABI::VAListStruct::GetGPR(const Core::CPUThreadGuard& guard, u32
return 0;
}
const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4);
return PowerPC::HostRead_U32(guard, gpr_address);
return PowerPC::MMU::HostRead_U32(guard, gpr_address);
}

double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard, u32 fpr) const
@@ -60,5 +60,5 @@ double HLE::SystemVABI::VAListStruct::GetFPR(const Core::CPUThreadGuard& guard,
return 0.0;
}
const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8);
return PowerPC::HostRead_F64(guard, fpr_address);
return PowerPC::MMU::HostRead_F64(guard, fpr_address);
}
@@ -55,7 +55,7 @@ class VAList

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;
@@ -76,7 +76,7 @@ class VAList
else
{
m_stack = Common::AlignUp(m_stack, 4);
value = PowerPC::HostRead_U32(guard, m_stack);
value = PowerPC::MMU::HostRead_U32(guard, m_stack);
m_stack += 4;
}

@@ -99,7 +99,7 @@ class VAList
else
{
m_stack = Common::AlignUp(m_stack, 8);
value = PowerPC::HostRead_U64(guard, m_stack);
value = PowerPC::MMU::HostRead_U64(guard, m_stack);
m_stack += 8;
}

@@ -120,7 +120,7 @@ class VAList
else
{
m_stack = Common::AlignUp(m_stack, 8);
value = PowerPC::HostRead_F64(guard, m_stack);
value = PowerPC::MMU::HostRead_F64(guard, m_stack);
m_stack += 8;
}

@@ -84,60 +84,61 @@ struct EffectiveAddressSpaceAccessors : Accessors
{
bool IsValidAddress(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostIsRAMAddress(guard, address);
return PowerPC::MMU::HostIsRAMAddress(guard, address);
}
u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostRead_U8(guard, address);
return PowerPC::MMU::HostRead_U8(guard, address);
}
void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override
{
PowerPC::HostWrite_U8(guard, value, address);
PowerPC::MMU::HostWrite_U8(guard, value, address);
}
u16 ReadU16(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostRead_U16(guard, address);
return PowerPC::MMU::HostRead_U16(guard, address);
}
void WriteU16(const Core::CPUThreadGuard& guard, u32 address, u16 value) override
{
PowerPC::HostWrite_U16(guard, value, address);
PowerPC::MMU::HostWrite_U16(guard, value, address);
}
u32 ReadU32(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostRead_U32(guard, address);
return PowerPC::MMU::HostRead_U32(guard, address);
}
void WriteU32(const Core::CPUThreadGuard& guard, u32 address, u32 value) override
{
PowerPC::HostWrite_U32(guard, value, address);
PowerPC::MMU::HostWrite_U32(guard, value, address);
}
u64 ReadU64(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostRead_U64(guard, address);
return PowerPC::MMU::HostRead_U64(guard, address);
}
void WriteU64(const Core::CPUThreadGuard& guard, u32 address, u64 value) override
{
PowerPC::HostWrite_U64(guard, value, address);
PowerPC::MMU::HostWrite_U64(guard, value, address);
}
float ReadF32(const Core::CPUThreadGuard& guard, u32 address) const override
{
return PowerPC::HostRead_F32(guard, address);
return PowerPC::MMU::HostRead_F32(guard, address);
};

bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start,
std::size_t needle_size) const
{
auto& system = guard.GetSystem();
auto& memory = system.GetMemory();
auto& mmu = system.GetMMU();

u32 page_base = haystack_start & 0xfffff000;
u32 offset = haystack_start & 0x0000fff;
do
{
if (!PowerPC::HostIsRAMAddress(guard, page_base))
if (!PowerPC::MMU::HostIsRAMAddress(guard, page_base))
{
return false;
}
auto page_physical_address = PowerPC::GetTranslatedAddress(page_base);
auto page_physical_address = mmu.GetTranslatedAddress(page_base);
if (!page_physical_address.has_value())
{
return false;
@@ -184,7 +185,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
const u32 haystack_offset_change = forward ? 1 : -1;
do
{
if (PowerPC::HostIsRAMAddress(guard, haystack_address))
if (PowerPC::MMU::HostIsRAMAddress(guard, haystack_address))
{
do
{
@@ -72,8 +72,8 @@ u32 MemoryWatcher::ChasePointer(const Core::CPUThreadGuard& guard, const std::st
u32 value = 0;
for (u32 offset : m_addresses[line])
{
value = PowerPC::HostRead_U32(guard, value + offset);
if (!PowerPC::HostIsRAMAddress(guard, value))
value = PowerPC::MMU::HostRead_U32(guard, value + offset);
if (!PowerPC::MMU::HostIsRAMAddress(guard, value))
break;
}
return value;
@@ -245,17 +245,22 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector<Pa
switch (entry.type)
{
case PatchType::Patch8Bit:
if (!entry.conditional || PowerPC::HostRead_U8(guard, addr) == static_cast<u8>(comparand))
PowerPC::HostWrite_U8(guard, static_cast<u8>(value), addr);
if (!entry.conditional ||
PowerPC::MMU::HostRead_U8(guard, addr) == static_cast<u8>(comparand))
{
PowerPC::MMU::HostWrite_U8(guard, static_cast<u8>(value), addr);
}
break;
case PatchType::Patch16Bit:
if (!entry.conditional ||
PowerPC::HostRead_U16(guard, addr) == static_cast<u16>(comparand))
PowerPC::HostWrite_U16(guard, static_cast<u16>(value), addr);
PowerPC::MMU::HostRead_U16(guard, addr) == static_cast<u16>(comparand))
{
PowerPC::MMU::HostWrite_U16(guard, static_cast<u16>(value), addr);
}
break;
case PatchType::Patch32Bit:
if (!entry.conditional || PowerPC::HostRead_U32(guard, addr) == comparand)
PowerPC::HostWrite_U32(guard, value, addr);
if (!entry.conditional || PowerPC::MMU::HostRead_U32(guard, addr) == comparand)
PowerPC::MMU::HostWrite_U32(guard, value, addr);
break;
default:
// unknown patchtype
@@ -288,19 +293,19 @@ static bool IsStackValid(const Core::CPUThreadGuard& guard)

// Check the stack pointer
u32 SP = ppc_state.gpr[1];
if (!PowerPC::HostIsRAMAddress(guard, SP))
if (!PowerPC::MMU::HostIsRAMAddress(guard, SP))
return false;

// Read the frame pointer from the stack (find 2nd frame from top), assert that it makes sense
u32 next_SP = PowerPC::HostRead_U32(guard, SP);
if (next_SP <= SP || !PowerPC::HostIsRAMAddress(guard, next_SP) ||
!PowerPC::HostIsRAMAddress(guard, next_SP + 4))
u32 next_SP = PowerPC::MMU::HostRead_U32(guard, SP);
if (next_SP <= SP || !PowerPC::MMU::HostIsRAMAddress(guard, next_SP) ||
!PowerPC::MMU::HostIsRAMAddress(guard, next_SP + 4))
return false;

// Check the link register makes sense (that it points to a valid IBAT address)
const u32 address = PowerPC::HostRead_U32(guard, next_SP + 4);
return PowerPC::HostIsInstructionRAMAddress(guard, address) &&
0 != PowerPC::HostRead_Instruction(guard, address);
const u32 address = PowerPC::MMU::HostRead_U32(guard, next_SP + 4);
return PowerPC::MMU::HostIsInstructionRAMAddress(guard, address) &&
0 != PowerPC::MMU::HostRead_Instruction(guard, address);
}

void AddMemoryPatch(std::size_t index)
@@ -280,7 +280,7 @@ void MemChecks::Add(TMemCheck memory_check)
// watchpoint-compatible code.
if (!had_any)
Core::System::GetInstance().GetJitInterface().ClearCache();
PowerPC::DBATUpdated();
Core::System::GetInstance().GetMMU().DBATUpdated();
});
}

@@ -309,7 +309,7 @@ void MemChecks::Remove(u32 address)
m_mem_checks.erase(iter);
if (!HasAny())
Core::System::GetInstance().GetJitInterface().ClearCache();
PowerPC::DBATUpdated();
Core::System::GetInstance().GetMMU().DBATUpdated();
});
}

@@ -318,7 +318,7 @@ void MemChecks::Clear()
Core::RunAsCPUThread([&] {
m_mem_checks.clear();
Core::System::GetInstance().GetJitInterface().ClearCache();
PowerPC::DBATUpdated();
Core::System::GetInstance().GetMMU().DBATUpdated();
});
}

@@ -31,49 +31,49 @@ static void HostWrite(const Core::CPUThreadGuard& guard, T var, u32 address);
template <>
u8 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::HostRead_U8(guard, address);
return PowerPC::MMU::HostRead_U8(guard, address);
}

template <>
u16 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::HostRead_U16(guard, address);
return PowerPC::MMU::HostRead_U16(guard, address);
}

template <>
u32 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::HostRead_U32(guard, address);
return PowerPC::MMU::HostRead_U32(guard, address);
}

template <>
u64 HostRead(const Core::CPUThreadGuard& guard, u32 address)
{
return PowerPC::HostRead_U64(guard, address);
return PowerPC::MMU::HostRead_U64(guard, address);
}

template <>
void HostWrite(const Core::CPUThreadGuard& guard, u8 var, u32 address)
{
PowerPC::HostWrite_U8(guard, var, address);
PowerPC::MMU::HostWrite_U8(guard, var, address);
}

template <>
void HostWrite(const Core::CPUThreadGuard& guard, u16 var, u32 address)
{
PowerPC::HostWrite_U16(guard, var, address);
PowerPC::MMU::HostWrite_U16(guard, var, address);
}

template <>
void HostWrite(const Core::CPUThreadGuard& guard, u32 var, u32 address)
{
PowerPC::HostWrite_U32(guard, var, address);
PowerPC::MMU::HostWrite_U32(guard, var, address);
}

template <>
void HostWrite(const Core::CPUThreadGuard& guard, u64 var, u32 address)
{
PowerPC::HostWrite_U64(guard, var, address);
PowerPC::MMU::HostWrite_U64(guard, var, address);
}

template <typename T, typename U = T>
@@ -146,7 +146,7 @@ static std::optional<std::string> ReadStringArg(const Core::CPUThreadGuard& guar
if (!std::isnan(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);
@@ -821,7 +821,7 @@ static void ReadMemory(const Core::CPUThreadGuard& guard)
if (len * 2 > sizeof reply)
SendReply("E01");

if (!PowerPC::HostIsRAMAddress(guard, addr))
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
return SendReply("E00");

auto& system = Core::System::GetInstance();
@@ -848,7 +848,7 @@ static void WriteMemory(const Core::CPUThreadGuard& guard)
len = (len << 4) | Hex2char(s_cmd_bfr[i++]);
INFO_LOG_FMT(GDB_STUB, "gdb: write memory: {:08x} bytes to {:08x}", len, addr);

if (!PowerPC::HostIsRAMAddress(guard, addr))
if (!PowerPC::MMU::HostIsRAMAddress(guard, addr))
return SendReply("E00");

auto& system = Core::System::GetInstance();
@@ -64,8 +64,8 @@ void Interpreter::UpdatePC()
m_ppc_state.pc = m_ppc_state.npc;
}

Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state)
: m_system(system), m_ppc_state(ppc_state)
Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu)
: m_system(system), m_ppc_state(ppc_state), m_mmu(mmu)
{
}

@@ -124,7 +124,7 @@ int Interpreter::SingleStepInner()
}

m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction);
m_prev_inst.hex = PowerPC::Read_Opcode(m_ppc_state.pc);
m_prev_inst.hex = m_mmu.Read_Opcode(m_ppc_state.pc);

const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);

@@ -316,7 +316,7 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio
Core::CPUThreadGuard guard(system);

const u32 last_pc = interpreter.m_last_pc;
const u32 opcode = PowerPC::HostRead_U32(guard, last_pc);
const u32 opcode = PowerPC::MMU::HostRead_U32(guard, last_pc);
const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc);
NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm);
Dolphin_Debugger::PrintCallstack(system, guard, Common::Log::LogType::POWERPC,
@@ -15,13 +15,14 @@ class System;
}
namespace PowerPC
{
class MMU;
struct PowerPCState;
}
} // namespace PowerPC

class Interpreter : public CPUCoreBase
{
public:
Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state);
Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state, PowerPC::MMU& mmu);
Interpreter(const Interpreter&) = delete;
Interpreter(Interpreter&&) = delete;
Interpreter& operator=(const Interpreter&) = delete;
@@ -312,6 +313,7 @@ class Interpreter : public CPUCoreBase

Core::System& m_system;
PowerPC::PowerPCState& m_ppc_state;
PowerPC::MMU& m_mmu;

UGeckoInstruction m_prev_inst{};
u32 m_last_pc = 0;

Large diffs are not rendered by default.

@@ -16,6 +16,7 @@
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

// dequantize table
const float m_dequantizeTable[] = {
@@ -68,111 +69,111 @@ SType ScaleAndClamp(double ps, u32 st_scale)
}

template <typename T>
static T ReadUnpaired(u32 addr);
static T ReadUnpaired(PowerPC::MMU& mmu, u32 addr);

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 <>
u16 ReadUnpaired<u16>(u32 addr)
u16 ReadUnpaired<u16>(PowerPC::MMU& mmu, u32 addr)
{
return PowerPC::Read_U16(addr);
return mmu.Read_U16(addr);
}

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>
static std::pair<T, T> ReadPair(u32 addr);
static std::pair<T, T> ReadPair(PowerPC::MMU& mmu, u32 addr);

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)};
}

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)};
}

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)};
}

template <typename T>
static void WriteUnpaired(T val, u32 addr);
static void WriteUnpaired(PowerPC::MMU& mmu, T val, u32 addr);

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 <>
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 <>
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>
static void WritePair(T val1, T val2, u32 addr);
static void WritePair(PowerPC::MMU& mmu, T val1, T val2, u32 addr);

template <>
void WritePair<u8>(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 <>
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 <>
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>
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>;

const U conv_ps0 = U(ScaleAndClamp<T>(ps0, st_scale));
if (instW)
{
WriteUnpaired<U>(conv_ps0, addr);
WriteUnpaired<U>(mmu, conv_ps0, addr);
}
else
{
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,
u32 instW)
static void Helper_Quantize(PowerPC::MMU& mmu, const PowerPC::PowerPCState* ppcs, u32 addr,
u32 instI, u32 instRS, u32 instW)
{
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
const EQuantizeType st_type = gqr.st_type;
@@ -190,32 +191,32 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins

if (instW != 0)
{
WriteUnpaired<u32>(conv_ps0, addr);
WriteUnpaired<u32>(mmu, conv_ps0, addr);
}
else
{
const u64 integral_ps1 = Common::BitCast<u64>(ps1);
const u32 conv_ps1 = ConvertToSingleFTZ(integral_ps1);

WritePair<u32>(conv_ps0, conv_ps1, addr);
WritePair<u32>(mmu, conv_ps0, conv_ps1, addr);
}
break;
}

case QUANTIZE_U8:
QuantizeAndStore<u8>(ps0, ps1, addr, instW, st_scale);
QuantizeAndStore<u8>(mmu, ps0, ps1, addr, instW, st_scale);
break;

case QUANTIZE_U16:
QuantizeAndStore<u16>(ps0, ps1, addr, instW, st_scale);
QuantizeAndStore<u16>(mmu, ps0, ps1, addr, instW, st_scale);
break;

case QUANTIZE_S8:
QuantizeAndStore<s8>(ps0, ps1, addr, instW, st_scale);
QuantizeAndStore<s8>(mmu, ps0, ps1, addr, instW, st_scale);
break;

case QUANTIZE_S16:
QuantizeAndStore<s16>(ps0, ps1, addr, instW, st_scale);
QuantizeAndStore<s16>(mmu, ps0, ps1, addr, instW, st_scale);
break;

case QUANTIZE_INVALID1:
@@ -227,29 +228,29 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
}

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>;

float ps0, ps1;
if (instW != 0)
{
const U value = ReadUnpaired<U>(addr);
const U value = ReadUnpaired<U>(mmu, addr);
ps0 = float(T(value)) * m_dequantizeTable[ld_scale];
ps1 = 1.0f;
}
else
{
const auto [first, second] = ReadPair<U>(addr);
const auto [first, second] = ReadPair<U>(mmu, addr);
ps0 = float(T(first)) * m_dequantizeTable[ld_scale];
ps1 = float(T(second)) * m_dequantizeTable[ld_scale];
}
// ps0 and ps1 always contain finite and normal numbers. So we can just cast them to double
return {static_cast<double>(ps0), static_cast<double>(ps1)};
}

static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRD,
u32 instW)
static void Helper_Dequantize(PowerPC::MMU& mmu, PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
u32 instRD, u32 instW)
{
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
const EQuantizeType ld_type = gqr.ld_type;
@@ -263,32 +264,32 @@ static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
case QUANTIZE_FLOAT:
if (instW != 0)
{
const u32 value = ReadUnpaired<u32>(addr);
const u32 value = ReadUnpaired<u32>(mmu, addr);
ps0 = Common::BitCast<double>(ConvertToDouble(value));
ps1 = 1.0;
}
else
{
const auto [first, second] = ReadPair<u32>(addr);
const auto [first, second] = ReadPair<u32>(mmu, addr);
ps0 = Common::BitCast<double>(ConvertToDouble(first));
ps1 = Common::BitCast<double>(ConvertToDouble(second));
}
break;

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;

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;

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;

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;

case QUANTIZE_INVALID1:
@@ -318,7 +319,7 @@ void Interpreter::psq_l(Interpreter& interpreter, UGeckoInstruction inst)
}

const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W);
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W);
}

void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst)
@@ -331,7 +332,7 @@ void Interpreter::psq_lu(Interpreter& interpreter, UGeckoInstruction inst)
}

const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
Helper_Dequantize(&ppc_state, EA, inst.I, inst.RD, inst.W);
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RD, inst.W);

if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{
@@ -351,7 +352,7 @@ void Interpreter::psq_st(Interpreter& interpreter, UGeckoInstruction inst)
}

const u32 EA = inst.RA ? (ppc_state.gpr[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W);
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W);
}

void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst)
@@ -364,7 +365,7 @@ void Interpreter::psq_stu(Interpreter& interpreter, UGeckoInstruction inst)
}

const u32 EA = ppc_state.gpr[inst.RA] + u32(inst.SIMM_12);
Helper_Quantize(&ppc_state, EA, inst.I, inst.RS, inst.W);
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.I, inst.RS, inst.W);

if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{
@@ -379,22 +380,22 @@ void Interpreter::psq_lx(Interpreter& interpreter, UGeckoInstruction inst)
auto& ppc_state = interpreter.m_ppc_state;
const u32 EA =
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
}

void Interpreter::psq_stx(Interpreter& interpreter, UGeckoInstruction inst)
{
auto& ppc_state = interpreter.m_ppc_state;
const u32 EA =
inst.RA ? (ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB]) : ppc_state.gpr[inst.RB];
Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
}

void Interpreter::psq_lux(Interpreter& interpreter, UGeckoInstruction inst)
{
auto& ppc_state = interpreter.m_ppc_state;
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
Helper_Dequantize(&ppc_state, EA, inst.Ix, inst.RD, inst.Wx);
Helper_Dequantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RD, inst.Wx);

if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{
@@ -408,7 +409,7 @@ void Interpreter::psq_stux(Interpreter& interpreter, UGeckoInstruction inst)
{
auto& ppc_state = interpreter.m_ppc_state;
const u32 EA = ppc_state.gpr[inst.RA] + ppc_state.gpr[inst.RB];
Helper_Quantize(&ppc_state, EA, inst.Ix, inst.RS, inst.Wx);
Helper_Quantize(interpreter.m_mmu, &ppc_state, EA, inst.Ix, inst.RS, inst.Wx);

if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
{
@@ -379,8 +379,8 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
if (old_value != ppc_state.spr[index])
{
INFO_LOG_FMT(POWERPC, "HID4 updated {:x} {:x}", old_value, ppc_state.spr[index]);
PowerPC::IBATUpdated();
PowerPC::DBATUpdated();
interpreter.m_mmu.IBATUpdated();
interpreter.m_mmu.DBATUpdated();
}
break;

@@ -414,9 +414,9 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
if (length == 0)
length = 128;
if (DMAL(ppc_state).DMA_LD)
PowerPC::DMA_MemoryToLC(cache_address, mem_address, length);
interpreter.m_mmu.DMA_MemoryToLC(cache_address, mem_address, length);
else
PowerPC::DMA_LCToMemory(mem_address, cache_address, length);
interpreter.m_mmu.DMA_LCToMemory(mem_address, cache_address, length);
}
DMAL(ppc_state).DMA_T = 0;
break;
@@ -436,7 +436,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)

// Page table base etc
case SPR_SDR:
PowerPC::SDRUpdated();
interpreter.m_mmu.SDRUpdated();
break;

case SPR_XER:
@@ -462,7 +462,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
if (old_value != ppc_state.spr[index])
{
INFO_LOG_FMT(POWERPC, "DBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
PowerPC::DBATUpdated();
interpreter.m_mmu.DBATUpdated();
}
break;

@@ -485,7 +485,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
if (old_value != ppc_state.spr[index])
{
INFO_LOG_FMT(POWERPC, "IBAT updated {} {:x} {:x}", index, old_value, ppc_state.spr[index]);
PowerPC::IBATUpdated();
interpreter.m_mmu.IBATUpdated();
}
break;

@@ -1183,8 +1183,8 @@ void Jit64::IntializeSpeculativeConstants()
for (auto i : code_block.m_gpr_inputs)
{
u32 compileTimeValue = m_ppc_state.gpr[i];
if (PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue) ||
PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) ||
if (m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue) ||
m_mmu.IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) ||
compileTimeValue == 0xCC000000)
{
if (!target)
@@ -324,7 +324,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
if (m_ppc_state.msr.IR)
{
// Translate effective address to physical address.
bat_lookup_failed = BATAddressLookup(addr, tmp, PowerPC::ibat_table.data());
bat_lookup_failed = BATAddressLookup(addr, tmp, m_jit.m_mmu.GetIBATTable().data());
MOV(32, R(tmp), R(effective_address));
AND(32, R(tmp), Imm32(0x0001ffff));
AND(32, R(addr), Imm32(0xfffe0000));
@@ -430,7 +430,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
if (emit_fast_path)
{
// Perform lookup to see if we can use fast path.
MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0]));
MOV(64, R(RSCRATCH2), ImmPtr(m_mmu.GetDBATTable().data()));
PUSH(RSCRATCH);
SHR(32, R(RSCRATCH), Imm8(PowerPC::BAT_INDEX_SHIFT));
TEST(32, MComplex(RSCRATCH2, RSCRATCH, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));
@@ -449,7 +449,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
BitSet32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
ABI_CallFunctionR(PowerPC::ClearDCacheLine, RSCRATCH);
ABI_CallFunctionPR(PowerPC::ClearDCacheLineFromJit64, &m_mmu, RSCRATCH);
ABI_PopRegistersAndAdjustStack(registersInUse, 0);

if (emit_fast_path)
@@ -119,7 +119,7 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_
MOV(32, R(RSCRATCH_EXTRA), R(reg_addr));

// Perform lookup to see if we can use fast path.
MOV(64, R(RSCRATCH), ImmPtr(&PowerPC::dbat_table[0]));
MOV(64, R(RSCRATCH), ImmPtr(m_jit.m_mmu.GetDBATTable().data()));
SHR(32, R(RSCRATCH_EXTRA), Imm8(PowerPC::BAT_INDEX_SHIFT));
TEST(32, MComplex(RSCRATCH, RSCRATCH_EXTRA, SCALE_4, 0), Imm32(PowerPC::BAT_PHYSICAL_BIT));

@@ -396,16 +396,16 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
switch (accessSize)
{
case 64:
ABI_CallFunctionR(PowerPC::Read_U64, reg_addr);
ABI_CallFunctionPR(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, reg_addr);
break;
case 32:
ABI_CallFunctionR(PowerPC::Read_U32, reg_addr);
ABI_CallFunctionPR(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, reg_addr);
break;
case 16:
ABI_CallFunctionR(PowerPC::Read_U16_ZX, reg_addr);
ABI_CallFunctionPR(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, reg_addr);
break;
case 8:
ABI_CallFunctionR(PowerPC::Read_U8_ZX, reg_addr);
ABI_CallFunctionPR(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, reg_addr);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
@@ -436,14 +436,14 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
BitSet32 registersInUse, bool signExtend)
{
// If the address is known to be RAM, just load it directly.
if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address))
if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address))
{
UnsafeLoadToReg(reg_value, Imm32(address), accessSize, 0, signExtend);
return;
}

// If the address maps to an MMIO register, inline MMIO read code.
u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize);
u32 mmioAddress = m_jit.m_mmu.IsOptimizableMMIOAccess(address, accessSize);
if (accessSize != 64 && mmioAddress)
{
auto& memory = m_jit.m_system.GetMemory();
@@ -460,16 +460,16 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
switch (accessSize)
{
case 64:
ABI_CallFunctionC(PowerPC::Read_U64, address);
ABI_CallFunctionPC(PowerPC::ReadU64FromJit64, &m_jit.m_mmu, address);
break;
case 32:
ABI_CallFunctionC(PowerPC::Read_U32, address);
ABI_CallFunctionPC(PowerPC::ReadU32FromJit64, &m_jit.m_mmu, address);
break;
case 16:
ABI_CallFunctionC(PowerPC::Read_U16_ZX, address);
ABI_CallFunctionPC(PowerPC::ReadU16ZXFromJit64, &m_jit.m_mmu, address);
break;
case 8:
ABI_CallFunctionC(PowerPC::Read_U8_ZX, address);
ABI_CallFunctionPC(PowerPC::ReadU8ZXFromJit64, &m_jit.m_mmu, address);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
@@ -578,16 +578,19 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
switch (accessSize)
{
case 64:
ABI_CallFunctionRR(swap ? PowerPC::Write_U64 : PowerPC::Write_U64_Swap, reg, reg_addr);
ABI_CallFunctionPRR(swap ? PowerPC::WriteU64FromJit64 : PowerPC::WriteU64SwapFromJit64,
&m_jit.m_mmu, reg, reg_addr);
break;
case 32:
ABI_CallFunctionRR(swap ? PowerPC::Write_U32 : PowerPC::Write_U32_Swap, reg, reg_addr);
ABI_CallFunctionPRR(swap ? PowerPC::WriteU32FromJit64 : PowerPC::WriteU32SwapFromJit64,
&m_jit.m_mmu, reg, reg_addr);
break;
case 16:
ABI_CallFunctionRR(swap ? PowerPC::Write_U16 : PowerPC::Write_U16_Swap, reg, reg_addr);
ABI_CallFunctionPRR(swap ? PowerPC::WriteU16FromJit64 : PowerPC::WriteU16SwapFromJit64,
&m_jit.m_mmu, reg, reg_addr);
break;
case 8:
ABI_CallFunctionRR(PowerPC::Write_U8, reg, reg_addr);
ABI_CallFunctionPRR(PowerPC::WriteU8FromJit64, &m_jit.m_mmu, reg, reg_addr);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
@@ -623,7 +626,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,

// If we already know the address through constant folding, we can do some
// fun tricks...
if (m_jit.jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(address))
if (m_jit.jo.optimizeGatherPipe && m_jit.m_mmu.IsOptimizableGatherPipeWrite(address))
{
X64Reg arg_reg = RSCRATCH;

@@ -643,7 +646,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
m_jit.js.fifoBytesSinceCheck += accessSize >> 3;
return false;
}
else if (m_jit.jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(address))
else if (m_jit.jo.fastmem_arena && m_jit.m_mmu.IsOptimizableRAMAddress(address))
{
WriteToConstRamAddress(accessSize, arg, address);
return false;
@@ -657,16 +660,16 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
switch (accessSize)
{
case 64:
ABI_CallFunctionAC(64, PowerPC::Write_U64, arg, address);
ABI_CallFunctionPAC(64, PowerPC::WriteU64FromJit64, &m_jit.m_mmu, arg, address);
break;
case 32:
ABI_CallFunctionAC(32, PowerPC::Write_U32, arg, address);
ABI_CallFunctionPAC(32, PowerPC::WriteU32FromJit64, &m_jit.m_mmu, arg, address);
break;
case 16:
ABI_CallFunctionAC(16, PowerPC::Write_U16, arg, address);
ABI_CallFunctionPAC(16, PowerPC::WriteU16FromJit64, &m_jit.m_mmu, arg, address);
break;
case 8:
ABI_CallFunctionAC(8, PowerPC::Write_U8, arg, address);
ABI_CallFunctionPAC(8, PowerPC::WriteU8FromJit64, &m_jit.m_mmu, arg, address);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
@@ -317,8 +317,8 @@ void JitArm64::IntializeSpeculativeConstants()
for (auto i : code_block.m_gpr_inputs)
{
u32 compile_time_value = m_ppc_state.gpr[i];
if (PowerPC::IsOptimizableGatherPipeWrite(compile_time_value) ||
PowerPC::IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) ||
if (m_mmu.IsOptimizableGatherPipeWrite(compile_time_value) ||
m_mmu.IsOptimizableGatherPipeWrite(compile_time_value - 0x8000) ||
compile_time_value == 0xCC000000)
{
if (!fail)
@@ -216,32 +216,48 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,

const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0;

MOVP2R(ARM64Reg::X2, &m_mmu);

if (access_size == 64)
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U64_Swap : &PowerPC::Write_U64);
{
MOVP2R(ARM64Reg::X8,
reverse ? &PowerPC::WriteU64SwapFromJitArm64 : &PowerPC::WriteU64FromJitArm64);
}
else if (access_size == 32)
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U32_Swap : &PowerPC::Write_U32);
{
MOVP2R(ARM64Reg::X8,
reverse ? &PowerPC::WriteU32SwapFromJitArm64 : &PowerPC::WriteU32FromJitArm64);
}
else if (access_size == 16)
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U16_Swap : &PowerPC::Write_U16);
{
MOVP2R(ARM64Reg::X8,
reverse ? &PowerPC::WriteU16SwapFromJitArm64 : &PowerPC::WriteU16FromJitArm64);
}
else
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U8);
{
MOVP2R(ARM64Reg::X8, &PowerPC::WriteU8FromJitArm64);
}

BLR(ARM64Reg::X8);
}
else if (flags & BackPatchInfo::FLAG_ZERO_256)
{
MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLine);
MOVP2R(ARM64Reg::X1, &m_mmu);
MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLineFromJitArm64);
BLR(ARM64Reg::X8);
}
else
{
MOVP2R(ARM64Reg::X1, &m_mmu);

if (access_size == 64)
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U64);
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU64FromJitArm64);
else if (access_size == 32)
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U32);
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU32FromJitArm64);
else if (access_size == 16)
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U16);
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU16FromJitArm64);
else
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U8);
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU8FromJitArm64);

BLR(ARM64Reg::X8);
}
@@ -132,9 +132,9 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
u32 access_size = BackPatchInfo::GetFlagSize(flags);
u32 mmio_address = 0;
if (is_immediate)
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);
mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size);

if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
{
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, dest_reg, XA, regs_in_use,
@@ -278,9 +278,9 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
u32 access_size = BackPatchInfo::GetFlagSize(flags);
u32 mmio_address = 0;
if (is_immediate)
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);
mmio_address = m_mmu.IsOptimizableMMIOAccess(imm_addr, access_size);

if (is_immediate && jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr))
if (is_immediate && jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr))
{
int accessSize;
if (flags & BackPatchInfo::FLAG_SIZE_32)
@@ -306,7 +306,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s

js.fifoBytesSinceCheck += accessSize >> 3;
}
else if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
else if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
{
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, RS, XA, regs_in_use, fprs_in_use);
@@ -358,7 +358,7 @@ FixupBranch JitArm64::CheckIfSafeAddress(Arm64Gen::ARM64Reg addr, Arm64Gen::ARM6
{
tmp2 = EncodeRegTo64(tmp2);

MOVP2R(tmp2, PowerPC::dbat_table.data());
MOVP2R(tmp2, m_mmu.GetDBATTable().data());
LSR(tmp1, addr, PowerPC::BAT_INDEX_SHIFT);
LDR(tmp1, tmp2, ArithOption(tmp1, true));
FixupBranch pass = TBNZ(tmp1, IntLog2(PowerPC::BAT_PHYSICAL_BIT));
@@ -730,7 +730,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
if (m_ppc_state.msr.IR)
{
bat_lookup_failed =
BATAddressLookup(physical_addr, effective_addr, WA, PowerPC::ibat_table.data());
BATAddressLookup(physical_addr, effective_addr, WA, m_mmu.GetIBATTable().data());
BFI(physical_addr, effective_addr, 0, PowerPC::BAT_INDEX_SHIFT);
}

@@ -174,7 +174,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
if (!jo.memcheck)
fprs_in_use[DecodeReg(VD)] = 0;

if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
if (is_immediate && m_mmu.IsOptimizableRAMAddress(imm_addr))
{
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, VD, XA, regs_in_use, fprs_in_use);
}
@@ -378,7 +378,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)

if (is_immediate)
{
if (jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr))
if (jo.optimizeGatherPipe && m_mmu.IsOptimizableGatherPipeWrite(imm_addr))
{
int accessSize;
if (flags & BackPatchInfo::FLAG_SIZE_64)
@@ -399,7 +399,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
js.fifoBytesSinceCheck += accessSize >> 3;
}
else if (PowerPC::IsOptimizableRAMAddress(imm_addr))
else if (m_mmu.IsOptimizableRAMAddress(imm_addr))
{
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, MemAccessMode::AlwaysUnsafe, V0, XA, regs_in_use, fprs_in_use);
@@ -61,7 +61,8 @@ void JitTrampoline(JitBase& jit, u32 em_address)
}

JitBase::JitBase(Core::System& system)
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState())
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()),
m_mmu(system.GetMMU())
{
m_registered_config_callback_id = Config::AddConfigChangedCallback(
[this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); });
@@ -198,6 +198,7 @@ class JitBase : public CPUCoreBase

Core::System& m_system;
PowerPC::PowerPCState& m_ppc_state;
PowerPC::MMU& m_mmu;
};

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)
{
const u32 physical_address = PowerPC::JitCache_TranslateAddress(em_address).address;
const u32 physical_address = m_jit.m_mmu.JitCache_TranslateAddress(em_address).address;
JitBlock& b = block_map.emplace(physical_address, JitBlock())->second;
b.effectiveAddress = em_address;
b.physicalAddress = physical_address;
@@ -147,7 +147,7 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
u32 translated_addr = addr;
if (UReg_MSR(msr).IR)
{
auto translated = PowerPC::JitCache_TranslateAddress(addr);
auto translated = m_jit.m_mmu.JitCache_TranslateAddress(addr);
if (!translated.valid)
{
return nullptr;
@@ -186,7 +186,7 @@ const u8* JitBaseBlockCache::Dispatch()
void JitBaseBlockCache::InvalidateICacheLine(u32 address)
{
const u32 cache_line_address = address & ~0x1f;
const auto translated = PowerPC::JitCache_TranslateAddress(cache_line_address);
const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(cache_line_address);
if (translated.valid)
InvalidateICacheInternal(translated.address, cache_line_address, 32, false);
}
@@ -197,7 +197,7 @@ void JitBaseBlockCache::InvalidateICache(u32 initial_address, u32 initial_length
u32 length = initial_length;
while (length > 0)
{
const auto translated = PowerPC::JitCache_TranslateAddress(address);
const auto translated = m_jit.m_mmu.JitCache_TranslateAddress(address);

const bool address_from_bat = translated.valid && translated.translated && translated.from_bat;
const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT;
@@ -297,7 +297,7 @@ void JitInterface::CompileExceptionCheck(ExceptionType type)

// Check in case the code has been replaced since: do we need to do this?
const OpType optype =
PPCTables::GetOpInfo(PowerPC::HostRead_U32(guard, PowerPC::ppcState.pc))->type;
PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, PowerPC::ppcState.pc))->type;
if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS)
return;
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -17,12 +17,14 @@
#include "Common/StringUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
#include "Core/System.h"

// Analyzes PowerPC code in memory to find functions
// After running, for each function we will know what functions it calls
@@ -82,6 +84,8 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
if (func.analyzed)
return true; // No error, just already did it.

auto& mmu = guard.GetSystem().GetMMU();

func.calls.clear();
func.callers.clear();
func.size = 0;
@@ -93,7 +97,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
{
func.size += 4;
if (func.size >= JitBase::code_buffer_size * 4 ||
!PowerPC::HostIsInstructionRAMAddress(guard, addr))
!PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr))
{
return false;
}
@@ -108,7 +112,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
func.flags |= Common::FFLAG_STRAIGHT;
return true;
}
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
const UGeckoInstruction instr = read_result.hex;
if (read_result.valid && PPCTables::IsValidInstruction(instr))
{
@@ -264,9 +268,10 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const
static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 startAddr, u32 endAddr,
Common::SymbolDB* func_db)
{
auto& mmu = guard.GetSystem().GetMMU();
for (u32 addr = startAddr; addr < endAddr; addr += 4)
{
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
const UGeckoInstruction instr = read_result.hex;

if (read_result.valid && PPCTables::IsValidInstruction(instr))
@@ -280,7 +285,7 @@ static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 sta
u32 target = SignExt26(instr.LI << 2);
if (!instr.AA)
target += addr;
if (PowerPC::HostIsRAMAddress(guard, target))
if (PowerPC::MMU::HostIsRAMAddress(guard, target))
{
func_db->AddFunction(guard, target);
}
@@ -314,9 +319,10 @@ static void FindFunctionsFromHandlers(const Core::CPUThreadGuard& guard, PPCSymb
{0x80001400, "system_management_interrupt_handler"},
{0x80001700, "thermal_management_interrupt_exception_handler"}};

auto& mmu = guard.GetSystem().GetMMU();
for (const auto& entry : handlers)
{
const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(entry.first);
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(entry.first);
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
{
// Check if this function is already mapped
@@ -336,19 +342,20 @@ static void FindFunctionsAfterReturnInstruction(const Core::CPUThreadGuard& guar
for (const auto& func : func_db->Symbols())
funcAddrs.push_back(func.second.address + func.second.size);

auto& mmu = guard.GetSystem().GetMMU();
for (u32& location : funcAddrs)
{
while (true)
{
// Skip zeroes (e.g. Donkey Kong Country Returns) and nop (e.g. libogc)
// that sometimes pad function to 16 byte boundary.
PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(location);
PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(location);
while (read_result.valid && (location & 0xf) != 0)
{
if (read_result.hex != 0 && read_result.hex != 0x60000000)
break;
location += 4;
read_result = PowerPC::TryReadInstruction(location);
read_result = mmu.TryReadInstruction(location);
}
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
{
@@ -757,9 +764,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,

const bool enable_follow = m_enable_branch_following;

auto& mmu = Core::System::GetInstance().GetMMU();
for (std::size_t i = 0; i < block_size; ++i)
{
auto result = PowerPC::TryReadInstruction(address);
auto result = mmu.TryReadInstruction(address);
if (!result.valid)
{
if (i == 0)
@@ -18,10 +18,12 @@
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/Core.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
#include "Core/System.h"

PPCSymbolDB g_symbolDB;

@@ -407,16 +409,17 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
if (strlen(name) > 0)
{
// Can't compute the checksum if not in RAM
bool good = !bad && PowerPC::HostIsInstructionRAMAddress(guard, vaddress) &&
PowerPC::HostIsInstructionRAMAddress(guard, vaddress + size - 4);
bool good = !bad && PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress) &&
PowerPC::MMU::HostIsInstructionRAMAddress(guard, vaddress + size - 4);
if (!good)
{
// check for BLR before function
PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(vaddress - 4);
PowerPC::TryReadInstResult read_result =
guard.GetSystem().GetMMU().TryReadInstruction(vaddress - 4);
if (read_result.valid && read_result.hex == 0x4e800020)
{
// check for BLR at end of function
read_result = PowerPC::TryReadInstruction(vaddress + size - 4);
read_result = guard.GetSystem().GetMMU().TryReadInstruction(vaddress + size - 4);
good = read_result.valid && read_result.hex == 0x4e800020;
}
}
@@ -146,8 +146,10 @@ void DoState(PointerWrap& p)
}

RoundingModeUpdated();
IBATUpdated();
DBATUpdated();

auto& mmu = Core::System::GetInstance().GetMMU();
mmu.IBATUpdated();
mmu.DBATUpdated();
}

// SystemTimers::DecrementerSet();
@@ -202,8 +204,10 @@ static void ResetRegisters()
ppcState.SetXER({});

RoundingModeUpdated();
DBATUpdated();
IBATUpdated();

auto& mmu = Core::System::GetInstance().GetMMU();
mmu.DBATUpdated();
mmu.IBATUpdated();

TL(PowerPC::ppcState) = 0;
TU(PowerPC::ppcState) = 0;
@@ -108,8 +108,8 @@ bool Compare(const Core::CPUThreadGuard& guard, u32 address, u32 size, const MEG

for (size_t i = 0; i < sig.code.size(); ++i)
{
if (sig.code[i] != 0 &&
PowerPC::HostRead_U32(guard, static_cast<u32>(address + i * sizeof(u32))) != sig.code[i])
if (sig.code[i] != 0 && PowerPC::MMU::HostRead_U32(
guard, static_cast<u32>(address + i * sizeof(u32))) != sig.code[i])
{
return false;
}
@@ -166,7 +166,7 @@ u32 HashSignatureDB::ComputeCodeChecksum(const Core::CPUThreadGuard& guard, u32
u32 sum = 0;
for (u32 offset = offsetStart; offset <= offsetEnd; offset += 4)
{
u32 opcode = PowerPC::HostRead_Instruction(guard, offset);
u32 opcode = PowerPC::MMU::HostRead_Instruction(guard, offset);
u32 op = opcode & 0xFC000000;
u32 op2 = 0;
u32 op3 = 0;
@@ -40,8 +40,9 @@ struct System::Impl
explicit Impl(System& system)
: m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system),
m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system),
m_ppc_state(PowerPC::ppcState), m_processor_interface(system), m_serial_interface(system),
m_video_interface(system), m_interpreter(system, m_ppc_state), m_jit_interface(system)
m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state),
m_processor_interface(system), m_serial_interface(system), m_video_interface(system),
m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system)
{
}

@@ -67,6 +68,7 @@ struct System::Impl
PixelEngine::PixelEngineManager m_pixel_engine;
PixelShaderManager m_pixel_shader_manager;
PowerPC::PowerPCState& m_ppc_state;
PowerPC::MMU m_mmu;
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
SerialInterface::SerialInterfaceManager m_serial_interface;
Sram m_sram;
@@ -204,6 +206,11 @@ MemoryInterface::MemoryInterfaceManager& System::GetMemoryInterface() const
return m_impl->m_memory_interface;
}

PowerPC::MMU& System::GetMMU() const
{
return m_impl->m_mmu;
}

PixelEngine::PixelEngineManager& System::GetPixelEngine() const
{
return m_impl->m_pixel_engine;
@@ -72,8 +72,9 @@ class PixelEngineManager;
};
namespace PowerPC
{
class MMU;
struct PowerPCState;
}
} // namespace PowerPC
namespace ProcessorInterface
{
class ProcessorInterfaceManager;
@@ -138,6 +139,7 @@ class System
IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const;
Memory::MemoryManager& GetMemory() const;
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;
PowerPC::MMU& GetMMU() const;
PixelEngine::PixelEngineManager& GetPixelEngine() const;
PixelShaderManager& GetPixelShaderManager() const;
PowerPC::PowerPCState& GetPPCState() const;
@@ -502,7 +502,7 @@ static bool MemoryMatchesAt(const Core::CPUThreadGuard& guard, u32 offset,
{
for (u32 i = 0; i < value.size(); ++i)
{
auto result = PowerPC::HostTryReadU8(guard, offset + i);
auto result = PowerPC::MMU::HostTryReadU8(guard, offset + i);
if (!result || result->value != value[i])
return false;
}
@@ -521,7 +521,7 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset,
auto& system = Core::System::GetInstance();
const u32 size = static_cast<u32>(value.size());
for (u32 i = 0; i < size; ++i)
PowerPC::HostTryWriteU8(guard, value[i], offset + i);
PowerPC::MMU::HostTryWriteU8(guard, value[i], offset + i);
const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size);
if (overlapping_hook_count != 0)
{
@@ -585,13 +585,13 @@ static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Pat
{
// from the pattern find the next blr instruction
const u32 blr_address = ram_start + i;
auto blr = PowerPC::HostTryReadU32(guard, blr_address);
auto blr = PowerPC::MMU::HostTryReadU32(guard, blr_address);
if (blr && blr->value == 0x4e800020)
{
// and replace it with a jump to the given offset
const u32 target = memory_patch.m_offset | 0x80000000;
const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000;
PowerPC::HostTryWriteU32(guard, jmp, blr_address);
PowerPC::MMU::HostTryWriteU32(guard, jmp, blr_address);
const u32 overlapping_hook_count =
HLE::UnpatchRange(system, blr_address, blr_address + 4);
if (overlapping_hook_count != 0)
@@ -987,10 +987,11 @@ void CodeViewWidget::OnReplaceInstruction()

const u32 addr = GetContextAddress();

if (!PowerPC::HostIsInstructionRAMAddress(guard, addr))
if (!PowerPC::MMU::HostIsInstructionRAMAddress(guard, addr))
return;

const PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(addr);
const PowerPC::TryReadInstResult read_result =
guard.GetSystem().GetMMU().TryReadInstruction(addr);
if (!read_result.valid)
return;

@@ -463,7 +463,7 @@ void CodeWidget::StepOver()

const UGeckoInstruction inst = [&] {
Core::CPUThreadGuard guard(system);
return PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
return PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
}();

if (inst.LK)
@@ -516,7 +516,7 @@ void CodeWidget::StepOut()
// Loop until either the current instruction is a return instruction with no Link flag
// or a breakpoint is detected so it can step at the breakpoint. If the PC is currently
// on a breakpoint, skip it.
UGeckoInstruction inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
UGeckoInstruction inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
do
{
if (WillInstructionReturn(inst))
@@ -540,7 +540,7 @@ void CodeWidget::StepOut()
PowerPC::SingleStep();
}

inst = PowerPC::HostRead_Instruction(guard, PowerPC::ppcState.pc);
inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc);
} while (clock::now() < timeout &&
!PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc));

@@ -268,7 +268,8 @@ void ThreadWidget::Update()
return QStringLiteral("%1").arg(value, 8, 16, QLatin1Char('0'));
};
const auto format_hex_from = [&format_hex](const Core::CPUThreadGuard& guard, u32 addr) {
addr = PowerPC::HostIsRAMAddress(guard, addr) ? PowerPC::HostRead_U32(guard, addr) : 0;
addr =
PowerPC::MMU::HostIsRAMAddress(guard, addr) ? PowerPC::MMU::HostRead_U32(guard, addr) : 0;
return format_hex(addr);
};
const auto get_state = [](u16 thread_state) {
@@ -449,13 +450,13 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
u32 sp = context.gpr->at(1);
for (int i = 0; i < 16; i++)
{
if (sp == 0 || sp == 0xffffffff || !PowerPC::HostIsRAMAddress(guard, sp))
if (sp == 0 || sp == 0xffffffff || !PowerPC::MMU::HostIsRAMAddress(guard, sp))
break;
m_callstack_table->insertRow(i);
m_callstack_table->setItem(i, 0, new QTableWidgetItem(format_hex(sp)));
if (PowerPC::HostIsRAMAddress(guard, sp + 4))
if (PowerPC::MMU::HostIsRAMAddress(guard, sp + 4))
{
const u32 lr_save = PowerPC::HostRead_U32(guard, sp + 4);
const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4);
m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save)));
m_callstack_table->setItem(i, 3,
new QTableWidgetItem(QString::fromStdString(
@@ -465,7 +466,7 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
{
m_callstack_table->setItem(i, 2, new QTableWidgetItem(QStringLiteral("--------")));
}
sp = PowerPC::HostRead_U32(guard, sp);
sp = PowerPC::MMU::HostRead_U32(guard, sp);
m_callstack_table->setItem(i, 1, new QTableWidgetItem(format_hex(sp)));
}
}
@@ -193,18 +193,19 @@ void WatchWidget::Update()

QBrush brush = QPalette().brush(QPalette::Text);

if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(guard, entry.address))
if (!Core::IsRunning() || !PowerPC::MMU::HostIsRAMAddress(guard, entry.address))
brush.setColor(Qt::red);

if (Core::IsRunning())
{
if (PowerPC::HostIsRAMAddress(guard, entry.address))
if (PowerPC::MMU::HostIsRAMAddress(guard, entry.address))
{
hex->setText(QStringLiteral("%1").arg(PowerPC::HostRead_U32(guard, entry.address), 8, 16,
QLatin1Char('0')));
decimal->setText(QString::number(PowerPC::HostRead_U32(guard, entry.address)));
string->setText(QString::fromStdString(PowerPC::HostGetString(guard, entry.address, 32)));
floatValue->setText(QString::number(PowerPC::HostRead_F32(guard, entry.address)));
hex->setText(QStringLiteral("%1").arg(PowerPC::MMU::HostRead_U32(guard, entry.address), 8,
16, QLatin1Char('0')));
decimal->setText(QString::number(PowerPC::MMU::HostRead_U32(guard, entry.address)));
string->setText(
QString::fromStdString(PowerPC::MMU::HostGetString(guard, entry.address, 32)));
floatValue->setText(QString::number(PowerPC::MMU::HostRead_F32(guard, entry.address)));
lockValue->setCheckState(entry.locked ? Qt::Checked : Qt::Unchecked);
}
}
@@ -418,7 +419,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
}
else
{
PowerPC::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address);
PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address);
}
}
else
@@ -446,7 +447,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)

void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 address)
{
const std::string memory_data_as_string = PowerPC::HostGetString(guard, address, 4);
const std::string memory_data_as_string = PowerPC::MMU::HostGetString(guard, address, 4);

std::vector<u8> bytes;
for (const char c : memory_data_as_string)