diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h deleted file mode 100644 index 42a8aeec82..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/* This header file has been moved, please include in future */ -#include diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_config.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_config.h deleted file mode 100644 index f8b2557e31..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_config.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc. - * - * SPDX-License-Identifier: MIT - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Copyright (c) 2015-2019 Cadence Design Systems, Inc. - * - * 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. - */ - -/* - * Configuration-specific information for Xtensa build. This file must be - * included in FreeRTOSConfig.h to properly set up the config-dependent - * parameters correctly. - * - * NOTE: To enable thread-safe C library support, XT_USE_THREAD_SAFE_CLIB must - * be defined to be > 0 somewhere above or on the command line. - */ - -#ifndef XTENSA_CONFIG_H -#define XTENSA_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include /* required for XSHAL_CLIB */ - -#include "xtensa_context.h" - - -/*----------------------------------------------------------------------------- -* STACK REQUIREMENTS -* -* This section defines the minimum stack size, and the extra space required to -* be allocated for saving coprocessor state and/or C library state information -* (if thread safety is enabled for the C library). The sizes are in bytes. -* -* Stack sizes for individual tasks should be derived from these minima based on -* the maximum call depth of the task and the maximum level of interrupt nesting. -* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based -* on the requirement for a task that calls nothing else but can be interrupted. -* This assumes that interrupt handlers do not call more than a few levels deep. -* If this is not true, i.e. one or more interrupt handlers make deep calls then -* the minimum must be increased. -* -* If the Xtensa processor configuration includes coprocessors, then space is -* allocated to save the coprocessor state on the stack. -* -* If thread safety is enabled for the C runtime library, (XT_USE_THREAD_SAFE_CLIB -* is defined) then space is allocated to save the C library context in the TCB. -* -* Allocating insufficient stack space is a common source of hard-to-find errors. -* During development, it is best to enable the FreeRTOS stack checking features. -* -* Usage: -* -* XT_USE_THREAD_SAFE_CLIB -- Define this to a nonzero value to enable thread-safe -* use of the C library. This will require extra stack -* space to be allocated for tasks that use the C library -* reentrant functions. See below for more information. -* -* NOTE: The Xtensa toolchain supports multiple C libraries and not all of them -* support thread safety. Check your core configuration to see which C library -* was chosen for your system. -* -* XT_STACK_MIN_SIZE -- The minimum stack size for any task. It is recommended -* that you do not use a stack smaller than this for any -* task. In case you want to use stacks smaller than this -* size, you must verify that the smaller size(s) will work -* under all operating conditions. -* -* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task -* that does not make C library reentrant calls. Add this -* to the amount of stack space required by the task itself. -* -* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state. -* ------------------------------------------------------------------------------*/ - -/* Extra space required for interrupt/exception hooks. */ -#ifdef XT_INTEXC_HOOKS - #ifdef __XTENSA_CALL0_ABI__ - #define STK_INTEXC_EXTRA 0x200 - #else - #define STK_INTEXC_EXTRA 0x180 - #endif -#else - #define STK_INTEXC_EXTRA 0 -#endif - -/* Check C library thread safety support and compute size of C library save area. - For the supported libraries, we enable thread safety by default, and this can - be overridden from the compiler/make command line. */ -#if (XSHAL_CLIB == XTHAL_CLIB_NEWLIB) || (XSHAL_CLIB == XTHAL_CLIB_XCLIB) - #ifndef XT_USE_THREAD_SAFE_CLIB - #define XT_USE_THREAD_SAFE_CLIB 1 - #endif -#else - #define XT_USE_THREAD_SAFE_CLIB 0 -#endif - -#if XT_USE_THREAD_SAFE_CLIB > 0u - #if XSHAL_CLIB == XTHAL_CLIB_XCLIB - #define XT_HAVE_THREAD_SAFE_CLIB 1 - #if !defined __ASSEMBLER__ - #include - #define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16)) - #define XT_CLIB_GLOBAL_PTR _reent_ptr - #define _REENT_INIT_PTR _init_reent - #define _impure_ptr _reent_ptr - - void _reclaim_reent(void * ptr); - #endif - #elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB - #define XT_HAVE_THREAD_SAFE_CLIB 1 - #if !defined __ASSEMBLER__ - #include - #define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16)) - #define XT_CLIB_GLOBAL_PTR _impure_ptr - #endif - #else - #define XT_HAVE_THREAD_SAFE_CLIB 0 - #error The selected C runtime library is not thread safe. - #endif -#else - #define XT_CLIB_CONTEXT_AREA_SIZE 0 -#endif - -/*------------------------------------------------------------------------------ - Extra size -- interrupt frame plus coprocessor save area plus hook space. - NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks. -------------------------------------------------------------------------------*/ -#ifdef __XTENSA_CALL0_ABI__ - #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE) -#else - #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE) -#endif - -/*------------------------------------------------------------------------------ - Space allocated for user code -- function calls and local variables. - NOTE: This number can be adjusted to suit your needs. You must verify that the - amount of space you reserve is adequate for the worst-case conditions in your - application. - NOTE: The windowed ABI requires more stack, since space has to be reserved - for spilling register windows. -------------------------------------------------------------------------------*/ -#ifdef __XTENSA_CALL0_ABI__ - #define XT_USER_SIZE 0x200 -#else - #define XT_USER_SIZE 0x400 -#endif - -/* Minimum recommended stack size. */ -#define XT_STACK_MIN_SIZE ((XT_XTRA_SIZE + XT_USER_SIZE) / sizeof(unsigned char)) - -/* OS overhead with and without C library thread context. */ -#define XT_STACK_EXTRA (XT_XTRA_SIZE) -#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE) - - -#ifdef __cplusplus -} -#endif - -#endif /* XTENSA_CONFIG_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h deleted file mode 100644 index 9e3c4d9074..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/* This header file has been moved, please include in future */ -#include diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_timer.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_timer.h deleted file mode 100644 index 53555ed8cd..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_timer.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc. - * - * SPDX-License-Identifier: MIT - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Copyright (c) 2015-2019 Cadence Design Systems, Inc. - * - * 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. - */ - -/* - * XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY - * - * This header contains definitions and macros for use primarily by Xtensa - * RTOS assembly coded source files. It includes and uses the Xtensa hardware - * abstraction layer (HAL) to deal with config specifics. It may also be - * included in C source files. - * - * Edit this file to modify timer selection and to specify clock frequency and - * tick duration to match timer interrupt to the real-time tick duration. - * - * If the RTOS has no timer interrupt, then there is no tick timer and the - * clock frequency is irrelevant, so all of these macros are left undefined - * and the Xtensa core configuration need not have a timer. - */ - -#ifndef XTENSA_TIMER_H -#define XTENSA_TIMER_H - -#ifdef __ASSEMBLER__ -#include -#endif - -#include -#include - -#include "xtensa_rtos.h" /* in case this wasn't included directly */ - -#include "freertos/FreeRTOSConfig.h" - -/* -Select timer to use for periodic tick, and determine its interrupt number -and priority. User may specify a timer by defining XT_TIMER_INDEX with -D, -in which case its validity is checked (it must exist in this core and must -not be on a high priority interrupt - an error will be reported in invalid). -Otherwise select the first low or medium priority interrupt timer available. -*/ -#if XCHAL_NUM_TIMERS == 0 - - #error "This Xtensa configuration is unsupported, it has no timers." - -#else - -#ifndef XT_TIMER_INDEX - #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED - #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL - #undef XT_TIMER_INDEX - #define XT_TIMER_INDEX 3 - #endif - #endif - #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED - #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL - #undef XT_TIMER_INDEX - #define XT_TIMER_INDEX 2 - #endif - #endif - #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED - #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL - #undef XT_TIMER_INDEX - #define XT_TIMER_INDEX 1 - #endif - #endif - #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED - #if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL - #undef XT_TIMER_INDEX - #define XT_TIMER_INDEX 0 - #endif - #endif -#endif -#ifndef XT_TIMER_INDEX - #error "There is no suitable timer in this Xtensa configuration." -#endif - -#define XT_CCOMPARE (CCOMPARE + XT_TIMER_INDEX) -#define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX) -#define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM) -#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM) - -#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED - #error "The timer selected by XT_TIMER_INDEX does not exist in this core." -#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL - #error "The timer interrupt cannot be high priority (use medium or low)." -#endif - -#endif /* XCHAL_NUM_TIMERS */ - -/* -Set processor clock frequency, used to determine clock divisor for timer tick. -User should BE SURE TO ADJUST THIS for the Xtensa platform being used. -If using a supported board via the board-independent API defined in xtbsp.h, -this may be left undefined and frequency and tick divisor will be computed -and cached during run-time initialization. - -NOTE ON SIMULATOR: -Under the Xtensa instruction set simulator, the frequency can only be estimated -because it depends on the speed of the host and the version of the simulator. -Also because it runs much slower than hardware, it is not possible to achieve -real-time performance for most applications under the simulator. A frequency -too low does not allow enough time between timer interrupts, starving threads. -To obtain a more convenient but non-real-time tick duration on the simulator, -compile with xt-xcc option "-DXT_SIMULATOR". -Adjust this frequency to taste (it's not real-time anyway!). -*/ -#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ) -#define XT_CLOCK_FREQ configCPU_CLOCK_HZ -#endif - -#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD) - #error "XT_CLOCK_FREQ must be defined for the target platform." -#endif - -/* -Default number of timer "ticks" per second (default 100 for 10ms tick). -RTOS may define this in its own way (if applicable) in xtensa_rtos.h. -User may redefine this to an optimal value for the application, either by -editing this here or in xtensa_rtos.h, or compiling with xt-xcc option -"-DXT_TICK_PER_SEC=" where is a suitable number. -*/ -#ifndef XT_TICK_PER_SEC -#define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */ -#endif - -/* -Derivation of clock divisor for timer tick and interrupt (one per tick). -*/ -#ifdef XT_CLOCK_FREQ -#define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC) -#endif - -#ifndef __ASSEMBLER__ -extern unsigned _xt_tick_divisor; -extern void _xt_tick_divisor_init(void); -#endif - -#endif /* XTENSA_TIMER_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xt_asm_utils.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xt_asm_utils.h deleted file mode 100644 index a21b02a687..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xt_asm_utils.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2017, Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ - -/* File adapted to use on IDF FreeRTOS component, extracted - * originally from zephyr RTOS code base: - * https://github.com/zephyrproject-rtos/zephyr/blob/dafd348/arch/xtensa/include/xtensa-asm2-s.h - */ - -#ifndef __XT_ASM_UTILS_H -#define __XT_ASM_UTILS_H - -/* - * SPILL_ALL_WINDOWS - * - * Spills all windowed registers (i.e. registers not visible as - * A0-A15) to their ABI-defined spill regions on the stack. - * - * Unlike the Xtensa HAL implementation, this code requires that the - * EXCM and WOE bit be enabled in PS, and relies on repeated hardware - * exception handling to do the register spills. The trick is to do a - * noop write to the high registers, which the hardware will trap - * (into an overflow exception) in the case where those registers are - * already used by an existing call frame. Then it rotates the window - * and repeats until all but the A0-A3 registers of the original frame - * are guaranteed to be spilled, eventually rotating back around into - * the original frame. Advantages: - * - * - Vastly smaller code size - * - * - More easily maintained if changes are needed to window over/underflow - * exception handling. - * - * - Requires no scratch registers to do its work, so can be used safely in any - * context. - * - * - If the WOE bit is not enabled (for example, in code written for - * the CALL0 ABI), this becomes a silent noop and operates compatbily. - * - * - Hilariously it's ACTUALLY FASTER than the HAL routine. And not - * just a little bit, it's MUCH faster. With a mostly full register - * 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_ALL_WINDOWS -#if XCHAL_NUM_AREGS == 64 - and a12, a12, a12 - rotw 3 - and a12, a12, a12 - rotw 3 - and a12, a12, a12 - rotw 3 - and a12, a12, a12 - rotw 3 - and a12, a12, a12 - rotw 4 -#elif XCHAL_NUM_AREGS == 32 - and a12, a12, a12 - rotw 3 - and a12, a12, a12 - rotw 3 - and a4, a4, a4 - rotw 2 -#else -#error Unrecognized XCHAL_NUM_AREGS -#endif -.endm - -/* --------------------------------------------------------------------------------- - Macro spinlock_take - - This macro will repeatedley attempt to atomically set a spinlock variable - using the s32c1i instruciton. A spinlock is considered free if its value is 0. - - Entry: - - "reg_A/B" as scratch registers - - "lock_var" spinlock variable's symbol - - Interrupts must already be disabled by caller - Exit: - - Spinlock set to current core's ID (PRID) - - "reg_A/B" clobbered --------------------------------------------------------------------------------- -*/ - -#if portNUM_PROCESSORS > 1 - - .macro spinlock_take reg_A reg_B lock_var - - movi \reg_A, \lock_var /* reg_A = &lock_var */ -.L_spinlock_loop: - movi \reg_B, 0 /* Load spinlock free value (0) into SCOMPARE1 */ - wsr \reg_B, SCOMPARE1 - rsync /* Ensure that SCOMPARE1 is set before s32c1i executes */ - rsr \reg_B, PRID /* Load the current core's ID into reg_B */ - s32c1i \reg_B, \reg_A, 0 /* Attempt *lock_var = reg_B */ - bnez \reg_B, .L_spinlock_loop /* If the write was successful (i.e., lock was free), 0 will have been written back to reg_B */ - - .endm - -#endif /* portNUM_PROCESSORS > 1 */ - -/* --------------------------------------------------------------------------------- - Macro spinlock_release - - This macro will release a spinlock variable previously taken by the - spinlock_take macro. - - Entry: - - "reg_A/B" as scratch registers - - "lock_var" spinlock variable's symbol - - Interrupts must already be disabled by caller - Exit: - - "reg_A/B" clobbered --------------------------------------------------------------------------------- -*/ - -#if portNUM_PROCESSORS > 1 - - .macro spinlock_release reg_A reg_B lock_var - - movi \reg_A, \lock_var /* reg_A = &lock_var */ - movi \reg_B, 0 - s32i \reg_B, \reg_A, 0 /* Release the spinlock (*reg_A = 0) */ - - .endm - -#endif /* portNUM_PROCESSORS > 1 */ - -#endif /* __XT_ASM_UTILS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_context.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_context.S deleted file mode 100644 index cde52ea40e..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_context.S +++ /dev/null @@ -1,672 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc. - * - * SPDX-License-Identifier: MIT - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Copyright (c) 2015-2019 Cadence Design Systems, Inc. - * - * 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. - */ - -/* - * XTENSA CONTEXT SAVE AND RESTORE ROUTINES - * - * Low-level Call0 functions for handling generic context save and restore of - * registers not specifically addressed by the interrupt vectors and handlers. - * Those registers (not handled by these functions) are PC, PS, A0, A1 (SP). - * Except for the calls to RTOS functions, this code is generic to Xtensa. - * - * Note that in Call0 ABI, interrupt handlers are expected to preserve the callee- - * save regs (A12-A15), which is always the case if the handlers are coded in C. - * However A12, A13 are made available as scratch registers for interrupt dispatch - * code, so are presumed saved anyway, and are always restored even in Call0 ABI. - * Only A14, A15 are truly handled as callee-save regs. - * - * Because Xtensa is a configurable architecture, this port supports all user - * generated configurations (except restrictions stated in the release notes). - * This is accomplished by conditional compilation using macros and functions - * defined in the Xtensa HAL (hardware adaptation layer) for your configuration. - * Only the processor state included in your configuration is saved and restored, - * including any processor state added by user configuration options or TIE. - */ - -/* Warn nicely if this file gets named with a lowercase .s instead of .S: */ -#define NOERROR # -NOERROR: .error "C preprocessor needed for this file: make sure its filename\ - ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option." - - -#include "xtensa_rtos.h" -#include "xtensa_context.h" -#include "xt_asm_utils.h" - -#ifdef XT_USE_OVLY -#include -#endif - - .text - -/******************************************************************************* - -_xt_context_save - - !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! - -Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the -interrupt stack frame defined in xtensa_rtos.h. -Its counterpart is _xt_context_restore (which also restores A12, A13). - -Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame. -This function preserves A12 & A13 in order to provide the caller with 2 scratch -regs that need not be saved over the call to this function. The choice of which -2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw, -to avoid moving data more than necessary. Caller can assign regs accordingly. - -Entry Conditions: - A0 = Return address in caller. - A1 = Stack pointer of interrupted thread or handler ("interruptee"). - Original A12, A13 have already been saved in the interrupt stack frame. - Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the - point of interruption. - If windowed ABI, PS.EXCM = 1 (exceptions disabled). - -Exit conditions: - A0 = Return address in caller. - A1 = Stack pointer of interrupted thread or handler ("interruptee"). - A12, A13 as at entry (preserved). - If windowed ABI, PS.EXCM = 1 (exceptions disabled). - -*******************************************************************************/ - - .global _xt_context_save - .type _xt_context_save,@function - .align 4 - .literal_position - .align 4 - -_xt_context_save: - - s32i a2, sp, XT_STK_A2 - s32i a3, sp, XT_STK_A3 - s32i a4, sp, XT_STK_A4 - s32i a5, sp, XT_STK_A5 - s32i a6, sp, XT_STK_A6 - s32i a7, sp, XT_STK_A7 - s32i a8, sp, XT_STK_A8 - s32i a9, sp, XT_STK_A9 - s32i a10, sp, XT_STK_A10 - s32i a11, sp, XT_STK_A11 - - /* - Call0 ABI callee-saved regs a12-15 do not need to be saved here. - a12-13 are the caller's responsibility so it can use them as scratch. - So only need to save a14-a15 here for Windowed ABI (not Call0). - */ - #ifndef __XTENSA_CALL0_ABI__ - s32i a14, sp, XT_STK_A14 - s32i a15, sp, XT_STK_A15 - #endif - - rsr a3, SAR - s32i a3, sp, XT_STK_SAR - - #if XCHAL_HAVE_LOOPS - rsr a3, LBEG - s32i a3, sp, XT_STK_LBEG - rsr a3, LEND - s32i a3, sp, XT_STK_LEND - rsr a3, LCOUNT - s32i a3, sp, XT_STK_LCOUNT - #endif - - #ifdef XT_USE_SWPRI - /* Save virtual priority mask */ - movi a3, _xt_vpri_mask - l32i a3, a3, 0 - s32i a3, sp, XT_STK_VPRI - #endif - - #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) - mov a9, a0 /* preserve ret addr */ - #endif - - s32i a12, sp, XT_STK_TMP0 /* temp. save stuff in stack frame */ - s32i a13, sp, XT_STK_TMP1 - s32i a9, sp, XT_STK_TMP2 - - l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */ - l32i a13, sp, XT_STK_A13 - l32i a9, sp, XT_STK_A9 - - #if XCHAL_EXTRA_SA_SIZE > 0 - addi a2, sp, XT_STK_EXTRA /* where to save it */ - # if XCHAL_EXTRA_SA_ALIGN > 16 - movi a3, -XCHAL_EXTRA_SA_ALIGN - and a2, a2, a3 /* align dynamically >16 bytes */ - # endif - call0 xthal_save_extra_nw /* destroys a0,2,3 */ - #endif - - #ifndef __XTENSA_CALL0_ABI__ - #ifdef XT_USE_OVLY - l32i a9, sp, XT_STK_PC /* recover saved PC */ - _xt_overlay_get_state a9, a12, a13 - s32i a9, sp, XT_STK_OVLY /* save overlay state */ - #endif - - /* SPILL_ALL_WINDOWS macro requires window overflow exceptions to be enabled, - * i.e. PS.EXCM cleared and PS.WOE set. - * Since we are going to clear PS.EXCM, we also need to increase INTLEVEL - * at least to XCHAL_EXCM_LEVEL. This matches that value of effective INTLEVEL - * at entry (CINTLEVEL=max(PS.INTLEVEL, XCHAL_EXCM_LEVEL) when PS.EXCM is set. - * Since WindowOverflow exceptions will trigger inside SPILL_ALL_WINDOWS, - * need to save/restore EPC1 as well. - * Note: even though a4-a15 are saved into the exception frame, we should not - * clobber them until after SPILL_ALL_WINDOWS. This is because these registers - * may contain live windows belonging to previous frames in the call stack. - * These frames will be spilled by SPILL_ALL_WINDOWS, and if the register was - * 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_ALL_WINDOWS */ - movi a0, PS_INTLEVEL_MASK - and a3, a2, a0 /* get the current INTLEVEL */ - bgeui a3, XCHAL_EXCM_LEVEL, 1f /* calculate max(INTLEVEL, XCHAL_EXCM_LEVEL) */ - movi a3, XCHAL_EXCM_LEVEL -1: - movi a0, PS_UM | PS_WOE /* clear EXCM, enable window overflow, set new INTLEVEL */ - or a3, a3, a0 - wsr a3, ps - rsr a0, EPC1 /* to be restored after SPILL_ALL_WINDOWS */ - - addi sp, sp, XT_STK_FRMSZ /* go back to spill register region */ - SPILL_ALL_WINDOWS /* place the live register windows there */ - addi sp, sp, -XT_STK_FRMSZ /* return the current stack pointer and proceed with context save*/ - - wsr a2, PS /* restore to the value at entry */ - rsync - wsr a0, EPC1 /* likewise */ - - #endif /* __XTENSA_CALL0_ABI__ */ - - l32i a12, sp, XT_STK_TMP0 /* restore the temp saved registers */ - l32i a13, sp, XT_STK_TMP1 /* our return address is there */ - l32i a9, sp, XT_STK_TMP2 - - #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) - mov a0, a9 /* retrieve ret addr */ - #endif - - ret - -/******************************************************************************* - -_xt_context_restore - - !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! - -Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0 -ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt -stack frame defined in xtensa_rtos.h . -Its counterpart is _xt_context_save (whose caller saved A12, A13). - -Caller is responsible to restore PC, PS, A0, A1 (SP). - -Entry Conditions: - A0 = Return address in caller. - A1 = Stack pointer of interrupted thread or handler ("interruptee"). - -Exit conditions: - A0 = Return address in caller. - A1 = Stack pointer of interrupted thread or handler ("interruptee"). - Other processor state except PC, PS, A0, A1 (SP), is as at the point - of interruption. - -*******************************************************************************/ - - .global _xt_context_restore - .type _xt_context_restore,@function - .align 4 - .literal_position - .align 4 -_xt_context_restore: - - #if XCHAL_EXTRA_SA_SIZE > 0 - /* - NOTE: Normally the xthal_restore_extra_nw macro only affects address - registers a2-a5. It is theoretically possible for Xtensa processor - designers to write TIE that causes more address registers to be - affected, but it is generally unlikely. If that ever happens, - more registers need to be saved/restored around this macro invocation. - Here we only assume a13 is preserved. - Future Xtensa tools releases might limit the regs that can be affected. - */ - mov a13, a0 /* preserve ret addr */ - addi a2, sp, XT_STK_EXTRA /* where to find it */ - # if XCHAL_EXTRA_SA_ALIGN > 16 - movi a3, -XCHAL_EXTRA_SA_ALIGN - and a2, a2, a3 /* align dynamically >16 bytes */ - # endif - call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */ - mov a0, a13 /* retrieve ret addr */ - #endif - - #if XCHAL_HAVE_LOOPS - l32i a2, sp, XT_STK_LBEG - l32i a3, sp, XT_STK_LEND - wsr a2, LBEG - l32i a2, sp, XT_STK_LCOUNT - wsr a3, LEND - wsr a2, LCOUNT - #endif - - #ifdef XT_USE_OVLY - /* - If we are using overlays, this is a good spot to check if we need - to restore an overlay for the incoming task. Here we have a bunch - of registers to spare. Note that this step is going to use a few - bytes of storage below SP (SP-20 to SP-32) if an overlay is going - to be restored. - */ - l32i a2, sp, XT_STK_PC /* retrieve PC */ - l32i a3, sp, XT_STK_PS /* retrieve PS */ - l32i a4, sp, XT_STK_OVLY /* retrieve overlay state */ - l32i a5, sp, XT_STK_A1 /* retrieve stack ptr */ - _xt_overlay_check_map a2, a3, a4, a5, a6 - s32i a2, sp, XT_STK_PC /* save updated PC */ - s32i a3, sp, XT_STK_PS /* save updated PS */ - #endif - - #ifdef XT_USE_SWPRI - /* Restore virtual interrupt priority and interrupt enable */ - movi a3, _xt_intdata - l32i a4, a3, 0 /* a4 = _xt_intenable */ - l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */ - and a4, a4, a5 - wsr a4, INTENABLE /* update INTENABLE */ - s32i a5, a3, 4 /* restore _xt_vpri_mask */ - #endif - - l32i a3, sp, XT_STK_SAR - l32i a2, sp, XT_STK_A2 - wsr a3, SAR - l32i a3, sp, XT_STK_A3 - l32i a4, sp, XT_STK_A4 - l32i a5, sp, XT_STK_A5 - l32i a6, sp, XT_STK_A6 - l32i a7, sp, XT_STK_A7 - l32i a8, sp, XT_STK_A8 - l32i a9, sp, XT_STK_A9 - l32i a10, sp, XT_STK_A10 - l32i a11, sp, XT_STK_A11 - - /* - Call0 ABI callee-saved regs a12-15 do not need to be restored here. - However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), - so need to be restored anyway, despite being callee-saved in Call0. - */ - l32i a12, sp, XT_STK_A12 - l32i a13, sp, XT_STK_A13 - #ifndef __XTENSA_CALL0_ABI__ - l32i a14, sp, XT_STK_A14 - l32i a15, sp, XT_STK_A15 - #endif - - ret - - -/******************************************************************************* - -_xt_coproc_init - -Initializes global co-processor management data, setting all co-processors -to "unowned". Leaves CPENABLE as it found it (does NOT clear it). - -Called during initialization of the RTOS, before any threads run. - -This may be called from normal Xtensa single-threaded application code which -might use co-processors. The Xtensa run-time initialization enables all -co-processors. They must remain enabled here, else a co-processor exception -might occur outside of a thread, which the exception handler doesn't expect. - -Entry Conditions: - Xtensa single-threaded run-time environment is in effect. - No thread is yet running. - -Exit conditions: - None. - -Obeys ABI conventions per prototype: - void _xt_coproc_init(void) - -*******************************************************************************/ - -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_init - .type _xt_coproc_init,@function - .align 4 - .literal_position - .align 4 -_xt_coproc_init: - ENTRY0 - - /* Initialize thread co-processor ownerships to 0 (unowned). */ - movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */ - addi a3, a2, (XCHAL_CP_MAX*portNUM_PROCESSORS) << 2 /* a3 = top+1 of owner array */ - movi a4, 0 /* a4 = 0 (unowned) */ -1: s32i a4, a2, 0 - addi a2, a2, 4 - bltu a2, a3, 1b - - RET0 - -#endif - - -/******************************************************************************* - -_xt_coproc_release - -Releases any and all co-processors owned by a given thread. The thread is -identified by it's co-processor state save area defined in xtensa_context.h . - -Must be called before a thread's co-proc save area is deleted to avoid -memory corruption when the exception handler tries to save the state. -May be called when a thread terminates or completes but does not delete -the co-proc save area, to avoid the exception handler having to save the -thread's co-proc state before another thread can use it (optimization). - -Entry Conditions: - A2 = Pointer to base of co-processor state save area. - A3 = Core ID of the task (must be pinned) who's coproc ownership we are - releasing. - -Exit conditions: - None. - -Obeys ABI conventions per prototype: - void _xt_coproc_release(void * coproc_sa_base, BaseType_t xTargetCoreID) - -*******************************************************************************/ - -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_release - .type _xt_coproc_release,@function - .align 4 - .literal_position - .align 4 -_xt_coproc_release: - ENTRY0 /* a2 = base of save area */ - /* a3 = xTargetCoreID */ - - movi a4, XCHAL_CP_MAX << 2 /* a4 = size of an owner array */ - mull a4, a3, a4 /* a4 = offset to the owner array of the target core */ - movi a3, _xt_coproc_owner_sa /* a3 = base of all owner arrays */ - add a3, a3, a4 /* a3 = base of owner array of the target core */ - addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array of the target core */ - movi a5, 0 /* a5 = 0 (unowned) */ - - rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */ -#if portNUM_PROCESSORS > 1 - /* If multicore, we must also acquire the _xt_coproc_owner_sa_lock spinlock - * to ensure thread safe access of _xt_coproc_owner_sa between cores. */ - spinlock_take a7 a8 _xt_coproc_owner_sa_lock -#endif /* portNUM_PROCESSORS > 1 */ - -1: l32i a7, a3, 0 /* a7 = owner at a3 */ - bne a2, a7, 2f /* if (coproc_sa_base == owner) */ - s32i a5, a3, 0 /* owner = unowned */ -2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ - bltu a3, a4, 1b /* repeat until end of array */ - -#if portNUM_PROCESSORS > 1 - /* Release previously taken spinlock */ - spinlock_release a7 a8 _xt_coproc_owner_sa_lock -#endif /* portNUM_PROCESSORS > 1 */ - wsr a6, PS /* restore interrupts */ - - RET0 - -#endif - - -/******************************************************************************* -_xt_coproc_savecs - -If there is a current thread and it has a coprocessor state save area, then -save all callee-saved state into this area. This function is called from the -solicited context switch handler. It calls a system-specific function to get -the coprocessor save area base address. - -Entry conditions: - - The thread being switched out is still the current thread. - - CPENABLE state reflects which coprocessors are active. - - Registers have been saved/spilled already. - -Exit conditions: - - All necessary CP callee-saved state has been saved. - - Registers a2-a7, a13-a15 have been trashed. - -Must be called from assembly code only, using CALL0. -*******************************************************************************/ -#if XCHAL_CP_NUM > 0 - - .extern _xt_coproc_sa_offset /* external reference */ - - .global _xt_coproc_savecs - .type _xt_coproc_savecs,@function - .align 4 - .literal_position - .align 4 -_xt_coproc_savecs: - - /* At entry, CPENABLE should be showing which CPs are enabled. */ - - rsr a2, CPENABLE /* a2 = which CPs are enabled */ - beqz a2, .Ldone /* quick exit if none */ - mov a14, a0 /* save return address */ - call0 XT_RTOS_CP_STATE /* get address of CP save area */ - mov a0, a14 /* restore return address */ - beqz a15, .Ldone /* if none then nothing to do */ - s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */ - movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ - l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ - -#if XCHAL_CP0_SA_SIZE - bbci.l a2, 0, 2f /* CP 0 not enabled */ - l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ - add a3, a14, a15 /* a3 = save area for CP 0 */ - xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP1_SA_SIZE - bbci.l a2, 1, 2f /* CP 1 not enabled */ - l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ - add a3, a14, a15 /* a3 = save area for CP 1 */ - xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP2_SA_SIZE - bbci.l a2, 2, 2f - l32i a14, a13, 8 - add a3, a14, a15 - xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP3_SA_SIZE - bbci.l a2, 3, 2f - l32i a14, a13, 12 - add a3, a14, a15 - xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP4_SA_SIZE - bbci.l a2, 4, 2f - l32i a14, a13, 16 - add a3, a14, a15 - xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP5_SA_SIZE - bbci.l a2, 5, 2f - l32i a14, a13, 20 - add a3, a14, a15 - xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP6_SA_SIZE - bbci.l a2, 6, 2f - l32i a14, a13, 24 - add a3, a14, a15 - xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP7_SA_SIZE - bbci.l a2, 7, 2f - l32i a14, a13, 28 - add a3, a14, a15 - xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -.Ldone: - ret -#endif - - -/******************************************************************************* -_xt_coproc_restorecs - -Restore any callee-saved coprocessor state for the incoming thread. -This function is called from coprocessor exception handling, when giving -ownership to a thread that solicited a context switch earlier. It calls a -system-specific function to get the coprocessor save area base address. - -Entry conditions: - - The incoming thread is set as the current thread. - - CPENABLE is set up correctly for all required coprocessors. - - a2 = mask of coprocessors to be restored. - -Exit conditions: - - All necessary CP callee-saved state has been restored. - - CPENABLE - unchanged. - - Registers a2-a7, a13-a15 have been trashed. - -Must be called from assembly code only, using CALL0. -*******************************************************************************/ -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_restorecs - .type _xt_coproc_restorecs,@function - .align 4 - .literal_position - .align 4 -_xt_coproc_restorecs: - - mov a14, a0 /* save return address */ - call0 XT_RTOS_CP_STATE /* get address of CP save area */ - mov a0, a14 /* restore return address */ - beqz a15, .Ldone2 /* if none then nothing to do */ - l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */ - xor a3, a3, a2 /* clear the ones being restored */ - s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */ - movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ - l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ - -#if XCHAL_CP0_SA_SIZE - bbci.l a2, 0, 2f /* CP 0 not enabled */ - l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ - add a3, a14, a15 /* a3 = save area for CP 0 */ - xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP1_SA_SIZE - bbci.l a2, 1, 2f /* CP 1 not enabled */ - l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ - add a3, a14, a15 /* a3 = save area for CP 1 */ - xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP2_SA_SIZE - bbci.l a2, 2, 2f - l32i a14, a13, 8 - add a3, a14, a15 - xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP3_SA_SIZE - bbci.l a2, 3, 2f - l32i a14, a13, 12 - add a3, a14, a15 - xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP4_SA_SIZE - bbci.l a2, 4, 2f - l32i a14, a13, 16 - add a3, a14, a15 - xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP5_SA_SIZE - bbci.l a2, 5, 2f - l32i a14, a13, 20 - add a3, a14, a15 - xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP6_SA_SIZE - bbci.l a2, 6, 2f - l32i a14, a13, 24 - add a3, a14, a15 - xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP7_SA_SIZE - bbci.l a2, 7, 2f - l32i a14, a13, 28 - add a3, a14, a15 - xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -.Ldone2: - ret - -#endif diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_loadstore_handler.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_loadstore_handler.S deleted file mode 100644 index 859a6ae81c..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_loadstore_handler.S +++ /dev/null @@ -1,549 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * LoadStoreErrorCause: Occurs when trying to access 32 bit addressable memory region as 8 bit or 16 bit - * LoadStoreAlignmentCause: Occurs when trying to access in an unaligned manner - * - * xxxx xxxx = imm8 field - * yyyy = imm4 field - * ssss = s field - * tttt = t field - * - * 16 0 - * ------------------- - * L32I.N yyyy ssss tttt 1000 - * S32I.N yyyy ssss tttt 1001 - * - * 23 0 - * ----------------------------- - * L8UI xxxx xxxx 0000 ssss tttt 0010 <- LoadStoreError - * L16UI xxxx xxxx 0001 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment - * L16SI xxxx xxxx 1001 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment - * L32I xxxx xxxx 0010 ssss tttt 0010 <- LoadStoreAlignment - * - * S8I xxxx xxxx 0100 ssss tttt 0010 <- LoadStoreError - * S16I xxxx xxxx 0101 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment - * S32I xxxx xxxx 0110 ssss tttt 0010 <- LoadStoreAlignment - * - * ******* UNSUPPORTED ******* - * - * L32E 0000 1001 rrrr ssss tttt 0000 - * S32E 0100 1001 rrrr ssss tttt 0000 - * ----------------------------- - */ - -#include "xtensa_rtos.h" -#include "sdkconfig.h" -#include "soc/soc.h" - -#define LOADSTORE_HANDLER_STACK_SZ 8 - .section .bss, "aw" - .balign 16 -LoadStoreHandlerStack: - .rept LOADSTORE_HANDLER_STACK_SZ - .word 0 - .endr - - -/* LoadStoreErrorCause handler: - * - * Completes 8-bit or 16-bit load/store instructions from 32-bit aligned memory region - * Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause - */ - - .global LoadStoreErrorHandler - .section .iram1, "ax" - - .literal_position - - .balign 4 -LoadStoreErrorHandler: - .type LoadStoreErrorHandler, @function - - wsr a0, depc // Save return address in depc - mov a0, sp - movi sp, LoadStoreHandlerStack - s32i a0, sp, 0x04 // Since a0 contains value of a1 - s32i a2, sp, 0x08 - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - - rsr a0, sar // Save SAR in a0 to restore later - - /* Check whether the address lies in the valid range */ - rsr a3, excvaddr - movi a4, _iram_text_end // End of code section of IRAM - bge a3, a4, 1f - movi a4, SOC_CACHE_APP_LOW // Check if in APP cache region - blt a3, a4, .LS_wrong_opcode - movi a4, SOC_CACHE_APP_HIGH - bge a3, a4, .LS_wrong_opcode - j 2f - -1: - movi a4, SOC_IRAM_HIGH // End of IRAM address range - bge a3, a4, .LS_wrong_opcode - -2: - /* Examine the opcode which generated the exception */ - /* Note: Instructions are in this order to avoid pipeline stalls. */ - rsr a2, epc1 - movi a4, ~3 - ssa8l a2 // sar is now correct shift for aligned read - and a2, a2, a4 // a2 now 4-byte aligned address of instruction - l32i a4, a2, 0 - l32i a2, a2, 4 - - src a2, a2, a4 // a2 now instruction that failed - bbci a2, 1, .LS_wrong_opcode - bbsi a2, 14, .LSE_store_op // Store instruction - - /* l8/l16ui/l16si */ - movi a4, ~3 - and a4, a3, a4 // a4 now word aligned read address - - ssa8l a3 // sar is now shift to extract a3's byte - l32i a4, a4, 0 // perform the actual read - srl a4, a4 // shift right correct distance - extui a3, a2, 12, 4 - bnez a3, 1f // l16ui/l16si - extui a4, a4, 0, 8 // mask off bits needed for an l8 - j 2f - -1: - extui a4, a4, 0, 16 - bbci a2, 15, 2f // l16ui - - /* Sign adjustment */ - slli a4, a4, 16 - srai a4, a4, 16 // a4 contains the value - -2: - /* a4 contains the value */ - rsr a3, epc1 - addi a3, a3, 3 - wsr a3, epc1 - wsr a0, sar - rsr a0, excsave1 - - extui a2, a2, 3, 5 - blti a2, 10, .LSE_stack_reg - - movi a3, .LS_jumptable_base - addx8 a2, a2, a3 // a2 is now the address to jump to - l32i a3, sp, 0x0c - jx a2 - -.LSE_stack_reg: - addx2 a2, a2, sp - s32i a4, a2, 0 - - /* Restore all values */ - l32i a4, sp, 0x10 - l32i a3, sp, 0x0c - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - -.LSE_store_op: - s32i a5, a1, 0x14 - s32i a6, a1, 0x18 - - /* a2 -> instruction that caused the error */ - /* a3 -> unaligned address */ - extui a4, a2, 4, 4 - blti a4, 7, 1f - movi a5, .LSE_store_reg - addx8 a5, a4, a5 - jx a5 - -1: - addx4 a4, a4, sp - l32i a4, a4, 0 - -.LSE_store_data: - /* a4 contains the value */ - rsr a6, epc1 - addi a6, a6, 3 - wsr a6, epc1 - - ssa8b a3 - movi a5, -1 - bbsi a2, 12, 1f // s16 - extui a4, a4, 0, 8 - movi a6, 0xff - j 2f -1: - extui a4, a4, 0, 16 - movi a6, 0xffff -2: - sll a4, a4 // shift the value to proper offset - sll a6, a6 - xor a5, a5, a6 // a5 contains the mask - - movi a6, ~3 - and a3, a3, a6 // a3 has the aligned address - l32i a6, a3, 0 // a6 contains the data at the aligned address - and a6, a6, a5 - or a4, a6, a4 - s32i a4, a3, 0 - - /* Restore registers */ - wsr a0, sar - - l32i a6, sp, 0x18 - l32i a5, sp, 0x14 - l32i a4, sp, 0x10 - l32i a3, sp, 0x0c - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rsr a0, excsave1 - - rfe - -.LSE_store_reg: - .org .LSE_store_reg + (7 * 8) - mov a4, a7 - j .LSE_store_data - - .org .LSE_store_reg + (8 * 8) - mov a4, a8 - j .LSE_store_data - - .org .LSE_store_reg + (9 * 8) - mov a4, a9 - j .LSE_store_data - - .org .LSE_store_reg + (10 * 8) - mov a4, a10 - j .LSE_store_data - - .org .LSE_store_reg + (11 * 8) - mov a4, a11 - j .LSE_store_data - - .org .LSE_store_reg + (12 * 8) - mov a4, a12 - j .LSE_store_data - - .org .LSE_store_reg + (13 * 8) - mov a4, a13 - j .LSE_store_data - - .org .LSE_store_reg + (14 * 8) - mov a4, a14 - j .LSE_store_data - - .org .LSE_store_reg + (15 * 8) - mov a4, a15 - j .LSE_store_data - - -/* LoadStoreAlignmentCause handler: - * - * Completes unaligned 16-bit and 32-bit load/store instructions from 32-bit aligned memory region - * Called from UserExceptionVector if EXCCAUSE is LoadStoreAlignmentCause - */ - - .global AlignmentErrorHandler - .section .iram1, "ax" - - .literal_position - - .balign 4 -AlignmentErrorHandler: - .type AlignmentErrorHandler, @function - - wsr a0, depc // Save return address in depc - mov a0, sp - movi sp, LoadStoreHandlerStack - s32i a0, sp, 0x04 // Since a0 contains value of a1 - s32i a2, sp, 0x08 - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - - rsr a0, sar // Save SAR in a0 to restore later - - /* Check whether the address lies in the valid range */ - rsr a3, excvaddr - movi a4, _iram_text_end // End of code section of IRAM - bge a3, a4, 1f - movi a4, SOC_CACHE_APP_LOW // Check if in APP cache region - blt a3, a4, .LS_wrong_opcode - movi a4, SOC_CACHE_APP_HIGH - bge a3, a4, .LS_wrong_opcode - j 2f - -1: - movi a4, SOC_IRAM_HIGH // End of IRAM address range - bge a3, a4, .LS_wrong_opcode - -2: - /* Examine the opcode which generated the exception */ - /* Note: Instructions are in this order to avoid pipeline stalls. */ - rsr a2, epc1 - movi a4, ~3 - ssa8l a2 // sar is now correct shift for aligned read - and a2, a2, a4 // a2 now 4-byte aligned address of instruction - l32i a4, a2, 0 - l32i a2, a2, 4 - - /* a2 has the instruction that caused the error */ - src a2, a2, a4 - extui a4, a2, 0, 4 - addi a4, a4, -9 - beqz a4, .LSA_store_op - bbsi a2, 14, .LSA_store_op - - ssa8l a3 // a3 contains the unaligned address - movi a4, ~3 - and a4, a3, a4 // a4 has the aligned address - l32i a3, a4, 0 - l32i a4, a4, 4 - src a4, a4, a3 - - rsr a3, epc1 - addi a3, a3, 2 - bbsi a2, 3, 1f // l32i.n - bbci a2, 1, .LS_wrong_opcode - addi a3, a3, 1 - - bbsi a2, 13, 1f // l32 - extui a4, a4, 0, 16 - bbci a2, 15, 1f // l16ui - - /* Sign adjustment */ - slli a4, a4, 16 - srai a4, a4, 16 // a4 contains the value - -1: - wsr a3, epc1 - wsr a0, sar - rsr a0, excsave1 - - extui a2, a2, 4, 4 - blti a2, 5, .LSA_stack_reg // a3 contains the target register - - movi a3, .LS_jumptable_base - slli a2, a2, 4 - add a2, a2, a3 // a2 is now the address to jump to - l32i a3, sp, 0x0c - jx a2 - -.LSA_stack_reg: - addx4 a2, a2, sp - s32i a4, a2, 0 - - /* Restore all values */ - l32i a4, sp, 0x10 - l32i a3, sp, 0x0c - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - -/* Store instruction */ -.LSA_store_op: - s32i a5, sp, 0x14 - s32i a6, sp, 0x18 - s32i a7, sp, 0x1c - - /* a2 -> instruction that caused the error */ - /* a3 -> unaligned address */ - extui a4, a2, 4, 4 - blti a4, 8, 1f - movi a5, .LSA_store_reg - addx8 a5, a4, a5 - jx a5 - -1: - addx4 a4, a4, sp - l32i a4, a4, 0 // a4 contains the value - -.LSA_store_data: - movi a6, 0 - - rsr a7, epc1 - addi a7, a7 ,2 - bbsi a2, 3, 1f // s32i.n - bbci a2, 1, .LS_wrong_opcode - - addi a7, a7, 1 - bbsi a2, 13, 1f // s32i - - movi a5, -1 - extui a4, a4, 0, 16 - slli a6, a5, 16 // 0xffff0000 - -1: - wsr a7, epc1 - movi a5, ~3 - and a5, a3, a5 // a5 has the aligned address - - ssa8b a3 - movi a3, -1 - src a7, a6, a3 - src a3, a3, a6 - - /* Store data on lower address */ - l32i a6, a5, 0 - and a6, a6, a7 - sll a7, a4 - or a6, a6, a7 - s32i a6, a5, 0 - - /* Store data on higher address */ - l32i a7, a5, 4 - srl a6, a4 - and a3, a7, a3 - or a3, a3, a6 - s32i a3, a5, 4 - - /* Restore registers */ - wsr a0, sar - rsr a0, excsave1 - - l32i a7, sp, 0x1c - l32i a6, sp, 0x18 - l32i a5, sp, 0x14 - l32i a4, sp, 0x10 - l32i a3, sp, 0x0c - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - -.LSA_store_reg: - .org .LSA_store_reg + (8 * 8) - mov a4, a8 - j .LSA_store_data - - .org .LSA_store_reg + (9 * 8) - mov a4, a9 - j .LSA_store_data - - .org .LSA_store_reg + (10 * 8) - mov a4, a10 - j .LSA_store_data - - .org .LSA_store_reg + (11 * 8) - mov a4, a11 - j .LSA_store_data - - .org .LSA_store_reg + (12 * 8) - mov a4, a12 - j .LSA_store_data - - .org .LSA_store_reg + (13 * 8) - mov a4, a13 - j .LSA_store_data - - .org .LSA_store_reg + (14 * 8) - mov a4, a14 - j .LSA_store_data - - .org .LSA_store_reg + (15 * 8) - mov a4, a15 - j .LSA_store_data - -/* - * Common routines for both the exception handlers - */ - .balign 4 -.LS_jumptable: - /* The first 5 entries (80 bytes) of this table are unused (registers - a0..a4 are handled separately above). Rather than have a whole bunch - of wasted space, just pretend that the table starts 80 bytes - earlier in memory. */ - .set .LS_jumptable_base, .LS_jumptable - (16 * 5) - - .org .LS_jumptable_base + (16 * 5) - mov a5, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 6) - mov a6, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 7) - mov a7, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 8) - mov a8, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 9) - mov a9, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 10) - mov a10, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 11) - mov a11, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 12) - mov a12, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 13) - mov a13, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 14) - mov a14, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - - .org .LS_jumptable_base + (16 * 15) - mov a15, a4 - l32i a4, sp, 0x10 - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rfe - -.LS_wrong_opcode: - /* Reaches here if the address is in invalid range or the opcode isn't supported. - * Restore registers and jump back to _xt_user_exc - */ - wsr a0, sar - l32i a4, sp, 0x10 - l32i a3, sp, 0x0c - l32i a2, sp, 0x08 - l32i a1, sp, 0x04 - rsr a0, depc - ret // Equivalent to jx a0 diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S deleted file mode 100644 index d0eaef4140..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S +++ /dev/null @@ -1,2209 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc. - * - * SPDX-License-Identifier: MIT - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Copyright (c) 2015-2019 Cadence Design Systems, Inc. - * - * 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. - */ - -/* - XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS - - Xtensa low level exception and interrupt vectors and handlers for an RTOS. - - Interrupt handlers and user exception handlers support interaction with - the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and - after user's specific interrupt handlers. These macros are defined in - xtensa_.h to call suitable functions in a specific RTOS. - - Users can install application-specific interrupt handlers for low and - medium level interrupts, by calling xt_set_interrupt_handler(). These - handlers can be written in C, and must obey C calling convention. The - handler table is indexed by the interrupt number. Each handler may be - provided with an argument. - - Note that the system timer interrupt is handled specially, and is - dispatched to the RTOS-specific handler. This timer cannot be hooked - by application code. - - Optional hooks are also provided to install a handler per level at - run-time, made available by compiling this source file with - '-DXT_INTEXC_HOOKS' (useful for automated testing). - -!! This file is a template that usually needs to be modified to handle !! -!! application specific interrupts. Search USER_EDIT for helpful comments !! -!! on where to insert handlers and how to write them. !! - - Users can also install application-specific exception handlers in the - same way, by calling xt_set_exception_handler(). One handler slot is - provided for each exception type. Note that some exceptions are handled - by the porting layer itself, and cannot be taken over by application - code in this manner. These are the alloca, syscall, and coprocessor - exceptions. - - The exception handlers can be written in C, and must follow C calling - convention. Each handler is passed a pointer to an exception frame as - its single argument. The exception frame is created on the stack, and - holds the saved context of the thread that took the exception. If the - handler returns, the context will be restored and the instruction that - caused the exception will be retried. If the handler makes any changes - to the saved state in the exception frame, the changes will be applied - when restoring the context. - - Because Xtensa is a configurable architecture, this port supports all user - generated configurations (except restrictions stated in the release notes). - This is accomplished by conditional compilation using macros and functions - defined in the Xtensa HAL (hardware adaptation layer) for your configuration. - Only the relevant parts of this file will be included in your RTOS build. - For example, this file provides interrupt vector templates for all types and - all priority levels, but only the ones in your configuration are built. - - NOTES on the use of 'call0' for long jumps instead of 'j': - 1. This file should be assembled with the -mlongcalls option to xt-xcc. - 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to - a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the - distance from the call to the destination. The linker then relaxes - it back to 'call0 dest' if it determines that dest is within range. - This allows more flexibility in locating code without the performance - overhead of the 'l32r' literal data load in cases where the destination - is in range of 'call0'. There is an additional benefit in that 'call0' - has a longer range than 'j' due to the target being word-aligned, so - the 'l32r' sequence is less likely needed. - 3. The use of 'call0' with -mlongcalls requires that register a0 not be - live at the time of the call, which is always the case for a function - call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'. - 4. This use of 'call0' is independent of the C function call ABI. - - */ - -#include "xtensa_rtos.h" -#include "esp_private/panic_reason.h" -#include "sdkconfig.h" -#include "soc/soc.h" -#include "xt_asm_utils.h" - - -/* --------------------------------------------------------------------------------- - In order for backtracing to be able to trace from the pre-exception stack - across to the exception stack (including nested interrupts), we need to create - a pseudo base-save area to make it appear like the exception dispatcher was - triggered by a CALL4 from the pre-exception code. In reality, the exception - dispatcher uses the same window as pre-exception code, and only CALL0s are - used within the exception dispatcher. - - To create the pseudo base-save area, we need to store a copy of the pre-exception's - base save area (a0 to a4) below the exception dispatcher's SP. EXCSAVE_x will - be used to store a copy of the SP that points to the interrupted code's exception - frame just in case the exception dispatcher's SP does not point to the exception - frame (which is the case when switching from task to interrupt stack). - - Clearing the pseudo base-save area is uncessary as the interrupt dispatcher - will restore the current SP to that of the pre-exception SP. --------------------------------------------------------------------------------- -*/ -#ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE -#define XT_DEBUG_BACKTRACE 1 -#endif - - -/* --------------------------------------------------------------------------------- - Defines used to access _xtos_interrupt_table. --------------------------------------------------------------------------------- -*/ -#define XIE_HANDLER 0 -#define XIE_ARG 4 -#define XIE_SIZE 8 - - -/* - Macro get_percpu_entry_for - convert a per-core ID into a multicore entry. - Basically does reg=reg*portNUM_PROCESSORS+current_core_id - Multiple versions here to optimize for specific portNUM_PROCESSORS values. -*/ - .macro get_percpu_entry_for reg scratch -#if (portNUM_PROCESSORS == 1) - /* No need to do anything */ -#elif (portNUM_PROCESSORS == 2) - /* Optimized 2-core code. */ - getcoreid \scratch - addx2 \reg,\reg,\scratch -#else - /* Generalized n-core code. Untested! */ - movi \scratch,portNUM_PROCESSORS - mull \scratch,\reg,\scratch - getcoreid \reg - add \reg,\scratch,\reg -#endif - .endm -/* --------------------------------------------------------------------------------- - Macro extract_msb - return the input with only the highest bit set. - - Input : "ain" - Input value, clobbered. - Output : "aout" - Output value, has only one bit set, MSB of "ain". - The two arguments must be different AR registers. --------------------------------------------------------------------------------- -*/ - - .macro extract_msb aout ain -1: - addi \aout, \ain, -1 /* aout = ain - 1 */ - and \ain, \ain, \aout /* ain = ain & aout */ - bnez \ain, 1b /* repeat until ain == 0 */ - addi \aout, \aout, 1 /* return aout + 1 */ - .endm - -/* --------------------------------------------------------------------------------- - Macro dispatch_c_isr - dispatch interrupts to user ISRs. - This will dispatch to user handlers (if any) that are registered in the - XTOS dispatch table (_xtos_interrupt_table). These handlers would have - been registered by calling _xtos_set_interrupt_handler(). There is one - exception - the timer interrupt used by the OS will not be dispatched - to a user handler - this must be handled by the caller of this macro. - - Level triggered and software interrupts are automatically deasserted by - this code. - - ASSUMPTIONS: - -- PS.INTLEVEL is set to "level" at entry - -- PS.EXCM = 0, C calling enabled - - NOTE: For CALL0 ABI, a12-a15 have not yet been saved. - - NOTE: This macro will use registers a0 and a2-a6. The arguments are: - level -- interrupt level - mask -- interrupt bitmask for this level --------------------------------------------------------------------------------- -*/ - - .macro dispatch_c_isr level mask - - #ifdef CONFIG_PM_TRACE - movi a6, 0 /* = ESP_PM_TRACE_IDLE */ - getcoreid a7 - call4 esp_pm_trace_exit - #endif // CONFIG_PM_TRACE - - /* Get mask of pending, enabled interrupts at this level into a2. */ - -.L_xt_user_int_\level : - rsr a2, INTENABLE - rsr a3, INTERRUPT - movi a4, \mask - and a2, a2, a3 - and a2, a2, a4 - beqz a2, 9f /* nothing to do */ - - /* This bit of code provides a nice debug backtrace in the debugger. - It does take a few more instructions, so undef XT_DEBUG_BACKTRACE - if you want to save the cycles. - At this point, the exception frame should have been allocated and filled, - and current sp points to the interrupt stack (for non-nested interrupt) - or below the allocated exception frame (for nested interrupts). Copy the - pre-exception's base save area below the current SP. - */ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - rsr a0, EXCSAVE_1 + \level - 1 /* Get exception frame pointer stored in EXCSAVE_x */ - l32i a3, a0, XT_STK_A0 /* Copy pre-exception a0 (return address) */ - s32e a3, a1, -16 - l32i a3, a0, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */ - s32e a3, a1, -12 - /* Backtracing only needs a0 and a1, no need to create full base save area. - Also need to change current frame's return address to point to pre-exception's - last run instruction. - */ - rsr a0, EPC_1 + \level - 1 /* return address */ - movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ - or a0, a0, a4 /* set top 2 bits */ - addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ - #endif - #endif - - #ifdef CONFIG_PM_ENABLE - call4 esp_pm_impl_isr_hook - #endif - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a4, _xt_intexc_hooks - l32i a4, a4, \level << 2 - beqz a4, 2f - #ifdef __XTENSA_CALL0_ABI__ - callx0 a4 - beqz a2, 9f - #else - mov a6, a2 - callx4 a4 - beqz a6, 9f - mov a2, a6 - #endif -2: - #endif - - /* Now look up in the dispatch table and call user ISR if any. */ - /* If multiple bits are set then MSB has highest priority. */ - - extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ - - #ifdef XT_USE_SWPRI - /* Enable all interrupts at this level that are numerically higher - than the one we just selected, since they are treated as higher - priority. - */ - movi a3, \mask /* a3 = all interrupts at this level */ - add a2, a4, a4 /* a2 = a4 << 1 */ - addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */ - and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */ - movi a3, _xt_intdata - l32i a6, a3, 4 /* a6 = _xt_vpri_mask */ - neg a2, a2 - addi a2, a2, -1 /* a2 = mask to apply */ - and a5, a6, a2 /* mask off all bits <= a4 bit */ - s32i a5, a3, 4 /* update _xt_vpri_mask */ - rsr a3, INTENABLE - and a3, a3, a2 /* mask off all bits <= a4 bit */ - wsr a3, INTENABLE - rsil a3, \level - 1 /* lower interrupt level by 1 */ - #endif - - #ifdef XT_RTOS_TIMER_INT - movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ - wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ - beq a3, a4, 7f /* if timer interrupt then skip table */ - #else - wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ - #endif // XT_RTOS_TIMER_INT - - find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ - - get_percpu_entry_for a3, a12 - movi a4, _xt_interrupt_table - addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ - l32i a4, a3, XIE_HANDLER /* a4 = handler address */ - #ifdef __XTENSA_CALL0_ABI__ - mov a12, a6 /* save in callee-saved reg */ - l32i a2, a3, XIE_ARG /* a2 = handler arg */ - callx0 a4 /* call handler */ - mov a2, a12 - #else - mov a2, a6 /* save in windowed reg */ - l32i a6, a3, XIE_ARG /* a6 = handler arg */ - callx4 a4 /* call handler */ - #endif - - #ifdef XT_USE_SWPRI - j 8f - #else - j .L_xt_user_int_\level /* check for more interrupts */ - #endif - - #ifdef XT_RTOS_TIMER_INT -7: - - .ifeq XT_TIMER_INTPRI - \level -.L_xt_user_int_timer_\level : - /* - Interrupt handler for the RTOS tick timer if at this level. - We'll be reading the interrupt state again after this call - so no need to preserve any registers except a6 (vpri_mask). - */ - - #ifdef __XTENSA_CALL0_ABI__ - mov a12, a6 - call0 XT_RTOS_TIMER_INT - mov a2, a12 - #else - mov a2, a6 - call4 XT_RTOS_TIMER_INT - #endif - .endif - #endif // XT_RTOS_TIMER_INT - - #ifdef XT_USE_SWPRI - j 8f - #else - j .L_xt_user_int_\level /* check for more interrupts */ - #endif - - #ifdef XT_USE_SWPRI -8: - /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from - virtual _xt_intenable which _could_ have changed during interrupt - processing. */ - - movi a3, _xt_intdata - l32i a4, a3, 0 /* a4 = _xt_intenable */ - s32i a2, a3, 4 /* update _xt_vpri_mask */ - and a4, a4, a2 /* a4 = masked intenable */ - wsr a4, INTENABLE /* update INTENABLE */ - #endif - -9: - /* done */ - - .endm - - - .section .rodata, "a" - .align 4 - -/* --------------------------------------------------------------------------------- - Hooks to dynamically install handlers for exceptions and interrupts. - Allows automated regression frameworks to install handlers per test. - Consists of an array of function pointers indexed by interrupt level, - with index 0 containing the entry for user exceptions. - Initialized with all 0s, meaning no handler is installed at each level. - See comment in xtensa_rtos.h for more details. - - *WARNING* This array is for all CPUs, that is, installing a hook for - one CPU will install it for all others as well! --------------------------------------------------------------------------------- -*/ - - #ifdef XT_INTEXC_HOOKS - .data - .global _xt_intexc_hooks - .type _xt_intexc_hooks,@object - .align 4 - -_xt_intexc_hooks: - .fill XT_INTEXC_HOOK_NUM, 4, 0 - #endif - - -/* --------------------------------------------------------------------------------- - EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS - (except 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 XT_RTOS_INT_ENTER to save the rest of the interrupted context - and enter the RTOS, then sets up a C environment. It then calls the - user's interrupt handler code (which may be coded in C) and finally - calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. - - While XT_RTOS_INT_EXIT does not return directly to the interruptee, - eventually the RTOS scheduler will want to dispatch the interrupted - task or handler. The scheduler will return to the exit point that was - saved in the interrupt stack frame at XT_STK_EXIT. --------------------------------------------------------------------------------- -*/ - - -/* --------------------------------------------------------------------------------- -Debug Exception. --------------------------------------------------------------------------------- -*/ - -#if XCHAL_HAVE_DEBUG - - .begin literal_prefix .DebugExceptionVector - .section .DebugExceptionVector.text, "ax" - .global _DebugExceptionVector - .align 4 - .global xt_debugexception -_DebugExceptionVector: - wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* preserve a0 */ - call0 xt_debugexception /* load exception handler */ - - .end literal_prefix - - .global xt_debugexception - .weak xt_debugexception - .set xt_debugexception, _xt_debugexception - .section .iram1,"ax" - .type _xt_debugexception,@function - .align 4 -_xt_debugexception: -#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) -#define XT_DEBUGCAUSE_DI (5) - getcoreid a0 -#if (CONFIG_BTDM_CTRL_PINNED_TO_CORE == PRO_CPU_NUM) - beqz a0, 1f -#else - bnez a0, 1f -#endif - - rsr a0, DEBUGCAUSE - extui a0, a0, XT_DEBUGCAUSE_DI, 1 - bnez a0, _xt_debug_di_exc -1: -#endif //(CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) - - movi a0,PANIC_RSN_DEBUGEXCEPTION - wsr a0,EXCCAUSE - /* _xt_panic assumes a level 1 exception. As we're - crashing anyhow, copy EPC & EXCSAVE from DEBUGLEVEL - to level 1. */ - rsr a0,(EPC + XCHAL_DEBUGLEVEL) - wsr a0,EPC_1 - rsr a0,(EXCSAVE + XCHAL_DEBUGLEVEL) - wsr a0,EXCSAVE_1 - call0 _xt_panic /* does not return */ - rfi XCHAL_DEBUGLEVEL - -#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) - .align 4 -_xt_debug_di_exc: - - /* - The delay time can be calculated by the following formula: - T = ceil(0.25 + max(t1, t2)) us - - t1 = 80 / f1, t2 = (1 + 14/N) * 20 / f2 - - f1: PSRAM access frequency, unit: MHz. - f2: Flash access frequency, unit: MHz. - - When flash is slow/fast read, N = 1. - When flash is DOUT/DIO read, N = 2. - When flash is QOUT/QIO read, N = 4. - - And after testing, when CPU frequency is 240 MHz, it will take 1us to loop 27 times. - */ -#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT) - -# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M) - movi a0, 54 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 81 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 81 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 108 -# else - movi a0, 135 -# endif - -#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT) - -# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M) - movi a0, 81 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 81 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 135 -# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M) - movi a0, 189 -# else - movi a0, 243 -# endif - -#else - movi a0, 243 -#endif - -1: addi a0, a0, -1 /* delay_us(N) */ - .rept 4 - nop - .endr - bnez a0, 1b - - rsr a0, EXCSAVE+XCHAL_DEBUGLEVEL - rfi XCHAL_DEBUGLEVEL -#endif //(CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) -#endif // XCHAL_HAVE_DEBUG - -/* --------------------------------------------------------------------------------- -Double Exception. -Double exceptions are not a normal occurrence. They indicate a bug of some kind. --------------------------------------------------------------------------------- -*/ - -#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR - - .begin literal_prefix .DoubleExceptionVector - .section .DoubleExceptionVector.text, "ax" - .global _DoubleExceptionVector - .align 4 - -_DoubleExceptionVector: - - #if XCHAL_HAVE_DEBUG - break 1, 4 /* unhandled double exception */ - #endif - movi a0,PANIC_RSN_DOUBLEEXCEPTION - wsr a0,EXCCAUSE - call0 _xt_panic /* does not return */ - rfde /* make a0 point here not later */ - - .end literal_prefix - -#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ - -/* --------------------------------------------------------------------------------- -Kernel Exception (including Level 1 Interrupt from kernel mode). --------------------------------------------------------------------------------- -*/ - - .begin literal_prefix .KernelExceptionVector - .section .KernelExceptionVector.text, "ax" - .global _KernelExceptionVector - .align 4 - -_KernelExceptionVector: - - wsr a0, EXCSAVE_1 /* preserve a0 */ - call0 _xt_kernel_exc /* kernel exception handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .section .iram1,"ax" - .align 4 - -_xt_kernel_exc: - #if XCHAL_HAVE_DEBUG - break 1, 0 /* unhandled kernel exception */ - #endif - movi a0,PANIC_RSN_KERNELEXCEPTION - wsr a0,EXCCAUSE - call0 _xt_panic /* does not return */ - rfe /* make a0 point here not there */ - - -/* --------------------------------------------------------------------------------- -User Exception (including Level 1 Interrupt from user mode). --------------------------------------------------------------------------------- -*/ - - .begin literal_prefix .UserExceptionVector - .section .UserExceptionVector.text, "ax" - .global _UserExceptionVector - .type _UserExceptionVector,@function - .align 4 - -_UserExceptionVector: - - wsr a0, EXCSAVE_1 /* preserve a0 */ - call0 _xt_user_exc /* user exception handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - -/* --------------------------------------------------------------------------------- - Insert some waypoints for jumping beyond the signed 8-bit range of - conditional branch instructions, so the conditional branchces to specific - exception handlers are not taken in the mainline. Saves some cycles in the - mainline. --------------------------------------------------------------------------------- -*/ - -#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY - .global LoadStoreErrorHandler - .global AlignmentErrorHandler -#endif - - .section .iram1,"ax" - - #if XCHAL_HAVE_WINDOWED - .align 4 -_xt_to_alloca_exc: - call0 _xt_alloca_exc /* in window vectors section */ - /* never returns here - call0 is used as a jump (see note at top) */ - #endif - - .align 4 -_xt_to_syscall_exc: - call0 _xt_syscall_exc - /* never returns here - call0 is used as a jump (see note at top) */ - - #if XCHAL_CP_NUM > 0 - .align 4 -_xt_to_coproc_exc: - call0 _xt_coproc_exc - /* never returns here - call0 is used as a jump (see note at top) */ - #endif - -#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY - .align 4 -_call_loadstore_handler: - call0 LoadStoreErrorHandler - /* This will return only if wrong opcode or address out of range*/ - j .LS_exit - - .align 4 -_call_alignment_handler: - call0 AlignmentErrorHandler - /* This will return only if wrong opcode or address out of range*/ - addi a0, a0, 1 - j .LS_exit -#endif - -/* --------------------------------------------------------------------------------- - User exception handler. --------------------------------------------------------------------------------- -*/ - - .type _xt_user_exc,@function - .align 4 - -_xt_user_exc: - - /* If level 1 interrupt then jump to the dispatcher */ - rsr a0, EXCCAUSE - beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 - - /* Handle any coprocessor exceptions. Rely on the fact that exception - numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. - */ - #if XCHAL_CP_NUM > 0 - bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc - #endif - - /* Handle alloca and syscall exceptions */ - #if XCHAL_HAVE_WINDOWED - beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc - #endif - beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc - -#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY - beqi a0, EXCCAUSE_LOAD_STORE_ERROR, _call_loadstore_handler - - addi a0, a0, -1 - beqi a0, 8, _call_alignment_handler - addi a0, a0, 1 -.LS_exit: -#endif - - /* 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. */ - mov a0, sp - addi sp, sp, -XT_STK_FRMSZ - s32i a0, sp, XT_STK_A1 - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -12 /* for debug backtrace */ - #endif - rsr a0, PS /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_1 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -16 /* for debug backtrace */ - #endif - s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ - s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ - call0 _xt_context_save - - /* Save exc cause and vaddr into exception frame */ - rsr a0, EXCCAUSE - s32i a0, sp, XT_STK_EXCCAUSE - rsr a0, EXCVADDR - s32i a0, sp, XT_STK_EXCVADDR - - /* Set up PS for C, reenable debug and NMI interrupts, and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(XCHAL_DEBUGLEVEL - 2) | PS_UM - #else - movi a0, PS_INTLEVEL(XCHAL_DEBUGLEVEL - 2) | PS_UM | PS_WOE - #endif - wsr a0, PS - - /* - Create pseudo base save area. At this point, sp is still pointing to the - allocated and filled exception stack frame. - */ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - l32i a3, sp, XT_STK_A0 /* Copy pre-exception a0 (return address) */ - s32e a3, sp, -16 - l32i a3, sp, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */ - s32e a3, sp, -12 - rsr a0, EPC_1 /* return address for debug backtrace */ - movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ - rsync /* wait for WSR.PS to complete */ - or a0, a0, a5 /* set top 2 bits */ - addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */ - #else - rsync /* wait for WSR.PS to complete */ - #endif - #endif - - rsr a2, EXCCAUSE /* recover exc cause */ - - #ifdef XT_INTEXC_HOOKS - /* - Call exception hook to pre-handle exceptions (if installed). - Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). - */ - movi a4, _xt_intexc_hooks - l32i a4, a4, 0 /* user exception hook index 0 */ - beqz a4, 1f -.Ln_xt_user_exc_call_hook: - #ifdef __XTENSA_CALL0_ABI__ - callx0 a4 - beqi a2, -1, .L_xt_user_done - #else - mov a6, a2 - callx4 a4 - beqi a6, -1, .L_xt_user_done - mov a2, a6 - #endif -1: - #endif - - rsr a2, EXCCAUSE /* recover exc cause */ - movi a3, _xt_exception_table - get_percpu_entry_for a2, a4 - addx4 a4, a2, a3 /* a4 = address of exception table entry */ - l32i a4, a4, 0 /* a4 = handler address */ - #ifdef __XTENSA_CALL0_ABI__ - mov a2, sp /* a2 = pointer to exc frame */ - callx0 a4 /* call handler */ - #else - mov a6, sp /* a6 = pointer to exc frame */ - callx4 a4 /* call handler */ - #endif - -.L_xt_user_done: - - /* Restore context and return */ - call0 _xt_context_restore - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, PS - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_1 - 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 */ - rfe /* PS.EXCM is cleared */ - - -/* --------------------------------------------------------------------------------- - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. --------------------------------------------------------------------------------- -*/ - - .global _xt_user_exit - .type _xt_user_exit,@function - .align 4 -_xt_user_exit: - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, PS - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_1 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure PS and EPC written */ - rfe /* PS.EXCM is cleared */ - - -/* - --------------------------------------------------------------------------------- -Syscall Exception Handler (jumped to from User Exception Handler). -Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). -Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. --------------------------------------------------------------------------------- -*/ - - .section .iram1,"ax" - .type _xt_syscall_exc,@function - .align 4 -_xt_syscall_exc: - - #ifdef __XTENSA_CALL0_ABI__ - /* - Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. - Use a minimal stack frame (16B) to save A2 & A3 for scratch. - PS.EXCM could be cleared here, but unlikely to improve worst-case latency. - rsr a0, PS - addi a0, a0, -PS_EXCM_MASK - wsr a0, PS - */ - addi sp, sp, -16 - s32i a2, sp, 8 - s32i a3, sp, 12 - #else /* Windowed ABI */ - /* - Save necessary context and spill the register windows. - PS.EXCM is still set and must remain set until after the spill. - Reuse context save function though it saves more than necessary. - For this reason, a full interrupt stack frame is allocated. - */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ - s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ - call0 _xt_context_save - #endif - - /* - Grab the interruptee's PC and skip over the 'syscall' instruction. - If it's at the end of a zero-overhead loop and it's not on the last - iteration, decrement loop counter and skip to beginning of loop. - */ - rsr a2, EPC_1 /* a2 = PC of 'syscall' */ - addi a3, a2, 3 /* ++PC */ - #if XCHAL_HAVE_LOOPS - rsr a0, LEND /* if (PC == LEND */ - bne a3, a0, 1f - rsr a0, LCOUNT /* && LCOUNT != 0) */ - beqz a0, 1f /* { */ - addi a0, a0, -1 /* --LCOUNT */ - rsr a3, LBEG /* PC = LBEG */ - wsr a0, LCOUNT /* } */ - #endif -1: wsr a3, EPC_1 /* update PC */ - - /* Restore interruptee's context and return from exception. */ - #ifdef __XTENSA_CALL0_ABI__ - l32i a2, sp, 8 - l32i a3, sp, 12 - addi sp, sp, 16 - #else - call0 _xt_context_restore - addi sp, sp, XT_STK_FRMSZ - #endif - movi a0, -1 - movnez a2, a0, a2 /* return -1 if not syscall 0 */ - rsr a0, EXCSAVE_1 - rfe - -/* --------------------------------------------------------------------------------- -Co-Processor Exception Handler (jumped to from User Exception Handler). -These exceptions are generated by co-processor instructions, which are only -allowed in thread code (not in interrupts or kernel code). This restriction is -deliberately imposed to reduce the burden of state-save/restore in interrupts. --------------------------------------------------------------------------------- -*/ -#if XCHAL_CP_NUM > 0 - - .section .rodata, "a" - -/* Offset to CP n save area in thread's CP save area. */ - .global _xt_coproc_sa_offset - .type _xt_coproc_sa_offset,@object - .align 16 /* minimize crossing cache boundaries */ -_xt_coproc_sa_offset: - .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA - .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA - -/* Bitmask for CP n's CPENABLE bit. */ - .type _xt_coproc_mask,@object - .align 16,,8 /* try to keep it all in one cache line */ - .set i, 0 -_xt_coproc_mask: - .rept XCHAL_CP_MAX - .long (i<<16) | (1< 1 - .global _xt_coproc_owner_sa_lock - .type _xt_coproc_owner_sa_lock,@object - .align 16 /* minimize crossing cache boundaries */ -_xt_coproc_owner_sa_lock: - .space 4 -#endif /* portNUM_PROCESSORS > 1 */ - - .section .iram1,"ax" - .align 4 -.L_goto_invalid: - j .L_xt_coproc_invalid /* not in a thread (invalid) */ - .align 4 -.L_goto_done: - j .L_xt_coproc_done - - -/* --------------------------------------------------------------------------------- - Coprocessor exception handler. - At entry, only a0 has been saved (in EXCSAVE_1). --------------------------------------------------------------------------------- -*/ - - .type _xt_coproc_exc,@function - .align 4 - -_xt_coproc_exc: - - /* Allocate interrupt stack frame and save minimal context. */ - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -12 /* for debug backtrace */ - #endif - rsr a0, PS /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_1 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -16 /* for debug backtrace */ - #endif - movi a0, _xt_user_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - rsr a0, EXCCAUSE - s32i a5, sp, XT_STK_A5 /* save a5 */ - addi a5, a0, -EXCCAUSE_CP0_DISABLED /* a5 = CP index */ - - /* Save a few more of interruptee's registers (a5 was already saved). */ - s32i a2, sp, XT_STK_A2 - s32i a3, sp, XT_STK_A3 - s32i a4, sp, XT_STK_A4 - s32i a15, sp, XT_STK_A15 - - /* Call the RTOS coprocessor exception hook */ - call0 XT_RTOS_CP_EXC_HOOK - - /* Get co-processor state save area of new owner thread. */ - call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */ - #if !CONFIG_FREERTOS_FPU_IN_ISR - beqz a15, .L_goto_invalid /* not in a thread (invalid) */ - #endif - - /* Enable the co-processor's bit in CPENABLE. */ - movi a0, _xt_coproc_mask - rsr a4, CPENABLE /* a4 = CPENABLE */ - addx4 a0, a5, a0 /* a0 = &_xt_coproc_mask[n] */ - l32i a0, a0, 0 /* a0 = (n << 16) | (1 << n) */ - extui a2, a0, 0, 16 /* coprocessor bitmask portion */ - or a4, a4, a2 /* a4 = CPENABLE | (1 << n) */ - wsr a4, CPENABLE - - /* Grab the xt_coproc_owner_sa owner array for current core */ - getcoreid a3 /* a3 = current core ID */ - movi a2, XCHAL_CP_MAX << 2 /* a2 = size of an owner array */ - mull a2, a2, a3 /* a2 = offset to the owner array of the current core*/ - movi a3, _xt_coproc_owner_sa /* a3 = base of all owner arrays */ - add a3, a3, a2 /* a3 = base of owner array of the current core */ - -#if portNUM_PROCESSORS > 1 - /* If multicore, we must also acquire the _xt_coproc_owner_sa_lock spinlock - * to ensure thread safe access of _xt_coproc_owner_sa between cores. */ - spinlock_take a0 a2 _xt_coproc_owner_sa_lock -#endif /* portNUM_PROCESSORS > 1 */ - - /* Get old coprocessor owner thread (save area ptr) and assign new one. */ - addx4 a3, a5, a3 /* a3 = &_xt_coproc_owner_sa[n] */ - l32i a2, a3, 0 /* a2 = old owner's save area */ - s32i a15, a3, 0 /* _xt_coproc_owner_sa[n] = new */ - rsync /* ensure wsr.CPENABLE is complete */ - -#if portNUM_PROCESSORS > 1 - /* Release previously taken spinlock */ - spinlock_release a0 a2 _xt_coproc_owner_sa_lock -#endif /* portNUM_PROCESSORS > 1 */ - - /* Only need to context switch if new owner != old owner. */ - /* If float is necessary on ISR, we need to remove this check */ - /* below, because on restoring from ISR we may have new == old condition used - * to force cp restore to next thread - * Todo: IDF-6418 - */ - #if !CONFIG_FREERTOS_FPU_IN_ISR - bne a15, a2, .L_switch_context - j .L_goto_done /* new owner == old, we're done */ -.L_switch_context: - #endif - - /* If no old owner then nothing to save. */ - beqz a2, .L_check_new - - /* If old owner not actively using CP then nothing to save. */ - l16ui a4, a2, XT_CPENABLE /* a4 = old owner's CPENABLE */ - bnone a4, a0, .L_check_new /* old owner not using CP */ - -.L_save_old: - /* Save old owner's coprocessor state. */ - - movi a5, _xt_coproc_sa_offset - - /* Mark old owner state as no longer active (CPENABLE bit n clear). */ - xor a4, a4, a0 /* clear CP bit in CPENABLE */ - s16i a4, a2, XT_CPENABLE /* update old owner's CPENABLE */ - - extui a4, a0, 16, 5 /* a4 = CP index = n */ - addx4 a5, a4, a5 /* a5 = &_xt_coproc_sa_offset[n] */ - - /* Mark old owner state as saved (CPSTORED bit n set). */ - l16ui a4, a2, XT_CPSTORED /* a4 = old owner's CPSTORED */ - l32i a5, a5, 0 /* a5 = XT_CP[n]_SA offset */ - or a4, a4, a0 /* set CP in old owner's CPSTORED */ - s16i a4, a2, XT_CPSTORED /* update old owner's CPSTORED */ - l32i a2, a2, XT_CP_ASA /* ptr to actual (aligned) save area */ - extui a3, a0, 16, 5 /* a3 = CP index = n */ - add a2, a2, a5 /* a2 = old owner's area for CP n */ - - /* - The config-specific HAL macro invoked below destroys a2-5, preserves a0-1. - It is theoretically possible for Xtensa processor designers to write TIE - that causes more address registers to be affected, but it is generally - unlikely. If that ever happens, more registers needs to be saved/restored - around this macro invocation, and the value in a15 needs to be recomputed. - */ - xchal_cpi_store_funcbody - -.L_check_new: - /* Check if any state has to be restored for new owner. */ - /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */ - beqz a15, .L_xt_coproc_done - - l16ui a3, a15, XT_CPSTORED /* a3 = new owner's CPSTORED */ - movi a4, _xt_coproc_sa_offset - bnone a3, a0, .L_check_cs /* full CP not saved, check callee-saved */ - xor a3, a3, a0 /* CPSTORED bit is set, clear it */ - s16i a3, a15, XT_CPSTORED /* update new owner's CPSTORED */ - - /* Adjust new owner's save area pointers to area for CP n. */ - extui a3, a0, 16, 5 /* a3 = CP index = n */ - addx4 a4, a3, a4 /* a4 = &_xt_coproc_sa_offset[n] */ - l32i a4, a4, 0 /* a4 = XT_CP[n]_SA */ - l32i a5, a15, XT_CP_ASA /* ptr to actual (aligned) save area */ - add a2, a4, a5 /* a2 = new owner's area for CP */ - - /* - The config-specific HAL macro invoked below destroys a2-5, preserves a0-1. - It is theoretically possible for Xtensa processor designers to write TIE - that causes more address registers to be affected, but it is generally - unlikely. If that ever happens, more registers needs to be saved/restored - around this macro invocation. - */ - xchal_cpi_load_funcbody - - /* Restore interruptee's saved registers. */ - /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */ -.L_xt_coproc_done: - l32i a15, sp, XT_STK_A15 - l32i a5, sp, XT_STK_A5 - l32i a4, sp, XT_STK_A4 - l32i a3, sp, XT_STK_A3 - l32i a2, sp, XT_STK_A2 - call0 _xt_user_exit /* return via exit dispatcher */ - /* Never returns here - call0 is used as a jump (see note at top) */ - -.L_check_cs: - /* a0 = CP mask in low bits, a15 = new owner's save area */ - l16ui a2, a15, XT_CP_CS_ST /* a2 = mask of CPs saved */ - bnone a2, a0, .L_xt_coproc_done /* if no match then done */ - and a2, a2, a0 /* a2 = which CPs to restore */ - extui a2, a2, 0, 8 /* extract low 8 bits */ - s32i a6, sp, XT_STK_A6 /* save extra needed regs */ - s32i a7, sp, XT_STK_A7 - s32i a13, sp, XT_STK_A13 - s32i a14, sp, XT_STK_A14 - call0 _xt_coproc_restorecs /* restore CP registers */ - l32i a6, sp, XT_STK_A6 /* restore saved registers */ - l32i a7, sp, XT_STK_A7 - l32i a13, sp, XT_STK_A13 - l32i a14, sp, XT_STK_A14 - j .L_xt_coproc_done - - /* Co-processor exception occurred outside a thread (not supported). */ -.L_xt_coproc_invalid: - movi a0,PANIC_RSN_COPROCEXCEPTION - wsr a0,EXCCAUSE - call0 _xt_panic /* not in a thread (invalid) */ - /* never returns */ - - -#endif /* XCHAL_CP_NUM */ - - -/* -------------------------------------------------------------------------------- - Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet. -------------------------------------------------------------------------------- -*/ - - .section .iram1,"ax" - .type _xt_lowint1,@function - .align 4 - -_xt_lowint1: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, PS /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_1 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_user_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_1 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_1 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(1) | PS_UM - #else - movi a0, PS_INTLEVEL(1) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - -/* -------------------------------------------------------------------------------- - MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS. - - Medium priority interrupts are by definition those with priority greater - than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by - setting PS.EXCM and therefore can easily support a C environment for - handlers in C, and interact safely with an RTOS. - - 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 XT_RTOS_INT_ENTER to save the rest of the interrupted context - and enter the RTOS, then sets up a C environment. It then calls the - user's interrupt handler code (which may be coded in C) and finally - calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. - - While XT_RTOS_INT_EXIT does not return directly to the interruptee, - eventually the RTOS scheduler will want to dispatch the interrupted - task or handler. The scheduler will return to the exit point that was - saved in the interrupt stack frame at XT_STK_EXIT. -------------------------------------------------------------------------------- -*/ - -#if XCHAL_EXCM_LEVEL >= 2 - - .begin literal_prefix .Level2InterruptVector - .section .Level2InterruptVector.text, "ax" - .global _Level2Vector - .type _Level2Vector,@function - .align 4 -_Level2Vector: - wsr a0, EXCSAVE_2 /* preserve a0 */ - call0 _xt_medint2 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .section .iram1,"ax" - .type _xt_medint2,@function - .align 4 -_xt_medint2: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, EPS_2 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_2 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_2 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_medint2_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_2 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_2 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(2) | PS_UM - #else - movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - /* - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. - */ - .global _xt_medint2_exit - .type _xt_medint2_exit,@function - .align 4 -_xt_medint2_exit: - /* Restore only level-specific regs (the rest were already restored) */ - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, EPS_2 - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_2 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure EPS and EPC written */ - rfi 2 - -#endif /* Level 2 */ - -#if XCHAL_EXCM_LEVEL >= 3 - - .begin literal_prefix .Level3InterruptVector - .section .Level3InterruptVector.text, "ax" - .global _Level3Vector - .type _Level3Vector,@function - .align 4 -_Level3Vector: - wsr a0, EXCSAVE_3 /* preserve a0 */ - call0 _xt_medint3 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .section .iram1,"ax" - .type _xt_medint3,@function - .align 4 -_xt_medint3: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, EPS_3 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_3 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_3 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_medint3_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_3 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_3 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(3) | PS_UM - #else - movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - /* - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. - */ - .global _xt_medint3_exit - .type _xt_medint3_exit,@function - .align 4 -_xt_medint3_exit: - /* Restore only level-specific regs (the rest were already restored) */ - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, EPS_3 - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_3 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure EPS and EPC written */ - rfi 3 - -#endif /* Level 3 */ - -#if XCHAL_EXCM_LEVEL >= 4 - - .begin literal_prefix .Level4InterruptVector - .section .Level4InterruptVector.text, "ax" - .global _Level4Vector - .type _Level4Vector,@function - .align 4 -_Level4Vector: - wsr a0, EXCSAVE_4 /* preserve a0 */ - call0 _xt_medint4 /* load interrupt handler */ - - .end literal_prefix - - .section .iram1,"ax" - .type _xt_medint4,@function - .align 4 -_xt_medint4: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, EPS_4 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_4 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_4 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_medint4_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_4 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_4 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(4) | PS_UM - #else - movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - /* - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. - */ - .global _xt_medint4_exit - .type _xt_medint4_exit,@function - .align 4 -_xt_medint4_exit: - /* Restore only level-specific regs (the rest were already restored) */ - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, EPS_4 - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_4 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure EPS and EPC written */ - rfi 4 - -#endif /* Level 4 */ - -#if XCHAL_EXCM_LEVEL >= 5 - - .begin literal_prefix .Level5InterruptVector - .section .Level5InterruptVector.text, "ax" - .global _Level5Vector - .type _Level5Vector,@function - .align 4 -_Level5Vector: - wsr a0, EXCSAVE_5 /* preserve a0 */ - call0 _xt_medint5 /* load interrupt handler */ - - .end literal_prefix - - .section .iram1,"ax" - .type _xt_medint5,@function - .align 4 -_xt_medint5: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, EPS_5 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_5 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_5 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_medint5_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_5 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_5 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(5) | PS_UM - #else - movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - /* - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. - */ - .global _xt_medint5_exit - .type _xt_medint5_exit,@function - .align 4 -_xt_medint5_exit: - /* Restore only level-specific regs (the rest were already restored) */ - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, EPS_5 - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_5 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure EPS and EPC written */ - rfi 5 - -#endif /* Level 5 */ - -#if XCHAL_EXCM_LEVEL >= 6 - - .begin literal_prefix .Level6InterruptVector - .section .Level6InterruptVector.text, "ax" - .global _Level6Vector - .type _Level6Vector,@function - .align 4 -_Level6Vector: - wsr a0, EXCSAVE_6 /* preserve a0 */ - call0 _xt_medint6 /* load interrupt handler */ - - .end literal_prefix - - .section .iram1,"ax" - .type _xt_medint6,@function - .align 4 -_xt_medint6: - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, EPS_6 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_6 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_6 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_medint6_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* EXCSAVE_6 should now be free to use. Use it to keep a copy of the - current stack pointer that points to the exception frame (XT_STK_FRAME).*/ - #ifdef XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - mov a0, sp - wsr a0, EXCSAVE_6 - #endif - #endif - - /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ - - /* !! We are now on the RTOS system stack !! */ - - /* Set up PS for C, enable interrupts above this level and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(6) | PS_UM - #else - movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE - #endif - wsr a0, PS - rsync - - /* OK to call C code at this point, dispatch user ISRs */ - - dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK - - /* Done handling interrupts, transfer control to OS */ - call0 XT_RTOS_INT_EXIT /* does not return directly here */ - - /* - Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT - on entry and used to return to a thread or interrupted interrupt handler. - */ - .global _xt_medint6_exit - .type _xt_medint6_exit,@function - .align 4 -_xt_medint6_exit: - /* Restore only level-specific regs (the rest were already restored) */ - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, EPS_6 - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_6 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure EPS and EPC written */ - rfi 6 - -#endif /* Level 6 */ - - -/******************************************************************************* - -HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS - -High priority interrupts are by definition those with priorities greater -than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority -interrupts cannot interact with the RTOS, that is they must save all regs -they use and not call any RTOS function. - -A further restriction imposed by the Xtensa windowed architecture is that -high priority interrupts must not modify the stack area even logically -"above" the top of the interrupted stack (they need to provide their -own stack or static save area). - -Cadence Design Systems recommends high priority interrupt handlers be coded in assembly -and used for purposes requiring very short service times. - -Here are templates for high priority (level 2+) interrupt vectors. -They assume only one interrupt per level to avoid the burden of identifying -which interrupts at this level are pending and enabled. This allows for -minimum latency and avoids having to save/restore a2 in addition to a0. -If more than one interrupt per high priority level is configured, this burden -is on the handler which in any case must provide a way to save and restore -registers it uses without touching the interrupted stack. - -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. - -*******************************************************************************/ - -/* -Currently only shells for high priority interrupt handlers are provided -here. However a template and example can be found in the Cadence Design Systems tools -documentation: "Microprocessor Programmer's Guide". -*/ - -#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2 - - .begin literal_prefix .Level2InterruptVector - .section .Level2InterruptVector.text, "ax" - .global _Level2Vector - .type _Level2Vector,@function - .global xt_highint2 - .align 4 -_Level2Vector: - wsr a0, EXCSAVE_2 /* preserve a0 */ - call0 xt_highint2 /* load interrupt handler */ - - .end literal_prefix - - .global xt_highint2 - .weak xt_highint2 - .set xt_highint2, _xt_highint2 - .section .iram1, "ax" - .type _xt_highint2,@function - .align 4 -_xt_highint2: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 2<<2 - beqz a0, 1f -.Ln_xt_highint2_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE. - */ - - .align 4 -.L_xt_highint2_exit: - rsr a0, EXCSAVE_2 /* restore a0 */ - rfi 2 - -#endif /* Level 2 */ - -#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3 - - .begin literal_prefix .Level3InterruptVector - .section .Level3InterruptVector.text, "ax" - .global _Level3Vector - .type _Level3Vector,@function - .global xt_highint3 - .align 4 -_Level3Vector: - wsr a0, EXCSAVE_3 /* preserve a0 */ - call0 xt_highint3 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .global xt_highint3 - .weak xt_highint3 - .set xt_highint3, _xt_highint3 - .section .iram1, "ax" - .type _xt_highint3,@function - .align 4 -_xt_highint3: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 3<<2 - beqz a0, 1f -.Ln_xt_highint3_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE. - */ - - .align 4 -.L_xt_highint3_exit: - rsr a0, EXCSAVE_3 /* restore a0 */ - rfi 3 - -#endif /* Level 3 */ - -#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4 - - .begin literal_prefix .Level4InterruptVector - .section .Level4InterruptVector.text, "ax" - .global _Level4Vector - .type _Level4Vector,@function - .global xt_highint4 - .align 4 -_Level4Vector: - wsr a0, EXCSAVE_4 /* preserve a0 */ - call0 xt_highint4 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .global xt_highint4 - .weak xt_highint4 - .set xt_highint4, _xt_highint4 - .section .iram1, "ax" - .type _xt_highint4,@function - .align 4 -_xt_highint4: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 4<<2 - beqz a0, 1f -.Ln_xt_highint4_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE. - */ - - .align 4 -.L_xt_highint4_exit: - rsr a0, EXCSAVE_4 /* restore a0 */ - rfi 4 - -#endif /* Level 4 */ - -#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5 - - .begin literal_prefix .Level5InterruptVector - .section .Level5InterruptVector.text, "ax" - .global _Level5Vector - .type _Level5Vector,@function - .global xt_highint5 - .align 4 -_Level5Vector: - wsr a0, EXCSAVE_5 /* preserve a0 */ - call0 xt_highint5 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .global xt_highint5 - .weak xt_highint5 - .set xt_highint5, _xt_highint5 - .section .iram1, "ax" - .type _xt_highint5,@function - .align 4 -_xt_highint5: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 5<<2 - beqz a0, 1f -.Ln_xt_highint5_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE. - */ - - .align 4 -.L_xt_highint5_exit: - rsr a0, EXCSAVE_5 /* restore a0 */ - rfi 5 - -#endif /* Level 5 */ - -#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6 - - .begin literal_prefix .Level6InterruptVector - .section .Level6InterruptVector.text, "ax" - .global _Level6Vector - .type _Level6Vector,@function - .global xt_highint6 - .align 4 -_Level6Vector: - wsr a0, EXCSAVE_6 /* preserve a0 */ - call0 xt_highint6 /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .global xt_highint6 - .weak xt_highint6 - .set xt_highint6, _xt_highint6 - .section .iram1, "ax" - .type _xt_highint6,@function - .align 4 -_xt_highint6: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 6<<2 - beqz a0, 1f -.Ln_xt_highint6_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE. - */ - - .align 4 -.L_xt_highint6_exit: - rsr a0, EXCSAVE_6 /* restore a0 */ - rfi 6 - -#endif /* Level 6 */ - -#if XCHAL_HAVE_NMI - - .begin literal_prefix .NMIExceptionVector - .section .NMIExceptionVector.text, "ax" - .global _NMIExceptionVector - .type _NMIExceptionVector,@function - .global xt_nmi - .align 4 -_NMIExceptionVector: - wsr a0, EXCSAVE + XCHAL_NMILEVEL /* preserve a0 */ - call0 xt_nmi /* load interrupt handler */ - /* never returns here - call0 is used as a jump (see note at top) */ - - .end literal_prefix - - .global xt_nmi - .weak xt_nmi - .set xt_nmi, _xt_nmi - .section .iram1, "ax" - .type _xt_nmi,@function - .align 4 -_xt_nmi: - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, XCHAL_NMILEVEL<<2 - beqz a0, 1f -.Ln_xt_nmi_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - - /* USER_EDIT: - ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. - */ - - .align 4 -.L_xt_nmi_exit: - rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ - rfi XCHAL_NMILEVEL - -#endif /* NMI */ - - -/******************************************************************************* - -WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER - -Here is the code for each window overflow/underflow exception vector and -(interspersed) efficient code for handling the alloca exception cause. -Window exceptions are handled entirely in the vector area and are very -tight for performance. The alloca exception is also handled entirely in -the window vector area so comes at essentially no cost in code size. -Users should never need to modify them and Cadence Design Systems recommends -they do not. - -Window handlers go at predetermined vector locations according to the -Xtensa hardware configuration, which is ensured by their placement in a -special section known to the Xtensa linker support package (LSP). Since -their offsets in that section are always the same, the LSPs do not define -a section per vector. - -These things are coded for XEA2 only (XEA1 is not supported). - -Note on Underflow Handlers: -The underflow handler for returning from call[i+1] to call[i] -must preserve all the registers from call[i+1]'s window. -In particular, a0 and a1 must be preserved because the RETW instruction -will be reexecuted (and may even underflow if an intervening exception -has flushed call[i]'s registers). -Registers a2 and up may contain return values. - -*******************************************************************************/ - -#if XCHAL_HAVE_WINDOWED - - .section .WindowVectors.text, "ax" - -/* --------------------------------------------------------------------------------- -Window Overflow Exception for Call4. - -Invoked if a call[i] referenced a register (a4-a15) -that contains data from ancestor call[j]; -call[j] had done a call4 to call[j+1]. -On entry here: - window rotated to call[j] start point; - a0-a3 are registers to be saved; - a4-a15 must be preserved; - a5 is call[j+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0x0 - .global _WindowOverflow4 -_WindowOverflow4: - - s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ - s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ - s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ - s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ - rfwo /* rotates back to call[i] position */ - -/* --------------------------------------------------------------------------------- -Window Underflow Exception for Call4 - -Invoked by RETW returning from call[i+1] to call[i] -where call[i]'s registers must be reloaded (not live in ARs); -where call[i] had done a call4 to call[i+1]. -On entry here: - window rotated to call[i] start point; - a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; - a4-a15 must be preserved (they are call[i+1].reg[0..11]); - a5 is call[i+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0x40 - .global _WindowUnderflow4 -_WindowUnderflow4: - - l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ - l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ - l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ - l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ - rfwu - -/* --------------------------------------------------------------------------------- -Handle alloca exception generated by interruptee executing 'movsp'. -This uses space between the window vectors, so is essentially "free". -All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, -and PS.EXCM has been set by the exception hardware (can't be interrupted). -The fact the alloca exception was taken means the registers associated with -the base-save area have been spilled and will be restored by the underflow -handler, so those 4 registers are available for scratch. -The code is optimized to avoid unaligned branches and minimize cache misses. --------------------------------------------------------------------------------- -*/ - - .align 4 - .global _xt_alloca_exc -_xt_alloca_exc: - - rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ - rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ - rsr a2, PS - extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS - xor a3, a3, a4 /* bits changed from old to current windowbase */ - rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ - slli a3, a3, XCHAL_PS_OWB_SHIFT - xor a2, a2, a3 /* flip changed bits in old window base */ - wsr a2, PS /* update PS.OWB to new window base */ - rsync - - bbci.l a4, 31, _WindowUnderflow4 - rotw -1 /* original a0 goes to a8 */ - bbci.l a8, 30, _WindowUnderflow8 - rotw -1 - j _WindowUnderflow12 - -/* --------------------------------------------------------------------------------- -Window Overflow Exception for Call8 - -Invoked if a call[i] referenced a register (a4-a15) -that contains data from ancestor call[j]; -call[j] had done a call8 to call[j+1]. -On entry here: - window rotated to call[j] start point; - a0-a7 are registers to be saved; - a8-a15 must be preserved; - a9 is call[j+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0x80 - .global _WindowOverflow8 -_WindowOverflow8: - - s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ - l32e a0, a1, -12 /* a0 <- call[j-1]'s sp - (used to find end of call[j]'s frame) */ - s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ - s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ - s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ - s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ - s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ - s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ - s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ - rfwo /* rotates back to call[i] position */ - -/* --------------------------------------------------------------------------------- -Window Underflow Exception for Call8 - -Invoked by RETW returning from call[i+1] to call[i] -where call[i]'s registers must be reloaded (not live in ARs); -where call[i] had done a call8 to call[i+1]. -On entry here: - window rotated to call[i] start point; - a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; - a8-a15 must be preserved (they are call[i+1].reg[0..7]); - a9 is call[i+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0xC0 - .global _WindowUnderflow8 -_WindowUnderflow8: - - l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ - l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ - l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ - l32e a7, a1, -12 /* a7 <- call[i-1]'s sp - (used to find end of call[i]'s frame) */ - l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ - l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ - l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ - l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ - l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ - rfwu - -/* --------------------------------------------------------------------------------- -Window Overflow Exception for Call12 - -Invoked if a call[i] referenced a register (a4-a15) -that contains data from ancestor call[j]; -call[j] had done a call12 to call[j+1]. -On entry here: - window rotated to call[j] start point; - a0-a11 are registers to be saved; - a12-a15 must be preserved; - a13 is call[j+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0x100 - .global _WindowOverflow12 -_WindowOverflow12: - - s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ - l32e a0, a1, -12 /* a0 <- call[j-1]'s sp - (used to find end of call[j]'s frame) */ - s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ - s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ - s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ - s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ - s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ - s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ - s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ - s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ - s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ - s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ - s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ - rfwo /* rotates back to call[i] position */ - -/* --------------------------------------------------------------------------------- -Window Underflow Exception for Call12 - -Invoked by RETW returning from call[i+1] to call[i] -where call[i]'s registers must be reloaded (not live in ARs); -where call[i] had done a call12 to call[i+1]. -On entry here: - window rotated to call[i] start point; - a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; - a12-a15 must be preserved (they are call[i+1].reg[0..3]); - a13 is call[i+1]'s stack pointer. --------------------------------------------------------------------------------- -*/ - - .org 0x140 - .global _WindowUnderflow12 -_WindowUnderflow12: - - l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ - l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ - l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ - l32e a11, a1, -12 /* a11 <- call[i-1]'s sp - (used to find end of call[i]'s frame) */ - l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ - l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ - l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ - l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ - l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ - l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ - l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ - l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ - l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ - rfwu - -#endif /* XCHAL_HAVE_WINDOWED */ - - .section .UserEnter.text, "ax" - .global call_user_start - .type call_user_start,@function - .align 4 - .literal_position