From b2d1db0ce2450a9bd58faaa87021ad810e304591 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 19:40:25 +0000 Subject: [PATCH] [nce] common ctx Signed-off-by: lizzie --- src/core/arm/nce/arm_nce.cpp | 100 +++++------------- src/core/arm/nce/interpreter_visitor.cpp | 30 +----- src/core/arm/nce/interpreter_visitor.h | 8 +- .../backend/exception_handler_posix.cpp | 16 +-- 4 files changed, 40 insertions(+), 114 deletions(-) diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index a81e5a5666..7a78921ab5 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -13,9 +13,10 @@ #include "core/arm/nce/patcher.h" #include "core/core.h" #include "core/memory.h" - #include "core/hle/kernel/k_process.h" +#include "dynarmic/common/context.h" + #include #include #include @@ -33,20 +34,6 @@ static_assert(offsetof(NativeExecutionParameters, native_context) == TpidrEl0Nat static_assert(offsetof(NativeExecutionParameters, lock) == TpidrEl0Lock); static_assert(offsetof(NativeExecutionParameters, magic) == TpidrEl0TlsMagic); -#ifdef __APPLE__ -_STRUCT_ARM_NEON_STATE64* GetFloatingPointState(mcontext_t& host_ctx) { - return &(host_ctx.__ns); -} -#else -fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) { - _aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved); - while (header->magic != FPSIMD_MAGIC) { - header = reinterpret_cast<_aarch64_ctx*>(reinterpret_cast(header) + header->size); - } - return reinterpret_cast(header); -} -#endif - using namespace Common::Literals; constexpr u32 StackSize = 128_KiB; @@ -59,38 +46,21 @@ void* ArmNce::RestoreGuestContext(void* raw_context) { auto* fpctx = GetFloatingPointState(host_ctx); // Restore all guest state except tpidr_el0. -#ifdef __APPLE__ // Thread-local parameters will be located in x9. - auto* tpidr = reinterpret_cast(host_ctx->__ss.__r[9]); + auto* tpidr = reinterpret_cast(CTX_X(9)); auto* guest_ctx = static_cast(tpidr->native_context); // Save host callee-saved registers. - std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &fpctx->__v[8], + std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &CTX_Q(8), sizeof(guest_ctx->host_ctx.host_saved_vregs)); // Save stack pointer. - guest_ctx->host_ctx.host_sp = host_ctx->__ss.__sp; - host_ctx->__ss.__pc = guest_ctx->sp; - host_ctx->__ss.__sp = guest_ctx->pc; - host_ctx->__ss.__pstate = guest_ctx->pstate; - fpctx->__fpcr = guest_ctx->fpcr; - fpctx->__fpsr = guest_ctx->fpsr; - std::memcpy(fpctx->__v, guest_ctx->vector_registers.data(), sizeof(fpctx->__v)); -#else - // Thread-local parameters will be located in x9. - auto* tpidr = reinterpret_cast(host_ctx.regs[9]); - auto* guest_ctx = static_cast(tpidr->native_context); - // Save host callee-saved registers. - std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &fpctx->vregs[8], - sizeof(guest_ctx->host_ctx.host_saved_vregs)); - // Save stack pointer. - guest_ctx->host_ctx.host_sp = host_ctx.sp; - host_ctx.sp = guest_ctx->sp; - host_ctx.pc = guest_ctx->pc; - host_ctx.pstate = guest_ctx->pstate; - fpctx->fpcr = guest_ctx->fpcr; - fpctx->fpsr = guest_ctx->fpsr; - std::memcpy(fpctx->vregs, guest_ctx->vector_registers.data(), sizeof(fpctx->vregs)); -#endif - std::memcpy(host_ctx.regs, guest_ctx->cpu_registers.data(), sizeof(host_ctx.regs)); + guest_ctx->host_ctx.host_sp = CTX_SP; + CTX_PC = guest_ctx->sp; + CTX_SP = guest_ctx->pc; + CTX_PSTATE = guest_ctx->pstate; + CTX_FPCR = guest_ctx->fpcr; + CTX_FPSR = guest_ctx->fpsr; + std::memcpy(&CTX_X(0), guest_ctx->cpu_registers.data(), sizeof(guest_ctx->cpu_registers)); + std::memcpy(&CTX_Q(0), guest_ctx->vector_registers.data(), sizeof(guest_ctx->vector_registers)); // Return the new thread-local storage pointer. return tpidr; } @@ -103,47 +73,25 @@ void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) { auto* fpctx = GetFloatingPointState(host_ctx); // Save all guest registers except tpidr_el0. -#ifdef __APPLE__ - std::memcpy(guest_ctx->cpu_registers.data(), host_ctx->__ss.__r, sizeof(host_ctx->__ss.__r)); - std::memcpy(guest_ctx->vector_registers.data(), fpctx->__v, sizeof(fpctx->__v)); - guest_ctx->fpsr = fpctx->__fpsr; - guest_ctx->fpcr = fpctx->__fpcr; - guest_ctx->pstate = static_cast(host_ctx->__ss.__pstate); - guest_ctx->pc = host_ctx->__ss.__pc; - guest_ctx->sp = host_ctx->__ss.__sp; - // Restore stack pointer. - host_ctx->__ss.__sp = guest_ctx->host_ctx.host_sp; - // Restore host callee-saved registers. - std::memcpy(&host_ctx->__ss.__r[19], guest_ctx->host_ctx.host_saved_regs.data(), - sizeof(guest_ctx->host_ctx.host_saved_regs)); - std::memcpy(&fpctx->__v[8], guest_ctx->host_ctx.host_saved_vregs.data(), - sizeof(guest_ctx->host_ctx.host_saved_vregs)); - // Return from the call on exit by setting pc to x30. - host_ctx->__ss.__pc = guest_ctx->host_ctx.host_saved_regs[11]; - // Clear esr_el1 and return it. - host_ctx->__ss.__r[0] = guest_ctx->esr_el1.exchange(0); -#else - std::memcpy(guest_ctx->cpu_registers.data(), host_ctx.regs, sizeof(host_ctx.regs)); - std::memcpy(guest_ctx->vector_registers.data(), fpctx->vregs, sizeof(fpctx->vregs)); - guest_ctx->fpsr = fpctx->fpsr; - guest_ctx->fpcr = fpctx->fpcr; - guest_ctx->pstate = static_cast(host_ctx.pstate); - guest_ctx->pc = host_ctx.pc; - guest_ctx->sp = host_ctx.sp; - + std::memcpy(guest_ctx->cpu_registers.data(), &CTX_X(0), sizeof(guest_ctx->cpu_registers)); + std::memcpy(guest_ctx->vector_registers.data(), &CTX_Q(0), sizeof(guest_ctx->vector_registers)); + guest_ctx->fpsr = CTX_FPSR; + guest_ctx->fpcr = CTX_FPCR; + guest_ctx->pc = CTX_PC; + guest_ctx->sp = CTX_SP; + guest_ctx->pstate = u32(CTX_PSTATE); // Restore stack pointer. - host_ctx.sp = guest_ctx->host_ctx.host_sp; + CTX_SP = guest_ctx->host_ctx.host_sp; // Restore host callee-saved registers. - std::memcpy(&host_ctx.regs[19], guest_ctx->host_ctx.host_saved_regs.data(), + std::memcpy(&CTX_X(19), guest_ctx->host_ctx.host_saved_regs.data(), sizeof(guest_ctx->host_ctx.host_saved_regs)); std::memcpy(&fpctx->vregs[8], guest_ctx->host_ctx.host_saved_vregs.data(), sizeof(guest_ctx->host_ctx.host_saved_vregs)); // Return from the call on exit by setting pc to x30. - host_ctx.pc = guest_ctx->host_ctx.host_saved_regs[11]; + CTX_PC = guest_ctx->host_ctx.host_saved_regs[11]; // Clear esr_el1 and return it. - host_ctx.regs[0] = guest_ctx->esr_el1.exchange(0); -#endif + CTX_X(0) = guest_ctx->esr_el1.exchange(0); } bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) { @@ -182,7 +130,7 @@ bool ArmNce::HandleGuestAlignmentFault(GuestContext* guest_ctx, void* raw_info, auto& memory = guest_ctx->system->ApplicationMemory(); // Match and execute an instruction. - auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); + auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx); if (next_pc) { host_ctx.pc = *next_pc; return true; diff --git a/src/core/arm/nce/interpreter_visitor.cpp b/src/core/arm/nce/interpreter_visitor.cpp index 920c6efe65..325ee1c8d4 100644 --- a/src/core/arm/nce/interpreter_visitor.cpp +++ b/src/core/arm/nce/interpreter_visitor.cpp @@ -761,13 +761,11 @@ bool InterpreterVisitor::LDR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3 return this->SIMDOffset(scale, shift, opc_0, Rm, option, Rn, Vt); } -#ifdef __APPLE__ -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - _STRUCT_ARM_NEON_STATE64* fpctx) { - std::span regs(reinterpret_cast(context->regs), 31); - std::span vregs(reinterpret_cast(fpctx->__v), 32); - u64& sp = *reinterpret_cast(&context->sp); - const u64& pc = *reinterpret_cast(&context->pc); +std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context) { + std::span regs(reinterpret_cast(&CTX_X(0)), 31); + std::span vregs(reinterpret_cast(&CTX_Q(0)), 32); + u64& sp = *reinterpret_cast(&CTX_SP); + const u64& pc = *reinterpret_cast(&CTX_PC); InterpreterVisitor visitor(memory, regs, vregs, sp, pc); u32 instruction = memory.Read32(pc); bool was_executed = false; @@ -778,23 +776,5 @@ std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, m } return was_executed ? std::optional(pc + 4) : std::nullopt; } -#else -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - fpsimd_context* fpctx) { - std::span regs(reinterpret_cast(context->regs), 31); - std::span vregs(reinterpret_cast(fpctx->vregs), 32); - u64& sp = *reinterpret_cast(&context->sp); - const u64& pc = *reinterpret_cast(&context->pc); - InterpreterVisitor visitor(memory, regs, vregs, sp, pc); - u32 instruction = memory.Read32(pc); - bool was_executed = false; - if (auto decoder = Dynarmic::A64::Decode(instruction)) { - was_executed = decoder->get().call(visitor, instruction); - } else { - LOG_ERROR(Core_ARM, "Unallocated encoding: {:#x}", instruction); - } - return was_executed ? std::optional(pc + 4) : std::nullopt; -} -#endif } // namespace Core diff --git a/src/core/arm/nce/interpreter_visitor.h b/src/core/arm/nce/interpreter_visitor.h index 051005c467..935f15c47c 100644 --- a/src/core/arm/nce/interpreter_visitor.h +++ b/src/core/arm/nce/interpreter_visitor.h @@ -105,12 +105,6 @@ private: const u64& m_pc; }; -#ifdef __APPLE__ -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - _STRUCT_ARM_NEON_STATE64* fpctx); -#else -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - fpsimd_context* fpctx); -#endif +std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context); } // namespace Core diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index 9f508f72e5..9af4300238 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -6,6 +6,8 @@ * SPDX-License-Identifier: 0BSD */ +#include "dynarmic/backend/exception_handler.h" + #include #include #include @@ -119,9 +121,10 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { CTX_DECLARE(raw_context); #if defined(ARCHITECTURE_x86_64) { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_RIP); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_RIP); + std::lock_guard guard(sig_handler->code_block_infos_mutex); + const auto iter = sig_handler->FindCodeBlockInfo(CTX_RIP); + if (iter != sig_handler->code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_RIP); CTX_RSP -= sizeof(u64); *std::bit_cast(CTX_RSP) = fc.ret_rip; CTX_RIP = fc.call_rip; @@ -131,9 +134,10 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP); #elif defined(ARCHITECTURE_arm64) { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_PC); + std::lock_guard guard(sig_handler->code_block_infos_mutex); + const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); + if (iter != sig_handler->code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_PC); CTX_PC = fc.call_pc; return; }