arch/xtensa: Refactor the differences in ABI calls.

Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
Abdelatif Guettouche 2022-06-11 16:05:19 +02:00 committed by Petro Karashchenko
parent 48f20af8bc
commit 1c94cb5324
4 changed files with 72 additions and 111 deletions

View File

@ -112,9 +112,10 @@
* Pre-processor Definitions
****************************************************************************/
/* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
/* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION CALL, ENTRY AND RETURN
*
* Convenient where the frame size requirements are the same for both ABIs.
* CALL, ARGx are used to make a call to a C function.
* ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
* ENTRY0, RET0 are for frameless functions (no locals, no calls).
*
@ -149,6 +150,15 @@
# define RET(sz) ret1 sz
# define RET0 ret
# define CALL call0
# define ARG1 a2
# define ARG2 a3
# define ARG3 a4
# define ARG4 a5
# define ARG5 a6
# define ARG6 a7
# define RETVAL a2
#else
/* Windowed */
@ -157,6 +167,21 @@
# define RET(sz) retw
# define RET0 retw
/* These macros are used only in assembly code when calling C functions
* with CALL4. This is to help refactor common code with the CALL0 ABI.
* call0 can still be used to call assembly function not conforming to the
* windowed ABI.
*/
# define CALL call4
# define ARG1 a6
# define ARG2 a7
# define ARG3 a8
# define ARG4 a9
# define ARG5 a10
# define ARG6 a11
# define RETVAL a6
#endif
/* Index into stack frame.

View File

@ -131,66 +131,32 @@ g_intstacktop:
ps_setup \level \tmp
#ifdef __XTENSA_CALL0_ABI__
/* Get mask of pending, enabled interrupts at this level into a2. */
rsr a2, INTENABLE
rsr ARG1, INTENABLE
rsr a3, INTERRUPT
movi a4, \mask
and a2, a2, a3
and a2, a2, a4 /* a2 = Set of pending, enabled interrupts for this level */
beqz a2, 1f /* Nothing to do */
and ARG1, ARG1, a3
and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
beqz ARG1, 1f /* Nothing to do */
/* Call xtensa_int_decode passing the address of the register save area
* as a parameter (A3).
*/
/* Argument 1: Set of CPU interrupt to dispatch */
mov a3, a12 /* Argument 2: Top of stack = register save area */
call0 xtensa_int_decode /* Call xtensa_int_decode */
/* On return from xtensa_int_decode, a2 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, a2 will instead refer to the TCB
* register save area. This may or may not reside on a stack.
*/
mov a12, a2 /* Switch to the save area of the new thread */
#else
/* Get mask of pending, enabled interrupts at this level into a6. */
rsr a6, INTENABLE
rsr a2, INTERRUPT
movi a3, \mask
and a6, a6, a2
and a6, a6, a3 /* a6 = Set of pending, enabled interrupts for this level */
beqz a6, 1f /* Nothing to do */
/* At this point, the exception frame should have been allocated and filled,
* and current sp points to the interrupt stack (if enabled). Copy the
* pre-exception's base save area below the current SP. We saved the SP in A12
* before getting here.
/* Link the pre-exception frame for debugging. At this point, a12 points to the
* allocated and filled exception stack frame (old value of SP in case of
* an interrupt stack).
*/
exception_backtrace a12 \level
/* Call xtensa_int_decode passing the address of the register save area
* as a parameter (A7).
/* Argument 1: Set of CPU interrupt to dispatch */
mov ARG2, a12 /* Argument 2: Top of stack = register save area */
CALL xtensa_int_decode
/* xtensa_int_decode returns the address of the new register save area.
* Usually this would be the same as the current SP. But in the event of
* a context switch, it will instead refer to the TCB register save area.
*/
/* Argument 1: Set of CPU interrupt to dispatch */
mov a7, a12 /* Argument 2: Top of stack = register save area */
call4 xtensa_int_decode /* Call xtensa_int_decode */
/* On return from xtensa_int_decode, a6 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, a6 will instead refer to the TCB
* register save area. This may or may not reside on a stack.
*/
mov a12, a6 /* Switch to the save area of the new thread */
#endif
mov a12, RETVAL /* Switch to the save area of the new thread */
#if CONFIG_ARCH_INTERRUPTSTACK < 15
addi sp, sp, XCPTCONTEXT_SIZE
@ -232,17 +198,17 @@ _xtensa_level1_handler:
call0 _xtensa_context_save
/* Save current SP before (possibly) overwriting it, it's the register save
* area. This value will be used later by dispatch_c_isr to retrieve the
* register save area.
*/
/* Save current SP before (possibly) overwriting it, it's the register save
* area. This value will be used later by dispatch_c_isr to retrieve the
* register save area.
*/
mov a12, sp
mov a12, sp
/* Switch to an interrupt stack if we have one */
/* Switch to an interrupt stack if we have one */
#if CONFIG_ARCH_INTERRUPTSTACK > 15
setintstack a13 a14
setintstack a13 a14
#endif
/* Decode and dispatch the interrupt. In the event of an interrupt

View File

@ -62,6 +62,7 @@
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa_macros.S"
@ -129,21 +130,16 @@ _xtensa_panic:
/* Set up PS for C, re-enable hi-pri interrupts, and clear EXCM. */
ps_setup XCHAL_EXCM_LEVEL a0
ps_setup XCHAL_EXCM_LEVEL a0
/* Call C panic handler: Arg1 (A2) = Exception code; Arg 2 (A3) = start
* of the register save area.
/* Call C panic handler:
* Arg1 = Exception code.
* Arg 2 = Start of the register save area.
*/
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCSAVE_1
mov a3, a12
call0 xtensa_panic /* Call xtensa_panic. Should not return */
#else
rsr a6, EXCSAVE_1
mov a7, a12
call4 xtensa_panic /* Call xtensa_panic. Should not return */
#endif
rsr ARG1, EXCSAVE_1
mov ARG2, a12
CALL xtensa_panic /* Call xtensa_panic. Should not return */
1: j 1b /* loop infinitely */
retw

