diff --git a/FEXCore/Source/Interface/Core/CPUID.cpp b/FEXCore/Source/Interface/Core/CPUID.cpp index f069d2ea5..b1da559b9 100644 --- a/FEXCore/Source/Interface/Core/CPUID.cpp +++ b/FEXCore/Source/Interface/Core/CPUID.cpp @@ -90,7 +90,7 @@ namespace ProductNames { #endif } // namespace ProductNames -static uint32_t GetCPUID() { +uint32_t GetCPUID_Syscall() { uint32_t CPU {}; FHU::Syscalls::getcpu(&CPU, nullptr); return CPU; @@ -138,6 +138,12 @@ uint32_t GetCycleCounterFrequency() { return Result; } +uint32_t GetCPUID_TPIDRRO() { + uint64_t Result {}; + __asm("mrs %[Res], TPIDRRO_EL0" : [Res] "=r"(Result)); + return Result; +} + void CPUIDEmu::SetupHostHybridFlag() { PerCPUData.resize(Cores); @@ -895,11 +901,11 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0000h(uint32_t Leaf) con // Extended processor and feature bits FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0001h(uint32_t Leaf) const { - // RDTSCP is disabled on WIN32/Wine because there is no sane way to query processor ID. #ifndef _WIN32 constexpr uint32_t SUPPORTS_RDTSCP = 1; #else - constexpr uint32_t SUPPORTS_RDTSCP = 0; + // RDTSCP under WIN32 is only supported if CPUIndex is available in TPIDRRO. + const uint32_t SUPPORTS_RDTSCP = SupportsCPUIndexInTPIDRRO; #endif FEXCore::CPUID::FunctionResults Res {}; @@ -1213,12 +1219,20 @@ FEXCore::CPUID::XCRResults CPUIDEmu::XCRFunction_0h() const { } CPUIDEmu::CPUIDEmu(const FEXCore::Context::ContextImpl* ctx) - : CTX {ctx} { + : CTX {ctx} + , SupportsCPUIndexInTPIDRRO {CTX->HostFeatures.SupportsCPUIndexInTPIDRRO} + , GetCPUID {GetCPUID_Syscall} { Cores = CTX->HostFeatures.CPUMIDRs.size(); // Setup some state tracking SetupHostHybridFlag(); SetupFeatures(); + +#ifdef _M_ARM_64 + if (SupportsCPUIndexInTPIDRRO) { + GetCPUID = GetCPUID_TPIDRRO; + } +#endif } } // namespace FEXCore diff --git a/FEXCore/Source/Interface/Core/CPUID.h b/FEXCore/Source/Interface/Core/CPUID.h index b8ea48576..6e9087c0f 100644 --- a/FEXCore/Source/Interface/Core/CPUID.h +++ b/FEXCore/Source/Interface/Core/CPUID.h @@ -115,6 +115,7 @@ public: private: const FEXCore::Context::ContextImpl* CTX; + bool SupportsCPUIndexInTPIDRRO {}; bool Hybrid {}; uint32_t Cores {}; FEX_CONFIG_OPT(HideHypervisorBit, HIDEHYPERVISORBIT); @@ -510,5 +511,8 @@ private: // 0x8000'001F: AMD Secure Encryption {SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT}, }}; + + using GetCPUIDPtr = uint32_t (*)(); + GetCPUIDPtr GetCPUID; }; } // namespace FEXCore diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp index e0df65d12..8699ee699 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp @@ -192,8 +192,17 @@ DEF_OP(Print) { PopDynamicRegsAndLR(); } -#ifndef _WIN32 DEF_OP(ProcessorID) { + if (CTX->HostFeatures.SupportsCPUIndexInTPIDRRO) { + mrs(GetReg(Node), ARMEmitter::SystemRegister::TPIDRRO_EL0); + return; + } +#ifdef _WIN32 + else { + // If on Windows and TPIDRRO isn't supported (like in wine), then this is a programming error. + ERROR_AND_DIE_FMT("Unsupported"); + } +#else // We always need to spill x8 since we can't know if it is live at this SSA location uint32_t SpillMask = 1U << 8; @@ -248,12 +257,8 @@ DEF_OP(ProcessorID) { // CPU is in w0 // Node is in w1 orr(ARMEmitter::Size::i64Bit, GetReg(Node), ARMEmitter::Reg::r0, ARMEmitter::Reg::r1, ARMEmitter::ShiftType::LSL, 12); -} -#else -DEF_OP(ProcessorID) { - ERROR_AND_DIE_FMT("Unsupported"); -} #endif +} DEF_OP(RDRAND) { auto Op = IROp->C(); diff --git a/FEXCore/include/FEXCore/Core/HostFeatures.h b/FEXCore/include/FEXCore/Core/HostFeatures.h index 675fc6750..e20518602 100644 --- a/FEXCore/include/FEXCore/Core/HostFeatures.h +++ b/FEXCore/include/FEXCore/Core/HostFeatures.h @@ -35,6 +35,7 @@ struct HostFeatures { bool SupportsPreserveAllABI {}; bool SupportsAES256 {}; bool SupportsSVEBitPerm {}; + bool SupportsCPUIndexInTPIDRRO {}; // Float exception behaviour bool SupportsAFP {}; diff --git a/Source/Common/HostFeatures.cpp b/Source/Common/HostFeatures.cpp index f6daee1e5..f302e95e5 100644 --- a/Source/Common/HostFeatures.cpp +++ b/Source/Common/HostFeatures.cpp @@ -630,6 +630,8 @@ FEXCore::HostFeatures FetchHostFeatures() { auto HostFeatures = FetchHostFeatures(Features, true, CTR, MIDR); FillMIDRInformationViaLinux(&HostFeatures); + + HostFeatures.SupportsCPUIndexInTPIDRRO = false; return HostFeatures; } } // namespace FEX diff --git a/Source/Windows/Common/CPUFeatures.cpp b/Source/Windows/Common/CPUFeatures.cpp index 0b38d28d3..dd14099e9 100644 --- a/Source/Windows/Common/CPUFeatures.cpp +++ b/Source/Windows/Common/CPUFeatures.cpp @@ -65,6 +65,8 @@ FEXCore::HostFeatures CPUFeatures::FetchHostFeatures(bool IsWine) { HostFeatures.CPUMIDRs.push_back(static_cast(ReadRegU64(Key, "CP 4000"))); RegCloseKey(Key); } + + HostFeatures.SupportsCPUIndexInTPIDRRO = !IsWine; return HostFeatures; }