Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/common/isa.hpp
4574 views
/****************************************************************************1* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21****************************************************************************/2223#pragma once2425#include <iostream>26#include <vector>27#include <bitset>28#include <array>29#include <string>30#include <algorithm>3132// Clang for Windows does supply an intrin.h with __cpuid intrinsics, however...33// It seems to not realize that a write to "b" (ebx) will kill the value in rbx.34// This attempts to use the "native" clang / gcc intrinsics instead of the windows35// compatible ones.36#if defined(_MSC_VER) && !defined(__clang__)37#include <intrin.h>38#else39#include <string.h>40#if !defined(__cpuid)41#include <cpuid.h>42#endif43#endif4445class InstructionSet46{47public:48InstructionSet() : CPU_Rep(){};4950// getters51std::string Vendor(void) { return CPU_Rep.vendor_; }52std::string Brand(void) { return CPU_Rep.brand_; }5354bool SSE3(void) { return CPU_Rep.f_1_ECX_[0]; }55bool PCLMULQDQ(void) { return CPU_Rep.f_1_ECX_[1]; }56bool MONITOR(void) { return CPU_Rep.f_1_ECX_[3]; }57bool SSSE3(void) { return CPU_Rep.f_1_ECX_[9]; }58bool FMA(void) { return CPU_Rep.f_1_ECX_[12]; }59bool CMPXCHG16B(void) { return CPU_Rep.f_1_ECX_[13]; }60bool SSE41(void) { return CPU_Rep.f_1_ECX_[19]; }61bool SSE42(void) { return CPU_Rep.f_1_ECX_[20]; }62bool MOVBE(void) { return CPU_Rep.f_1_ECX_[22]; }63bool POPCNT(void) { return CPU_Rep.f_1_ECX_[23]; }64bool AES(void) { return CPU_Rep.f_1_ECX_[25]; }65bool XSAVE(void) { return CPU_Rep.f_1_ECX_[26]; }66bool OSXSAVE(void) { return CPU_Rep.f_1_ECX_[27]; }67bool RDRAND(void) { return CPU_Rep.f_1_ECX_[30]; }6869bool MSR(void) { return CPU_Rep.f_1_EDX_[5]; }70bool CX8(void) { return CPU_Rep.f_1_EDX_[8]; }71bool SEP(void) { return CPU_Rep.f_1_EDX_[11]; }72bool CMOV(void) { return CPU_Rep.f_1_EDX_[15]; }73bool CLFSH(void) { return CPU_Rep.f_1_EDX_[19]; }74bool MMX(void) { return CPU_Rep.f_1_EDX_[23]; }75bool FXSR(void) { return CPU_Rep.f_1_EDX_[24]; }76bool SSE(void) { return CPU_Rep.f_1_EDX_[25]; }77bool SSE2(void) { return CPU_Rep.f_1_EDX_[26]; }7879bool FSGSBASE(void) { return CPU_Rep.f_7_EBX_[0]; }80bool BMI1(void) { return CPU_Rep.f_7_EBX_[3]; }81bool HLE(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[4]; }82bool BMI2(void) { return CPU_Rep.f_7_EBX_[8]; }83bool ERMS(void) { return CPU_Rep.f_7_EBX_[9]; }84bool INVPCID(void) { return CPU_Rep.f_7_EBX_[10]; }85bool RTM(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[11]; }86bool RDSEED(void) { return CPU_Rep.f_7_EBX_[18]; }87bool ADX(void) { return CPU_Rep.f_7_EBX_[19]; }88bool SHA(void) { return CPU_Rep.f_7_EBX_[29]; }8990bool PREFETCHWT1(void) { return CPU_Rep.f_7_ECX_[0]; }9192bool LAHF(void) { return CPU_Rep.f_81_ECX_[0]; }93bool LZCNT(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_ECX_[5]; }94bool ABM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[5]; }95bool SSE4a(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[6]; }96bool XOP(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[11]; }97bool TBM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[21]; }9899bool SYSCALL(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[11]; }100bool MMXEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[22]; }101bool RDTSCP(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[27]; }102bool _3DNOWEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[30]; }103bool _3DNOW(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[31]; }104105bool AVX(void) { return CPU_Rep.f_1_ECX_[28]; }106bool F16C(void) { return CPU_Rep.f_1_ECX_[29]; }107bool AVX2(void) { return CPU_Rep.f_7_EBX_[5]; }108bool AVX512F(void) { return CPU_Rep.f_7_EBX_[16]; }109bool AVX512PF(void) { return CPU_Rep.f_7_EBX_[26]; }110bool AVX512ER(void) { return CPU_Rep.f_7_EBX_[27]; }111bool AVX512CD(void) { return CPU_Rep.f_7_EBX_[28]; }112113private:114class InstructionSet_Internal115{116public:117InstructionSet_Internal() :118nIds_{0}, nExIds_{0}, isIntel_{false}, isAMD_{false}, f_1_ECX_{0}, f_1_EDX_{0},119f_7_EBX_{0}, f_7_ECX_{0}, f_81_ECX_{0}, f_81_EDX_{0}, data_{}, extdata_{}120{121// int cpuInfo[4] = {-1};122std::array<int, 4> cpui;123124// Calling __cpuid with 0x0 as the function_id argument125// gets the number of the highest valid function ID.126#if defined(_MSC_VER) && !defined(__clang__)127__cpuid(cpui.data(), 0);128nIds_ = cpui[0];129#else130nIds_ = __get_cpuid_max(0, NULL);131#endif132133for (int i = 0; i <= nIds_; ++i)134{135#if defined(_MSC_VER) && !defined(__clang__)136__cpuidex(cpui.data(), i, 0);137#else138int* data = cpui.data();139__cpuid_count(i, 0, data[0], data[1], data[2], data[3]);140#endif141data_.push_back(cpui);142}143144// Capture vendor string145char vendor[0x20];146memset(vendor, 0, sizeof(vendor));147*reinterpret_cast<int*>(vendor) = data_[0][1];148*reinterpret_cast<int*>(vendor + 4) = data_[0][3];149*reinterpret_cast<int*>(vendor + 8) = data_[0][2];150vendor_ = vendor;151if (vendor_ == "GenuineIntel")152{153isIntel_ = true;154}155else if (vendor_ == "AuthenticAMD")156{157isAMD_ = true;158}159160// load bitset with flags for function 0x00000001161if (nIds_ >= 1)162{163f_1_ECX_ = data_[1][2];164f_1_EDX_ = data_[1][3];165}166167// load bitset with flags for function 0x00000007168if (nIds_ >= 7)169{170f_7_EBX_ = data_[7][1];171f_7_ECX_ = data_[7][2];172}173174// Calling __cpuid with 0x80000000 as the function_id argument175// gets the number of the highest valid extended ID.176#if defined(_MSC_VER) && !defined(__clang__)177__cpuid(cpui.data(), 0x80000000);178nExIds_ = cpui[0];179#else180nExIds_ = __get_cpuid_max(0x80000000, NULL);181#endif182183char brand[0x40];184memset(brand, 0, sizeof(brand));185186for (unsigned i = 0x80000000; i <= nExIds_; ++i)187{188#if defined(_MSC_VER) && !defined(__clang__)189__cpuidex(cpui.data(), i, 0);190#else191int* data = cpui.data();192__cpuid_count(i, 0, data[0], data[1], data[2], data[3]);193#endif194extdata_.push_back(cpui);195}196197// load bitset with flags for function 0x80000001198if (nExIds_ >= 0x80000001)199{200f_81_ECX_ = extdata_[1][2];201f_81_EDX_ = extdata_[1][3];202}203204// Interpret CPU brand string if reported205if (nExIds_ >= 0x80000004)206{207memcpy(brand, extdata_[2].data(), sizeof(cpui));208memcpy(brand + 16, extdata_[3].data(), sizeof(cpui));209memcpy(brand + 32, extdata_[4].data(), sizeof(cpui));210brand_ = brand;211}212};213214int nIds_;215unsigned nExIds_;216std::string vendor_;217std::string brand_;218bool isIntel_;219bool isAMD_;220std::bitset<32> f_1_ECX_;221std::bitset<32> f_1_EDX_;222std::bitset<32> f_7_EBX_;223std::bitset<32> f_7_ECX_;224std::bitset<32> f_81_ECX_;225std::bitset<32> f_81_EDX_;226std::vector<std::array<int, 4>> data_;227std::vector<std::array<int, 4>> extdata_;228};229const InstructionSet_Internal CPU_Rep;230};231232233