Skip to content

Commit 64f4ae8

Browse files
committed
cpufeatures: add support for avx10.1 and avx10.2
1 parent 98d49ed commit 64f4ae8

4 files changed

Lines changed: 195 additions & 1 deletion

File tree

‎cpufeatures/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ Target features:
101101
- `adx`
102102
- `aes`
103103
- `avx`
104+
- `avx10.1`*
105+
- `avx10.2`*
104106
- `avx2`
105107
- `avx512bw`*
106108
- `avx512cd`*

‎cpufeatures/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x
3434
#[macro_export]
3535
macro_rules! new {
3636
($mod_name:ident, $($tf:tt),+ $(,)?) => {
37+
#[allow(unexpected_cfgs)]
3738
mod $mod_name {
3839
use core::sync::atomic::{AtomicU8, Ordering::Relaxed};
3940

‎cpufeatures/src/x86.rs‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ macro_rules! __detect_target_features {
4747
}
4848

4949
let cr = unsafe {
50-
[cpuid(1), cpuid_count(7, 0), cpuid_count(7, 1)]
50+
[
51+
cpuid(1),
52+
cpuid_count(7, 0),
53+
cpuid_count(7, 1),
54+
cpuid(0),
55+
cpuid_count(0x24, 0),
56+
]
5157
};
5258

5359
$($crate::check!(cr, $tf) & )+ true
@@ -81,6 +87,23 @@ macro_rules! __expand_check_macro {
8187
#[macro_export]
8288
#[doc(hidden)]
8389
macro_rules! check {
90+
($cr:expr, "avx10.1") => {{
91+
$crate::__xgetbv!($cr, 0b1110_0110)
92+
& ($cr[3].eax >= 0x24)
93+
& ($cr[2].edx & (1 << 19) != 0)
94+
& (($cr[4].ebx & 0xff) >= 1)
95+
& (($cr[4].ebx & (1 << 18)) != 0)
96+
}};
97+
($cr:expr, "avx10.2") => {{
98+
$crate::__xgetbv!($cr, 0b1110_0110)
99+
& ($cr[3].eax >= 0x24)
100+
& ($cr[2].edx & (1 << 19) != 0)
101+
& (($cr[4].ebx & 0xff) >= 2)
102+
& (($cr[4].ebx & (1 << 18)) != 0)
103+
& ($cr[2].eax & (1 << 4) != 0)
104+
& ($cr[2].edx & (1 << 4) != 0)
105+
& ($cr[2].edx & (1 << 10) != 0)
106+
}};
84107
$(
85108
($cr:expr, $name) => {{
86109
// Register bits are listed here:

‎cpufeatures/tests/x86.rs‎

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
44

55
cpufeatures::new!(cpuid, "aes", "sha");
6+
cpufeatures::new!(cpuid_avx10, "avx10.1", "avx10.2");
67

78
#[test]
89
fn init() {
@@ -15,3 +16,170 @@ fn init_get() {
1516
let (token, val) = cpuid::init_get();
1617
assert_eq!(val, token.get());
1718
}
19+
20+
#[test]
21+
fn avx10_probe_does_not_fault() {
22+
let (token, val) = cpuid_avx10::init_get();
23+
assert_eq!(val, token.get());
24+
let _ = cpuid_avx10::get();
25+
}
26+
27+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
28+
mod avx10_logic {
29+
#[cfg(target_arch = "x86")]
30+
use core::arch::x86::CpuidResult;
31+
#[cfg(target_arch = "x86_64")]
32+
use core::arch::x86_64::CpuidResult;
33+
34+
fn leaf1() -> CpuidResult {
35+
CpuidResult {
36+
eax: 0,
37+
ebx: 0,
38+
ecx: 0b11 << 26,
39+
edx: 0,
40+
}
41+
}
42+
43+
fn blank() -> CpuidResult {
44+
CpuidResult {
45+
eax: 0,
46+
ebx: 0,
47+
ecx: 0,
48+
edx: 0,
49+
}
50+
}
51+
52+
#[test]
53+
fn version_zero_is_disabled() {
54+
let cr = [
55+
leaf1(),
56+
blank(),
57+
CpuidResult {
58+
eax: 0,
59+
ebx: 0,
60+
ecx: 0,
61+
edx: 1 << 19,
62+
},
63+
CpuidResult {
64+
eax: 0x24,
65+
ebx: 0,
66+
ecx: 0,
67+
edx: 0,
68+
},
69+
CpuidResult {
70+
eax: 0,
71+
ebx: (1 << 17) | (1 << 18),
72+
ecx: 0,
73+
edx: 0,
74+
},
75+
];
76+
assert!(!cpufeatures::check!(cr, "avx10.1"));
77+
assert!(!cpufeatures::check!(cr, "avx10.2"));
78+
}
79+
80+
#[test]
81+
fn max_leaf_guard_holds() {
82+
let cr = [
83+
leaf1(),
84+
blank(),
85+
CpuidResult {
86+
eax: 0,
87+
ebx: 0,
88+
ecx: 0,
89+
edx: 1 << 19,
90+
},
91+
CpuidResult {
92+
eax: 0x16,
93+
ebx: 0,
94+
ecx: 0,
95+
edx: 0,
96+
},
97+
CpuidResult {
98+
eax: 0,
99+
ebx: 1 | (1 << 17) | (1 << 18),
100+
ecx: 0,
101+
edx: 0,
102+
},
103+
];
104+
assert!(!cpufeatures::check!(cr, "avx10.1"));
105+
assert!(!cpufeatures::check!(cr, "avx10.2"));
106+
}
107+
108+
#[test]
109+
fn presence_bit_required() {
110+
let cr = [
111+
leaf1(),
112+
blank(),
113+
blank(),
114+
CpuidResult {
115+
eax: 0x24,
116+
ebx: 0,
117+
ecx: 0,
118+
edx: 0,
119+
},
120+
CpuidResult {
121+
eax: 0,
122+
ebx: 1 | (1 << 17) | (1 << 18),
123+
ecx: 0,
124+
edx: 0,
125+
},
126+
];
127+
assert!(!cpufeatures::check!(cr, "avx10.1"));
128+
assert!(!cpufeatures::check!(cr, "avx10.2"));
129+
}
130+
131+
#[test]
132+
fn narrow_vector_without_512_bit_reports_false() {
133+
let cr = [
134+
leaf1(),
135+
blank(),
136+
CpuidResult {
137+
eax: 0,
138+
ebx: 0,
139+
ecx: 0,
140+
edx: 1 << 19,
141+
},
142+
CpuidResult {
143+
eax: 0x24,
144+
ebx: 0,
145+
ecx: 0,
146+
edx: 0,
147+
},
148+
CpuidResult {
149+
eax: 0,
150+
ebx: 1 | (1 << 17),
151+
ecx: 0,
152+
edx: 0,
153+
},
154+
];
155+
assert!(!cpufeatures::check!(cr, "avx10.1"));
156+
assert!(!cpufeatures::check!(cr, "avx10.2"));
157+
}
158+
159+
#[test]
160+
fn vnni_trio_required_for_avx10_2() {
161+
let cr = [
162+
leaf1(),
163+
blank(),
164+
CpuidResult {
165+
eax: 0,
166+
ebx: 0,
167+
ecx: 0,
168+
edx: 1 << 19,
169+
},
170+
CpuidResult {
171+
eax: 0x24,
172+
ebx: 0,
173+
ecx: 0,
174+
edx: 0,
175+
},
176+
CpuidResult {
177+
eax: 0,
178+
ebx: 2 | (1 << 18),
179+
ecx: 0,
180+
edx: 0,
181+
},
182+
];
183+
assert!(!cpufeatures::check!(cr, "avx10.2"));
184+
}
185+
}

0 commit comments

Comments
 (0)