This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 73a1e0fc581ae12ea0ad284bf4ee0daa4123baa6
Author: Abdelatif Guettouche <[email protected]>
AuthorDate: Mon Jun 13 14:19:46 2022 +0200

    arch/xtensa: Refactor exceptions' entry and exit.
    
    Signed-off-by: Abdelatif Guettouche <[email protected]>
---
 arch/xtensa/src/common/xtensa_int_handlers.S | 220 +++++++--------------------
 arch/xtensa/src/common/xtensa_macros.S       |  84 ++++++++++
 arch/xtensa/src/common/xtensa_panic.S        |   4 +-
 arch/xtensa/src/common/xtensa_user_handler.S |  48 ++----
 arch/xtensa/src/common/xtensa_vectors.S      |  41 ++---
 5 files changed, 160 insertions(+), 237 deletions(-)

diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S 
b/arch/xtensa/src/common/xtensa_int_handlers.S
index 052cce6e0c..10dc7391a7 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -133,12 +133,12 @@ g_intstacktop:
 
        /* Get mask of pending, enabled interrupts at this level into a2. */
 
-       rsr             ARG1, INTENABLE
-       rsr             a3, INTERRUPT
-       movi    a4, \mask
-       and             ARG1, ARG1, a3
-       and             ARG1, ARG1, a4                          /* Set of 
pending, enabled interrupts for this level */
-       beqz    ARG1, 1f                                        /* Nothing to 
do */
+       rsr    ARG1, INTENABLE
+       rsr    a3, INTERRUPT
+       movi   a4, \mask
+       and    ARG1, ARG1, a3
+       and    ARG1, ARG1, a4           /* Set of pending, enabled interrupts 
for this level */
+       beqz   ARG1, 1f                 /* Nothing to do */
 
        /* 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
@@ -148,8 +148,8 @@ g_intstacktop:
        exception_backtrace a12 \level
 
                                                                    /* Argument 
1: Set of CPU interrupt to dispatch */
-       mov             ARG2, a12                                       /* 
Argument 2: Top of stack = register save area */
-       CALL    xtensa_int_decode
+       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
@@ -183,16 +183,9 @@ g_intstacktop:
 
 _xtensa_level1_handler:
 
-       mov             a0, sp                                                  
              /* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE   /* Allocate interrupt stack frame */
-       s32i    a0, sp, (4 * REG_A1)                            /* Save 
pre-interrupt SP */
-       rsr             a0, PS                                                  
        /* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_1                                               
              /* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_1                                           
    /* Save interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create an interrupt frame and save minimal context. */
+
+       exception_entry 1
 
        /* Save rest of interrupt context. */
 
@@ -202,7 +195,7 @@ _xtensa_level1_handler:
         * area. This value will be used later by dispatch_c_isr to retrieve the
         * register save area.
         */
-       
+
        mov  a12, sp
 
        /* Switch to an interrupt stack if we have one */
@@ -222,26 +215,19 @@ _xtensa_level1_handler:
 
        /* Restore registers in preparation to return from interrupt */
 
-       mov             a2, a12                                                 
      /* a2 = address of new state save area */
-       call0   _xtensa_context_restore         /* (preserves a2) */
+       mov     a2, a12                     /* a2 = address of new state save 
area */
+       call0   _xtensa_context_restore     /* (preserves a2) */
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
-       wsr             a0, PS
-       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
-       wsr             a0, EPC_1
-       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
-       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
-       rsync                                                                   
        /* Ensure PS and EPC written */
+       exception_exit 1
 
        /* Return from exception. RFE returns from either the 
UserExceptionVector
         * or the KernelExceptionVector.  RFE sets PS.EXCM back to 0, and then
         * jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
         */
 
-       rfe                                                                     
                  /* And return from "exception" */
+       rfe                                 /* And return from "exception" */
 
 /****************************************************************************
  * MEDIUM PRIORITY (LEVEL 2+) INTERRUPT LOW LEVEL HANDLERS.
@@ -277,16 +263,9 @@ _xtensa_level1_handler:
 
 _xtensa_level2_handler:
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_2                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_2                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_2                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create an interrupt frame and save minimal context. */
+
+       exception_entry 2
 
        /* Save rest of interrupt context. */
 
