1 // window-vectors.S - Register Window Overflow/Underflow Handlers
2 // $Id: //depot/rel/Cottonwood/Xtensa/OS/xtos/window-vectors.S#3 $
4 // Copyright (c) 1999-2010 Tensilica Inc.
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include <xtensa/coreasm.h>
27 #if XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__)
29 # ifndef NO_SECTION_DIRECTIVES
31 .global _WindowOverflow4
32 .global _WindowUnderflow4
33 .global _WindowOverflow8
34 .global _WindowUnderflow8
35 .global _WindowOverflow12
36 .global _WindowUnderflow12
38 // Note: the current window exception vectors do not generate any
39 // literals. Hence the literal_prefix directive is not necessary.
40 // Specifying it "just in case" creates an empty section (named
41 // ".WindowVectors.literal") which can in some cases cause linking
42 // problems (the linker scripts don't place it anywhere).
43 // So leave it commented out:
45 //.begin literal_prefix .WindowVectors
47 .section .WindowVectors.text, "ax"
54 // These window exception handlers need not be modified.
55 // They are specific to the windowed call ABI only.
57 // Underflow Handlers:
59 // The underflow handler for returning from call[i+1] to call[i]
60 // must preserve all the registers from call[i+1]'s window.
61 // In particular, a0 and a1 must be preserved because the RETW instruction
62 // will be reexecuted (and may even underflow again if an intervening
63 // exception has flushed call[i]'s registers).
64 // Registers a2 and up may contain return values.
66 // The caller could also potentially assume that the callee's a0 and a1
67 // (its own a4&a5 if call4, a8&a9 if call8, a12&a13 if call12)
68 // are correct for whatever reason (not a clean thing to do in general,
69 // but if it's possible, unless the ABI explicitly prohibits it,
70 // it will eventually be done :) -- whether the the ABI needs to
71 // prohibit this is a different question).
73 // Timing of Handlers:
75 // Here is an overview of the overhead of taking a window exception,
76 // ie. the number of additional cycles taken relative to case where
77 // an exception is not taken.
78 // NOTE: these numbers do not take into account any cache misses,
79 // write buffer stalls, or other external stalls, if they occur.
80 // The totals consist of 5 cycles to enter the handler (or 6 or 7
81 // for optional longer pipelines in Xtensa LX), the number of instructions
82 // and interlocks (2nd and 3rd columns below), and 2 cycles jump delay
83 // on return (3 cycles for optional longer I-side pipeline in Xtensa LX):
85 // Instruction+bubbles Totals (5-stage)
86 // XEA1 XEA2 XEA1 XEA2
87 // Overflow-4 7 5 14 12
88 // Overflow-8 14 10 21 17
89 // Overflow-12 18 14 25 21
90 // Underflow-4 6 5 13 12
91 // Underflow-8 14 10 21 17
92 // Underflow-12 18 14 25 21
94 // Underflow-8 15 12 25 22 (7-stage; could be made 1 less)
95 // Underflow-12 19 16 29 26 (7-stage; could be made 1 less)
97 #ifndef WINDOW_BASE_VECOFS
98 #define WINDOW_BASE_VECOFS XCHAL_WINDOW_OF4_VECOFS
102 // 4-Register Window Overflow Vector (Handler)
104 // Invoked if a call[i] referenced a register (a4-a15)
105 // that contains data from ancestor call[j];
106 // call[j] had done a call4 to call[j+1].
108 // window rotated to call[j] start point;
109 // a0-a3 are registers to be saved;
110 // a4-a15 must be preserved;
111 // a5 is call[j+1]'s stack pointer.
113 .org XCHAL_WINDOW_OF4_VECOFS - WINDOW_BASE_VECOFS
116 addi a5, a5, -16 // to make store offsets positive
117 s32i a0, a5, 0 // save a0 to call[j+1]'s stack frame
118 s32i a1, a5, 4 // save a1 to call[j+1]'s stack frame
119 s32i a2, a5, 8 // save a2 to call[j+1]'s stack frame
120 s32i a3, a5, 12 // save a3 to call[j+1]'s stack frame
121 addi a5, a5, 16 // restore a5
123 s32e a0, a5, -16 // save a0 to call[j+1]'s stack frame
124 s32e a1, a5, -12 // save a1 to call[j+1]'s stack frame
125 s32e a2, a5, -8 // save a2 to call[j+1]'s stack frame
126 s32e a3, a5, -4 // save a3 to call[j+1]'s stack frame
128 rfwo // rotates back to call[i] position
130 .size _WindowOverflow4, . - _WindowOverflow4
133 // 4-Register Window Underflow Vector (Handler)
135 // Invoked by RETW returning from call[i+1] to call[i]
136 // where call[i]'s registers must be reloaded (not live in ARs);
137 // call[i] had done a call4 to call[i+1].
139 // window rotated to call[i] start point;
140 // a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
141 // a4-a15 must be preserved (they are call[i+1].reg[0..11]);
142 // a5 is call[i+1]'s stack pointer.
144 .org XCHAL_WINDOW_UF4_VECOFS - WINDOW_BASE_VECOFS
147 addi a3, a5, -16 // to make load offsets positive
148 l32i a0, a3, 0 // restore a0 from call[i+1]'s stack frame
149 l32i a1, a3, 4 // restore a1 from call[i+1]'s stack frame
150 l32i a2, a3, 8 // restore a2 from call[i+1]'s stack frame
151 l32i a3, a3, 12 // restore a3 from call[i+1]'s stack frame
153 l32e a0, a5, -16 // restore a0 from call[i+1]'s stack frame
154 l32e a1, a5, -12 // restore a1 from call[i+1]'s stack frame
155 l32e a2, a5, -8 // restore a2 from call[i+1]'s stack frame
156 l32e a3, a5, -4 // restore a3 from call[i+1]'s stack frame
160 .size _WindowUnderflow4, . - _WindowUnderflow4
163 // 8-Register Window Overflow Vector (Handler)
165 // Invoked if a call[i] referenced a register (a4-a15)
166 // that contains data from ancestor call[j];
167 // call[j] had done a call8 to call[j+1].
169 // window rotated to call[j] start point;
170 // a0-a7 are registers to be saved;
171 // a8-a15 must be preserved;
172 // a9 is call[j+1]'s stack pointer.
174 .org XCHAL_WINDOW_OF8_VECOFS - WINDOW_BASE_VECOFS
177 addi a9, a9, -16 // to make store offsets positive
178 s32i a0, a9, 0 // save a0 to call[j+1]'s stack frame
179 addi a0, a1, -16 // a0 <- call[j-1]'s sp
180 s32i a1, a9, 4 // save a1 to call[j+1]'s stack frame
181 l32i a0, a0, 4 // (used to find end of call[j]'s frame)
182 s32i a2, a9, 8 // save a2 to call[j+1]'s stack frame
183 s32i a3, a9, 12 // save a3 to call[j+1]'s stack frame
184 addi a9, a9, 16 // restore a9
185 addi a0, a0, -32 // to make load offsets positive
186 s32i a4, a0, 0 // save a4 to call[j]'s stack frame
187 s32i a5, a0, 4 // save a5 to call[j]'s stack frame
188 s32i a6, a0, 8 // save a6 to call[j]'s stack frame
189 s32i a7, a0, 12 // save a7 to call[j]'s stack frame
191 s32e a0, a9, -16 // save a0 to call[j+1]'s stack frame
192 l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame)
193 s32e a1, a9, -12 // save a1 to call[j+1]'s stack frame
194 s32e a2, a9, -8 // save a2 to call[j+1]'s stack frame
195 s32e a3, a9, -4 // save a3 to call[j+1]'s stack frame
196 s32e a4, a0, -32 // save a4 to call[j]'s stack frame
197 s32e a5, a0, -28 // save a5 to call[j]'s stack frame
198 s32e a6, a0, -24 // save a6 to call[j]'s stack frame
199 s32e a7, a0, -20 // save a7 to call[j]'s stack frame
201 rfwo // rotates back to call[i] position
203 .size _WindowOverflow8, . - _WindowOverflow8
206 // 8-Register Window Underflow Vector (Handler)
208 // Invoked by RETW returning from call[i+1] to call[i]
209 // where call[i]'s registers must be reloaded (not live in ARs);
210 // call[i] had done a call8 to call[i+1].
212 // window rotated to call[i] start point;
213 // a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
214 // a8-a15 must be preserved (they are call[i+1].reg[0..7]);
215 // a9 is call[i+1]'s stack pointer.
217 .org XCHAL_WINDOW_UF8_VECOFS - WINDOW_BASE_VECOFS
220 addi a9, a9, -16 // to make load offsets positive
221 l32i a0, a9, 0 // restore a0 from call[i+1]'s stack frame
222 l32i a1, a9, 4 // restore a1 from call[i+1]'s stack frame
223 l32i a2, a9, 8 // restore a2 from call[i+1]'s stack frame
224 addi a7, a1, -16 // a7 <- call[i-1]'s sp
225 l32i a7, a7, 4 // (used to find end of call[i]'s frame)
226 l32i a3, a9, 12 // restore a3 from call[i+1]'s stack frame
227 addi a9, a9, 16 // restore a9
228 addi a7, a7, -32 // to make load offsets positive
229 l32i a4, a7, 0 // restore a4 from call[i]'s stack frame
230 l32i a5, a7, 4 // restore a5 from call[i]'s stack frame
231 l32i a6, a7, 8 // restore a6 from call[i]'s stack frame
232 l32i a7, a7, 12 // restore a7 from call[i]'s stack frame
234 l32e a0, a9, -16 // restore a0 from call[i+1]'s stack frame
235 l32e a1, a9, -12 // restore a1 from call[i+1]'s stack frame
236 l32e a2, a9, -8 // restore a2 from call[i+1]'s stack frame
237 l32e a7, a1, -12 // a7 <- call[i-1]'s sp (used to find end of call[i]'s frame)
238 l32e a3, a9, -4 // restore a3 from call[i+1]'s stack frame
239 l32e a4, a7, -32 // restore a4 from call[i]'s stack frame
240 l32e a5, a7, -28 // restore a5 from call[i]'s stack frame
241 l32e a6, a7, -24 // restore a6 from call[i]'s stack frame
242 l32e a7, a7, -20 // restore a7 from call[i]'s stack frame
246 .size _WindowUnderflow8, . - _WindowUnderflow8
249 // 12-Register Window Overflow Vector (Handler)
251 // Invoked if a call[i] referenced a register (a4-a15)
252 // that contains data from ancestor call[j];
253 // call[j] had done a call12 to call[j+1].
255 // window rotated to call[j] start point;
256 // a0-a11 are registers to be saved;
257 // a12-a15 must be preserved;
258 // a13 is call[j+1]'s stack pointer.
260 .org XCHAL_WINDOW_OF12_VECOFS - WINDOW_BASE_VECOFS
263 addi a13, a13, -16 // to make store offsets positive
264 s32i a0, a13, 0 // save a0 to call[j+1]'s stack frame
265 addi a0, a1, -16 // a0 <- call[j-1]'s sp
266 s32i a1, a13, 4 // save a1 to call[j+1]'s stack frame
267 l32i a0, a0, 4 // (used to find end of call[j]'s frame)
268 s32i a2, a13, 8 // save a2 to call[j+1]'s stack frame
269 s32i a3, a13, 12 // save a3 to call[j+1]'s stack frame
270 addi a13, a13, 16 // restore a13
271 addi a0, a0, -48 // to make load offsets positive
272 s32i a4, a0, 0 // save a4 to end of call[j]'s stack frame
273 s32i a5, a0, 4 // save a5 to end of call[j]'s stack frame
274 s32i a6, a0, 8 // save a6 to end of call[j]'s stack frame
275 s32i a7, a0, 12 // save a7 to end of call[j]'s stack frame
276 s32i a8, a0, 16 // save a8 to end of call[j]'s stack frame
277 s32i a9, a0, 20 // save a9 to end of call[j]'s stack frame
278 s32i a10, a0, 24 // save a10 to end of call[j]'s stack frame
279 s32i a11, a0, 28 // save a11 to end of call[j]'s stack frame
281 s32e a0, a13, -16 // save a0 to call[j+1]'s stack frame
282 l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame)
283 s32e a1, a13, -12 // save a1 to call[j+1]'s stack frame
284 s32e a2, a13, -8 // save a2 to call[j+1]'s stack frame
285 s32e a3, a13, -4 // save a3 to call[j+1]'s stack frame
286 s32e a4, a0, -48 // save a4 to end of call[j]'s stack frame
287 s32e a5, a0, -44 // save a5 to end of call[j]'s stack frame
288 s32e a6, a0, -40 // save a6 to end of call[j]'s stack frame
289 s32e a7, a0, -36 // save a7 to end of call[j]'s stack frame
290 s32e a8, a0, -32 // save a8 to end of call[j]'s stack frame
291 s32e a9, a0, -28 // save a9 to end of call[j]'s stack frame
292 s32e a10, a0, -24 // save a10 to end of call[j]'s stack frame
293 s32e a11, a0, -20 // save a11 to end of call[j]'s stack frame
295 rfwo // rotates back to call[i] position
297 .size _WindowOverflow12, . - _WindowOverflow12
300 // 12-Register Window Underflow Vector (Handler)
302 // Invoked by RETW returning from call[i+1] to call[i]
303 // where call[i]'s registers must be reloaded (not live in ARs);
304 // call[i] had done a call12 to call[i+1].
306 // window rotated to call[i] start point;
307 // a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
308 // a12-a15 must be preserved (they are call[i+1].reg[0..3]);
309 // a13 is call[i+1]'s stack pointer.
311 .org XCHAL_WINDOW_UF12_VECOFS - WINDOW_BASE_VECOFS
314 addi a13, a13, -16 // to make load offsets positive
315 l32i a0, a13, 0 // restore a0 from call[i+1]'s stack frame
316 l32i a1, a13, 4 // restore a1 from call[i+1]'s stack frame
317 l32i a2, a13, 8 // restore a2 from call[i+1]'s stack frame
318 addi a11, a1, -16 // a11 <- call[i-1]'s sp
319 l32i a11, a11, 4 // (used to find end of call[i]'s frame)
320 l32i a3, a13, 12 // restore a3 from call[i+1]'s stack frame
321 addi a13, a13, 16 // restore a13
322 addi a11, a11, -48 // to make load offsets positive
323 l32i a4, a11, 0 // restore a4 from end of call[i]'s stack frame
324 l32i a5, a11, 4 // restore a5 from end of call[i]'s stack frame
325 l32i a6, a11, 8 // restore a6 from end of call[i]'s stack frame
326 l32i a7, a11, 12 // restore a7 from end of call[i]'s stack frame
327 l32i a8, a11, 16 // restore a8 from end of call[i]'s stack frame
328 l32i a9, a11, 20 // restore a9 from end of call[i]'s stack frame
329 l32i a10, a11, 24 // restore a10 from end of call[i]'s stack frame
330 l32i a11, a11, 28 // restore a11 from end of call[i]'s stack frame
332 l32e a0, a13, -16 // restore a0 from call[i+1]'s stack frame
333 l32e a1, a13, -12 // restore a1 from call[i+1]'s stack frame
334 l32e a2, a13, -8 // restore a2 from call[i+1]'s stack frame
335 l32e a11, a1, -12 // a11 <- call[i-1]'s sp (used to find end of call[i]'s frame)
336 l32e a3, a13, -4 // restore a3 from call[i+1]'s stack frame
337 l32e a4, a11, -48 // restore a4 from end of call[i]'s stack frame
338 l32e a5, a11, -44 // restore a5 from end of call[i]'s stack frame
339 l32e a6, a11, -40 // restore a6 from end of call[i]'s stack frame
340 l32e a7, a11, -36 // restore a7 from end of call[i]'s stack frame
341 l32e a8, a11, -32 // restore a8 from end of call[i]'s stack frame
342 l32e a9, a11, -28 // restore a9 from end of call[i]'s stack frame
343 l32e a10, a11, -24 // restore a10 from end of call[i]'s stack frame
344 l32e a11, a11, -20 // restore a11 from end of call[i]'s stack frame
348 .size _WindowUnderflow12, . - _WindowUnderflow12
351 # ifndef NO_SECTION_DIRECTIVES
352 //.end literal_prefix
357 #endif /* XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) */