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