@@ -321,14 +300,7 @@ _xtensa_level2_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
-       wsr             a0, EPS_2
-       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
-       wsr             a0, EPC_2
-       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
-       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
-       rsync                                                                   
/* Ensure EPS and EPC written */
+       exception_exit 2
 
        /* Return from interrupt.  RFI  restores the PS from EPS_2 and jumps to
         * the address in EPC_2.
@@ -346,16 +318,9 @@ _xtensa_level2_handler:
 
 _xtensa_level3_handler:
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_3                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_3                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_3                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 3
 
        /* Save rest of interrupt context. */
 
@@ -390,14 +355,7 @@ _xtensa_level3_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
-       wsr             a0, EPS_3
-       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
-       wsr             a0, EPC_3
-       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
-       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
-       rsync                                                                   
/* Ensure EPS and EPC written */
+       exception_exit 3
 
        /* Return from interrupt.  RFI  restores the PS from EPS_3 and jumps to
         * the address in EPC_3.
@@ -415,16 +373,9 @@ _xtensa_level3_handler:
 
 _xtensa_level4_handler:
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_4                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_4                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_4                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 4
 
        /* Save rest of interrupt context. */
 
@@ -455,18 +406,11 @@ _xtensa_level4_handler:
        /* Restore registers in preparation to return from interrupt */
 
        mov             a2, a12                                                 
/* a2 = address of new state save area */
-       call0   _xtensa_context_restore                 /* (presevers a2) */
+       call0   _xtensa_context_restore                 /* (preserves a2) */
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
-       wsr             a0, EPS_4
-       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
-       wsr             a0, EPC_4
-       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
-       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
-       rsync                                                                   
/* Ensure EPS and EPC written */
+       exception_exit 4
 
        /* Return from interrupt.  RFI  restores the PS from EPS_4 and jumps to
         * the address in EPC_4.
@@ -484,16 +428,9 @@ _xtensa_level4_handler:
 
 _xtensa_level5_handler:
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_5                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_5                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_5                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 5
 
        /* Save rest of interrupt context. */
 
@@ -528,14 +465,7 @@ _xtensa_level5_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
-       wsr             a0, EPS_5
-       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
-       wsr             a0, EPC_5
-       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
-       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
-       rsync                                                                   
/* Ensure EPS and EPC written */
+       exception_exit 5
 
        /* Return from interrupt.  RFI  restores the PS from EPS_5 and jumps to
         * the address in EPC_5.
@@ -553,20 +483,13 @@ _xtensa_level5_handler:
 
 _xtensa_level6_handler:
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_6                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_6                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_6                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 6
 
        /* Save rest of interrupt context. */
 
-       call0   _xtensa_context_save                    /* Save full register 
state */
+       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
@@ -597,14 +520,7 @@ _xtensa_level6_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)                    /* Retrieve 
interruptee's PS */
-       wsr             a0, EPS_6
-       l32i    a0, a2, (4 * REG_PC)                    /* Retrieve 
interruptee's PC */
-       wsr             a0, EPC_6
-       l32i    a0, a2, (4 * REG_A0)                    /* Retrieve 
interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)                    /* Retrieve interrupt 
stack frame */
-       l32i    a2, a2, (4 * REG_A2)                    /* Retrieve 
interruptee's A2 */
-       rsync                                                                   
/* Ensure EPS and EPC written */
+       exception_exit 6
 
        /* Return from interrupt.  RFI  restores the PS from EPS_6 and jumps to
         * the address in EPC_6.
@@ -661,15 +577,9 @@ _xtensa_level2_handler:
 #if 1
        /* For now, just panic */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_2                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_2                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_2                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 2
 
        s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_LEVEL2_EXCEPTION     /* Address of state save on 
stack */
@@ -695,15 +605,9 @@ _xtensa_level3_handler:
 #if 1
        /* For now, just panic */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_3                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_3                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_3                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 3
 
        s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_LEVEL3_EXCEPTION     /* Address of state save on 
stack */
@@ -731,15 +635,9 @@ _xtensa_level4_handler:
 #if 1
        /* For now, just panic */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_4                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_4                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_4                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 4
 
        s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_LEVEL4_EXCEPTION     /* Address of state save on 
stack */
@@ -767,15 +665,9 @@ _xtensa_level5_handler:
 #if 1
        /* For now, just panic */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_5                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_5                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_5                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 5
 
        s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_LEVEL5_EXCEPTION     /* Address of state save on 
stack */
@@ -803,15 +695,9 @@ _xtensa_level6_handler:
 #if 1
        /* For now, just panic */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS_6                                               
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_6                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_6                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       /* Create interrupt frame and save minimal context. */
+
+       exception_entry 6
 
        s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_LEVEL6_EXCEPTION     /* Address of state save on 
stack */
diff --git a/arch/xtensa/src/common/xtensa_macros.S 
b/arch/xtensa/src/common/xtensa_macros.S
index 5adb3633aa..3ebf0391e6 100644
--- a/arch/xtensa/src/common/xtensa_macros.S
+++ b/arch/xtensa/src/common/xtensa_macros.S
@@ -92,6 +92,44 @@
 
        .endm
 
