Program Listing for File CPUinfo.cc¶
↰ Return to documentation for file (CPUinfo.cc)
/*--------------------------------------------------------------------------*\
| |
| Copyright (C) 2011 |
| |
| , __ , __ |
| /|/ \ /|/ \ |
| | __/ _ ,_ | __/ _ ,_ |
| | \|/ / | | | | \|/ / | | | |
| |(__/|__/ |_/ \_/|/|(__/|__/ |_/ \_/|/ |
| /| /| |
| \| \| |
| |
| Enrico Bertolazzi |
| Dipartimento di Ingegneria Industriale |
| Universita` degli Studi di Trento |
| email: enrico.bertolazzi@unitn.it |
| |
\*--------------------------------------------------------------------------*/
/*
SIMD class to detect presence of SIMD version 1.2.0
Copyright (c) 2008 Wong Shao Voon
1.1.0 - Contains the 3DNow, 3DNow+ and MMX+ detection bug fix by Leonardo Tazzini
1.2.0 - Added AMD's SSE4a and SSE5
The Code Project Open License (CPOL)
http://www.codeproject.com/info/cpol10.aspx
*/
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include "Utils.hh"
#include "Utils_CPU_info.hh"
#include <map>
#ifdef __ARM_ARCH
namespace Utils {
using std::string;
using std::map;
void
info( bool & m_bMMX,
bool & m_bMMXplus,
bool & m_bSSE,
bool & m_bSSE2,
bool & m_bSSE3,
bool & m_bSSSE3,
bool & m_bSSE41,
bool & m_bSSE42,
bool & m_bSSE4a,
bool & m_bSSE5,
bool & m_b3Dnow,
bool & m_b3DnowExt ) {
m_bMMX = false;
m_bMMXplus = false;
m_bSSE = false;
m_bSSE2 = false;
m_bSSE3 = false;
m_bSSSE3 = false;
m_bSSE41 = false;
m_bSSE42 = false;
m_bSSE4a = false;
m_bSSE5 = false;
m_b3Dnow = false;
m_b3DnowExt = false;
}
bool has_MMX() { return false; }
bool has_MMXplus() { return false; }
bool has_SSE() { return false; }
bool has_SSE2() { return false; }
bool has_SSE3() { return false; }
bool has_SSSE3() { return false; }
bool has_SSE41() { return false; }
bool has_SSE42() { return false; }
bool has_SSE4a() { return false; }
bool has_SSE5() { return false; }
bool has_3Dnow() { return false; }
bool has_3DnowExt() { return false; }
string
cpuInfo() {
return "ARM-unsupported";
}
}
#else
#define EDX_MMX_bit 0x800000UL // 23 bit
#define EDX_SSE_bit 0x2000000UL // 25 bit
#define EDX_SSE2_bit 0x4000000UL // 26 bit
#define EDX_3DnowExt_bit 0x40000000UL // 30 bit
#define EDX_3Dnow_bit 0x80000000UL // 31 bit
#define EDX_MMXplus_bit 0x400000UL // 22 bit
#define ECX_SSE3_bit 0x1UL // 0 bit
#define ECX_SSSE3_bit 0x200UL // 9 bit
#define ECX_SSE41_bit 0x80000UL // 19 bit
#define ECX_SSE42_bit 0x100000UL // 20 bit
#define ECX_SSE4A_bit 0x40UL // 6 bit
#define ECX_SSE5_bit 0x800UL // 11 bit
namespace Utils {
using std::string;
using std::map;
#if defined(UTILS_OS_WINDOWS)
#include <intrin.h>
void
cpuId( unsigned long CPUInfo[4], unsigned long l ) {
int CPUInfo1[4];
__cpuid( CPUInfo1, l );
CPUInfo[0] = CPUInfo1[0];
CPUInfo[1] = CPUInfo1[1];
CPUInfo[2] = CPUInfo1[2];
CPUInfo[3] = CPUInfo1[3];
}
#else
#if defined(__i386__) && defined(__PIC__)
/* %ebx may be the PIC register. */
#if __GNUC__ >= 3
#define __cpuid(level, a, b, c, d) \
__asm__ ( "xchg{l}\t{%%}ebx, %1\n\t" \
"cpuid\n\t" \
"xchg{l}\t{%%}ebx, %1\n\t" \
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
: "0" (level))
#else
/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
nor alternatives in i386 code. */
#define __cpuid(level, a, b, c, d) \
__asm__ ( "xchgl\t%%ebx, %1\n\t" \
"cpuid\n\t" \
"xchgl\t%%ebx, %1\n\t" \
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
: "0" (level))
#endif
#else
#define __cpuid(level, a, b, c, d) \
__asm__ ( "cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level))
#endif
void
cpuId( unsigned long CPUInfo[4], unsigned long l ) {
__cpuid( l, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3] );
}
#endif
static
void
info(
unsigned long CPUInfo[4],
unsigned long CPUInfoExt[4],
unsigned long & ECX,
unsigned long & EDX
) {
ECX = EDX = CPUInfoExt[0] = CPUInfoExt[1] = CPUInfoExt[2] = CPUInfoExt[3] = 0;
cpuId(CPUInfo, 0);
if( CPUInfo[0] >= 1 ) {
cpuId(CPUInfo, 1);
ECX = CPUInfo[2];
EDX = CPUInfo[3];
}
cpuId(CPUInfo, 0x80000000UL);
if( CPUInfo[0] >= 0x80000001UL ) cpuId(CPUInfoExt, 0x80000001UL);
}
void
info(
bool & m_bMMX,
bool & m_bMMXplus,
bool & m_bSSE,
bool & m_bSSE2,
bool & m_bSSE3,
bool & m_bSSSE3,
bool & m_bSSE41,
bool & m_bSSE42,
bool & m_bSSE4a,
bool & m_bSSE5,
bool & m_b3Dnow,
bool & m_b3DnowExt
) {
m_bMMX = false;
m_bMMXplus = false;
m_bSSE = false;
m_bSSE2 = false;
m_bSSE3 = false;
m_bSSSE3 = false;
m_bSSE41 = false;
m_bSSE42 = false;
m_bSSE4a = false;
m_bSSE5 = false;
m_b3Dnow = false;
m_b3DnowExt = false;
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
if ( EDX_MMX_bit & EDX ) m_bMMX = true;
if ( EDX_SSE_bit & EDX ) m_bSSE = true;
if ( EDX_SSE2_bit & EDX ) m_bSSE2 = true;
if ( ECX_SSE3_bit & ECX ) m_bSSE3 = true;
if ( ECX_SSSE3_bit & ECX ) m_bSSSE3 = true;
if ( ECX_SSE41_bit & ECX ) m_bSSE41 = true;
if ( ECX_SSE42_bit & ECX ) m_bSSE42 = true;
if ( EDX_3DnowExt_bit & CPUInfoExt[3] ) m_b3DnowExt = true;
if ( EDX_3Dnow_bit & CPUInfoExt[3] ) m_b3Dnow = true;
if ( EDX_MMXplus_bit & CPUInfoExt[3] ) m_bMMXplus = true;
if ( ECX_SSE4A_bit & CPUInfoExt[2] ) m_bSSE4a = true;
if ( ECX_SSE5_bit & CPUInfoExt[2] ) m_bSSE5 = true;
}
bool
has_MMX() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_MMX_bit & EDX) != 0;
}
bool
has_MMXplus() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_SSE_bit & EDX) != 0;
}
bool
has_SSE() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_SSE_bit & EDX) != 0;
}
bool
has_SSE2() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_SSE2_bit & EDX) != 0;
}
bool
has_SSE3() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSE3_bit & ECX) != 0;
}
bool
has_SSSE3() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSSE3_bit & ECX) != 0;
}
bool
has_SSE41() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSE41_bit & ECX) != 0;
}
bool
has_SSE42() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSE42_bit & ECX) != 0;
}
bool
has_SSE4a() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSE4A_bit & CPUInfoExt[2]) != 0;
}
bool
has_SSE5() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (ECX_SSE5_bit & CPUInfoExt[2]) != 0;
}
bool
has_3Dnow() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_3Dnow_bit & CPUInfoExt[3]) != 0;
}
bool
has_3DnowExt() {
unsigned long ECX, EDX, CPUInfo[4], CPUInfoExt[4];
info( CPUInfo, CPUInfoExt, ECX, EDX );
return (EDX_3DnowExt_bit & CPUInfoExt[3]) != 0;
}
struct CPUVendorID {
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
string
toString() const {
return string(reinterpret_cast<const char *>(this), 12);
}
};
string
cpuInfo() {
unsigned long CPUInfo[4];
cpuId( CPUInfo, 0 );
CPUVendorID vendorID;
vendorID.ebx = uint32_t(CPUInfo[1]);
vendorID.edx = uint32_t(CPUInfo[3]);
vendorID.ecx = uint32_t(CPUInfo[2]);
map<string,string> vendorIdToName;
vendorIdToName["GenuineIntel"] = "Intel";
vendorIdToName["AuthenticAMD"] = "AMD";
vendorIdToName["CyrixInstead"] = "Cyrix";
vendorIdToName["CentaurHauls"] = "Centaur";
vendorIdToName["SiS SiS SiS "] = "SiS";
vendorIdToName["NexGenDriven"] = "NexGen";
vendorIdToName["GenuineTMx86"] = "Transmeta";
vendorIdToName["RiseRiseRise"] = "Rise";
vendorIdToName["UMC UMC UMC "] = "UMC";
vendorIdToName["Geode by NSC"] = "National Semiconductor";
string vendorIDString = vendorID.toString();
map<string,string>::iterator it = vendorIdToName.find(vendorIDString);
string vendorName = (it == vendorIdToName.end()) ? "Unknown" : it->second;
return fmt::format(
"Max instruction ID: {} Vendor ID: {} Vendor name: {}",
CPUInfo[0], vendorIDString, vendorName
);
}
}
#endif
#endif