From 9d18ecc5cbcc295d04dec3ee48cb0d5547ea20fd Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 8 Jul 2026 17:41:03 -0700 Subject: [PATCH] FEXCore: Fixes a crash with multiblock if `ProcessorID` IR op is encountered If during multiblock code discovery a RDTSCP/RDPID instruction was encountered then ProcessorID has an assert at JIT compile time. Make sure to early exit with an illegal instruction encoding early instead. Also make sure to correctly report RDPID support in CPUID, it's technically a different bit than RDTSCP. Fixes a crash in Crusader Kings 3's Paradox Launcher installer. Although the installer seems to fail otherwise for some reason. --- FEXCore/Source/Interface/Core/CPUID.cpp | 9 ++++++++- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/FEXCore/Source/Interface/Core/CPUID.cpp b/FEXCore/Source/Interface/Core/CPUID.cpp index cab6eaf65..ac5f5c14b 100644 --- a/FEXCore/Source/Interface/Core/CPUID.cpp +++ b/FEXCore/Source/Interface/Core/CPUID.cpp @@ -650,6 +650,13 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_06h(uint32_t Leaf) const { FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const { FEXCore::CPUID::FunctionResults Res {}; if (Leaf == 0) { +#ifndef _WIN32 + constexpr uint32_t SUPPORTS_RDPID = 1; +#else + // RDPID under WIN32 is only supported if CPUIndex is available in TPIDRRO. + const uint32_t SUPPORTS_RDPID = SupportsCPUIndexInTPIDRRO; +#endif + // Disable Enhanced REP MOVS when TSO is enabled. // vcruntime140 memmove will use `rep movsb` in this case which completely destroys perf in Hades(appId 1145360) // This is due to LRCPC performance on Cortex being abysmal. @@ -715,7 +722,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const { (0 << 19) | // MPX MAWAU (0 << 20) | // MPX MAWAU (0 << 21) | // MPX MAWAU - (1 << 22) | // RDPID Read Processor ID + (SUPPORTS_RDPID << 22) | // RDPID Read Processor ID (0 << 23) | // AES Key Locker (1 << 24) | // bus-lock-detect (0 << 25) | // CLDEMOTE diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index b4541e6fc..31f9eddc0 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5037,7 +5037,11 @@ void OpDispatchBuilder::RDTSCPOp(OpcodeArgs) { // - Explicitly use an MFENCE before this instruction if you want this behaviour // This instruction is not an execution fence, so subsequent instructions can execute after this // - Explicitly use an LFENCE after RDTSCP if you want to block this behaviour - + 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; + } auto Counter = CycleCounter(true); auto ID = _ProcessorID(); @@ -5047,6 +5051,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()); }