diff --git a/src/backend/A64/a32_emit_a64.cpp b/src/backend/A64/a32_emit_a64.cpp index d9dbb03d..fccae1cf 100644 --- a/src/backend/A64/a32_emit_a64.cpp +++ b/src/backend/A64/a32_emit_a64.cpp @@ -164,12 +164,11 @@ void A32EmitA64::ClearCache() { void A32EmitA64::InvalidateCacheRanges(const boost::icl::interval_set& ranges) { InvalidateBasicBlocks(block_ranges.InvalidateRanges(ranges)); - ClearFastDispatchTable(); } void A32EmitA64::ClearFastDispatchTable() { if (config.enable_fast_dispatch) { - fast_dispatch_table.fill({0xFFFFFFFFFFFFFFFFull, nullptr}); + fast_dispatch_table.fill({}); } } @@ -327,6 +326,14 @@ void A32EmitA64::GenTerminalHandlers() { code.STR(INDEX_UNSIGNED, code.ABI_RETURN, fast_dispatch_entry_reg, offsetof(FastDispatchEntry, code_ptr)); code.BR(code.ABI_RETURN); PerfMapRegister(terminal_handler_fast_dispatch_hint, code.GetCodePtr(), "a32_terminal_handler_fast_dispatch_hint"); + + code.AlignCode16(); + fast_dispatch_table_lookup = reinterpret_cast(code.GetWritableCodePtr()); + code.MOVI2R(code.ABI_PARAM2, reinterpret_cast(fast_dispatch_table.data())); + code.CRC32CW(DecodeReg(code.ABI_PARAM1), DecodeReg(code.ABI_PARAM1), DecodeReg(code.ABI_PARAM2)); + code.ANDI2R(DecodeReg(code.ABI_PARAM1), DecodeReg(code.ABI_PARAM1), fast_dispatch_table_mask); + code.ADD(code.ABI_RETURN, code.ABI_PARAM1, code.ABI_PARAM2); + code.RET(); } } @@ -1551,4 +1558,11 @@ void A32EmitA64::EmitPatchMovX0(CodePtr target_code_ptr) { code.EnsurePatchLocationSize(patch_location, 16); } +void A32EmitA64::Unpatch(const IR::LocationDescriptor& location) { + EmitA64::Unpatch(location); + if (config.enable_fast_dispatch) { + (*fast_dispatch_table_lookup)(location.Value()) = {}; + } +} + } // namespace Dynarmic::BackendA64 diff --git a/src/backend/A64/a32_emit_a64.h b/src/backend/A64/a32_emit_a64.h index 99a4927a..320cb3d1 100644 --- a/src/backend/A64/a32_emit_a64.h +++ b/src/backend/A64/a32_emit_a64.h @@ -61,8 +61,8 @@ protected: ExceptionHandler exception_handler; struct FastDispatchEntry { - u64 location_descriptor; - const void* code_ptr; + u64 location_descriptor = 0xFFFF'FFFF'FFFF'FFFFull; + const void* code_ptr = nullptr; }; static_assert(sizeof(FastDispatchEntry) == 0x10); static constexpr u64 fast_dispatch_table_mask = 0xFFFF0; @@ -92,6 +92,7 @@ protected: const void* terminal_handler_pop_rsb_hint; const void* terminal_handler_fast_dispatch_hint = nullptr; + FastDispatchEntry& (*fast_dispatch_table_lookup)(u64) = nullptr; void GenTerminalHandlers(); // Microinstruction emitters @@ -125,6 +126,7 @@ protected: void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) override; // Patching + void Unpatch(const IR::LocationDescriptor& target_desc) override; void EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr = nullptr) override; void EmitPatchJmp(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr = nullptr) override; void EmitPatchMovX0(CodePtr target_code_ptr = nullptr) override; diff --git a/src/backend/A64/emit_a64.h b/src/backend/A64/emit_a64.h index 85386e57..d67e6967 100644 --- a/src/backend/A64/emit_a64.h +++ b/src/backend/A64/emit_a64.h @@ -111,7 +111,7 @@ protected: std::vector mov_x0; }; void Patch(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr); - void Unpatch(const IR::LocationDescriptor& target_desc); + virtual void Unpatch(const IR::LocationDescriptor& target_desc); virtual void EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr = nullptr) = 0; virtual void EmitPatchJmp(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr = nullptr) = 0; virtual void EmitPatchMovX0(CodePtr target_code_ptr = nullptr) = 0;