* config/xtensa/xtensa.md (fix_return_addr): Remove.
[official-gcc.git] / gcc / config / xtensa / lib2funcs.S
blob16d6734c277349ed5981fa63b2e544e30ae7302b
1 /* Assembly functions for libgcc2.
2    Copyright (C) 2001, 2006, 2007 Free Software Foundation, Inc.
3    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file.  (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
21 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22 WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24 for more details.
26 You should have received a copy of the GNU General Public License
27 along with GCC; see the file COPYING.  If not, write to the Free
28 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29 02110-1301, USA.  */
31 #include "xtensa-config.h"
33 /* __xtensa_libgcc_window_spill: This function flushes out all but the
34    current register window.  This is used to set up the stack so that
35    arbitrary frames can be accessed.  */
37         .align  4
38         .global __xtensa_libgcc_window_spill
39         .type   __xtensa_libgcc_window_spill,@function
40 __xtensa_libgcc_window_spill:
41         entry   sp, 32
42         movi    a2, 0
43         syscall
44         retw
45         .size   __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill
48 /* __xtensa_nonlocal_goto: This code does all the hard work of a
49    nonlocal goto on Xtensa.  It is here in the library to avoid the
50    code size bloat of generating it in-line.  There are two
51    arguments:
53         a2 = frame pointer for the procedure containing the label
54         a3 = goto handler address
56   This function never returns to its caller but instead goes directly
57   to the address of the specified goto handler.  */
59         .align  4
60         .global __xtensa_nonlocal_goto
61         .type   __xtensa_nonlocal_goto,@function
62 __xtensa_nonlocal_goto:
63         entry   sp, 32
65         /* Flush registers.  */
66         mov     a5, a2
67         movi    a2, 0
68         syscall
69         mov     a2, a5
71         /* Because the save area for a0-a3 is stored one frame below
72            the one identified by a2, the only way to restore those
73            registers is to unwind the stack.  If alloca() were never
74            called, we could just unwind until finding the sp value
75            matching a2.  However, a2 is a frame pointer, not a stack
76            pointer, and may not be encountered during the unwinding.
77            The solution is to unwind until going _past_ the value
78            given by a2.  This involves keeping three stack pointer
79            values during the unwinding:
81                 next = sp of frame N-1
82                 cur = sp of frame N
83                 prev = sp of frame N+1
85            When next > a2, the desired save area is stored relative
86            to prev.  At this point, cur will be the same as a2
87            except in the alloca() case.
89            Besides finding the values to be restored to a0-a3, we also
90            need to find the current window size for the target
91            function.  This can be extracted from the high bits of the
92            return address, initially in a0.  As the unwinding
93            proceeds, the window size is taken from the value of a0
94            saved _two_ frames below the current frame.  */
96         addi    a5, sp, -16     /* a5 = prev - save area */
97         l32i    a6, a5, 4
98         addi    a6, a6, -16     /* a6 = cur - save area */
99         mov     a8, a0          /* a8 = return address (for window size) */
100         j       .Lfirstframe
102 .Lnextframe:
103         l32i    a8, a5, 0       /* next return address (for window size) */
104         mov     a5, a6          /* advance prev */
105         addi    a6, a7, -16     /* advance cur */
106 .Lfirstframe:
107         l32i    a7, a6, 4       /* a7 = next */
108         bge     a2, a7, .Lnextframe
110         /* At this point, prev (a5) points to the save area with the saved
111            values of a0-a3.  Copy those values into the save area at the
112            current sp so they will be reloaded when the return from this
113            function underflows.  We don't have to worry about exceptions
114            while updating the current save area, because the windows have
115            already been flushed.  */
117         addi    a4, sp, -16     /* a4 = save area of this function */
118         l32i    a6, a5, 0
119         l32i    a7, a5, 4
120         s32i    a6, a4, 0
121         s32i    a7, a4, 4
122         l32i    a6, a5, 8
123         l32i    a7, a5, 12
124         s32i    a6, a4, 8
125         s32i    a7, a4, 12
127         /* Set return address to goto handler.  Use the window size bits
128            from the return address two frames below the target.  */
129         extui   a8, a8, 30, 2   /* get window size from return addr. */
130         slli    a3, a3, 2       /* get goto handler addr. << 2 */
131         ssai    2
132         src     a0, a8, a3      /* combine them with a funnel shift */
134         retw
135         .size   __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto
138 /* __xtensa_sync_caches: This function is called after writing a trampoline
139    on the stack to force all the data writes to memory and invalidate the
140    instruction cache. a2 is the address of the new trampoline.
142    After the trampoline data is written out, it must be flushed out of
143    the data cache into memory.  We use DHWB in case we have a writeback
144    cache.  At least one DHWB instruction is needed for each data cache
145    line which may be touched by the trampoline.  An ISYNC instruction
146    must follow the DHWBs.
148    We have to flush the i-cache to make sure that the new values get used.
149    At least one IHI instruction is needed for each i-cache line which may
150    be touched by the trampoline.  An ISYNC instruction is also needed to
151    make sure that the modified instructions are loaded into the instruction
152    fetch buffer.  */
154 /* Use the maximum trampoline size.  Flushing a bit extra is OK.  */
155 #define TRAMPOLINE_SIZE 60
157         .text
158         .align  4
159         .global __xtensa_sync_caches
160         .type   __xtensa_sync_caches,@function
161 __xtensa_sync_caches:
162         entry   sp, 32
163 #if XCHAL_DCACHE_SIZE > 0
164         /* Flush the trampoline from the data cache.  */
165         extui   a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
166         addi    a4, a4, TRAMPOLINE_SIZE
167         addi    a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1
168         srli    a4, a4, XCHAL_DCACHE_LINEWIDTH
169         mov     a3, a2
170 .Ldcache_loop:
171         dhwb    a3, 0
172         addi    a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
173         addi    a4, a4, -1
174         bnez    a4, .Ldcache_loop
175         isync
176 #endif
177 #if XCHAL_ICACHE_SIZE > 0
178         /* Invalidate the corresponding lines in the instruction cache.  */
179         extui   a4, a2, 0, XCHAL_ICACHE_LINEWIDTH
180         addi    a4, a4, TRAMPOLINE_SIZE
181         addi    a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1
182         srli    a4, a4, XCHAL_ICACHE_LINEWIDTH
183 .Licache_loop:
184         ihi     a2, 0
185         addi    a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
186         addi    a4, a4, -1
187         bnez    a4, .Licache_loop
188 #endif
189         isync
190         retw
191         .size   __xtensa_sync_caches, .-__xtensa_sync_caches