blob: c997b7b9ca20610328ae1f9b3a901e8e6dd618a3 [file] [log] [blame]
Guillaume Chatelet439d3712018-02-01 10:03:09 +01001// Copyright 2017 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "cpuinfo_x86.h"
16#include "internal/bit_utils.h"
17#include "internal/cpuid_x86.h"
18
19#include <stdbool.h>
20#include <string.h>
21
Guillaume Chatelete8e56102019-01-15 10:52:56 +010022#if !defined(CPU_FEATURES_ARCH_X86)
23#error "Cannot compile cpuinfo_x86 on a non x86 platform."
24#endif
25
26////////////////////////////////////////////////////////////////////////////////
27// Definitions for CpuId and GetXCR0Eax.
28////////////////////////////////////////////////////////////////////////////////
29
30#if defined(CPU_FEATURES_MOCK_CPUID_X86)
31// Implementation will be provided by test/cpuinfo_x86_test.cc.
32#elif defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
33
34#include <cpuid.h>
35
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030036Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
Guillaume Chatelete8e56102019-01-15 10:52:56 +010037 Leaf leaf;
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030038 __cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
Guillaume Chatelete8e56102019-01-15 10:52:56 +010039 return leaf;
40}
41
42uint32_t GetXCR0Eax(void) {
43 uint32_t eax, edx;
natanbc084ec5c2019-03-20 06:04:24 -030044 /* named form of xgetbv not supported on OSX, so must use byte form, see:
45 https://github.com/asmjit/asmjit/issues/78
46 */
47 __asm(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
Guillaume Chatelete8e56102019-01-15 10:52:56 +010048 return eax;
49}
50
51#elif defined(CPU_FEATURES_COMPILER_MSC)
52
53#include <immintrin.h>
54#include <intrin.h> // For __cpuidex()
55
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030056Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
Guillaume Chatelete8e56102019-01-15 10:52:56 +010057 Leaf leaf;
58 int data[4];
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030059 __cpuidex(data, leaf_id, ecx);
Guillaume Chatelete8e56102019-01-15 10:52:56 +010060 leaf.eax = data[0];
61 leaf.ebx = data[1];
62 leaf.ecx = data[2];
63 leaf.edx = data[3];
64 return leaf;
65}
66
Leonard Mosescubdb36d92019-07-03 05:57:19 -070067uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
Guillaume Chatelete8e56102019-01-15 10:52:56 +010068
69#else
70#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC."
71#endif
72
Artem Alekseev653d5812019-07-02 17:52:25 +030073static Leaf CpuId(uint32_t leaf_id) { return CpuIdEx(leaf_id, 0); }
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030074
Guillaume Chatelet439d3712018-02-01 10:03:09 +010075static const Leaf kEmptyLeaf;
76
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030077static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) {
Guillaume Chatelet439d3712018-02-01 10:03:09 +010078 if (leaf_id <= max_cpuid_leaf) {
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030079 return CpuIdEx(leaf_id, ecx);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010080 } else {
81 return kEmptyLeaf;
82 }
83}
84
Artem Alekseevbfb4cf92019-06-21 15:13:29 +030085static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) {
86 return SafeCpuIdEx(max_cpuid_leaf, leaf_id, 0);
87}
88
Guillaume Chatelet439d3712018-02-01 10:03:09 +010089#define MASK_XMM 0x2
90#define MASK_YMM 0x4
91#define MASK_MASKREG 0x20
92#define MASK_ZMM0_15 0x40
93#define MASK_ZMM16_31 0x80
94
95static bool HasMask(uint32_t value, uint32_t mask) {
96 return (value & mask) == mask;
97}
98
99// Checks that operating system saves and restores xmm registers during context
100// switches.
101static bool HasXmmOsXSave(uint32_t xcr0_eax) {
102 return HasMask(xcr0_eax, MASK_XMM);
103}
104
105// Checks that operating system saves and restores ymm registers during context
106// switches.
107static bool HasYmmOsXSave(uint32_t xcr0_eax) {
108 return HasMask(xcr0_eax, MASK_XMM | MASK_YMM);
109}
110
111// Checks that operating system saves and restores zmm registers during context
112// switches.
113static bool HasZmmOsXSave(uint32_t xcr0_eax) {
114 return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
115 MASK_ZMM16_31);
116}
117
118static void SetVendor(const Leaf leaf, char* const vendor) {
119 *(uint32_t*)(vendor) = leaf.ebx;
120 *(uint32_t*)(vendor + 4) = leaf.edx;
121 *(uint32_t*)(vendor + 8) = leaf.ecx;
122 vendor[12] = '\0';
123}
124
125static int IsVendor(const Leaf leaf, const char* const name) {
126 const uint32_t ebx = *(const uint32_t*)(name);
127 const uint32_t edx = *(const uint32_t*)(name + 4);
128 const uint32_t ecx = *(const uint32_t*)(name + 8);
129 return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
130}
131
Artem Alekseev653d5812019-07-02 17:52:25 +0300132static const CacheLevelInfo kEmptyCacheLevelInfo;
133
134static CacheLevelInfo MakeX86CacheLevelInfo(int level, CacheType cache_type,
135 int cache_size, int ways,
136 int line_size, int entries,
137 int partitioning) {
138 CacheLevelInfo info;
139 info.level = level;
140 info.cache_type = cache_type;
141 info.cache_size = cache_size;
142 info.ways = ways;
143 info.line_size = line_size;
144 info.tlb_entries = entries;
145 info.partitioning = partitioning;
146 return info;
147}
148
149static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
150 const int UNDEF = -1;
151 const int KiB = 1024;
152 const int MiB = 1024 * KiB;
153 const int GiB = 1024 * MiB;
154 switch (reg) {
155 case 0x01:
156 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
157 UNDEF, 32, 0);
158 case 0x02:
159 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 0xFF,
160 UNDEF, 2, 0);
161 case 0x03:
162 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
163 UNDEF, 64, 0);
164 case 0x04:
165 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
166 UNDEF, 8, 0);
167 case 0x05:
168 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
169 UNDEF, 32, 0);
170 case 0x06:
171 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 8 * KiB, 4,
172 32, UNDEF, 0);
173 case 0x08:
174 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
175 4, 32, UNDEF, 0);
176 case 0x09:
177 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
178 4, 64, UNDEF, 0);
179 case 0x0A:
180 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 2, 32,
181 UNDEF, 0);
182 case 0x0B:
183 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
184 UNDEF, 4, 0);
185 case 0x0C:
186 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 32,
187 UNDEF, 0);
188 case 0x0D:
189 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
190 UNDEF, 0);
191 case 0x0E:
192 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 24 * KiB, 6, 64,
193 UNDEF, 0);
194 case 0x1D:
195 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 2, 64,
196 UNDEF, 0);
197 case 0x21:
198 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
199 UNDEF, 0);
200 case 0x22:
201 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
202 UNDEF, 2);
203 case 0x23:
204 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
205 UNDEF, 2);
206 case 0x24:
207 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 16, 64,
208 UNDEF, 0);
209 case 0x25:
210 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
211 UNDEF, 2);
212 case 0x29:
213 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
214 UNDEF, 2);
215 case 0x2C:
216 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 8, 64,
217 UNDEF, 0);
218 case 0x30:
219 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
220 8, 64, UNDEF, 0);
221 case 0x40:
222 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DATA, UNDEF, UNDEF,
223 UNDEF, UNDEF, 0);
224 case 0x41:
225 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 4, 32,
226 UNDEF, 0);
227 case 0x42:
228 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 4, 32,
229 UNDEF, 0);
230 case 0x43:
231 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
232 UNDEF, 0);
233 case 0x44:
234 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 32,
235 UNDEF, 0);
236 case 0x45:
237 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 32,
238 UNDEF, 0);
239 case 0x46:
240 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 4, 64,
241 UNDEF, 0);
242 case 0x47:
243 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 8, 64,
244 UNDEF, 0);
245 case 0x48:
246 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
247 UNDEF, 0);
248 case 0x49:
249 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
250 UNDEF, 0);
251 case (0x49 | (1 << 8)):
252 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
253 UNDEF, 0);
254 case 0x4A:
255 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
256 UNDEF, 0);
257 case 0x4B:
258 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
259 UNDEF, 0);
260 case 0x4C:
261 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 12, 64,
262 UNDEF, 0);
263 case 0x4D:
264 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 16 * MiB, 16, 64,
265 UNDEF, 0);
266 case 0x4E:
267 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 6 * MiB, 24, 64,
268 UNDEF, 0);
269 case 0x4F:
270 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
271 UNDEF, 32, 0);
272 case 0x50:
273 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
274 UNDEF, 64, 0);
275 case 0x51:
276 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
277 UNDEF, 128, 0);
278 case 0x52:
279 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
280 UNDEF, 256, 0);
281 case 0x55:
282 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
283 UNDEF, 7, 0);
284 case 0x56:
285 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
286 UNDEF, 16, 0);
287 case 0x57:
288 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
289 UNDEF, 16, 0);
290 case 0x59:
291 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
292 UNDEF, 16, 0);
293 case 0x5A:
294 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
295 UNDEF, 32, 0);
296 case 0x5B:
297 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
298 UNDEF, 64, 0);
299 case 0x5C:
300 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
301 UNDEF, 128, 0);
302 case 0x5D:
303 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4, UNDEF,
304 UNDEF, 256, 0);
305 case 0x60:
306 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 8, 64,
307 UNDEF, 0);
308 case 0x61:
309 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
310 UNDEF, 48, 0);
311 case 0x63:
312 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
313 UNDEF, 4, 0);
314 case 0x66:
315 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 4, 64,
316 UNDEF, 0);
317 case 0x67:
318 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
319 UNDEF, 0);
320 case 0x68:
321 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 4, 64,
322 UNDEF, 0);
323 case 0x70:
324 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 12 * KiB,
325 8, UNDEF, UNDEF, 0);
326 case 0x71:
327 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
328 8, UNDEF, UNDEF, 0);
329 case 0x72:
330 return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
331 8, UNDEF, UNDEF, 0);
332 case 0x76:
333 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
334 UNDEF, 8, 0);
335 case 0x78:
336 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
337 UNDEF, 0);
338 case 0x79:
339 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 8, 64,
340 UNDEF, 2);
341 case 0x7A:
342 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
343 UNDEF, 2);
344 case 0x7B:
345 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
346 UNDEF, 2);
347 case 0x7C:
348 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
349 UNDEF, 2);
350 case 0x7D:
351 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
352 UNDEF, 0);
353 case 0x7F:
354 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 2, 64,
355 UNDEF, 0);
356 case 0x80:
357 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
358 UNDEF, 0);
359 case 0x82:
360 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 32,
361 UNDEF, 0);
362 case 0x83:
363 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 32,
364 UNDEF, 0);
365 case 0x84:
366 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 32,
367 UNDEF, 0);
368 case 0x85:
369 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 32,
370 UNDEF, 0);
371 case 0x86:
372 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
373 UNDEF, 0);
374 case 0x87:
375 return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
376 UNDEF, 0);
377 case 0xA0:
378 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 0xFF,
379 UNDEF, 32, 0);
380 case 0xB0:
381 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
382 UNDEF, 128, 0);
383 case 0xB1:
384 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
385 UNDEF, 8, 0);
386 case 0xB2:
387 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
388 UNDEF, 64, 0);
389 case 0xB3:
390 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
391 UNDEF, 128, 0);
392 case 0xB4:
393 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
394 UNDEF, 256, 0);
395 case 0xB5:
396 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
397 UNDEF, 64, 0);
398 case 0xB6:
399 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
400 UNDEF, 128, 0);
401 case 0xBA:
402 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
403 UNDEF, 64, 0);
404 case 0xC0:
405 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
406 UNDEF, 8, 0);
407 case 0xC1:
408 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 8,
409 UNDEF, 1024, 0);
410 case 0xC2:
411 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 4,
412 UNDEF, 16, 0);
413 case 0xC3:
414 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 6,
415 UNDEF, 1536, 0);
416 case 0xCA:
417 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 4,
418 UNDEF, 512, 0);
419 case 0xD0:
420 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
421 UNDEF, 0);
422 case 0xD1:
423 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
424 UNDEF, 0);
425 case 0xD2:
426 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 64,
427 UNDEF, 0);
428 case 0xD6:
429 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
430 UNDEF, 0);
431 case 0xD7:
432 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
433 UNDEF, 0);
434 case 0xD8:
435 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
436 UNDEF, 0);
437 case 0xDC:
438 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * 1536 * KiB,
439 12, 64, UNDEF, 0);
440 case 0xDD:
441 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
442 UNDEF, 0);
443 case 0xDE:
444 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
445 UNDEF, 0);
446 case 0xE2:
447 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 16, 64,
448 UNDEF, 0);
449 case 0xE3:
450 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
451 UNDEF, 0);
452 case 0xE4:
453 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
454 UNDEF, 0);
455 case 0xEA:
456 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 24, 64,
457 UNDEF, 0);
458 case 0xEB:
459 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 18 * MiB, 24, 64,
460 UNDEF, 0);
461 case 0xEC:
462 return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 24 * MiB, 24, 64,
463 UNDEF, 0);
464 case 0xF0:
465 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 64 * KiB,
466 UNDEF, UNDEF, UNDEF, 0);
467 case 0xF1:
468 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 128 * KiB,
469 UNDEF, UNDEF, UNDEF, 0);
470 case 0xFF:
471 return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_NULL, UNDEF, UNDEF,
472 UNDEF, UNDEF, 0);
473 default:
474 return kEmptyCacheLevelInfo;
475 }
476}
477
478static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) {
479 for (int i = 0; i < 4; ++i) {
480 result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8);
481 }
482}
483
484static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
485 Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
486 uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
487 for (int i = 0; i < 4; ++i) {
488 if (registers[i] & (1 << 31)) {
489 continue; // register does not contains valid information
490 }
491 uint32_t bytes[4];
492 GetByteArrayFromRegister(bytes, registers[i]);
493 for (int i = 0; i < 4; ++i) {
494 if (bytes[i] == 0xFF)
495 break; // leaf 4 should be used to fetch cache information
496 info->levels[info->size] = GetCacheLevelInfo(bytes[i]);
497 }
498 info->size++;
499 }
500}
501
502static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
503 info->size = 0;
504 for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) {
505 const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id);
506 CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
507 if (cache_type == CPU_FEATURE_CACHE_NULL) {
508 info->levels[cache_id] = kEmptyCacheLevelInfo;
509 continue;
510 }
511 int level = ExtractBitRange(leaf.eax, 7, 5);
512 int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
513 int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
514 int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
515 int entries = leaf.ecx + 1;
516 int cache_size = (ways * partitioning * line_size * (entries));
517 info->levels[cache_id] = MakeX86CacheLevelInfo(
518 level, cache_type, cache_size, ways, line_size, entries, partitioning);
519 info->size++;
520 }
521}
522
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100523// Reference https://en.wikipedia.org/wiki/CPUID.
524static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info) {
525 const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
526 const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
527
528 const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
529 const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
530 const uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0;
531 const bool have_sse_os_support = HasXmmOsXSave(xcr0_eax);
532 const bool have_avx_os_support = HasYmmOsXSave(xcr0_eax);
533 const bool have_avx512_os_support = HasZmmOsXSave(xcr0_eax);
534
535 const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
536 const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
537 const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4);
538 const uint32_t extended_model = ExtractBitRange(leaf_1.eax, 19, 16);
539
540 X86Features* const features = &info->features;
541
542 info->family = extended_family + family;
543 info->model = (extended_model << 4) + model;
544 info->stepping = ExtractBitRange(leaf_1.eax, 3, 0);
545
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200546 features->fpu = IsBitSet(leaf_1.edx, 0);
547 features->tsc = IsBitSet(leaf_1.edx, 4);
548 features->cx8 = IsBitSet(leaf_1.edx, 8);
549 features->clfsh = IsBitSet(leaf_1.edx, 19);
550 features->mmx = IsBitSet(leaf_1.edx, 23);
Artem Alekseev3ee4a9e2019-06-19 16:06:05 +0300551 features->ss = IsBitSet(leaf_1.edx, 27);
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200552 features->pclmulqdq = IsBitSet(leaf_1.ecx, 1);
Patrik Fiedler0f1f3ac2018-02-13 11:44:40 +0100553 features->smx = IsBitSet(leaf_1.ecx, 6);
Guillaume Chatelet9b872ce2018-03-13 10:58:42 +0100554 features->cx16 = IsBitSet(leaf_1.ecx, 13);
Artem Alekseev3ee4a9e2019-06-19 16:06:05 +0300555 features->dca = IsBitSet(leaf_1.ecx, 18);
Guillaume Chateletd395dfa2019-01-22 13:19:42 +0100556 features->movbe = IsBitSet(leaf_1.ecx, 22);
557 features->popcnt = IsBitSet(leaf_1.ecx, 23);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100558 features->aes = IsBitSet(leaf_1.ecx, 25);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100559 features->f16c = IsBitSet(leaf_1.ecx, 29);
Guillaume Chateletd395dfa2019-01-22 13:19:42 +0100560 features->rdrnd = IsBitSet(leaf_1.ecx, 30);
Patrik Fiedler0f1f3ac2018-02-13 11:44:40 +0100561 features->sgx = IsBitSet(leaf_7.ebx, 2);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100562 features->bmi1 = IsBitSet(leaf_7.ebx, 3);
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200563 features->hle = IsBitSet(leaf_7.ebx, 4);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100564 features->bmi2 = IsBitSet(leaf_7.ebx, 8);
Patrik Fiedler0f1f3ac2018-02-13 11:44:40 +0100565 features->erms = IsBitSet(leaf_7.ebx, 9);
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200566 features->rtm = IsBitSet(leaf_7.ebx, 11);
567 features->rdseed = IsBitSet(leaf_7.ebx, 18);
568 features->clflushopt = IsBitSet(leaf_7.ebx, 23);
569 features->clwb = IsBitSet(leaf_7.ebx, 24);
Guillaume Chateletd395dfa2019-01-22 13:19:42 +0100570 features->sha = IsBitSet(leaf_7.ebx, 29);
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200571 features->vaes = IsBitSet(leaf_7.ecx, 9);
Guillaume Chatelet11e3e202018-02-09 08:55:11 +0100572 features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100573
574 if (have_sse_os_support) {
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200575 features->sse = IsBitSet(leaf_1.edx, 25);
576 features->sse2 = IsBitSet(leaf_1.edx, 26);
577 features->sse3 = IsBitSet(leaf_1.ecx, 0);
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100578 features->ssse3 = IsBitSet(leaf_1.ecx, 9);
579 features->sse4_1 = IsBitSet(leaf_1.ecx, 19);
580 features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
581 }
582
583 if (have_avx_os_support) {
584 features->fma3 = IsBitSet(leaf_1.ecx, 12);
585 features->avx = IsBitSet(leaf_1.ecx, 28);
586 features->avx2 = IsBitSet(leaf_7.ebx, 5);
587 }
588
589 if (have_avx512_os_support) {
590 features->avx512f = IsBitSet(leaf_7.ebx, 16);
591 features->avx512cd = IsBitSet(leaf_7.ebx, 28);
592 features->avx512er = IsBitSet(leaf_7.ebx, 27);
593 features->avx512pf = IsBitSet(leaf_7.ebx, 26);
594 features->avx512bw = IsBitSet(leaf_7.ebx, 30);
595 features->avx512dq = IsBitSet(leaf_7.ebx, 17);
596 features->avx512vl = IsBitSet(leaf_7.ebx, 31);
597 features->avx512ifma = IsBitSet(leaf_7.ebx, 21);
598 features->avx512vbmi = IsBitSet(leaf_7.ecx, 1);
599 features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6);
600 features->avx512vnni = IsBitSet(leaf_7.ecx, 11);
601 features->avx512bitalg = IsBitSet(leaf_7.ecx, 12);
602 features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
603 features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
604 features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
605 }
606}
607
608static const X86Info kEmptyX86Info;
Artem Alekseev653d5812019-07-02 17:52:25 +0300609static const CacheInfo kEmptyCacheInfo;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100610
611X86Info GetX86Info(void) {
612 X86Info info = kEmptyX86Info;
613 const Leaf leaf_0 = CpuId(0);
614 const uint32_t max_cpuid_leaf = leaf_0.eax;
615 SetVendor(leaf_0, info.vendor);
616 if (IsVendor(leaf_0, "GenuineIntel") || IsVendor(leaf_0, "AuthenticAMD")) {
617 ParseCpuId(max_cpuid_leaf, &info);
618 }
619 return info;
620}
621
Artem Alekseev653d5812019-07-02 17:52:25 +0300622CacheInfo GetX86CacheInfo(void) {
623 CacheInfo info = kEmptyCacheInfo;
624 const Leaf leaf_0 = CpuId(0);
625 const uint32_t max_cpuid_leaf = leaf_0.eax;
626 if (IsVendor(leaf_0, "GenuineIntel")) {
627 ParseLeaf2(max_cpuid_leaf, &info);
628 ParseLeaf4(max_cpuid_leaf, &info);
629 }
630 return info;
631}
632
Guillaume Chateletdfdac6a2019-01-17 18:00:21 +0100633#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF))
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100634
635X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
636 if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) {
637 switch (CPUID(info->family, info->model)) {
638 case CPUID(0x06, 0x35):
639 case CPUID(0x06, 0x36):
640 // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture)
641 return INTEL_ATOM_BNL;
642 case CPUID(0x06, 0x37):
643 case CPUID(0x06, 0x4C):
644 // https://en.wikipedia.org/wiki/Silvermont
645 return INTEL_ATOM_SMT;
646 case CPUID(0x06, 0x5C):
647 // https://en.wikipedia.org/wiki/Goldmont
648 return INTEL_ATOM_GMT;
649 case CPUID(0x06, 0x0F):
650 case CPUID(0x06, 0x16):
651 // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture)
652 return INTEL_CORE;
653 case CPUID(0x06, 0x17):
654 case CPUID(0x06, 0x1D):
655 // https://en.wikipedia.org/wiki/Penryn_(microarchitecture)
656 return INTEL_PNR;
657 case CPUID(0x06, 0x1A):
658 case CPUID(0x06, 0x1E):
659 case CPUID(0x06, 0x1F):
660 case CPUID(0x06, 0x2E):
661 // https://en.wikipedia.org/wiki/Nehalem_(microarchitecture)
662 return INTEL_NHM;
663 case CPUID(0x06, 0x25):
664 case CPUID(0x06, 0x2C):
665 case CPUID(0x06, 0x2F):
666 // https://en.wikipedia.org/wiki/Westmere_(microarchitecture)
667 return INTEL_WSM;
668 case CPUID(0x06, 0x2A):
669 case CPUID(0x06, 0x2D):
670 // https://en.wikipedia.org/wiki/Sandy_Bridge#Models_and_steppings
671 return INTEL_SNB;
672 case CPUID(0x06, 0x3A):
673 case CPUID(0x06, 0x3E):
674 // https://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)#Models_and_steppings
675 return INTEL_IVB;
676 case CPUID(0x06, 0x3C):
677 case CPUID(0x06, 0x3F):
678 case CPUID(0x06, 0x45):
679 case CPUID(0x06, 0x46):
680 // https://en.wikipedia.org/wiki/Haswell_(microarchitecture)
681 return INTEL_HSW;
682 case CPUID(0x06, 0x3D):
683 case CPUID(0x06, 0x47):
684 case CPUID(0x06, 0x4F):
685 case CPUID(0x06, 0x56):
686 // https://en.wikipedia.org/wiki/Broadwell_(microarchitecture)
687 return INTEL_BDW;
688 case CPUID(0x06, 0x4E):
689 case CPUID(0x06, 0x55):
690 case CPUID(0x06, 0x5E):
691 // https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
692 return INTEL_SKL;
693 case CPUID(0x06, 0x8E):
694 case CPUID(0x06, 0x9E):
695 // https://en.wikipedia.org/wiki/Kaby_Lake
696 return INTEL_KBL;
697 default:
698 return X86_UNKNOWN;
699 }
700 }
701 if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) {
702 switch (info->family) {
703 // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
704 case 0x0F:
705 return AMD_HAMMER;
706 case 0x10:
707 return AMD_K10;
708 case 0x14:
709 return AMD_BOBCAT;
710 case 0x15:
711 return AMD_BULLDOZER;
712 case 0x16:
713 return AMD_JAGUAR;
714 case 0x17:
715 return AMD_ZEN;
716 default:
717 return X86_UNKNOWN;
718 }
719 }
720 return X86_UNKNOWN;
721}
722
723static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id,
724 char* buffer) {
725 const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id);
726 // We allow calling memcpy from SetString which is only called when requesting
727 // X86BrandString.
728 memcpy(buffer, &leaf, sizeof(Leaf));
729}
730
731void FillX86BrandString(char brand_string[49]) {
732 const Leaf leaf_ext_0 = CpuId(0x80000000);
733 const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax;
734 SetString(max_cpuid_leaf_ext, 0x80000002, brand_string);
735 SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16);
736 SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32);
737 brand_string[48] = '\0';
738}
739
740////////////////////////////////////////////////////////////////////////////////
741// Introspection functions
742
743int GetX86FeaturesEnumValue(const X86Features* features,
744 X86FeaturesEnum value) {
745 switch (value) {
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200746 case X86_FPU:
747 return features->fpu;
748 case X86_TSC:
749 return features->tsc;
750 case X86_CX8:
751 return features->cx8;
752 case X86_CLFSH:
753 return features->clfsh;
754 case X86_MMX:
755 return features->mmx;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100756 case X86_AES:
757 return features->aes;
758 case X86_ERMS:
759 return features->erms;
760 case X86_F16C:
761 return features->f16c;
762 case X86_FMA3:
763 return features->fma3;
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200764 case X86_VAES:
765 return features->vaes;
Guillaume Chatelet11e3e202018-02-09 08:55:11 +0100766 case X86_VPCLMULQDQ:
767 return features->vpclmulqdq;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100768 case X86_BMI1:
769 return features->bmi1;
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200770 case X86_HLE:
771 return features->hle;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100772 case X86_BMI2:
773 return features->bmi2;
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200774 case X86_RTM:
775 return features->rtm;
776 case X86_RDSEED:
777 return features->rdseed;
778 case X86_CLFLUSHOPT:
779 return features->clflushopt;
780 case X86_CLWB:
781 return features->clwb;
782 case X86_SSE:
783 return features->sse;
784 case X86_SSE2:
785 return features->sse2;
786 case X86_SSE3:
787 return features->sse3;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100788 case X86_SSSE3:
789 return features->ssse3;
790 case X86_SSE4_1:
791 return features->sse4_1;
792 case X86_SSE4_2:
793 return features->sse4_2;
794 case X86_AVX:
795 return features->avx;
796 case X86_AVX2:
797 return features->avx2;
798 case X86_AVX512F:
799 return features->avx512f;
800 case X86_AVX512CD:
801 return features->avx512cd;
802 case X86_AVX512ER:
803 return features->avx512er;
804 case X86_AVX512PF:
805 return features->avx512pf;
806 case X86_AVX512BW:
807 return features->avx512bw;
808 case X86_AVX512DQ:
809 return features->avx512dq;
810 case X86_AVX512VL:
811 return features->avx512vl;
812 case X86_AVX512IFMA:
813 return features->avx512ifma;
814 case X86_AVX512VBMI:
815 return features->avx512vbmi;
816 case X86_AVX512VBMI2:
817 return features->avx512vbmi2;
818 case X86_AVX512VNNI:
819 return features->avx512vnni;
820 case X86_AVX512BITALG:
821 return features->avx512bitalg;
822 case X86_AVX512VPOPCNTDQ:
823 return features->avx512vpopcntdq;
824 case X86_AVX512_4VNNIW:
825 return features->avx512_4vnniw;
826 case X86_AVX512_4VBMI2:
827 return features->avx512_4vbmi2;
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200828 case X86_PCLMULQDQ:
829 return features->pclmulqdq;
Patrik Fiedler3ee0d622018-02-13 11:14:32 +0100830 case X86_SMX:
831 return features->smx;
832 case X86_SGX:
833 return features->sgx;
Guillaume Chatelet9b872ce2018-03-13 10:58:42 +0100834 case X86_CX16:
835 return features->cx16;
Guillaume Chateletd395dfa2019-01-22 13:19:42 +0100836 case X86_SHA:
837 return features->sha;
838 case X86_POPCNT:
839 return features->popcnt;
840 case X86_MOVBE:
841 return features->movbe;
842 case X86_RDRND:
843 return features->rdrnd;
Artem Alekseev3ee4a9e2019-06-19 16:06:05 +0300844 case X86_DCA:
845 return features->dca;
846 case X86_SS:
847 return features->ss;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100848 case X86_LAST_:
849 break;
850 }
851 return false;
852}
853
854const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
855 switch (value) {
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200856 case X86_FPU:
857 return "fpu";
858 case X86_TSC:
859 return "tsc";
860 case X86_CX8:
861 return "cx8";
862 case X86_CLFSH:
863 return "clfsh";
864 case X86_MMX:
865 return "mmx";
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100866 case X86_AES:
867 return "aes";
868 case X86_ERMS:
869 return "erms";
870 case X86_F16C:
871 return "f16c";
872 case X86_FMA3:
873 return "fma3";
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200874 case X86_VAES:
875 return "vaes";
Guillaume Chatelet11e3e202018-02-09 08:55:11 +0100876 case X86_VPCLMULQDQ:
877 return "vpclmulqdq";
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100878 case X86_BMI1:
879 return "bmi1";
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200880 case X86_HLE:
881 return "hle";
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100882 case X86_BMI2:
883 return "bmi2";
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200884 case X86_RTM:
885 return "rtm";
886 case X86_RDSEED:
887 return "rdseed";
888 case X86_CLFLUSHOPT:
889 return "clflushopt";
890 case X86_CLWB:
891 return "clwb";
892 case X86_SSE:
893 return "sse";
894 case X86_SSE2:
895 return "sse2";
896 case X86_SSE3:
897 return "sse3";
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100898 case X86_SSSE3:
899 return "ssse3";
900 case X86_SSE4_1:
901 return "sse4_1";
902 case X86_SSE4_2:
903 return "sse4_2";
904 case X86_AVX:
905 return "avx";
906 case X86_AVX2:
907 return "avx2";
908 case X86_AVX512F:
909 return "avx512f";
910 case X86_AVX512CD:
911 return "avx512cd";
912 case X86_AVX512ER:
913 return "avx512er";
914 case X86_AVX512PF:
915 return "avx512pf";
916 case X86_AVX512BW:
917 return "avx512bw";
918 case X86_AVX512DQ:
919 return "avx512dq";
920 case X86_AVX512VL:
921 return "avx512vl";
922 case X86_AVX512IFMA:
923 return "avx512ifma";
924 case X86_AVX512VBMI:
925 return "avx512vbmi";
926 case X86_AVX512VBMI2:
927 return "avx512vbmi2";
928 case X86_AVX512VNNI:
929 return "avx512vnni";
930 case X86_AVX512BITALG:
931 return "avx512bitalg";
932 case X86_AVX512VPOPCNTDQ:
933 return "avx512vpopcntdq";
934 case X86_AVX512_4VNNIW:
935 return "avx512_4vnniw";
936 case X86_AVX512_4VBMI2:
937 return "avx512_4vbmi2";
Dr.-Ing. Patrick Siegl367bc422019-06-13 11:53:39 +0200938 case X86_PCLMULQDQ:
939 return "pclmulqdq";
Patrik Fiedler3ee0d622018-02-13 11:14:32 +0100940 case X86_SMX:
941 return "smx";
942 case X86_SGX:
943 return "sgx";
Guillaume Chatelet9b872ce2018-03-13 10:58:42 +0100944 case X86_CX16:
945 return "cx16";
Guillaume Chateletd395dfa2019-01-22 13:19:42 +0100946 case X86_SHA:
947 return "sha";
948 case X86_POPCNT:
949 return "popcnt";
950 case X86_MOVBE:
951 return "movbe";
952 case X86_RDRND:
953 return "rdrnd";
Artem Alekseev3ee4a9e2019-06-19 16:06:05 +0300954 case X86_DCA:
955 return "dca";
956 case X86_SS:
957 return "ss";
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100958 case X86_LAST_:
959 break;
960 }
961 return "unknown_feature";
962}
963
964const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
965 switch (uarch) {
966 case X86_UNKNOWN:
967 return "X86_UNKNOWN";
968 case INTEL_CORE:
969 return "INTEL_CORE";
970 case INTEL_PNR:
971 return "INTEL_PNR";
972 case INTEL_NHM:
973 return "INTEL_NHM";
974 case INTEL_ATOM_BNL:
975 return "INTEL_ATOM_BNL";
976 case INTEL_WSM:
977 return "INTEL_WSM";
978 case INTEL_SNB:
979 return "INTEL_SNB";
980 case INTEL_IVB:
981 return "INTEL_IVB";
982 case INTEL_ATOM_SMT:
983 return "INTEL_ATOM_SMT";
984 case INTEL_HSW:
985 return "INTEL_HSW";
986 case INTEL_BDW:
987 return "INTEL_BDW";
988 case INTEL_SKL:
989 return "INTEL_SKL";
990 case INTEL_ATOM_GMT:
991 return "INTEL_ATOM_GMT";
992 case INTEL_KBL:
993 return "INTEL_KBL";
994 case INTEL_CFL:
995 return "INTEL_CFL";
996 case INTEL_CNL:
997 return "INTEL_CNL";
998 case AMD_HAMMER:
999 return "AMD_HAMMER";
1000 case AMD_K10:
1001 return "AMD_K10";
1002 case AMD_BOBCAT:
1003 return "AMD_BOBCAT";
1004 case AMD_BULLDOZER:
1005 return "AMD_BULLDOZER";
1006 case AMD_JAGUAR:
1007 return "AMD_JAGUAR";
1008 case AMD_ZEN:
1009 return "AMD_ZEN";
1010 }
1011 return "unknown microarchitecture";
1012}