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_*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|