diff --git a/CMakeLists.txt b/CMakeLists.txt index 07ca01032..e831c0d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/shell/cmake") if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum macOS deployment version") + set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") endif() project(flycast) @@ -813,7 +814,7 @@ if(WIN32) target_link_libraries(${PROJECT_NAME} PRIVATE d3d9 d3dx9) endif() -if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)" AND NOT APPLE) target_include_directories(${PROJECT_NAME} PRIVATE core/deps/vixl) target_sources(${PROJECT_NAME} PRIVATE core/rec-ARM/rec_arm.cpp @@ -847,7 +848,9 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)") core/deps/vixl/pool-manager-impl.h core/deps/vixl/utils-vixl.cc core/deps/vixl/utils-vixl.h) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") + set(KNOWN_ARCHITECTURE_DETECTED ON) +endif() +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|arm64.*)" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64") target_include_directories(${PROJECT_NAME} PRIVATE core/deps/vixl) target_sources(${PROJECT_NAME} PRIVATE core/deps/vixl/aarch64/abi-aarch64.h @@ -892,7 +895,9 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") core/deps/vixl/utils-vixl.cc core/deps/vixl/utils-vixl.h) target_sources(${PROJECT_NAME} PRIVATE core/rec-ARM64/rec_arm64.cpp core/rec-ARM64/arm64_regalloc.h) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|x86_64.*|AMD64.*") + set(KNOWN_ARCHITECTURE_DETECTED ON) +endif() +if(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|x86_64.*|AMD64.*" OR CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") add_subdirectory(core/deps/xbyak) target_link_libraries(${PROJECT_NAME} PRIVATE xbyak::xbyak) if(CMAKE_SIZEOF_VOID_P EQUAL 4) @@ -908,7 +913,9 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|x86_64.*|AMD6 core/rec-x64/rec_x64.cpp core/rec-x64/x64_regalloc.h) endif() -else() + set(KNOWN_ARCHITECTURE_DETECTED ON) +endif() +if(NOT KNOWN_ARCHITECTURE_DETECTED) message(FATAL_ERROR "Unknown target processor: ${CMAKE_SYSTEM_PROCESSOR}") endif() diff --git a/core/deps/libchdr b/core/deps/libchdr index 00319cf31..d3ffd20ca 160000 --- a/core/deps/libchdr +++ b/core/deps/libchdr @@ -1 +1 @@ -Subproject commit 00319cf31f034e4d468a49a60265c7c5b8305b70 +Subproject commit d3ffd20ca71686877372dea7f9eed359dbf65ba2 diff --git a/core/hw/arm7/arm7_rec_arm64.cpp b/core/hw/arm7/arm7_rec_arm64.cpp index f95f04b0c..63218d08e 100644 --- a/core/hw/arm7/arm7_rec_arm64.cpp +++ b/core/hw/arm7/arm7_rec_arm64.cpp @@ -107,9 +107,17 @@ class Arm7Compiler : public MacroAssembler void call(void *loc) { ptrdiff_t offset = reinterpret_cast(loc) - GetBuffer()->GetStartAddress(); - Label function_label; - BindToOffset(&function_label, offset); - Bl(&function_label); + if (offset < -128 * 1024 * 1024 || offset > 128 * 1024 * 1024) + { + Mov(x4, reinterpret_cast(loc)); + Blr(x4); + } + else + { + Label function_label; + BindToOffset(&function_label, offset); + Bl(&function_label); + } } Operand getOperand(const ArmOp::Operand& arg, const Register& scratch_reg) @@ -543,6 +551,7 @@ public: void compile(const std::vector& block_ops, u32 cycles) { + JITWriteProtect(false); Ldr(w1, arm_reg_operand(CYCL_CNT)); Sub(w1, w1, cycles); Str(w1, arm_reg_operand(CYCL_CNT)); @@ -622,6 +631,7 @@ public: #endif delete regalloc; regalloc = nullptr; + JITWriteProtect(true); } void generateMainLoop() @@ -632,6 +642,7 @@ public: verify(arm_compilecode != nullptr); return; } + JITWriteProtect(false); Label arm_dispatch_label; Label arm_dofiq; Label arm_exit; @@ -686,6 +697,7 @@ public: GetBuffer()->GetStartAddress(), GetBuffer()->GetEndAddress(), GetBuffer()->GetStartAddress(), GetBuffer()->GetEndAddress()); recompiler::advance(GetBuffer()->GetSizeInBytes()); + JITWriteProtect(true); } }; diff --git a/core/hw/sh4/dyna/driver.cpp b/core/hw/sh4/dyna/driver.cpp index fbd301761..742fad34e 100644 --- a/core/hw/sh4/dyna/driver.cpp +++ b/core/hw/sh4/dyna/driver.cpp @@ -423,7 +423,6 @@ static void recSh4_Init() // Ensure the pointer returned is non-null verify(CodeCache != NULL); - memset(CodeCache, 0xFF, CODE_SIZE + TEMP_CODE_SIZE); TempCodeCache = CodeCache + CODE_SIZE; ngen_init(); bm_ResetCache(); diff --git a/core/linux/posix_vmem.cpp b/core/linux/posix_vmem.cpp index 65f916d0a..c6d39c0d4 100644 --- a/core/linux/posix_vmem.cpp +++ b/core/linux/posix_vmem.cpp @@ -249,11 +249,21 @@ bool vmem_platform_prepare_jit_block(void *code_area, unsigned size, void **code { // Well it failed, use another approach, unmap the memory area and remap it back. // Seems it works well on Darwin according to reicast code :P + #ifndef __ARM_MAC__ munmap(code_area, size); void *ret_ptr = mmap(code_area, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0); // Ensure it's the area we requested if (ret_ptr != code_area) return false; // Couldn't remap it? Perhaps RWX is disabled? This should never happen in any supported Unix platform. + #else + // MAP_JIT and toggleable write protection is required on Apple Silicon + // Cannot use MAP_FIXED with MAP_JIT + void *ret_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON | MAP_JIT, -1, 0); + if ( ret_ptr == MAP_FAILED ) + return false; + *code_area_rwx = ret_ptr; + return true; + #endif } // Pointer location should be same: diff --git a/core/rec-ARM64/rec_arm64.cpp b/core/rec-ARM64/rec_arm64.cpp index eff3d4efa..61d82f897 100644 --- a/core/rec-ARM64/rec_arm64.cpp +++ b/core/rec-ARM64/rec_arm64.cpp @@ -278,6 +278,7 @@ public: void ngen_Compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise) { //printf("REC-ARM64 compiling %08x\n", block->addr); + JITWriteProtect(false); this->block = block; CheckBlock(force_checks, block); @@ -959,6 +960,7 @@ public: RelinkBlock(block); Finalize(); + JITWriteProtect(true); } void ngen_CC_Start(shil_opcode* op) @@ -1518,11 +1520,18 @@ private: void GenCallRuntime(R (*function)(P...)) { ptrdiff_t offset = reinterpret_cast(function) - reinterpret_cast(CC_RW2RX(GetBuffer()->GetStartAddress())); - verify(offset >= -128 * 1024 * 1024 && offset <= 128 * 1024 * 1024); verify((offset & 3) == 0); - Label function_label; - BindToOffset(&function_label, offset); - Bl(&function_label); + if (offset < -128 * 1024 * 1024 || offset > 128 * 1024 * 1024) + { + Mov(x4, reinterpret_cast(function)); + Blr(x4); + } + else + { + Label function_label; + BindToOffset(&function_label, offset); + Bl(&function_label); + } } void GenCall(DynaCode *function) @@ -1539,14 +1548,34 @@ private: void GenBranchRuntime(R (*target)(P...), Condition cond = al) { ptrdiff_t offset = reinterpret_cast(target) - reinterpret_cast(CC_RW2RX(GetBuffer()->GetStartAddress())); - verify(offset >= -128 * 1024 * 1024 && offset <= 128 * 1024 * 1024); verify((offset & 3) == 0); - Label target_label; - BindToOffset(&target_label, offset); - if (cond == al) - B(&target_label); + if (offset < -128 * 1024 * 1024 || offset > 128 * 1024 * 1024) + { + if (cond == al) + { + Mov(x4, reinterpret_cast(target)); + Br(x4); + } + else + { + Label skip_target; + Condition inverse_cond = (Condition)((u32)cond ^ 1); + + B(&skip_target, inverse_cond); + Mov(x4, reinterpret_cast(target)); + Br(x4); + Bind(&skip_target); + } + } else - B(&target_label, cond); + { + Label target_label; + BindToOffset(&target_label, offset); + if (cond == al) + B(&target_label); + else + B(&target_label, cond); + } } void GenBranch(DynaCode *code, Condition cond = al) @@ -2116,8 +2145,8 @@ private: std::vector call_fregs; Arm64RegAlloc regalloc; RuntimeBlockInfo* block = NULL; - const int read_memory_rewrite_size = 3; // ubfx, add, ldr - const int write_memory_rewrite_size = 3; // ubfx, add, str + const int read_memory_rewrite_size = 5; // ubfx, add, ldr + const int write_memory_rewrite_size = 5; // ubfx, add, str }; static Arm64Assembler* compiler; @@ -2188,6 +2217,7 @@ static const u32 op_sizes[] = { }; bool ngen_Rewrite(host_context_t &context, void *faultAddress) { + JITWriteProtect(false); //LOGI("ngen_Rewrite pc %zx\n", context.pc); u32 *code_ptr = (u32 *)CC_RX2RW(context.pc); u32 armv8_op = *code_ptr; @@ -2219,6 +2249,7 @@ bool ngen_Rewrite(host_context_t &context, void *faultAddress) assembler->Finalize(true); delete assembler; context.pc = (unat)CC_RW2RX(code_rewrite); + JITWriteProtect(true); return true; } @@ -2227,12 +2258,14 @@ static void generate_mainloop() { if (mainloop != nullptr) return; + JITWriteProtect(false); compiler = new Arm64Assembler(); compiler->GenMainloop(); delete compiler; compiler = nullptr; + JITWriteProtect(true); } RuntimeBlockInfo* ngen_AllocateBlock() @@ -2250,11 +2283,13 @@ u32 DynaRBI::Relink() { #ifndef NO_BLOCK_LINKING //printf("DynaRBI::Relink %08x\n", this->addr); + JITWriteProtect(false); Arm64Assembler *compiler = new Arm64Assembler((u8 *)this->code + this->relink_offset); u32 code_size = compiler->RelinkBlock(this); compiler->Finalize(true); delete compiler; + JITWriteProtect(true); return code_size; #else diff --git a/core/stdclass.h b/core/stdclass.h index 5857f3965..28447c669 100644 --- a/core/stdclass.h +++ b/core/stdclass.h @@ -12,7 +12,11 @@ #undef PAGE_MASK #define PAGE_MASK (PAGE_SIZE-1) #else +#if defined(__APPLE__) && defined(__aarch64__) +#define PAGE_SIZE 16384 +#else #define PAGE_SIZE 4096 +#endif #define PAGE_MASK (PAGE_SIZE-1) #endif diff --git a/core/types.h b/core/types.h index 5bd0acd7c..70d35ebea 100644 --- a/core/types.h +++ b/core/types.h @@ -139,6 +139,14 @@ enum HollyInterruptID int darw_printf(const char* Text,...); #endif +#if defined(__APPLE__) && defined(__MACH__) && HOST_CPU == CPU_ARM64 + #define __ARM_MAC__ + #include "pthread.h" + static void JITWriteProtect(bool enabled) { if (__builtin_available(macOS 11.0, *)) pthread_jit_write_protect_np(enabled); } +#else + __forceinline static void JITWriteProtect(bool enabled) {} +#endif + //includes from c++rt #include #include diff --git a/shell/apple/emulator-osx/emulator-osx/DreamcastConfig.xcconfig b/shell/apple/emulator-osx/emulator-osx/DreamcastConfig.xcconfig index e5ebfd333..6a1970cca 100644 --- a/shell/apple/emulator-osx/emulator-osx/DreamcastConfig.xcconfig +++ b/shell/apple/emulator-osx/emulator-osx/DreamcastConfig.xcconfig @@ -7,5 +7,4 @@ REI_APP_NAME = Flycast PRODUCT_NAME = Flycast CFLAGS = - - +LIBSDL = /usr/local/lib/libSDL2.a diff --git a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj index ae65a5076..4d69afaf3 100644 --- a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj +++ b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj @@ -306,7 +306,6 @@ AEE6278822131BB500EC7E89 /* mapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6278522131BB500EC7E89 /* mapping.cpp */; }; AEE6278E2224762000EC7E89 /* imgui_impl_opengl3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6278B2224762000EC7E89 /* imgui_impl_opengl3.cpp */; }; AEE6279422247C0A00EC7E89 /* gui_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6279222247C0A00EC7E89 /* gui_util.cpp */; }; - AEE6279622247C2B00EC7E89 /* keyboard_device.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6279522247C2B00EC7E89 /* keyboard_device.cpp */; }; AEF25646227C442F00348550 /* fastmmu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEF25644227C442F00348550 /* fastmmu.cpp */; }; AEF2564822886A2E00348550 /* posix_vmem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEF2564722886A2E00348550 /* posix_vmem.cpp */; }; AEF256502294060400348550 /* ZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEF2564A2294060300348550 /* ZipArchive.cpp */; }; @@ -943,7 +942,6 @@ AEE6278D2224762000EC7E89 /* imgui_impl_opengl3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_opengl3.h; sourceTree = ""; }; AEE6279222247C0A00EC7E89 /* gui_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gui_util.cpp; sourceTree = ""; }; AEE6279322247C0A00EC7E89 /* gui_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gui_util.h; sourceTree = ""; }; - AEE6279522247C2B00EC7E89 /* keyboard_device.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyboard_device.cpp; sourceTree = ""; }; AEF25644227C442F00348550 /* fastmmu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fastmmu.cpp; sourceTree = ""; }; AEF25645227C442F00348550 /* wince.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wince.h; sourceTree = ""; }; AEF2564722886A2E00348550 /* posix_vmem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = posix_vmem.cpp; sourceTree = ""; }; @@ -1530,6 +1528,7 @@ 84B7BDCF1B72720100F9733F /* dsp.h */, AE8C27332111A31100D4D8F4 /* dsp_interp.cpp */, AE7BCB512406EDB0007285F8 /* dsp_x64.cpp */, + F2D7C89E265B304F002812E2 /* dsp_arm64.cpp */, 84B7BDD01B72720100F9733F /* sgc_if.cpp */, 84B7BDD11B72720100F9733F /* sgc_if.h */, ); @@ -1540,6 +1539,7 @@ isa = PBXGroup; children = ( AE7BCB562415515B007285F8 /* arm7_rec_x64.cpp */, + F2D7C8A2265B3082002812E2 /* arm7_rec_arm64.cpp */, AE7BCB572415515B007285F8 /* arm7_rec.cpp */, AE7BCB552415515B007285F8 /* arm7_rec.h */, 84B7BDD31B72720100F9733F /* arm-new.h */, @@ -2747,6 +2747,7 @@ 84B7BF2A1B72720200F9733F /* arm7.cpp in Sources */, AE90679D235DF80400CE473C /* osd.cpp in Sources */, AE82C67D25B64AE200C79BC2 /* zip_get_name.c in Sources */, + F2D7C8A3265B3082002812E2 /* arm7_rec_arm64.cpp in Sources */, 84B7BF551B72720200F9733F /* sh4_mem.cpp in Sources */, AE82C69F25B64AE200C79BC2 /* zip_open.c in Sources */, AE649C2C218C553A00EF4A81 /* Lzma86Enc.c in Sources */, @@ -2914,6 +2915,7 @@ 84B7BF771B72720200F9733F /* reios_elf.cpp in Sources */, AE9125CC25E3BBDC00ED4594 /* option.cpp in Sources */, 84B7BF5C1B72720200F9733F /* common.cpp in Sources */, + F2D7C89F265B304F002812E2 /* dsp_arm64.cpp in Sources */, AE82C6BE25B64AE200C79BC2 /* zip_source_crc.c in Sources */, 84B7BF681B72720200F9733F /* audiobackend_directsound.cpp in Sources */, AE2A2D5C21D68470004B308D /* awcartridge.cpp in Sources */, @@ -3165,7 +3167,7 @@ ); INFOPLIST_FILE = "emulator-osx/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - OTHER_LDFLAGS = /usr/local/lib/libSDL2.a; + OTHER_LDFLAGS = "$(LIBSDL)"; OTHER_LIBTOOLFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.flyinghead.Flycast; PRODUCT_NAME = "$(REI_APP_NAME)"; @@ -3217,7 +3219,7 @@ ); INFOPLIST_FILE = "emulator-osx/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - OTHER_LDFLAGS = /usr/local/lib/libSDL2.a; + OTHER_LDFLAGS = "$(LIBSDL)"; OTHER_LIBTOOLFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.flyinghead.Flycast; PRODUCT_NAME = "$(REI_APP_NAME)"; diff --git a/shell/apple/emulator-osx/reicast-osx.xcodeproj/xcshareddata/xcschemes/reicast-osx.xcscheme b/shell/apple/emulator-osx/reicast-osx.xcodeproj/xcshareddata/xcschemes/reicast-osx.xcscheme index 544fff583..2f483cec1 100644 --- a/shell/apple/emulator-osx/reicast-osx.xcodeproj/xcshareddata/xcschemes/reicast-osx.xcscheme +++ b/shell/apple/emulator-osx/reicast-osx.xcodeproj/xcshareddata/xcschemes/reicast-osx.xcscheme @@ -1,10 +1,28 @@ + version = "1.7"> + + + + + + + + + +