+/****************************************************************************
+ * Name: ps_excp_read
+ *
+ * Description:
+ *  Read from the correct PS register corresponding to the current interrupt
+ *  level.
+ *
+ ****************************************************************************/
+
+       .macro ps_excp_read tmp level
+
+       .ifeq \level - 1
+       rsr             \tmp, PS
+       .else
+       rsr             \tmp, EPS_2 + \level - 2
+       .endif
+
+       .endm
+
+/****************************************************************************
+ * Name: ps_excp_write
+ *
+ * Description:
+ *  Write to the correct PS register corresponding to the current interrupt
+ *  level.
+ *
+ ****************************************************************************/
+
+       .macro ps_excp_write tmp level
+
+       .ifeq \level - 1
+       wsr             \tmp, PS
+       .else
+       wsr             \tmp, EPS_2 + \level - 2
+       .endif
+
+       .endm
+
 /****************************************************************************
  * Name: exceptin_backtrace
  *
@@ -121,3 +159,49 @@
 #endif
 
        .endm
+
+/****************************************************************************
+ * Name: exception_entry
+ *
+ * Description:
+ *  Create an interrupt frame and save level specific registers.  The rest of
+ *  registers will be saved by xtensa_context_save.
+ *
+ ****************************************************************************/
+
+       .macro exception_entry level
+
+       mov             a0, sp                           /* Save SP in A0 */
+       addi    sp, sp, -XCPTCONTEXT_SIZE        /* Allocate interrupt stack 
frame */
+       s32i    a0, sp, (4 * REG_A1)             /* Save pre-interrupt SP */
+       ps_excp_read a0 \level                   /* Save interruptee's PS */
+       s32i    a0, sp, (4 * REG_PS)
+       rsr             a0, EPC_1 + \level - 1           /* Save interruptee's 
PC */
+       s32i    a0, sp, (4 * REG_PC)
+       rsr             a0, EXCSAVE_1 + \level - 1       /* Save interruptee's 
a0 */
+       s32i    a0, sp, (4 * REG_A0)
+       s32i    a2, sp, (4 * REG_A2)
+
+       .endm
+
+/****************************************************************************
+ * Name: exception_exit
+ *
+ * Description:
+ *  Restore level specific registers, the rest should have been restored
+ *  before calling this macro.
+ *
+ ****************************************************************************/
+
+       .macro exception_exit level
+
+       l32i    a0, a2, (4 * REG_PS)      /* Retrieve interruptee's PS */
+       ps_excp_write a0 \level
+       l32i    a0, a2, (4 * REG_PC)      /* Retrieve interruptee's PC */
+       wsr             a0, EPC_1 + \level - 1
+       l32i    a0, a2, (4 * REG_A0)      /* Retrieve interruptee's A0 */
+       l32i    sp, a2, (4 * REG_A1)      /* Retrieve interrupt stack frame */
+       l32i    a2, a2, (4 * REG_A2)      /* Retrieve interruptee's A2 */
+       rsync                                                 /* Ensure PS and 
EPC written */
+
+       .endm
diff --git a/arch/xtensa/src/common/xtensa_panic.S 
b/arch/xtensa/src/common/xtensa_panic.S
index 05eef85e6e..ccb70e22d5 100644
--- a/arch/xtensa/src/common/xtensa_panic.S
+++ b/arch/xtensa/src/common/xtensa_panic.S
@@ -133,8 +133,8 @@ _xtensa_panic:
        ps_setup XCHAL_EXCM_LEVEL a0
 
        /* Call C panic handler: 
-        *  Arg1  = Exception code.
-        *  Arg 2 = Start of the register save area.
+        *  Arg1 = Exception code.
+        *  Arg2 = Start of the register save area.
         */
 
        rsr             ARG1, EXCSAVE_1
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S 
b/arch/xtensa/src/common/xtensa_user_handler.S
index dd5cd26da1..8695409c3a 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -145,18 +145,9 @@ _xtensa_user_handler:
        /* Handle all other exceptions. All can have user-defined handlers. */
        /* NOTE: we'll stay on the user stack for exception handling. */
 
