#[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(super) type State = u32;
#[inline]
#[instruction_set(arm::a32)]
pub(super) 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]
#[instruction_set(arm::a32)]
pub(super) unsafe fn restore(cpsr: State) {
unsafe {
asm!("msr cpsr_c, {0}", in(reg) cpsr, options(nostack, preserves_flags));
}
}
pub(crate) 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, $asm_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;
match order {
Ordering::Relaxed => {
asm!(
concat!("ldr", $asm_suffix, " {out}, [{src}]"),
src = in(reg) src,
out = lateout(reg) out,
options(nostack, preserves_flags, readonly),
);
}
Ordering::Acquire | Ordering::SeqCst => {
asm!(
concat!("ldr", $asm_suffix, " {out}, [{src}]"),
src = in(reg) src,
out = lateout(reg) out,
options(nostack, preserves_flags),
);
}
_ => unreachable!("{:?}", order),
}
out
}
}
#[inline]
pub(crate) fn store(&self, val: $value_type, _order: Ordering) {
let dst = self.v.get();
unsafe {
asm!(
concat!("str", $asm_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, "");
}