diff --git a/Common/CPUDetect.cpp b/Common/CPUDetect.cpp index ebf78012b6..c80b32d5b1 100644 --- a/Common/CPUDetect.cpp +++ b/Common/CPUDetect.cpp @@ -19,6 +19,12 @@ #include "ppsspp_config.h" #if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) +#include "ext/cpu_features/include/cpuinfo_x86.h" + +#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) || defined(CPU_FEATURES_OS_MACOS) || defined(CPU_FEATURES_OS_WINDOWS) +#define USE_CPU_FEATURES 1 +#endif + #ifdef __ANDROID__ #include #include @@ -141,6 +147,10 @@ static std::vector ParseCPUList(const std::string &filename) { // Detects the various cpu features void CPUInfo::Detect() { +#ifdef USE_CPU_FEATURES + cpu_features::X86Info info = cpu_features::GetX86Info(); +#endif + memset(this, 0, sizeof(*this)); #if PPSSPP_ARCH(X86) Mode64bit = false; @@ -185,7 +195,50 @@ void CPUInfo::Detect() { vendor = VENDOR_OTHER; // Set reasonable default brand string even if brand string not available. - strcpy(brand_string, cpu_string); +#ifdef USE_CPU_FEATURES + if (info.brand_string[0]) + strcpy(brand_string, info.brand_string); + else +#endif + strcpy(brand_string, cpu_string); + +#ifdef USE_CPU_FEATURES + switch (cpu_features::GetX86Microarchitecture(&info)) { + case cpu_features::INTEL_ATOM_BNL: + case cpu_features::INTEL_ATOM_SMT: + case cpu_features::INTEL_ATOM_GMT: + case cpu_features::INTEL_ATOM_GMT_PLUS: + case cpu_features::INTEL_ATOM_TMT: + bAtom = true; + break; + default: + bAtom = false; + break; + } + + bPOPCNT = info.features.popcnt; + bBMI1 = info.features.bmi1; + bBMI2 = info.features.bmi2; + bBMI2_fast = bBMI2 && (vendor != VENDOR_AMD || info.family >= 0x19); + bMOVBE = info.features.movbe; + bLZCNT = info.features.lzcnt; + bRTM = info.features.rtm; + + bSSE = info.features.sse; + bSSE2 = info.features.sse2; + bSSE3 = info.features.sse3; + bSSSE3 = info.features.ssse3; + bSSE4_1 = info.features.sse4_1; + bSSE4_2 = info.features.sse4_2; + bSSE4A = info.features.sse4a; + bAES = info.features.aes; + bSHA = info.features.sha; + bF16C = info.features.f16c; + bAVX = info.features.avx; + bAVX2 = info.features.avx2; + bFMA3 = info.features.fma3; + bFMA4 = info.features.fma4; +#endif // Detect family and other misc stuff. bool ht = false; @@ -193,16 +246,19 @@ void CPUInfo::Detect() { logical_cpu_count = 1; if (max_std_fn >= 1) { do_cpuid(cpu_id, 0x00000001); +#ifndef USE_CPU_FEATURES int family = ((cpu_id[0] >> 8) & 0xf) + ((cpu_id[0] >> 20) & 0xff); int model = ((cpu_id[0] >> 4) & 0xf) + ((cpu_id[0] >> 12) & 0xf0); // Detect people unfortunate enough to be running PPSSPP on an Atom if (family == 6 && (model == 0x1C || model == 0x26 || model == 0x27 || model == 0x35 || model == 0x36 || model == 0x37 || model == 0x4A || model == 0x4D || model == 0x5A || model == 0x5D)) bAtom = true; +#endif logical_cpu_count = (cpu_id[1] >> 16) & 0xFF; ht = (cpu_id[3] >> 28) & 1; +#ifndef USE_CPU_FEATURES if ((cpu_id[3] >> 25) & 1) bSSE = true; if ((cpu_id[3] >> 26) & 1) bSSE2 = true; if ((cpu_id[2]) & 1) bSSE3 = true; @@ -215,6 +271,7 @@ void CPUInfo::Detect() { bFMA3 = true; } if ((cpu_id[2] >> 25) & 1) bAES = true; +#endif if ((cpu_id[3] >> 24) & 1) { @@ -222,6 +279,7 @@ void CPUInfo::Detect() { bFXSR = true; } +#ifndef USE_CPU_FEATURES // AVX support requires 3 separate checks: // - Is the AVX bit set in CPUID? (>>28) // - Is the XSAVE bit set in CPUID? ( >>26) @@ -257,8 +315,10 @@ void CPUInfo::Detect() { } bBMI2_fast = bBMI2 && (vendor != VENDOR_AMD || family >= 0x19); +#endif } if (max_ex_fn >= 0x80000004) { +#ifndef USE_CPU_FEATURES // Extract brand string do_cpuid(cpu_id, 0x80000002); memcpy(brand_string, cpu_id, sizeof(cpu_id)); @@ -266,13 +326,16 @@ void CPUInfo::Detect() { memcpy(brand_string + 16, cpu_id, sizeof(cpu_id)); do_cpuid(cpu_id, 0x80000004); memcpy(brand_string + 32, cpu_id, sizeof(cpu_id)); +#endif } if (max_ex_fn >= 0x80000001) { // Check for more features. do_cpuid(cpu_id, 0x80000001); if (cpu_id[2] & 1) bLAHFSAHF64 = true; +#ifndef USE_CPU_FEATURES if ((cpu_id[2] >> 6) & 1) bSSE4A = true; if ((cpu_id[2] >> 16) & 1) bFMA4 = true; +#endif if ((cpu_id[2] >> 11) & 1) bXOP = true; // CmpLegacy (bit 2) is deprecated. if ((cpu_id[3] >> 29) & 1) bLongMode = true; @@ -445,6 +508,11 @@ std::string CPUInfo::Summarize() if (bSHA) sum += ", SHA"; if (bXOP) sum += ", XOP"; if (bRTM) sum += ", TSX"; + if (bF16C) sum += ", F16C"; + if (bBMI1) sum += ", BMI1"; + if (bPOPCNT) sum += ", POPCNT"; + if (bMOVBE) sum += ", MOVBE"; + if (bLZCNT) sum += ", LZCNT"; if (bLongMode) sum += ", 64-bit support"; return sum; } diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index 5d3dd0f3e2..417cd48e5b 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -68,6 +68,7 @@ struct CPUInfo { bool bSSE4A; bool bAES; bool bSHA; + bool bF16C; // x86 : SIMD 256 bit bool bAVX; bool bAVX2;