1 /* setjmp/longjmp functions for Xtensa.
3 Copyright (c) 2001-2006 by Tensilica Inc.
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
26 This implementation relies heavily on the Xtensa register window
27 mechanism. Setjmp flushes all the windows except its own to the
28 stack and then copies registers from the save areas on the stack
29 into the jmp_buf structure, along with the return address of the call
30 to setjmp. Longjmp invalidates all the windows except its own, and
31 then sets things up so that it will return to the right place,
32 using a window underflow to automatically restore the registers.
34 Note that it would probably be sufficient to only copy the
35 registers from setjmp's caller into jmp_buf. However, we also copy
36 the save area located at the stack pointer of setjmp's caller.
37 This save area will typically remain intact until the longjmp call.
38 The one exception is when there is an intervening alloca in
39 setjmp's caller. This is certainly an unusual situation and is
40 likely to cause problems in any case (the storage allocated on the
41 stack cannot be safely accessed following the longjmp). As bad as
42 it is, on most systems this situation would not necessarily lead to
43 a catastrophic failure. If we did not preserve the extra save area
44 on Xtensa, however, it would. When setjmp's caller returns after a
45 longjmp, there will be a window underflow; an invalid return
46 address or stack pointer in the save area will almost certainly
47 lead to a crash. Keeping a copy of the extra save area in the
48 jmp_buf avoids this with only a small additional cost. If setjmp
49 and longjmp are ever time-critical, this could be removed.
54 Much like other ABIs, this version just saves the necessary registers
55 to the stack and restores them later. Much less needs to be done. */
57 #include "xtensa-asm.h"
62 #if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
64 /* int setjmp (jmp_buf env) */
70 .type setjmp, @function
74 /* Flush registers. */
75 mov a4, a2 // save a2 (jmp_buf)
78 mov a2, a4 // restore a2
80 /* Copy the register save area at (sp - 16). */
91 /* Copy 0-8 words from the register overflow area. */
98 addi a7, a7, -16 // a7 = end of register overflow area
113 /* Copy the register save area at sp. */
123 /* Save the return address, including the window size bits. */
128 .size setjmp, . - setjmp
131 /* void longjmp (jmp_buf env, int val) */
136 .type longjmp, @function
139 /* a2 == &env, a3 == val */
141 /* Invalidate all but the current window;
142 set WindowStart to (1 << WindowBase). */
150 /* Return to the return address of the setjmp, using the
151 window size bits from the setjmp call so that the caller
152 will be able to find the return value that we put in a2. */
156 /* Copy the first 4 saved registers from jmp_buf into the save area
157 at the current sp so that the values will be restored to registers
158 when longjmp returns. */
170 /* Copy the remaining 0-8 saved registers. */
177 addi a8, a8, -16 // a8 = end of register overflow area
192 /* The 4 words saved from the register save area at the target's
193 sp are copied back to the target procedure's save area. The
194 only point of this is to prevent a catastrophic failure in
195 case the contents were moved by an alloca after calling
196 setjmp. This is a bit paranoid but it doesn't cost much. */
198 l32i a7, a2, 4 // load the target stack pointer
199 addi a7, a7, -16 // find the destination save area
209 /* Return val ? val : 1. */
214 .size longjmp, . - longjmp
216 #else /* CALL0 ABI */
222 .type setjmp, @function
232 .size setjmp, . - setjmp
237 .type longjmp, @function
245 /* Return val ? val : 1. */
250 .size longjmp, .-longjmp
252 #endif /* CALL0 ABI */