diff --git a/FEXCore/Source/Interface/Core/CPUID.cpp b/FEXCore/Source/Interface/Core/CPUID.cpp index 365ebfc55..3c42d3043 100644 --- a/FEXCore/Source/Interface/Core/CPUID.cpp +++ b/FEXCore/Source/Interface/Core/CPUID.cpp @@ -1347,7 +1347,7 @@ FEXCore::CPUID::XCRResults CPUIDEmu::XCRFunction_0h() const { CPUIDEmu::CPUIDEmu(const FEXCore::Context::ContextImpl* ctx) : CTX {ctx} - , SupportsCPUIndexInTPIDRRO {CTX->HostFeatures.SupportsCPUIndexInTPIDRRO} + , SupportsCPUIndexInTPIDRRO {CTX->HostFeatures.SupportsCPUIndexInTPIDRRO != 0} , GetCPUID {GetCPUID_Syscall} { Cores = CTX->HostFeatures.CPUMIDRs.size(); diff --git a/FEXCore/Source/Interface/Core/JIT/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/JIT.cpp index 46cc17902..1b3d90981 100644 --- a/FEXCore/Source/Interface/Core/JIT/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/JIT.cpp @@ -616,11 +616,11 @@ void Arm64JITCore::Op_NoOp(const IR::IROp_Header* IROp, IR::Ref Node) {} Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl* ctx, FEXCore::Core::InternalThreadState* Thread) : CPUBackend(*ctx, Thread) , Arm64Emitter(ctx) - , HostSupportsSVE128 {ctx->HostFeatures.SupportsSVE128} - , HostSupportsSVE256 {ctx->HostFeatures.SupportsSVE256} + , HostSupportsSVE128 {ctx->HostFeatures.SupportsSVE128 != 0} + , HostSupportsSVE256 {ctx->HostFeatures.SupportsSVE256 != 0} , HostSupportsAVX256 {ctx->HostFeatures.SupportsAVX && ctx->HostFeatures.SupportsSVE256} - , HostSupportsRPRES {ctx->HostFeatures.SupportsRPRES} - , HostSupportsAFP {ctx->HostFeatures.SupportsAFP} + , HostSupportsRPRES {ctx->HostFeatures.SupportsRPRES != 0} + , HostSupportsAFP {ctx->HostFeatures.SupportsAFP != 0} , CTX {ctx} , TempCodeBufferAllocator(ctx->CPUBackendAllocator, 0) { diff --git a/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp b/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp index 849df0f2c..805a7312a 100644 --- a/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp @@ -2401,13 +2401,13 @@ DEF_OP(CacheLineClear) { // Clear dcache only // icache doesn't matter here since the guest application shouldn't be calling clflush on JIT code. // check host cacheline size again x86_64 size to ensure at least 64 bytes are cleaned - if (CTX->HostFeatures.DCacheLineSize >= 64U) { + if (CTX->HostFeatures.DCacheSize() >= 64U) { dc(ARMEmitter::DataCacheOperation::CIVAC, MemReg); } else { auto CurrentWorkingReg = MemReg.X(); - for (size_t i = 0; i < std::max(1U, 64U / CTX->HostFeatures.DCacheLineSize); ++i) { + for (size_t i = 0; i < std::max(1U, 64U / CTX->HostFeatures.DCacheSize()); ++i) { dc(ARMEmitter::DataCacheOperation::CIVAC, CurrentWorkingReg); - add(ARMEmitter::Size::i64Bit, TMP1, CurrentWorkingReg, CTX->HostFeatures.DCacheLineSize); + add(ARMEmitter::Size::i64Bit, TMP1, CurrentWorkingReg, CTX->HostFeatures.DCacheSize()); CurrentWorkingReg = TMP1; } } @@ -2430,13 +2430,13 @@ DEF_OP(CacheLineClean) { // Clean dcache only // check host cacheline size again x86_64 size to ensure at least 64 bytes are cleaned - if (CTX->HostFeatures.DCacheLineSize >= 64U) { + if (CTX->HostFeatures.DCacheSize() >= 64U) { dc(ARMEmitter::DataCacheOperation::CVAC, MemReg); } else { auto CurrentWorkingReg = MemReg.X(); - for (size_t i = 0; i < std::max(1U, 64U / CTX->HostFeatures.DCacheLineSize); ++i) { + for (size_t i = 0; i < std::max(1U, 64U / CTX->HostFeatures.DCacheSize()); ++i) { dc(ARMEmitter::DataCacheOperation::CVAC, CurrentWorkingReg); - add(ARMEmitter::Size::i64Bit, TMP1, CurrentWorkingReg, CTX->HostFeatures.DCacheLineSize); + add(ARMEmitter::Size::i64Bit, TMP1, CurrentWorkingReg, CTX->HostFeatures.DCacheSize()); CurrentWorkingReg = TMP1; } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 01d43168f..51b305b65 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4617,7 +4617,7 @@ void OpDispatchBuilder::StoreResult(RegClass Class, X86Tables::DecodedOp Op, Ref } OpDispatchBuilder::OpDispatchBuilder(FEXCore::Context::ContextImpl* ctx, FEXCore::Core::InternalThreadState* Thread) - : IREmitter {ctx->OpDispatcherAllocator, ctx->HostFeatures.SupportsTSOImm9} + : IREmitter {ctx->OpDispatcherAllocator, ctx->HostFeatures.SupportsTSOImm9 != 0} , CTX {ctx} , Thread {Thread} { if (CTX->HostFeatures.SupportsAVX && CTX->HostFeatures.SupportsSVE256) { diff --git a/FEXCore/include/FEXCore/Core/HostFeatures.h b/FEXCore/include/FEXCore/Core/HostFeatures.h index c927df66b..077e4de67 100644 --- a/FEXCore/include/FEXCore/Core/HostFeatures.h +++ b/FEXCore/include/FEXCore/Core/HostFeatures.h @@ -13,48 +13,6 @@ namespace FEXCore { * Not the x86->IR process */ struct HostFeatures { - // Whether or not the host supports any kind of SVE implementation. - [[nodiscard]] - bool SupportsSVE() const { - return SupportsSVE128 || SupportsSVE256; - } - - uint32_t DCacheLineSize {}; - uint32_t ICacheLineSize {}; - bool SupportsCacheMaintenanceOps {}; - bool SupportsAES {}; - bool SupportsCRC {}; - bool SupportsCLZERO {}; - bool SupportsAtomics {}; - bool SupportsRCPC {}; - bool SupportsTSOImm9 {}; - bool SupportsRAND {}; - bool SupportsAVX {}; - bool SupportsSVE128 {}; - bool SupportsSVE256 {}; - bool SupportsSHA {}; - bool SupportsPMULL_128Bit {}; - bool SupportsCSSC {}; - bool SupportsFCMA {}; - bool SupportsFlagM {}; - bool SupportsFlagM2 {}; - bool SupportsRPRES {}; - bool SupportsPreserveAllABI {}; - bool SupportsAES256 {}; - bool SupportsSVEBitPerm {}; - bool SupportsCPUIndexInTPIDRRO {}; - bool SupportsFRINTTS {}; - bool SupportsECV {}; - bool SupportsWFXT {}; - bool Supports3DNow {}; - bool SupportsSSE4a {}; - bool SupportsMOPS {}; - bool PreferZVAForVZero {}; - - // Float exception behaviour - bool SupportsAFP {}; - bool SupportsFloatExceptions {}; - // Changes code generation slightly. enum class HostTypeEnum { Unknown, @@ -62,10 +20,64 @@ struct HostFeatures { Wow64, Arm64ec, }; - HostTypeEnum HostType {}; + // Whether or not the host supports any kind of SVE implementation. + [[nodiscard]] + bool SupportsSVE() const { + return SupportsSVE128 || SupportsSVE256; + } + + [[nodiscard]] + uint32_t DCacheSize() const { + return 4 << DCacheLineLog2; + } + + [[nodiscard]] + uint64_t HashForCaching() const { + // As long as the number of options is 64-bit or below, we can just return it. + // Skip CPUMIDRs as it doesn't affect codegen. + static_assert(offsetof(HostFeatures, CPUMIDRs) == 8); + uint64_t Result {}; + memcpy(&Result, this, sizeof(Result)); + return Result; + } + + uint32_t DCacheLineLog2 : 4 {}; + uint32_t SupportsCacheMaintenanceOps : 1 {}; + uint32_t SupportsAES : 1 {}; + uint32_t SupportsCRC : 1 {}; + uint32_t SupportsCLZERO : 1 {}; + uint32_t SupportsAtomics : 1 {}; + uint32_t SupportsRCPC : 1 {}; + uint32_t SupportsTSOImm9 : 1 {}; + uint32_t SupportsRAND : 1 {}; + uint32_t SupportsAVX : 1 {}; + uint32_t SupportsSVE128 : 1 {}; + uint32_t SupportsSVE256 : 1 {}; + uint32_t SupportsSHA : 1 {}; + uint32_t SupportsPMULL_128Bit : 1 {}; + uint32_t SupportsCSSC : 1 {}; + uint32_t SupportsFCMA : 1 {}; + uint32_t SupportsFlagM : 1 {}; + uint32_t SupportsFlagM2 : 1 {}; + uint32_t SupportsRPRES : 1 {}; + uint32_t SupportsPreserveAllABI : 1 {}; + uint32_t SupportsAES256 : 1 {}; + uint32_t SupportsSVEBitPerm : 1 {}; + uint32_t SupportsCPUIndexInTPIDRRO : 1 {}; + uint32_t SupportsFRINTTS : 1 {}; + uint32_t SupportsECV : 1 {}; + uint32_t SupportsWFXT : 1 {}; + uint32_t Supports3DNow : 1 {}; + uint32_t SupportsSSE4a : 1 {}; + uint32_t SupportsMOPS : 1 {}; + uint32_t PreferZVAForVZero : 1 {}; + uint32_t SupportsAFP : 1 {}; + uint32_t SupportsFloatExceptions : 1 {}; // Flag if this is InstCountCI - bool IsInstCountCI {}; + uint32_t IsInstCountCI : 1 {}; + HostTypeEnum HostType : 2 {}; + uint32_t pad : 26 {}; // MIDR information // Also used for determining number of CPU cores for CPUID diff --git a/Source/Common/HostFeatures.cpp b/Source/Common/HostFeatures.cpp index 00abcaa5b..ddc2cf4cd 100644 --- a/Source/Common/HostFeatures.cpp +++ b/Source/Common/HostFeatures.cpp @@ -543,11 +543,10 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe HostFeatures.PreferZVAForVZero = false; if (CTR) { - HostFeatures.DCacheLineSize = 4 << ((CTR >> 16) & 0xF); - HostFeatures.ICacheLineSize = 4 << (CTR & 0xF); + HostFeatures.DCacheLineLog2 = (CTR >> 16) & 0xF; } else { - HostFeatures.DCacheLineSize = 64; - HostFeatures.ICacheLineSize = 64; + // 64-bytes + HostFeatures.DCacheLineLog2 = 4; } if (!HostFeatures.SupportsAtomics) {