OSDN Git Service

bdc26e85cc5c93b4c4315f7e098967db69063c1f
[pf3gnuchains/gcc-fork.git] / gcc / config / xtensa / lib2funcs.S
1 /* Assembly functions for libgcc2.
2    Copyright (C) 2001 Free Software Foundation, Inc.
3    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
4
5 This file is part of GCC.
6
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.
11
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.)
20
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.
25
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, 59 Temple Place - Suite 330, Boston, MA
29 02111-1307, USA.  */
30
31 #include "xtensa/xtensa-config.h"
32
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. */
36
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
46
47
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:
52
53         a2 = frame pointer for the procedure containing the label
54         a3 = goto handler address
55
56   This function never returns to its caller but instead goes directly
57   to the address of the specified goto handler.  */
58
59         .align  4
60         .global __xtensa_nonlocal_goto
61         .type   __xtensa_nonlocal_goto,@function
62 __xtensa_nonlocal_goto:
63         entry   sp, 32
64
65         /* flush registers */
66         mov     a5, a2
67         movi    a2, 0
68         syscall
69         mov     a2, a5
70
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:
80
81                 next = sp of frame N-1
82                 cur = sp of frame N
83                 prev = sp of frame N+1
84
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.
88
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. */
95
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
101
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
109
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. */
116
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
126         
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
133
134         retw
135         .size   __xtensa_nonlocal_goto,.-__xtensa_nonlocal_goto
136
137
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.
141
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.
147
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. */
153         
154 #define TRAMPOLINE_SIZE 49
155
156         .text
157         .align  4
158         .global __xtensa_sync_caches
159         .type   __xtensa_sync_caches,@function
160 __xtensa_sync_caches:
161         entry   sp, 32
162 #if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
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
168         mov     a3, a2
169 .Ldcache_loop:
170         dhwb    a3, 0
171         addi    a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
172         addi    a4, a4, -1
173         bnez    a4, .Ldcache_loop
174         isync
175 #endif 
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
182 .Licache_loop:
183         ihi     a2, 0
184         addi    a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
185         addi    a4, a4, -1
186         bnez    a4, .Licache_loop
187         isync
188 #endif
189         retw
190         .size   __xtensa_sync_caches,.-__xtensa_sync_caches