HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
cpu_id.hpp
1// Copyright Take Vos 2019, 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "architecture.hpp"
8#include "cast.hpp"
9#include <array>
10
11#if HI_COMPILER == HI_CC_MSVC
12#include <intrin.h>
13#elif HI_COMPILER == HI_CC_GCC || HI_COMPILER == HI_CC_CLANG
14#include <cpuid.h>
15#else
16#error "Unsuported compiler for x64 cpu_id"
17#endif
18
19namespace hi {
20inline namespace v1 {
21
22class cpu_id {
23public:
24 constexpr static uint32_t processor_type_OEM = 0;
25 constexpr static uint32_t processor_type_Intel_overdrive = 1;
26 constexpr static uint32_t processor_type_dual_processor = 2;
27
28 std::string vendor_id = {};
29 std::string brand_name = {};
30
31 uint32_t stepping_id:4 = 0;
32 uint32_t model_id:8 = 0;
33 uint32_t family_id:9 = 0;
34 uint32_t processor_type:2 = 0;
35
36 uint64_t features = 0;
37
38
39 size_t cache_flush_size = 0;
40
43 uint8_t APIC_id = 0;
44
45 cpu_id(cpu_id const &) noexcept = default;
46 cpu_id(cpu_id &&) noexcept = default;
47 cpu_id &operator=(cpu_id const &) noexcept = default;
48 cpu_id &operator=(cpu_id &&) noexcept = default;
49
50 cpu_id() noexcept
51 {
52 hilet leaf0 = get_leaf(0);
53 hilet max_leaf = leaf0.a;
54
55 // vendor_id are 12 characters from ebx, edx, ecx in that order.
56 vendor_id.resize(12);
57 std::memcpy(vendor_id.data() + 0, leaf0.b, 4);
58 std::memcpy(vendor_id.data() + 4, leaf0.d, 4);
59 std::memcpy(vendor_id.data() + 8, leaf0.c, 4);
60
61 size_t brand_index = 0;
62 if (max_leaf >= 1) {
63 hilet leaf1 = get_leaf(1);
64
65 stepping_id = leaf1.a & 0xf;
66 model_id = (leaf1.a >> 4) & 0xf;
67 family_id = (leaf1.a >> 8) & 0xf;
68 processor_type = (leaf1.a >> 12) & 0x3;
69
70 if (family_id == 0x6 or family_id == 0xf) {
71 // Extended model is concatenated.
72 model_id |= ((leaf1.a >> 16) & 0xf) << 4;
73 }
74 if (family_id == 0xf) {
75 // Extended family is simply added.
76 family_id += (leaf1.a >> 20) & 0xff;
77 }
78
79 brand_index = leaf1.b & 0xff;
80 cache_flush_size = ((leaf1.b >> 8) & 0xff) * 8;
81 APIC_id = (leaf1.b >> 24) & 0xff;
82
83
84
85 }
86 }
87
88
89 [[nodiscard]] bool has_aesni() const noexcept
90 {
91 return to_bool(instruction_set & instruction_set_aesni);
92 }
93
94 [[nodiscard]] bool has_avx() const noexcept
95 {
96 return to_bool(instruction_set & instruction_set_avx);
97 }
98
99 [[nodiscard]] bool has_cmpxchg16b() const noexcept
100 {
101 return to_bool(instruction_set & instruction_set_cmpxchg16b);
102 }
103
104 [[nodiscard]] bool has_clfsh() const noexcept
105 {
106 return to_bool(instruction_set & instruction_set_clfsh);
107 }
108
109 [[nodiscard]] bool has_cmov() const noexcept
110 {
111 return to_bool(instruction_set & instruction_set_cmov);
112 }
113
114 [[nodiscard]] bool has_cx8() const noexcept
115 {
116 return to_bool(instruction_set & instruction_set_cx8);
117 }
118
119 [[nodiscard]] bool has_fma() const noexcept
120 {
121 return to_bool(instruction_set & instruction_set_fma);
122 }
123
124 [[nodiscard]] bool has_f16c() const noexcept
125 {
126 return to_bool(instruction_set & instruction_set_f16c);
127 }
128
129 [[nodiscard]] bool has_fxsr() const noexcept
130 {
131 return to_bool(instruction_set & instruction_set_fxsr);
132 }
133
134 [[nodiscard]] bool has_sse() const noexcept
135 {
136 return to_bool(instruction_set & instruction_set_sse);
137 }
138
139 [[nodiscard]] bool has_sse2() const noexcept
140 {
141 return to_bool(instruction_set & instruction_set_sse2);
142 }
143
144 [[nodiscard]] bool has_sse3() const noexcept
145 {
146 return to_bool(instruction_set & instruction_set_sse3);
147 }
148
149 [[nodiscard]] bool has_ssse3() const noexcept
150 {
151 return to_bool(instruction_set & instruction_set_ssse3);
152 }
153
154 [[nodiscard]] bool has_sse4_1() const noexcept
155 {
156 return to_bool(instruction_set & instruction_set_sse4_1);
157 }
158
159 [[nodiscard]] bool has_sse4_2() const noexcept
160 {
161 return to_bool(instruction_set & instruction_set_sse4_2);
162 }
163
164 [[nodiscard]] bool has_movbe() const noexcept
165 {
166 return to_bool(instruction_set & instruction_set_movbe);
167 }
168
169 [[nodiscard]] bool has_mmx() const noexcept
170 {
171 return to_bool(instruction_set & instruction_set_mmx);
172 }
173
174 [[nodiscard]] bool has_msr() const noexcept
175 {
176 return to_bool(instruction_set & instruction_set_msr);
177 }
178
179 [[nodiscard]] bool has_osxsave() const noexcept
180 {
181 return to_bool(instruction_set & instruction_set_osxsave);
182 }
183
184 [[nodiscard]] bool has_pclmulqdq() const noexcept
185 {
186 return to_bool(instruction_set & instruction_set_pclmulqdq);
187 }
188
189 [[nodiscard]] bool has_popcnt() const noexcept
190 {
191 return to_bool(instruction_set & instruction_set_popcnt);
192 }
193
194 [[nodiscard]] bool has_rdrand() const noexcept
195 {
196 return to_bool(instruction_set & instruction_set_rdrand);
197 }
198
199 [[nodiscard]] bool has_sep() const noexcept
200 {
201 return to_bool(instruction_set & instruction_set_sep);
202 }
203
204 [[nodiscard]] bool has_tsc() const noexcept
205 {
206 return to_bool(instruction_set & instruction_set_tsc);
207 }
208
209 [[nodiscard]] bool has_xsave() const noexcept
210 {
211 return to_bool(instruction_set & instruction_set_xsave);
212 }
213
214 [[nodiscard]] bool has_acpi() const noexcept
215 {
216 return to_bool(features & features_acpi);
217 }
218
219 [[nodiscard]] bool has_apic() const noexcept
220 {
221 return to_bool(features & features_apic);
222 }
223
224 [[nodiscard]] bool has_cnxt_id() const noexcept
225 {
226 return to_bool(features & features_cnxt_id);
227 }
228
229 [[nodiscard]] bool has_dca() const noexcept
230 {
231 return to_bool(features & features_dca);
232 }
233
234 [[nodiscard]] bool has_de() const noexcept
235 {
236 return to_bool(features & features_de);
237 }
238
239 [[nodiscard]] bool has_ds() const noexcept
240 {
241 return to_bool(features & features_ds);
242 }
243
244 [[nodiscard]] bool has_ds_cpl() const noexcept
245 {
246 return to_bool(features & features_ds_cpl);
247 }
248
249 [[nodiscard]] bool has_dtes64() const noexcept
250 {
251 return to_bool(features & features_dtes64);
252 }
253
254 [[nodiscard]] bool has_eist() const noexcept
255 {
256 return to_bool(features & features_eist);
257 }
258
259 [[nodiscard]] bool has_fpu() const noexcept
260 {
261 return to_bool(features & features_fpu);
262 }
263
264 [[nodiscard]] bool has_htt() const noexcept
265 {
266 return to_bool(features & features_htt);
267 }
268
269 [[nodiscard]] bool has_mca() const noexcept
270 {
271 return to_bool(features & features_mca);
272 }
273
274 [[nodiscard]] bool has_mce() const noexcept
275 {
276 return to_bool(features & features_mce);
277 }
278
279 [[nodiscard]] bool has_monitor() const noexcept
280 {
281 return to_bool(features & features_monitor);
282 }
283
284 [[nodiscard]] bool has_mttr() const noexcept
285 {
286 return to_bool(features & features_mttr);
287 }
288
289 [[nodiscard]] bool has_pae() const noexcept
290 {
291 return to_bool(features & features_pae);
292 }
293
294 [[nodiscard]] bool has_pat() const noexcept
295 {
296 return to_bool(features & features_pat);
297 }
298
299 [[nodiscard]] bool has_pbe() const noexcept
300 {
301 return to_bool(features & features_pbe);
302 }
303
304 [[nodiscard]] bool has_pcid() const noexcept
305 {
306 return to_bool(features & features_pcid);
307 }
308
309 [[nodiscard]] bool has_pdcm() const noexcept
310 {
311 return to_bool(features & features_pdcm);
312 }
313
314 [[nodiscard]] bool has_pge() const noexcept
315 {
316 return to_bool(features & features_pge);
317 }
318
319 [[nodiscard]] bool has_pse() const noexcept
320 {
321 return to_bool(features & features_pse);
322 }
323
324 [[nodiscard]] bool has_pse_36() const noexcept
325 {
326 return to_bool(features & features_pse_36);
327 }
328
329 [[nodiscard]] bool has_psn() const noexcept
330 {
331 return to_bool(features & features_psm);
332 }
333
334 [[nodiscard]] bool has_sdbg() const noexcept
335 {
336 return to_bool(features & features_sdbg);
337 }
338
339 [[nodiscard]] bool has_smx() const noexcept
340 {
341 return to_bool(features & features_smx);
342 }
343
344 [[nodiscard]] bool has_ss() const noexcept
345 {
346 return to_bool(features & features_ss);
347 }
348
349 [[nodiscard]] bool has_tm() const noexcept
350 {
351 return to_bool(features & features_tm);
352 }
353
354 [[nodiscard]] bool has_tm2() const noexcept
355 {
356 return to_bool(features & features_tm2);
357 }
358
359 [[nodiscard]] bool has_tsc_deadline() const noexcept
360 {
361 return to_bool(features & features_tsc_deadline);
362 }
363
364 [[nodiscard]] bool has_vme() const noexcept
365 {
366 return to_bool(features & features_vme);
367 }
368
369 [[nodiscard]] bool has_vmx() const noexcept
370 {
371 return to_bool(features & features_vmx);
372 }
373
374 [[nodiscard]] bool has_x2apic() const noexcept
375 {
376 return to_bool(features & features_x2apic);
377 }
378
379 [[nodiscard]] bool has_xtpr() const noexcept
380 {
381 return to_bool(features & features_xtpr);
382 }
383
384private:
385 // clang-format off
386 constexpr static uint64_t instruction_set_aesni = 0x0000'0000'0000'0001;
387 constexpr static uint64_t instruction_set_avx = 0x0000'0000'0000'0002;
388 constexpr static uint64_t instruction_set_cmpxchg16b = 0x0000'0000'0000'0004;
389 constexpr static uint64_t instruction_set_clfsh = 0x0000'0000'0000'0008;
390 constexpr static uint64_t instruction_set_cmov = 0x0000'0000'0000'0010;
391 constexpr static uint64_t instruction_set_cx8 = 0x0000'0000'0000'0020;
392 constexpr static uint64_t instruction_set_fma = 0x0000'0000'0000'0040;
393 constexpr static uint64_t instruction_set_f16c = 0x0000'0000'0000'0080;
394 constexpr static uint64_t instruction_set_fxsr = 0x0000'0000'0000'0100;
395 constexpr static uint64_t instruction_set_sse = 0x0000'0000'0000'0200;
396 constexpr static uint64_t instruction_set_sse2 = 0x0000'0000'0000'0300;
397 constexpr static uint64_t instruction_set_sse3 = 0x0000'0000'0000'0800;
398 constexpr static uint64_t instruction_set_ssse3 = 0x0000'0000'0000'1000;
399 constexpr static uint64_t instruction_set_sse4_1 = 0x0000'0000'0000'2000;
400 constexpr static uint64_t instruction_set_sse4_2 = 0x0000'0000'0000'4000;
401 constexpr static uint64_t instruction_set_movbe = 0x0000'0000'0000'8000;
402 constexpr static uint64_t instruction_set_mmx = 0x0000'0000'0001'0000;
403 constexpr static uint64_t instruction_set_msr = 0x0000'0000'0002'0000;
404 constexpr static uint64_t instruction_set_osxsave = 0x0000'0000'0004'0000;
405 constexpr static uint64_t instruction_set_pclmulqdq = 0x0000'0000'0008'0000;
406 constexpr static uint64_t instruction_set_popcnt = 0x0000'0000'0010'0000;
407 constexpr static uint64_t instruction_set_rdrand = 0x0000'0000'0020'0000;
408 constexpr static uint64_t instruction_set_sep = 0x0000'0000'0040'0000;
409 constexpr static uint64_t instruction_set_tsc = 0x0000'0000'0080'0000;
410 constexpr static uint64_t instruction_set_xsave = 0x0000'0000'0100'0000;
411
412 constexpr static uint64_t features_acpi = 0x0000'0000'0000'0001;
413 constexpr static uint64_t features_apic = 0x0000'0000'0000'0002;
414 constexpr static uint64_t features_cnxt_id = 0x0000'0000'0000'0004;
415 constexpr static uint64_t features_dca = 0x0000'0000'0000'0008;
416 constexpr static uint64_t features_de = 0x0000'0000'0000'0010;
417 constexpr static uint64_t features_ds = 0x0000'0000'0000'0020;
418 constexpr static uint64_t features_ds_cpl = 0x0000'0000'0000'0040;
419 constexpr static uint64_t features_dtes64 = 0x0000'0000'0000'0080;
420 constexpr static uint64_t features_eist = 0x0000'0000'0000'0100;
421 constexpr static uint64_t features_fpu = 0x0000'0000'0000'0200;
422 constexpr static uint64_t features_htt = 0x0000'0000'0000'0400;
423 constexpr static uint64_t features_mca = 0x0000'0000'0000'0800;
424 constexpr static uint64_t features_mce = 0x0000'0000'0000'1000;
425 constexpr static uint64_t features_monitor = 0x0000'0000'0000'2000;
426 constexpr static uint64_t features_mttr = 0x0000'0000'0000'4000;
427 constexpr static uint64_t features_pae = 0x0000'0000'0000'8000;
428 constexpr static uint64_t features_pat = 0x0000'0000'0001'0000;
429 constexpr static uint64_t features_pbe = 0x0000'0000'0002'0000;
430 constexpr static uint64_t features_pcid = 0x0000'0000'0004'0000;
431 constexpr static uint64_t features_pdcm = 0x0000'0000'0008'0000;
432 constexpr static uint64_t features_pge = 0x0000'0000'0010'0000;
433 constexpr static uint64_t features_pse = 0x0000'0000'0020'0000;
434 constexpr static uint64_t features_pse_36 = 0x0000'0000'0040'0000;
435 constexpr static uint64_t features_psn = 0x0000'0000'0080'0000;
436 constexpr static uint64_t features_sdbg = 0x0000'0000'0100'0000;
437 constexpr static uint64_t features_smx = 0x0000'0000'0200'0000;
438 constexpr static uint64_t features_ss = 0x0000'0000'0400'0000;
439 constexpr static uint64_t features_tm = 0x0000'0000'0800'0000;
440 constexpr static uint64_t features_tm2 = 0x0000'0000'1000'0000;
441 constexpr static uint64_t features_tsc_deadline = 0x0000'0000'2000'0000;
442 constexpr static uint64_t features_vme = 0x0000'0000'4000'0000;
443 constexpr static uint64_t features_vmx = 0x0000'0000'8000'0000;
444 constexpr static uint64_t features_x2apic = 0x0000'0001'0000'0000;
445 constexpr static uint64_t features_xtpr = 0x0000'0002'0000'0000;
446 // clang-format off
447
448 uint32_t instruction_set = 0;
449 uint64_t features = 0;
450
451 struct leaf_type {
452 uint32_t a; // EAX
453 uint32_t b; // EBX
454 uint32_t c; // ECX
455 uint32_t d; // EDX
456 };
457
458#if HI_COMPILER == HI_CC_MSVC
459
460 [[nodiscard]] static leaf_type get_leaf(uint32_t leaf_id, uint32_t index = 0) noexcept
461 {
462 query_result_type r;
463 int tmp[4];
464
465 __cpuindex(tmp, char_cast<int>(cpu_id_leaf), char_cast<int>(index));
466
467 std::memcpy(&r, tmp, sizeof(result_type));
468 return r;
469 }
470
471#elif HI_COMPILER == HI_CC_GCC || HI_COMPILER == HI_CC_CLANG
472
473 [[nodiscard]] static leaf_type get_leaf(uint32_t leaf_id, uint32_t index = 0) noexcept
474 {
475 query_result_type r;
476 __cpuid_count(leaf_id, index, r.a, r.b, r.c, r.d);
477 return r;
478 }
479
480#else
481#error "Unsuported compiler for x64 cpu_id"
482#endif
483};
484
485}}
486
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
DOXYGEN BUG.
Definition algorithm.hpp:15
geometry/margins.hpp
Definition assert.hpp:18
Definition cpu_id.hpp:22
uint8_t APIC_id
Local processor id.
Definition cpu_id.hpp:43
T data(T... args)
T memcpy(T... args)
T resize(T... args)