1 /*
2  * Copyright (c) 2017, Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_
7 #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_
8 
9 #include <xtensa/corebits.h>
10 #include <xtensa/config/core-isa.h>
11 
12 /*
13  * Stack frame layout for a saved processor context, in memory order,
14  * high to low address:
15  *
16  * SP-0 <-- Interrupted stack pointer points here
17  *
18  * SP-4   Caller A3 spill slot \
19  * SP-8   Caller A2 spill slot |
20  * SP-12  Caller A1 spill slot + (Part of ABI standard)
21  * SP-16  Caller A0 spill slot /
22  *
23  * SP-20  Saved A3
24  * SP-24  Saved A2
25  * SP-28  Unused (not "Saved A1" because the SP is saved externally as a handle)
26  * SP-32  Saved A0
27  *
28  * SP-36  Saved PC (address to jump to following restore)
29  * SP-40  Saved/interrupted PS special register
30  *
31  * SP-44  Saved SAR special register
32  *
33  * SP-48  Saved LBEG special register (if loops enabled)
34  * SP-52  Saved LEND special register (if loops enabled)
35  * SP-56  Saved LCOUNT special register (if loops enabled)
36  *
37  * SP-60  Saved SCOMPARE special register (if S32C1I enabled)
38  *
39  * SP-64  Saved EXCCAUSE special register
40  *
41  * SP-68  Saved THREADPTR special register (if processor has thread pointer)
42  *
43  *       (The above fixed-size region is known as the "base save area" in the
44  *        code below)
45  *
46  * - 18 FPU registers (if FPU is present and CONFIG_FPU_SHARING enabled)
47  *
48  * - Saved A7 \
49  * - Saved A6 |
50  * - Saved A5 +- If not in-use by another frame
51  * - Saved A4 /
52  *
53  * - Saved A11 \
54  * - Saved A10 |
55  * - Saved A9  +- If not in-use by another frame
56  * - Saved A8  /
57  *
58  * - Saved A15 \
59  * - Saved A14 |
60  * - Saved A13 +- If not in-use by another frame
61  * - Saved A12 /
62  *
63  * - Saved intermediate stack pointer (points to low word of base save
64  *   area, i.e. the saved LCOUNT or SAR).  The pointer to this value
65  *   (i.e. the final stack pointer) is stored externally as the
66  *   "restore handle" in the thread context.
67  *
68  * Essentially, you can recover a pointer to the BSA by loading *SP.
69  * Adding the fixed BSA size to that gets you back to the
70  * original/interrupted stack pointer.
71  */
72 
73 #ifndef __ASSEMBLER__
74 
75 #include <stdint.h>
76 #include <zephyr/toolchain.h>
77 
78 /**
79  * Base Save Area (BSA) during interrupt.
80  *
81  * This saves the registers during interrupt entrance
82  * so they can be restored later.
83  *
84  * Note that only A0-A3 are saved here. High registers
85  * are saved after the BSA.
86  */
87 struct xtensa_irq_base_save_area {
88 #if XCHAL_HAVE_FP && defined(CONFIG_CPU_HAS_FPU) && defined(CONFIG_FPU_SHARING)
89 	uintptr_t fcr;
90 	uintptr_t fsr;
91 	uintptr_t fpu0;
92 	uintptr_t fpu1;
93 	uintptr_t fpu2;
94 	uintptr_t fpu3;
95 	uintptr_t fpu4;
96 	uintptr_t fpu5;
97 	uintptr_t fpu6;
98 	uintptr_t fpu7;
99 	uintptr_t fpu8;
100 	uintptr_t fpu9;
101 	uintptr_t fpu10;
102 	uintptr_t fpu11;
103 	uintptr_t fpu12;
104 	uintptr_t fpu13;
105 	uintptr_t fpu14;
106 	uintptr_t fpu15;
107 #endif
108 
109 #if XCHAL_HAVE_THREADPTR
110 	uintptr_t threadptr;
111 #endif
112 
113 #if XCHAL_HAVE_S32C1I
114 	uintptr_t scompare1;
115 #endif
116 
117 	uintptr_t exccause;
118 
119 #if XCHAL_HAVE_LOOPS
120 	uintptr_t lcount;
121 	uintptr_t lend;
122 	uintptr_t lbeg;
123 #endif
124 
125 	uintptr_t sar;
126 	uintptr_t ps;
127 	uintptr_t pc;
128 	uintptr_t a0;
129 	uintptr_t scratch;
130 	uintptr_t a2;
131 	uintptr_t a3;
132 
133 	uintptr_t caller_a0;
134 	uintptr_t caller_a1;
135 	uintptr_t caller_a2;
136 	uintptr_t caller_a3;
137 };
138 
139 typedef struct xtensa_irq_base_save_area _xtensa_irq_bsa_t;
140 
141 /**
142  * Raw interrupt stack frame.
143  *
144  * This provides a raw interrupt stack frame to make it
145  * easier to construct general purpose code in loops.
146  * Avoid using this if possible.
147  */
148 struct xtensa_irq_stack_frame_raw {
149 	_xtensa_irq_bsa_t *ptr_to_bsa;
150 
151 	struct {
152 		uintptr_t r0;
153 		uintptr_t r1;
154 		uintptr_t r2;
155 		uintptr_t r3;
156 	} blks[3];
157 };
158 
159 typedef struct xtensa_irq_stack_frame_raw _xtensa_irq_stack_frame_raw_t;
160 
161 /**
162  * Interrupt stack frame containing A0 - A15.
163  */
164 struct xtensa_irq_stack_frame_a15 {
165 	_xtensa_irq_bsa_t *ptr_to_bsa;
166 
167 	uintptr_t a12;
168 	uintptr_t a13;
169 	uintptr_t a14;
170 	uintptr_t a15;
171 
172 	uintptr_t a8;
173 	uintptr_t a9;
174 	uintptr_t a10;
175 	uintptr_t a11;
176 
177 	uintptr_t a4;
178 	uintptr_t a5;
179 	uintptr_t a6;
180 	uintptr_t a7;
181 
182 	_xtensa_irq_bsa_t bsa;
183 };
184 
185 typedef struct xtensa_irq_stack_frame_a15 _xtensa_irq_stack_frame_a15_t;
186 
187 /**
188  * Interrupt stack frame containing A0 - A11.
189  */
190 struct xtensa_irq_stack_frame_a11 {
191 	_xtensa_irq_bsa_t *ptr_to_bsa;
192 
193 	uintptr_t a8;
194 	uintptr_t a9;
195 	uintptr_t a10;
196 	uintptr_t a11;
197 
198 	uintptr_t a4;
199 	uintptr_t a5;
200 	uintptr_t a6;
201 	uintptr_t a7;
202 
203 	_xtensa_irq_bsa_t bsa;
204 };
205 
206 typedef struct xtensa_irq_stack_frame_a11 _xtensa_irq_stack_frame_a11_t;
207 
208 /**
209  * Interrupt stack frame containing A0 - A7.
210  */
211 struct xtensa_irq_stack_frame_a7 {
212 	_xtensa_irq_bsa_t *ptr_to_bsa;
213 
214 	uintptr_t a4;
215 	uintptr_t a5;
216 	uintptr_t a6;
217 	uintptr_t a7;
218 
219 	_xtensa_irq_bsa_t bsa;
220 };
221 
222 typedef struct xtensa_irq_stack_frame_a7 _xtensa_irq_stack_frame_a7_t;
223 
224 /**
225  * Interrupt stack frame containing A0 - A3.
226  */
227 struct xtensa_irq_stack_frame_a3 {
228 	_xtensa_irq_bsa_t *ptr_to_bsa;
229 
230 	_xtensa_irq_bsa_t bsa;
231 };
232 
233 typedef struct xtensa_irq_stack_frame_a3 _xtensa_irq_stack_frame_a3_t;
234 
235 #endif /* __ASSEMBLER__ */
236 
237 #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ */
238