CPU/Recompiler: Use fastmem instead of global for RAM loads

This commit is contained in:
Connor McLaughlin 2020-10-18 21:03:22 +10:00
parent 622aee7c96
commit 6a4a4c62d7
5 changed files with 115 additions and 16 deletions

View File

@ -284,9 +284,9 @@ void UpdateFastmemViews(bool enabled, bool isolate_cache)
CPU::g_state.fastmem_base = m_fastmem_base; CPU::g_state.fastmem_base = m_fastmem_base;
} }
auto MapRAM = [](u32 base_address) { auto MapRAM = [](u32 base_address, bool writable) {
u8* map_address = m_fastmem_base + base_address; u8* map_address = m_fastmem_base + base_address;
auto view = m_memory_arena.CreateView(MEMORY_ARENA_RAM_OFFSET, RAM_SIZE, true, false, map_address); auto view = m_memory_arena.CreateView(MEMORY_ARENA_RAM_OFFSET, RAM_SIZE, writable, false, map_address);
if (!view) if (!view)
{ {
Log_ErrorPrintf("Failed to map RAM at fastmem area %p (offset 0x%08X)", map_address, RAM_SIZE); Log_ErrorPrintf("Failed to map RAM at fastmem area %p (offset 0x%08X)", map_address, RAM_SIZE);
@ -313,23 +313,23 @@ void UpdateFastmemViews(bool enabled, bool isolate_cache)
if (!isolate_cache) if (!isolate_cache)
{ {
// KUSEG - cached // KUSEG - cached
MapRAM(0x00000000); MapRAM(0x00000000, !isolate_cache);
//MapRAM(0x00200000); //MapRAM(0x00200000, !isolate_cache);
//MapRAM(0x00400000); //MapRAM(0x00400000, !isolate_cache);
//MapRAM(0x00600000); //MapRAM(0x00600000, !isolate_cache);
// KSEG0 - cached // KSEG0 - cached
MapRAM(0x80000000); MapRAM(0x80000000, !isolate_cache);
//MapRAM(0x80200000); //MapRAM(0x80200000, !isolate_cache);
//MapRAM(0x80400000); //MapRAM(0x80400000, !isolate_cache);
//MapRAM(0x80600000); //MapRAM(0x80600000, !isolate_cache);
} }
// KSEG1 - uncached // KSEG1 - uncached
MapRAM(0xA0000000); MapRAM(0xA0000000, true);
//MapRAM(0xA0200000); //MapRAM(0xA0200000, true);
//MapRAM(0xA0400000); //MapRAM(0xA0400000, true);
//MapRAM(0xA0600000); //MapRAM(0xA0600000, true);
} }
bool CanUseFastmemForAddress(VirtualMemoryAddress address) bool CanUseFastmemForAddress(VirtualMemoryAddress address)

View File

@ -79,6 +79,7 @@ public:
// Automatically generates an exception handler. // Automatically generates an exception handler.
Value EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec, Value EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec,
RegSize size); RegSize size);
void EmitLoadGuestRAMFastmem(const Value& address, RegSize size, Value& result);
void EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result); void EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result);
void EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result, void EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result,
bool in_far_code); bool in_far_code);

View File

@ -1281,6 +1281,39 @@ void CodeGenerator::EmitAddCPUStructField(u32 offset, const Value& value)
} }
} }
void CodeGenerator::EmitLoadGuestRAMFastmem(const Value& address, RegSize size, Value& result)
{
a64::MemOperand actual_address;
if (address.IsConstant())
{
m_emit->Mov(GetHostReg32(result.host_reg), address.constant_value);
actual_address = a64::MemOperand(GetFastmemBasePtrReg(), GetHostReg32(result.host_reg));
}
else
{
actual_address = a64::MemOperand(GetFastmemBasePtrReg(), GetHostReg32(address));
}
switch (size)
{
case RegSize_8:
m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_16:
m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_32:
m_emit->Ldr(GetHostReg32(result.host_reg), actual_address);
break;
default:
UnreachableCode();
break;
}
}
void CodeGenerator::EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, void CodeGenerator::EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size,
Value& result) Value& result)
{ {

View File

@ -1,8 +1,8 @@
#include "common/log.h"
#include "cpu_core.h" #include "cpu_core.h"
#include "cpu_core_private.h" #include "cpu_core_private.h"
#include "cpu_recompiler_code_generator.h" #include "cpu_recompiler_code_generator.h"
#include "settings.h" #include "settings.h"
#include "common/log.h"
Log_SetChannel(Recompiler::CodeGenerator); Log_SetChannel(Recompiler::CodeGenerator);
namespace CPU::Recompiler { namespace CPU::Recompiler {
@ -40,7 +40,12 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const
if (ptr) if (ptr)
{ {
Value result = m_register_cache.AllocateScratch(size); Value result = m_register_cache.AllocateScratch(size);
if (g_settings.IsUsingFastmem() && Bus::IsRAMAddress(static_cast<u32>(address.constant_value)))
EmitLoadGuestRAMFastmem(address, size, result);
else
EmitLoadGlobal(result.GetHostRegister(), size, ptr); EmitLoadGlobal(result.GetHostRegister(), size, ptr);
m_delayed_cycles_add += read_ticks; m_delayed_cycles_add += read_ticks;
return result; return result;
} }

View File

@ -1745,6 +1745,66 @@ void CodeGenerator::EmitAddCPUStructField(u32 offset, const Value& value)
} }
} }
void CodeGenerator::EmitLoadGuestRAMFastmem(const Value& address, RegSize size, Value& result)
{
// can't store displacements > 0x80000000 in-line
const Value* actual_address = &address;
if (address.IsConstant() && address.constant_value >= 0x80000000)
{
actual_address = &result;
m_emit->mov(GetHostReg32(result.host_reg), address.constant_value);
}
// TODO: movsx/zx inline here
switch (size)
{
case RegSize_8:
{
if (actual_address->IsConstant())
{
m_emit->mov(GetHostReg8(result.host_reg),
m_emit->byte[GetFastmemBasePtrReg() + actual_address->constant_value]);
}
else
{
m_emit->mov(GetHostReg8(result.host_reg),
m_emit->byte[GetFastmemBasePtrReg() + GetHostReg64(actual_address->host_reg)]);
}
}
break;
case RegSize_16:
{
if (actual_address->IsConstant())
{
m_emit->mov(GetHostReg16(result.host_reg),
m_emit->word[GetFastmemBasePtrReg() + actual_address->constant_value]);
}
else
{
m_emit->mov(GetHostReg16(result.host_reg),
m_emit->word[GetFastmemBasePtrReg() + GetHostReg64(actual_address->host_reg)]);
}
}
break;
case RegSize_32:
{
if (actual_address->IsConstant())
{
m_emit->mov(GetHostReg32(result.host_reg),
m_emit->dword[GetFastmemBasePtrReg() + actual_address->constant_value]);
}
else
{
m_emit->mov(GetHostReg32(result.host_reg),
m_emit->dword[GetFastmemBasePtrReg() + GetHostReg64(actual_address->host_reg)]);
}
}
break;
}
}
void CodeGenerator::EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, void CodeGenerator::EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size,
Value& result) Value& result)
{ {