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.
174 lines
3.7 KiB
174 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"
|
|
|
|
#ifdef __linux__
|
|
#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<ucontext_t *>(ptr_)->uc_mcontext), 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<ucontext_t>(ptr).uc_mcontext) {}
|
|
|
|
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;
|
|
}
|
|
#elif defined(__WIN32)
|
|
KernelContext(void* ptr) : ptr(static_cast<ARM64_NT_CONTEXT*>(ptr)) {}
|
|
|
|
u64* pc() {
|
|
return ptr->Pc;
|
|
}
|
|
|
|
u64* sp() {
|
|
return ptr->Sp;
|
|
}
|
|
|
|
u64* regs() {
|
|
return ptr->X;
|
|
}
|
|
|
|
u128* vregs() {
|
|
// V returns ARM64_NT_NEON128, u128 is an std::array
|
|
return reinterpret_cast<u128 *>(ptr->V);
|
|
}
|
|
|
|
u32* fpcr() {
|
|
return &ptr->Fpcr;
|
|
}
|
|
|
|
u32* fpsr() {
|
|
return &ptr->Fpsr;
|
|
}
|
|
|
|
u32* pstate() {
|
|
return &ptr->Cpsr;
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
#if defined(__APPLE__)
|
|
mcontext_t ptr;
|
|
#elif defined(__linux__)
|
|
mcontext_t* ptr;
|
|
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);
|
|
}
|
|
#elif defined(__WIN32)
|
|
ARM64_NT_CONTEXT* ptr;
|
|
#endif
|
|
};
|
|
|
|
#ifdef __APPLE__
|
|
// 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
|