#[cfg(not(portable_atomic_no_asm))]
use core::arch::asm;
#[cfg(not(portable_atomic_disable_fiq))]
macro_rules! mask {
() => {
"0x80"
};
}
#[cfg(portable_atomic_disable_fiq)]
macro_rules! mask {
() => {
"0xC0" };
}
pub(crate) type State = u32;
#[inline]
#[cfg_attr(
not(any(target_feature = "v7", portable_atomic_target_feature = "v7")),
instruction_set(arm::a32)
)]
pub(crate) fn disable() -> State {
let cpsr: State;
unsafe {
asm!(
"mrs {prev}, cpsr", concat!("orr {new}, {prev}, ", mask!()), "msr cpsr_c, {new}", prev = out(reg) cpsr,
new = out(reg) _,
options(nostack, preserves_flags),
);
}
cpsr
}
#[inline]
#[cfg_attr(
not(any(target_feature = "v7", portable_atomic_target_feature = "v7")),
instruction_set(arm::a32)
)]
pub(crate) unsafe fn restore(prev_cpsr: State) {
unsafe {
asm!(
"msr cpsr_c, {prev_cpsr}", prev_cpsr = in(reg) prev_cpsr,
options(nostack, preserves_flags),
);
}
}
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(any(test, not(target_has_atomic = "ptr")))
)]
pub(super) mod atomic {
#[cfg(not(portable_atomic_no_asm))]
use core::arch::asm;
use core::{cell::UnsafeCell, sync::atomic::Ordering};
macro_rules! atomic {
($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $suffix:tt) => {
#[repr(transparent)]
pub(crate) struct $atomic_type $(<$($generics)*>)? {
v: UnsafeCell<$value_type>,
}
unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {}
unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {}
impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? {
#[inline]
pub(crate) fn load(&self, _order: Ordering) -> $value_type {
let src = self.v.get();
unsafe {
let out;
asm!(
concat!("ldr", $suffix, " {out}, [{src}]"), src = in(reg) src,
out = lateout(reg) out,
options(nostack, preserves_flags),
);
out
}
}
#[inline]
pub(crate) fn store(&self, val: $value_type, _order: Ordering) {
let dst = self.v.get();
unsafe {
asm!(
concat!("str", $suffix, " {val}, [{dst}]"), dst = in(reg) dst,
val = in(reg) val,
options(nostack, preserves_flags),
);
}
}
}
};
}
atomic!(AtomicI8, i8, "b");
atomic!(AtomicU8, u8, "b");
atomic!(AtomicI16, i16, "h");
atomic!(AtomicU16, u16, "h");
atomic!(AtomicI32, i32, "");
atomic!(AtomicU32, u32, "");
atomic!(AtomicIsize, isize, "");
atomic!(AtomicUsize, usize, "");
atomic!([T] AtomicPtr, *mut T, "");
}