From d5c99a5b48a6cce702a1aa1e2b105ffe558d9ac9 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 7 Aug 2015 22:08:57 -0500 Subject: [PATCH 1/4] Add support for a CodeBlock holding a child. This is required to make sure two code spaces are relatively close to one another. In this case I need the AArch64 JIT codespace and its farcode space to be within 128MB of one another for branches. --- Source/Core/Common/CodeBlock.h | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Source/Core/Common/CodeBlock.h b/Source/Core/Common/CodeBlock.h index 5699fc5385..865c4513ca 100644 --- a/Source/Core/Common/CodeBlock.h +++ b/Source/Core/Common/CodeBlock.h @@ -22,9 +22,19 @@ private: protected: u8 *region; size_t region_size; + size_t parent_region_size; + + bool m_has_child; + bool m_is_child; + CodeBlock* m_child; public: - CodeBlock() : region(nullptr), region_size(0) {} + CodeBlock() + : region(nullptr), region_size(0), parent_region_size(0), + m_has_child(false), m_is_child(false), m_child(nullptr) + { + } + virtual ~CodeBlock() { if (region) FreeCodeSpace(); } // Call this before you generate any code. @@ -49,6 +59,12 @@ public: FreeMemoryPages(region, region_size); region = nullptr; region_size = 0; + parent_region_size = 0; + if (m_has_child) + { + m_child->region = nullptr; + m_child->region_size = 0; + } } bool IsInSpace(u8 *ptr) const @@ -70,7 +86,7 @@ public: size_t GetSpaceLeft() const { - return region_size - (T::GetCodePtr() - region); + return (m_has_child ? parent_region_size : region_size) - (T::GetCodePtr() - region); } bool IsAlmostFull() const @@ -78,5 +94,16 @@ public: // This should be bigger than the biggest block ever. return GetSpaceLeft() < 0x10000; } + void AddChildCodeSpace(CodeBlock* child, size_t size) + { + _assert_msg_(DYNA_REC, !m_has_child, "Already have a child! Can't have another!"); + m_child = child; + m_has_child = true; + m_child->m_is_child = true; + u8* child_region = region + region_size - size; + m_child->region = child_region; + m_child->region_size = size; + m_child->ResetCodePtr(); + parent_region_size = region_size - size; + } }; - From bb39ba1f3a76136a850da505f1b411e6c142bc0b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 7 Aug 2015 22:11:38 -0500 Subject: [PATCH 2/4] [AArch64] Banish slowmem operations to farcode. This improves performance pretty much across the board for games. The increase in performance is mainly from removing some code from the main JIT blocks of code (pushing and popping millions of registers) and throwing them in farcode where it doesn't pollute the icache. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 13 +- Source/Core/Core/PowerPC/JitArm64/Jit.h | 36 ++- .../PowerPC/JitArm64/JitArm64_BackPatch.cpp | 247 ++++++++++-------- .../PowerPC/JitArm64/JitArm64_LoadStore.cpp | 29 +- .../JitArm64/JitArm64_LoadStoreFloating.cpp | 34 +-- 5 files changed, 197 insertions(+), 162 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 9836e0b70a..a4a6d62a83 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -14,10 +14,13 @@ using namespace Arm64Gen; +static const int AARCH64_FARCODE_SIZE = 1024 * 1024 * 16; + void JitArm64::Init() { - AllocCodeSpace(CODE_SIZE); - farcode.Init(SConfig::GetInstance().bMMU ? FARCODE_SIZE_MMU : FARCODE_SIZE); + size_t child_code_size = SConfig::GetInstance().bMMU ? FARCODE_SIZE_MMU : AARCH64_FARCODE_SIZE; + AllocCodeSpace(CODE_SIZE + child_code_size); + AddChildCodeSpace(&farcode, child_code_size); jo.enableBlocklink = true; jo.optimizeGatherPipe = true; UpdateMemoryOptions(); @@ -36,16 +39,18 @@ void JitArm64::Init() void JitArm64::ClearCache() { + m_fault_to_handler.clear(); + m_handler_to_loc.clear(); + + blocks.Clear(); ClearCodeSpace(); farcode.ClearCodeSpace(); - blocks.Clear(); UpdateMemoryOptions(); } void JitArm64::Shutdown() { FreeCodeSpace(); - farcode.Shutdown(); blocks.Shutdown(); asm_routines.Shutdown(); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 476af4c3d8..de784b8f61 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -18,15 +18,6 @@ #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"); @@ -184,6 +175,27 @@ public: void psq_st(UGeckoInstruction inst); private: + + struct SlowmemHandler + { + ARM64Reg dest_reg; + ARM64Reg addr_reg; + BitSet32 gprs; + BitSet32 fprs; + u32 flags; + bool operator< (const SlowmemHandler& rhs) const + { + return !(dest_reg == rhs.dest_reg && + addr_reg == rhs.addr_reg && + gprs == rhs.gprs && + fprs == rhs.fprs && + flags == rhs.flags); + } + }; + + // + std::map> m_fault_to_handler; + std::map m_handler_to_loc; Arm64GPRCache gpr; Arm64FPRCache fpr; @@ -194,7 +206,7 @@ private: ARM64FloatEmitter m_float_emit; - FarCodeCacheArm64 farcode; + Arm64Gen::ARM64CodeBlock farcode; u8* nearcode; // Backed up when we switch to far code. // Simple functions to switch between near and far code emitting @@ -219,7 +231,9 @@ private: // Backpatching routines bool DisasmLoadStore(const u8* ptr, u32* flags, Arm64Gen::ARM64Reg* reg); void InitBackpatch(); - u32 EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem, bool do_padding, Arm64Gen::ARM64Reg RS, Arm64Gen::ARM64Reg addr); + u32 EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, + Arm64Gen::ARM64Reg RS, Arm64Gen::ARM64Reg addr, + BitSet32 gprs_to_push = BitSet32(0), BitSet32 fprs_to_push = BitSet32(0)); // Loadstore routines void SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 offset, bool update); void SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp index 83605bb07f..303f180e7f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp @@ -127,10 +127,14 @@ bool JitArm64::DisasmLoadStore(const u8* ptr, u32* flags, ARM64Reg* reg) return false; } -u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem, bool do_padding, ARM64Reg RS, ARM64Reg addr) +u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, + ARM64Reg RS, ARM64Reg addr, + BitSet32 gprs_to_push, BitSet32 fprs_to_push) { + bool in_far_code = false; u32 trouble_offset = 0; - const u8* code_base = emit->GetCodePtr(); + const u8* trouble_location = nullptr; + const u8* code_base = GetCodePtr(); if (fastmem) { @@ -140,169 +144,199 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem, if (flags & BackPatchInfo::FLAG_STORE && flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) { - ARM64FloatEmitter float_emit(emit); if (flags & BackPatchInfo::FLAG_SIZE_F32) { - float_emit.FCVT(32, 64, D0, RS); - float_emit.REV32(8, D0, D0); - trouble_offset = (emit->GetCodePtr() - code_base) / 4; - float_emit.STR(32, INDEX_UNSIGNED, D0, addr, 0); + m_float_emit.FCVT(32, 64, D0, RS); + m_float_emit.REV32(8, D0, D0); + trouble_offset = (GetCodePtr() - code_base) / 4; + trouble_location = GetCodePtr(); + m_float_emit.STR(32, INDEX_UNSIGNED, D0, addr, 0); } else { - float_emit.REV64(8, Q0, RS); - trouble_offset = (emit->GetCodePtr() - code_base) / 4; - float_emit.STR(64, INDEX_UNSIGNED, Q0, addr, 0); + m_float_emit.REV64(8, Q0, RS); + trouble_offset = (GetCodePtr() - code_base) / 4; + trouble_location = GetCodePtr(); + m_float_emit.STR(64, INDEX_UNSIGNED, Q0, addr, 0); } } else if (flags & BackPatchInfo::FLAG_LOAD && flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) { - ARM64FloatEmitter float_emit(emit); - trouble_offset = (emit->GetCodePtr() - code_base) / 4; + trouble_offset = (GetCodePtr() - code_base) / 4; + trouble_location = GetCodePtr(); if (flags & BackPatchInfo::FLAG_SIZE_F32) { - float_emit.LD1R(32, EncodeRegToDouble(RS), addr); - float_emit.REV32(8, EncodeRegToDouble(RS), EncodeRegToDouble(RS)); - float_emit.FCVTL(64, EncodeRegToDouble(RS), EncodeRegToDouble(RS)); + m_float_emit.LD1R(32, EncodeRegToDouble(RS), addr); + m_float_emit.REV32(8, EncodeRegToDouble(RS), EncodeRegToDouble(RS)); + m_float_emit.FCVTL(64, EncodeRegToDouble(RS), EncodeRegToDouble(RS)); } else { - float_emit.LDR(64, INDEX_UNSIGNED, Q0, addr, 0); - float_emit.REV64(8, D0, D0); - float_emit.INS(64, RS, 0, Q0, 0); + m_float_emit.LDR(64, INDEX_UNSIGNED, Q0, addr, 0); + m_float_emit.REV64(8, D0, D0); + m_float_emit.INS(64, RS, 0, Q0, 0); } } else if (flags & BackPatchInfo::FLAG_STORE) { ARM64Reg temp = W0; if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->REV32(temp, RS); + REV32(temp, RS); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->REV16(temp, RS); + REV16(temp, RS); - trouble_offset = (emit->GetCodePtr() - code_base) / 4; + trouble_offset = (GetCodePtr() - code_base) / 4; + trouble_location = GetCodePtr(); if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->STR(INDEX_UNSIGNED, temp, addr, 0); + STR(INDEX_UNSIGNED, temp, addr, 0); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->STRH(INDEX_UNSIGNED, temp, addr, 0); + STRH(INDEX_UNSIGNED, temp, addr, 0); else - emit->STRB(INDEX_UNSIGNED, RS, addr, 0); + STRB(INDEX_UNSIGNED, RS, addr, 0); } else { - trouble_offset = (emit->GetCodePtr() - code_base) / 4; + trouble_offset = (GetCodePtr() - code_base) / 4; + trouble_location = GetCodePtr(); if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->LDR(INDEX_UNSIGNED, RS, addr, 0); + LDR(INDEX_UNSIGNED, RS, addr, 0); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->LDRH(INDEX_UNSIGNED, RS, addr, 0); + LDRH(INDEX_UNSIGNED, RS, addr, 0); else if (flags & BackPatchInfo::FLAG_SIZE_8) - emit->LDRB(INDEX_UNSIGNED, RS, addr, 0); + LDRB(INDEX_UNSIGNED, RS, addr, 0); if (!(flags & BackPatchInfo::FLAG_REVERSE)) { if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->REV32(RS, RS); + REV32(RS, RS); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->REV16(RS, RS); + REV16(RS, RS); } if (flags & BackPatchInfo::FLAG_EXTEND) - emit->SXTH(RS, RS); + SXTH(RS, RS); } } - else + + if (!fastmem || do_farcode) { - if (flags & BackPatchInfo::FLAG_STORE && - flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) + if (fastmem && do_farcode) { - ARM64FloatEmitter float_emit(emit); - if (flags & BackPatchInfo::FLAG_SIZE_F32) + SlowmemHandler handler; + handler.dest_reg = RS; + handler.addr_reg = addr; + handler.gprs = gprs_to_push; + handler.fprs = fprs_to_push; + handler.flags = flags; + + std::map::iterator handler_loc_iter; + handler_loc_iter = m_handler_to_loc.find(handler); + + if (handler_loc_iter == m_handler_to_loc.end()) { - float_emit.FCVT(32, 64, D0, RS); - float_emit.UMOV(32, W0, Q0, 0); - emit->MOVI2R(X30, (u64)&PowerPC::Write_U32); - emit->BLR(X30); + in_far_code = true; + SwitchToFarCode(); + const u8* handler_loc = GetCodePtr(); + m_handler_to_loc[handler] = handler_loc; + m_fault_to_handler[trouble_location] = std::make_pair(handler, handler_loc); } else { - emit->MOVI2R(X30, (u64)&PowerPC::Write_U64); - float_emit.UMOV(64, X0, RS, 0); - emit->BLR(X30); + const u8* handler_loc = handler_loc_iter->second; + m_fault_to_handler[trouble_location] = std::make_pair(handler, handler_loc); + return trouble_offset; + } + } + + ABI_PushRegisters(gprs_to_push); + m_float_emit.ABI_PushRegisters(fprs_to_push, X30); + + if (flags & BackPatchInfo::FLAG_STORE && + flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) + { + if (flags & BackPatchInfo::FLAG_SIZE_F32) + { + m_float_emit.FCVT(32, 64, D0, RS); + m_float_emit.UMOV(32, W0, Q0, 0); + MOVI2R(X30, (u64)&PowerPC::Write_U32); + BLR(X30); + } + else + { + MOVI2R(X30, (u64)&PowerPC::Write_U64); + m_float_emit.UMOV(64, X0, RS, 0); + BLR(X30); } } else if (flags & BackPatchInfo::FLAG_LOAD && flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) { - ARM64FloatEmitter float_emit(emit); if (flags & BackPatchInfo::FLAG_SIZE_F32) { - emit->MOVI2R(X30, (u64)&PowerPC::Read_U32); - emit->BLR(X30); - float_emit.DUP(32, RS, X0); - float_emit.FCVTL(64, RS, RS); + MOVI2R(X30, (u64)&PowerPC::Read_U32); + BLR(X30); + m_float_emit.DUP(32, RS, X0); + m_float_emit.FCVTL(64, RS, RS); } else { - emit->MOVI2R(X30, (u64)&PowerPC::Read_F64); - emit->BLR(X30); - float_emit.INS(64, RS, 0, X0); + MOVI2R(X30, (u64)&PowerPC::Read_F64); + BLR(X30); + m_float_emit.INS(64, RS, 0, X0); } } else if (flags & BackPatchInfo::FLAG_STORE) { - emit->MOV(W0, RS); + MOV(W0, RS); if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->MOVI2R(X30, (u64)&PowerPC::Write_U32); + MOVI2R(X30, (u64)&PowerPC::Write_U32); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->MOVI2R(X30, (u64)&PowerPC::Write_U16); + MOVI2R(X30, (u64)&PowerPC::Write_U16); else - emit->MOVI2R(X30, (u64)&PowerPC::Write_U8); + MOVI2R(X30, (u64)&PowerPC::Write_U8); - emit->BLR(X30); + BLR(X30); } else { if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->MOVI2R(X30, (u64)&PowerPC::Read_U32); + MOVI2R(X30, (u64)&PowerPC::Read_U32); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->MOVI2R(X30, (u64)&PowerPC::Read_U16); + MOVI2R(X30, (u64)&PowerPC::Read_U16); else if (flags & BackPatchInfo::FLAG_SIZE_8) - emit->MOVI2R(X30, (u64)&PowerPC::Read_U8); + MOVI2R(X30, (u64)&PowerPC::Read_U8); - emit->BLR(X30); + BLR(X30); if (!(flags & BackPatchInfo::FLAG_REVERSE)) { - emit->MOV(RS, W0); + MOV(RS, W0); } else { if (flags & BackPatchInfo::FLAG_SIZE_32) - emit->REV32(RS, W0); + REV32(RS, W0); else if (flags & BackPatchInfo::FLAG_SIZE_16) - emit->REV16(RS, W0); + REV16(RS, W0); } if (flags & BackPatchInfo::FLAG_EXTEND) - emit->SXTH(RS, RS); + SXTH(RS, RS); } + + m_float_emit.ABI_PopRegisters(fprs_to_push, X30); + ABI_PopRegisters(gprs_to_push); } - if (do_padding) + if (in_far_code) { - BackPatchInfo& info = m_backpatch_info[flags]; - u32 num_insts_max = std::max(info.m_fastmem_size, info.m_slowmem_size); - - u32 code_size = emit->GetCodePtr() - code_base; - code_size /= 4; - - for (u32 i = 0; i < (num_insts_max - code_size); ++i) - emit->HINT(HINT_NOP); + RET(X30); + SwitchToNearCode(); } return trouble_offset; @@ -338,13 +372,22 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) return false; } + std::map>::iterator slow_handler_iter = m_fault_to_handler.find((const u8*)ctx->CTX_PC); + BackPatchInfo& info = m_backpatch_info[flags]; ARM64XEmitter emitter((u8*)(ctx->CTX_PC - info.m_fastmem_trouble_inst_offset * 4)); u64 new_pc = (u64)emitter.GetCodePtr(); - // Slowmem routine doesn't need the address location - // It is already in the correct location - EmitBackpatchRoutine(&emitter, flags, false, true, reg, INVALID_REG); + { + u32 num_insts_max = info.m_fastmem_size - 1; + + for (u32 i = 0; i < num_insts_max; ++i) + emitter.HINT(HINT_NOP); + + emitter.BL(slow_handler_iter->second.second); + + m_fault_to_handler.erase(slow_handler_iter); + } emitter.FlushIcache(); ctx->CTX_PC = new_pc; @@ -372,14 +415,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_8; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -392,14 +435,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_16; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -412,14 +455,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_32; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -433,14 +476,14 @@ void JitArm64::InitBackpatch() BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_16 | BackPatchInfo::FLAG_EXTEND; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -454,14 +497,14 @@ void JitArm64::InitBackpatch() BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_16 | BackPatchInfo::FLAG_REVERSE; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -475,14 +518,14 @@ void JitArm64::InitBackpatch() BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_32 | BackPatchInfo::FLAG_REVERSE; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -495,14 +538,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_F32; - EmitBackpatchRoutine(this, flags, false, false, Q0, X1); + EmitBackpatchRoutine(flags, false, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, Q0, X1); + EmitBackpatchRoutine(flags, true, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -515,14 +558,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_LOAD | BackPatchInfo::FLAG_SIZE_F64; - EmitBackpatchRoutine(this, flags, false, false, Q0, X1); + EmitBackpatchRoutine(flags, false, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, Q0, X1); + EmitBackpatchRoutine(flags, true, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -539,14 +582,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_SIZE_8; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -559,14 +602,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_SIZE_16; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -579,14 +622,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_SIZE_32; - EmitBackpatchRoutine(this, flags, false, false, W0, X1); + EmitBackpatchRoutine(flags, false, false, W0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, W0, X1); + EmitBackpatchRoutine(flags, true, false, W0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -599,14 +642,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_SIZE_F32; - EmitBackpatchRoutine(this, flags, false, false, Q0, X1); + EmitBackpatchRoutine(flags, false, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, Q0, X1); + EmitBackpatchRoutine(flags, true, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; @@ -619,14 +662,14 @@ void JitArm64::InitBackpatch() flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_SIZE_F64; - EmitBackpatchRoutine(this, flags, false, false, Q0, X1); + EmitBackpatchRoutine(flags, false, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_slowmem_size = (code_end - code_base) / 4; SetCodePtr(code_base); info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(this, flags, true, false, Q0, X1); + EmitBackpatchRoutine(flags, true, false, Q0, X1); code_end = GetWritableCodePtr(); info.m_fastmem_size = (code_end - code_base) / 4; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index 133ff3e936..ef810edaa1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -37,7 +37,6 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o BitSet32 regs_in_use = gpr.GetCallerSavedUsed(); BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); regs_in_use[W0] = 0; - regs_in_use[W30] = 0; regs_in_use[dest_reg] = 0; ARM64Reg addr_reg = W0; @@ -148,7 +147,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) { - EmitBackpatchRoutine(this, flags, true, false, dest_reg, XA); + EmitBackpatchRoutine(flags, true, false, dest_reg, XA, BitSet32(0), BitSet32(0)); } else if (mmio_address) { @@ -158,16 +157,11 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o } else { - // Has a chance of being backpatched which will destroy our state - // push and pop everything in this instance - ABI_PushRegisters(regs_in_use); - m_float_emit.ABI_PushRegisters(fprs_in_use, X30); - EmitBackpatchRoutine(this, flags, + EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, - dest_reg, XA); - m_float_emit.ABI_PopRegisters(fprs_in_use, X30); - ABI_PopRegisters(regs_in_use); + dest_reg, XA, + regs_in_use, fprs_in_use); } gpr.Unlock(W0, W30); @@ -192,7 +186,6 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); regs_in_use[W0] = 0; regs_in_use[W1] = 0; - regs_in_use[W30] = 0; ARM64Reg addr_reg = W1; @@ -296,7 +289,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s { MOVI2R(XA, imm_addr); - EmitBackpatchRoutine(this, flags, true, false, RS, XA); + EmitBackpatchRoutine(flags, true, false, RS, XA, BitSet32(0), BitSet32(0)); } else if (mmio_address && !(flags & BackPatchInfo::FLAG_REVERSE)) { @@ -309,16 +302,12 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s if (is_immediate) MOVI2R(XA, imm_addr); - // Has a chance of being backpatched which will destroy our state - // push and pop everything in this instance - ABI_PushRegisters(regs_in_use); - m_float_emit.ABI_PushRegisters(fprs_in_use, X30); - EmitBackpatchRoutine(this, flags, + EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, - RS, XA); - m_float_emit.ABI_PopRegisters(fprs_in_use, X30); - ABI_PopRegisters(regs_in_use); + RS, XA, + regs_in_use, + fprs_in_use); } gpr.Unlock(W0, W1, W30); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp index da79ce823b..414b16650f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp @@ -183,26 +183,20 @@ void JitArm64::lfXX(UGeckoInstruction inst) BitSet32 regs_in_use = gpr.GetCallerSavedUsed(); BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); regs_in_use[W0] = 0; - regs_in_use[W30] = 0; fprs_in_use[0] = 0; // Q0 fprs_in_use[VD - Q0] = 0; if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) { - EmitBackpatchRoutine(this, flags, true, false, VD, XA); + EmitBackpatchRoutine(flags, true, false, VD, XA, BitSet32(0), BitSet32(0)); } else { - // Has a chance of being backpatched which will destroy our state - // push and pop everything in this instance - ABI_PushRegisters(regs_in_use); - m_float_emit.ABI_PushRegisters(fprs_in_use, X30); - EmitBackpatchRoutine(this, flags, + EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, - VD, XA); - m_float_emit.ABI_PopRegisters(fprs_in_use, X30); - ABI_PopRegisters(regs_in_use); + VD, XA, + regs_in_use, fprs_in_use); } gpr.Unlock(W0, W30); @@ -383,7 +377,6 @@ void JitArm64::stfXX(UGeckoInstruction inst) BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); regs_in_use[W0] = 0; regs_in_use[W1] = 0; - regs_in_use[W30] = 0; fprs_in_use[0] = 0; // Q0 if (is_immediate) @@ -437,29 +430,20 @@ void JitArm64::stfXX(UGeckoInstruction inst) } else if (PowerPC::IsOptimizableRAMAddress(imm_addr)) { - EmitBackpatchRoutine(this, flags, true, false, V0, XA); + EmitBackpatchRoutine(flags, true, false, V0, XA, BitSet32(0), BitSet32(0)); } else { - ABI_PushRegisters(regs_in_use); - m_float_emit.ABI_PushRegisters(fprs_in_use, X30); - EmitBackpatchRoutine(this, flags, false, false, V0, XA); - m_float_emit.ABI_PopRegisters(fprs_in_use, X30); - ABI_PopRegisters(regs_in_use); + EmitBackpatchRoutine(flags, false, false, V0, XA, regs_in_use, fprs_in_use); } } else { - // Has a chance of being backpatched which will destroy our state - // push and pop everything in this instance - ABI_PushRegisters(regs_in_use); - m_float_emit.ABI_PushRegisters(fprs_in_use, X30); - EmitBackpatchRoutine(this, flags, + EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, - V0, XA); - m_float_emit.ABI_PopRegisters(fprs_in_use, X30); - ABI_PopRegisters(regs_in_use); + V0, XA, + regs_in_use, fprs_in_use); } gpr.Unlock(W0, W1, W30); fpr.Unlock(Q0); From 878f919f63c335e62866ad05c660adc721943292 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 14 Aug 2015 15:38:50 +0200 Subject: [PATCH 3/4] JitArm64: Fastmem: fixup map & lookup --- Source/Core/Common/BitSet.h | 2 ++ Source/Core/Core/PowerPC/JitArm64/Jit.h | 17 ++++++++++++----- .../PowerPC/JitArm64/JitArm64_BackPatch.cpp | 3 +++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/Core/Common/BitSet.h b/Source/Core/Common/BitSet.h index 70b9204fa5..caa59c150f 100644 --- a/Source/Core/Common/BitSet.h +++ b/Source/Core/Common/BitSet.h @@ -155,6 +155,8 @@ public: const Ref operator[](size_t bit) const { return (*const_cast(this))[bit]; } bool operator==(BitSet other) const { return m_val == other.m_val; } bool operator!=(BitSet other) const { return m_val != other.m_val; } + bool operator<(BitSet other) const { return m_val < other.m_val; } + bool operator>(BitSet other) const { return m_val > other.m_val; } BitSet operator|(BitSet other) const { return BitSet(m_val | other.m_val); } BitSet operator&(BitSet other) const { return BitSet(m_val & other.m_val); } BitSet operator^(BitSet other) const { return BitSet(m_val ^ other.m_val); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index de784b8f61..6271589ed2 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -185,11 +185,18 @@ private: u32 flags; bool operator< (const SlowmemHandler& rhs) const { - return !(dest_reg == rhs.dest_reg && - addr_reg == rhs.addr_reg && - gprs == rhs.gprs && - fprs == rhs.fprs && - flags == rhs.flags); + if (dest_reg < rhs.dest_reg) return true; + if (dest_reg > rhs.dest_reg) return false; + if (addr_reg < rhs.addr_reg) return true; + if (addr_reg > rhs.addr_reg) return false; + if (gprs < rhs.gprs) return true; + if (gprs > rhs.gprs) return false; + if (fprs < rhs.fprs) return true; + if (fprs > rhs.fprs) return false; + if (flags < rhs.flags) return true; + if (flags > rhs.flags) return false; + + return false; } }; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp index 303f180e7f..e0b8ada73f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp @@ -374,6 +374,9 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) std::map>::iterator slow_handler_iter = m_fault_to_handler.find((const u8*)ctx->CTX_PC); + if (slow_handler_iter == m_fault_to_handler.end()) + return false; + BackPatchInfo& info = m_backpatch_info[flags]; ARM64XEmitter emitter((u8*)(ctx->CTX_PC - info.m_fastmem_trouble_inst_offset * 4)); u64 new_pc = (u64)emitter.GetCodePtr(); From 715802d5aa096fad957f0b2fadac3d1b829fe7d6 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 14 Aug 2015 17:02:12 +0200 Subject: [PATCH 4/4] JitArm64: Move all pointers into the map And cleanup all of the old code for sharing and generating this pointers. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 1 - Source/Core/Core/PowerPC/JitArm64/Jit.h | 14 +- .../PowerPC/JitArm64/JitArm64_BackPatch.cpp | 338 ++---------------- .../Core/PowerPC/JitArmCommon/BackPatch.h | 4 - 4 files changed, 31 insertions(+), 326 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index a4a6d62a83..f9d80d396c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -33,7 +33,6 @@ void JitArm64::Init() code_block.m_stats = &js.st; code_block.m_gpa = &js.gpa; code_block.m_fpa = &js.fpa; - InitBackpatch(); analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 6271589ed2..7199fb38e4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -200,8 +200,14 @@ private: } }; + struct FastmemArea + { + u32 length; + const u8* slowmem_code; + }; + // - std::map> m_fault_to_handler; + std::map m_fault_to_handler; std::map m_handler_to_loc; Arm64GPRCache gpr; Arm64FPRCache fpr; @@ -232,13 +238,9 @@ private: // Dump a memory range of code void DumpCode(const u8* start, const u8* end); - // The key is the backpatch flags - std::map m_backpatch_info; - // Backpatching routines bool DisasmLoadStore(const u8* ptr, u32* flags, Arm64Gen::ARM64Reg* reg); - void InitBackpatch(); - u32 EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, + void EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, Arm64Gen::ARM64Reg RS, Arm64Gen::ARM64Reg addr, BitSet32 gprs_to_push = BitSet32(0), BitSet32 fprs_to_push = BitSet32(0)); // Loadstore routines diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp index e0b8ada73f..a71944479c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp @@ -127,14 +127,12 @@ bool JitArm64::DisasmLoadStore(const u8* ptr, u32* flags, ARM64Reg* reg) return false; } -u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, +void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, ARM64Reg RS, ARM64Reg addr, BitSet32 gprs_to_push, BitSet32 fprs_to_push) { bool in_far_code = false; - u32 trouble_offset = 0; - const u8* trouble_location = nullptr; - const u8* code_base = GetCodePtr(); + const u8* fastmem_start = GetCodePtr(); if (fastmem) { @@ -148,23 +146,17 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, { m_float_emit.FCVT(32, 64, D0, RS); m_float_emit.REV32(8, D0, D0); - trouble_offset = (GetCodePtr() - code_base) / 4; - trouble_location = GetCodePtr(); m_float_emit.STR(32, INDEX_UNSIGNED, D0, addr, 0); } else { m_float_emit.REV64(8, Q0, RS); - trouble_offset = (GetCodePtr() - code_base) / 4; - trouble_location = GetCodePtr(); m_float_emit.STR(64, INDEX_UNSIGNED, Q0, addr, 0); } } else if (flags & BackPatchInfo::FLAG_LOAD && flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64)) { - trouble_offset = (GetCodePtr() - code_base) / 4; - trouble_location = GetCodePtr(); if (flags & BackPatchInfo::FLAG_SIZE_F32) { m_float_emit.LD1R(32, EncodeRegToDouble(RS), addr); @@ -186,9 +178,6 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, else if (flags & BackPatchInfo::FLAG_SIZE_16) REV16(temp, RS); - trouble_offset = (GetCodePtr() - code_base) / 4; - trouble_location = GetCodePtr(); - if (flags & BackPatchInfo::FLAG_SIZE_32) STR(INDEX_UNSIGNED, temp, addr, 0); else if (flags & BackPatchInfo::FLAG_SIZE_16) @@ -198,9 +187,6 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, } else { - trouble_offset = (GetCodePtr() - code_base) / 4; - trouble_location = GetCodePtr(); - if (flags & BackPatchInfo::FLAG_SIZE_32) LDR(INDEX_UNSIGNED, RS, addr, 0); else if (flags & BackPatchInfo::FLAG_SIZE_16) @@ -220,6 +206,7 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, SXTH(RS, RS); } } + const u8* fastmem_end = GetCodePtr(); if (!fastmem || do_farcode) { @@ -232,8 +219,8 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, handler.fprs = fprs_to_push; handler.flags = flags; - std::map::iterator handler_loc_iter; - handler_loc_iter = m_handler_to_loc.find(handler); + FastmemArea* fastmem_area = &m_fault_to_handler[fastmem_start]; + auto handler_loc_iter = m_handler_to_loc.find(handler); if (handler_loc_iter == m_handler_to_loc.end()) { @@ -241,13 +228,15 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, SwitchToFarCode(); const u8* handler_loc = GetCodePtr(); m_handler_to_loc[handler] = handler_loc; - m_fault_to_handler[trouble_location] = std::make_pair(handler, handler_loc); + fastmem_area->slowmem_code = handler_loc; + fastmem_area->length = fastmem_end - fastmem_start; } else { const u8* handler_loc = handler_loc_iter->second; - m_fault_to_handler[trouble_location] = std::make_pair(handler, handler_loc); - return trouble_offset; + fastmem_area->slowmem_code = handler_loc; + fastmem_area->length = fastmem_end - fastmem_start; + return; } } @@ -338,8 +327,6 @@ u32 JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, RET(X30); SwitchToNearCode(); } - - return trouble_offset; } bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) @@ -372,28 +359,29 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) return false; } - std::map>::iterator slow_handler_iter = m_fault_to_handler.find((const u8*)ctx->CTX_PC); + auto slow_handler_iter = m_fault_to_handler.upper_bound((const u8*)ctx->CTX_PC); + slow_handler_iter--; + // no fastmem area found if (slow_handler_iter == m_fault_to_handler.end()) return false; - BackPatchInfo& info = m_backpatch_info[flags]; - ARM64XEmitter emitter((u8*)(ctx->CTX_PC - info.m_fastmem_trouble_inst_offset * 4)); - u64 new_pc = (u64)emitter.GetCodePtr(); + // no overlapping fastmem area found + if ((const u8*)ctx->CTX_PC - slow_handler_iter->first > slow_handler_iter->second.length) + return false; - { - u32 num_insts_max = info.m_fastmem_size - 1; + ARM64XEmitter emitter((u8*) slow_handler_iter->first); - for (u32 i = 0; i < num_insts_max; ++i) - emitter.HINT(HINT_NOP); + emitter.BL(slow_handler_iter->second.slowmem_code); - emitter.BL(slow_handler_iter->second.second); + u32 num_insts_max = slow_handler_iter->second.length / 4 - 1; + for (u32 i = 0; i < num_insts_max; ++i) + emitter.HINT(HINT_NOP); - m_fault_to_handler.erase(slow_handler_iter); - } + m_fault_to_handler.erase(slow_handler_iter); emitter.FlushIcache(); - ctx->CTX_PC = new_pc; + ctx->CTX_PC = (u64)slow_handler_iter->first; // Wipe the top bits of the addr_register if (flags & BackPatchInfo::FLAG_STORE && @@ -403,283 +391,3 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) ctx->CTX_REG(0) &= 0xFFFFFFFFUll; return true; } - -void JitArm64::InitBackpatch() -{ - u32 flags = 0; - BackPatchInfo info; - u8* code_base = GetWritableCodePtr(); - u8* code_end; - - // Loads - { - // 8bit - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_8; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 16bit - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_16; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 32bit - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_32; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 16bit - Extend - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_16 | - BackPatchInfo::FLAG_EXTEND; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 16bit - Reverse - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_16 | - BackPatchInfo::FLAG_REVERSE; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 32bit - Reverse - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_32 | - BackPatchInfo::FLAG_REVERSE; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 32bit float - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_F32; - EmitBackpatchRoutine(flags, false, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 64bit float - { - flags = - BackPatchInfo::FLAG_LOAD | - BackPatchInfo::FLAG_SIZE_F64; - EmitBackpatchRoutine(flags, false, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - } - - // Stores - { - // 8bit - { - flags = - BackPatchInfo::FLAG_STORE | - BackPatchInfo::FLAG_SIZE_8; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 16bit - { - flags = - BackPatchInfo::FLAG_STORE | - BackPatchInfo::FLAG_SIZE_16; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 32bit - { - flags = - BackPatchInfo::FLAG_STORE | - BackPatchInfo::FLAG_SIZE_32; - EmitBackpatchRoutine(flags, false, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, W0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 32bit float - { - flags = - BackPatchInfo::FLAG_STORE | - BackPatchInfo::FLAG_SIZE_F32; - EmitBackpatchRoutine(flags, false, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - // 64bit float - { - flags = - BackPatchInfo::FLAG_STORE | - BackPatchInfo::FLAG_SIZE_F64; - EmitBackpatchRoutine(flags, false, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_slowmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - info.m_fastmem_trouble_inst_offset = - EmitBackpatchRoutine(flags, true, false, Q0, X1); - code_end = GetWritableCodePtr(); - info.m_fastmem_size = (code_end - code_base) / 4; - - SetCodePtr(code_base); - - m_backpatch_info[flags] = info; - } - } -} - diff --git a/Source/Core/Core/PowerPC/JitArmCommon/BackPatch.h b/Source/Core/Core/PowerPC/JitArmCommon/BackPatch.h index 369854a621..fc8f96ad26 100644 --- a/Source/Core/Core/PowerPC/JitArmCommon/BackPatch.h +++ b/Source/Core/Core/PowerPC/JitArmCommon/BackPatch.h @@ -34,8 +34,4 @@ struct BackPatchInfo return 64; return 0; } - - u32 m_fastmem_size; - u32 m_fastmem_trouble_inst_offset; - u32 m_slowmem_size; };