74 lines
2.3 KiB
C++
74 lines
2.3 KiB
C++
#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_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_INTEL_COMPILER)
|
||
__cpuid((void *) ®s,0); // test if __cpuid() works, if not catch the exception
|
||
__cpuid((void *) ®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_*/
|
||
|
||
|
||
|
||
|