1 #ifndef PROCESSOR_SUPPORT_H_ 2 #define PROCESSOR_SUPPORT_H_ 3 4 // Utility class ProcessorSupport provides POPCNTenabled() to determine 5 // processor support for POPCNT instruction. It uses CPUID to 6 // retrieve the processor capabilities. 7 // for Intel ICC compiler __cpuid() is an intrinsic 8 // for Microsoft compiler __cpuid() is provided by #include <intrin.h> 9 // for GCC compiler __get_cpuid() is provided by #include <cpuid.h> 10 11 // Intel compiler defines __GNUC__, so this is needed to disambiguate 12 13 #if defined(__INTEL_COMPILER) 14 # define USING_INTEL_COMPILER 15 #elif defined(__GNUC__) 16 # define USING_GCC_COMPILER 17 # include <cpuid.h> 18 #elif defined(_MSC_VER) 19 // __MSC_VER defined by Microsoft compiler 20 #define USING MSC_COMPILER 21 #endif 22 23 struct regs_t {unsigned int EAX, EBX, ECX, EDX;}; 24 #define BIT(n) ((1<<n)) 25 26 class ProcessorSupport { 27 28 #ifdef POPCNT_CAPABILITY 29 30 public: ProcessorSupport()31 ProcessorSupport() { } POPCNTenabled()32 bool POPCNTenabled() 33 { 34 // from: Intel® 64 and IA-32 Architectures Software Developer’s Manual, 325462-036US,March 2013 35 //Before an application attempts to use the POPCNT instruction, it must check that the 36 //processor supports SSE4.2 37 //"(if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT (if CPUID.01H:ECX.POPCNT[bit 23] = 1)" 38 // 39 // see p.272 of http://download.intel.com/products/processor/manual/253667.pdf available at 40 // http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html 41 // Also http://en.wikipedia.org/wiki/SSE4 talks about available on Intel & AMD processors 42 43 regs_t regs; 44 45 try { 46 #if ( defined(USING_INTEL_COMPILER) || defined(USING_MSC_COMPILER) ) 47 __cpuid((int *) ®s,0); // test if __cpuid() works, if not catch the exception 48 __cpuid((int *) ®s,0x1); // POPCNT bit is bit 23 in ECX 49 #elif defined(USING_GCC_COMPILER) 50 __get_cpuid(0x1, ®s.EAX, ®s.EBX, ®s.ECX, ®s.EDX); 51 #else 52 std::cerr << "ERROR: please define __cpuid() for this build.\n"; 53 assert(0); 54 #endif 55 if( !( (regs.ECX & BIT(20)) && (regs.ECX & BIT(23)) ) ) return false; 56 } 57 catch (int e) { 58 return false; 59 } 60 return true; 61 } 62 63 #endif // POPCNT_CAPABILITY 64 }; 65 66 #endif /*PROCESSOR_SUPPORT_H_*/ 67