diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index d0ba5a42ed..0f195965ca 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -777,6 +777,14 @@ namespace FEXCore::Context { FEXCORE_PROFILE_SCOPED("CompileBlock"); auto Thread = Frame->Thread; +#ifdef _M_ARM_64EC + // If the target PC is EC code, mark it in the L2 and return straight to the dispatcher + // so it can handle the call/return. + if (Thread->LookupCache->CheckPageEC(GuestRIP)) { + return GuestRIP; + } +#endif + // Invalidate might take a unique lock on this, to guarantee that during invalidation no code gets compiled auto lk = GuardSignalDeferringSection(CodeInvalidationMutex, Thread); diff --git a/FEXCore/Source/Interface/Core/LookupCache.h b/FEXCore/Source/Interface/Core/LookupCache.h index d1f93aa033..c1b91ead61 100644 --- a/FEXCore/Source/Interface/Core/LookupCache.h +++ b/FEXCore/Source/Interface/Core/LookupCache.h @@ -13,6 +13,9 @@ #include #include #include +#ifdef _M_ARM_64EC +#include +#endif namespace FEXCore { @@ -68,6 +71,24 @@ class LookupCache { return 0; } +#ifdef _M_ARM_64EC + bool CheckPageEC(uint64_t Address) { + if (!RtlIsEcCode(Address)) { + return false; + } + + std::lock_guard lk(WriteLock); + + // Mark L2 entry for this page as EC by setting the LSB, this can then be + // checked by the dispatcher to see if it needs to perform a call/return to + // EC code. + const auto PageIndex = (Address & (VirtualMemSize -1)) >> 12; + const auto Pointers = reinterpret_cast(PagePointer); + Pointers[PageIndex] |= 1; + return true; + } +#endif + fextl::map> CodePages; // Appends Block {Address} to CodePages [Start, Start + Length)