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