]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/xtensa/lib2funcs.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / xtensa / lib2funcs.S
CommitLineData
f6b7ba2b 1/* Assembly functions for libgcc2.
fbd26352 2 Copyright (C) 2001-2019 Free Software Foundation, Inc.
f6b7ba2b 3 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
6bc9506f 9Software Foundation; either version 3, or (at your option) any later
f6b7ba2b 10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
6bc9506f 17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
f6b7ba2b 25
f112e975 26#include "xtensa-config.h"
f6b7ba2b 27
e17ee7e6 28/* __xtensa_libgcc_window_spill: This function flushes out all but the
29 current register window. This is used to set up the stack so that
1d60d981 30 arbitrary frames can be accessed. */
f6b7ba2b 31
b89c671b 32#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
e17ee7e6 33 .align 4
34 .global __xtensa_libgcc_window_spill
35 .type __xtensa_libgcc_window_spill,@function
f6b7ba2b 36__xtensa_libgcc_window_spill:
863356ea 37 entry sp, 48
38#if XCHAL_NUM_AREGS > 16
39 call12 1f
40 retw
41 .align 4
421:
43 .rept (XCHAL_NUM_AREGS - 24) / 12
44 _entry sp, 48
45 mov a12, a0
46 .endr
47 _entry sp, 16
48#if XCHAL_NUM_AREGS % 12 == 0
49 mov a4, a4
50#elif XCHAL_NUM_AREGS % 12 == 4
51 mov a8, a8
52#elif XCHAL_NUM_AREGS % 12 == 8
53 mov a12, a12
54#endif
55 retw
56#else
57 mov a8, a8
f6b7ba2b 58 retw
863356ea 59#endif
d33ad8b2 60 .size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill
b89c671b 61#endif
f6b7ba2b 62
63
64/* __xtensa_nonlocal_goto: This code does all the hard work of a
65 nonlocal goto on Xtensa. It is here in the library to avoid the
66 code size bloat of generating it in-line. There are two
67 arguments:
68
69 a2 = frame pointer for the procedure containing the label
70 a3 = goto handler address
71
72 This function never returns to its caller but instead goes directly
73 to the address of the specified goto handler. */
74
b89c671b 75#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
f6b7ba2b 76 .align 4
77 .global __xtensa_nonlocal_goto
78 .type __xtensa_nonlocal_goto,@function
79__xtensa_nonlocal_goto:
80 entry sp, 32
81
d33ad8b2 82 /* Flush registers. */
863356ea 83 call8 __xtensa_libgcc_window_spill
f6b7ba2b 84
85 /* Because the save area for a0-a3 is stored one frame below
86 the one identified by a2, the only way to restore those
87 registers is to unwind the stack. If alloca() were never
88 called, we could just unwind until finding the sp value
89 matching a2. However, a2 is a frame pointer, not a stack
90 pointer, and may not be encountered during the unwinding.
91 The solution is to unwind until going _past_ the value
92 given by a2. This involves keeping three stack pointer
93 values during the unwinding:
94
95 next = sp of frame N-1
96 cur = sp of frame N
97 prev = sp of frame N+1
98
99 When next > a2, the desired save area is stored relative
100 to prev. At this point, cur will be the same as a2
101 except in the alloca() case.
102
103 Besides finding the values to be restored to a0-a3, we also
104 need to find the current window size for the target
105 function. This can be extracted from the high bits of the
106 return address, initially in a0. As the unwinding
107 proceeds, the window size is taken from the value of a0
1d60d981 108 saved _two_ frames below the current frame. */
f6b7ba2b 109
d33ad8b2 110 addi a5, sp, -16 /* a5 = prev - save area */
f6b7ba2b 111 l32i a6, a5, 4
d33ad8b2 112 addi a6, a6, -16 /* a6 = cur - save area */
113 mov a8, a0 /* a8 = return address (for window size) */
f6b7ba2b 114 j .Lfirstframe
115
d33ad8b2 116.Lnextframe:
117 l32i a8, a5, 0 /* next return address (for window size) */
118 mov a5, a6 /* advance prev */
119 addi a6, a7, -16 /* advance cur */
120.Lfirstframe:
121 l32i a7, a6, 4 /* a7 = next */
98d31fbc 122 bgeu a2, a7, .Lnextframe
f6b7ba2b 123
124 /* At this point, prev (a5) points to the save area with the saved
125 values of a0-a3. Copy those values into the save area at the
126 current sp so they will be reloaded when the return from this
127 function underflows. We don't have to worry about exceptions
128 while updating the current save area, because the windows have
1d60d981 129 already been flushed. */
f6b7ba2b 130
d33ad8b2 131 addi a4, sp, -16 /* a4 = save area of this function */
f6b7ba2b 132 l32i a6, a5, 0
133 l32i a7, a5, 4
134 s32i a6, a4, 0
135 s32i a7, a4, 4
136 l32i a6, a5, 8
d33ad8b2 137 l32i a7, a5, 12
f6b7ba2b 138 s32i a6, a4, 8
139 s32i a7, a4, 12
d33ad8b2 140
f6b7ba2b 141 /* Set return address to goto handler. Use the window size bits
1d60d981 142 from the return address two frames below the target. */
d33ad8b2 143 extui a8, a8, 30, 2 /* get window size from return addr. */
144 slli a3, a3, 2 /* get goto handler addr. << 2 */
f6b7ba2b 145 ssai 2
d33ad8b2 146 src a0, a8, a3 /* combine them with a funnel shift */
f6b7ba2b 147
148 retw
d33ad8b2 149 .size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto
b89c671b 150#endif
f6b7ba2b 151
152
153/* __xtensa_sync_caches: This function is called after writing a trampoline
154 on the stack to force all the data writes to memory and invalidate the
155 instruction cache. a2 is the address of the new trampoline.
156
157 After the trampoline data is written out, it must be flushed out of
158 the data cache into memory. We use DHWB in case we have a writeback
159 cache. At least one DHWB instruction is needed for each data cache
160 line which may be touched by the trampoline. An ISYNC instruction
161 must follow the DHWBs.
162
163 We have to flush the i-cache to make sure that the new values get used.
164 At least one IHI instruction is needed for each i-cache line which may
165 be touched by the trampoline. An ISYNC instruction is also needed to
166 make sure that the modified instructions are loaded into the instruction
1d60d981 167 fetch buffer. */
027edd6b 168
57ffde16 169/* Use the maximum trampoline size. Flushing a bit extra is OK. */
82261032 170#define TRAMPOLINE_SIZE 60
f6b7ba2b 171
172 .text
173 .align 4
174 .global __xtensa_sync_caches
175 .type __xtensa_sync_caches,@function
176__xtensa_sync_caches:
b89c671b 177#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
f6b7ba2b 178 entry sp, 32
b89c671b 179#endif
d2cfc124 180#if XCHAL_DCACHE_SIZE > 0
d33ad8b2 181 /* Flush the trampoline from the data cache. */
f6b7ba2b 182 extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
183 addi a4, a4, TRAMPOLINE_SIZE
184 addi a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1
185 srli a4, a4, XCHAL_DCACHE_LINEWIDTH
186 mov a3, a2
187.Ldcache_loop:
188 dhwb a3, 0
189 addi a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
190 addi a4, a4, -1
191 bnez a4, .Ldcache_loop
192 isync
d33ad8b2 193#endif
f6b7ba2b 194#if XCHAL_ICACHE_SIZE > 0
d33ad8b2 195 /* Invalidate the corresponding lines in the instruction cache. */
f6b7ba2b 196 extui a4, a2, 0, XCHAL_ICACHE_LINEWIDTH
197 addi a4, a4, TRAMPOLINE_SIZE
198 addi a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1
199 srli a4, a4, XCHAL_ICACHE_LINEWIDTH
200.Licache_loop:
201 ihi a2, 0
202 addi a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
203 addi a4, a4, -1
204 bnez a4, .Licache_loop
f6b7ba2b 205#endif
b50d211f 206 isync
b89c671b 207#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
f6b7ba2b 208 retw
b89c671b 209#else
210 ret
211#endif
d33ad8b2 212 .size __xtensa_sync_caches, .-__xtensa_sync_caches