From dcd036d261b258444d8fb4707af4af6b14fc3b69 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:21:38 -0700 Subject: [PATCH] build: Get compiling on ARM64 again (#4598) --- CMakeLists.txt | 10 ++- src/common/signal_context.cpp | 69 ++------------- src/common/va_ctx.h | 9 +- src/core/cpu_patches.cpp | 88 +++++++++++++++---- src/core/file_sys/devices/base_device.h | 5 +- src/core/file_sys/devices/rng_device.cpp | 3 +- .../file_sys/directories/base_directory.h | 2 - src/core/libraries/audio/openal_audio_out.cpp | 4 +- .../libraries/kernel/threads/exception.cpp | 5 ++ src/core/libraries/kernel/threads/mutex.cpp | 5 ++ src/core/libraries/kernel/threads/pthread.cpp | 6 ++ src/core/libraries/libs.cpp | 5 +- src/core/linker.cpp | 6 +- src/core/thread.cpp | 5 ++ .../passes/flatten_extended_userdata_pass.cpp | 28 +++++- 15 files changed, 151 insertions(+), 99 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61927681b..094e6fda0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -337,7 +337,6 @@ set(KERNEL_LIB src/core/libraries/kernel/coredump/coredump.cpp src/core/libraries/kernel/threads/sleepq.cpp src/core/libraries/kernel/threads/sleepq.h src/core/libraries/kernel/threads/stack.cpp - src/core/libraries/kernel/threads/stack.S src/core/libraries/kernel/threads/tcb.cpp src/core/libraries/kernel/threads/pthread.h src/core/libraries/kernel/threads/thread_state.cpp @@ -364,7 +363,10 @@ set(KERNEL_LIB src/core/libraries/kernel/coredump/coredump.cpp src/core/libraries/kernel/aio.h ) -set_source_files_properties(src/core/libraries/kernel/threads/stack.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument) +if (ARCHITECTURE STREQUAL "x86_64") + list(APPEND KERNEL_LIB src/core/libraries/kernel/threads/stack.S) + set_source_files_properties(src/core/libraries/kernel/threads/stack.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument) +endif() set(NETWORK_LIBS src/core/libraries/network/http.cpp src/core/libraries/network/http.h @@ -888,7 +890,6 @@ set(CORE src/core/aerolib/stubs.cpp ${ZLIB_LIB} ${MISC_LIBS} ${IME_LIB} - ${FIBER_LIB} ${VDEC_LIB} ${VR_LIBS} ${CAMERA_LIBS} @@ -924,7 +925,8 @@ set(CORE src/core/aerolib/stubs.cpp if (ARCHITECTURE STREQUAL "x86_64") set(CORE ${CORE} src/core/cpu_patches.cpp - src/core/cpu_patches.h) + src/core/cpu_patches.h + ${FIBER_LIB}) endif() set(SHADER_RECOMPILER src/shader_recompiler/profile.h diff --git a/src/common/signal_context.cpp b/src/common/signal_context.cpp index b1ac8d96f..67d8294f4 100644 --- a/src/common/signal_context.cpp +++ b/src/common/signal_context.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/arch.h" -#include "common/assert.h" #include "common/signal_context.h" #ifdef _WIN32 @@ -16,76 +15,19 @@ namespace Common { -void* GetXmmPointer(void* ctx, u8 index) { -#if defined(_WIN32) -#define CASE(index) \ - case index: \ - return (void*)(&((EXCEPTION_POINTERS*)ctx)->ContextRecord->Xmm##index.Low) -#elif defined(__APPLE__) -#define CASE(index) \ - case index: \ - return (void*)(&((ucontext_t*)ctx)->uc_mcontext->__fs.__fpu_xmm##index); -#elif defined(__FreeBSD__) - // In mc_fpstate - // See for the internals of mc_fpstate[]. -#define CASE(index) \ - case index: { \ - auto& mctx = ((ucontext_t*)ctx)->uc_mcontext; \ - ASSERT(mctx.mc_fpformat == _MC_FPFMT_XMM); \ - auto* s_fpu = (struct savefpu*)(&mctx.mc_fpstate[0]); \ - return (void*)(&(s_fpu->sv_xmm[0])); \ - } -#else -#define CASE(index) \ - case index: \ - return (void*)(&((ucontext_t*)ctx)->uc_mcontext.fpregs->_xmm[index].element[0]) -#endif - switch (index) { - CASE(0); - CASE(1); - CASE(2); - CASE(3); - CASE(4); - CASE(5); - CASE(6); - CASE(7); - CASE(8); - CASE(9); - CASE(10); - CASE(11); - CASE(12); - CASE(13); - CASE(14); - CASE(15); - default: { - UNREACHABLE_MSG("Invalid XMM register index: {}", index); - return nullptr; - } - } -#undef CASE -} - void* GetRip(void* ctx) { #if defined(_WIN32) return (void*)((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip; -#elif defined(__APPLE__) +#elif defined(__APPLE__) && defined(ARCH_X86_64) return (void*)((ucontext_t*)ctx)->uc_mcontext->__ss.__rip; +#elif defined(__APPLE__) && defined(ARCH_ARM64) + return (void*)((ucontext_t*)ctx)->uc_mcontext->__ss.__pc; #elif defined(__FreeBSD__) return (void*)((ucontext_t*)ctx)->uc_mcontext.mc_rip; -#else +#elif defined(ARCH_X86_64) return (void*)((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP]; -#endif -} - -void IncrementRip(void* ctx, u64 length) { -#if defined(_WIN32) - ((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip += length; -#elif defined(__APPLE__) - ((ucontext_t*)ctx)->uc_mcontext->__ss.__rip += length; -#elif defined(__FreeBSD__) - ((ucontext_t*)ctx)->uc_mcontext.mc_rip += length; #else - ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP] += length; +#error "Unsupported architecture" #endif } @@ -104,4 +46,5 @@ bool IsWriteError(void* ctx) { #error "Unsupported architecture" #endif } + } // namespace Common diff --git a/src/common/va_ctx.h b/src/common/va_ctx.h index cffe468ff..ed2deedf1 100644 --- a/src/common/va_ctx.h +++ b/src/common/va_ctx.h @@ -2,9 +2,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include +#include "common/arch.h" #include "common/types.h" +#ifdef ARCH_X86_64 +#include +#else +// FIXME +typedef __int128 __m128; +#endif + #define VA_ARGS \ uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \ uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \ diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index d31985775..01bcbee02 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -22,7 +22,11 @@ #ifdef _WIN32 #include #else +#if defined(__FreeBSD__) +#include +#endif #include +#include #endif using namespace Xbyak::util; @@ -590,8 +594,6 @@ static std::pair TryPatch(u8* code, PatchModule* module) { return std::make_pair(false, instruction.length); } -#if defined(ARCH_X86_64) - static bool Is4ByteExtrqOrInsertq(void* code_address) { u8* bytes = (u8*)code_address; if (bytes[0] == 0x66 && bytes[1] == 0x0F && bytes[2] == 0x79) { @@ -603,6 +605,67 @@ static bool Is4ByteExtrqOrInsertq(void* code_address) { } } +static void* GetXmmPointer(void* ctx, u8 index) { +#if defined(_WIN32) +#define CASE(index) \ + case index: \ + return (void*)(&((EXCEPTION_POINTERS*)ctx)->ContextRecord->Xmm##index.Low) +#elif defined(__APPLE__) +#define CASE(index) \ + case index: \ + return (void*)(&((ucontext_t*)ctx)->uc_mcontext->__fs.__fpu_xmm##index); +#elif defined(__FreeBSD__) + // In mc_fpstate + // See for the internals of mc_fpstate[]. +#define CASE(index) \ + case index: { \ + auto& mctx = ((ucontext_t*)ctx)->uc_mcontext; \ + ASSERT(mctx.mc_fpformat == _MC_FPFMT_XMM); \ + auto* s_fpu = (struct savefpu*)(&mctx.mc_fpstate[0]); \ + return (void*)(&(s_fpu->sv_xmm[0])); \ + } +#else +#define CASE(index) \ + case index: \ + return (void*)(&((ucontext_t*)ctx)->uc_mcontext.fpregs->_xmm[index].element[0]) +#endif + switch (index) { + CASE(0); + CASE(1); + CASE(2); + CASE(3); + CASE(4); + CASE(5); + CASE(6); + CASE(7); + CASE(8); + CASE(9); + CASE(10); + CASE(11); + CASE(12); + CASE(13); + CASE(14); + CASE(15); + default: { + UNREACHABLE_MSG("Invalid XMM register index: {}", index); + return nullptr; + } + } +#undef CASE +} + +static void IncrementRip(void* ctx, u64 length) { +#if defined(_WIN32) + ((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip += length; +#elif defined(__APPLE__) + ((ucontext_t*)ctx)->uc_mcontext->__ss.__rip += length; +#elif defined(__FreeBSD__) + ((ucontext_t*)ctx)->uc_mcontext.mc_rip += length; +#else + ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP] += length; +#endif +} + static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { // We need to decode the instruction to find out what it is. Normally we'd use a fully fleshed // out decoder like Zydis, however Zydis does a bunch of stuff that impact performance that we @@ -644,8 +707,8 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { switch (mnemonic) { case ZYDIS_MNEMONIC_EXTRQ: { - const auto dst = Common::GetXmmPointer(ctx, dstIndex); - const auto src = Common::GetXmmPointer(ctx, srcIndex); + const auto dst = GetXmmPointer(ctx, dstIndex); + const auto src = GetXmmPointer(ctx, srcIndex); u64 lowQWordSrc; memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc)); @@ -678,13 +741,13 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { memset((u8*)dst + sizeof(u64), 0, sizeof(u64)); memcpy(dst, &lowQWordDst, sizeof(lowQWordDst)); - Common::IncrementRip(ctx, 4); + IncrementRip(ctx, 4); return true; } case ZYDIS_MNEMONIC_INSERTQ: { - const auto dst = Common::GetXmmPointer(ctx, dstIndex); - const auto src = Common::GetXmmPointer(ctx, srcIndex); + const auto dst = GetXmmPointer(ctx, dstIndex); + const auto src = GetXmmPointer(ctx, srcIndex); u64 lowQWordSrc, highQWordSrc; memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc)); @@ -719,7 +782,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { memset((u8*)dst + sizeof(u64), 0, sizeof(u64)); memcpy(dst, &lowQWordDst, sizeof(lowQWordDst)); - Common::IncrementRip(ctx, 4); + IncrementRip(ctx, 4); return true; } @@ -730,15 +793,6 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { UNREACHABLE(); } -#elif defined(ARCH_ARM64) -// These functions shouldn't be needed for ARM as it will use a JIT so there's no need to patch -// instructions. -static bool TryExecuteIllegalInstruction(void*, void*) { - return false; -} -#else -#error "Unsupported architecture" -#endif static bool TryPatchJit(void* code_address) { auto* code = static_cast(code_address); diff --git a/src/core/file_sys/devices/base_device.h b/src/core/file_sys/devices/base_device.h index 27baab4ba..b79c59566 100644 --- a/src/core/file_sys/devices/base_device.h +++ b/src/core/file_sys/devices/base_device.h @@ -4,9 +4,12 @@ #pragma once #include "common/types.h" -#include "common/va_ctx.h" #include "core/libraries/kernel/orbis_error.h" +namespace Common { +struct VaCtx; +} + namespace Libraries::Kernel { struct OrbisKernelStat; struct OrbisKernelIovec; diff --git a/src/core/file_sys/devices/rng_device.cpp b/src/core/file_sys/devices/rng_device.cpp index 0cbdf17d6..3bdd76bdd 100644 --- a/src/core/file_sys/devices/rng_device.cpp +++ b/src/core/file_sys/devices/rng_device.cpp @@ -1,9 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include "common/logging/log.h" +#include "common/va_ctx.h" #include "core/file_sys/devices/rng_device.h" namespace Core::Devices { diff --git a/src/core/file_sys/directories/base_directory.h b/src/core/file_sys/directories/base_directory.h index 832b8ac40..b64742825 100644 --- a/src/core/file_sys/directories/base_directory.h +++ b/src/core/file_sys/directories/base_directory.h @@ -3,10 +3,8 @@ #pragma once -#include #include #include "common/types.h" -#include "common/va_ctx.h" #include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/orbis_error.h" diff --git a/src/core/libraries/audio/openal_audio_out.cpp b/src/core/libraries/audio/openal_audio_out.cpp index d40f01588..015a32d3e 100644 --- a/src/core/libraries/audio/openal_audio_out.cpp +++ b/src/core/libraries/audio/openal_audio_out.cpp @@ -711,7 +711,7 @@ private: d[i] = OrbisFloatToS16(s[i]); } } -#elif +#else static void ConvertF32ToS16Stereo(const void* src, void* dst, u32 frames, const float*) { const float* s = static_cast(src); s16* d = static_cast(dst); @@ -755,7 +755,7 @@ private: d[i] = OrbisFloatToS16(s[i]); } } -#elif +#else static void ConvertF32ToS16_8CH(const void* src, void* dst, u32 frames, const float*) { const float* s = static_cast(src); s16* d = static_cast(dst); diff --git a/src/core/libraries/kernel/threads/exception.cpp b/src/core/libraries/kernel/threads/exception.cpp index 0ac820c86..306c886df 100644 --- a/src/core/libraries/kernel/threads/exception.cpp +++ b/src/core/libraries/kernel/threads/exception.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/arch.h" #include "common/assert.h" #include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/orbis_error.h" @@ -194,6 +195,7 @@ void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context const auto handler = Handlers[NativeToOrbisSignal(native_signum)]; if (handler) { auto ctx = Ucontext{}; +#ifdef ARCH_X86_64 #ifdef __APPLE__ const auto& regs = raw_context->uc_mcontext->__ss; ctx.uc_mcontext.mc_r8 = regs.__r8; @@ -260,6 +262,9 @@ void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context ctx.uc_mcontext.mc_gs = (regs[REG_CSGSFS] >> 16) & 0xFFFF; ctx.uc_mcontext.mc_rip = (regs[REG_RIP]); ctx.uc_mcontext.mc_addr = reinterpret_cast(inf->si_addr); +#endif +#else + UNREACHABLE_MSG("SigactionHandler not implemented for current architecture."); #endif handler(NativeToOrbisSignal(native_signum), &ctx); } else { diff --git a/src/core/libraries/kernel/threads/mutex.cpp b/src/core/libraries/kernel/threads/mutex.cpp index b04000021..c6f15588e 100644 --- a/src/core/libraries/kernel/threads/mutex.cpp +++ b/src/core/libraries/kernel/threads/mutex.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/arch.h" #include "common/assert.h" #include "common/types.h" #include "core/libraries/kernel/kernel.h" @@ -18,7 +19,11 @@ static std::mutex MutxStaticLock; #define THR_ADAPTIVE_MUTEX_INITIALIZER ((PthreadMutex*)1) #define THR_MUTEX_DESTROYED ((PthreadMutex*)2) +#if defined(ARCH_X86_64) #define CPU_SPINWAIT __asm__ volatile("pause") +#elif defined(ARCH_ARM64) +#define CPU_SPINWAIT __asm__ volatile("yield") +#endif #define CHECK_AND_INIT_MUTEX \ if (PthreadMutex* m = *mutex; m <= THR_MUTEX_DESTROYED) [[unlikely]] { \ diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index 05ded58ac..ec52a3edc 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -12,8 +12,14 @@ #include "core/libraries/libs.h" #include "core/memory.h" +#ifdef ARCH_X86_64 extern "C" void* PS4_SYSV_ABI _runOnAnotherStack(void* arg, void* func, void* stackb) asm("_runOnAnotherStack"); +#else +void* PS4_SYSV_ABI _runOnAnotherStack(void* arg, void* func, void* stackb) { + UNREACHABLE_MSG("_runOnAnotherStack not implemented on target architecture."); +} +#endif namespace Libraries::Kernel { diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 1aadc6ffa..590442d7c 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/arch.h" #include "core/libraries/ajm/ajm.h" #include "core/libraries/app_content/app_content.h" #include "core/libraries/audio/audioin.h" @@ -13,6 +14,7 @@ #include "core/libraries/companion/companion_util.h" #include "core/libraries/content_export/content_export.h" #include "core/libraries/disc_map/disc_map.h" +#include "core/libraries/fiber/fiber.h" #include "core/libraries/game_live_streaming/gamelivestreaming.h" #include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/hmd/hmd.h" @@ -75,7 +77,6 @@ #include "core/libraries/vr_tracker/vr_tracker.h" #include "core/libraries/web_browser_dialog/webbrowserdialog.h" #include "core/libraries/zlib/zlib_sce.h" -#include "fiber/fiber.h" namespace Libraries { @@ -140,7 +141,9 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Remoteplay::RegisterLib(sym); Libraries::RazorCpu::RegisterLib(sym); Libraries::Move::RegisterLib(sym); +#ifdef ARCH_X86_64 Libraries::Fiber::RegisterLib(sym); +#endif Libraries::Mouse::RegisterLib(sym); Libraries::WebBrowserDialog::RegisterLib(sym); Libraries::Zlib::RegisterLib(sym); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 935ea005a..2a073d40a 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -33,8 +33,8 @@ static PS4_SYSV_ABI void ProgramExitFunc() { LOG_ERROR(Core_Linker, "Exit function called"); } -#ifdef ARCH_X86_64 static PS4_SYSV_ABI void* RunMainEntry [[noreturn]] (EntryParams* params) { +#ifdef ARCH_X86_64 // Start shared library modules asm volatile("andq $-16, %%rsp\n" // Align to 16 bytes "subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned @@ -54,8 +54,10 @@ static PS4_SYSV_ABI void* RunMainEntry [[noreturn]] (EntryParams* params) { : "r"(params->entry_addr), "r"(params), "r"(ProgramExitFunc) : "rax", "rsi", "rdi"); UNREACHABLE(); -} +#else + UNREACHABLE_MSG("RunMainEntry unimplemented for current architecture."); #endif +} Linker::Linker() : memory{Memory::Instance()} {} diff --git a/src/core/thread.cpp b/src/core/thread.cpp index ee879a7d8..e58f16e5b 100644 --- a/src/core/thread.cpp +++ b/src/core/thread.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/alignment.h" +#include "common/arch.h" #include "core/libraries/kernel/threads/pthread.h" #include "thread.h" #ifdef _WIN64 @@ -11,8 +12,10 @@ #include #include #include +#ifdef ARCH_X86_64 #include #endif +#endif namespace Core { @@ -62,9 +65,11 @@ void NativeThread::Exit() { } void NativeThread::Initialize() { +#ifdef ARCH_X86_64 // Set MXCSR and FPUCW registers to the values used by Orbis. _mm_setcsr(ORBIS_MXCSR); asm volatile("fldcw %0" : : "m"(ORBIS_FPUCW)); +#endif #if _WIN64 tid = GetCurrentThreadId(); #else diff --git a/src/shader_recompiler/ir/passes/flatten_extended_userdata_pass.cpp b/src/shader_recompiler/ir/passes/flatten_extended_userdata_pass.cpp index a23ee2319..34abd7778 100644 --- a/src/shader_recompiler/ir/passes/flatten_extended_userdata_pass.cpp +++ b/src/shader_recompiler/ir/passes/flatten_extended_userdata_pass.cpp @@ -5,6 +5,8 @@ #include #include #include +#include "common/arch.h" +#include "common/decoder.h" #include "common/io_file.h" #include "common/logging/log.h" #include "common/path_util.h" @@ -19,8 +21,8 @@ #include "shader_recompiler/ir/reg.h" #include "shader_recompiler/ir/srt_gvn_table.h" #include "shader_recompiler/ir/value.h" -#include "src/common/arch.h" -#include "src/common/decoder.h" + +#ifdef ARCH_X86_64 using namespace Xbyak::util; @@ -41,7 +43,6 @@ PFN_SrtWalker RegisterWalkerCode(const u8* ptr, size_t size) { namespace { static void DumpSrtProgram(const Shader::Info& info, const u8* code, size_t codesize) { -#ifdef ARCH_X86_64 using namespace Common::FS; const auto dump_dir = GetUserPath(PathType::ShaderDir) / "dumps"; @@ -64,7 +65,6 @@ static void DumpSrtProgram(const Shader::Info& info, const u8* code, size_t code file.WriteString(s); address += instruction.length; } -#endif } static bool SrtWalkerSignalHandler(void* context, void* fault_address) { @@ -305,3 +305,23 @@ void FlattenExtendedUserdataPass(IR::Program& program) { } } // namespace Shader::Optimization + +#else + +namespace Shader { + +PFN_SrtWalker RegisterWalkerCode(const u8* ptr, size_t size) { + UNREACHABLE_MSG("RegisterWalkerCode unimplemented for target architecture."); +} + +namespace Optimization { + +void FlattenExtendedUserdataPass(IR::Program& program) { + UNREACHABLE_MSG("FlattenExtendedUserdataPass unimplemented for target architecture."); +} + +} // namespace Optimization + +} // namespace Shader + +#endif