r/
asm.rs

1//! Commonly used assemblies
2
3/// x86 RDTSC
4#[cfg(target_arch = "x86")]
5#[inline(always)]
6pub fn rdtsc_arch() -> u64 {
7    unsafe { ::core::arch::x86::_rdtsc() as u64 }
8}
9
10/// x86_64 RDTSC
11#[cfg(target_arch = "x86_64")]
12#[inline(always)]
13pub fn rdtsc_arch() -> u64 {
14    unsafe { ::core::arch::x86_64::_rdtsc() as u64 }
15}
16
17#[cfg(not(any(arget_arch = "x86", target_arch = "x86_64")))]
18compile_error!("Expected x86 or x86_64 architecture.");
19
20/// Memory load fence (x86)
21#[cfg(target_arch = "x86")]
22pub fn lfence() {
23    unsafe { ::core::arch::x86::_mm_lfence() }
24}
25
26/// Memory load fence (x86_64)
27#[cfg(target_arch = "x86_64")]
28pub fn lfence() {
29    unsafe { ::core::arch::x86_64::_mm_lfence() }
30}
31
32#[cfg(not(any(arget_arch = "x86", target_arch = "x86_64")))]
33compile_error!("Expected x86 or x86_64 architecture.");
34
35/// RDTSC with memory fence
36#[inline(always)]
37pub fn rdtsc_precise() -> u64 {
38    lfence();
39    rdtsc_arch()
40}
41
42/// Calculate RDTSC Hz in unit of 0.01 GHz.
43/// This takes time so do not use this inside a hot loop.
44#[inline(always)]
45pub fn calc_tsc_hz() -> u64 {
46    // 10MHz
47    const ROUNDUP_UNIT: u64 = 10_000_000;
48    let start = rdtsc_arch();
49    std::thread::sleep(std::time::Duration::from_secs(1));
50    let end = rdtsc_arch();
51
52    (((end - start) + (ROUNDUP_UNIT - 1)) / ROUNDUP_UNIT) * ROUNDUP_UNIT
53}