101 lines
2.8 KiB
C++
101 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#if (defined(__clang__) || defined(__GNUC__)) && (__x86_64__ || __i386__) && !defined(__MINGW32__)
|
|
#include <cpuid.h>
|
|
#endif
|
|
|
|
#ifndef DISABLE_INTRINSICS
|
|
#ifdef _MSC_VER
|
|
#pragma warning(push)
|
|
#pragma warning(disable : 4987)
|
|
// C4987: Off by default noise
|
|
#endif
|
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
#include <intrin.h>
|
|
#endif
|
|
#ifdef _MSC_VER
|
|
#pragma warning(pop)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifndef __cplusplus
|
|
#error This header requires C++
|
|
#endif
|
|
|
|
//
|
|
// CPU related functions
|
|
//
|
|
inline bool PerfsCPUSIMDReady(void) noexcept {
|
|
#if !defined(DISABLE_INTRINSICS)
|
|
int CPUInfo[4] = {-1};
|
|
|
|
#if (defined(__clang__) || defined(__GNUC__)) && defined(__cpuid)
|
|
__cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
|
#else
|
|
__cpuid(CPUInfo, 0);
|
|
#endif
|
|
|
|
#ifdef __AVX2__
|
|
if (CPUInfo[0] < 7)
|
|
return false;
|
|
#else
|
|
if (CPUInfo[0] < 1)
|
|
return false;
|
|
#endif
|
|
|
|
#if (defined(__clang__) || defined(__GNUC__)) && defined(__cpuid)
|
|
__cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
|
#else
|
|
__cpuid(CPUInfo, 1);
|
|
#endif
|
|
|
|
#if defined(__AVX2__) || defined(AVX2_INTRINSICS)
|
|
// The compiler can emit FMA3 instructions even without explicit intrinsics use
|
|
if ((CPUInfo[2] & 0x38081001) != 0x38081001)
|
|
return false; // No F16C/AVX/OSXSAVE/SSE4.1/FMA3/SSE3 support
|
|
#elif defined(FMA3_INTRINSICS) && defined(F16C_INTRINSICS)
|
|
if ((CPUInfo[2] & 0x38081001) != 0x38081001)
|
|
return false; // No F16C/AVX/OSXSAVE/SSE4.1/FMA3/SSE3 support
|
|
#elif defined(FMA3_INTRINSICS)
|
|
if ((CPUInfo[2] & 0x18081001) != 0x18081001)
|
|
return false; // No AVX/OSXSAVE/SSE4.1/FMA3/SSE3 support
|
|
#elif defined(F16C_INTRINSICS)
|
|
if ((CPUInfo[2] & 0x38080001) != 0x38080001)
|
|
return false; // No F16C/AVX/OSXSAVE/SSE4.1/SSE3 support
|
|
#elif defined(__AVX__) || defined(AVX_INTRINSICS)
|
|
if ((CPUInfo[2] & 0x18080001) != 0x18080001)
|
|
return false; // No AVX/OSXSAVE/SSE4.1/SSE3 support
|
|
#elif defined(SSE4_INTRINSICS)
|
|
if ((CPUInfo[2] & 0x80001) != 0x80001)
|
|
return false; // No SSE3/SSE4.1 support
|
|
#elif defined(SSE3_INTRINSICS)
|
|
if (!(CPUInfo[2] & 0x1))
|
|
return false; // No SSE3 support
|
|
#endif
|
|
|
|
// The x64 processor model requires SSE2 support, but no harm in checking
|
|
if ((CPUInfo[3] & 0x6000000) != 0x6000000)
|
|
return false; // No SSE2/SSE support
|
|
|
|
#if defined(__AVX2__) || defined(AVX2_INTRINSICS)
|
|
#if defined(__GNUC__)
|
|
__cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
|
#else
|
|
__cpuidex(CPUInfo, 7, 0);
|
|
#endif
|
|
if (!(CPUInfo[1] & 0x20))
|
|
return false; // No AVX2 support
|
|
#endif
|
|
return true;
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// RAM related functions
|
|
//
|
|
const size_t PerfsGetVirtMem(void);
|
|
const size_t PerfsGetPhysMem(void);
|