flycast/core/linux/context.cpp

121 lines
3.7 KiB
C++

#include "oslib/host_context.h"
#if defined(__ANDROID__)
#include <asm/sigcontext.h>
#else
#if defined(__APPLE__)
#define _XOPEN_SOURCE 1
#define __USE_GNU 1
#endif
#if !defined(TARGET_NO_EXCEPTIONS)
#include <ucontext.h>
#endif
#endif
//////
#define MCTX(p) (((ucontext_t *)(segfault_ctx))->uc_mcontext p)
template <bool ToSegfault, typename Tctx, typename Tseg>
static void bicopy(Tctx& ctx, Tseg& seg)
{
static_assert(sizeof(Tctx) == sizeof(Tseg), "Invalid assignment");
if (ToSegfault)
seg = (Tseg)ctx;
else
ctx = (Tctx)seg;
}
template<bool ToSegfault>
static void context_segfault(host_context_t* hostctx, void* segfault_ctx)
{
#if !defined(TARGET_NO_EXCEPTIONS)
#if HOST_CPU == CPU_ARM
#if defined(__FreeBSD__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.__gregs[_REG_PC]));
for (int i = 0; i < 15; i++)
bicopy<ToSegfault>(hostctx->reg[i], MCTX(.__gregs[i]));
#elif defined(__unix__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.arm_pc));
u32* reg =(u32*) &MCTX(.arm_r0);
for (int i = 0; i < 15; i++)
bicopy<ToSegfault>(hostctx->reg[i], reg[i]);
#elif defined(__APPLE__)
bicopy<ToSegfault>(hostctx->pc, MCTX(->__ss.__pc));
for (int i = 0; i < 15; i++)
bicopy<ToSegfault>(hostctx->reg[i], MCTX(->__ss.__r[i]));
#else
#error "Unsupported OS"
#endif
#elif HOST_CPU == CPU_ARM64
#if defined(__APPLE__)
bicopy<ToSegfault>(hostctx->pc, MCTX(->__ss.__pc));
bicopy<ToSegfault>(hostctx->x0, MCTX(->__ss.__x[0]));
#else
bicopy<ToSegfault>(hostctx->pc, MCTX(.pc));
bicopy<ToSegfault>(hostctx->x0, MCTX(.regs[0]));
#endif
#elif HOST_CPU == CPU_X86
#if defined(__FreeBSD__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.mc_eip));
bicopy<ToSegfault>(hostctx->esp, MCTX(.mc_esp));
bicopy<ToSegfault>(hostctx->eax, MCTX(.mc_eax));
bicopy<ToSegfault>(hostctx->ecx, MCTX(.mc_ecx));
#elif defined(__unix__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.gregs[REG_EIP]));
bicopy<ToSegfault>(hostctx->esp, MCTX(.gregs[REG_ESP]));
bicopy<ToSegfault>(hostctx->eax, MCTX(.gregs[REG_EAX]));
bicopy<ToSegfault>(hostctx->ecx, MCTX(.gregs[REG_ECX]));
#elif defined(__APPLE__)
bicopy<ToSegfault>(hostctx->pc, MCTX(->__ss.__eip));
bicopy<ToSegfault>(hostctx->esp, MCTX(->__ss.__esp));
bicopy<ToSegfault>(hostctx->eax, MCTX(->__ss.__eax));
bicopy<ToSegfault>(hostctx->ecx, MCTX(->__ss.__ecx));
#else
#error "Unsupported OS"
#endif
#elif HOST_CPU == CPU_X64
#if defined(__FreeBSD__) || defined(__DragonFly__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.mc_rip));
#elif defined(__NetBSD__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.__gregs[_REG_RIP]));
bicopy<ToSegfault>(hostctx->rsp, MCTX(.__gregs[REG_RSP]));
bicopy<ToSegfault>(hostctx->r9, MCTX(.__gregs[REG_R9]));
bicopy<ToSegfault>(hostctx->rdi, MCTX(.__gregs[REG_RDI]));
#elif defined(__unix__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.gregs[REG_RIP]));
bicopy<ToSegfault>(hostctx->rsp, MCTX(.gregs[REG_RSP]));
bicopy<ToSegfault>(hostctx->r9, MCTX(.gregs[REG_R9]));
bicopy<ToSegfault>(hostctx->rdi, MCTX(.gregs[REG_RDI]));
#elif defined(__APPLE__)
bicopy<ToSegfault>(hostctx->pc, MCTX(->__ss.__rip));
bicopy<ToSegfault>(hostctx->rsp, MCTX(->__ss.__rsp));
bicopy<ToSegfault>(hostctx->r9, MCTX(->__ss.__r9));
bicopy<ToSegfault>(hostctx->rdi, MCTX(->__ss.__rdi));
#else
#error "Unsupported OS"
#endif
#elif HOST_CPU == CPU_MIPS
bicopy<ToSegfault>(hostctx->pc, MCTX(.pc));
#elif HOST_CPU == CPU_GENERIC
//nothing!
#else
#error Unsupported HOST_CPU
#endif
#endif
}
void context_from_segfault(host_context_t* hostctx, void* segfault_ctx) {
context_segfault<false>(hostctx, segfault_ctx);
}
void context_to_segfault(host_context_t* hostctx, void* segfault_ctx) {
context_segfault<true>(hostctx, segfault_ctx);
}