-       /* Allocate exception frame and save minimal context. */
+       /* Create interrupt frame and save minimal context. */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, PS                                                  
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_1                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_1                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       exception_entry 1
 
        /* Save EXCCAUSE and EXCVADDR into the user frame */
 
@@ -207,14 +198,7 @@ _xtensa_user_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)                    /* Retrieve 
interruptee's PS */
-       wsr             a0, PS
-       l32i    a0, a2, (4 * REG_PC)                    /* Retrieve 
interruptee's PC */
-       wsr             a0, EPC_1
-       l32i    a0, a2, (4 * REG_A0)                    /* Retrieve 
interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)                    /* Retrieve interrupt 
stack frame */
-       l32i    a2, a2, (4 * REG_A2)                    /* Retrieve 
interruptee's A2 */
-       rsync                                                                   
/* Ensure PS and EPC written */
+       exception_exit 1
 
        /* Return from exception. RFE returns from either the 
UserExceptionVector
         * or the KernelExceptionVector.  RFE sets PS.EXCM back to 0, and then
@@ -242,22 +226,17 @@ _xtensa_user_handler:
 
 _xtensa_syscall_handler:
 
-       /* Allocate stack frame and save A0, A1, and PS */
+       /* Create interrupt frame and save minimal context. */
 
-       mov             a0, sp                                                  
/* Save SP in A0 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, PS                                                  
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EXCSAVE_1                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
-       s32i    a2, sp, (4 * REG_A2)
+       exception_entry 1
 
        /* Save rest of interrupt context. */
 
        call0   _xtensa_context_save
 
-       /* Save EPC */
+       /* Save EPC (note that this will overwrite the PC saved by the exception
+        * entry with the correct value skipping the syscall instruction.)
+        */
 
 #if XCHAL_HAVE_LOOPS != 0
        /* Get the interruptee's PC and skip over the 'syscall' instruction.
@@ -292,7 +271,7 @@ _xtensa_syscall_handler:
        s32i    a0, sp, (4 * REG_PC)
 #endif
 
-       /* Dispatch the sycall as with other interrupts. */
+       /* Dispatch the syscall as with other interrupts. */
 
        mov             a12, sp                                                 
/* a12 = address of register save area */
 
@@ -323,14 +302,7 @@ _xtensa_syscall_handler:
 
        /* Restore only level-specific regs (the rest were already restored) */
 
