diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 425303b28..5edb10c7c 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -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) diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index 576f3556c..e90f1e0b7 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -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); diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index a815c4b4f..f51ae9b65 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -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) { diff --git a/src/core/cpu_recompiler_code_generator_generic.cpp b/src/core/cpu_recompiler_code_generator_generic.cpp index 6246184c8..2d4e1128f 100644 --- a/src/core/cpu_recompiler_code_generator_generic.cpp +++ b/src/core/cpu_recompiler_code_generator_generic.cpp @@ -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(address.constant_value))) + EmitLoadGuestRAMFastmem(address, size, result); + else + EmitLoadGlobal(result.GetHostRegister(), size, ptr); + m_delayed_cycles_add += read_ticks; return result; } diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index 83410b070..6b26bf13a 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -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) {