#[cfg(not(portable_atomic_no_asm))]
use core::arch::asm;
use core::sync::atomic::Ordering;
use super::core_atomic as imp;
#[cfg(target_pointer_width = "32")]
macro_rules! ptr_modifier {
() => {
":e"
};
}
#[cfg(target_pointer_width = "64")]
macro_rules! ptr_modifier {
() => {
""
};
}
macro_rules! atomic_int {
(uint, $int_type:ident, $atomic_type:ident, $val_reg:tt, $val_modifier:tt, $ptr_size:tt) => {
impl imp::$atomic_type {
#[inline]
pub(crate) fn not(&self, _order: Ordering) {
let dst = self.as_mut_ptr();
unsafe {
asm!(
concat!("lock not ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"),
dst = inout(reg) dst => _,
options(nostack, preserves_flags),
);
}
}
#[inline]
pub(crate) fn as_mut_ptr(&self) -> *mut $int_type {
unsafe {
(*(self as *const Self as *const core::cell::UnsafeCell<$int_type>)).get()
}
}
}
};
(int, $int_type:ident, $atomic_type:ident, $val_reg:tt, $val_modifier:tt, $ptr_size:tt) => {
atomic_int!(uint, $int_type, $atomic_type, $val_reg, $val_modifier, $ptr_size);
impl imp::$atomic_type {
#[inline]
pub(crate) fn neg(&self, _order: Ordering) {
let dst = self.as_mut_ptr();
unsafe {
asm!(
concat!("lock neg ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"),
dst = inout(reg) dst => _,
options(nostack),
);
}
}
}
};
}
atomic_int!(int, i8, AtomicI8, reg_byte, "", "byte");
atomic_int!(uint, u8, AtomicU8, reg_byte, "", "byte");
atomic_int!(int, i16, AtomicI16, reg, ":x", "word");
atomic_int!(uint, u16, AtomicU16, reg, ":x", "word");
atomic_int!(int, i32, AtomicI32, reg, ":e", "dword");
atomic_int!(uint, u32, AtomicU32, reg, ":e", "dword");
#[cfg(target_arch = "x86_64")]
atomic_int!(int, i64, AtomicI64, reg, "", "qword");
#[cfg(target_arch = "x86_64")]
atomic_int!(uint, u64, AtomicU64, reg, "", "qword");
#[cfg(target_pointer_width = "32")]
atomic_int!(int, isize, AtomicIsize, reg, ":e", "dword");
#[cfg(target_pointer_width = "32")]
atomic_int!(uint, usize, AtomicUsize, reg, ":e", "dword");
#[cfg(target_pointer_width = "64")]
atomic_int!(int, isize, AtomicIsize, reg, "", "qword");
#[cfg(target_pointer_width = "64")]
atomic_int!(uint, usize, AtomicUsize, reg, "", "qword");
#[cfg(target_arch = "x86")]
impl imp::AtomicI64 {
#[inline]
pub(crate) fn not(&self, order: Ordering) {
self.fetch_not(order);
}
#[inline]
pub(crate) fn neg(&self, order: Ordering) {
self.fetch_neg(order);
}
}
#[cfg(target_arch = "x86")]
impl imp::AtomicU64 {
#[inline]
pub(crate) fn not(&self, order: Ordering) {
self.fetch_not(order);
}
}