diff --git a/Source/Core/Common/CPUDetect.h b/Source/Core/Common/CPUDetect.h index 38cfa4be17..5d73be28ee 100644 --- a/Source/Core/Common/CPUDetect.h +++ b/Source/Core/Common/CPUDetect.h @@ -40,6 +40,9 @@ struct CPUInfo bool bLZCNT; bool bSSE4A; bool bAVX; + bool bAVX2; + bool bBMI1; + bool bBMI2; bool bFMA; bool bAES; // FXSAVE/FXRSTOR diff --git a/Source/Core/Common/x64CPUDetect.cpp b/Source/Core/Common/x64CPUDetect.cpp index a17a8492cb..592857a165 100644 --- a/Source/Core/Common/x64CPUDetect.cpp +++ b/Source/Core/Common/x64CPUDetect.cpp @@ -82,7 +82,8 @@ static unsigned long long _xgetbv(unsigned int index) CPUInfo cpu_info; -CPUInfo::CPUInfo() { +CPUInfo::CPUInfo() +{ Detect(); } @@ -97,7 +98,8 @@ void CPUInfo::Detect() num_cores = 1; // Set obvious defaults, for extra safety - if (Mode64bit) { + if (Mode64bit) + { bSSE = true; bSSE2 = true; bLongMode = true; @@ -130,7 +132,8 @@ void CPUInfo::Detect() bool ht = false; HTT = ht; logical_cpu_count = 1; - if (max_std_fn >= 1) { + if (max_std_fn >= 1) + { __cpuid(cpu_id, 0x00000001); logical_cpu_count = (cpu_id[1] >> 16) & 0xFF; ht = (cpu_id[3] >> 28) & 1; @@ -163,11 +166,24 @@ void CPUInfo::Detect() bFMA = true; } } + + if (max_std_fn >= 7) + { + __cpuid(cpu_id, 0x00000007); + // careful; we can't enable AVX2 unless the XSAVE/XGETBV checks above passed + if ((cpu_id[1] >> 5) & 1) + bAVX2 = bAVX; + if ((cpu_id[1] >> 3) & 1) + bBMI1 = true; + if ((cpu_id[1] >> 8) & 1) + bBMI2 = true; + } } bFlushToZero = bSSE; - if (max_ex_fn >= 0x80000004) { + if (max_ex_fn >= 0x80000004) + { // Extract brand string __cpuid(cpu_id, 0x80000002); memcpy(brand_string, cpu_id, sizeof(cpu_id)); @@ -176,7 +192,8 @@ void CPUInfo::Detect() __cpuid(cpu_id, 0x80000004); memcpy(brand_string + 32, cpu_id, sizeof(cpu_id)); } - if (max_ex_fn >= 0x80000001) { + if (max_ex_fn >= 0x80000001) + { // Check for more features. __cpuid(cpu_id, 0x80000001); if (cpu_id[2] & 1) bLAHFSAHF64 = true; @@ -185,14 +202,18 @@ void CPUInfo::Detect() num_cores = (logical_cpu_count == 0) ? 1 : logical_cpu_count; - if (max_ex_fn >= 0x80000008) { + if (max_ex_fn >= 0x80000008) + { // Get number of cores. This is a bit complicated. Following AMD manual here. __cpuid(cpu_id, 0x80000008); int apic_id_core_id_size = (cpu_id[2] >> 12) & 0xF; - if (apic_id_core_id_size == 0) { - if (ht) { + if (apic_id_core_id_size == 0) + { + if (ht) + { // New mechanism for modern Intel CPUs. - if (vendor == VENDOR_INTEL) { + if (vendor == VENDOR_INTEL) + { __cpuid(cpu_id, 0x00000004); int cores_x_package = ((cpu_id[0] >> 26) & 0x3F) + 1; HTT = (cores_x_package < logical_cpu_count); @@ -201,7 +222,8 @@ void CPUInfo::Detect() logical_cpu_count /= cores_x_package; } } - } else { + } else + { // Use AMD's new method. num_cores = (cpu_id[2] & 0xFF) + 1; } @@ -225,6 +247,9 @@ std::string CPUInfo::Summarize() if (bSSE4_2) sum += ", SSE4.2"; if (HTT) sum += ", HTT"; if (bAVX) sum += ", AVX"; + if (bAVX2) sum += ", AVX2"; + if (bBMI1) sum += ", BMI1"; + if (bBMI2) sum += ", BMI2"; if (bFMA) sum += ", FMA"; if (bAES) sum += ", AES"; if (bMOVBE) sum += ", MOVBE";