-
Notifications
You must be signed in to change notification settings - Fork 176
Description
If I interpret this correctly, LR can basically contain an undefined value when reading it. (see https://doc.rust-lang.org/reference/inline-assembly.html#r-asm.rules.reg-not-input) In addition, the behavior is undefined when writing to LR without declaring it as out register. (see https://doc.rust-lang.org/reference/inline-assembly.html#r-asm.rules.reg-not-output)
Furthermore, specifically with the link register (LR) in the context of function calls, (see https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#subroutine-calls) this then completely relies on the compiler inlining this function, as otherwise, LR would contain the return address of the read/write function. (apart from that, by the rules above, LR does not even need to contain anything meaningful).
I am unsure how to solve this right now. If I am not mistaken, the inlining problem could be solved by using a macro.
However, regarding the undefined behavior in general, I am unsure if Rust currently has a way to make this reliably safe.
cortex-m/cortex-m/src/register/lr.rs
Lines 6 to 20 in 9177271
| /// Reads the CPU register | |
| #[cfg(cortex_m)] | |
| #[inline] | |
| pub fn read() -> u32 { | |
| let r; | |
| unsafe { asm!("mov {}, lr", out(reg) r, options(nomem, nostack, preserves_flags)) }; | |
| r | |
| } | |
| /// Writes `bits` to the CPU register | |
| #[cfg(cortex_m)] | |
| #[inline] | |
| pub unsafe fn write(bits: u32) { | |
| asm!("mov lr, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); | |
| } |