Merge pull request #5851 from Sonicadvance1/215

FEXCore/HostFeatures: Adds HostFeatures hashing support
This commit is contained in:
LC authored and GitHub committed 2026-08-25 06:13:21 -04:00
commit 7614e48322
6 files changed
+71 -60

No files matched your search

+1 -1
View File
@@ -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();
+4 -4
View File
@@ -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) {
@@ -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;
}
}
@@ -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) {
+56 -44
View File
@@ -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
+3 -4
View File
@@ -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) {