diff --git a/src/imp/interrupt/msp430.rs b/src/imp/interrupt/msp430.rs index 89b516c6..70cf12c2 100644 --- a/src/imp/interrupt/msp430.rs +++ b/src/imp/interrupt/msp430.rs @@ -6,11 +6,11 @@ use core::arch::asm; pub(super) use super::super::msp430 as atomic; #[derive(Clone, Copy)] -pub(super) struct WasEnabled(bool); +pub(super) struct State(u16); /// Disables interrupts and returns the previous interrupt state. #[inline] -pub(super) fn disable() -> WasEnabled { +pub(super) fn disable() -> State { let r: u16; // SAFETY: reading the status register and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) @@ -31,24 +31,19 @@ pub(super) fn disable() -> WasEnabled { llvm_asm!("dint { nop" ::: "memory" : "volatile"); } } - // GIE (global interrupt enable) bit (1 << 3) - WasEnabled(r & 0x8 != 0) + State(r) } /// Restores the previous interrupt state. #[inline] -pub(super) unsafe fn restore(WasEnabled(was_enabled): WasEnabled) { - if was_enabled { - // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, - // and we've checked that interrupts were enabled before disabling interrupts. - unsafe { - // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. - // Do not use `preserves_flags` because EINT modifies the GIE (global interrupt enable) bit of the status register. - // Refs: http://mspgcc.sourceforge.net/manual/x951.html - #[cfg(not(portable_atomic_no_asm))] - asm!("nop {{ eint {{ nop", options(nostack)); - #[cfg(portable_atomic_no_asm)] - llvm_asm!("nop { eint { nop" ::: "memory" : "volatile"); - } +pub(super) unsafe fn restore(State(r): State) { + // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, + unsafe { + // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. + // Do not use `preserves_flags` because MOV modifies the status register. + #[cfg(not(portable_atomic_no_asm))] + asm!("nop {{ mov {0}, R2 {{ nop", in(reg) r, options(nostack)); + #[cfg(portable_atomic_no_asm)] + llvm_asm!("nop { mov $0, R2 { nop" :: "r"(r) : "memory" : "volatile"); } }