Just to add @ Guilherme Bernal's answer and share the code.
I did a program to test the class that Guilherme posted and it looks like it is
working. I have not tested fully since this varies from PC to PC.
(I compiled it in MSVC 2013, but it should work in GCC too.)
I tested on a Core i5 and the result seems correct (compared to CPUz).
It looks like this:
#ifndef HARDWARE_HPP_INCLUDED
#define HARDWARE_HPP_INCLUDED
#include <string>
#ifdef _WIN32
#include <limits.h>
#include <intrin.h>
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
namespace hardware
{
enum TechEAX
{
kFSGSBASE = (1 << 0),
kBMI = (1 << 3),
kHLE = (1 << 4),
kAVX2 = (1 << 5),
kBMI2 = (1 << 8),
kRTM = (1 << 11),
kRDSEED = (1 << 18),
kADX = (1 << 19),
};
enum TechECX
{
kSSE3 = (1 << 0),
kPCLMUL = (1 << 1),
kLZCNT = (1 << 5),
kSSSE3 = (1 << 9),
kFMA = (1 << 12),
kCMPXCHG16B = (1 << 13),
kSSE4_1 = (1 << 19),
kSSE4_2 = (1 << 20),
kMOVBE = (1 << 22),
kPOPCNT = (1 << 23),
kAES = (1 << 25),
kXSAVE = (1 << 26),
kOSXSAVE = (1 << 27),
kAVX = (1 << 28),
kF16C = (1 << 29),
kRDRND = (1 << 30),
kLAHF_LM = (1 << 0),
kABM = (1 << 5),
kSSE4a = (1 << 6),
kPRFCHW = (1 << 8),
kXOP = (1 << 11),
kLWP = (1 << 15),
kFMA4 = (1 << 16),
kTBM = (1 << 21)
};
enum TechEDX
{
kCMPXCHG8B = (1 << 8),
kCMOV = (1 << 15),
kMMX = (1 << 23),
kFXSAVE = (1 << 24),
kSSE = (1 << 25),
kSSE2 = (1 << 26),
kMMXEXT = (1 << 22),
kLM = (1 << 29),
k3DNOWP = (1 << 30),
k3DNOW = (1 << 31)
};
class CPU
{
public:
CPU();
std::string getVendor() const;
bool checkTechnology(TechEAX tech) const;
bool checkTechnology(TechECX tech) const;
bool checkTechnology(TechEDX tech) const;
private:
void load(unsigned value) const;
const uint32_t& EAX() const
{
return regs[0];
}
const uint32_t& EBX() const
{
return regs[1];
}
const uint32_t& ECX() const
{
return regs[2];
}
const uint32_t& EDX() const
{
return regs[3];
}
private:
uint32_t regs[4];
};
}
#endif
#include "hardware.hpp"
namespace hardware
{
CPU::CPU()
{
this->load(0);
}
bool CPU::checkTechnology(TechEAX tech) const
{
this->load(7);
return (EAX() & tech) != 0;
}
bool CPU::checkTechnology(TechECX tech) const
{
this->load(1);
return (ECX() & tech) != 0;
}
bool CPU::checkTechnology(TechEDX tech) const
{
this->load(1);
return (EDX() & tech) != 0;
}
std::string CPU::getVendor() const
{
std::string vendor;
vendor += std::string((const char *)&EBX(), 4);
vendor += std::string((const char *)&EDX(), 4);
vendor += std::string((const char *)&ECX(), 4);
if (vendor == "AMDisbetter!" || vendor == "AuthenticAMD") return "AMD";
if (vendor == "GenuineIntel") return "Intel";
if (vendor == "VIA VIA VIA ") return "VIA";
if (vendor == "CentaurHauls") return "Centaur";
if (vendor == "CyrixInstead") return "Cyrix";
if (vendor == "TransmetaCPU" || vendor == "GenuineTMx86") return "Transmeta";
if (vendor == "Geode by NSC") return "National Semiconductor";
if (vendor == "NexGenDriven") return "NexGen";
if (vendor == "RiseRiseRise") return "Rise";
if (vendor == "SiS SiS SiS ") return "SiS";
if (vendor == "UMC UMC UMC ") return "UMC";
if (vendor == "Vortex86 SoC") return "Vortex";
if (vendor == "KVMKVMKVMKVM") return "KVM";
if (vendor == "Microsoft Hv") return "Microsoft Hyper-V";
if (vendor == "VMwareVMware") return "VMware";
if (vendor == "XenVMMXenVMM") return "Xen HVM";
return vendor;
}
void CPU::load(unsigned value) const
{
#ifdef _WIN32
__cpuid((int *) regs, (int)value);
#else
asm volatile
("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
: "a" (i), "c" (0));
// ECX is set to zero for CPUID function 4
#endif
}
}
#include <iostream>
#include "hardware.hpp"
int main(int argc, char** argv)
{
using namespace hardware;
CPU cpu;
std::cout << "Fabricante: " << cpu.getVendor() << std::endl;
std::cout << " SSE: " << cpu.checkTechnology(kSSE) << std::endl;
std::cout << " SSE2: " << cpu.checkTechnology(kSSE2) << std::endl;
std::cout << " SSE3: " << cpu.checkTechnology(kSSE3) << std::endl;
std::cout << " SSSE3: " << cpu.checkTechnology(kSSSE3) << std::endl;
std::cout << " SSE4.1: " << cpu.checkTechnology(kSSE4_1) << std::endl;
std::cout << " SSE4.2: " << cpu.checkTechnology(kSSE4_2) << std::endl;
std::cout << " SSE4A: " << cpu.checkTechnology(kSSE4a) << std::endl;
std::cout << " AES: " << cpu.checkTechnology(kAES) << std::endl;
std::cout << " AVX: " << cpu.checkTechnology(kAVX) << std::endl;
std::cout << " AVX2: " << cpu.checkTechnology(kAVX2) << std::endl;
std::cin.get();
return 0;
}
The output stayed (for the Intel Core i5 Sandy Bridge ):
Fabricante: Intel
SSE: 1
SSE2: 1
SSE3: 1
SSSE3: 1
SSE4.1: 1
SSE4.2: 1
SSE4A: 1
AES: 1
AVX: 1
AVX2: 0