1 /* 2 * SPDX-FileCopyrightText: 2017, Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD 7 */ 8 9 /* File adapted to use on IDF FreeRTOS component, extracted 10 * originally from zephyr RTOS code base: 11 * https://github.com/zephyrproject-rtos/zephyr/blob/dafd3485bf67880e667b6e9a758b0b64fb688d63/arch/xtensa/include/xtensa-asm2-s.h 12 */ 13 14 #ifndef __XT_ASM_UTILS_H 15 #define __XT_ASM_UTILS_H 16 17 /* 18 * SPILL_ALL_WINDOWS 19 * 20 * Spills all windowed registers (i.e. registers not visible as 21 * A0-A15) to their ABI-defined spill regions on the stack. 22 * 23 * Unlike the Xtensa HAL implementation, this code requires that the 24 * EXCM and WOE bit be enabled in PS, and relies on repeated hardware 25 * exception handling to do the register spills. The trick is to do a 26 * noop write to the high registers, which the hardware will trap 27 * (into an overflow exception) in the case where those registers are 28 * already used by an existing call frame. Then it rotates the window 29 * and repeats until all but the A0-A3 registers of the original frame 30 * are guaranteed to be spilled, eventually rotating back around into 31 * the original frame. Advantages: 32 * 33 * - Vastly smaller code size 34 * 35 * - More easily maintained if changes are needed to window over/underflow 36 * exception handling. 37 * 38 * - Requires no scratch registers to do its work, so can be used safely in any 39 * context. 40 * 41 * - If the WOE bit is not enabled (for example, in code written for 42 * the CALL0 ABI), this becomes a silent noop and operates compatbily. 43 * 44 * - Hilariously it's ACTUALLY FASTER than the HAL routine. And not 45 * just a little bit, it's MUCH faster. With a mostly full register 46 * file on an LX6 core (ESP-32) I'm measuring 145 cycles to spill 47 * registers with this vs. 279 (!) to do it with 48 * xthal_spill_windows(). 49 */ 50 51 .macro SPILL_ALL_WINDOWS 52 #if XCHAL_NUM_AREGS == 64 53 and a12, a12, a12 54 rotw 3 55 and a12, a12, a12 56 rotw 3 57 and a12, a12, a12 58 rotw 3 59 and a12, a12, a12 60 rotw 3 61 and a12, a12, a12 62 rotw 4 63 #elif XCHAL_NUM_AREGS == 32 64 and a12, a12, a12 65 rotw 3 66 and a12, a12, a12 67 rotw 3 68 and a4, a4, a4 69 rotw 2 70 #else /* if XCHAL_NUM_AREGS == 64 */ 71 #error Unrecognized XCHAL_NUM_AREGS 72 #endif /* if XCHAL_NUM_AREGS == 64 */ 73 .endm 74 75 #endif /* ifndef __XT_ASM_UTILS_H */ 76