| /**************************************************************************** |
| * arch/xtensa/src/common/xtensa_vectors.S |
| * |
| * SPDX-License-Identifier: MIT |
| * SPDX-FileCopyrightText: 2016 Gregory Nutt. All rights reserved. |
| * SPDX-FileCopyrightText: 2006-2015 Cadence Design Systems Inc. |
| * SPDX-FileContributor: Gregory Nutt <gnutt@nuttx.org> |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| ****************************************************************************/ |
| |
| .file "xtensa_vectors.S" |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <arch/irq.h> |
| #include <arch/chip/core-isa.h> |
| #include <arch/xtensa/xtensa_abi.h> |
| #include <arch/xtensa/xtensa_specregs.h> |
| |
| #include "xtensa_macros.S" |
| #include "xtensa.h" |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: _xtensa_level[n]_vector, n=2..6 |
| * |
| * Description: |
| * Xtensa medium/nigh priority interrupt vectors. Each vector goes at a |
| * predetermined location according to the Xtensa hardware configuration, |
| * which is ensured by its placement in a special section known to the |
| * NuttX linker script. The vector logic performs the minimum necessary |
| * operations before jumping to the handler. |
| * |
| ****************************************************************************/ |
| |
| #if XCHAL_EXCM_LEVEL >= 2 |
| .begin literal_prefix .xtensa_level2_vector |
| .section .xtensa_level2_vector.text, "ax" |
| .global _xtensa_level2_vector |
| .global _xtensa_level2_handler |
| .type _xtensa_level2_vector, @function |
| .align 4 |
| |
| _xtensa_level2_vector: |
| wsr a0, EXCSAVE_2 /* Preserve a0 */ |
| call0 _xtensa_level2_handler /* Call level 2 interrupt handling */ |
| |
| /* Never returns here - call0 is used as a jump */ |
| |
| .end literal_prefix |
| |
| .size _xtensa_level2_vector, . - _xtensa_level2_vector |
| #endif |
| |
| #if XCHAL_EXCM_LEVEL >= 3 |
| .begin literal_prefix .xtensa_level3_vector |
| .section .xtensa_level3_vector.text, "ax" |
| .global _xtensa_level3_vector |
| .global _xtensa_level3_handler |
| .type _xtensa_level3_vector, @function |
| .align 4 |
| |
| _xtensa_level3_vector: |
| wsr a0, EXCSAVE_3 /* Preserve a0 */ |
| call0 _xtensa_level3_handler /* Call level 3 interrupt handling */ |
| |
| /* Never returns here - call0 is used as a jump */ |
| |
| .end literal_prefix |
| |
| .size _xtensa_level3_vector, . - _xtensa_level3_vector |
| #endif |
| |
| #if XCHAL_EXCM_LEVEL >= 4 |
| .begin literal_prefix .xtensa_level4_vector |
| .section .xtensa_level4_vector.text, "ax" |
| .global _xtensa_level4_vector |
| .global _xtensa_level4_handler |
| .type _xtensa_level4_vector, @function |
| .align 4 |
| |
| _xtensa_level4_vector: |
| wsr a0, EXCSAVE_4 /* Preserve a0 */ |
| call0 _xtensa_level4_handler /* Call level 4 interrupt handling */ |
| |
| /* Never returns here - call0 is used as a jump */ |
| |
| .end literal_prefix |
| |
| .size _xtensa_level4_vector, . - _xtensa_level4_vector |
| #endif |
| |
| #if XCHAL_EXCM_LEVEL >= 5 |
| .begin literal_prefix .xtensa_level5_vector |
| .section .xtensa_level5_vector.text, "ax" |
| .global _xtensa_level5_vector |
| .global _xtensa_level5_handler |
| .type _xtensa_level5_vector, @function |
| .align 4 |
| |
| _xtensa_level5_vector: |
| wsr a0, EXCSAVE_5 /* Preserve a0 */ |
| call0 _xtensa_level5_handler /* Call level 5 interrupt handling */ |
| |
| /* Never returns here - call0 is used as a jump */ |
| |
| .size _xtensa_level5_vector, . - _xtensa_level5_vector |
| .end literal_prefix |
| #endif |
| |
| #if XCHAL_EXCM_LEVEL >= 6 |
| .begin literal_prefix .xtensa_level6_vector |
| .section .xtensa_level6_vector.text, "ax" |
| .global _xtensa_level6_vector |
| .global _xtensa_level6_handler |
| .type _xtensa_level6_vector, @function |
| .align 4 |
| |
| _xtensa_level6_vector: |
| wsr a0, EXCSAVE_6 /* Preserve a0 */ |
| call0 _xtensa_level6_handler /* Call level 6 interrupt handling */ |
| |
| /* Never returns here - call0 is used as a jump */ |
| |
| .size _xtensa_level6_vector, . - _xtensa_level6_vector |
| .end literal_prefix |
| #endif |
| |
| /**************************************************************************** |
| * Exception Vectors (except User, Co-processor and window exception |
| * vectors). |
| * |
| * Each vector goes at a predetermined location according to the Xtensa |
| * hardware configuration, which is ensured by its placement in a special |
| * section known to the Xtensa linker support package (LSP). It performs |
| * the minimum necessary before jumping to the handler in the .text section. |
| * |
| * The corresponding handler goes in the normal .text section. It sets up |
| * the appropriate stack frame, saves a few vector-specific registers and |
| * calls _xtensa_panic() to save the rest of the interrupted context |
| * and enter the NuttX panic handler |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: _xtensa_nmi_vector |
| * |
| * Description: |
| * NMI Exception |
| * |
| ****************************************************************************/ |
| |
| #if XCHAL_HAVE_NMI |
| .begin literal_prefix .nmi_vector |
| .section .nmi_vector.text, "ax" |
| .global _xtensa_nmi_vector |
| .global _xtensa_nmi_handler |
| .type _xtensa_nmi_vector, @function |
| .align 4 |
| |
| _xtensa_nmi_vector: |
| wsr a0, EXCSAVE + XCHAL_NMILEVEL /* Preserve a0 */ |
| call0 _xtensa_nmi_handler |
| |
| .size _xtensa_nmi_vector, . - _xtensa_nmi_vector |
| .end literal_prefix |
| |
| #endif /* XCHAL_HAVE_NMI */ |
| |
| /**************************************************************************** |
| * Name: _debug_exception_vector |
| * |
| * Description: |
| * Debug exception vector |
| * |
| ****************************************************************************/ |
| |
| #if XCHAL_HAVE_DEBUG |
| .begin literal_prefix .debug_exception_vector |
| .section .debug_exception_vector.text, "ax" |
| .global _debug_exception_vector |
| .global _xtensa_debug_handler |
| .type _debug_exception_vector, @function |
| .align 4 |
| |
| _debug_exception_vector: |
| wsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* Preserve a0 */ |
| call0 _xtensa_debug_handler |
| |
| .size _debug_exception_vector, . - _debug_exception_vector |
| .end literal_prefix |
| |
| #endif /* XCHAL_HAVE_DEBUG */ |
| |
| /**************************************************************************** |
| * Name: _double_exception_vector |
| * |
| * Description: |
| * Double Exception Vector. Double exceptions are not a normal occurrence. |
| * They indicate a bug of some kind. |
| * |
| ****************************************************************************/ |
| |
| #ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR |
| .begin literal_prefix .double_exception_vector |
| .section .double_exception_vector.text, "ax" |
| .global _double_exception_vector |
| .align 4 |
| |
| _double_exception_vector: |
| |
| #if XCHAL_HAVE_DEBUG |
| break 1, 4 /* Unhandled double exception */ |
| #endif |
| |
| /* Can't use exception_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 */ |
| 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 -- REVISIT */ |
| s32i a0, sp, (4 * REG_PS) |
| rsr a0, DEPC /* Save interruptee's PC */ |
| s32i a0, sp, (4 * REG_PC) |
| rsr a0, EXCSAVE_1 /* Save interruptee's a0 -- REVISIT */ |
| s32i a0, sp, (4 * REG_A0) |
| |
| rsr a0, EXCCAUSE /* Save the EXCCAUSE register */ |
| s32i a0, sp, (4 * REG_EXCCAUSE) |
| rsr a0, EXCVADDR /* Save the EXCVADDR register */ |
| s32i a0, sp, (4 * REG_EXCVADDR) |
| |
| s32i a2, sp, (4 * REG_A2) |
| movi a2, XTENSA_DOUBLE_EXCEPTION /* Argument 1: Error code */ |
| call0 _xtensa_panic /* Does not return */ |
| |
| .end literal_prefix |
| |
| #endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ |
| |
| /**************************************************************************** |
| * Name: _kernel_exception_vector |
| * |
| * Description: |
| * Kernel Exception (including Level 1 Interrupt from kernel mode). |
| * |
| ****************************************************************************/ |
| |
| .begin literal_prefix .kernel_exception_vector |
| .section .kernel_exception_vector.text, "ax" |
| .global _kernel_exception_vector |
| .global _xtensa_kernel_handler |
| .type _kernel_exception_vector, @function |
| .align 4 |
| |
| _kernel_exception_vector: |
| |
| #if XCHAL_HAVE_DEBUG |
| break 1, 0 /* Unhandled kernel exception */ |
| #endif |
| |
| wsr a0, EXCSAVE_1 /* Preserve a0 */ |
| call0 _xtensa_kernel_handler |
| |
| .size _kernel_exception_vector, . - _kernel_exception_vector |
| .end literal_prefix |
| |
| /**************************************************************************** |
| * Name: _user_exception_vector |
| * |
| * Description: |
| * User Exception (including Level 1 Interrupt from user mode). |
| * |
| ****************************************************************************/ |
| |
| .begin literal_prefix .user_exception_vector |
| .section .user_exception_vector.text, "ax" |
| .global _user_exception_vector |
| .type _user_exception_vector, @function |
| .align 4 |
| |
| _user_exception_vector: |
| |
| wsr a0, EXCSAVE_1 /* Preserve a0 */ |
| call0 _xtensa_user_handler /* And jump to user exception handler */ |
| |
| .end literal_prefix |