From 91bbce5a96b9e1eaa32f95f440ea8b46bbfbdf20 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 10 Sep 2026 09:50:07 -0700 Subject: [PATCH] FEXCore/OpcodeDispatcher: Fixes syscall instruction on Linux I forgot on Linux by default we didn't have the syscall instructions count as block end. Change this so that it counts as block end now. This has the additional benefit that now the frontend needs to modify the RIP manually as well which is fine as it's what arm64ec and wow64 does. Also add back the UnimplementedOp in RDPID that accidentally got caught up. Also increment DiskCache version as both changes will change codegen. Fixes #5942 --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 5 +++++ FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp | 2 +- .../Source/Interface/Core/X86Tables/SecondaryTables.cpp | 4 ++-- FEXCore/Source/Interface/Core/X86Tables/X86Tables.h | 7 ------- FEXCore/include/FEXCore/Core/DiskCache.h | 2 +- Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | 4 ++++ 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 22c7e46b8..9c4957fc9 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5013,6 +5013,11 @@ void OpDispatchBuilder::RDTSCPOp(OpcodeArgs) { } void OpDispatchBuilder::RDPIDOp(OpcodeArgs) { + if (CTX->HostFeatures.HostType != FEXCore::HostFeatures::HostTypeEnum::Linux && !CTX->HostFeatures.SupportsCPUIndexInTPIDRRO) { + // RDTSCP is unsupported on Win32 platforms if TPIDRRO isn't supported. + UnimplementedOp(Op); + return; + } StoreResultGPR(Op, _ProcessorID()); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index feb3dfb4f..c8e867d47 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -362,7 +362,7 @@ const std::array BaseOps = []() consteval { {0xCA, 1, X86InstInfo{"RETF", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END, 2}}, {0xCB, 1, X86InstInfo{"RETF", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0}}, {0xCC, 1, X86InstInfo{"INT3", TYPE_INST, FLAGS_BLOCK_END, 0}}, - {0xCD, 1, X86InstInfo{"INT", TYPE_INST, DEFAULT_SYSCALL_FLAGS, 1}}, + {0xCD, 1, X86InstInfo{"INT", TYPE_INST, FLAGS_NO_OVERLAY | FLAGS_BLOCK_END, 1}}, {0xCE, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_NONE, 0, { .Indirect = Primary_ArchSelect_LUT[ENTRY_CE] }}}, {0xCF, 1, X86InstInfo{"IRET", TYPE_INST, FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0}}, diff --git a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp index aa7295918..02948a36e 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp @@ -26,8 +26,8 @@ enum Secondary_LUT { constexpr std::array Secondary_ArchSelect_LUT = {{ { - {"SYSCALL", TYPE_INST, DEFAULT_SYSCALL_FLAGS, 0, { .OpDispatch = &IR::OpDispatchBuilder::NOPOp } }, - {"SYSCALL", TYPE_INST, DEFAULT_SYSCALL_FLAGS, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::SyscallOp, true> } }, + {"SYSCALL", TYPE_INST, FLAGS_NO_OVERLAY | FLAGS_BLOCK_END, 0, { .OpDispatch = &IR::OpDispatchBuilder::NOPOp } }, + {"SYSCALL", TYPE_INST, FLAGS_NO_OVERLAY | FLAGS_BLOCK_END, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::SyscallOp, true> } }, }, { {"PUSH FS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } }, diff --git a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h index bae27564a..281379799 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h +++ b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h @@ -419,13 +419,6 @@ namespace InstFlags { constexpr InstFlagType SIZE_256BIT = 0b110; constexpr InstFlagType SIZE_64BITDEF = 0b111; // Default mode is 64bit instead of typical 32bit -#ifndef _WIN32 - constexpr uint32_t DEFAULT_SYSCALL_FLAGS = FLAGS_NO_OVERLAY; -#else - // Syscall ends a block on WIN32 because the instruction can update the CPU's RIP. - constexpr uint32_t DEFAULT_SYSCALL_FLAGS = FLAGS_NO_OVERLAY | FLAGS_BLOCK_END; -#endif - constexpr InstFlagType GetSizeDstFlags(InstFlagType Flags) { return (Flags >> FLAGS_SIZE_DST_OFF) & SIZE_MASK; } diff --git a/FEXCore/include/FEXCore/Core/DiskCache.h b/FEXCore/include/FEXCore/Core/DiskCache.h index abc4d2727..617cac42c 100644 --- a/FEXCore/include/FEXCore/Core/DiskCache.h +++ b/FEXCore/include/FEXCore/Core/DiskCache.h @@ -223,7 +223,7 @@ namespace DiskCache { // TODO: This header is in global installed header path, but uses internal headers. // Migrate this once that is fixed. - static constexpr uint16_t FormatVersion = 19; + static constexpr uint16_t FormatVersion = 20; FEX_DEFAULT_VISIBILITY uint16_t GetFormatVersion(); } // namespace DiskCache diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp index 01600e605..6f4f19fc9 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp @@ -887,6 +887,10 @@ void SyscallHandler::HandleSyscall(FEXCore::Core::CpuStateFrame* Frame) { } else { HandleSyscallImpl(Frame, JITPC); } + + // Skip past the `syscall` or `int 0x80` instruction. Both of which are 2-bytes. + auto Thread = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); + Thread->Thread->CurrentFrame->State.rip += 2; } #ifdef DEBUG_STRACE