You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

150 lines
3.7 KiB

// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <atomic>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/arm/nce/arm_nce_asm_definitions.h"
#ifdef __linux__
#include <unistd.h>
#include <sys/syscall.h>
#include <signal.h>
#endif
namespace Core {
class ArmNce;
class System;
struct HostContext {
alignas(16) std::array<u64, 12> host_saved_regs{};
alignas(16) std::array<u128, 8> host_saved_vregs{};
u64 host_sp{};
void* host_tpidr_el0{};
};
struct GuestContext {
std::array<u64, 31> cpu_registers{};
u64 sp{};
u64 pc{};
u32 fpcr{};
u32 fpsr{};
std::array<u128, 32> vector_registers{};
u32 pstate{};
alignas(16) HostContext host_ctx{};
u64 tpidrro_el0{};
u64 tpidr_el0{};
std::atomic<u64> esr_el1{};
u32 nzcv{};
u32 svc{};
System* system{};
ArmNce* parent{};
};
class KernelContext {
public:
#if defined(__linux__)
KernelContext(void* ptr_) : ptr(static_cast<mcontext_t *>(ptr_)), fpsimd{GetFloatingPointState(ptr)} {}
u64* pc() {
// u64 (unsigned long) does not equal unsigned long long
// thank you gcc
return reinterpret_cast<u64*>(&ptr->pc);
}
u64* sp() {
return reinterpret_cast<u64*>(&ptr->sp);
}
u64* regs() {
return reinterpret_cast<u64*>(&ptr->regs);
}
u128* vregs() {
// returns __uint128, u128 is a std::array
return reinterpret_cast<u128*>(&fpsimd->vregs);
}
u32* fpcr() {
return &fpsimd->fpcr;
}
u32* fpsr() {
return &fpsimd->fpsr;
}
u32* pstate() {
// only first 32 bits are used
return reinterpret_cast<u32*>(&ptr->pstate);
}
#elif defined(__APPLE__)
KernelContext(void* ptr) : ptr(static_cast<mcontext_t *>(ptr)) {}
u64* pc() {
return &(*ptr)->__ss.__pc;
}
u64* sp() {
return &(*ptr)->__ss.__sp;
}
u64* regs() {
return (*ptr)->__ss.__x;
}
u128* vregs() {
// .__v returns __uint128, u128 is an std::array
return reinterpret_cast<u128 *>((*ptr)->__ns.__v);
}
u32* fpcr() {
return &(*ptr)->__ns.__fpcr;
}
u32* fpsr() {
return &(*ptr)->__ns.__fpsr;
}
u32* pstate() {
return &(*ptr)->__ss.__cpsr;
}
#endif
private:
mcontext_t* ptr;
#ifdef __linux__
fpsimd_context* fpsimd;
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
};
// Verify assembly offsets.
static_assert(offsetof(GuestContext, sp) == GuestContextSp);
static_assert(offsetof(GuestContext, host_ctx) == GuestContextHostContext);
static_assert(offsetof(HostContext, host_sp) == HostContextSpTpidrEl0);
static_assert(offsetof(HostContext, host_tpidr_el0) - 8 == HostContextSpTpidrEl0);
static_assert(offsetof(HostContext, host_tpidr_el0) == HostContextTpidrEl0);
static_assert(offsetof(HostContext, host_saved_regs) == HostContextRegs);
static_assert(offsetof(HostContext, host_saved_vregs) == HostContextVregs);
#ifdef TARGET_OS_MAC
// ensure that fp and lr are next to the rest of the x registers so they can be accessed like an array
static_assert(offsetof(_STRUCT_ARM_THREAD_STATE64, __sp) - offsetof(_STRUCT_ARM_THREAD_STATE64, __x) == sizeof(u64) * 31);
#endif
} // namespace Core