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 <cstddef>
 #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);
 }