7#include "../macros.hpp"
21#if HI_COMPILER == HI_CC_MSVC
23#elif HI_COMPILER == HI_CC_GCC || HI_COMPILER == HI_CC_CLANG
26#error "Unsupported compiler for x64 cpu_id"
60hi_export_module(hikogui.utility.cpu_id);
62namespace hi {
inline namespace v1 {
121constexpr auto cpu_feature_metadata_init()
noexcept
126 r[std::to_underlying(cpu_feature::cmov)] =
"CMOV";
127 r[std::to_underlying(cpu_feature::cx8)] =
"CX8";
128 r[std::to_underlying(cpu_feature::fpu)] =
"FPU";
129 r[std::to_underlying(cpu_feature::fxsr)] =
"FXSR";
130 r[std::to_underlying(cpu_feature::mmx)] =
"MMX";
131 r[std::to_underlying(cpu_feature::osfxsr)] =
"OSDXSR";
132 r[std::to_underlying(cpu_feature::sce)] =
"SCE";
133 r[std::to_underlying(cpu_feature::sse)] =
"SSE";
134 r[std::to_underlying(cpu_feature::sse2)] =
"SSE2";
135 r[std::to_underlying(cpu_feature::cx16)] =
"CX16";
136 r[std::to_underlying(cpu_feature::lahf)] =
"LAHF";
137 r[std::to_underlying(cpu_feature::popcnt)] =
"POPCNT";
138 r[std::to_underlying(cpu_feature::sse3)] =
"SSE3";
139 r[std::to_underlying(cpu_feature::sse4_1)] =
"SSE4.1";
140 r[std::to_underlying(cpu_feature::sse4_2)] =
"SSE4.2";
141 r[std::to_underlying(cpu_feature::ssse3)] =
"SSSE3";
142 r[std::to_underlying(cpu_feature::avx)] =
"AVX";
143 r[std::to_underlying(cpu_feature::avx2)] =
"AVX2";
144 r[std::to_underlying(cpu_feature::bmi1)] =
"BMI1";
145 r[std::to_underlying(cpu_feature::bmi2)] =
"BMI2";
146 r[std::to_underlying(cpu_feature::f16c)] =
"F16C";
147 r[std::to_underlying(cpu_feature::fma)] =
"FMA";
148 r[std::to_underlying(cpu_feature::lzcnt)] =
"LZCNT";
149 r[std::to_underlying(cpu_feature::movbe)] =
"MOVBE";
150 r[std::to_underlying(cpu_feature::osxsave)] =
"OSXSAVE";
151 r[std::to_underlying(cpu_feature::avx512f)] =
"AVX512F";
152 r[std::to_underlying(cpu_feature::avx512bw)] =
"AVX512BW";
153 r[std::to_underlying(cpu_feature::avx512cd)] =
"AVX512CD";
154 r[std::to_underlying(cpu_feature::avx512dq)] =
"AVX512DQ";
155 r[std::to_underlying(cpu_feature::avx512vl)] =
"AVX512VL";
156 r[std::to_underlying(cpu_feature::avx512pf)] =
"AVX512PF";
157 r[std::to_underlying(cpu_feature::avx512er)] =
"AVX512ER";
158 r[std::to_underlying(cpu_feature::sha)] =
"SHA";
159 r[std::to_underlying(cpu_feature::aes)] =
"AES";
160 r[std::to_underlying(cpu_feature::pclmul)] =
"PCLMUL";
161 r[std::to_underlying(cpu_feature::rdrnd)] =
"RDRND";
162 r[std::to_underlying(cpu_feature::rdseed)] =
"RDSEED";
166constexpr auto cpu_feature_metadata = cpu_feature_metadata_init();
171struct std::formatter<::
hi::cpu_feature, char> : std::formatter<std::string_view, char> {
174 return std::formatter<std::string_view, char>::format(::hi::cpu_feature_metadata[std::to_underlying(t)], fc);
178hi_export
namespace hi {
181template<std::
integral Lhs>
184 if (
not std::cmp_equal(lhs, 1)) {
187 if (
not std::cmp_less(std::to_underlying(rhs), 64)) {
188 throw std::logic_error(
"cpu_feature is not allowed the have a value beyond 63");
191 return static_cast<unsigned long long>(lhs) << std::to_underlying(rhs);
201 cmov = 1 << cpu_feature::cmov,
202 cx8 = 1 << cpu_feature::cx8,
203 fpu = 1 << cpu_feature::fpu,
204 fxsr = 1 << cpu_feature::fxsr,
205 mmx = 1 << cpu_feature::mmx,
206 osfxsr = 1 << cpu_feature::osfxsr,
207 sce = 1 << cpu_feature::sce,
208 sse = 1 << cpu_feature::sse,
209 sse2 = 1 << cpu_feature::sse2,
210 x86_64_v1 = cmov | cx8 | fpu | fxsr | mmx | osfxsr | sce | sse | sse2,
212 cx16 = 1 << cpu_feature::cx16,
213 lahf = 1 << cpu_feature::lahf,
214 popcnt = 1 << cpu_feature::popcnt,
215 sse3 = 1 << cpu_feature::sse3,
216 sse4_1 = 1 << cpu_feature::sse4_1,
217 sse4_2 = 1 << cpu_feature::sse4_2,
218 ssse3 = 1 << cpu_feature::ssse3,
219 x86_64_v2 = x86_64_v1 | cx16 | lahf | popcnt | sse3 | sse4_1 | sse4_2 | ssse3,
221 avx = 1 << cpu_feature::avx,
222 avx2 = 1 << cpu_feature::avx2,
223 bmi1 = 1 << cpu_feature::bmi1,
224 bmi2 = 1 << cpu_feature::bmi2,
225 f16c = 1 << cpu_feature::f16c,
226 fma = 1 << cpu_feature::fma,
227 lzcnt = 1 << cpu_feature::lzcnt,
228 movbe = 1 << cpu_feature::movbe,
229 osxsave = 1 << cpu_feature::osxsave,
230 x86_64_v3 = x86_64_v2 | avx | avx2 | bmi1 | bmi2 | f16c | fma | lzcnt | movbe | osxsave,
232 avx512f = 1 << cpu_feature::avx512f,
233 avx512bw = 1 << cpu_feature::avx512bw,
234 avx512cd = 1 << cpu_feature::avx512cd,
235 avx512dq = 1 << cpu_feature::avx512dq,
236 avx512vl = 1 << cpu_feature::avx512vl,
237 x86_64_v4 = x86_64_v3 | avx512f | avx512bw | avx512cd | avx512dq | avx512vl,
239 avx512pf = 1 << cpu_feature::avx512pf,
240 avx512er = 1 << cpu_feature::avx512er,
241 sha = 1 << cpu_feature::sha,
242 aes = 1 << cpu_feature::aes,
243 pclmul = 1 << cpu_feature::pclmul,
244 rdrnd = 1 << cpu_feature::rdrnd,
245 rdseed = 1 << cpu_feature::rdseed,
250 return static_cast<cpu_feature_mask>(std::to_underlying(lhs) | std::to_underlying(rhs));
255 return static_cast<cpu_feature_mask>(std::to_underlying(lhs) & std::to_underlying(rhs));
265 return std::to_underlying(rhs) != 0;
282 return lhs = lhs | rhs;
292 using mask_type = std::underlying_type_t<::hi::cpu_feature_mask>;
295 for (mask_type mask = 1; mask != 0; mask <<= 1) {
296 if ((std::to_underlying(t) & mask) != 0) {
297 auto const feature =
static_cast<::
hi::cpu_feature>(std::countr_zero(mask));
300 str = std::format(
"{}", feature);
302 str = std::format(
"{}, {}", str, feature);
307 return std::formatter<std::string, char>::format(str, fc);
311hi_export
namespace hi {
322 return (eax & (1U <<
bit_nr)) != 0;
327 return (ebx & (1U <<
bit_nr)) != 0;
332 return (ecx & (1U <<
bit_nr)) != 0;
337 return (edx & (1U <<
bit_nr)) != 0;
351#if HI_COMPILER == HI_CC_MSVC
356#elif HI_COMPILER == HI_CC_GCC || HI_COMPILER == HI_CC_CLANG
360#error "cpu_id() not implemented"
375 r |= cpu_feature::cmov;
378 r |= cpu_feature::cx8;
381 r |= cpu_feature::fpu;
384 r |= cpu_feature::fxsr;
387 r |= cpu_feature::osfxsr;
390 r |= cpu_feature::sce;
393 r |= cpu_feature::mmx;
396 r |= cpu_feature::sse;
399 r |= cpu_feature::sse2;
402 r |= cpu_feature::cx16;
405 r |= cpu_feature::lahf;
408 r |= cpu_feature::popcnt;
411 r |= cpu_feature::sse3;
414 r |= cpu_feature::sse4_1;
417 r |= cpu_feature::sse4_2;
420 r |= cpu_feature::ssse3;
423 r |= cpu_feature::lzcnt;
426 r |= cpu_feature::movbe;
429 r |= cpu_feature::osxsave;
432 r |= cpu_feature::f16c;
435 r |= cpu_feature::fma;
438 r |= cpu_feature::bmi1;
441 r |= cpu_feature::bmi2;
444 r |= cpu_feature::avx;
447 r |= cpu_feature::avx2;
450 r |= cpu_feature::avx512f;
453 r |= cpu_feature::avx512bw;
456 r |= cpu_feature::avx512cd;
459 r |= cpu_feature::avx512dq;
462 r |= cpu_feature::avx512vl;
465 r |= cpu_feature::avx512pf;
468 r |= cpu_feature::avx512er;
471 r |= cpu_feature::sha;
474 r |= cpu_feature::aes;
477 r |= cpu_feature::pclmul;
480 r |= cpu_feature::rdrnd;
483 r |= cpu_feature::rdseed;
500 if (
leaf1.ecx_bit( 0)) { r |= cpu_feature::sse3; }
501 if (
leaf1.ecx_bit( 1)) { r |= cpu_feature::pclmul; }
502 if (
leaf1.ecx_bit( 9)) { r |= cpu_feature::ssse3; }
503 if (
leaf1.ecx_bit(12)) { r |= cpu_feature::fma; }
504 if (
leaf1.ecx_bit(13)) { r |= cpu_feature::cx16; }
505 if (
leaf1.ecx_bit(19)) { r |= cpu_feature::sse4_1; }
506 if (
leaf1.ecx_bit(20)) { r |= cpu_feature::sse4_2; }
507 if (
leaf1.ecx_bit(22)) { r |= cpu_feature::movbe; }
508 if (
leaf1.ecx_bit(23)) { r |= cpu_feature::popcnt; }
509 if (
leaf1.ecx_bit(25)) { r |= cpu_feature::aes; }
510 if (
leaf1.ecx_bit(27)) { r |= cpu_feature::osxsave; }
511 if (
leaf1.ecx_bit(28)) { r |= cpu_feature::avx; }
512 if (
leaf1.ecx_bit(29)) { r |= cpu_feature::f16c; }
513 if (
leaf1.ecx_bit(30)) { r |= cpu_feature::rdrnd; }
515 if (
leaf1.edx_bit( 0)) { r |= cpu_feature::fpu; }
516 if (
leaf1.edx_bit( 8)) { r |= cpu_feature::cx8; }
517 if (
leaf1.edx_bit(15)) { r |= cpu_feature::cmov; }
518 if (
leaf1.edx_bit(23)) { r |= cpu_feature::mmx; }
519 if (
leaf1.edx_bit(24)) {
520 r |= cpu_feature::fxsr;
523 r |= cpu_feature::osfxsr;
525 if (
leaf1.edx_bit(25)) { r |= cpu_feature::sse; }
526 if (
leaf1.edx_bit(26)) { r |= cpu_feature::sse2; }
532 if (
leaf7.ebx_bit( 3)) { r |= cpu_feature::bmi1; }
533 if (
leaf7.ebx_bit( 5)) { r |= cpu_feature::avx2; }
534 if (
leaf7.ebx_bit( 8)) { r |= cpu_feature::bmi2; }
535 if (
leaf7.ebx_bit(16)) { r |= cpu_feature::avx512f; }
536 if (
leaf7.ebx_bit(17)) { r |= cpu_feature::avx512dq; }
537 if (
leaf7.ebx_bit(18)) { r |= cpu_feature::rdseed; }
538 if (
leaf7.ebx_bit(26)) { r |= cpu_feature::avx512pf; }
539 if (
leaf7.ebx_bit(27)) { r |= cpu_feature::avx512er; }
540 if (
leaf7.ebx_bit(28)) { r |= cpu_feature::avx512cd; }
541 if (
leaf7.ebx_bit(29)) { r |= cpu_feature::sha; }
542 if (
leaf7.ebx_bit(30)) { r |= cpu_feature::avx512bw; }
543 if (
leaf7.ebx_bit(31)) { r |= cpu_feature::avx512vl; }
552 if (
leaf81.ecx_bit( 0)) { r |= cpu_feature::lahf; }
553 if (
leaf81.ecx_bit( 5)) { r |= cpu_feature::lzcnt; }
556 if (
leaf81.edx_bit(11)) { r |= cpu_feature::sce; }
566 auto const error_message = std::format(
567 "This executable is incompatible with the CPU in this computer.\n"
568 "The CPU is missing the following features:\n"
581 std::println(
std::cerr,
"{}", error_message);
598 return detail::cpu_features;
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
hi_inline bool has_pclmul() noexcept
This CPU has the PCLMUL carry-less multiply instruction.
Definition cpu_id_x86.hpp:912
hi_inline bool has_cx16() noexcept
This CPU has the CMPXCG16 (Compare and exchange 16 bytes) instruction.
Definition cpu_id_x86.hpp:688
hi_inline bool has_lahf() noexcept
This CPU has the LAHF and SAHF instructions.
Definition cpu_id_x86.hpp:696
hi_inline bool has_avx() noexcept
This CPU has the AVX instruction set.
Definition cpu_id_x86.hpp:808
hi_inline bool has_avx512er() noexcept
This CPU has the AVX512ER instruction set.
Definition cpu_id_x86.hpp:888
hi_inline bool has_avx512vl() noexcept
This CPU has the AVX512VL instruction set.
Definition cpu_id_x86.hpp:864
hi_inline bool has_bmi2() noexcept
This CPU has the BMI2 instruction set.
Definition cpu_id_x86.hpp:776
hi_inline bool has_sse2() noexcept
This CPU has the SSE2 instruction set.
Definition cpu_id_x86.hpp:672
hi_inline bool has_osfxsr() noexcept
This operating system uses the FXSAVE instruction.
Definition cpu_id_x86.hpp:640
hi_inline bool has_popcnt() noexcept
This CPU has the POPCNT instructions.
Definition cpu_id_x86.hpp:704
hi_inline bool has_sha() noexcept
This CPU has the SHA cryptographical secure hash instruction set.
Definition cpu_id_x86.hpp:896
cpu_feature_mask cpu_features() noexcept
Get a list of features of the current CPU.
Definition cpu_id_x86.hpp:596
hi_inline bool has_osxsave() noexcept
This operating system uses the SXSAVE instruction.
Definition cpu_id_x86.hpp:800
hi_inline bool has_cx8() noexcept
This CPU has the CMPXCG8 (Compare and exchange 8 bytes) instruction.
Definition cpu_id_x86.hpp:616
hi_inline bool has_mmx() noexcept
This CPU has the MMX instruction set.
Definition cpu_id_x86.hpp:656
hi_inline bool has_movbe() noexcept
This CPU has the MOVBE (Move Big Endian) instruction.
Definition cpu_id_x86.hpp:792
hi_inline bool has_avx2() noexcept
This CPU has the AVX2 instruction set.
Definition cpu_id_x86.hpp:816
hi_inline bool has_sse4_2() noexcept
This CPU has the SSE4.2 instruction set.
Definition cpu_id_x86.hpp:736
hi_inline bool has_sse() noexcept
This CPU has the SSE instruction set.
Definition cpu_id_x86.hpp:664
hi_inline bool has_fxsr() noexcept
This CPU has the fxsave instruction.
Definition cpu_id_x86.hpp:632
hi_inline bool has_x86_64_v4() noexcept
This CPU has all the features for x86-64-v4 microarchitecture level.
Definition cpu_id_x86.hpp:872
hi_inline bool has_avx512cd() noexcept
This CPU has the AVX512CD instruction set.
Definition cpu_id_x86.hpp:848
hi_inline bool has_rdrnd() noexcept
This CPU has the RDRAND on-chip random number generator instruction.
Definition cpu_id_x86.hpp:920
hi_inline bool has_fma() noexcept
This CPU has fused-multiply-accumulate instructions.
Definition cpu_id_x86.hpp:760
hi_inline bool has_x86_64_v2() noexcept
This CPU has all the features for x86-64-v2 microarchitecture level.
Definition cpu_id_x86.hpp:744
hi_inline bool has_avx512dq() noexcept
This CPU has the AVX512DQ instruction set.
Definition cpu_id_x86.hpp:856
hi_inline bool has_sse3() noexcept
This CPU has the SSE3 instruction set.
Definition cpu_id_x86.hpp:712
hi_inline bool has_x86_64_v1() noexcept
This CPU has all the features for x86-64-v1 microarchitecture level.
Definition cpu_id_x86.hpp:680
cpu_feature_mask
A mask of features.
Definition cpu_id_x86.hpp:198
hi_inline bool has_avx512f() noexcept
This CPU has the AVX512F instruction set.
Definition cpu_id_x86.hpp:832
hi_inline bool has_aes() noexcept
This CPU has the AES-NI block cypher instruction set.
Definition cpu_id_x86.hpp:904
hi_inline bool has_rdseed() noexcept
This CPU has the RDSEED access to the conditioned on-chip entropy.
Definition cpu_id_x86.hpp:928
hi_inline bool has_f16c() noexcept
This CPU has float-16 conversion instructions.
Definition cpu_id_x86.hpp:752
hi_inline bool has_avx512bw() noexcept
This CPU has the AVX512BW instruction set.
Definition cpu_id_x86.hpp:840
hi_inline bool has_ssse3() noexcept
This CPU has the SSSE3 instruction set.
Definition cpu_id_x86.hpp:720
cpu_feature
Possible features of x86 CPUs.
Definition cpu_id_x86.hpp:76
hi_inline bool has_sce() noexcept
This operating system uses the SYSCALL instruction.
Definition cpu_id_x86.hpp:648
hi_inline bool has_cmov() noexcept
This CPU has the CMOV (Conditional Move) instruction.
Definition cpu_id_x86.hpp:608
hi_inline bool has_lzcnt() noexcept
This CPU has the LZCNT instruction.
Definition cpu_id_x86.hpp:784
hi_inline bool has_bmi1() noexcept
This CPU has the BMI1 instruction set.
Definition cpu_id_x86.hpp:768
hi_inline bool has_sse4_1() noexcept
This CPU has the SSE4.1 instruction set.
Definition cpu_id_x86.hpp:728
hi_inline bool has_avx512pf() noexcept
This CPU has the AVX512PF instruction set.
Definition cpu_id_x86.hpp:880
hi_inline bool has_x86_64_v3() noexcept
This CPU has all the features for x86-64-v3 microarchitecture level.
Definition cpu_id_x86.hpp:824
hi_inline cpu_id_result cpu_id(uint32_t leaf_id, uint32_t index=0) noexcept
A generic x86 cpu-id instruction.
Definition cpu_id_x86.hpp:347
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
hi_inline bool has_fpu() noexcept
This CPU has a floating-point co-processor.
Definition cpu_id_x86.hpp:624
Definition cpu_id_x86.hpp:314