1 /* Assembly functions for libgcc2.
2 Copyright (C) 2001 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
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
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
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
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. */
38 .global __xtensa_libgcc_window_spill
39 .type __xtensa_libgcc_window_spill,@function
40 __xtensa_libgcc_window_spill:
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
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. */
60 .global __xtensa_nonlocal_goto
61 .type __xtensa_nonlocal_goto,@function
62 __xtensa_nonlocal_goto:
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
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
98 addi a6, a6, -16 # a6 = cur - save area
99 mov a8, a0 # a8 = return address (for window size)
103 l32i a8, a5, 0 # next return address (for window size)
104 mov a5, a6 # advance prev
105 addi a6, a7, -16 # advance cur
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
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
132 src a0, a8, a3 # combine them with a funnel shift
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
154 #define TRAMPOLINE_SIZE 60
158 .global __xtensa_sync_caches
159 .type __xtensa_sync_caches,@function
160 __xtensa_sync_caches:
162 #if XCHAL_DCACHE_SIZE > 0
163 # Flush the trampoline from the data cache
164 extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
165 addi a4, a4, TRAMPOLINE_SIZE
166 addi a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1
167 srli a4, a4, XCHAL_DCACHE_LINEWIDTH
171 addi a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
173 bnez a4, .Ldcache_loop
176 #if XCHAL_ICACHE_SIZE > 0
177 # Invalidate the corresponding lines in the instruction cache
178 extui a4, a2, 0, XCHAL_ICACHE_LINEWIDTH
179 addi a4, a4, TRAMPOLINE_SIZE
180 addi a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1
181 srli a4, a4, XCHAL_ICACHE_LINEWIDTH
184 addi a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
186 bnez a4, .Licache_loop
190 .size __xtensa_sync_caches,.-__xtensa_sync_caches