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
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
|