core/stdarch/crates/core_arch/src/x86_64/xsave.rs
1//! `x86_64`'s `xsave` and `xsaveopt` target feature intrinsics
2
3#![allow(clippy::module_name_repetitions)]
4
5#[cfg(test)]
6use stdarch_test::assert_instr;
7
8#[allow(improper_ctypes)]
9unsafe extern "C" {
10 #[link_name = "llvm.x86.xsave64"]
11 fn xsave64(p: *mut u8, hi: u32, lo: u32);
12 #[link_name = "llvm.x86.xrstor64"]
13 fn xrstor64(p: *const u8, hi: u32, lo: u32);
14 #[link_name = "llvm.x86.xsaveopt64"]
15 fn xsaveopt64(p: *mut u8, hi: u32, lo: u32);
16 #[link_name = "llvm.x86.xsavec64"]
17 fn xsavec64(p: *mut u8, hi: u32, lo: u32);
18 #[link_name = "llvm.x86.xsaves64"]
19 fn xsaves64(p: *mut u8, hi: u32, lo: u32);
20 #[link_name = "llvm.x86.xrstors64"]
21 fn xrstors64(p: *const u8, hi: u32, lo: u32);
22}
23
24/// Performs a full or partial save of the enabled processor states to memory at
25/// `mem_addr`.
26///
27/// State is saved based on bits `[62:0]` in `save_mask` and XCR0.
28/// `mem_addr` must be aligned on a 64-byte boundary.
29///
30/// The format of the XSAVE area is detailed in Section 13.4, “XSAVE Area,” of
31/// Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1.
32///
33/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xsave64)
34#[inline]
35#[target_feature(enable = "xsave")]
36#[cfg_attr(test, assert_instr(xsave64))]
37#[stable(feature = "simd_x86", since = "1.27.0")]
38pub unsafe fn _xsave64(mem_addr: *mut u8, save_mask: u64) {
39 xsave64(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
40}
41
42/// Performs a full or partial restore of the enabled processor states using
43/// the state information stored in memory at `mem_addr`.
44///
45/// State is restored based on bits `[62:0]` in `rs_mask`, `XCR0`, and
46/// `mem_addr.HEADER.XSTATE_BV`. `mem_addr` must be aligned on a 64-byte
47/// boundary.
48///
49/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xrstor64)
50#[inline]
51#[target_feature(enable = "xsave")]
52#[cfg_attr(test, assert_instr(xrstor64))]
53#[stable(feature = "simd_x86", since = "1.27.0")]
54pub unsafe fn _xrstor64(mem_addr: *const u8, rs_mask: u64) {
55 xrstor64(mem_addr, (rs_mask >> 32) as u32, rs_mask as u32);
56}
57
58/// Performs a full or partial save of the enabled processor states to memory at
59/// `mem_addr`.
60///
61/// State is saved based on bits `[62:0]` in `save_mask` and `XCR0`.
62/// `mem_addr` must be aligned on a 64-byte boundary. The hardware may optimize
63/// the manner in which data is saved. The performance of this instruction will
64/// be equal to or better than using the `XSAVE64` instruction.
65///
66/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xsaveopt64)
67#[inline]
68#[target_feature(enable = "xsave,xsaveopt")]
69#[cfg_attr(test, assert_instr(xsaveopt64))]
70#[stable(feature = "simd_x86", since = "1.27.0")]
71pub unsafe fn _xsaveopt64(mem_addr: *mut u8, save_mask: u64) {
72 xsaveopt64(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
73}
74
75/// Performs a full or partial save of the enabled processor states to memory
76/// at `mem_addr`.
77///
78/// `xsavec` differs from `xsave` in that it uses compaction and that it may
79/// use init optimization. State is saved based on bits `[62:0]` in `save_mask`
80/// and `XCR0`. `mem_addr` must be aligned on a 64-byte boundary.
81///
82/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xsavec64)
83#[inline]
84#[target_feature(enable = "xsave,xsavec")]
85#[cfg_attr(test, assert_instr(xsavec64))]
86#[stable(feature = "simd_x86", since = "1.27.0")]
87pub unsafe fn _xsavec64(mem_addr: *mut u8, save_mask: u64) {
88 xsavec64(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
89}
90
91/// Performs a full or partial save of the enabled processor states to memory at
92/// `mem_addr`
93///
94/// `xsaves` differs from xsave in that it can save state components
95/// corresponding to bits set in `IA32_XSS` `MSR` and that it may use the
96/// modified optimization. State is saved based on bits `[62:0]` in `save_mask`
97/// and `XCR0`. `mem_addr` must be aligned on a 64-byte boundary.
98///
99/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xsaves64)
100#[inline]
101#[target_feature(enable = "xsave,xsaves")]
102#[cfg_attr(test, assert_instr(xsaves64))]
103#[stable(feature = "simd_x86", since = "1.27.0")]
104pub unsafe fn _xsaves64(mem_addr: *mut u8, save_mask: u64) {
105 xsaves64(mem_addr, (save_mask >> 32) as u32, save_mask as u32);
106}
107
108/// Performs a full or partial restore of the enabled processor states using the
109/// state information stored in memory at `mem_addr`.
110///
111/// `xrstors` differs from `xrstor` in that it can restore state components
112/// corresponding to bits set in the `IA32_XSS` `MSR`; `xrstors` cannot restore
113/// from an `xsave` area in which the extended region is in the standard form.
114/// State is restored based on bits `[62:0]` in `rs_mask`, `XCR0`, and
115/// `mem_addr.HEADER.XSTATE_BV`. `mem_addr` must be aligned on a 64-byte
116/// boundary.
117///
118/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_xrstors64)
119#[inline]
120#[target_feature(enable = "xsave,xsaves")]
121#[cfg_attr(test, assert_instr(xrstors64))]
122#[stable(feature = "simd_x86", since = "1.27.0")]
123pub unsafe fn _xrstors64(mem_addr: *const u8, rs_mask: u64) {
124 xrstors64(mem_addr, (rs_mask >> 32) as u32, rs_mask as u32);
125}
126
127#[cfg(test)]
128mod tests {
129 use crate::core_arch::x86_64::xsave;
130 use std::fmt;
131 use stdarch_test::simd_test;
132
133 #[repr(align(64))]
134 #[derive(Debug)]
135 struct XsaveArea {
136 // max size for 256-bit registers is 800 bytes:
137 // see https://software.intel.com/en-us/node/682996
138 // max size for 512-bit registers is 2560 bytes:
139 // FIXME: add source
140 data: [u8; 2560],
141 }
142
143 impl XsaveArea {
144 fn new() -> XsaveArea {
145 XsaveArea { data: [0; 2560] }
146 }
147 fn ptr(&mut self) -> *mut u8 {
148 self.data.as_mut_ptr()
149 }
150 }
151
152 #[simd_test(enable = "xsave")]
153 #[cfg_attr(miri, ignore)] // Register saving/restoring is not supported in Miri
154 unsafe fn test_xsave64() {
155 let m = 0xFFFFFFFFFFFFFFFF_u64; //< all registers
156 let mut a = XsaveArea::new();
157 let mut b = XsaveArea::new();
158
159 xsave::_xsave64(a.ptr(), m);
160 xsave::_xrstor64(a.ptr(), m);
161 xsave::_xsave64(b.ptr(), m);
162 }
163
164 #[simd_test(enable = "xsave,xsaveopt")]
165 #[cfg_attr(miri, ignore)] // Register saving/restoring is not supported in Miri
166 unsafe fn test_xsaveopt64() {
167 let m = 0xFFFFFFFFFFFFFFFF_u64; //< all registers
168 let mut a = XsaveArea::new();
169 let mut b = XsaveArea::new();
170
171 xsave::_xsaveopt64(a.ptr(), m);
172 xsave::_xrstor64(a.ptr(), m);
173 xsave::_xsaveopt64(b.ptr(), m);
174 }
175
176 #[simd_test(enable = "xsave,xsavec")]
177 #[cfg_attr(miri, ignore)] // Register saving/restoring is not supported in Miri
178 unsafe fn test_xsavec64() {
179 let m = 0xFFFFFFFFFFFFFFFF_u64; //< all registers
180 let mut a = XsaveArea::new();
181 let mut b = XsaveArea::new();
182
183 xsave::_xsavec64(a.ptr(), m);
184 xsave::_xrstor64(a.ptr(), m);
185 xsave::_xsavec64(b.ptr(), m);
186 }
187}