use core::arch::asm;
#[cfg(feature = "panic-handler")]
pub(crate) use xtensa_lx::interrupt::free as interrupt_free;
use crate::{Backtrace, BacktraceFrame};
pub(super) const RA_OFFSET: usize = 3;
#[inline(never)]
#[cold]
fn sp() -> u32 {
let mut sp: u32;
unsafe {
asm!(
"mov {0}, a1", "add a12,a12,a12",
"rotw 3",
"add a12,a12,a12",
"rotw 3",
"add a12,a12,a12",
"rotw 3",
"add a12,a12,a12",
"rotw 3",
"add a12,a12,a12",
"rotw 4",
out(reg) sp
);
}
unsafe { ((sp - 12) as *const u32).read_volatile() }
}
#[inline(never)]
#[cold]
pub fn backtrace() -> Backtrace {
let sp = sp();
backtrace_internal(sp, 0)
}
pub(crate) fn remove_window_increment(address: u32) -> u32 {
(address & 0x3fff_ffff) | 0x4000_0000
}
pub(crate) fn backtrace_internal(sp: u32, suppress: u32) -> Backtrace {
let mut result = Backtrace(heapless::Vec::new());
let mut fp = sp;
let mut suppress = suppress;
if !crate::is_valid_ram_address(fp) {
return result;
}
while !result.0.is_full() {
let address = unsafe { (fp as *const u32).offset(-4).read_volatile() };
let address = remove_window_increment(address);
fp = unsafe { (fp as *const u32).offset(-3).read_volatile() };
if address == 0x40000000 {
break;
}
if !crate::is_valid_ram_address(fp) {
break;
}
if suppress == 0 {
_ = result.0.push(BacktraceFrame {
pc: address as usize,
});
} else {
suppress -= 1;
}
}
result
}