diff --git a/externals/dynarmic b/externals/dynarmic index f343c5626..4110494ac 160000 --- a/externals/dynarmic +++ b/externals/dynarmic @@ -1 +1 @@ -Subproject commit f343c56268ef3f8fbed5bbc513fbc56430a47255 +Subproject commit 4110494ac4edc83f74c65834ab3ba6ddd166f42e diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 436425c83..e43ac5429 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -4,6 +4,7 @@ #pragma once +#include #include "common/common_types.h" #include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" @@ -33,6 +34,13 @@ public: /// Clear all instruction cache virtual void ClearInstructionCache() = 0; + /** + * Invalidate the code cache at a range of addresses. + * @param start_address The starting address of the range to invalidate. + * @param length The length (in bytes) of the range to invalidate. + */ + virtual void InvalidateCacheRange(u32 start_address, size_t length) = 0; + /// Notify CPU emulation that page tables have changed virtual void PageTableChanged() = 0; diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 1c99fc9b8..c318aa0f2 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -187,6 +187,10 @@ void ARM_Dynarmic::ClearInstructionCache() { } } +void ARM_Dynarmic::InvalidateCacheRange(u32 start_address, size_t length) { + jit->InvalidateCacheRange(start_address, length); +} + void ARM_Dynarmic::PageTableChanged() { current_page_table = Memory::GetCurrentPageTable(); diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index ffedfbc91..4c5ac7c53 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -41,6 +41,7 @@ public: void PrepareReschedule() override; void ClearInstructionCache() override; + void InvalidateCacheRange(u32 start_address, size_t length) override; void PageTableChanged() override; private: diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 7e0624e16..4f2e1b7a7 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -34,6 +34,10 @@ void ARM_DynCom::ClearInstructionCache() { trans_cache_buf_top = 0; } +void ARM_DynCom::InvalidateCacheRange(u32, size_t) { + ClearInstructionCache(); +} + void ARM_DynCom::PageTableChanged() { ClearInstructionCache(); } diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 3c6cc3bda..3c92b2547 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -19,6 +19,7 @@ public: void Step() override; void ClearInstructionCache() override; + void InvalidateCacheRange(u32 start_address, size_t length) override; void PageTableChanged() override; void SetPC(u32 pc) override; diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index f78545f37..acecceeb7 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp @@ -5,6 +5,8 @@ #include "common/alignment.h" #include "common/logging/log.h" #include "common/scope_exit.h" +#include "core/arm/arm_interface.h" +#include "core/core.h" #include "core/hle/service/ldr_ro/cro_helper.h" namespace Service { @@ -61,9 +63,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc case RelocationType::AbsoluteAddress: case RelocationType::AbsoluteAddress2: Memory::Write32(target_address, symbol_address + addend); + Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::RelativeAddress: Memory::Write32(target_address, symbol_address + addend - target_future_address); + Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::ThumbBranch: case RelocationType::ArmBranch: @@ -86,6 +90,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc case RelocationType::AbsoluteAddress2: case RelocationType::RelativeAddress: Memory::Write32(target_address, 0); + Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::ThumbBranch: case RelocationType::ArmBranch: diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 7255ea026..c500d69f1 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -439,7 +439,7 @@ static void LoadCRO(Interface* self, bool link_on_load_bug_fix) { } } - Core::CPU().ClearInstructionCache(); + Core::CPU().InvalidateCacheRange(cro_address, cro_size); LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), cro_address, cro_address + fix_size); @@ -535,7 +535,7 @@ static void UnloadCRO(Interface* self) { memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr); } - Core::CPU().ClearInstructionCache(); + Core::CPU().InvalidateCacheRange(cro_address, fixed_size); rb.Push(result); } @@ -588,7 +588,6 @@ static void LinkCRO(Interface* self) { } memory_synchronizer.SynchronizeOriginalMemory(); - Core::CPU().ClearInstructionCache(); rb.Push(result); } @@ -641,7 +640,6 @@ static void UnlinkCRO(Interface* self) { } memory_synchronizer.SynchronizeOriginalMemory(); - Core::CPU().ClearInstructionCache(); rb.Push(result); }