openspades/Sources/Core/CpuID.cpp

100 lines
2.0 KiB
C++

// WTFPL
#include "CpuID.h"
namespace spades {
#if defined(__i386__) || defined(_M_IX86)
static std::array<uint32_t, 4> cpuid(uint32_t a) {
std::array<uint32_t, 4> regs;
#ifdef WIN32
__cpuid(reinterpret_cast<int *>(regs.data()), a);
#else
asm volatile("cpuid":
"=a" (regs[0]),
"=b" (regs[1]),
"=c" (regs[2]),
"=d" (regs[3]):
"a"(a),
"c"(0));
#endif
return regs;
}
CpuID::CpuID() {
uint32_t maxStdLevel;
{
auto ar = cpuid(0);
char buf[13];
buf[12] = 0;
maxStdLevel = ar[0];
memcpy(buf, ar.data()+1, 12);
vendor = buf;
}
{
auto ar = cpuid(1);
featureEcx = ar[2];
featureEdx = ar[3];
}
{
if(cpuid(0x80000000U)[0] >= 0x80000004U){
char buf[49];
buf[48] = 0;
memcpy(buf, cpuid(0x80000002U).data(), 16);
memcpy(buf+16, cpuid(0x80000003U).data(), 16);
memcpy(buf+32, cpuid(0x80000004U).data(), 16);
brand = buf;
}else{
brand = "Unknown";
}
}
{
auto ar = cpuid(7);
// FIXME: sublevels?
subfeature = ar[1];
}
{
info = "(none)";
}
}
bool CpuID::Supports(spades::CpuFeature feature) {
switch(feature){
case CpuFeature::MMX:
return featureEdx & (1U << 23);
case CpuFeature::SSE:
return featureEdx & (1U << 25);
case CpuFeature::SSE2:
return featureEdx & (1U << 26);
case CpuFeature::SSE3:
return featureEcx & (1U << 0);
case CpuFeature::SSSE3:
return featureEcx & (1U << 9);
case CpuFeature::FMA:
return featureEcx & (1U << 12);
case CpuFeature::AVX:
return featureEcx & (1U << 28);
case CpuFeature::AVX2:
return subfeature & (1U << 5);
case CpuFeature::AVX512CD:
return subfeature & (1U << 28);
case CpuFeature::AVX512ER:
return subfeature & (1U << 27);
case CpuFeature::AVX512PF:
return subfeature & (1U << 26);
case CpuFeature::AVX512F:
return subfeature & (1U << 16);
case CpuFeature::SimultaneousMT:
return featureEdx & (1U << 28);
}
}
#endif
}