OSDN Git Service

Move libgcc1 to toplevel libgcc
[pf3gnuchains/gcc-fork.git] / libgcc / config / rs6000 / darwin-world.S
1 /*  This file contains the exception-handling save_world and
2  *  restore_world routines, which need to do a run-time check to see if
3  *  they should save and restore the vector registers.
4  *
5  *   Copyright (C) 2004, 2009 Free Software Foundation, Inc.
6  * 
7  * This file is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 3, or (at your option) any
10  * later version.
11  * 
12  * This file is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  * 
17  * Under Section 7 of GPL version 3, you are granted additional
18  * permissions described in the GCC Runtime Library Exception, version
19  * 3.1, as published by the Free Software Foundation.
20  *
21  * You should have received a copy of the GNU General Public License and
22  * a copy of the GCC Runtime Library Exception along with this program;
23  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24  * <http://www.gnu.org/licenses/>.
25  */ 
26
27         .machine ppc7400
28 .data
29         .align 2
30
31 #ifdef __DYNAMIC__
32
33 .non_lazy_symbol_pointer
34 L_has_vec$non_lazy_ptr:
35         .indirect_symbol __cpu_has_altivec
36 #ifdef __ppc64__
37         .quad   0
38 #else
39         .long   0
40 #endif
41
42 #else
43
44 /* For static, "pretend" we have a non-lazy-pointer.  */
45
46 L_has_vec$non_lazy_ptr:
47         .long __cpu_has_altivec
48
49 #endif
50
51
52 .text
53         .align 2
54
55 /* save_world and rest_world save/restore F14-F31 and possibly V20-V31
56    (assuming you have a CPU with vector registers; we use a global var
57    provided by the System Framework to determine this.)
58
59    SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11
60    (the stack frame size) as parameters.  It returns VRsave in R0 if
61    we`re on a CPU with vector regs.
62
63    With gcc3, we now need to save and restore CR as well, since gcc3's
64    scheduled prologs can cause comparisons to be moved before calls to
65    save_world!
66
67    USES: R0 R11 R12  */
68
69 .private_extern save_world
70 save_world:
71         stw r0,8(r1)
72         mflr r0
73         bcl 20,31,Ls$pb
74 Ls$pb:  mflr r12
75         addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Ls$pb)
76         lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12)
77         mtlr r0
78         lwz r12,0(r12)
79                                 /* grab CR  */
80         mfcr r0 
81                                 /* test HAS_VEC  */
82         cmpwi r12,0
83         stfd f14,-144(r1)
84         stfd f15,-136(r1)
85         stfd f16,-128(r1)
86         stfd f17,-120(r1)
87         stfd f18,-112(r1)
88         stfd f19,-104(r1)
89         stfd f20,-96(r1)
90         stfd f21,-88(r1)
91         stfd f22,-80(r1)
92         stfd f23,-72(r1)
93         stfd f24,-64(r1)
94         stfd f25,-56(r1)
95         stfd f26,-48(r1)
96         stfd f27,-40(r1)
97         stfd f28,-32(r1)
98         stfd f29,-24(r1)
99         stfd f30,-16(r1)
100         stfd f31,-8(r1)
101         stmw r13,-220(r1)
102                                 /* stash CR  */
103         stw r0,4(r1)
104                                 /* set R12 pointing at Vector Reg save area  */
105         addi r12,r1,-224
106                                 /* allocate stack frame  */
107         stwux r1,r1,r11
108                                 /* ...but return if HAS_VEC is zero   */
109         bne+ L$saveVMX
110                                 /* Not forgetting to restore CR.  */
111         mtcr r0
112         blr
113
114 L$saveVMX:
115                                 /* We're saving Vector regs too.  */
116                                 /* Restore CR from R0.  No More Branches!  */
117         mtcr r0
118
119         /* We should really use VRSAVE to figure out which vector regs
120            we actually need to save and restore.  Some other time :-/  */
121
122         li r11,-192
123         stvx v20,r11,r12
124         li r11,-176
125         stvx v21,r11,r12
126         li r11,-160
127         stvx v22,r11,r12
128         li r11,-144
129         stvx v23,r11,r12
130         li r11,-128
131         stvx v24,r11,r12
132         li r11,-112
133         stvx v25,r11,r12
134         li r11,-96
135         stvx v26,r11,r12
136         li r11,-80
137         stvx v27,r11,r12
138         li r11,-64
139         stvx v28,r11,r12
140         li r11,-48
141         stvx v29,r11,r12
142         li r11,-32
143         stvx v30,r11,r12
144         mfspr r0,VRsave
145         li r11,-16
146         stvx v31,r11,r12
147                                 /* VRsave lives at -224(R1)  */
148         stw r0,0(r12)
149         blr
150
151
152 /* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR.
153    R10 is the C++ EH stack adjust parameter, we return to the caller`s caller.
154
155    USES: R0 R10 R11 R12   and R7 R8
156    RETURNS: C++ EH Data registers (R3 - R6.)
157
158    We now set up R7/R8 and jump to rest_world_eh_r7r8.
159
160    rest_world doesn't use the R10 stack adjust parameter, nor does it
161    pick up the R3-R6 exception handling stuff.  */
162
163 .private_extern rest_world
164 rest_world:
165                                 /* Pickup previous SP  */
166         lwz r11, 0(r1)
167         li r7, 0
168         lwz r8, 8(r11)
169         li r10, 0
170         b rest_world_eh_r7r8
171
172 .private_extern eh_rest_world_r10
173 eh_rest_world_r10:
174                                 /* Pickup previous SP  */
175         lwz r11, 0(r1)
176         mr  r7,r10
177         lwz r8, 8(r11)
178                         /* pickup the C++ EH data regs (R3 - R6.)  */
179         lwz r6,-420(r11)
180         lwz r5,-424(r11)
181         lwz r4,-428(r11)
182         lwz r3,-432(r11)
183
184         b rest_world_eh_r7r8
185
186 /* rest_world_eh_r7r8 is jumped to -- not called! -- when we're doing
187    the exception-handling epilog.  R7 contains the offset to add to
188    the SP, and R8 contains the 'real' return address.
189
190    USES: R0 R11 R12  [R7/R8]
191    RETURNS: C++ EH Data registers (R3 - R6.)  */
192
193 rest_world_eh_r7r8:
194         bcl 20,31,Lr7r8$pb
195 Lr7r8$pb: mflr r12
196         lwz r11,0(r1)
197                                 /* R11 := previous SP  */
198         addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7r8$pb)
199         lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7r8$pb)(r12)
200         lwz r0,4(r11)
201                                 /* R0 := old CR  */
202         lwz r12,0(r12)
203                                 /* R12 := HAS_VEC  */
204         mtcr r0 
205         cmpwi r12,0
206         lmw r13,-220(r11)
207         beq L.rest_world_fp_eh
208                                 /* restore VRsave and V20..V31  */
209         lwz r0,-224(r11)
210         li r12,-416
211         mtspr VRsave,r0
212         lvx v20,r11,r12
213         li r12,-400
214         lvx v21,r11,r12
215         li r12,-384
216         lvx v22,r11,r12
217         li r12,-368
218         lvx v23,r11,r12
219         li r12,-352
220         lvx v24,r11,r12
221         li r12,-336
222         lvx v25,r11,r12
223         li r12,-320
224         lvx v26,r11,r12
225         li r12,-304
226         lvx v27,r11,r12
227         li r12,-288
228         lvx v28,r11,r12
229         li r12,-272
230         lvx v29,r11,r12
231         li r12,-256
232         lvx v30,r11,r12
233         li r12,-240
234         lvx v31,r11,r12
235
236 L.rest_world_fp_eh:
237         lfd f14,-144(r11)
238         lfd f15,-136(r11)
239         lfd f16,-128(r11)
240         lfd f17,-120(r11)
241         lfd f18,-112(r11)
242         lfd f19,-104(r11)
243         lfd f20,-96(r11)
244         lfd f21,-88(r11)
245         lfd f22,-80(r11)
246         lfd f23,-72(r11)
247         lfd f24,-64(r11)
248         lfd f25,-56(r11)
249         lfd f26,-48(r11)
250         lfd f27,-40(r11)
251         lfd f28,-32(r11)
252         lfd f29,-24(r11)
253         lfd f30,-16(r11)
254                         /* R8 is the exception-handler's address  */
255         mtctr r8
256         lfd f31,-8(r11)
257                         /* set SP to original value + R7 offset  */
258         add r1,r11,r7
259         bctr