use core::{arch::asm, cell::UnsafeCell, sync::atomic::Ordering};
macro_rules! atomic8 {
($atomic_type:ident, $value_type:ty) => {
#[repr(transparent)]
pub(crate) struct $atomic_type {
v: UnsafeCell<$value_type>,
}
unsafe impl Send for $atomic_type {}
unsafe impl Sync for $atomic_type {}
impl $atomic_type {
#[inline]
#[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)]
pub(crate) fn load(&self, order: Ordering) -> $value_type {
crate::utils::assert_load_ordering(order);
let src = self.v.get();
unsafe {
let out;
asm!(
"ld {out}, Z", out = out(reg) out,
in("Z") src,
options(nostack, preserves_flags),
);
out
}
}
#[inline]
#[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)]
pub(crate) fn store(&self, val: $value_type, order: Ordering) {
crate::utils::assert_store_ordering(order);
let dst = self.v.get();
unsafe {
asm!(
"st Z, {val}", val = in(reg) val,
in("Z") dst,
options(nostack, preserves_flags),
);
}
}
#[cfg(any(target_feature = "rmw", portable_atomic_target_feature = "rmw"))]
#[inline]
pub(crate) fn swap(&self, val: $value_type, _order: Ordering) -> $value_type {
let dst = self.v.get();
let out;
unsafe {
asm!(
"xch Z, {val}", val = inout(reg) val => out,
in("Z") dst,
options(nostack, preserves_flags),
);
}
out
}
}
};
}
atomic8!(AtomicI8, i8);
atomic8!(AtomicU8, u8);