xtensa: Remove OS agnostic files from Amazon SMP FreeRTOS port

The previous commit moved the OS agnostic files from the IDF FreeRTOS port to
the xtensa component, thus can be accessed by both IDF and Amazon SMP FreeRTOS.

This commit removes the redudant copies in the Amazon SMP FreeRTOS port.
This commit is contained in:
Darian Leung 2023-04-10 23:47:18 +08:00
parent b2c074bb70
commit 5fde889a3d
8 changed files with 0 additions and 3934 deletions

View File

@ -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 <xtensa/xtensa_api.h> in future */
#include <xtensa/xtensa_api.h>

View File

@ -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 <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* 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 <sys/reent.h>
#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 <sys/reent.h>
#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 */

View File

@ -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 <xtensa/xtensa_context.h> in future */
#include <xtensa/xtensa_context.h>

View File

@ -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 <xtensa/coreasm.h>
#endif
#include <xtensa/corebits.h>
#include <xtensa/config/system.h>
#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=<value>" where <value> 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 */

View File

@ -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 */

View File

@ -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 <xtensa/overlay_os_asm.h>
#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

View File

@ -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