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