Common: Detect x86 features with cpu_features.

This commit is contained in:
Unknown W. Brackets 2023-01-29 13:03:08 -08:00
parent 489411359e
commit 368aba3c8d
2 changed files with 70 additions and 1 deletions

View file

@ -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 <sys/stat.h>
#include <fcntl.h>
@ -141,6 +147,10 @@ static std::vector<int> 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;
}

View file

@ -68,6 +68,7 @@ struct CPUInfo {
bool bSSE4A;
bool bAES;
bool bSHA;
bool bF16C;
// x86 : SIMD 256 bit
bool bAVX;
bool bAVX2;