1c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley/**************************************************************************** 2c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. 3c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* 4c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* Permission is hereby granted, free of charge, to any person obtaining a 5c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* copy of this software and associated documentation files (the "Software"), 6c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* to deal in the Software without restriction, including without limitation 7c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* and/or sell copies of the Software, and to permit persons to whom the 9c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* Software is furnished to do so, subject to the following conditions: 10c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* 11c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* The above copyright notice and this permission notice (including the next 12c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* paragraph) shall be included in all copies or substantial portions of the 13c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* Software. 14c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* 15c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley* IN THE SOFTWARE. 22c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley****************************************************************************/ 23c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 24c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#pragma once 25c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 26c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <iostream> 27c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <vector> 28c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <bitset> 29c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <array> 30c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <string> 31c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <algorithm> 32c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 3395f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley// Clang for Windows does supply an intrin.h with __cpuid intrinsics, however... 3495f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley// It seems to not realize that a write to "b" (ebx) will kill the value in rbx. 3595f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley// This attempts to use the "native" clang / gcc intrinsics instead of the windows 3695f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley// compatible ones. 3795f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley#if defined(_MSC_VER) && !defined(__clang__) 38c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <intrin.h> 39c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#else 40c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <string.h> 41c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#include <cpuid.h> 42c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#endif 43c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 44c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass InstructionSet 45c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley{ 46c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleypublic: 47c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley InstructionSet() : CPU_Rep() {}; 48c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 49c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // getters 50c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::string Vendor(void) { return CPU_Rep.vendor_; } 51c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::string Brand(void) { return CPU_Rep.brand_; } 52c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 53c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE3(void) { return CPU_Rep.f_1_ECX_[0]; } 54c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool PCLMULQDQ(void) { return CPU_Rep.f_1_ECX_[1]; } 55c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool MONITOR(void) { return CPU_Rep.f_1_ECX_[3]; } 56c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSSE3(void) { return CPU_Rep.f_1_ECX_[9]; } 57c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool FMA(void) { return CPU_Rep.f_1_ECX_[12]; } 58c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool CMPXCHG16B(void) { return CPU_Rep.f_1_ECX_[13]; } 59c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE41(void) { return CPU_Rep.f_1_ECX_[19]; } 60c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE42(void) { return CPU_Rep.f_1_ECX_[20]; } 61c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool MOVBE(void) { return CPU_Rep.f_1_ECX_[22]; } 62c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool POPCNT(void) { return CPU_Rep.f_1_ECX_[23]; } 63c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AES(void) { return CPU_Rep.f_1_ECX_[25]; } 64c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool XSAVE(void) { return CPU_Rep.f_1_ECX_[26]; } 65c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool OSXSAVE(void) { return CPU_Rep.f_1_ECX_[27]; } 66c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool RDRAND(void) { return CPU_Rep.f_1_ECX_[30]; } 67c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 68c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool MSR(void) { return CPU_Rep.f_1_EDX_[5]; } 69c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool CX8(void) { return CPU_Rep.f_1_EDX_[8]; } 70c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SEP(void) { return CPU_Rep.f_1_EDX_[11]; } 71c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool CMOV(void) { return CPU_Rep.f_1_EDX_[15]; } 72c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool CLFSH(void) { return CPU_Rep.f_1_EDX_[19]; } 73c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool MMX(void) { return CPU_Rep.f_1_EDX_[23]; } 74c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool FXSR(void) { return CPU_Rep.f_1_EDX_[24]; } 75c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE(void) { return CPU_Rep.f_1_EDX_[25]; } 76c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE2(void) { return CPU_Rep.f_1_EDX_[26]; } 77c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 78c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool FSGSBASE(void) { return CPU_Rep.f_7_EBX_[0]; } 79c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool BMI1(void) { return CPU_Rep.f_7_EBX_[3]; } 80c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool HLE(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[4]; } 81c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool BMI2(void) { return CPU_Rep.f_7_EBX_[8]; } 82c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool ERMS(void) { return CPU_Rep.f_7_EBX_[9]; } 83c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool INVPCID(void) { return CPU_Rep.f_7_EBX_[10]; } 84c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool RTM(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[11]; } 85c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool RDSEED(void) { return CPU_Rep.f_7_EBX_[18]; } 86c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool ADX(void) { return CPU_Rep.f_7_EBX_[19]; } 87c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SHA(void) { return CPU_Rep.f_7_EBX_[29]; } 88c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 89c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool PREFETCHWT1(void) { return CPU_Rep.f_7_ECX_[0]; } 90c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 91c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool LAHF(void) { return CPU_Rep.f_81_ECX_[0]; } 92c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool LZCNT(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_ECX_[5]; } 93c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool ABM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[5]; } 94c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SSE4a(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[6]; } 95c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool XOP(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[11]; } 96c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool TBM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[21]; } 97c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 98c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool SYSCALL(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[11]; } 99c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool MMXEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[22]; } 100c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool RDTSCP(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[27]; } 101c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool _3DNOWEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[30]; } 102c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool _3DNOW(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[31]; } 103c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 104c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX(void) { return CPU_Rep.f_1_ECX_[28]; } 105c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool F16C(void) { return CPU_Rep.f_1_ECX_[29]; } 106c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX2(void) { return CPU_Rep.f_7_EBX_[5]; } 107c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX512F(void) { return CPU_Rep.f_7_EBX_[16]; } 108c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX512PF(void) { return CPU_Rep.f_7_EBX_[26]; } 109c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX512ER(void) { return CPU_Rep.f_7_EBX_[27]; } 110c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool AVX512CD(void) { return CPU_Rep.f_7_EBX_[28]; } 111c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 112c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyprivate: 113c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley class InstructionSet_Internal 114c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 115c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley public: 116c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley InstructionSet_Internal() 117c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley : nIds_{ 0 }, 118c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley nExIds_{ 0 }, 119c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley isIntel_{ false }, 120c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley isAMD_{ false }, 121c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_1_ECX_{ 0 }, 122c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_1_EDX_{ 0 }, 123c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_7_EBX_{ 0 }, 124c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_7_ECX_{ 0 }, 125c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_81_ECX_{ 0 }, 126c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_81_EDX_{ 0 }, 127c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley data_{}, 128c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley extdata_{} 129c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 130c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley //int cpuInfo[4] = {-1}; 131c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::array<int, 4> cpui; 132c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 133c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // Calling __cpuid with 0x0 as the function_id argument 134c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // gets the number of the highest valid function ID. 13595f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley#if defined(_MSC_VER) && !defined(__clang__) 136c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuid(cpui.data(), 0); 137c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley nIds_ = cpui[0]; 138c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#else 139c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley nIds_ = __get_cpuid_max(0, NULL); 140c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#endif 141c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 142c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley for (int i = 0; i <= nIds_; ++i) 143c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 14495f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley#if defined(_MSC_VER) && !defined(__clang__) 145c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuidex(cpui.data(), i, 0); 146c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#else 147c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley int *data = cpui.data(); 148c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuid_count(i, 0, data[0], data[1], data[2], data[3]); 149c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#endif 150c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley data_.push_back(cpui); 151c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 152c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 153c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // Capture vendor string 154c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley char vendor[0x20]; 155c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley memset(vendor, 0, sizeof(vendor)); 156c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley *reinterpret_cast<int*>(vendor) = data_[0][1]; 157c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley *reinterpret_cast<int*>(vendor + 4) = data_[0][3]; 158c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley *reinterpret_cast<int*>(vendor + 8) = data_[0][2]; 159c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley vendor_ = vendor; 160c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if (vendor_ == "GenuineIntel") 161c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 162c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley isIntel_ = true; 163c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 164c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else if (vendor_ == "AuthenticAMD") 165c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 166c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley isAMD_ = true; 167c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 168c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 169c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // load bitset with flags for function 0x00000001 170c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if (nIds_ >= 1) 171c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 172c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_1_ECX_ = data_[1][2]; 173c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_1_EDX_ = data_[1][3]; 174c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 175c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 176c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // load bitset with flags for function 0x00000007 177c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if (nIds_ >= 7) 178c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 179c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_7_EBX_ = data_[7][1]; 180c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_7_ECX_ = data_[7][2]; 181c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 182c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 183c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // Calling __cpuid with 0x80000000 as the function_id argument 184c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // gets the number of the highest valid extended ID. 18595f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley#if defined(_MSC_VER) && !defined(__clang__) 186c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuid(cpui.data(), 0x80000000); 187c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley nExIds_ = cpui[0]; 188c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#else 189c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley nExIds_ = __get_cpuid_max(0x80000000, NULL); 190c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#endif 191c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 192c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley char brand[0x40]; 193c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley memset(brand, 0, sizeof(brand)); 194c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 195c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley for (unsigned i = 0x80000000; i <= nExIds_; ++i) 196c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 19795f21a97666d5eb112fffc4d724e54229e06ebf8Tim Rowley#if defined(_MSC_VER) && !defined(__clang__) 198c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuidex(cpui.data(), i, 0); 199c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#else 200c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley int *data = cpui.data(); 201c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley __cpuid_count(i, 0, data[0], data[1], data[2], data[3]); 202c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley#endif 203c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley extdata_.push_back(cpui); 204c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 205c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 206c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // load bitset with flags for function 0x80000001 207c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if (nExIds_ >= 0x80000001) 208c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 209c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_81_ECX_ = extdata_[1][2]; 210c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley f_81_EDX_ = extdata_[1][3]; 211c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 212c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 213c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley // Interpret CPU brand string if reported 214c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if (nExIds_ >= 0x80000004) 215c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley { 216c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley memcpy(brand, extdata_[2].data(), sizeof(cpui)); 217c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley memcpy(brand + 16, extdata_[3].data(), sizeof(cpui)); 218c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley memcpy(brand + 32, extdata_[4].data(), sizeof(cpui)); 219c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley brand_ = brand; 220c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley } 221c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley }; 222c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 223c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley int nIds_; 224c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley unsigned nExIds_; 225c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::string vendor_; 226c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::string brand_; 227c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool isIntel_; 228c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley bool isAMD_; 229c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_1_ECX_; 230c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_1_EDX_; 231c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_7_EBX_; 232c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_7_ECX_; 233c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_81_ECX_; 234c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::bitset<32> f_81_EDX_; 235c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::vector<std::array<int, 4>> data_; 236c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley std::vector<std::array<int, 4>> extdata_; 237c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley }; 238c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley const InstructionSet_Internal CPU_Rep; 239c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley}; 240