From a3490aad5bd2de51d5a3b34f5522085c815edc93 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 26 Aug 2021 01:27:07 -0700 Subject: [PATCH] Hangover: Initial support for the syscall handling. Hangover currently abuses the syscall op for thunking purposes. Very likely this will be changed in the future but for now make sure to support that use case. --- .../Interface/Core/OpcodeDispatcher.cpp | 48 +++++++++++++++---- .../include/FEXCore/HLE/SyscallHandler.h | 1 + 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index b11513d7f..0d155a366 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -75,13 +75,25 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { }; static_assert(GPRIndexes_64.size() == GPRIndexes_32.size()); + static std::array GPRIndexes_Hangover = { + FEXCore::X86State::REG_RCX, + }; + + size_t NumArguments{}; + const auto OSABI = CTX->SyscallHandler->GetOSABI(); if (OSABI == FEXCore::HLE::SyscallOSABI::OS_LINUX64) { + NumArguments = GPRIndexes_64.size(); GPRIndexes = &GPRIndexes_64; } else if (OSABI == FEXCore::HLE::SyscallOSABI::OS_LINUX32) { + NumArguments = GPRIndexes_64.size(); GPRIndexes = &GPRIndexes_32; } + else if (OSABI == FEXCore::HLE::SyscallOSABI::OS_HANGOVER) { + NumArguments = 1; + GPRIndexes = &GPRIndexes_Hangover; + } else { LogMan::Msg::D("Unhandled OSABI syscall"); } @@ -91,16 +103,34 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { _StoreContext(GPRClass, GPRSize, offsetof(FEXCore::Core::CPUState, rip), NewRIP); const auto& GPRIndicesRef = *GPRIndexes; - auto SyscallOp = _Syscall( - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[0] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[1] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[2] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[3] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[4] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[5] * 8, GPRClass), - _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[6] * 8, GPRClass)); - _StoreContext(GPRClass, GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), SyscallOp); + OrderedNode *Arguments[SyscallArgs] { + InvalidNode, + InvalidNode, + InvalidNode, + InvalidNode, + InvalidNode, + InvalidNode, + InvalidNode, + }; + for (size_t i = 0; i < NumArguments; ++i) { + Arguments[i] = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndicesRef[i] * 8, GPRClass); + } + + auto SyscallOp = _Syscall( + Arguments[0], + Arguments[1], + Arguments[2], + Arguments[3], + Arguments[4], + Arguments[5], + Arguments[6]); + + if (OSABI != FEXCore::HLE::SyscallOSABI::OS_HANGOVER) { + // Hangover doesn't want us returning a result here + // syscall is being abused as a thunk for now. + _StoreContext(GPRClass, GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), SyscallOp); + } } void OpDispatchBuilder::ThunkOp(OpcodeArgs) { diff --git a/External/FEXCore/include/FEXCore/HLE/SyscallHandler.h b/External/FEXCore/include/FEXCore/HLE/SyscallHandler.h index c18bae408..489d6a226 100644 --- a/External/FEXCore/include/FEXCore/HLE/SyscallHandler.h +++ b/External/FEXCore/include/FEXCore/HLE/SyscallHandler.h @@ -32,6 +32,7 @@ namespace FEXCore::HLE { OS_LINUX32, OS_WIN64, OS_WIN32, + OS_HANGOVER, }; class SyscallHandler {