-
Notifications
You must be signed in to change notification settings - Fork 77
/
processor_support.h
66 lines (55 loc) · 2.18 KB
/
processor_support.h
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
#ifndef PROCESSOR_SUPPORT_H_
#define PROCESSOR_SUPPORT_H_
// Utility class ProcessorSupport provides POPCNTenabled() to determine
// processor support for POPCNT instruction. It uses CPUID to
// retrieve the processor capabilities.
// for Intel ICC compiler __cpuid() is an intrinsic
// for Microsoft compiler __cpuid() is provided by #include <intrin.h>
// for GCC compiler __get_cpuid() is provided by #include <cpuid.h>
// Intel compiler defines __GNUC__, so this is needed to disambiguate
#if defined(__INTEL_COMPILER)
# define USING_INTEL_COMPILER
#elif defined(__GNUC__)
# define USING_GCC_COMPILER
# include <cpuid.h>
#elif defined(_MSC_VER)
// __MSC_VER defined by Microsoft compiler
#define USING MSC_COMPILER
#endif
struct regs_t {unsigned int EAX, EBX, ECX, EDX;};
#define BIT(n) ((1<<n))
class ProcessorSupport {
#ifdef POPCNT_CAPABILITY
public:
ProcessorSupport() { }
bool POPCNTenabled()
{
// from: Intel® 64 and IA-32 Architectures Software Developer’s Manual, 325462-036US,March 2013
//Before an application attempts to use the POPCNT instruction, it must check that the
//processor supports SSE4.2
//“(if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT (if CPUID.01H:ECX.POPCNT[bit 23] = 1)”
//
// see p.272 of http://download.intel.com/products/processor/manual/253667.pdf available at
// http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
// Also http://en.wikipedia.org/wiki/SSE4 talks about available on Intel & AMD processors
regs_t regs;
try {
#if ( defined(USING_INTEL_COMPILER) || defined(USING_MSC_COMPILER) )
__cpuid((int *) ®s,0); // test if __cpuid() works, if not catch the exception
__cpuid((int *) ®s,0x1); // POPCNT bit is bit 23 in ECX
#elif defined(USING_GCC_COMPILER)
__get_cpuid(0x1, ®s.EAX, ®s.EBX, ®s.ECX, ®s.EDX);
#else
std::cerr << "ERROR: please define __cpuid() for this build.\n";
assert(0);
#endif
if( !( (regs.ECX & BIT(20)) && (regs.ECX & BIT(23)) ) ) return false;
}
catch (int e) {
return false;
}
return true;
}
#endif // POPCNT_CAPABILITY
};
#endif /*PROCESSOR_SUPPORT_H_*/