1 /*  This file is part of the Vc library. {{{
2 Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the names of contributing organizations nor the
12       names of its contributors may be used to endorse or promote products
13       derived from this software without specific prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 }}}*/
27 
28 #ifndef VC_CPUID_H_
29 #define VC_CPUID_H_
30 
31 #include "common/macros.h"
32 namespace Vc_VERSIONED_NAMESPACE
33 {
34 
35 /**
36  * \ingroup Utilities
37  * \headerfile cpuid.h <Vc/cpuid.h>
38  *
39  * This class is available for x86 / AMD64 systems to read and interpret information about the CPU's
40  * capabilities.
41  *
42  * Before any of the getter functions may be called, the init() function must have been called. It
43  * will be called automatically, but for any function executing before main, you better call
44  * \c CpuId::init() first.
45  *
46  * %Vc users will most likely not need this class directly, but rely on the
47  * isImplementationSupported, bestImplementationSupported, extraInstructionsSupported, and
48  * currentImplementationSupported functions.
49  */
50 class CpuId
51 {
52     typedef unsigned char uchar;
53     typedef unsigned short ushort;
54     typedef unsigned int uint;
55 
56     public:
57         enum ProcessorType {
58             OriginalOemProcessor = 0,
59             IntelOverDriveProcessor = 1,
60             DualProcessor = 2,
61             IntelReserved = 3
62         };
63 
64         /**
65          * Reads the CPU capabilities and stores them for faster subsequent access.
66          *
67          * Will be executed automatically before main, but not necessarily before other functions
68          * executing before main.
69          */
70         static void init();
71 
72         //! Return the cache line size in bits.
cacheLineSize()73         static inline ushort cacheLineSize() { return static_cast<ushort>(s_cacheLineSize) * 8u; }
74         //! Return the ProcessorType.
processorType()75         static inline ProcessorType processorType() { return s_processorType; }
76         //! Return the family number of the processor (vendor dependent).
processorFamily()77         static inline uint processorFamily() { return s_processorFamily; }
78         //! Return the model number of the processor (vendor dependent).
processorModel()79         static inline uint processorModel() { return s_processorModel; }
80         //! Return the number of logical processors.
logicalProcessors()81         static inline uint logicalProcessors() { return s_logicalProcessors; }
82         //! Return whether the CPU vendor is AMD.
isAmd()83         static inline bool isAmd   () { return s_ecx0 == 0x444D4163; }
84         //! Return whether the CPU vendor is Intel.
isIntel()85         static inline bool isIntel () { return s_ecx0 == 0x6C65746E; }
86         //! Return whether the CPU supports SSE3.
hasSse3()87         static inline bool hasSse3 () { return s_processorFeaturesC & (1 << 0); }
88         //! Return whether the CPU supports the PCLMULQDQ instruction.
hasPclmulqdq()89         static inline bool hasPclmulqdq() { return (s_processorFeaturesC & (1 << 1)) != 0; }
90         //! Return whether the CPU supports the MONITOR/MWAIT instructions.
hasMonitor()91         static inline bool hasMonitor() { return (s_processorFeaturesC & (1 << 3)) != 0; }
92         //! Return whether the CPU supports the Virtual Machine Extensions.
hasVmx()93         static inline bool hasVmx  () { return (s_processorFeaturesC & (1 << 5)) != 0; }
94         //! Return whether the CPU supports the Safer Mode Extensions.
hasSmx()95         static inline bool hasSmx  () { return (s_processorFeaturesC & (1 << 6)) != 0; }
96         //! Return whether the CPU supports the Enhanced Intel SpeedStep technology.
hasEist()97         static inline bool hasEist () { return (s_processorFeaturesC & (1 << 7)) != 0; }
98         //! Return whether the CPU supports Thermal Monitor 2.
hasTm2()99         static inline bool hasTm2  () { return (s_processorFeaturesC & (1 << 8)) != 0; }
100         //! Return whether the CPU supports SSSE3.
hasSsse3()101         static inline bool hasSsse3() { return (s_processorFeaturesC & (1 << 9)) != 0; }
102         //! Return whether the CPU supports FMA extensions using YMM state.
hasFma()103         static inline bool hasFma  () { return (s_processorFeaturesC & (1 << 12)) != 0; }
104         //! Return whether the CPU supports CMPXCHG16B.
hasCmpXchg16b()105         static inline bool hasCmpXchg16b() { return (s_processorFeaturesC & (1 << 13)) != 0; }
106         //! Return whether the CPU supports the Perfmon and Debug Capability.
hasPdcm()107         static inline bool hasPdcm () { return (s_processorFeaturesC & (1 << 15)) != 0; }
108         //! Return whether the CPU supports Direct Cache Access: prefetch data from a memory mapped device.
hasDca()109         static inline bool hasDca()   { return (s_processorFeaturesC & (1 << 18)) != 0; }
110         //! Return whether the CPU supports SSE 4.1
hasSse41()111         static inline bool hasSse41() { return (s_processorFeaturesC & (1 << 19)) != 0; }
112         //! Return whether the CPU supports SSE 4.2
hasSse42()113         static inline bool hasSse42() { return (s_processorFeaturesC & (1 << 20)) != 0; }
114         //! Return whether the CPU supports the MOVBE instruction.
hasMovbe()115         static inline bool hasMovbe() { return (s_processorFeaturesC & (1 << 22)) != 0; }
116         //! Return whether the CPU supports the POPCNT instruction.
hasPopcnt()117         static inline bool hasPopcnt(){ return (s_processorFeaturesC & (1 << 23)) != 0; }
118         //static inline bool hasTscDeadline() { return (s_processorFeaturesC & (1 << 24)) != 0; }
119         //! Return whether the CPU supports the AESNI instructions.
hasAes()120         static inline bool hasAes  () { return (s_processorFeaturesC & (1 << 25)) != 0; }
121         //static inline bool hasXsave() { return (s_processorFeaturesC & (1 << 26)) != 0; }
122         //! Return whether the CPU and OS support the XSETBV/XGETBV instructions.
hasOsxsave()123         static inline bool hasOsxsave() { return (s_processorFeaturesC & (1 << 27)) != 0; }
124         //! Return whether the CPU supports AVX.
hasAvx()125         static inline bool hasAvx  () { return (s_processorFeaturesC & (1 << 28)) != 0; }
126         //! Return whether the CPU supports BMI1.
hasBmi1()127         static inline bool hasBmi1 () { return (s_processorFeatures7B& (1 << 3)) != 0; }
128         //! Return whether the CPU supports transactional synchronization extensions.
hasHle()129         static inline bool hasHle  () { return (s_processorFeatures7B& (1 << 4)) != 0; }
130         //! Return whether the CPU supports AVX2.
hasAvx2()131         static inline bool hasAvx2 () { return (s_processorFeatures7B& (1 << 5)) != 0; }
132         //! Return whether the CPU supports BMI2.
hasBmi2()133         static inline bool hasBmi2 () { return (s_processorFeatures7B& (1 << 8)) != 0; }
134         //! Return whether the CPU supports transactional synchronization extensions.
hasRtm()135         static inline bool hasRtm  () { return (s_processorFeatures7B& (1 << 11)) != 0; }
136 
137         //! Return whether the CPU supports AVX512f.
hasAvx512f()138         static inline bool hasAvx512f   () { return (s_processorFeatures7B & (1u << 16)) != 0; }
139         //! Return whether the CPU supports AVX512dq.
hasAvx512dq()140         static inline bool hasAvx512dq  () { return (s_processorFeatures7B & (1u << 17)) != 0; }
141         //! Return whether the CPU supports AVX512ifma.
hasAvx512ifma()142         static inline bool hasAvx512ifma() { return (s_processorFeatures7B & (1u << 21)) != 0; }
143         //! Return whether the CPU supports AVX512pf.
hasAvx512pf()144         static inline bool hasAvx512pf  () { return (s_processorFeatures7B & (1u << 26)) != 0; }
145         //! Return whether the CPU supports AVX512er.
hasAvx512er()146         static inline bool hasAvx512er  () { return (s_processorFeatures7B & (1u << 27)) != 0; }
147         //! Return whether the CPU supports AVX512cd.
hasAvx512cd()148         static inline bool hasAvx512cd  () { return (s_processorFeatures7B & (1u << 28)) != 0; }
149         //! Return whether the CPU supports AVX512bw.
hasAvx512bw()150         static inline bool hasAvx512bw  () { return (s_processorFeatures7B & (1u << 30)) != 0; }
151         //! Return whether the CPU supports AVX512vl.
hasAvx512vl()152         static inline bool hasAvx512vl  () { return (s_processorFeatures7B & (1u << 31)) != 0; }
153         //! Return whether the CPU supports AVX512vbmi.
hasAvx512vbmi()154         static inline bool hasAvx512vbmi() { return (s_processorFeatures7C & (1u <<  1)) != 0; }
155 
156         //! Return whether the CPU supports 16-bit floating-point conversion instructions.
hasF16c()157         static inline bool hasF16c () { return (s_processorFeaturesC & (1 << 29)) != 0; }
158         //! Return whether the CPU supports the RDRAND instruction.
hasRdrand()159         static inline bool hasRdrand(){ return (s_processorFeaturesC & (1 << 30)) != 0; }
160         //! Return whether the CPU contains an x87 FPU.
hasFpu()161         static inline bool hasFpu  () { return (s_processorFeaturesD & (1 << 0)) != 0; }
hasVme()162         static inline bool hasVme  () { return (s_processorFeaturesD & (1 << 1)) != 0; }
163         //! Return whether the CPU contains Debugging Extensions.
hasDe()164         static inline bool hasDe   () { return (s_processorFeaturesD & (1 << 2)) != 0; }
165         //! Return whether the CPU contains Page Size Extensions.
hasPse()166         static inline bool hasPse  () { return (s_processorFeaturesD & (1 << 3)) != 0; }
167         //! Return whether the CPU supports the RDTSC instruction.
hasTsc()168         static inline bool hasTsc  () { return (s_processorFeaturesD & (1 << 4)) != 0; }
169         //! Return whether the CPU supports the Model Specific Registers instructions.
hasMsr()170         static inline bool hasMsr  () { return (s_processorFeaturesD & (1 << 5)) != 0; }
171         //! Return whether the CPU supports the Physical Address Extension.
hasPae()172         static inline bool hasPae  () { return (s_processorFeaturesD & (1 << 6)) != 0; }
173         //! Return whether the CPU supports the CMPXCHG8B instruction.
hasCx8()174         static inline bool hasCx8  () { return (s_processorFeaturesD & (1 << 8)) != 0; }
175         //! Return whether the CPU supports Memory Type Range Registers.
hasMtrr()176         static inline bool hasMtrr () { return (s_processorFeaturesD & (1 << 12)) != 0; }
177         //! Return whether the CPU supports CMOV instructions.
hasCmov()178         static inline bool hasCmov () { return (s_processorFeaturesD & (1 << 15)) != 0; }
179         //! Return whether the CPU supports the CLFLUSH instruction.
hasClfsh()180         static inline bool hasClfsh() { return (s_processorFeaturesD & (1 << 19)) != 0; }
181         //! Return whether the CPU supports ACPI.
hasAcpi()182         static inline bool hasAcpi () { return (s_processorFeaturesD & (1 << 22)) != 0; }
183         //! Return whether the CPU supports MMX.
hasMmx()184         static inline bool hasMmx  () { return (s_processorFeaturesD & (1 << 23)) != 0; }
185         //! Return whether the CPU supports SSE.
hasSse()186         static inline bool hasSse  () { return (s_processorFeaturesD & (1 << 25)) != 0; }
187         //! Return whether the CPU supports SSE2.
hasSse2()188         static inline bool hasSse2 () { return (s_processorFeaturesD & (1 << 26)) != 0; }
hasHtt()189         static inline bool hasHtt  () { return (s_processorFeaturesD & (1 << 28)) != 0; }
190         //! Return whether the CPU supports SSE4a.
hasSse4a()191         static inline bool hasSse4a() { return (s_processorFeatures8C & (1 << 6)) != 0; }
192         //! Return whether the CPU supports misaligned SSE instructions.
hasMisAlignSse()193         static inline bool hasMisAlignSse() { return (s_processorFeatures8C & (1 << 7)) != 0; }
194         //! Return whether the CPU supports the AMD prefetchw instruction.
hasAmdPrefetch()195         static inline bool hasAmdPrefetch() { return (s_processorFeatures8C & (1 << 8)) != 0; }
196         //! Return whether the CPU supports the XOP instructions.
hasXop()197         static inline bool hasXop ()        { return (s_processorFeatures8C & (1 << 11)) != 0; }
198         //! Return whether the CPU supports the FMA4 instructions.
hasFma4()199         static inline bool hasFma4 ()       { return (s_processorFeatures8C & (1 << 16)) != 0; }
200         //! Return whether the CPU supports the RDTSCP instruction.
hasRdtscp()201         static inline bool hasRdtscp()      { return (s_processorFeatures8D & (1 << 27)) != 0; }
has3DNow()202         static inline bool has3DNow()       { return (s_processorFeatures8D & (1u << 31)) != 0; }
has3DNowExt()203         static inline bool has3DNowExt()    { return (s_processorFeatures8D & (1 << 30)) != 0; }
204         //! Return the size of the L1 instruction cache.
L1Instruction()205         static inline uint   L1Instruction() { return s_L1Instruction; }
206         //! Return the size of the L1 data cache.
L1Data()207         static inline uint   L1Data() { return s_L1Data; }
208         //! Return the size of the L2 cache.
L2Data()209         static inline uint   L2Data() { return s_L2Data; }
210         //! Return the size of the L3 cache.
L3Data()211         static inline uint   L3Data() { return s_L3Data; }
L1InstructionLineSize()212         static inline ushort L1InstructionLineSize() { return s_L1InstructionLineSize; }
L1DataLineSize()213         static inline ushort L1DataLineSize() { return s_L1DataLineSize; }
L2DataLineSize()214         static inline ushort L2DataLineSize() { return s_L2DataLineSize; }
L3DataLineSize()215         static inline ushort L3DataLineSize() { return s_L3DataLineSize; }
L1Associativity()216         static inline uint   L1Associativity() { return s_L1Associativity; }
L2Associativity()217         static inline uint   L2Associativity() { return s_L2Associativity; }
L3Associativity()218         static inline uint   L3Associativity() { return s_L3Associativity; }
prefetch()219         static inline ushort prefetch() { return s_prefetch; }
220 
221     private:
222         static void interpret(uchar byte, bool *checkLeaf4);
223 
224         static uint   s_ecx0;
225         static uint   s_logicalProcessors;
226         static uint   s_processorFeaturesC;
227         static uint   s_processorFeaturesD;
228         static uint   s_processorFeatures7B;
229         static uint   s_processorFeatures7C;
230         static uint   s_processorFeatures8C;
231         static uint   s_processorFeatures8D;
232         static uint   s_L1Instruction;
233         static uint   s_L1Data;
234         static uint   s_L2Data;
235         static uint   s_L3Data;
236         static ushort s_L1InstructionLineSize;
237         static ushort s_L1DataLineSize;
238         static ushort s_L2DataLineSize;
239         static ushort s_L3DataLineSize;
240         static uint   s_L1Associativity;
241         static uint   s_L2Associativity;
242         static uint   s_L3Associativity;
243         static ushort s_prefetch;
244         static uchar  s_brandIndex;
245         static uchar  s_cacheLineSize;
246         static uchar  s_processorModel;
247         static uchar  s_processorFamily;
248         static ProcessorType s_processorType;
249         static bool   s_noL2orL3;
250 };
251 
252 #ifndef Vc_COMPILE_LIB
253 namespace detail
254 {
255 template <int = 0> struct RunCpuIdInit {
RunCpuIdInitRunCpuIdInit256     RunCpuIdInit() { CpuId::init(); }
257     static RunCpuIdInit tmp;
258 };
259 template <int N> RunCpuIdInit<N> RunCpuIdInit<N>::tmp;
260 namespace
261 {
262 static auto ctor = RunCpuIdInit<>::tmp;
263 }  // unnamed namespace
264 }  // namespace detail
265 #endif
266 
267 }
268 
269 #endif // VC_CPUID_H_
270