Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save/restore coprocessor state on stack #2057

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 72 additions & 69 deletions xtensa-lx-rt/src/exception/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,25 @@ use crate::cfg_asm;
// Additionally there is a chunk of memory reserved for spilled registers.
global_asm!(
"
.set XT_STK_PC, 0
.set XT_STK_PS, 4
.set XT_STK_A0, 8
.equ XT_STK_A1, 12
.set XT_STK_A2, 16
.set XT_STK_A3, 20
.set XT_STK_A4, 24
.set XT_STK_A5, 28
.set XT_STK_A6, 32
.set XT_STK_A7, 36
.set XT_STK_A8, 40
.set XT_STK_A9, 44
.set XT_STK_A10, 48
.set XT_STK_A11, 52
.set XT_STK_A12, 56
.set XT_STK_A13, 60
.set XT_STK_A14, 64
.set XT_STK_A15, 68
.set XT_STK_SAR, 72
.set XT_STK_PC, 0
.set XT_STK_PS, 4
.set XT_STK_A0, 8
.equ XT_STK_A1, 12
.set XT_STK_A2, 16
.set XT_STK_A3, 20
.set XT_STK_A4, 24
.set XT_STK_A5, 28
.set XT_STK_A6, 32
.set XT_STK_A7, 36
.set XT_STK_A8, 40
.set XT_STK_A9, 44
.set XT_STK_A10, 48
.set XT_STK_A11, 52
.set XT_STK_A12, 56
.set XT_STK_A13, 60
.set XT_STK_A14, 64
.set XT_STK_A15, 68
.set XT_STK_SAR, 72
.set XT_STK_EXCCAUSE, 76
.set XT_STK_EXCVADDR, 80
.set XT_STK_LBEG, 84 // Registers for Loop Option
Expand Down Expand Up @@ -66,6 +66,7 @@ global_asm!(
.set XT_STK_F14, 208
.set XT_STK_F15, 212
.set XT_STK_TMP, 216
.set XT_STK_CPENABLE, 220

.set XT_STK_FRMSZ, 256 // needs to be multiple of 16 and enough additional free space
// for the registers spilled to the stack (max 8 registers / 0x20 bytes)
Expand Down Expand Up @@ -126,6 +127,8 @@ unsafe extern "C" fn save_context() {
#[cfg(all(XCHAL_HAVE_CP, not(feature = "float-save-restore")))]
"
/* Disable coprocessor, any use of floats in ISRs will cause an exception unless float-save-restore feature is enabled */
rsr a3, CPENABLE
s32i a3, sp, +XT_STK_CPENABLE
movi a3, 0
wsr a3, CPENABLE
rsync
Expand Down Expand Up @@ -177,11 +180,11 @@ unsafe extern "C" fn save_context() {
#[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))]
"
// Double Precision Accelerator Option
rur a3, f64r_lo
rur a3, f64r_lo
s32i a3, sp, +XT_STK_F64R_LO
rur a3, f64r_hi
s32i a3, sp, +XT_STK_F64R_HI
rur a3, f64s
rur a3, f64s
s32i a3, sp, +XT_STK_F64S
",
#[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
Expand Down Expand Up @@ -226,7 +229,7 @@ unsafe extern "C" fn save_context() {
// used as a temporary by this code, the temporary value would get stored
// onto the stack, instead of the real value.
//

rsr a2, PS // to be restored after SPILL_REGISTERS
movi a0, PS_INTLEVEL_MASK
and a3, a2, a0 // get the current INTLEVEL
Expand All @@ -237,11 +240,11 @@ unsafe extern "C" fn save_context() {
or a3, a3, a0
wsr a3, ps
rsr a0, EPC1

addmi sp, sp, +XT_STK_FRMSZ // go back to spill register region
SPILL_REGISTERS
addmi sp, sp, -XT_STK_FRMSZ // return the current stack pointer

wsr a2, PS // restore to the value at entry
rsync
wsr a0, EPC1
Expand Down Expand Up @@ -288,9 +291,9 @@ global_asm!(
// file on an LX6 core (ESP-32) I'm measuring 145 cycles to spill
// registers with this vs. 279 (!) to do it with
// xthal_spill_windows().

.macro SPILL_REGISTERS
and a12, a12, a12
and a12, a12, a12
rotw 3
and a12, a12, a12
rotw 3
Expand All @@ -311,10 +314,10 @@ global_asm!(
addmi sp, sp, -XT_STK_FRMSZ // only allow multiple of 256

s32i a0, sp, +XT_STK_A1 // save interruptee's A1/SP
s32e a0, sp, -12 // for debug backtrace
s32e a0, sp, -12 // for debug backtrace

.ifc \level,1
rsr a0, PS
rsr a0, PS
s32i a0, sp, +XT_STK_PS // save interruptee's PS

rsr a0, EXCCAUSE
Expand All @@ -323,15 +326,15 @@ global_asm!(
s32i a0, sp, +XT_STK_EXCVADDR
.else
rsr a0, EPS\level
s32i a0, sp, +XT_STK_PS // save interruptee's PS
s32i a0, sp, +XT_STK_PS // save interruptee's PS
.endif

rsr a0, EPC\level
s32i a0, sp, +XT_STK_PC // save interruptee's PC
s32e a0, sp, -16 // for debug backtrace
rsr a0, EPC\level
s32i a0, sp, +XT_STK_PC // save interruptee's PC
s32e a0, sp, -16 // for debug backtrace

rsr a0, EXCSAVE\level
s32i a0, sp, +XT_STK_A0 // save interruptee's A0
rsr a0, EXCSAVE\level
s32i a0, sp, +XT_STK_A0 // save interruptee's A0

call0 save_context

Expand Down Expand Up @@ -429,8 +432,8 @@ unsafe extern "C" fn restore_context() {
",
#[cfg(all(XCHAL_HAVE_CP, not(feature = "float-save-restore")))]
"
/* Re-enable coprocessor(s) after ISR */
movi a3, 8 /* XCHAL_CP_MAXCFG */
/* Restore coprocessor state after ISR */
l32i a3, sp, +XT_STK_CPENABLE
wsr a3, CPENABLE
rsync
",
Expand Down Expand Up @@ -458,26 +461,26 @@ unsafe extern "C" fn restore_context() {
global_asm!(
r#"
.macro RESTORE_CONTEXT level:req
// Restore context and return

// Restore context and return
call0 restore_context

.ifc \level,1
l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
wsr a0, PS
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
wsr a0, EPC\level
.else
l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
wsr a0, EPS\level
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
wsr a0, EPC\level
.endif

l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0
l32i sp, sp, +XT_STK_A1 // remove exception frame
rsync // ensure PS and EPC written
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
wsr a0, EPC\level
.endif

l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0
l32i sp, sp, +XT_STK_A1 // remove exception frame
rsync // ensure PS and EPC written

.endm
"#
);
Expand Down Expand Up @@ -518,8 +521,8 @@ unsafe extern "C" fn __default_naked_exception() {

.RestoreContext:
RESTORE_CONTEXT 1
rfe // PS.EXCM is cleared

rfe // PS.EXCM is cleared
",
options(noreturn)
)
Expand All @@ -539,44 +542,44 @@ unsafe extern "C" fn __default_naked_double_exception() {
"
mov a0, a1 // save a1/sp
addmi sp, sp, -XT_STK_FRMSZ // only allow multiple of 256

s32i a0, sp, +XT_STK_A1 // save interruptee's A1/SP
s32e a0, sp, -12 // for debug backtrace
rsr a0, PS
s32e a0, sp, -12 // for debug backtrace

rsr a0, PS
s32i a0, sp, +XT_STK_PS // save interruptee's PS

rsr a0, EXCCAUSE
s32i a0, sp, +XT_STK_EXCCAUSE
rsr a0, EXCVADDR
s32i a0, sp, +XT_STK_EXCVADDR
rsr a0, DEPC
s32i a0, sp, +XT_STK_PC // save interruptee's PC
s32e a0, sp, -16 // for debug backtrace

rsr a0, DEPC
s32i a0, sp, +XT_STK_PC // save interruptee's PC
s32e a0, sp, -16 // for debug backtrace

rsr a0, EXCSAVE7 // ok to reuse EXCSAVE7 for double exception as long as
// double exception is not in first couple of instructions
// of level 7 handler
s32i a0, sp, +XT_STK_A0 // save interruptee's A0
s32i a0, sp, +XT_STK_A0 // save interruptee's A0

call0 save_context

l32i a6, sp, +XT_STK_EXCCAUSE // put cause in a6 = a2 in callee
mov a7, sp // put address of save frame in a7=a3 in callee
call4 __exception // call handler <= actual call!

// Restore context and return
// Restore context and return
call0 restore_context

l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS
wsr a0, PS
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC
wsr a0, EPC1

l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0
l32i sp, sp, +XT_STK_A1 // remove exception frame
rsync // ensure PS and EPC written
l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0
l32i sp, sp, +XT_STK_A1 // remove exception frame
rsync // ensure PS and EPC written

rfde
",
Expand Down