1//! RDTSC instructions.
2
3#[cfg(test)]
4use stdarch_test::assert_instr;
5
6/// Reads the current value of the processor’s time-stamp counter.
7///
8/// The processor monotonically increments the time-stamp counter MSR
9/// every clock cycle and resets it to 0 whenever the processor is
10/// reset.
11///
12/// The RDTSC instruction is not a serializing instruction. It does
13/// not necessarily wait until all previous instructions have been
14/// executed before reading the counter. Similarly, subsequent
15/// instructions may begin execution before the read operation is
16/// performed.
17///
18/// On processors that support the Intel 64 architecture, the
19/// high-order 32 bits of each of RAX and RDX are cleared.
20///
21/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdtsc)
22#[inline]
23#[cfg_attr(test, assert_instr(rdtsc))]
24#[stable(feature = "simd_x86", since = "1.27.0")]
25pub unsafe fn _rdtsc() -> u64 {
26 rdtsc()
27}
28
29/// Reads the current value of the processor’s time-stamp counter and
30/// the `IA32_TSC_AUX MSR`.
31///
32/// The processor monotonically increments the time-stamp counter MSR
33/// every clock cycle and resets it to 0 whenever the processor is
34/// reset.
35///
36/// The RDTSCP instruction waits until all previous instructions have
37/// been executed before reading the counter. However, subsequent
38/// instructions may begin execution before the read operation is
39/// performed.
40///
41/// On processors that support the Intel 64 architecture, the
42/// high-order 32 bits of each of RAX, RDX, and RCX are cleared.
43///
44/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__rdtscp)
45#[inline]
46#[cfg_attr(test, assert_instr(rdtscp))]
47#[stable(feature = "simd_x86", since = "1.27.0")]
48pub unsafe fn __rdtscp(aux: *mut u32) -> u64 {
49 rdtscp(aux as *mut _)
50}
51
52#[allow(improper_ctypes)]
53extern "C" {
54 #[link_name = "llvm.x86.rdtsc"]
55 fn rdtsc() -> u64;
56 #[link_name = "llvm.x86.rdtscp"]
57 fn rdtscp(aux: *mut u8) -> u64;
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::core_arch::x86::*;
63 use stdarch_test::simd_test;
64
65 #[simd_test(enable = "sse2")]
66 unsafe fn _rdtsc() {
67 let r = rdtsc::_rdtsc();
68 assert_ne!(r, 0); // The chances of this being 0 are infinitesimal
69 }
70
71 #[simd_test(enable = "sse2")]
72 unsafe fn _rdtscp() {
73 let mut aux = 0;
74 let r = rdtsc::__rdtscp(&mut aux);
75 assert_ne!(r, 0); // The chances of this being 0 are infinitesimal
76 }
77}
78