1616#include < cassert>
1717#include < cstdint>
1818#include < cstring>
19+ #include < type_traits>
1920#if __cplusplus >= 201703L
2021#include < string_view>
2122#endif
@@ -55,61 +56,60 @@ namespace xsimd
5556 template <typename E>
5657 using x86_reg32_bitset = utils::uint_bitset<E, x86_reg32_t >;
5758
59+ template <typename E, x86_reg32_t I>
60+ struct x86_reg_id
61+ {
62+ static constexpr x86_reg32_t index = I;
63+ using bits = E;
64+ };
65+
66+ template <x86_reg32_t K, typename ... reg_ids>
67+ struct find_reg_k
68+ {
69+ using type = x86_reg_id<void , 0 >;
70+ };
71+
72+ template <x86_reg32_t K, typename reg_id_head, typename ... reg_id_tail>
73+ struct find_reg_k <K, reg_id_head, reg_id_tail...>
74+ {
75+ using type = std::conditional_t <
76+ reg_id_head::index == K,
77+ reg_id_head,
78+ typename find_reg_k<K, reg_id_tail...>::type>;
79+ };
80+
5881 template <x86_reg32_t leaf_num, x86_reg32_t subleaf_num,
59- typename A, typename B, typename C, typename D >
82+ typename ... reg_ids >
6083 class x86_cpuid_regs
61- : private x86_reg32_bitset<A>,
62- private x86_reg32_bitset<B>,
63- private x86_reg32_bitset<C>,
64- private x86_reg32_bitset<D>
84+ : private x86_reg32_bitset<typename reg_ids::bits>...
6585 {
6686 private:
67- using eax_bitset = x86_reg32_bitset<A>;
68- using ebx_bitset = x86_reg32_bitset<B>;
69- using ecx_bitset = x86_reg32_bitset<C>;
70- using edx_bitset = x86_reg32_bitset<D>;
71-
7287 /* Parse CPUINFO register value into individual bit components.*/
7388 constexpr explicit x86_cpuid_regs (const cpuid_reg_t & regs) noexcept
74- : eax_bitset(regs[0 ])
75- , ebx_bitset(regs[1 ])
76- , ecx_bitset(regs[2 ])
77- , edx_bitset(regs[3 ])
89+ : x86_reg32_bitset<typename reg_ids::bits>(regs[reg_ids::index])...
7890 {
7991 }
8092
8193 public:
82- using eax = A;
83- using ebx = B;
84- using ecx = C;
85- using edx = D;
8694 static constexpr x86_reg32_t leaf = leaf_num;
8795 static constexpr x86_reg32_t subleaf = subleaf_num;
8896
97+ using eax = typename find_reg_k<0 , reg_ids...>::type::bits;
98+ using ebx = typename find_reg_k<1 , reg_ids...>::type::bits;
99+ using ecx = typename find_reg_k<2 , reg_ids...>::type::bits;
100+ using edx = typename find_reg_k<3 , reg_ids...>::type::bits;
101+
89102 inline static x86_cpuid_regs read ()
90103 {
91104 return x86_cpuid_regs (detail::x86_cpuid (leaf, subleaf));
92105 }
93106
94107 constexpr x86_cpuid_regs () noexcept = default;
95108
96- using eax_bitset::all_bits_set;
97- using eax_bitset::get_range;
98- using ebx_bitset::all_bits_set;
99- using ebx_bitset::get_range;
100- using ecx_bitset::all_bits_set;
101- using ecx_bitset::get_range;
102- using edx_bitset::all_bits_set;
103- using edx_bitset::get_range;
109+ using x86_reg32_bitset<typename reg_ids::bits>::all_bits_set...;
110+ using x86_reg32_bitset<typename reg_ids::bits>::get_range...;
104111 };
105112
106- template <typename T>
107- using make_x86_cpuid_regs = x86_cpuid_regs<T::leaf, T::subleaf,
108- typename T::eax,
109- typename T::ebx,
110- typename T::ecx,
111- typename T::edx>;
112-
113113 template <bool extended>
114114 struct x86_cpuid_highest_func
115115 {
@@ -298,12 +298,6 @@ namespace xsimd
298298 static constexpr detail::x86_reg32_t leaf = 1 ;
299299 static constexpr detail::x86_reg32_t subleaf = 0 ;
300300
301- enum class eax
302- {
303- };
304- enum class ebx
305- {
306- };
307301 enum class ecx
308302 {
309303 /* Streaming SIMD Extensions 3. */
@@ -328,6 +322,10 @@ namespace xsimd
328322 /* Streaming SIMD Extensions 2. */
329323 sse2 = 26 ,
330324 };
325+
326+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
327+ detail::x86_reg_id<ecx, 2 >,
328+ detail::x86_reg_id<edx, 3 >>;
331329 };
332330
333331 /* *
@@ -340,7 +338,7 @@ namespace xsimd
340338 *
341339 * @see https://en.wikipedia.org/wiki/CPUID
342340 */
343- using x86_cpuid_leaf1 = detail::make_x86_cpuid_regs<x86_cpuid_leaf1_traits> ;
341+ using x86_cpuid_leaf1 = typename x86_cpuid_leaf1_traits:: regs_t ;
344342
345343 struct x86_cpuid_leaf7_traits
346344 {
@@ -386,9 +384,11 @@ namespace xsimd
386384 /* AVX-512 Vector Neural Network instructions. */
387385 avx512vnni_bw = 11 ,
388386 };
389- enum class edx
390- {
391- };
387+
388+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
389+ detail::x86_reg_id<eax, 0 >,
390+ detail::x86_reg_id<ebx, 1 >,
391+ detail::x86_reg_id<ecx, 2 >>;
392392 };
393393
394394 /* *
@@ -401,7 +401,7 @@ namespace xsimd
401401 *
402402 * @see https://en.wikipedia.org/wiki/CPUID
403403 */
404- using x86_cpuid_leaf7 = detail::make_x86_cpuid_regs<x86_cpuid_leaf7_traits> ;
404+ using x86_cpuid_leaf7 = typename x86_cpuid_leaf7_traits:: regs_t ;
405405
406406 struct x86_cpuid_leaf7sub1_traits
407407 {
@@ -413,15 +413,9 @@ namespace xsimd
413413 /* AVX (VEX-encoded) Vector Neural Network instructions. */
414414 avxvnni = 4 ,
415415 };
416- enum class ebx
417- {
418- };
419- enum class ecx
420- {
421- };
422- enum class edx
423- {
424- };
416+
417+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
418+ detail::x86_reg_id<eax, 0 >>;
425419 };
426420
427421 /* *
@@ -434,7 +428,7 @@ namespace xsimd
434428 *
435429 * @see https://en.wikipedia.org/wiki/CPUID
436430 */
437- using x86_cpuid_leaf7sub1 = detail::make_x86_cpuid_regs<x86_cpuid_leaf7sub1_traits> ;
431+ using x86_cpuid_leaf7sub1 = typename x86_cpuid_leaf7sub1_traits:: regs_t ;
438432
439433 /* *
440434 * Highest Extended CPUID Function Parameter (EAX=0x80000000).
@@ -451,20 +445,14 @@ namespace xsimd
451445 static constexpr detail::x86_reg32_t leaf = 0x80000001 ;
452446 static constexpr detail::x86_reg32_t subleaf = 0 ;
453447
454- enum class eax
455- {
456- };
457- enum class ebx
458- {
459- };
460448 enum class ecx
461449 {
462450 /* AMD Fused multiply-add with 4 operands (FMA4). */
463451 fma4 = 16 ,
464452 };
465- enum class edx
466- {
467- } ;
453+
454+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
455+ detail::x86_reg_id<ecx, 2 >> ;
468456 };
469457
470458 /* *
@@ -477,7 +465,7 @@ namespace xsimd
477465 *
478466 * @see https://en.wikipedia.org/wiki/CPUID
479467 */
480- using x86_cpuid_leaf80000001 = detail::make_x86_cpuid_regs<x86_cpuid_leaf80000001_traits> ;
468+ using x86_cpuid_leaf80000001 = typename x86_cpuid_leaf80000001_traits:: regs_t ;
481469
482470 /*
483471 * Extended Control Register 0 (XCR0).
0 commit comments