Initially ran into this error in Rust:
unsafe fn set_int_level<const LEVEL: u8>() {
core::arch::asm!(
"move.w #{l},%sr",
l = const (0x2000i16 | (((LEVEL & 0x7) as i16) << 8)),
)
}
Tried a simpler case in C and compiled using clang:
https://godbolt.org/z/eMh7qWz6G
/* Example usecase: Disabling interrupts by setting the interrupt mask bits of SR to 7. */
void disable_interrupts() {
asm("move.w #0x2700,%sr");
}
Both backends generated IR similar to this:
define dso_local void @disable_interrupts() {
entry:
call void asm sideeffect "move.w #0x2700,%sr", ""() #1
ret void
}
However, something goes wrong during codegen, and somehow the move.w #imm,%sr directive turns into move.w #imm,%d0:
disable_interrupts:
link.w %a6, #0
move.w #9984, %d0
unlk %a6
rts
The issue can technically be bypassed by moving the immediate value into a temporary register, and then into the status register, but it's still incorrect behavior by the codegen backend.