-       l32i    a0, a2, (4 * REG_PS)                    /* Retrieve 
interruptee's PS */
-       wsr             a0, PS
-       l32i    a0, a2, (4 * REG_PC)                    /* Retrieve 
interruptee's PC */
-       wsr             a0, EPC_1
-       l32i    a0, a2, (4 * REG_A0)                    /* Retrieve 
interruptee's A0 */
-       l32i    sp, a2, (4 * REG_A1)                    /* Retrieve interrupt 
stack frame */
-       l32i    a2, a2, (4 * REG_A2)                    /* Retrieve 
interruptee's A2 */
-       rsync                                                                   
/* Ensure PS and EPC written */
+       exception_exit 1
 
        /* Return from exception. RFE returns from either the 
UserExceptionVector
         * or the KernelExceptionVector.  RFE sets PS.EXCM back to 0, and then
diff --git a/arch/xtensa/src/common/xtensa_vectors.S 
b/arch/xtensa/src/common/xtensa_vectors.S
index e0ef459b01..2b4ae27004 100644
--- a/arch/xtensa/src/common/xtensa_vectors.S
+++ b/arch/xtensa/src/common/xtensa_vectors.S
@@ -43,6 +43,7 @@
 #include <arch/xtensa/xtensa_abi.h>
 #include <arch/xtensa/xtensa_specregs.h>
 
+#include "xtensa_macros.S"
 #include "xtensa.h"
 
 /****************************************************************************
@@ -192,17 +193,8 @@ _xtensa_nmi_vector:
 
        wsr             a0, EXCSAVE + XCHAL_NMILEVEL    /* Preserve a0 */
 
-       mov             a0, sp                                                  
/* sp == a1 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS + XCHAL_NMILEVEL                /* Save 
interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_2                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE + XCHAL_NMILEVEL    /* Save interruptee's 
a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       exception_entry XCHAL_NMILEVEL
 
-       s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_NMI_EXCEPTION                /* Argument 1: Error 
code */
        call0   _xtensa_panic                                   /* Does not 
return */
 
@@ -234,17 +226,9 @@ _xtensa_nmi_vector:
 
 _debug_exception_vector:
        wsr             a0, EXCSAVE + XCHAL_DEBUGLEVEL   /* Preserve a0 */
-       mov             a0, sp                                                  
/* sp == a1 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, EPS + XCHAL_DEBUGLEVEL              /* Save 
interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC + XCHAL_DEBUGLEVEL              /* Save 
interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE + XCHAL_DEBUGLEVEL  /* Save interruptee's 
a0 */
-       s32i    a0, sp, (4 * REG_A0)
 
-       s32i    a2, sp, (4 * REG_A2)
+       exception_entry XCHAL_DEBUGLEVEL
+
        movi    a2, XTENSA_DEBUG_EXCEPTION              /* Argument 1: Error 
code */
        call0   _xtensa_panic                                   /* Does not 
return */
 
@@ -273,6 +257,12 @@ _double_exception_vector:
        break   1, 4                                                    /* 
Unhandled double exception */
 #endif
 
+       /* Can't use excetpion_entry because there is no relationship between 
EPC1
+        * DEPC and the current level.  This can be handled by a separate ifeq
+        * block in the macro, however this part is not used, so let's not add
+        * this special case until we have an application for it.
+        */
+
        wsr             a0, EXCSAVE_1           /* Preserve a0 */
 
        mov             a0, sp                                                  
/* sp == a1 */
@@ -319,17 +309,8 @@ _kernel_exception_vector:
 
        wsr             a0, EXCSAVE_1                                   /* 
Preserve a0 */
 
-       mov             a0, sp                                                  
/* sp == a1 */
-       addi    sp, sp, -XCPTCONTEXT_SIZE       /* Allocate interrupt stack 
frame */
-       s32i    a0, sp, (4 * REG_A1)                    /* Save pre-interrupt 
SP */
-       rsr             a0, PS                                                  
/* Save interruptee's PS */
-       s32i    a0, sp, (4 * REG_PS)
-       rsr             a0, EPC_1                                               
/* Save interruptee's PC */
-       s32i    a0, sp, (4 * REG_PC)
-       rsr             a0, EXCSAVE_1                                   /* Save 
interruptee's a0 */
-       s32i    a0, sp, (4 * REG_A0)
+       exception_entry 1
 
-       s32i    a2, sp, (4 * REG_A2)
        movi    a2, XTENSA_KERNEL_EXCEPTION             /* Argument 1: Error 
code */
        call0   _xtensa_panic                                   /* Does not 
return */
 

Reply via email to