From 8b0229eda0282ec0c6b278f7bd7696ad4d887b2b Mon Sep 17 00:00:00 2001 From: Exverge Date: Tue, 14 Jul 2026 17:19:28 -0400 Subject: [PATCH] Make Windows NCE code actually compliable --- src/common/host_memory.cpp | 42 ++++++++++++- src/core/CMakeLists.txt | 4 +- src/core/arm/nce/arm_nce.cpp | 82 +++++++++++++++++-------- src/core/arm/nce/arm_nce.h | 22 +++++-- src/core/arm/nce/guest_context.h | 26 ++++---- src/core/arm/nce/patcher.cpp | 31 +++++----- src/core/arm/nce/patcher.h | 4 +- src/core/arm/nce/win/exceptions.cpp | 29 --------- src/core/arm/nce/win/exceptions.h | 18 ------ src/core/arm/nce/win/nt_headers.h | 14 ----- src/core/arm/nce/win/platform_visitor.h | 2 +- src/core/hle/kernel/k_thread.h | 2 +- 12 files changed, 147 insertions(+), 129 deletions(-) delete mode 100644 src/core/arm/nce/win/exceptions.cpp delete mode 100644 src/core/arm/nce/win/exceptions.h delete mode 100644 src/core/arm/nce/win/nt_headers.h diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index a4e9559af4..36cbc59efc 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -110,6 +110,9 @@ using PFN_MapViewOfFile3 = _Ret_maybenull_ PVOID(WINAPI*)( using PFN_UnmapViewOfFile2 = BOOL(WINAPI*)(_In_ HANDLE Process, _In_ PVOID BaseAddress, _In_ ULONG UnmapFlags); +using PFN_VirtualQuery = SIZE_T(WINAPI*) ( + _In_opt_ LPCVOID lpAddress, _Out_ PMEMORY_BASIC_INFORMATION lpBuffer, _In_ SIZE_T dwLength); + template static void GetFuncAddress(Common::DynamicLibrary& dll, const char* name, T& pfn) { if (!dll.GetSymbol(name, &pfn)) { @@ -134,10 +137,11 @@ public: } GetFuncAddress(kernelbase_dll, "CreateFileMapping2", pfn_CreateFileMapping2); GetFuncAddress(kernelbase_dll, "VirtualAlloc2", pfn_VirtualAlloc2); + GetFuncAddress(kernelbase_dll, "VirtualQuery", pfn_VirtualQuery); GetFuncAddress(kernelbase_dll, "MapViewOfFile3", pfn_MapViewOfFile3); GetFuncAddress(kernelbase_dll, "UnmapViewOfFile2", pfn_UnmapViewOfFile2); - if (!pfn_CreateFileMapping2 || !pfn_VirtualAlloc2 || !pfn_MapViewOfFile3 || !pfn_UnmapViewOfFile2) { + if (!pfn_CreateFileMapping2 || !pfn_VirtualAlloc2 || !pfn_VirtualQuery || !pfn_MapViewOfFile3 || !pfn_UnmapViewOfFile2) { LOG_CRITICAL(HW_Memory, "Failed to find functions for virtual allocs"); return false; } @@ -162,8 +166,39 @@ public: LOG_CRITICAL(HW_Memory, "Failed to map {} MiB of virtual memory", backing_size >> 20); return false; } - // Allocate virtual address placeholder - virtual_base = static_cast(pfn_VirtualAlloc2(process, nullptr, virtual_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0)); + + // Allocate virtual address placeholder within a 39-bit address space + SIZE_T cursor = 0; + while (cursor < (1ULL << 39) - virtual_size) { + MEMORY_BASIC_INFORMATION info{}; + + // find the next mapped region of memory + auto res = pfn_VirtualQuery(reinterpret_cast(cursor), &info, sizeof(info)); + + if (res == 0) { + LOG_WARNING(HW_Memory, "Failed to check memory region: {}", GetLastError()); + continue; + } + + auto start_aligned = AlignUp(reinterpret_cast(info.BaseAddress), HugePageSize); + // is this region free? + if (info.State == MEM_FREE && start_aligned < reinterpret_cast(info.BaseAddress) + info.RegionSize) { + // is this region big enough for us to use? + if (info.RegionSize - (start_aligned - reinterpret_cast(info.BaseAddress)) >= virtual_size) { + virtual_base = static_cast(pfn_VirtualAlloc2 + (process, reinterpret_cast(start_aligned), virtual_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0)); + } + } + + cursor = reinterpret_cast(info.BaseAddress) + info.RegionSize; + } + // Check if we failed to allocate for direct-mapping, otherwise map normally + if (!virtual_base) { + LOG_WARNING(HW_Memory, "Failed to allocate within 39-bit address space, direct mapping is not supported"); + virtual_base = static_cast(pfn_VirtualAlloc2 + (process, nullptr, virtual_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0)); + } + if (!virtual_base) { Release(); LOG_CRITICAL(HW_Memory, "Failed to reserve {} GiB of virtual memory", virtual_size >> 30); @@ -383,6 +418,7 @@ private: DynamicLibrary kernelbase_dll; PFN_CreateFileMapping2 pfn_CreateFileMapping2{}; PFN_VirtualAlloc2 pfn_VirtualAlloc2{}; + PFN_VirtualQuery pfn_VirtualQuery{}; PFN_MapViewOfFile3 pfn_MapViewOfFile3{}; PFN_UnmapViewOfFile2 pfn_UnmapViewOfFile2{}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a43d5bfdfb..501a684de8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1251,9 +1251,7 @@ if (HAS_NCE) if (WIN32) target_sources(core PRIVATE arm/nce/win/platform_visitor.h - arm/nce/win/platform_visitor.cpp - arm/nce/win/exceptions.h - arm/nce/win/exceptions.cpp) + arm/nce/win/platform_visitor.cpp) endif () endif() diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index d83e5d8c12..54a061e5b8 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -37,19 +37,17 @@ #include "core/hle/kernel/k_process.h" -#ifndef __WIN32 +#ifndef _WIN32 #include #include #include -#else -#include "core/arm/nce/win/exceptions.h" #endif namespace Core { namespace { -#ifndef __WIN32 +#ifndef _WIN32 struct sigaction g_orig_bus_action; struct sigaction g_orig_segv_action; #endif @@ -72,7 +70,7 @@ void* ArmNce::GetGuestParameters() { : [out] "=&r"(nep) : [off] "i"((ContextKey - 1) * 8) : "memory"); -#elif defined(__WIN32) +#elif defined(_WIN32) asm volatile( "mrs %[out], TPIDR_EL0\n" // load windows TLS storage "ldr %[out], [ %[out], #%[off] ]\n" @@ -106,7 +104,7 @@ void ArmNce::UnlockThreadParameters(void* tpidr) { static_cast(tpidr)->lock.store(SpinLockUnlocked, std::memory_order_release); } -#ifndef __WIN32 +#ifndef _WIN32 YUZU_NAKED YUZU_NO_INLINE HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void *tpidr) { @@ -143,10 +141,10 @@ HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void *tpidr) { } YUZU_NAKED_END #else -HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void *tpidr) { - DEBUG_ASSERT(os::TlsGetValue(ContextKey) == tpidr); +HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(void* tid, void *tpidr) { + DEBUG_ASSERT(TlsGetValue(ContextKey) == tpidr); - os::RaiseException(SIGUSR2, 0, 0, nullptr); // TODO: pass tpidr through arguments? + RaiseException(ExceptionLevelChangeSignal, 0, 0, nullptr); // TODO: pass tpidr through arguments? __builtin_unreachable(); } #endif @@ -154,7 +152,7 @@ HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void *tpidr) { void ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void *info, void *raw_context) { auto tpidr = static_cast(RestoreGuestContext(raw_context)); -#if !defined(__APPLE__) && !defined(__WIN32) +#if !defined(__APPLE__) && !defined(_WIN32) // Save old value of TPIDR_EL0, load guest one u64 tpidr_el0; asm volatile("mrs %0, TPIDR_EL0\n" @@ -186,7 +184,7 @@ HaltReason ArmNce::ReturnToRunCodeByTrampoline(void *tpidr, u64 trampoline_addr) "ldr x2, [ x0, #%[ctx_off] ]\n" "add x5, x2, #%[host_ctx] \n" -#if !defined(__APPLE__) && !defined(__WIN32) +#if !defined(__APPLE__) && !defined(_WIN32) // Load guest tpidr_el0 "mrs x4, TPIDR_EL0\n" "msr TPIDR_EL0, x0\n" @@ -223,7 +221,7 @@ HaltReason ArmNce::ReturnToRunCodeByTrampoline(void *tpidr, u64 trampoline_addr) :: [ctx_off] "i"(offsetof(NativeExecutionParameters, native_context)), [sp_off] "i"(offsetof(GuestContext, sp)), [host_ctx] "i"(offsetof(GuestContext, host_ctx)) -#if defined(__APPLE__) || defined(__WIN32) +#if defined(__APPLE__) || defined(_WIN32) ,[is_running_off] "i"(offsetof(NativeExecutionParameters, is_actually_running)) #endif ); @@ -232,7 +230,7 @@ YUZU_NAKED_END static_assert(offsetof(HostContext, host_sp) == 0xE0); // TODO: don't use magic number -#ifndef __WIN32 +#ifndef _WIN32 void ArmNce::BreakFromRunCodeSignalHandler(int sig, void *info, void *raw_context) { NativeExecutionParameters* tpidr = static_cast(GetGuestParameters()); @@ -255,11 +253,9 @@ void ArmNce::BreakFromRunCodeSignalHandler(int sig, void *info, void *raw_contex #endif void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_context) { - DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS); - NativeExecutionParameters* nep = static_cast(GetGuestParameters()); -#if defined(__APPLE__) || defined(__WIN32) +#if defined(__APPLE__) || defined(_WIN32) if (nep->is_actually_running) { nep->is_actually_running = false; #else @@ -274,10 +270,14 @@ void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_co auto* guest_ctx = static_cast(nep->native_context); auto& memory = guest_ctx->parent->m_running_thread->GetOwnerProcess()->GetMemory(); +#ifndef _WIN32 if (sig == SIGSEGV) { +#else + if (sig == static_cast(EXCEPTION_ACCESS_VIOLATION)) { +#endif // Try to handle an invalid access. // TODO: handle accesses which split a page? -#ifndef __WIN32 +#ifndef _WIN32 const Common::ProcessAddress addr = (reinterpret_cast(static_cast(raw_info)->si_addr) & ~Memory::YUZU_PAGEMASK); #else @@ -288,7 +288,11 @@ void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_co // We handled the access successfully and are returning to guest code. goto ret; } +#ifndef _WIN32 } else if (sig == SIGBUS) { +#else + } else if (sig == static_cast(EXCEPTION_DATATYPE_MISALIGNMENT)) { +#endif // Match and execute an instruction. auto ctx = KernelContext(raw_context); auto next_pc = MatchAndExecuteOneInstruction(memory, &ctx); @@ -318,7 +322,7 @@ void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_co nep->is_actually_running = true; #endif } -#ifndef __WIN32 +#ifndef _WIN32 else { // Host fault, call original handler if (sig == SIGSEGV) { @@ -329,7 +333,7 @@ void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_co UNREACHABLE_MSG("unexpected signal {}", sig); } } -#elif +#else is_host_fault = true; #endif } @@ -338,7 +342,7 @@ void* ArmNce::RestoreGuestContext(void* raw_context) { // Retrieve the host context. auto host_ctx = KernelContext(raw_context); -#ifndef __WIN32 +#ifndef _WIN32 // Thread-local parameters will be located in x9. auto* tpidr = reinterpret_cast(host_ctx.regs()[9]); #else @@ -401,7 +405,11 @@ bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, voi auto host_ctx = KernelContext(raw_context); // We can't handle the access, so determine why we crashed. +#ifndef _WIN32 const bool is_prefetch_abort = *host_ctx.pc() == reinterpret_cast(static_cast(raw_info)->si_addr); +#else + const bool is_prefetch_abort = *host_ctx.pc() == *static_cast(raw_info); +#endif // 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. @@ -453,7 +461,7 @@ HaltReason ArmNce::RunThread(Kernel::KThread* thread) { #if defined(__APPLE__) ASSERT(pthread_setspecific(ContextKey, &thread_params) == 0); -#elif defined(__WIN32) +#elif defined(_WIN32) ASSERT(TlsSetValue(ContextKey, &thread_params) == 0); #endif @@ -526,6 +534,27 @@ ArmNce::ArmNce(System& system, bool uses_wall_clock, std::size_t core_index) ArmNce::~ArmNce() = default; +#ifdef _WIN32 +LONG WINAPI ArmNce::VectoredExceptionHandler(PEXCEPTION_POINTERS info) { + DWORD code = info->ExceptionRecord->ExceptionCode; + + if (code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_DATATYPE_MISALIGNMENT) { + GuestMemoryFaultSignalHandler(code, reinterpret_cast(&info->ExceptionRecord->ExceptionAddress), info->ContextRecord); + if (is_host_fault) { + is_host_fault = false; + return EXCEPTION_CONTINUE_SEARCH; + } + return EXCEPTION_CONTINUE_EXECUTION; + } else if (code == ExceptionLevelChangeSignal) { + ReturnToRunCodeByExceptionLevelChangeSignalHandler(code, reinterpret_cast(&info->ExceptionRecord->ExceptionAddress), info->ContextRecord); + return EXCEPTION_CONTINUE_EXECUTION; + } else { + // other exception? let it pass + return EXCEPTION_CONTINUE_SEARCH; + } +} +#endif + #ifdef __APPLE__ // https://github.com/apple-oss-distributions/libpthread/blob/42d026df5b07825070f60134b980a1ec2552dfee/src/pthread_tsd.c#L418-L435 extern "C" int pthread_key_init_np(int, void (*)(void *)); @@ -542,13 +571,14 @@ void ArmNce::Initialize() { if (m_thread_id == -1) { m_thread_id = gettid(); } -#elif defined(__WIN32) +#elif defined(_WIN32) if (m_thread_id == nullptr) { DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_thread_id, 0, false, DUPLICATE_SAME_ACCESS); } #endif +#ifndef _WIN32 // Configure signal stack. if (!m_stack) { m_stack = std::make_unique(StackSize); @@ -562,7 +592,6 @@ void ArmNce::Initialize() { // Set up signals. static std::once_flag flag; std::call_once(flag, [] { -#ifndef __WIN32 using HandlerType = decltype(sigaction::sa_sigaction); sigset_t signal_mask; @@ -600,10 +629,11 @@ void ArmNce::Initialize() { reinterpret_cast(&ArmNce::GuestMemoryFaultSignalHandler); access_fault_action.sa_mask = signal_mask; Common::SigAction(SIGSEGV, &access_fault_action, &g_orig_segv_action); + }); #else - AddVectoredExceptionHandler(1, VectoredExceptionHandler); + static std::once_flag flag; + std::call_once(flag, [] { AddVectoredExceptionHandler(1, VectoredExceptionHandler); }); #endif - }); } void ArmNce::SetTpidrroEl0(u64 value) { @@ -663,7 +693,7 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) { "svc #0x80\n" :: "r"(static_cast(m_thread_id)), "r"(static_cast(SIGURG)) : "x0", "x1", "x16", "memory", "cc"); -#elif defined(__WIN32) +#elif defined(_WIN32) // TODO: use SetThreadState to emulate BreakFromRunCodeSignalHandler SuspendThread(m_thread_id); UnlockThreadParameters(params); diff --git a/src/core/arm/nce/arm_nce.h b/src/core/arm/nce/arm_nce.h index 6bbdca7187..68330d5af8 100644 --- a/src/core/arm/nce/arm_nce.h +++ b/src/core/arm/nce/arm_nce.h @@ -11,6 +11,10 @@ #include "core/arm/arm_interface.h" #include "core/arm/nce/guest_context.h" +#ifdef _WIN32 +#include +#endif + #define SpinLockLocked 0 #define SpinLockUnlocked 1 @@ -28,11 +32,14 @@ class System; // so we can manually initialize and use it. // https://github.com/apple-oss-distributions/libpthread/blob/42d026df5b07825070f60134b980a1ec2552dfee/private/pthread/tsd_private.h#L241-L245 constexpr pthread_key_t ContextKey = 210; -#elif __WIN32 +#elif _WIN32 + +#define ExceptionLevelChangeSignal 0xE0000001 +thread_local bool is_host_fault = false; -static const u32 ContextKey = os::TlsAlloc(); -static const u32 NCEStorage = os::TlsAlloc(); -static const u64 TlsSlots = offsetof(os::TEB, TlsSlots); +static const u32 ContextKey = TlsAlloc(); +static const u32 NCEStorage = TlsAlloc(); +static const u64 TlsSlots = offsetof(TEB, TlsSlots); #endif @@ -77,7 +84,12 @@ private: static void* GetGuestParameters(); static HaltReason ReturnToRunCodeByTrampoline(void* tpidr, u64 trampoline_addr); +#ifndef _WIN32 static HaltReason ReturnToRunCodeByExceptionLevelChange(int tid, void* tpidr); +#else + static HaltReason ReturnToRunCodeByExceptionLevelChange(void* tid, void* tpidr); + static LONG VectoredExceptionHandler(PEXCEPTION_POINTERS info); +#endif static void ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context); @@ -96,7 +108,7 @@ public: // Members set on initialization. std::size_t m_core_index{}; -#ifndef __WIN32 +#ifndef _WIN32 pid_t m_thread_id{-1}; #else void* m_thread_id{}; diff --git a/src/core/arm/nce/guest_context.h b/src/core/arm/nce/guest_context.h index addda7d6b8..a34d435cee 100644 --- a/src/core/arm/nce/guest_context.h +++ b/src/core/arm/nce/guest_context.h @@ -14,8 +14,9 @@ #ifdef __linux__ #include -#elif __WIN32 -#include "core/arm/nce/win/nt_headers.h" +#elif _WIN32 +#include +#undef interface #endif namespace Core { @@ -116,15 +117,15 @@ public: u32* pstate() { return &ptr->__ss.__cpsr; } -#elif defined(__WIN32) - KernelContext(void* ptr) : ptr(static_cast(ptr)) {} +#elif defined(_WIN32) + KernelContext(void* ptr) : ptr(static_cast(ptr)) {} u64* pc() { - return ptr->Pc; + return &ptr->Pc; } u64* sp() { - return ptr->Sp; + return &ptr->Sp; } u64* regs() { @@ -137,15 +138,18 @@ public: } u32* fpcr() { - return &ptr->Fpcr; + // unsigned long vs unsigned int + return reinterpret_cast(&ptr->Fpcr); } u32* fpsr() { - return &ptr->Fpsr; + // unsigned long vs unsigned int + return reinterpret_cast(&ptr->Fpsr); } u32* pstate() { - return &ptr->Cpsr; + // unsigned long vs unsigned int + return reinterpret_cast(&ptr->Cpsr); } #endif @@ -163,8 +167,8 @@ private: } return reinterpret_cast(header); } -#elif defined(__WIN32) - os::CONTEXT* ptr; +#elif defined(_WIN32) + CONTEXT* ptr; #endif }; diff --git a/src/core/arm/nce/patcher.cpp b/src/core/arm/nce/patcher.cpp index 9bf2e80681..f4362fae44 100644 --- a/src/core/arm/nce/patcher.cpp +++ b/src/core/arm/nce/patcher.cpp @@ -18,7 +18,7 @@ #include "core/memory.h" #include "core/hle/kernel/k_thread.h" -#ifdef __WIN32 +#ifdef _WIN32 #include "win/platform_visitor.h" #endif @@ -169,16 +169,16 @@ bool Patcher::PatchText(std::span program_image, const Kernel::CodeSet if (auto exclusive = Exclusive{inst}; exclusive.Verify()) { curr_patch->m_exclusives.push_back(i); } -#ifdef __WIN32 - // TODO: keep track of exclusives? +#ifdef _WIN32 + // TODO: do we still keep track of exclusives? if (auto scratch = CheckForPlatformRegister(inst); scratch) { bool pre_buffer = false; auto ret = AddRelocations(pre_buffer); if (pre_buffer) { - WritePlatformRegHandler(ret, inst, scratch, c_pre); + WritePlatformRegHandler(ret, inst, *scratch, c_pre); } else { - WritePlatformRegHandler(ret, inst, scratch, c); + WritePlatformRegHandler(ret, inst, *scratch, c); } } #endif @@ -391,17 +391,16 @@ void Patcher::LoadTLS(oaknut::VectorCodeGenerator& cg, oaknut::XReg out) { // https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/libsyscall/os/tsd.h#L156-L189 cg.MRS(out, oaknut::SystemReg::TPIDRRO_EL0); cg.LDR(out, out, ContextKey * 8); -#elif __WIN32 +#elif _WIN32 // x18 always points to TEB in Windows, we can just use that for TLS storage - ASSERT(out != X18); cg.LDR(out, X18, TlsSlots + 8 * ContextKey); #else cg.MRS(out, oaknut::SystemReg::TPIDR_EL0); #endif } -#ifdef __WIN32 -void Patcher::WritePlatformRegHandler(ModuleDestLabel module_dest, uint32 instruction, oaknut::XReg scratch, oaknut::VectorCodeGenerator& code) { +#ifdef _WIN32 +void Patcher::WritePlatformRegHandler(ModuleDestLabel module_dest, u32 instruction, oaknut::XReg scratch, oaknut::VectorCodeGenerator& cg) { // Save X18 register and scratch register cg.STP(X18, scratch, SP, PRE_INDEXED, -16); @@ -410,7 +409,7 @@ void Patcher::WritePlatformRegHandler(ModuleDestLabel module_dest, uint32 instru cg.LDR(X18, scratch, TlsSlots + 8 * NCEStorage); // Perform operation - cg.append(instruction); + cg.dw(instruction); // Store x18 register and restore scratch register cg.STR(X18, scratch, TlsSlots + 8 * NCEStorage); @@ -540,7 +539,7 @@ void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id, oaknut // Reload host TPIDR_EL0 and SP. cg.LDP(X2, X3, X1, offsetof(HostContext, host_sp)); cg.MOV(SP, X2); -#if !defined(__APPLE__) && !defined(__WIN32) +#if !defined(__APPLE__) && !defined(_WIN32) static_assert(offsetof(HostContext, host_sp) + 8 == offsetof(HostContext, host_tpidr_el0)); cg.MSR(oaknut::SystemReg::TPIDR_EL0, X3); #endif @@ -608,8 +607,8 @@ void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id, oaknut // Retrieve emulated TLS register from GuestContext. void Patcher::WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg, oaknut::VectorCodeGenerator& cg) { -#ifdef __WIN32 - if (dest_reg != X18) { +#ifdef _WIN32 + if (dest_reg.index() == 18) { #endif LoadTLS(cg, dest_reg); @@ -618,7 +617,7 @@ void Patcher::WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg } else { cg.LDR(dest_reg, dest_reg, offsetof(NativeExecutionParameters, tpidr_el0)); } -#ifdef __WIN32 +#ifdef _WIN32 } else { const auto scratch = dest_reg.index() == 0 ? X1 : X0; cg.STR(scratch, SP, PRE_INDEXED, -16); @@ -646,8 +645,8 @@ void Patcher::WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg, // Save guest value to NativeExecutionParameters::tpidr_el0. LoadTLS(cg, scratch_reg); -#ifdef __WIN32 - if (src_reg == X18) { +#ifdef _WIN32 + if (src_reg.index() == 18) { // Load real x18 value and use that cg.LDR(scratch_reg2, X18, TlsSlots + 8 * NCEStorage); src_reg = scratch_reg2; diff --git a/src/core/arm/nce/patcher.h b/src/core/arm/nce/patcher.h index 3bc5bc83c4..d7ed01bacd 100644 --- a/src/core/arm/nce/patcher.h +++ b/src/core/arm/nce/patcher.h @@ -82,8 +82,8 @@ private: void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg, oaknut::VectorCodeGenerator& code); void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg, oaknut::VectorCodeGenerator& code); void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& code); -#ifdef __WIN32 - void WritePlatformRegHandler(ModuleDestLabel module_dest, uint32 instruction, oaknut::XReg scratch, oaknut::VectorCodeGenerator& code); +#ifdef _WIN32 + void WritePlatformRegHandler(ModuleDestLabel module_dest, u32 instruction, oaknut::XReg scratch, oaknut::VectorCodeGenerator& code); #endif // Convenience wrappers using default code generator diff --git a/src/core/arm/nce/win/exceptions.cpp b/src/core/arm/nce/win/exceptions.cpp deleted file mode 100644 index de64f45197..0000000000 --- a/src/core/arm/nce/win/exceptions.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/arm/nce/win/exceptions.h" - -#include "core/arm/nce/arm_nce.h" - -namespace Core { - -static s32 WINAPI VectoredExecptionHandler(os::EXCEPTION_POINTERS* info) { - u32 code = info->ExceptionRecord->ExceptionCode; - - if (code == SIGSEGV || code == SIGBUS) { - GuestMemoryFaultSignalHandler(code, &info->ExceptionRecord->ExceptionAddress, info->ContextRecord); - if (is_host_fault) { - is_host_fault = false; - return EXCEPTION_CONTINUE_SEARCH; - } - return EXCEPTION_CONTINUE_EXECUTION; - } else if (code == SIGUSR2) { - ReturnToGuestByExceptionLevelChangeSignalHandler(code, &info->ExceptionRecord->ExceptionAddress, info->ContextRecord); - return EXCEPTION_CONTINUE_EXECUTION; - } else { - // other exception?? let it pass - return EXCEPTION_CONTINUE_SEARCH; - } -} - -} // namespace Core \ No newline at end of file diff --git a/src/core/arm/nce/win/exceptions.h b/src/core/arm/nce/win/exceptions.h deleted file mode 100644 index 5a4e9c3e79..0000000000 --- a/src/core/arm/nce/win/exceptions.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "core/arm/nce/arm_nce.h" - -#define SIGBUS EXCEPTION_DATATYPE_MISALIGNMENT -#define SIGSEGV EXCEPTION_ACCESS_VIOLATION -#define SIGUSR2 0xE0000001 - -namespace Core { - -thread_local bool is_host_fault = false; - -static s32 WINAPI VectoredExecptionHandler(os::EXCEPTION_POINTERS* info); - -} // namespace Core \ No newline at end of file diff --git a/src/core/arm/nce/win/nt_headers.h b/src/core/arm/nce/win/nt_headers.h deleted file mode 100644 index 61b1d7298d..0000000000 --- a/src/core/arm/nce/win/nt_headers.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -// Use a separate namespace to not add Windows headers to the global path in header files -// We can't directly add Windows.h because of winternl.h -namespace os { -extern "C" { - #include - #include - #include -} -} // namespace os \ No newline at end of file diff --git a/src/core/arm/nce/win/platform_visitor.h b/src/core/arm/nce/win/platform_visitor.h index 458c8a5093..00d2065475 100644 --- a/src/core/arm/nce/win/platform_visitor.h +++ b/src/core/arm/nce/win/platform_visitor.h @@ -14,7 +14,7 @@ struct XReg; namespace Core { -std::optional CheckForPlatformRegister(u32 instruction); +std::optional CheckForPlatformRegister(u32 instruction); class PlatformVisitor final : public VisitorBase { public: diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 5e6e425220..148fb14e81 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -668,7 +668,7 @@ public: public: // TODO: This shouldn't be defined in kernel namespace struct NativeExecutionParameters { -#if (defined(__APPLE__) || defined(__WIN32)) && HAS_NCE +#if (defined(__APPLE__) || defined(_WIN32)) && HAS_NCE // Are we in actual guest code? bool is_actually_running{}; #endif