diff --git a/arch/arc/core/fast_irq.S b/arch/arc/core/fast_irq.S index f14a541f5b1..19c83e06bab 100644 --- a/arch/arc/core/fast_irq.S +++ b/arch/arc/core/fast_irq.S @@ -101,20 +101,25 @@ firq_nest: * save original value of _ARC_V2_USER_SP and ilink into * the stack of interrupted context first, then restore them later */ - st ilink, [sp] - lr ilink, [_ARC_V2_USER_SP] - st ilink, [sp, -4] + push ilink + PUSHAX ilink, _ARC_V2_USER_SP + /* sp here is the sp of interrupted context */ sr sp, [_ARC_V2_USER_SP] + /* here, bank 0 sp must go back to the value before push and + * PUSHAX as we will switch to bank1, the pop and POPAX later will + * change bank1's sp, not bank0's sp + */ + add sp, sp, 8 /* switch back to banked reg, only ilink can be used */ lr ilink, [_ARC_V2_STATUS32] or ilink, ilink, _ARC_V2_STATUS32_RB(1) kflag ilink lr sp, [_ARC_V2_USER_SP] - ld ilink, [sp, -4] - sr ilink, [_ARC_V2_USER_SP] - ld ilink, [sp] + + POPAX ilink, _ARC_V2_USER_SP + pop ilink firq_nest_1: #else firq_nest: diff --git a/arch/arc/include/swap_macros.h b/arch/arc/include/swap_macros.h index 491a1af50ef..f92ac12f71c 100644 --- a/arch/arc/include/swap_macros.h +++ b/arch/arc/include/swap_macros.h @@ -365,6 +365,18 @@ #endif .endm +/* macro to push aux reg through reg */ +.macro PUSHAX reg aux + lr \reg, [\aux] + st.a \reg, [sp, -4] +.endm + +/* macro to pop aux reg through reg */ +.macro POPAX reg aux + ld.ab \reg, [sp, 4] + sr \reg, [\aux] +.endm + #endif /* _ASMLANGUAGE */ #endif /* ZEPHYR_ARCH_ARC_INCLUDE_SWAP_MACROS_H_ */