View File

@ -62,6 +62,7 @@
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa_macros.S"
@ -184,7 +185,7 @@ _xtensa_user_handler:
ps_setup 1 a0
/* Create pseudo base save area. At this point, a12 points to the
/* Link the pre-exception frame for debugging. At this point, a12 points to the
* allocated and filled exception stack frame (old value of SP in case of
* an interrupt stack).
*/
@ -195,16 +196,9 @@ _xtensa_user_handler:
* beginning of the register save area.
*/
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a3, a12 /* Argument 2 (a3) = pointer to register save area */
calx0 xtensa_user /* Call xtensa_user */
#else
rsr a6, EXCCAUSE /* Argument 1 (a6) = EXCCAUSE */
mov a7, a12 /* Argument 2 (a7) = pointer to register save area */
call4 xtensa_user /* Call xtensa_user */
mov a12, a6
#endif
rsr ARG1, EXCCAUSE /* Argument 1 = EXCCAUSE */
mov ARG2, a12 /* Argument 2 = pointer to register save area */
CALL xtensa_user /* Call xtensa_user */
/* Restore registers in preparation to return from interrupt */
@ -312,30 +306,16 @@ _xtensa_syscall_handler:
ps_setup 1 a0
#ifdef __XTENSA_CALL0_ABI__
movi a2, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov a3, a12 /* Argument 2: Top of stack = register save area */
call0 xtensa_irq_dispatch /* Call xtensa_int_decode */
movi ARG1, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov ARG2, a12 /* Argument 2: Top of stack = register save area */
CALL xtensa_irq_dispatch /* Call xtensa_int_decode */
/* On return from xtensa_irq_dispatch, A2 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, A2 will instead refer to the TCB
* register save area.
/* xtensa_irq_dispatch returns the address of the new register save area.
* Usually this would be the same as the current SP. But in the event of
* a context switch, it will instead refer to the TCB register save area.
*/
#else
movi a6, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov a7, a12 /* Argument 2: Top of stack = register save area */
call4 xtensa_irq_dispatch /* Call xtensa_int_decode */
/* On return from xtensa_irq_dispatch, A6 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, A6 will instead refer to the TCB
* register save area.
*/
mov a2, a6 /* Switch to the new register save area */
#endif
mov a2, RETVAL /* Switch to the new register save area */
/* Restore registers in preparation to return from interrupt */
@ -447,15 +427,9 @@ _xtensa_coproc_handler:
* beginning of the register save area.
*/
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a3, sp /* Argument 2 (a2) = pointer to register save area */
calx0 xtensa_user_panic /* Call xtensa_user_panic */
#else
rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a7, sp /* Argument 2 (a2) = pointer to register save area */
call4 xtensa_user_panic /* Call xtensa_user_panic */
#endif
rsr ARG1, EXCCAUSE /* Argument 1 = EXCCAUSE */
mov ARG2, sp /* Argument 2 = pointer to register save area */
CALL xtensa_user_panic /* Call xtensa_user_panic */
/* xtensa_user_panic should not return */