Botan  1.11.15
src/lib/utils/cpuid.h
Go to the documentation of this file.
00001 /*
00002 * Runtime CPU detection
00003 * (C) 2009-2010,2013 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_CPUID_H__
00009 #define BOTAN_CPUID_H__
00010 
00011 #include <botan/types.h>
00012 #include <iosfwd>
00013 
00014 namespace Botan {
00015 
00016 /**
00017 * A class handling runtime CPU feature detection
00018 */
00019 class BOTAN_DLL CPUID
00020    {
00021    public:
00022       /**
00023       * Probe the CPU and see what extensions are supported
00024       */
00025       static void initialize();
00026 
00027       /**
00028       * Return a best guess of the cache line size
00029       */
00030       static size_t cache_line_size() { initialize(); return g_cache_line_size; }
00031 
00032       /**
00033       * Check if the processor supports AltiVec/VMX
00034       */
00035       static bool has_altivec() { initialize(); return g_altivec_capable; }
00036 
00037       /**
00038       * Check if the processor supports RDTSC
00039       */
00040       static bool has_rdtsc()
00041          { return x86_processor_flags_has(CPUID_RDTSC_BIT); }
00042 
00043       /**
00044       * Check if the processor supports SSE2
00045       */
00046       static bool has_sse2()
00047          { return x86_processor_flags_has(CPUID_SSE2_BIT); }
00048 
00049       /**
00050       * Check if the processor supports SSSE3
00051       */
00052       static bool has_ssse3()
00053          { return x86_processor_flags_has(CPUID_SSSE3_BIT); }
00054 
00055       /**
00056       * Check if the processor supports SSE4.1
00057       */
00058       static bool has_sse41()
00059          { return x86_processor_flags_has(CPUID_SSE41_BIT); }
00060 
00061       /**
00062       * Check if the processor supports SSE4.2
00063       */
00064       static bool has_sse42()
00065          { return x86_processor_flags_has(CPUID_SSE42_BIT); }
00066 
00067       /**
00068       * Check if the processor supports AVX2
00069       */
00070       static bool has_avx2()
00071          { return x86_processor_flags_has(CPUID_AVX2_BIT); }
00072 
00073       /**
00074       * Check if the processor supports AVX-512F
00075       */
00076       static bool has_avx512f()
00077          { return x86_processor_flags_has(CPUID_AVX512F_BIT); }
00078 
00079       /**
00080       * Check if the processor supports BMI2
00081       */
00082       static bool has_bmi2()
00083          { return x86_processor_flags_has(CPUID_BMI2_BIT); }
00084 
00085       /**
00086       * Check if the processor supports AES-NI
00087       */
00088       static bool has_aes_ni()
00089          { return x86_processor_flags_has(CPUID_AESNI_BIT); }
00090 
00091       /**
00092       * Check if the processor supports CLMUL
00093       */
00094       static bool has_clmul()
00095          { return x86_processor_flags_has(CPUID_CLMUL_BIT); }
00096 
00097       /**
00098       * Check if the processor supports Intel SHA extension
00099       */
00100       static bool has_intel_sha()
00101          { return x86_processor_flags_has(CPUID_SHA_BIT); }
00102 
00103       /**
00104       * Check if the processor supports ADX extension
00105       */
00106       static bool has_adx()
00107          { return x86_processor_flags_has(CPUID_ADX_BIT); }
00108 
00109       /**
00110       * Check if the processor supports RDRAND
00111       */
00112       static bool has_rdrand()
00113          { return x86_processor_flags_has(CPUID_RDRAND_BIT); }
00114 
00115       /**
00116       * Check if the processor supports RDSEED
00117       */
00118       static bool has_rdseed()
00119          { return x86_processor_flags_has(CPUID_RDSEED_BIT); }
00120 
00121       static void print(std::ostream& o);
00122    private:
00123       enum CPUID_bits {
00124          CPUID_RDTSC_BIT = 4,
00125          CPUID_SSE2_BIT = 26,
00126          CPUID_CLMUL_BIT = 33,
00127          CPUID_SSSE3_BIT = 41,
00128          CPUID_SSE41_BIT = 51,
00129          CPUID_SSE42_BIT = 52,
00130          CPUID_AESNI_BIT = 57,
00131          CPUID_RDRAND_BIT = 62,
00132 
00133          CPUID_AVX2_BIT = 64+5,
00134          CPUID_BMI2_BIT = 64+8,
00135          CPUID_AVX512F_BIT = 64+16,
00136          CPUID_RDSEED_BIT = 64+18,
00137          CPUID_ADX_BIT = 64+19,
00138          CPUID_SHA_BIT = 64+29,
00139       };
00140 
00141       static bool x86_processor_flags_has(u64bit bit)
00142          {
00143          if(!g_initialized)
00144             initialize();
00145          return ((g_x86_processor_flags[bit/64] >> (bit % 64)) & 1);
00146          }
00147 
00148       static bool g_initialized;
00149       static u64bit g_x86_processor_flags[2];
00150       static size_t g_cache_line_size;
00151       static bool g_altivec_capable;
00152    };
00153 
00154 }
00155 
00156 #endif