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