From a03bca2f720766053ecbc83c62201eedd2c99ac9 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 21 Nov 2020 01:56:51 +1000 Subject: [PATCH] CPU: Make fastmem a compile-time feature (support 32-bit targets) --- src/core/CMakeLists.txt | 4 +- src/core/bus.cpp | 27 ++++++++- src/core/bus.h | 5 +- src/core/core.vcxproj | 16 +++--- src/core/cpu_code_cache.cpp | 26 ++++++++- src/core/cpu_core.cpp | 6 +- src/core/cpu_recompiler_code_generator.cpp | 6 ++ src/core/cpu_recompiler_code_generator.h | 4 ++ .../cpu_recompiler_code_generator_generic.cpp | 56 ++++++++++++++----- src/core/cpu_recompiler_thunks.h | 6 +- 10 files changed, 127 insertions(+), 29 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aaaaaa758..16b9075d1 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -115,13 +115,13 @@ endif() if(${CPU_ARCH} STREQUAL "x64") target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../dep/xbyak/xbyak") - target_compile_definitions(core PRIVATE "WITH_RECOMPILER=1") + target_compile_definitions(core PRIVATE "WITH_RECOMPILER=1 WITH_FASTMEM=1") target_sources(core PRIVATE ${RECOMPILER_SRCS} cpu_recompiler_code_generator_x64.cpp ) message("Building x64 recompiler") elseif(${CPU_ARCH} STREQUAL "aarch64") - target_compile_definitions(core PRIVATE "WITH_RECOMPILER=1") + target_compile_definitions(core PRIVATE "WITH_RECOMPILER=1 WITH_FASTMEM=1") target_sources(core PRIVATE ${RECOMPILER_SRCS} cpu_recompiler_code_generator_aarch64.cpp ) diff --git a/src/core/bus.cpp b/src/core/bus.cpp index aa01e9b05..6259d6876 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -87,15 +87,21 @@ static u32 m_ram_size_reg = 0; static std::string m_tty_line_buffer; static Common::MemoryArena m_memory_arena; + +#ifdef WITH_FASTMEM static u8* m_fastmem_base = nullptr; static std::vector m_fastmem_ram_views; +#endif static std::tuple CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay); static void RecalculateMemoryTimings(); -static void SetCodePageFastmemProtection(u32 page_index, bool writable); static bool AllocateMemory(); + +#ifdef WITH_FASTMEM +static void SetCodePageFastmemProtection(u32 page_index, bool writable); static void UnmapFastmemViews(); +#endif #define FIXUP_WORD_READ_OFFSET(offset) ((offset) & ~u32(3)) #define FIXUP_WORD_READ_VALUE(offset, value) ((value) >> (((offset)&u32(3)) * 8u)) @@ -126,7 +132,10 @@ bool Initialize() void Shutdown() { +#ifdef WITH_FASTMEM UnmapFastmemViews(); +#endif + if (g_ram) { m_memory_arena.ReleaseViewPtr(g_ram, RAM_SIZE); @@ -259,6 +268,8 @@ bool AllocateMemory() return true; } +#ifdef WITH_FASTMEM + void UnmapFastmemViews() { m_fastmem_ram_views.clear(); @@ -344,6 +355,8 @@ bool CanUseFastmemForAddress(VirtualMemoryAddress address) return (paddr < RAM_SIZE); } +#endif + bool IsRAMCodePage(u32 index) { return m_ram_code_bits[index]; @@ -356,7 +369,10 @@ void SetRAMCodePage(u32 index) // protect fastmem pages m_ram_code_bits[index] = true; + +#ifdef WITH_FASTMEM SetCodePageFastmemProtection(index, false); +#endif } void ClearRAMCodePage(u32 index) @@ -366,9 +382,14 @@ void ClearRAMCodePage(u32 index) // unprotect fastmem pages m_ram_code_bits[index] = false; + +#ifdef WITH_FASTMEM SetCodePageFastmemProtection(index, true); +#endif } +#ifdef WITH_FASTMEM + void SetCodePageFastmemProtection(u32 page_index, bool writable) { // unprotect fastmem pages @@ -383,10 +404,13 @@ void SetCodePageFastmemProtection(u32 page_index, bool writable) } } +#endif + void ClearRAMCodePageFlags() { m_ram_code_bits.reset(); +#ifdef WITH_FASTMEM // unprotect fastmem pages for (const auto& view : m_fastmem_ram_views) { @@ -395,6 +419,7 @@ void ClearRAMCodePageFlags() Log_ErrorPrintf("Failed to unprotect code pages for fastmem view @ %p", view.GetBasePointer()); } } +#endif } bool IsCodePageAddress(PhysicalMemoryAddress address) diff --git a/src/core/bus.h b/src/core/bus.h index 05982edd0..6f3cf94ea 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -82,8 +82,10 @@ enum : size_t // Offsets within the memory arena. MEMORY_ARENA_RAM_OFFSET = 0, +#ifdef WITH_FASTMEM // Fastmem region size is 4GB to cover the entire 32-bit address space. FASTMEM_REGION_SIZE = UINT64_C(0x100000000) +#endif }; bool Initialize(); @@ -91,9 +93,10 @@ void Shutdown(); void Reset(); bool DoState(StateWrapper& sw); -u8* GetFastmemBase(); +#ifdef WITH_FASTMEM void UpdateFastmemViews(bool enabled, bool isolate_cache); bool CanUseFastmemForAddress(VirtualMemoryAddress address); +#endif void SetExpansionROM(std::vector data); void SetBIOS(const std::vector& image); diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index c893774ce..3181a6a38 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -425,7 +425,7 @@ Level4 Disabled - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true ProgramDatabase $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) @@ -451,7 +451,7 @@ Level4 Disabled - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true ProgramDatabase $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\vixl\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) @@ -506,7 +506,7 @@ Level4 Disabled - WITH_IMGUI=1;WITH_RECOMPILER=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true ProgramDatabase $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) @@ -535,7 +535,7 @@ Level4 Disabled - WITH_IMGUI=1;WITH_RECOMPILER=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true ProgramDatabase $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\vixl\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) @@ -620,7 +620,7 @@ MaxSpeed true - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) true false @@ -647,7 +647,7 @@ MaxSpeed true - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\vixl\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) true false @@ -674,7 +674,7 @@ MaxSpeed true - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) true true @@ -702,7 +702,7 @@ MaxSpeed true - WITH_IMGUI=1;WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + WITH_IMGUI=1;WITH_RECOMPILER=1;WITH_FASTMEM=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\vixl\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) true true diff --git a/src/core/cpu_code_cache.cpp b/src/core/cpu_code_cache.cpp index 611bd18a8..6ee124125 100644 --- a/src/core/cpu_code_cache.cpp +++ b/src/core/cpu_code_cache.cpp @@ -99,10 +99,13 @@ static HostCodeMap s_host_code_map; static void AddBlockToHostCodeMap(CodeBlock* block); static void RemoveBlockFromHostCodeMap(CodeBlock* block); + +#ifdef WITH_FASTMEM static bool InitializeFastmem(); static void ShutdownFastmem(); static Common::PageFaultHandler::HandlerResult PageFaultHandler(void* exception_pc, void* fault_address, bool is_write); -#endif +#endif // WITH_FASTMEM +#endif // WITH_RECOMPILER void Initialize() { @@ -121,8 +124,10 @@ void Initialize() Panic("Failed to initialize code space"); } +#ifdef WITH_FASTMEM if (g_settings.IsUsingFastmem() && !InitializeFastmem()) Panic("Failed to initialize fastmem"); +#endif ResetFastMap(); CompileDispatcher(); @@ -150,7 +155,9 @@ void ClearState() void Shutdown() { ClearState(); +#ifdef WITH_FASTMEM ShutdownFastmem(); +#endif #ifdef WITH_RECOMPILER s_code_buffer.Destroy(); #endif @@ -326,7 +333,10 @@ void Reinitialize() #ifdef WITH_RECOMPILER +#ifdef WITH_FASTMEM ShutdownFastmem(); +#endif + s_code_buffer.Destroy(); if (g_settings.IsUsingRecompiler()) @@ -342,8 +352,10 @@ void Reinitialize() Panic("Failed to initialize code space"); } +#ifdef WITH_FASTMEM if (g_settings.IsUsingFastmem() && !InitializeFastmem()) Panic("Failed to initialize fastmem"); +#endif ResetFastMap(); CompileDispatcher(); @@ -354,8 +366,10 @@ void Reinitialize() void Flush() { ClearState(); +#ifdef WITH_RECOMPILER if (g_settings.IsUsingRecompiler()) CompileDispatcher(); +#endif } void LogCurrentState() @@ -437,7 +451,9 @@ bool RevalidateBlock(CodeBlock* block) return true; recompile: +#ifdef WITH_RECOMPILER RemoveBlockFromHostCodeMap(block); +#endif block->instructions.clear(); if (!CompileBlock(block)) @@ -447,8 +463,10 @@ recompile: return false; } +#ifdef WITH_RECOMPILER // re-add to page map again AddBlockToHostCodeMap(block); +#endif if (block->IsInRAM()) AddBlockToPageMap(block); @@ -713,6 +731,8 @@ void RemoveBlockFromHostCodeMap(CodeBlock* block) s_host_code_map.erase(hc_iter); } +#ifdef WITH_FASTMEM + bool InitializeFastmem() { if (!Common::PageFaultHandler::InstallHandler(&s_host_code_map, PageFaultHandler)) @@ -801,6 +821,8 @@ Common::PageFaultHandler::HandlerResult PageFaultHandler(void* exception_pc, voi return Common::PageFaultHandler::HandlerResult::ExecuteNextHandler; } -#endif +#endif // WITH_FASTMEM + +#endif // WITH_RECOMPILER } // namespace CPU::CodeCache diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index a44787544..440b06373 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -1600,11 +1600,15 @@ bool InterpretInstructionPGXP() return g_state.exception_raised; } +#ifdef WITH_FASTMEM + void UpdateFastmemMapping() { Bus::UpdateFastmemViews(true, g_state.cop0_regs.sr.Isc); } +#endif + } // namespace Recompiler::Thunks -} // namespace CPU \ No newline at end of file +} // namespace CPU diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index e2ab9bc9c..9b1986733 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -2202,6 +2202,7 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi) value = AndValues(value, Value::FromConstantU32(write_mask)); } +#ifdef WITH_FASTMEM // changing SR[Isc] needs to update fastmem views if (reg == Cop0Reg::SR && g_settings.cpu_fastmem) { @@ -2211,13 +2212,18 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi) EmitStoreCPUStructField(offset, value); EmitXor(old_value.host_reg, old_value.host_reg, value); EmitBranchIfBitClear(old_value.host_reg, RegSize_32, 16, &skip_fastmem_update); + m_register_cache.InhibitAllocation(); EmitFunctionCall(nullptr, &Thunks::UpdateFastmemMapping, m_register_cache.GetCPUPtr()); EmitBindLabel(&skip_fastmem_update); + m_register_cache.UninhibitAllocation(); } else { EmitStoreCPUStructField(offset, value); } +#else + EmitStoreCPUStructField(offset, value); +#endif } } diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index e90f1e0b7..9dd87c857 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -79,13 +79,17 @@ public: // Automatically generates an exception handler. Value EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec, RegSize size); +#ifdef WITH_FASTMEM void EmitLoadGuestRAMFastmem(const Value& address, RegSize size, Value& result); void EmitLoadGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result); +#endif void EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result, bool in_far_code); void EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec, const Value& value); +#ifdef WITH_FASTMEM void EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value); +#endif void EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value, bool in_far_code); diff --git a/src/core/cpu_recompiler_code_generator_generic.cpp b/src/core/cpu_recompiler_code_generator_generic.cpp index ce64e22f7..043ef7055 100644 --- a/src/core/cpu_recompiler_code_generator_generic.cpp +++ b/src/core/cpu_recompiler_code_generator_generic.cpp @@ -41,6 +41,8 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const { Value result = m_register_cache.AllocateScratch(size); +#ifdef WITH_FASTMEM + if (g_settings.IsUsingFastmem() && Bus::IsRAMAddress(static_cast(address.constant_value))) { // have to mask away the high bits for mirrors, since we don't map them in fastmem @@ -52,6 +54,12 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const EmitLoadGlobal(result.GetHostRegister(), size, ptr); } +#else + + EmitLoadGlobal(result.GetHostRegister(), size, ptr); + +#endif + m_delayed_cycles_add += read_ticks; return result; } @@ -59,6 +67,8 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const AddPendingCycles(true); +#ifdef WITH_FASTMEM + const bool use_fastmem = address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true; if (address_spec) { @@ -83,24 +93,35 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const EmitLoadGuestMemorySlowmem(cbi, address, size, result, false); } +#else + + Value result = m_register_cache.AllocateScratch(HostPointerSize); + m_register_cache.FlushCallerSavedGuestRegisters(true, true); + EmitLoadGuestMemorySlowmem(cbi, address, size, result, false); + +#endif + // Downcast to ignore upper 56/48/32 bits. This should be a noop. - switch (size) + if (result.size != size) { - case RegSize_8: - ConvertValueSizeInPlace(&result, RegSize_8, false); - break; + switch (size) + { + case RegSize_8: + ConvertValueSizeInPlace(&result, RegSize_8, false); + break; - case RegSize_16: - ConvertValueSizeInPlace(&result, RegSize_16, false); - break; + case RegSize_16: + ConvertValueSizeInPlace(&result, RegSize_16, false); + break; - case RegSize_32: - ConvertValueSizeInPlace(&result, RegSize_32, false); - break; + case RegSize_32: + ConvertValueSizeInPlace(&result, RegSize_32, false); + break; - default: - UnreachableCode(); - break; + default: + UnreachableCode(); + break; + } } return result; @@ -124,6 +145,8 @@ void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const AddPendingCycles(true); +#ifdef WITH_FASTMEM + const bool use_fastmem = address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true; if (address_spec) { @@ -146,6 +169,13 @@ void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const m_register_cache.FlushCallerSavedGuestRegisters(true, true); EmitStoreGuestMemorySlowmem(cbi, address, value, false); } + +#else + + m_register_cache.FlushCallerSavedGuestRegisters(true, true); + EmitStoreGuestMemorySlowmem(cbi, address, value, false); + +#endif } #ifndef CPU_X64 diff --git a/src/core/cpu_recompiler_thunks.h b/src/core/cpu_recompiler_thunks.h index b9f5ced77..aa9330e77 100644 --- a/src/core/cpu_recompiler_thunks.h +++ b/src/core/cpu_recompiler_thunks.h @@ -32,8 +32,12 @@ void UncheckedWriteMemoryByte(u32 address, u8 value); void UncheckedWriteMemoryHalfWord(u32 address, u16 value); void UncheckedWriteMemoryWord(u32 address, u32 value); +#ifdef WITH_FASTMEM + void UpdateFastmemMapping(); +#endif + } // namespace Recompiler::Thunks -} // namespace CPU \ No newline at end of file +} // namespace CPU