First Commit
This commit is contained in:
141
externals/openal-soft/core/cpu_caps.cpp
vendored
Normal file
141
externals/openal-soft/core/cpu_caps.cpp
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "cpu_caps.h"
|
||||
|
||||
#if defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#ifndef PF_ARM_NEON_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID_H)
|
||||
#include <cpuid.h>
|
||||
#elif defined(HAVE_INTRIN_H)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
|
||||
int CPUCapFlags{0};
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(HAVE_GCC_GET_CPUID) \
|
||||
&& (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
|
||||
using reg_type = unsigned int;
|
||||
inline std::array<reg_type,4> get_cpuid(unsigned int f)
|
||||
{
|
||||
std::array<reg_type,4> ret{};
|
||||
__get_cpuid(f, ret.data(), &ret[1], &ret[2], &ret[3]);
|
||||
return ret;
|
||||
}
|
||||
#define CAN_GET_CPUID
|
||||
#elif defined(HAVE_CPUID_INTRINSIC) \
|
||||
&& (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
|
||||
using reg_type = int;
|
||||
inline std::array<reg_type,4> get_cpuid(unsigned int f)
|
||||
{
|
||||
std::array<reg_type,4> ret{};
|
||||
(__cpuid)(ret.data(), f);
|
||||
return ret;
|
||||
}
|
||||
#define CAN_GET_CPUID
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
al::optional<CPUInfo> GetCPUInfo()
|
||||
{
|
||||
CPUInfo ret;
|
||||
|
||||
#ifdef CAN_GET_CPUID
|
||||
auto cpuregs = get_cpuid(0);
|
||||
if(cpuregs[0] == 0)
|
||||
return al::nullopt;
|
||||
|
||||
const reg_type maxfunc{cpuregs[0]};
|
||||
|
||||
cpuregs = get_cpuid(0x80000000);
|
||||
const reg_type maxextfunc{cpuregs[0]};
|
||||
|
||||
ret.mVendor.append(reinterpret_cast<char*>(&cpuregs[1]), 4);
|
||||
ret.mVendor.append(reinterpret_cast<char*>(&cpuregs[3]), 4);
|
||||
ret.mVendor.append(reinterpret_cast<char*>(&cpuregs[2]), 4);
|
||||
auto iter_end = std::remove(ret.mVendor.begin(), ret.mVendor.end(), '\0');
|
||||
iter_end = std::unique(ret.mVendor.begin(), iter_end,
|
||||
[](auto&& c0, auto&& c1) { return std::isspace(c0) && std::isspace(c1); });
|
||||
ret.mVendor.erase(iter_end, ret.mVendor.end());
|
||||
if(!ret.mVendor.empty() && std::isspace(ret.mVendor.back()))
|
||||
ret.mVendor.pop_back();
|
||||
if(!ret.mVendor.empty() && std::isspace(ret.mVendor.front()))
|
||||
ret.mVendor.erase(ret.mVendor.begin());
|
||||
|
||||
if(maxextfunc >= 0x80000004)
|
||||
{
|
||||
cpuregs = get_cpuid(0x80000002);
|
||||
ret.mName.append(reinterpret_cast<char*>(cpuregs.data()), 16);
|
||||
cpuregs = get_cpuid(0x80000003);
|
||||
ret.mName.append(reinterpret_cast<char*>(cpuregs.data()), 16);
|
||||
cpuregs = get_cpuid(0x80000004);
|
||||
ret.mName.append(reinterpret_cast<char*>(cpuregs.data()), 16);
|
||||
iter_end = std::remove(ret.mName.begin(), ret.mName.end(), '\0');
|
||||
iter_end = std::unique(ret.mName.begin(), iter_end,
|
||||
[](auto&& c0, auto&& c1) { return std::isspace(c0) && std::isspace(c1); });
|
||||
ret.mName.erase(iter_end, ret.mName.end());
|
||||
if(!ret.mName.empty() && std::isspace(ret.mName.back()))
|
||||
ret.mName.pop_back();
|
||||
if(!ret.mName.empty() && std::isspace(ret.mName.front()))
|
||||
ret.mName.erase(ret.mName.begin());
|
||||
}
|
||||
|
||||
if(maxfunc >= 1)
|
||||
{
|
||||
cpuregs = get_cpuid(1);
|
||||
if((cpuregs[3]&(1<<25)))
|
||||
ret.mCaps |= CPU_CAP_SSE;
|
||||
if((ret.mCaps&CPU_CAP_SSE) && (cpuregs[3]&(1<<26)))
|
||||
ret.mCaps |= CPU_CAP_SSE2;
|
||||
if((ret.mCaps&CPU_CAP_SSE2) && (cpuregs[2]&(1<<0)))
|
||||
ret.mCaps |= CPU_CAP_SSE3;
|
||||
if((ret.mCaps&CPU_CAP_SSE3) && (cpuregs[2]&(1<<19)))
|
||||
ret.mCaps |= CPU_CAP_SSE4_1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Assume support for whatever's supported if we can't check for it */
|
||||
#if defined(HAVE_SSE4_1)
|
||||
#warning "Assuming SSE 4.1 run-time support!"
|
||||
ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
|
||||
#elif defined(HAVE_SSE3)
|
||||
#warning "Assuming SSE 3 run-time support!"
|
||||
ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
|
||||
#elif defined(HAVE_SSE2)
|
||||
#warning "Assuming SSE 2 run-time support!"
|
||||
ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2;
|
||||
#elif defined(HAVE_SSE)
|
||||
#warning "Assuming SSE run-time support!"
|
||||
ret.mCaps |= CPU_CAP_SSE;
|
||||
#endif
|
||||
#endif /* CAN_GET_CPUID */
|
||||
|
||||
#ifdef HAVE_NEON
|
||||
#ifdef __ARM_NEON
|
||||
ret.mCaps |= CPU_CAP_NEON;
|
||||
#elif defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
if(IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
|
||||
ret.mCaps |= CPU_CAP_NEON;
|
||||
#else
|
||||
#warning "Assuming NEON run-time support!"
|
||||
ret.mCaps |= CPU_CAP_NEON;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user