From ad315fd20dba17593f83f1d40bab95e5e6814883 Mon Sep 17 00:00:00 2001 From: Vitor Kiguchi Date: Wed, 28 Apr 2021 01:03:43 -0300 Subject: [PATCH] Attempt to implement changes necessary for JIT on Apple Silicon as described on https://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon --- src/backend/A64/block_of_code.cpp | 10 ++++++++++ src/backend/A64/emitter/a64_emitter.cpp | 6 ++++++ src/backend/A64/emitter/code_block.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/src/backend/A64/block_of_code.cpp b/src/backend/A64/block_of_code.cpp index fd370d7f..c27f66a1 100644 --- a/src/backend/A64/block_of_code.cpp +++ b/src/backend/A64/block_of_code.cpp @@ -20,6 +20,10 @@ #include #endif +#ifdef __APPLE__ +#include +#endif + namespace Dynarmic::BackendA64 { const Arm64Gen::ARM64Reg BlockOfCode::ABI_RETURN = Arm64Gen::ARM64Reg::X0; @@ -86,12 +90,18 @@ void BlockOfCode::EnableWriting() { #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT ProtectMemory(GetCodePtr(), TOTAL_CODE_SIZE, false); #endif +#ifdef __APPLE__ + pthread_jit_write_protect_np(false); +#endif } void BlockOfCode::DisableWriting() { #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT ProtectMemory(GetCodePtr(), TOTAL_CODE_SIZE, true); #endif +#ifdef __APPLE__ + pthread_jit_write_protect_np(true); +#endif } void BlockOfCode::ClearCache() { diff --git a/src/backend/A64/emitter/a64_emitter.cpp b/src/backend/A64/emitter/a64_emitter.cpp index 0718afb6..cfe905be 100644 --- a/src/backend/A64/emitter/a64_emitter.cpp +++ b/src/backend/A64/emitter/a64_emitter.cpp @@ -8,6 +8,10 @@ #include #include +#if defined(__APPLE__) +#include +#endif + #include "a64_emitter.h" #include "common/assert.h" #include "common/bit_util.h" @@ -366,6 +370,8 @@ void ARM64XEmitter::FlushIcacheSection(const u8* start, const u8* end) { // Header file says this is equivalent to: sys_icache_invalidate(start, end - // start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); +#elif defined(__APPLE__) + sys_icache_invalidate(const_cast(start), end - start); #else // Don't rely on GCC's __clear_cache implementation, as it caches // icache/dcache cache line sizes, that can vary between cores on diff --git a/src/backend/A64/emitter/code_block.h b/src/backend/A64/emitter/code_block.h index 5f1bfa91..26b0ebbc 100644 --- a/src/backend/A64/emitter/code_block.h +++ b/src/backend/A64/emitter/code_block.h @@ -56,8 +56,12 @@ public: total_region_size = size; #if defined(_WIN32) void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else +#if defined(__APPLE__) + void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0); #else void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); +#endif if (ptr == MAP_FAILED) ptr = nullptr;