diff --git a/FEXCore/Scripts/config_generator.py b/FEXCore/Scripts/config_generator.py index 1cdaa9e53..481222fe8 100644 --- a/FEXCore/Scripts/config_generator.py +++ b/FEXCore/Scripts/config_generator.py @@ -441,6 +441,30 @@ def print_parse_envloader_options(options): output_argloader.write("}\n") output_argloader.write("#endif\n") +def print_parse_jsonloader_options(options): + output_argloader.write("#ifdef JSONLOADER\n") + output_argloader.write("#undef JSONLOADER\n") + output_argloader.write("if (false) {}\n") + for op_group, group_vals in options.items(): + for op_key, op_vals in group_vals.items(): + value_type = op_vals["Type"] + if (value_type == "strenum"): + output_argloader.write("else if (KeyName == \"{0}\") {{\n".format(op_key)) + output_argloader.write("Set(KeyOption, FEXCore::Config::EnumParser(FEXCore::Config::{}_EnumPairs, Value_View));\n".format(op_key, op_key, op_key)) + output_argloader.write("}\n") + + if ("ArgumentHandler" in op_vals): + conversion_func = "FEXCore::Config::Handler::{0}".format(op_vals["ArgumentHandler"]) + output_argloader.write("else if (KeyName == \"{0}\") {{\n".format(op_key)) + output_argloader.write("Set(KeyOption, {0}(Value_View));\n".format(conversion_func)) + output_argloader.write("}\n") + + output_argloader.write("else {{\n".format(op_key)) + output_argloader.write("Set(KeyOption, ConfigString);\n") + output_argloader.write("}\n") + + output_argloader.write("#endif\n") + def print_parse_enum_options(options): output_argloader.write("#ifdef ENUMDEFINES\n") output_argloader.write("#undef ENUMDEFINES\n") @@ -556,6 +580,9 @@ print_parse_argloader_options(options); # Generate environment loader code print_parse_envloader_options(options); +# Generate json loader code +print_parse_jsonloader_options(options); + # Generate enum variable options print_parse_enum_options(options); diff --git a/FEXCore/Source/Interface/Config/Config.json.in b/FEXCore/Source/Interface/Config/Config.json.in index d5c378755..d7a6f589a 100644 --- a/FEXCore/Source/Interface/Config/Config.json.in +++ b/FEXCore/Source/Interface/Config/Config.json.in @@ -99,6 +99,19 @@ "\t{enable,disable}crypto: Will force enable or disable crypto extensions even if the host doesn't support it", "\t{enable,disable}rpres: Will force enable or disable rpres even if the host doesn't support it" ] + }, + "CPUID": { + "Type": "strenum", + "Default": "FEXCore::Config::CPUID::OFF", + "Enums": { + "ENABLESHA": "enablesha", + "DISABLESHA": "disablesha" + }, + "Desc": [ + "Allows controlling of the CPU features are exposed in CPUID.", + "\toff: Default CPU features queried from CPU features", + "\t{enable,disable}sha: Will force enable or disable sha even if the host doesn't support it" + ] } }, "Emulation": { diff --git a/FEXCore/Source/Interface/Core/CPUID.cpp b/FEXCore/Source/Interface/Core/CPUID.cpp index 0bcc2da07..c04cff637 100644 --- a/FEXCore/Source/Interface/Core/CPUID.cpp +++ b/FEXCore/Source/Interface/Core/CPUID.cpp @@ -358,6 +358,34 @@ void CPUIDEmu::SetupHostHybridFlag() { #endif + +void CPUIDEmu::SetupFeatures() { + // TODO: Enable once AVX is supported. + if (false && CTX->HostFeatures.SupportsAVX) { + XCR0 |= XCR0_AVX; + } + + // Override features if the user has specifically called for it. + FEX_CONFIG_OPT(CPUIDFeatures, CPUID); + if (!CPUIDFeatures()) { + // Early exit if no features are overriden. + return; + } + +#define ENABLE_DISABLE_OPTION(name, enum_name) \ + const bool Disable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::DISABLE##enum_name) != 0; \ + const bool Enable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::ENABLE##enum_name) != 0; \ + LogMan::Throw::AFmt(!(Disable##name && Enable##name), "Disabling and Enabling CPUID feature (" #name ") is mutually exclusive"); + + ENABLE_DISABLE_OPTION(SHA, SHA); + if (EnableSHA) { + Features.SHA = true; + } + else if (DisableSHA) { + Features.SHA = false; + } +} + FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0h(uint32_t Leaf) const { FEXCore::CPUID::FunctionResults Res{}; @@ -639,7 +667,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const { (0 << 26) | // Reserved (0 << 27) | // Reserved (0 << 28) | // Reserved - (1 << 29) | // SHA instructions + (Features.SHA << 29) | // SHA instructions (0 << 30) | // Reserved (0 << 31); // Reserved @@ -1212,10 +1240,7 @@ CPUIDEmu::CPUIDEmu(FEXCore::Context::ContextImpl const *ctx) // Setup some state tracking SetupHostHybridFlag(); - // TODO: Enable once AVX is supported. - if (false && CTX->HostFeatures.SupportsAVX) { - XCR0 |= XCR0_AVX; - } + SetupFeatures(); } } diff --git a/FEXCore/Source/Interface/Core/CPUID.h b/FEXCore/Source/Interface/Core/CPUID.h index db429bafc..63dcb1726 100644 --- a/FEXCore/Source/Interface/Core/CPUID.h +++ b/FEXCore/Source/Interface/Core/CPUID.h @@ -136,6 +136,15 @@ private: constexpr static uint64_t XCR0_SSE = 1ULL << 1; constexpr static uint64_t XCR0_AVX = 1ULL << 2; + struct FeaturesConfig { + uint64_t SHA : 1; + uint64_t _pad : 63; + }; + + FeaturesConfig Features { + .SHA = 1, + }; + uint64_t XCR0 { XCR0_X87 | XCR0_SSE @@ -189,6 +198,7 @@ private: FEXCore::CPUID::XCRResults XCRFunction_0h() const; void SetupHostHybridFlag(); + void SetupFeatures(); static constexpr size_t PRIMARY_FUNCTION_COUNT = 27; static constexpr size_t HYPERVISOR_FUNCTION_COUNT = 2; static constexpr size_t EXTENDED_FUNCTION_COUNT = 32; diff --git a/Source/Common/Config.cpp b/Source/Common/Config.cpp index 5d6cfed33..5a1aaef50 100644 --- a/Source/Common/Config.cpp +++ b/Source/Common/Config.cpp @@ -165,7 +165,11 @@ namespace JSON { void OptionMapper::MapNameToOption(const char *ConfigName, const char *ConfigString) { auto it = ConfigLookup.find(ConfigName); if (it != ConfigLookup.end()) { - Set(it->second, ConfigString); + const auto KeyOption = it->second; + const auto KeyName = std::string_view(ConfigName); + const auto Value_View = std::string_view(ConfigString); +#define JSONLOADER +#include } }