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