forked from STEllAR-GROUP/hpx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpuid.cpp
88 lines (77 loc) · 2.45 KB
/
cpuid.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
////////////////////////////////////////////////////////////////////////////////
// Copyright 2003 & onward LASMEA UMR 6602 CNRS/Univ. Clermont II
// Copyright 2009 & onward LRI UMR 8623 CNRS/Univ Paris Sud XI
// Copyright (c) 2011 Bryce Lelbach
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
////////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <string>
using namespace std;
struct registers_t { uint32_t eax, ebx, ecx, edx; };
#if defined __GNUC__
void __cpuid(registers_t& CPUInfo, uint32_t InfoType)
{
__asm__ __volatile__
(
"cpuid":
"=a" (CPUInfo.eax), "=b" (CPUInfo.ebx)
, "=c" (CPUInfo.ecx), "=d" (CPUInfo.edx)
: "a" (InfoType)
);
}
#elif defined _MSC_VER
#include <intrin.h>
#endif
bool has_bit_set(uint32_t value, uint32_t bit)
{
return (value & (1U<<bit)) != 0;
}
struct matcher
{
uint32_t function;
uint32_t registers_t::* reg;
uint32_t bit;
const char* target;
}
options[] =
{
{0x00000001U, ®isters_t::edx, 19, "clflush"}
, {0x00000001U, ®isters_t::edx, 8, "cx8" }
, {0x00000001U, ®isters_t::ecx, 13, "cx16" }
, {0x00000001U, ®isters_t::edx, 15, "cmov" }
, {0x00000001U, ®isters_t::edx, 5, "msr" }
, {0x00000001U, ®isters_t::edx, 4, "rdtsc" }
, {0x80000001U, ®isters_t::edx, 27, "rdtscp" }
, {0x00000001U, ®isters_t::edx, 23, "mmx" }
, {0x00000001U, ®isters_t::edx, 25, "sse" }
, {0x00000001U, ®isters_t::edx, 26, "sse2" }
, {0x00000001U, ®isters_t::ecx, 0, "sse3" }
, {0x00000001U, ®isters_t::ecx, 9, "ssse3" }
, {0x00000001U, ®isters_t::ecx, 19, "sse4.1" }
, {0x00000001U, ®isters_t::ecx, 20, "sse4.2" }
, {0x00000001U, ®isters_t::ecx, 28, "avx" }
, {0x80000001U, ®isters_t::edx, 11, "xop" }
, {0x80000001U, ®isters_t::edx, 16, "fma4" }
};
const size_t noptions = sizeof options / sizeof options[0];
int main(int argc, char** argv)
{
registers_t registers;
if (argc < 2) return -1;
string target(argv[1]);
__cpuid(registers,0x00000000);
matcher m;
size_t i = 0;
for (i=0; i<noptions; ++i) {
if (target == options[i].target) {
m = options[i];
break;
}
}
if (i >= noptions) return -2;
__cpuid(registers, m.function);
// exit with 0 if the bit is set
return !has_bit_set(registers.*m.reg, m.bit);
}