core/stdarch/crates/core_arch/src/x86/
xsave.rs1#![allow(clippy::module_name_repetitions)]
3
4#[cfg(test)]
5use stdarch_test::assert_instr;
6
7#[allow(improper_ctypes)]
8unsafe extern "C" {
9 #[link_name = "llvm.x86.xsave"]
10 fn xsave(p: *mut u8, hi: u32, lo: u32);
11 #[link_name = "llvm.x86.xrstor"]
12 fn xrstor(p: *const u8, hi: u32, lo: u32);
13 #[link_name = "llvm.x86.xsetbv"]
14 fn xsetbv(v: u32, hi: u32, lo: u32);
15 #[link_name = "llvm.x86.xgetbv"]
16 fn xgetbv(v: u32) -> i64;
17 #[link_name = "llvm.x86.xsaveopt"]
18 fn xsaveopt(p: *mut u8, hi: u32, lo: u32);
19 #[link_name = "llvm.x86.xsavec"]
20 fn xsavec(p: *mut u8, hi: u32, lo: u32);
21 #[link_name = "llvm.x86.xsaves"]
22 fn xsaves(p: *mut u8, hi: u32, lo: u32);
23 #[link_name = "llvm.x86.xrstors"]
24 fn xrstors(p: *const u8, hi: u32, lo: u32);
25}
26
27#[inline]
38#[target_feature(enable = "xsave")]
39#[cfg_attr(test, assert_instr(xsave))]
40#[stable(feature = "simd_x86", since = "1.27.0")]
41pub unsafe fn _xsave(mem_addr: *mut u8, save_mask: u64) {
42 xsave(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
43}
44
45#[inline]
54#[target_feature(enable = "xsave")]
55#[cfg_attr(test, assert_instr(xrstor))]
56#[stable(feature = "simd_x86", since = "1.27.0")]
57pub unsafe fn _xrstor(mem_addr: *const u8, rs_mask: u64) {
58 xrstor(mem_addr, (rs_mask >> 32) as u32, rs_mask as u32);
59}
60
61#[stable(feature = "simd_x86", since = "1.27.0")]
65pub const _XCR_XFEATURE_ENABLED_MASK: u32 = 0;
66
67#[inline]
74#[target_feature(enable = "xsave")]
75#[cfg_attr(test, assert_instr(xsetbv))]
76#[stable(feature = "simd_x86", since = "1.27.0")]
77pub unsafe fn _xsetbv(a: u32, val: u64) {
78 xsetbv(a, (val >> 32) as u32, val as u32);
79}
80
81#[inline]
86#[target_feature(enable = "xsave")]
87#[cfg_attr(test, assert_instr(xgetbv))]
88#[stable(feature = "simd_x86", since = "1.27.0")]
89pub unsafe fn _xgetbv(xcr_no: u32) -> u64 {
90 xgetbv(xcr_no) as u64
91}
92
93#[inline]
103#[target_feature(enable = "xsave,xsaveopt")]
104#[cfg_attr(test, assert_instr(xsaveopt))]
105#[stable(feature = "simd_x86", since = "1.27.0")]
106pub unsafe fn _xsaveopt(mem_addr: *mut u8, save_mask: u64) {
107 xsaveopt(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
108}
109
110#[inline]
119#[target_feature(enable = "xsave,xsavec")]
120#[cfg_attr(test, assert_instr(xsavec))]
121#[stable(feature = "simd_x86", since = "1.27.0")]
122pub unsafe fn _xsavec(mem_addr: *mut u8, save_mask: u64) {
123 xsavec(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
124}
125
126#[inline]
136#[target_feature(enable = "xsave,xsaves")]
137#[cfg_attr(test, assert_instr(xsaves))]
138#[stable(feature = "simd_x86", since = "1.27.0")]
139pub unsafe fn _xsaves(mem_addr: *mut u8, save_mask: u64) {
140 xsaves(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
141}
142
143#[inline]
155#[target_feature(enable = "xsave,xsaves")]
156#[cfg_attr(test, assert_instr(xrstors))]
157#[stable(feature = "simd_x86", since = "1.27.0")]
158pub unsafe fn _xrstors(mem_addr: *const u8, rs_mask: u64) {
159 xrstors(mem_addr, (rs_mask >> 32) as u32, rs_mask as u32);
160}
161
162#[cfg(test)]
163pub(crate) use tests::XsaveArea;
164
165#[cfg(test)]
166mod tests {
167 use std::boxed::Box;
168
169 use crate::core_arch::x86::*;
170 use stdarch_test::simd_test;
171
172 #[derive(Debug)]
173 pub(crate) struct XsaveArea {
174 data: Box<[AlignedArray]>,
175 }
176
177 #[repr(align(64))]
178 #[derive(Copy, Clone, Debug)]
179 struct AlignedArray([u8; 64]);
180
181 impl XsaveArea {
182 #[target_feature(enable = "xsave")]
183 pub(crate) fn new() -> XsaveArea {
184 let CpuidResult { ecx, .. } = __cpuid(0x0d);
188
189 XsaveArea {
190 data: vec![AlignedArray([0; 64]); ecx.div_ceil(64) as usize].into_boxed_slice(),
191 }
192 }
193 pub(crate) fn ptr(&mut self) -> *mut u8 {
194 self.data.as_mut_ptr().cast()
195 }
196 }
197
198 #[simd_test(enable = "xsave")]
199 #[cfg_attr(miri, ignore)] fn test_xsave() {
201 let m = 0xFFFFFFFFFFFFFFFF_u64; let mut a = XsaveArea::new();
203 let mut b = XsaveArea::new();
204
205 unsafe {
206 _xsave(a.ptr(), m);
207 _xrstor(a.ptr(), m);
208 _xsave(b.ptr(), m);
209 }
210 }
211
212 #[simd_test(enable = "xsave")]
213 #[cfg_attr(miri, ignore)] fn test_xgetbv() {
215 let xcr_n: u32 = _XCR_XFEATURE_ENABLED_MASK;
216
217 let xcr: u64 = unsafe { _xgetbv(xcr_n) };
218 let xcr_cpy: u64 = unsafe { _xgetbv(xcr_n) };
219 assert_eq!(xcr, xcr_cpy);
220 }
221
222 #[simd_test(enable = "xsave,xsaveopt")]
223 #[cfg_attr(miri, ignore)] fn test_xsaveopt() {
225 let m = 0xFFFFFFFFFFFFFFFF_u64; let mut a = XsaveArea::new();
227 let mut b = XsaveArea::new();
228
229 unsafe {
230 _xsaveopt(a.ptr(), m);
231 _xrstor(a.ptr(), m);
232 _xsaveopt(b.ptr(), m);
233 }
234 }
235
236 #[simd_test(enable = "xsave,xsavec")]
237 #[cfg_attr(miri, ignore)] fn test_xsavec() {
239 let m = 0xFFFFFFFFFFFFFFFF_u64; let mut a = XsaveArea::new();
241 let mut b = XsaveArea::new();
242
243 unsafe {
244 _xsavec(a.ptr(), m);
245 _xrstor(a.ptr(), m);
246 _xsavec(b.ptr(), m);
247 }
248 }
249}