annotate libgcc/config/xtensa/lib2funcs.S @ 158:494b0b89df80 default tip

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