diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp index 6eaa4fdfca..f5b00de3cc 100644 --- a/Source/Core/Common/Arm64Emitter.cpp +++ b/Source/Core/Common/Arm64Emitter.cpp @@ -271,8 +271,8 @@ bool IsImmLogical(uint64_t value, unsigned int width, unsigned int *n, unsigned void ARM64XEmitter::SetCodePtr(u8* ptr) { m_code = ptr; - m_startcode = m_code; - m_lastCacheFlushEnd = ptr; + if (!m_lastCacheFlushEnd) + m_lastCacheFlushEnd = ptr; } const u8* ARM64XEmitter::GetCodePtr() const @@ -315,6 +315,9 @@ void ARM64XEmitter::FlushIcache() void ARM64XEmitter::FlushIcacheSection(u8* start, u8* end) { + if (start == end) + return; + #if defined(IOS) // Header file says this is equivalent to: sys_icache_invalidate(start, end - start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); diff --git a/Source/Core/Common/Arm64Emitter.h b/Source/Core/Common/Arm64Emitter.h index 6939984308..c4ce6ab253 100644 --- a/Source/Core/Common/Arm64Emitter.h +++ b/Source/Core/Common/Arm64Emitter.h @@ -324,7 +324,6 @@ class ARM64XEmitter private: u8* m_code; - u8* m_startcode; u8* m_lastCacheFlushEnd; void EncodeCompareBranchInst(u32 op, ARM64Reg Rt, const void* ptr); @@ -365,14 +364,13 @@ protected: public: ARM64XEmitter() - : m_code(nullptr), m_startcode(nullptr), m_lastCacheFlushEnd(nullptr) + : m_code(nullptr), m_lastCacheFlushEnd(nullptr) { } ARM64XEmitter(u8* code_ptr) { m_code = code_ptr; m_lastCacheFlushEnd = code_ptr; - m_startcode = code_ptr; } virtual ~ARM64XEmitter() diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index c1bf82b05d..e346ea198e 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -17,6 +17,7 @@ using namespace Arm64Gen; void JitArm64::Init() { AllocCodeSpace(CODE_SIZE); + farcode.Init(SConfig::GetInstance().bMMU ? FARCODE_SIZE_MMU : FARCODE_SIZE); jo.enableBlocklink = true; jo.optimizeGatherPipe = true; UpdateMemoryOptions(); @@ -36,6 +37,7 @@ void JitArm64::Init() void JitArm64::ClearCache() { ClearCodeSpace(); + farcode.ClearCodeSpace(); blocks.Clear(); UpdateMemoryOptions(); } @@ -43,6 +45,7 @@ void JitArm64::ClearCache() void JitArm64::Shutdown() { FreeCodeSpace(); + farcode.Shutdown(); blocks.Shutdown(); asm_routines.Shutdown(); } @@ -276,7 +279,8 @@ void JitArm64::SingleStep() void JitArm64::Jit(u32) { - if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || SConfig::GetInstance().bJITNoBlockCache) + if (GetSpaceLeft() < 0x10000 || farcode.GetSpaceLeft() < 0x10000 || blocks.IsFull() || + SConfig::GetInstance().bJITNoBlockCache) { ClearCache(); } @@ -450,5 +454,6 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB b->originalSize = code_block.m_num_instructions; FlushIcache(); + farcode.FlushIcache(); return start; } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 6b2d0c3fe8..476af4c3d8 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -18,6 +18,15 @@ #define PPCSTATE_OFF(elem) (offsetof(PowerPC::PowerPCState, elem)) +// A place to throw blocks of code we don't want polluting the cache, e.g. rarely taken +// exception branches. +class FarCodeCacheArm64 : public Arm64Gen::ARM64CodeBlock +{ +public: + void Init(int size) { AllocCodeSpace(size); } + void Shutdown() { FreeCodeSpace(); } +}; + // Some asserts to make sure we will be able to load everything static_assert(PPCSTATE_OFF(spr[1023]) <= 16380, "LDR(32bit) can't reach the last SPR"); static_assert((PPCSTATE_OFF(ps[0][0]) % 8) == 0, "LDR(64bit VFP) requires FPRs to be 8 byte aligned"); @@ -185,6 +194,22 @@ private: ARM64FloatEmitter m_float_emit; + FarCodeCacheArm64 farcode; + u8* nearcode; // Backed up when we switch to far code. + + // Simple functions to switch between near and far code emitting + void SwitchToFarCode() + { + nearcode = GetWritableCodePtr(); + SetCodePtr(farcode.GetWritableCodePtr()); + } + + void SwitchToNearCode() + { + farcode.SetCodePtr(GetWritableCodePtr()); + SetCodePtr(nearcode); + } + // Dump a memory range of code void DumpCode(const u8* start, const u8* end);