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;
}
auto MapRAM = [](u32 base_address) {
auto MapRAM = [](u32 base_address, bool writable) {
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)
{
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)
{
// KUSEG - cached
MapRAM(0x00000000);
//MapRAM(0x00200000);
//MapRAM(0x00400000);
//MapRAM(0x00600000);
MapRAM(0x00000000, !isolate_cache);
//MapRAM(0x00200000, !isolate_cache);
//MapRAM(0x00400000, !isolate_cache);
//MapRAM(0x00600000, !isolate_cache);
// KSEG0 - cached
MapRAM(0x80000000);
//MapRAM(0x80200000);
//MapRAM(0x80400000);
//MapRAM(0x80600000);
MapRAM(0x80000000, !isolate_cache);
//MapRAM(0x80200000, !isolate_cache);
//MapRAM(0x80400000, !isolate_cache);
//MapRAM(0x80600000, !isolate_cache);
}
// KSEG1 - uncached
MapRAM(0xA0000000);
//MapRAM(0xA0200000);
//MapRAM(0xA0400000);
//MapRAM(0xA0600000);
MapRAM(0xA0000000, true);
//MapRAM(0xA0200000, true);
//MapRAM(0xA0400000, true);
//MapRAM(0xA0600000, true);
}
bool CanUseFastmemForAddress(VirtualMemoryAddress address)

View File

@ -79,6 +79,7 @@ public:
// Automatically generates an exception handler.
Value EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec,
RegSize size);
void EmitLoadGuestRAMFastmem(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,
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,
Value& result)
{

View File

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