forked from eden-emu/eden
Compare commits
20 commits
master
...
liz-dynarm
Author | SHA1 | Date | |
---|---|---|---|
51d49512bc | |||
317d942ae0 | |||
70d1e5cac5 | |||
65691376ff | |||
aadfd4bcbc | |||
e390b5790e | |||
a2a77982da | |||
df6fa8b9e5 | |||
4bf84095b5 | |||
49236324aa | |||
dfbce406d7 | |||
e618e5e818 | |||
b72a98c807 | |||
bb8782fff1 | |||
49cae00c97 | |||
ff72ba4fc2 | |||
ec96d066ab | |||
e4d75caca4 | |||
c44b3423f3 | |||
20bdcc5731 |
22 changed files with 376 additions and 239 deletions
|
@ -50,7 +50,7 @@ CMAKE_DEPENDENT_OPTION(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" O
|
|||
|
||||
set(EXT_DEFAULT ON)
|
||||
|
||||
if (PLATFORM_FREEBSD)
|
||||
if (PLATFORM_FREEBSD OR APPLE)
|
||||
set(EXT_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
|
@ -314,7 +314,7 @@ if (UNIX)
|
|||
add_definitions(-DYUZU_UNIX=1)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX))
|
||||
if (ARCHITECTURE_arm64 AND (ANDROID OR APPLE OR PLATFORM_LINUX))
|
||||
set(HAS_NCE 1)
|
||||
add_definitions(-DHAS_NCE=1)
|
||||
endif()
|
||||
|
@ -455,10 +455,17 @@ if (YUZU_USE_CPM)
|
|||
|
||||
if (enet_ADDED)
|
||||
target_include_directories(enet INTERFACE ${enet_SOURCE_DIR}/include)
|
||||
if (NOT TARGET enet::enet)
|
||||
add_library(enet::enet ALIAS enet)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
AddJsonPackage(opus)
|
||||
|
||||
if (NOT TARGET Opus::opus)
|
||||
add_library(Opus::opus ALIAS opus)
|
||||
endif()
|
||||
else()
|
||||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||
find_package(fmt 8 REQUIRED)
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
# Future crueter: Wow this was a lie and a half, at this point I might as well make my own CPN
|
||||
# haha just kidding... unless?
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
if (MSVC OR ANDROID)
|
||||
set(BUNDLED_DEFAULT OFF)
|
||||
else()
|
||||
set(BUNDLED_DEFAULT ON)
|
||||
else()
|
||||
set(BUNDLED_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
option(CPMUTIL_FORCE_BUNDLED
|
||||
|
@ -23,7 +25,6 @@ option(CPMUTIL_FORCE_BUNDLED
|
|||
option(CPMUTIL_FORCE_SYSTEM
|
||||
"Force system packages for all CPM dependencies (NOT RECOMMENDED)" OFF)
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
include(CPM)
|
||||
|
||||
# TODO(crueter): Better solution for separate cpmfiles e.g. per-directory
|
||||
|
|
8
docs/CrossCompileARM64.md
Normal file
8
docs/CrossCompileARM64.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Cross compile ARM64
|
||||
|
||||
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
|
||||
|
||||
- Install QEMU: `sudo pkg install qemu`
|
||||
- Download Debian 13: `wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso`
|
||||
- Create a system disk: `qemu-img create -f qcow2 debian-13-arm64-ci.qcow2 30G`
|
||||
- Run the VM: `qemu-system-aarch64 -M virt -m 2G -cpu max -bios /usr/local/share/qemu/edk2-aarch64-code.fd -drive if=none,file=debian-13.0.0-arm64-netinst.iso,format=raw,id=cdrom -device scsi-cd,drive=cdrom -drive if=none,file=debian-13-arm64-ci.qcow2,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 -device virtio-gpu-pci -device usb-ehci -device usb-kbd -device intel-hda -device hda-output -nic user,model=virtio-net-pci`
|
1
externals/CMakeLists.txt
vendored
1
externals/CMakeLists.txt
vendored
|
@ -54,6 +54,7 @@ endif()
|
|||
add_subdirectory(glad)
|
||||
|
||||
# mbedtls
|
||||
# TODO(crueter): Findmbedtls that ONLY accepts mbedtls2
|
||||
AddJsonPackage(mbedtls)
|
||||
|
||||
if (mbedtls_ADDED)
|
||||
|
|
3
externals/cpmfile.json
vendored
3
externals/cpmfile.json
vendored
|
@ -5,7 +5,8 @@
|
|||
"hash": "769ad1e94c570671071e1f2a5c0f1027e0bf6bcdd1a80ea8ac970f2c86bc45ce4e31aa88d6d8110fc1bed1de81c48bc624df1b38a26f8b340a44e109d784a966",
|
||||
"patches": [
|
||||
"0001-cmake-version.patch"
|
||||
]
|
||||
],
|
||||
"bundled": true
|
||||
},
|
||||
"spirv-headers": {
|
||||
"package": "SPIRV-Headers",
|
||||
|
|
2
externals/libusb/libusb
vendored
2
externals/libusb/libusb
vendored
|
@ -1 +1 @@
|
|||
Subproject commit c060e9ce30ac2e3ffb49d94209c4dae77b6642f7
|
||||
Subproject commit 3dbfa16f0cd9e8ed4fec916c6c00f41c738cb8f4
|
|
@ -227,7 +227,7 @@ else()
|
|||
endif()
|
||||
|
||||
target_include_directories(audio_core PRIVATE ${OPUS_INCLUDE_DIRS})
|
||||
target_link_libraries(audio_core PUBLIC common core opus)
|
||||
target_link_libraries(audio_core PUBLIC common core Opus::opus)
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
target_link_libraries(audio_core PRIVATE dynarmic::dynarmic)
|
||||
|
|
|
@ -283,4 +283,13 @@ if(YUZU_USE_PRECOMPILED_HEADERS)
|
|||
target_precompile_headers(common PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
# IOPS (needed for power state) requires linking to IOKit
|
||||
if (APPLE)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
if(NOT IOKIT_LIBRARY)
|
||||
message(FATAL_ERROR "IOKit not found, did you install XCode tools?")
|
||||
endif()
|
||||
target_link_libraries(common PRIVATE ${IOKIT_LIBRARY})
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
#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 <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
@ -33,95 +35,67 @@ static_assert(offsetof(NativeExecutionParameters, native_context) == TpidrEl0Nat
|
|||
static_assert(offsetof(NativeExecutionParameters, lock) == TpidrEl0Lock);
|
||||
static_assert(offsetof(NativeExecutionParameters, magic) == TpidrEl0TlsMagic);
|
||||
|
||||
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<char*>(header) + header->size);
|
||||
}
|
||||
return reinterpret_cast<fpsimd_context*>(header);
|
||||
}
|
||||
|
||||
using namespace Common::Literals;
|
||||
constexpr u32 StackSize = 128_KiB;
|
||||
|
||||
} // namespace
|
||||
|
||||
void* ArmNce::RestoreGuestContext(void* raw_context) {
|
||||
// Retrieve the host context.
|
||||
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
|
||||
|
||||
// Thread-local parameters will be located in x9.
|
||||
auto* tpidr = reinterpret_cast<NativeExecutionParameters*>(host_ctx.regs[9]);
|
||||
auto* guest_ctx = static_cast<GuestContext*>(tpidr->native_context);
|
||||
|
||||
// Retrieve the host floating point state.
|
||||
auto* fpctx = GetFloatingPointState(host_ctx);
|
||||
|
||||
// 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));
|
||||
std::memcpy(guest_ctx->host_ctx.host_saved_regs.data(), &host_ctx.regs[19],
|
||||
sizeof(guest_ctx->host_ctx.host_saved_regs));
|
||||
|
||||
// Save stack pointer.
|
||||
guest_ctx->host_ctx.host_sp = host_ctx.sp;
|
||||
|
||||
CTX_DECLARE(raw_context);
|
||||
// Restore all guest state except tpidr_el0.
|
||||
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(host_ctx.regs, guest_ctx->cpu_registers.data(), sizeof(host_ctx.regs));
|
||||
std::memcpy(fpctx->vregs, guest_ctx->vector_registers.data(), sizeof(fpctx->vregs));
|
||||
|
||||
// Thread-local parameters will be located in x9.
|
||||
auto* tpidr = reinterpret_cast<NativeExecutionParameters*>(CTX_X(9));
|
||||
auto* guest_ctx = static_cast<GuestContext*>(tpidr->native_context);
|
||||
// Save host callee-saved registers.
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) {
|
||||
// Retrieve the host context.
|
||||
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
|
||||
|
||||
// Retrieve the host floating point state.
|
||||
auto* fpctx = GetFloatingPointState(host_ctx);
|
||||
|
||||
CTX_DECLARE(raw_context);
|
||||
// Save all guest registers except tpidr_el0.
|
||||
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<u32>(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(),
|
||||
std::memcpy(&CTX_Q(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);
|
||||
CTX_X(0) = guest_ctx->esr_el1.exchange(0);
|
||||
}
|
||||
|
||||
bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
|
||||
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
|
||||
CTX_DECLARE(raw_context);
|
||||
auto* info = static_cast<siginfo_t*>(raw_info);
|
||||
|
||||
// We can't handle the access, so determine why we crashed.
|
||||
const bool is_prefetch_abort = host_ctx.pc == reinterpret_cast<u64>(info->si_addr);
|
||||
|
||||
auto const is_prefetch_abort = CTX_PC == reinterpret_cast<u64>(info->si_addr);
|
||||
// For data aborts, skip the instruction and return to guest code.
|
||||
// This will allow games to continue in many scenarios where they would otherwise crash.
|
||||
if (!is_prefetch_abort) {
|
||||
host_ctx.pc += 4;
|
||||
CTX_PC += 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -142,17 +116,13 @@ bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, voi
|
|||
}
|
||||
|
||||
bool ArmNce::HandleGuestAlignmentFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
|
||||
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
|
||||
auto* fpctx = GetFloatingPointState(host_ctx);
|
||||
CTX_DECLARE(raw_context);
|
||||
auto& memory = guest_ctx->system->ApplicationMemory();
|
||||
|
||||
// Match and execute an instruction.
|
||||
auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx);
|
||||
if (next_pc) {
|
||||
host_ctx.pc = *next_pc;
|
||||
if (auto next_pc = MatchAndExecuteOneInstruction(memory, raw_context); next_pc) {
|
||||
CTX_PC = *next_pc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We couldn't handle the access.
|
||||
return HandleFailedGuestFault(guest_ctx, raw_info, raw_context);
|
||||
}
|
||||
|
@ -275,9 +245,51 @@ ArmNce::ArmNce(System& system, bool uses_wall_clock, std::size_t core_index)
|
|||
|
||||
ArmNce::~ArmNce() = default;
|
||||
|
||||
// Borrowed from libusb
|
||||
static unsigned int posix_gettid(void) {
|
||||
static thread_local unsigned int tl_tid;
|
||||
int tid;
|
||||
if (tl_tid)
|
||||
return tl_tid;
|
||||
#if defined(__ANDROID__)
|
||||
tid = gettid();
|
||||
#elif defined(__APPLE__)
|
||||
#ifdef HAVE_PTHREAD_THREADID_NP
|
||||
uint64_t thread_id;
|
||||
if (pthread_threadid_np(NULL, &thread_id) == 0)
|
||||
tid = (int)thread_id;
|
||||
else
|
||||
tid = -1;
|
||||
#else
|
||||
tid = (int)pthread_mach_thread_np(pthread_self());
|
||||
#endif
|
||||
#elif defined(__HAIKU__)
|
||||
tid = get_pthread_thread_id(pthread_self());
|
||||
#elif defined(__linux__)
|
||||
tid = (int)syscall(SYS_gettid);
|
||||
#elif defined(__NetBSD__)
|
||||
tid = _lwp_self();
|
||||
#elif defined(__OpenBSD__)
|
||||
/* The following only works with OpenBSD > 5.1 as it requires
|
||||
* real thread support. For 5.1 and earlier, -1 is returned. */
|
||||
tid = syscall(SYS_getthrid);
|
||||
#elif defined(__sun__)
|
||||
tid = _lwp_self();
|
||||
#else
|
||||
tid = -1;
|
||||
#endif
|
||||
if (tid == -1) {
|
||||
/* If we don't have a thread ID, at least return a unique
|
||||
* value that can be used to distinguish individual
|
||||
* threads. */
|
||||
tid = (int)(intptr_t)pthread_self();
|
||||
}
|
||||
return tl_tid = (unsigned int)tid;
|
||||
}
|
||||
|
||||
void ArmNce::Initialize() {
|
||||
if (m_thread_id == -1) {
|
||||
m_thread_id = gettid();
|
||||
m_thread_id = posix_gettid();
|
||||
}
|
||||
|
||||
// Configure signal stack.
|
||||
|
@ -308,7 +320,7 @@ void ArmNce::Initialize() {
|
|||
&ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler);
|
||||
return_to_run_code_action.sa_mask = signal_mask;
|
||||
Common::SigAction(ReturnToRunCodeByExceptionLevelChangeSignal, &return_to_run_code_action,
|
||||
nullptr);
|
||||
nullptr);
|
||||
|
||||
struct sigaction break_from_run_code_action {};
|
||||
break_from_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
|
@ -378,7 +390,11 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) {
|
|||
if (params->is_running) {
|
||||
// We should signal to the running thread.
|
||||
// The running thread will unlock the thread context.
|
||||
#ifdef __linux__
|
||||
syscall(SYS_tkill, m_thread_id, BreakFromRunCodeSignal);
|
||||
#else
|
||||
pthread_kill(pthread_t(m_thread_id), int(BreakFromRunCodeSignal));
|
||||
#endif
|
||||
} else {
|
||||
// If the thread is no longer running, we have nothing to do.
|
||||
UnlockThreadParameters(params);
|
||||
|
|
|
@ -9,10 +9,15 @@
|
|||
|
||||
|
||||
/* static HaltReason Core::ArmNce::ReturnToRunCodeByTrampoline(void* tpidr, Core::GuestContext* ctx, u64 trampoline_addr) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEy
|
||||
__ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEy:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm
|
||||
.type _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, %function
|
||||
.global _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm
|
||||
_ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
|
||||
#endif
|
||||
/* Back up host sp to x3. */
|
||||
/* Back up host tpidr_el0 to x4. */
|
||||
mov x3, sp
|
||||
|
@ -50,38 +55,51 @@ _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
|
|||
|
||||
|
||||
/* static HaltReason Core::ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void* tpidr) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv
|
||||
__ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv
|
||||
.type _ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv, %function
|
||||
.global _ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv
|
||||
_ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv:
|
||||
#endif
|
||||
/* This jumps to the signal handler, which will restore the entire context. */
|
||||
/* On entry, x0 = thread id, which is already in the right place. */
|
||||
|
||||
/* On entry, x0 = thread id, which is already in the right place. Even on macOS. */
|
||||
/* Move tpidr to x9 so it is not trampled. */
|
||||
mov x9, x1
|
||||
|
||||
/* Set up arguments. */
|
||||
mov x8, #(__NR_tkill)
|
||||
mov x1, #(ReturnToRunCodeByExceptionLevelChangeSignal)
|
||||
|
||||
/* Tail call the signal handler. */
|
||||
svc #0
|
||||
|
||||
/* Block execution from flowing here. */
|
||||
brk #1000
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* I can never be happy, why no tkill in mach kernel? Ugh ... */
|
||||
/* Signature: 328 AUE_PTHREADKILL ALL { int __pthread_kill(int thread_port, int sig); } */
|
||||
mov x16, #(328)
|
||||
#else
|
||||
/* Signature: int tgkill(pid_t tgid, pid_t tid, int sig); */
|
||||
mov x8, #(__NR_tkill)
|
||||
#endif
|
||||
svc #0 /* Tail call the signal handler. */
|
||||
brk #1000 /* Block execution from flowing here. */
|
||||
|
||||
/* static void Core::ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
|
||||
__ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
|
||||
.type _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, %function
|
||||
.global _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
|
||||
_ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
|
||||
#endif
|
||||
stp x29, x30, [sp, #-0x10]!
|
||||
mov x29, sp
|
||||
|
||||
/* Call the context restorer with the raw context. */
|
||||
mov x0, x2
|
||||
#ifdef __APPLE__
|
||||
bl __ZN4Core6ArmNce19RestoreGuestContextEPv
|
||||
#else
|
||||
bl _ZN4Core6ArmNce19RestoreGuestContextEPv
|
||||
#endif
|
||||
|
||||
/* Save the old value of tpidr_el0. */
|
||||
mrs x8, tpidr_el0
|
||||
|
@ -92,7 +110,11 @@ _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
|
|||
msr tpidr_el0, x0
|
||||
|
||||
/* Unlock the context. */
|
||||
#ifdef __APPLE__
|
||||
bl __ZN4Core6ArmNce22UnlockThreadParametersEPv
|
||||
#else
|
||||
bl _ZN4Core6ArmNce22UnlockThreadParametersEPv
|
||||
#endif
|
||||
|
||||
/* Returning from here will enter the guest. */
|
||||
ldp x29, x30, [sp], #0x10
|
||||
|
@ -100,10 +122,15 @@ _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
|
|||
|
||||
|
||||
/* static void Core::ArmNce::BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_
|
||||
__ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_
|
||||
.type _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_, %function
|
||||
.global _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_
|
||||
_ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
|
||||
#endif
|
||||
/* Check to see if we have the correct TLS magic. */
|
||||
mrs x8, tpidr_el0
|
||||
ldr w9, [x8, #(TpidrEl0TlsMagic)]
|
||||
|
@ -121,7 +148,11 @@ _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
|
|||
|
||||
/* Tail call the restorer. */
|
||||
mov x1, x2
|
||||
#ifdef __APPLE__
|
||||
b __ZN4Core6ArmNce16SaveGuestContextEPNS_12GuestContextEPv
|
||||
#else
|
||||
b _ZN4Core6ArmNce16SaveGuestContextEPNS_12GuestContextEPv
|
||||
#endif
|
||||
|
||||
/* Returning from here will enter host code. */
|
||||
|
||||
|
@ -131,10 +162,15 @@ _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
|
|||
|
||||
|
||||
/* static void Core::ArmNce::GuestAlignmentFaultSignalHandler(int sig, void* info, void* raw_context) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_
|
||||
__ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_
|
||||
.type _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_, %function
|
||||
.global _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_
|
||||
_ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
|
||||
#endif
|
||||
/* Check to see if we have the correct TLS magic. */
|
||||
mrs x8, tpidr_el0
|
||||
ldr w9, [x8, #(TpidrEl0TlsMagic)]
|
||||
|
@ -146,7 +182,11 @@ _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
|
|||
|
||||
/* Incorrect TLS magic, so this is a host fault. */
|
||||
/* Tail call the handler. */
|
||||
#ifdef __APPLE__
|
||||
b __ZN4Core6ArmNce24HandleHostAlignmentFaultEiPvS1_
|
||||
#else
|
||||
b _ZN4Core6ArmNce24HandleHostAlignmentFaultEiPvS1_
|
||||
#endif
|
||||
|
||||
1:
|
||||
/* Correct TLS magic, so this is a guest fault. */
|
||||
|
@ -163,7 +203,11 @@ _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
|
|||
msr tpidr_el0, x3
|
||||
|
||||
/* Call the handler. */
|
||||
#ifdef __APPLE__
|
||||
bl __ZN4Core6ArmNce25HandleGuestAlignmentFaultEPNS_12GuestContextEPvS3_
|
||||
#else
|
||||
bl _ZN4Core6ArmNce25HandleGuestAlignmentFaultEPNS_12GuestContextEPvS3_
|
||||
#endif
|
||||
|
||||
/* If the handler returned false, we want to preserve the host tpidr_el0. */
|
||||
cbz x0, 2f
|
||||
|
@ -177,10 +221,15 @@ _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
|
|||
ret
|
||||
|
||||
/* static void Core::ArmNce::GuestAccessFaultSignalHandler(int sig, void* info, void* raw_context) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_
|
||||
__ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_
|
||||
.type _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_, %function
|
||||
.global _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_
|
||||
_ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
|
||||
#endif
|
||||
/* Check to see if we have the correct TLS magic. */
|
||||
mrs x8, tpidr_el0
|
||||
ldr w9, [x8, #(TpidrEl0TlsMagic)]
|
||||
|
@ -192,7 +241,11 @@ _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
|
|||
|
||||
/* Incorrect TLS magic, so this is a host fault. */
|
||||
/* Tail call the handler. */
|
||||
#ifdef __APPLE__
|
||||
b __ZN4Core6ArmNce21HandleHostAccessFaultEiPvS1_
|
||||
#else
|
||||
b _ZN4Core6ArmNce21HandleHostAccessFaultEiPvS1_
|
||||
#endif
|
||||
|
||||
1:
|
||||
/* Correct TLS magic, so this is a guest fault. */
|
||||
|
@ -209,7 +262,11 @@ _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
|
|||
msr tpidr_el0, x3
|
||||
|
||||
/* Call the handler. */
|
||||
#ifdef __APPLE__
|
||||
bl __ZN4Core6ArmNce22HandleGuestAccessFaultEPNS_12GuestContextEPvS3_
|
||||
#else
|
||||
bl _ZN4Core6ArmNce22HandleGuestAccessFaultEPNS_12GuestContextEPvS3_
|
||||
#endif
|
||||
|
||||
/* If the handler returned false, we want to preserve the host tpidr_el0. */
|
||||
cbz x0, 2f
|
||||
|
@ -224,10 +281,15 @@ _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
|
|||
|
||||
|
||||
/* static void Core::ArmNce::LockThreadParameters(void* tpidr) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce20LockThreadParametersEPv
|
||||
__ZN4Core6ArmNce20LockThreadParametersEPv:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce20LockThreadParametersEPv, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce20LockThreadParametersEPv
|
||||
.type _ZN4Core6ArmNce20LockThreadParametersEPv, %function
|
||||
.global _ZN4Core6ArmNce20LockThreadParametersEPv
|
||||
_ZN4Core6ArmNce20LockThreadParametersEPv:
|
||||
#endif
|
||||
/* Offset to lock member. */
|
||||
add x0, x0, #(TpidrEl0Lock)
|
||||
|
||||
|
@ -252,10 +314,15 @@ _ZN4Core6ArmNce20LockThreadParametersEPv:
|
|||
|
||||
|
||||
/* static void Core::ArmNce::UnlockThreadParameters(void* tpidr) */
|
||||
#ifdef __APPLE__
|
||||
.global __ZN4Core6ArmNce22UnlockThreadParametersEPv
|
||||
__ZN4Core6ArmNce22UnlockThreadParametersEPv:
|
||||
#else
|
||||
.section .text._ZN4Core6ArmNce22UnlockThreadParametersEPv, "ax", %progbits
|
||||
.global _ZN4Core6ArmNce22UnlockThreadParametersEPv
|
||||
.type _ZN4Core6ArmNce22UnlockThreadParametersEPv, %function
|
||||
.global _ZN4Core6ArmNce22UnlockThreadParametersEPv
|
||||
_ZN4Core6ArmNce22UnlockThreadParametersEPv:
|
||||
#endif
|
||||
/* Offset to lock member. */
|
||||
add x0, x0, #(TpidrEl0Lock)
|
||||
|
||||
|
|
|
@ -5,22 +5,24 @@
|
|||
|
||||
#define __ASSEMBLY__
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* https://cpip.readthedocs.io/en/stable/_static/dictobject.c/signal.h_bbe000f9714f274340a28e000a369354.html */
|
||||
#define ReturnToRunCodeByExceptionLevelChangeSignal 31
|
||||
#define BreakFromRunCodeSignal 16
|
||||
#define GuestAccessFaultSignal 11
|
||||
#define GuestAlignmentFaultSignal 10
|
||||
#else
|
||||
#include <asm-generic/signal.h>
|
||||
#include <asm-generic/unistd.h>
|
||||
|
||||
#define ReturnToRunCodeByExceptionLevelChangeSignal SIGUSR2
|
||||
#define BreakFromRunCodeSignal SIGURG
|
||||
#define GuestAccessFaultSignal SIGSEGV
|
||||
#define GuestAlignmentFaultSignal SIGBUS
|
||||
#endif
|
||||
|
||||
#define GuestContextSp 0xF8
|
||||
#define GuestContextHostContext 0x320
|
||||
|
||||
#define HostContextSpTpidrEl0 0xE0
|
||||
#define HostContextTpidrEl0 0xE8
|
||||
#define HostContextRegs 0x0
|
||||
#define HostContextVregs 0x60
|
||||
|
||||
#define TpidrEl0NativeContext 0x10
|
||||
#define TpidrEl0Lock 0x18
|
||||
#define TpidrEl0TlsMagic 0x20
|
||||
|
@ -28,3 +30,8 @@
|
|||
|
||||
#define SpinLockLocked 0
|
||||
#define SpinLockUnlocked 1
|
||||
|
||||
#define HostContextSpTpidrEl0 0xE0
|
||||
#define HostContextTpidrEl0 0xE8
|
||||
#define HostContextRegs 0x0
|
||||
#define HostContextVregs 0x60
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 merryhime <https://mary.rs>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/bit_cast.h"
|
||||
#include "core/arm/nce/interpreter_visitor.h"
|
||||
#include "core/memory.h"
|
||||
#include "dynarmic/common/context.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
@ -790,23 +791,20 @@ 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);
|
||||
}
|
||||
|
||||
std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context,
|
||||
fpsimd_context* fpsimd_context) {
|
||||
std::span<u64, 31> regs(reinterpret_cast<u64*>(context->regs), 31);
|
||||
std::span<u128, 32> vregs(reinterpret_cast<u128*>(fpsimd_context->vregs), 32);
|
||||
u64& sp = *reinterpret_cast<u64*>(&context->sp);
|
||||
const u64& pc = *reinterpret_cast<u64*>(&context->pc);
|
||||
|
||||
std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, void* raw_context) {
|
||||
CTX_DECLARE(raw_context);
|
||||
std::span<u64, 31> regs(reinterpret_cast<u64*>(&CTX_X(0)), 31);
|
||||
std::span<u128, 32> vregs(reinterpret_cast<u128*>(&CTX_Q(0)), 32);
|
||||
u64& sp = *reinterpret_cast<u64*>(&CTX_SP);
|
||||
const u64& pc = *reinterpret_cast<u64*>(&CTX_PC);
|
||||
InterpreterVisitor visitor(memory, regs, vregs, sp, pc);
|
||||
u32 instruction = memory.Read32(pc);
|
||||
bool was_executed = false;
|
||||
|
||||
if (auto decoder = Dynarmic::A64::Decode<VisitorBase>(instruction)) {
|
||||
was_executed = decoder->get().call(visitor, instruction);
|
||||
} else {
|
||||
LOG_ERROR(Core_ARM, "Unallocated encoding: {:#x}", instruction);
|
||||
}
|
||||
|
||||
return was_executed ? std::optional<u64>(pc + 4) : std::nullopt;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <signal.h>
|
||||
#include <span>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "core/arm/nce/visitor_base.h"
|
||||
|
@ -97,7 +98,6 @@ private:
|
|||
const u64& m_pc;
|
||||
};
|
||||
|
||||
std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context,
|
||||
fpsimd_context* fpsimd_context);
|
||||
std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, void* raw_context);
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
#include "common/arm64/native_clock.h"
|
||||
#include "common/bit_cast.h"
|
||||
#include "common/literals.h"
|
||||
#include "core/arm/nce/arm_nce.h"
|
||||
#include "core/arm/nce/guest_context.h"
|
||||
#include "core/arm/nce/instructions.h"
|
||||
#include "core/arm/nce/patcher.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core::NCE {
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ ExceptionHandler::~ExceptionHandler() = default;
|
|||
void ExceptionHandler::Register(X64::BlockOfCode&) {
|
||||
// Do nothing
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) {
|
||||
// Do nothing
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
|
||||
# include "dynarmic/backend/x64/block_of_code.h"
|
||||
# define mig_external extern "C"
|
||||
|
@ -36,7 +36,7 @@
|
|||
|
||||
using dynarmic_thread_state_t = x86_thread_state64_t;
|
||||
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
|
||||
# include <oaknut/code_block.hpp>
|
||||
# define mig_external extern "C"
|
||||
|
@ -133,7 +133,7 @@ void MachHandler::MessagePump() {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) {
|
||||
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
|
||||
|
||||
|
@ -151,7 +151,7 @@ kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) {
|
|||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
kern_return_t MachHandler::HandleRequest(arm_thread_state64_t* ts) {
|
||||
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
|
||||
|
||||
|
@ -269,13 +269,13 @@ private:
|
|||
ExceptionHandler::ExceptionHandler() = default;
|
||||
ExceptionHandler::~ExceptionHandler() = default;
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
void ExceptionHandler::Register(X64::BlockOfCode& code) {
|
||||
const u64 code_begin = mcl::bit_cast<u64>(code.getCode());
|
||||
const u64 code_end = code_begin + code.GetTotalCodeSize();
|
||||
impl = std::make_unique<Impl>(code_begin, code_end);
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
|
||||
const u64 code_end = code_begin + size;
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# include "dynarmic/backend/x64/mig/mach_exc_server.c"
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
# include "dynarmic/backend/arm64/mig/mach_exc_server.c"
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
|
|
|
@ -8,19 +8,6 @@
|
|||
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <signal.h>
|
||||
# include <sys/ucontext.h>
|
||||
#else
|
||||
# include <signal.h>
|
||||
# ifndef __OpenBSD__
|
||||
# include <ucontext.h>
|
||||
# endif
|
||||
# ifdef __sun__
|
||||
# include <sys/regset.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
@ -29,12 +16,13 @@
|
|||
#include <vector>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/context.h"
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# include "dynarmic/backend/x64/block_of_code.h"
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
# include <oaknut/code_block.hpp>
|
||||
|
||||
# include "dynarmic/backend/arm64/abi.h"
|
||||
|
@ -148,122 +136,35 @@ void SigHandler::RemoveCodeBlock(u64 host_pc) {
|
|||
|
||||
void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||
ASSERT(sig == SIGSEGV || sig == SIGBUS);
|
||||
|
||||
#ifndef MCL_ARCHITECTURE_RISCV
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
|
||||
#ifndef __OpenBSD__
|
||||
auto& mctx = ucontext->uc_mcontext;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
|
||||
# if defined(__APPLE__)
|
||||
# define CTX_RIP (mctx->__ss.__rip)
|
||||
# define CTX_RSP (mctx->__ss.__rsp)
|
||||
# elif defined(__linux__)
|
||||
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||
# elif defined(__FreeBSD__)
|
||||
# define CTX_RIP (mctx.mc_rip)
|
||||
# define CTX_RSP (mctx.mc_rsp)
|
||||
# elif defined(__NetBSD__)
|
||||
# define CTX_RIP (mctx.__gregs[_REG_RIP])
|
||||
# define CTX_RSP (mctx.__gregs[_REG_RSP])
|
||||
# elif defined(__OpenBSD__)
|
||||
# define CTX_RIP (ucontext->sc_rip)
|
||||
# define CTX_RSP (ucontext->sc_rsp)
|
||||
# elif defined(__sun__)
|
||||
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||
# else
|
||||
# error "Unknown platform"
|
||||
# endif
|
||||
|
||||
CTX_DECLARE(raw_context);
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
{
|
||||
std::lock_guard<std::mutex> 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);
|
||||
*mcl::bit_cast<u64*>(CTX_RSP) = fc.ret_rip;
|
||||
CTX_RIP = fc.call_rip;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP);
|
||||
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
|
||||
# if defined(__APPLE__)
|
||||
# define CTX_PC (mctx->__ss.__pc)
|
||||
# define CTX_SP (mctx->__ss.__sp)
|
||||
# define CTX_LR (mctx->__ss.__lr)
|
||||
# define CTX_X(i) (mctx->__ss.__x[i])
|
||||
# define CTX_Q(i) (mctx->__ns.__v[i])
|
||||
# elif defined(__linux__)
|
||||
# define CTX_PC (mctx.pc)
|
||||
# define CTX_SP (mctx.sp)
|
||||
# define CTX_LR (mctx.regs[30])
|
||||
# define CTX_X(i) (mctx.regs[i])
|
||||
# define CTX_Q(i) (fpctx->vregs[i])
|
||||
[[maybe_unused]] const auto fpctx = [&mctx] {
|
||||
_aarch64_ctx* header = (_aarch64_ctx*)&mctx.__reserved;
|
||||
while (header->magic != FPSIMD_MAGIC) {
|
||||
ASSERT(header->magic && header->size);
|
||||
header = (_aarch64_ctx*)((char*)header + header->size);
|
||||
}
|
||||
return (fpsimd_context*)header;
|
||||
}();
|
||||
# elif defined(__FreeBSD__)
|
||||
# define CTX_PC (mctx.mc_gpregs.gp_elr)
|
||||
# define CTX_SP (mctx.mc_gpregs.gp_sp)
|
||||
# define CTX_LR (mctx.mc_gpregs.gp_lr)
|
||||
# define CTX_X(i) (mctx.mc_gpregs.gp_x[i])
|
||||
# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i])
|
||||
# elif defined(__NetBSD__)
|
||||
# define CTX_PC (mctx.mc_gpregs.gp_elr)
|
||||
# define CTX_SP (mctx.mc_gpregs.gp_sp)
|
||||
# define CTX_LR (mctx.mc_gpregs.gp_lr)
|
||||
# define CTX_X(i) (mctx.mc_gpregs.gp_x[i])
|
||||
# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i])
|
||||
# elif defined(__OpenBSD__)
|
||||
# define CTX_PC (ucontext->sc_elr)
|
||||
# define CTX_SP (ucontext->sc_sp)
|
||||
# define CTX_LR (ucontext->sc_lr)
|
||||
# define CTX_X(i) (ucontext->sc_x[i])
|
||||
# define CTX_Q(i) (ucontext->sc_q[i])
|
||||
# else
|
||||
# error "Unknown platform"
|
||||
# endif
|
||||
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
{
|
||||
std::lock_guard<std::mutex> 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;
|
||||
}
|
||||
}
|
||||
|
||||
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
|
||||
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
|
||||
ASSERT_FALSE("Unimplemented");
|
||||
|
||||
#else
|
||||
|
||||
# error "Invalid architecture"
|
||||
|
||||
#endif
|
||||
|
||||
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus;
|
||||
|
@ -309,13 +210,13 @@ private:
|
|||
ExceptionHandler::ExceptionHandler() = default;
|
||||
ExceptionHandler::~ExceptionHandler() = default;
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
void ExceptionHandler::Register(X64::BlockOfCode& code) {
|
||||
const u64 code_begin = mcl::bit_cast<u64>(code.getCode());
|
||||
const u64 code_end = code_begin + code.GetTotalCodeSize();
|
||||
impl = std::make_unique<Impl>(code_begin, code_end);
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
|
||||
const u64 code_end = code_begin + size;
|
||||
|
|
121
src/dynarmic/src/dynarmic/common/context.h
Normal file
121
src/dynarmic/src/dynarmic/common/context.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <signal.h>
|
||||
# include <sys/ucontext.h>
|
||||
#else
|
||||
# include <signal.h>
|
||||
# ifndef __OpenBSD__
|
||||
# include <ucontext.h>
|
||||
# endif
|
||||
# ifdef __sun__
|
||||
# include <sys/regset.h>
|
||||
# endif
|
||||
# ifdef __linux__
|
||||
# include <sys/syscall.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
# ifdef __OpenBSD__
|
||||
# define CTX_DECLARE(raw_context) ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
|
||||
# else
|
||||
# define CTX_DECLARE(raw_context) \
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context); \
|
||||
[[maybe_unused]] auto& mctx = ucontext->uc_mcontext;
|
||||
# endif
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
# ifdef __OpenBSD__
|
||||
# define CTX_DECLARE(raw_context) ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
|
||||
# else
|
||||
# define CTX_DECLARE(raw_context) \
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context); \
|
||||
[[maybe_unused]] auto& mctx = ucontext->uc_mcontext; \
|
||||
[[maybe_unused]] const auto fpctx = GetFloatingPointState(mctx);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# if defined(__APPLE__)
|
||||
# define CTX_RIP (mctx->__ss.__rip)
|
||||
# define CTX_RSP (mctx->__ss.__rsp)
|
||||
# elif defined(__linux__)
|
||||
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||
# elif defined(__FreeBSD__)
|
||||
# define CTX_RIP (mctx.mc_rip)
|
||||
# define CTX_RSP (mctx.mc_rsp)
|
||||
# elif defined(__NetBSD__)
|
||||
# define CTX_RIP (mctx.__gregs[_REG_RIP])
|
||||
# define CTX_RSP (mctx.__gregs[_REG_RSP])
|
||||
# elif defined(__OpenBSD__)
|
||||
# define CTX_RIP (ucontext->sc_rip)
|
||||
# define CTX_RSP (ucontext->sc_rsp)
|
||||
# elif defined(__sun__)
|
||||
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||
# else
|
||||
# error "Unknown platform"
|
||||
# endif
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
# if defined(__APPLE__)
|
||||
# define CTX_PC (mctx->__ss.__pc)
|
||||
# define CTX_SP (mctx->__ss.__sp)
|
||||
# define CTX_LR (mctx->__ss.__lr)
|
||||
# define CTX_PSTATE (mctx->__ss.__cpsr)
|
||||
# define CTX_X(i) (mctx->__ss.__x[i])
|
||||
# define CTX_Q(i) (mctx->__ns.__v[i])
|
||||
# define CTX_FPSR (mctx->__ns.__fpsr)
|
||||
# define CTX_FPCR (mctx->__ns.__fpcr)
|
||||
# elif defined(__linux__)
|
||||
# define CTX_PC (mctx.pc)
|
||||
# define CTX_SP (mctx.sp)
|
||||
# define CTX_LR (mctx.regs[30])
|
||||
# define CTX_PSTATE (mctx.pstate)
|
||||
# define CTX_X(i) (mctx.regs[i])
|
||||
# define CTX_Q(i) (fpctx->vregs[i])
|
||||
# define CTX_FPSR (fpctx->fpsr)
|
||||
# define CTX_FPCR (fpctx->fpcr)
|
||||
# elif defined(__FreeBSD__)
|
||||
# define CTX_PC (mctx.mc_gpregs.gp_elr)
|
||||
# define CTX_SP (mctx.mc_gpregs.gp_sp)
|
||||
# define CTX_LR (mctx.mc_gpregs.gp_lr)
|
||||
# define CTX_X(i) (mctx.mc_gpregs.gp_x[i])
|
||||
# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i])
|
||||
# elif defined(__NetBSD__)
|
||||
# define CTX_PC (mctx.mc_gpregs.gp_elr)
|
||||
# define CTX_SP (mctx.mc_gpregs.gp_sp)
|
||||
# define CTX_LR (mctx.mc_gpregs.gp_lr)
|
||||
# define CTX_X(i) (mctx.mc_gpregs.gp_x[i])
|
||||
# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i])
|
||||
# elif defined(__OpenBSD__)
|
||||
# define CTX_PC (ucontext->sc_elr)
|
||||
# define CTX_SP (ucontext->sc_sp)
|
||||
# define CTX_LR (ucontext->sc_lr)
|
||||
# define CTX_X(i) (ucontext->sc_x[i])
|
||||
# define CTX_Q(i) (ucontext->sc_q[i])
|
||||
# else
|
||||
# error "Unknown platform"
|
||||
# endif
|
||||
#else
|
||||
# error "unimplemented"
|
||||
#endif
|
||||
|
||||
#ifdef ARCHITECTURE_arm64
|
||||
#ifdef __APPLE__
|
||||
inline _STRUCT_ARM_NEON_STATE64* GetFloatingPointState(mcontext_t& host_ctx) {
|
||||
return &(host_ctx->__ns);
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
inline 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<char*>(header) + header->size);
|
||||
}
|
||||
return reinterpret_cast<fpsimd_context*>(header);
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -133,6 +133,8 @@ target_include_directories(dynarmic_tests PRIVATE . ../src)
|
|||
target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS})
|
||||
target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=1)
|
||||
|
||||
target_compile_options(dynarmic_tests PRIVATE -mavx2)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_compile_options(dynarmic_tests PRIVATE -mavx2)
|
||||
endif()
|
||||
|
||||
add_test(dynarmic_tests dynarmic_tests --durations yes)
|
||||
|
|
|
@ -19,7 +19,7 @@ add_library(network STATIC
|
|||
|
||||
create_target_directory_groups(network)
|
||||
|
||||
target_link_libraries(network PRIVATE common enet Boost::headers)
|
||||
target_link_libraries(network PRIVATE common enet::enet Boost::headers)
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
|
||||
target_link_libraries(network PRIVATE web_service)
|
||||
|
|
|
@ -376,7 +376,7 @@ if (APPLE)
|
|||
|
||||
if (NOT USE_SYSTEM_MOLTENVK)
|
||||
set(MOLTENVK_PLATFORM "macOS")
|
||||
set(MOLTENVK_VERSION "v1.3.0")
|
||||
set(MOLTENVK_VERSION "v1.4.0")
|
||||
download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION})
|
||||
endif()
|
||||
find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue