]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/xtensa/lib2funcs.S
Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[thirdparty/gcc.git] / gcc / config / xtensa / lib2funcs.S
CommitLineData
03984308 1/* Assembly functions for libgcc2.
748086b7 2 Copyright (C) 2001, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
03984308
BW
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
748086b7 9Software Foundation; either version 3, or (at your option) any later
03984308
BW
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
748086b7
JJ
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/>. */
03984308 25
e677f70c 26#include "xtensa-config.h"
03984308 27
57174693
BW
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
ff482c8d 30 arbitrary frames can be accessed. */
03984308 31
57174693
BW
32 .align 4
33 .global __xtensa_libgcc_window_spill
34 .type __xtensa_libgcc_window_spill,@function
03984308 35__xtensa_libgcc_window_spill:
57174693
BW
36 entry sp, 32
37 movi a2, 0
38 syscall
03984308 39 retw
76f6e118 40 .size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill
03984308
BW
41
42
43/* __xtensa_nonlocal_goto: This code does all the hard work of a
44 nonlocal goto on Xtensa. It is here in the library to avoid the
45 code size bloat of generating it in-line. There are two
46 arguments:
47
48 a2 = frame pointer for the procedure containing the label
49 a3 = goto handler address
50
51 This function never returns to its caller but instead goes directly
52 to the address of the specified goto handler. */
53
54 .align 4
55 .global __xtensa_nonlocal_goto
56 .type __xtensa_nonlocal_goto,@function
57__xtensa_nonlocal_goto:
58 entry sp, 32
59
76f6e118 60 /* Flush registers. */
57174693
BW
61 mov a5, a2
62 movi a2, 0
63 syscall
64 mov a2, a5
03984308
BW
65
66 /* Because the save area for a0-a3 is stored one frame below
67 the one identified by a2, the only way to restore those
68 registers is to unwind the stack. If alloca() were never
69 called, we could just unwind until finding the sp value
70 matching a2. However, a2 is a frame pointer, not a stack
71 pointer, and may not be encountered during the unwinding.
72 The solution is to unwind until going _past_ the value
73 given by a2. This involves keeping three stack pointer
74 values during the unwinding:
75
76 next = sp of frame N-1
77 cur = sp of frame N
78 prev = sp of frame N+1
79
80 When next > a2, the desired save area is stored relative
81 to prev. At this point, cur will be the same as a2
82 except in the alloca() case.
83
84 Besides finding the values to be restored to a0-a3, we also
85 need to find the current window size for the target
86 function. This can be extracted from the high bits of the
87 return address, initially in a0. As the unwinding
88 proceeds, the window size is taken from the value of a0
ff482c8d 89 saved _two_ frames below the current frame. */
03984308 90
76f6e118 91 addi a5, sp, -16 /* a5 = prev - save area */
03984308 92 l32i a6, a5, 4
76f6e118
BW
93 addi a6, a6, -16 /* a6 = cur - save area */
94 mov a8, a0 /* a8 = return address (for window size) */
03984308
BW
95 j .Lfirstframe
96
76f6e118
BW
97.Lnextframe:
98 l32i a8, a5, 0 /* next return address (for window size) */
99 mov a5, a6 /* advance prev */
100 addi a6, a7, -16 /* advance cur */
101.Lfirstframe:
102 l32i a7, a6, 4 /* a7 = next */
9e8c2a98 103 bgeu a2, a7, .Lnextframe
03984308
BW
104
105 /* At this point, prev (a5) points to the save area with the saved
106 values of a0-a3. Copy those values into the save area at the
107 current sp so they will be reloaded when the return from this
108 function underflows. We don't have to worry about exceptions
109 while updating the current save area, because the windows have
ff482c8d 110 already been flushed. */
03984308 111
76f6e118 112 addi a4, sp, -16 /* a4 = save area of this function */
03984308
BW
113 l32i a6, a5, 0
114 l32i a7, a5, 4
115 s32i a6, a4, 0
116 s32i a7, a4, 4
117 l32i a6, a5, 8
76f6e118 118 l32i a7, a5, 12
03984308
BW
119 s32i a6, a4, 8
120 s32i a7, a4, 12
76f6e118 121
03984308 122 /* Set return address to goto handler. Use the window size bits
ff482c8d 123 from the return address two frames below the target. */
76f6e118
BW
124 extui a8, a8, 30, 2 /* get window size from return addr. */
125 slli a3, a3, 2 /* get goto handler addr. << 2 */
03984308 126 ssai 2
76f6e118 127 src a0, a8, a3 /* combine them with a funnel shift */
03984308
BW
128
129 retw
76f6e118 130 .size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto
03984308
BW
131
132
133/* __xtensa_sync_caches: This function is called after writing a trampoline
134 on the stack to force all the data writes to memory and invalidate the
135 instruction cache. a2 is the address of the new trampoline.
136
137 After the trampoline data is written out, it must be flushed out of
138 the data cache into memory. We use DHWB in case we have a writeback
139 cache. At least one DHWB instruction is needed for each data cache
140 line which may be touched by the trampoline. An ISYNC instruction
141 must follow the DHWBs.
142
143 We have to flush the i-cache to make sure that the new values get used.
144 At least one IHI instruction is needed for each i-cache line which may
145 be touched by the trampoline. An ISYNC instruction is also needed to
146 make sure that the modified instructions are loaded into the instruction
ff482c8d 147 fetch buffer. */
13fb3a61 148
7f0ee694 149/* Use the maximum trampoline size. Flushing a bit extra is OK. */
85333688 150#define TRAMPOLINE_SIZE 60
03984308
BW
151
152 .text
153 .align 4
154 .global __xtensa_sync_caches
155 .type __xtensa_sync_caches,@function
156__xtensa_sync_caches:
157 entry sp, 32
1839841c 158#if XCHAL_DCACHE_SIZE > 0
76f6e118 159 /* Flush the trampoline from the data cache. */
03984308
BW
160 extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
161 addi a4, a4, TRAMPOLINE_SIZE
162 addi a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1
163 srli a4, a4, XCHAL_DCACHE_LINEWIDTH
164 mov a3, a2
165.Ldcache_loop:
166 dhwb a3, 0
167 addi a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
168 addi a4, a4, -1
169 bnez a4, .Ldcache_loop
170 isync
76f6e118 171#endif
03984308 172#if XCHAL_ICACHE_SIZE > 0
76f6e118 173 /* Invalidate the corresponding lines in the instruction cache. */
03984308
BW
174 extui a4, a2, 0, XCHAL_ICACHE_LINEWIDTH
175 addi a4, a4, TRAMPOLINE_SIZE
176 addi a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1
177 srli a4, a4, XCHAL_ICACHE_LINEWIDTH
178.Licache_loop:
179 ihi a2, 0
180 addi a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
181 addi a4, a4, -1
182 bnez a4, .Licache_loop
03984308 183#endif
9502767b 184 isync
03984308 185 retw
76f6e118 186 .size __xtensa_sync_caches, .-__xtensa_sync_caches