#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "OLD_ASM"), feature(llvm_asm))]
#![cfg_attr(feature = "OLD_ASM", feature(asm))]
#[inline(never)]
#[cfg(target_arch = "x86_64")]
pub fn ticks() -> u64 {
let mask = 0xFFFFFFFFu64;
let high: u64;
let low: u64;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("lfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("lfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
}
((high) << 32) | (mask & low)
}
#[test]
fn test_delta() {
let x = ticks();
let y = ticks();
assert!((y - x) < 1000000);
}
#[inline(never)]
#[cfg(target_arch = "x86_64")]
pub fn ticks_amd() -> u64 {
let mask = 0xFFFFFFFFu64;
let high: u64;
let low: u64;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("mfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("mfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
}
((high) << 32) | (mask & low)
}
#[inline(never)]
#[cfg(target_arch = "x86_64")]
pub fn ticks_modern() -> u64 {
let mask = 0xFFFFFFFFu64;
let high: u64;
let low: u64;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("rdtscp"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("rdtscp"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
}
((high) << 32) | (mask & low)
}
#[inline(never)]
#[cfg(target_arch = "x86")]
pub fn ticks() -> u64 {
let high: u32;
let low: u32;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("lfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "edx", "eax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("rdtscp"
: "={edx}"(high), "={eax}"(low)
:
: "rdx", "rax"
: "volatile"
);
}
}
let high_val = (high as u64) << 32;
let low_val = low as u64;
high_val | low_val
}
#[inline(never)]
#[cfg(target_arch = "x86")]
pub fn ticks_amd() -> u64 {
let high: u32;
let low: u32;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("mfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "edx", "eax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("mfence;rdtsc"
: "={edx}"(high), "={eax}"(low)
:
: "edx", "eax"
: "volatile"
);
}
}
let high_val = (high as u64) << 32;
let low_val = low as u64;
high_val | low_val
}
#[inline(never)]
#[cfg(target_arch = "x86")]
pub fn ticks_modern() -> u64 {
let mask = 0xFFFFFFFFu64;
let high: u32;
let low: u32;
unsafe {
#[cfg(not(feature = "OLD_ASM"))]
{
llvm_asm!("rdtscp"
: "={edx}"(high), "={eax}"(low)
:
: "edx", "eax"
: "volatile"
);
}
#[cfg(feature = "OLD_ASM")]
{
asm!("rdtscp"
: "={edx}"(high), "={eax}"(low)
:
: "edx", "eax"
: "volatile"
);
}
}
let high_val = (high as u64) << 32;
let low_val = low as u64;
high_val | low_val
}