1 /*
2 * Runtime CPU detection
3 * (C) 2009-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #ifndef BOTAN_CPUID_H__
9 #define BOTAN_CPUID_H__
10 
11 #include <botan/types.h>
12 
13 namespace Botan {
14 
15 /**
16 * A class handling runtime CPU feature detection
17 */
18 class BOTAN_DLL CPUID
19    {
20    public:
21       /**
22       * Probe the CPU and see what extensions are supported
23       */
24       static void initialize();
25 
26       /**
27       * Return a best guess of the cache line size
28       */
cache_line_size()29       static size_t cache_line_size() { return cache_line; }
30 
31       /**
32       * Check if the processor supports RDTSC
33       */
has_rdtsc()34       static bool has_rdtsc()
35          { return x86_processor_flags_has(CPUID_RDTSC_BIT); }
36 
37       /**
38       * Check if the processor supports SSE2
39       */
has_sse2()40       static bool has_sse2()
41          { return x86_processor_flags_has(CPUID_SSE2_BIT); }
42 
43       /**
44       * Check if the processor supports SSSE3
45       */
has_ssse3()46       static bool has_ssse3()
47          { return x86_processor_flags_has(CPUID_SSSE3_BIT); }
48 
49       /**
50       * Check if the processor supports SSE4.1
51       */
has_sse41()52       static bool has_sse41()
53          { return x86_processor_flags_has(CPUID_SSE41_BIT); }
54 
55       /**
56       * Check if the processor supports SSE4.2
57       */
has_sse42()58       static bool has_sse42()
59          { return x86_processor_flags_has(CPUID_SSE42_BIT); }
60 
61       /**
62       * Check if the processor supports extended AVX vector instructions
63       */
has_avx()64       static bool has_avx()
65          { return x86_processor_flags_has(CPUID_AVX_BIT); }
66 
67       /**
68       * Check if the processor supports AES-NI
69       */
has_aes_ni()70       static bool has_aes_ni()
71          { return x86_processor_flags_has(CPUID_AESNI_BIT); }
72 
73       /**
74       * Check if the processor supports PCMULUDQ
75       */
has_pcmuludq()76       static bool has_pcmuludq()
77          { return x86_processor_flags_has(CPUID_PCMUL_BIT); }
78 
79       /**
80       * Check if the processor supports MOVBE
81       */
has_movbe()82       static bool has_movbe()
83          { return x86_processor_flags_has(CPUID_MOVBE_BIT); }
84 
85       /**
86       * Check if the processor supports RDRAND
87       */
has_rdrand()88       static bool has_rdrand()
89          { return x86_processor_flags_has(CPUID_RDRAND_BIT); }
90 
91       /**
92       * Check if the processor supports AltiVec/VMX
93       */
has_altivec()94       static bool has_altivec() { return altivec_capable; }
95    private:
96       enum CPUID_bits {
97          CPUID_RDTSC_BIT = 4,
98          CPUID_SSE2_BIT = 26,
99          CPUID_PCMUL_BIT = 33,
100          CPUID_SSSE3_BIT = 41,
101          CPUID_SSE41_BIT = 51,
102          CPUID_SSE42_BIT = 52,
103          CPUID_MOVBE_BIT = 54,
104          CPUID_AESNI_BIT = 57,
105          CPUID_AVX_BIT = 60,
106          CPUID_RDRAND_BIT = 62
107       };
108 
x86_processor_flags_has(u64bit bit)109       static bool x86_processor_flags_has(u64bit bit)
110          {
111          return ((x86_processor_flags >> bit) & 1);
112          }
113 
114       static u64bit x86_processor_flags;
115       static size_t cache_line;
116       static bool altivec_capable;
117    };
118 
119 }
120 
121 #endif
122