[gcc]
[official-gcc.git] / libgcc / config / rs6000 / darwin-world.S
blob4ccd6e2bae9d2908e51c1c10672e8ea67f919bc7
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-2018 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  */ 
27 #ifndef __ppc64__
29         .machine ppc7400
30 .data
31         .align 2
33 #ifdef __DYNAMIC__
35 .non_lazy_symbol_pointer
36 L_has_vec$non_lazy_ptr:
37         .indirect_symbol __cpu_has_altivec
38         .long   0
39 #else
41 /* For static, "pretend" we have a non-lazy-pointer.  */
43 L_has_vec$non_lazy_ptr:
44         .long __cpu_has_altivec
46 #endif
49 .text
50         .align 2
52 /* save_world and rest_world save/restore F14-F31 and possibly V20-V31
53    (assuming you have a CPU with vector registers; we use a global var
54    provided by the System Framework to determine this.)
56    SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11
57    (the stack frame size) as parameters.  It returns the updated VRsave
58    in R0 if we`re on a CPU with vector regs.
60    For gcc3 onward, we need to save and restore CR as well, since scheduled
61    prologs can cause comparisons to be moved before calls to save_world.
63    USES: R0 R11 R12  */
65 .private_extern save_world
66 save_world:
67         stw r0,8(r1)
68         mflr r0
69         bcl 20,31,Ls$pb
70 Ls$pb:  mflr r12
71         addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Ls$pb)
72         lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12)
73         mtlr r0
74         lwz r12,0(r12)
75                                 /* grab CR  */
76         mfcr r0 
77                                 /* test HAS_VEC  */
78         cmpwi r12,0
79         stfd f14,-144(r1)
80         stfd f15,-136(r1)
81         stfd f16,-128(r1)
82         stfd f17,-120(r1)
83         stfd f18,-112(r1)
84         stfd f19,-104(r1)
85         stfd f20,-96(r1)
86         stfd f21,-88(r1)
87         stfd f22,-80(r1)
88         stfd f23,-72(r1)
89         stfd f24,-64(r1)
90         stfd f25,-56(r1)
91         stfd f26,-48(r1)
92         stfd f27,-40(r1)
93         stfd f28,-32(r1)
94         stfd f29,-24(r1)
95         stfd f30,-16(r1)
96         stfd f31,-8(r1)
97         stmw r13,-220(r1)
98                                 /* stash CR  */
99         stw r0,4(r1)
100                                 /* set R12 pointing at Vector Reg save area  */
101         addi r12,r1,-224
102                                 /* allocate stack frame  */
103         stwux r1,r1,r11
104                                 /* ...but return if HAS_VEC is zero   */
105         bne+ L$saveVMX
106                                 /* Not forgetting to restore CR.  */
107         mtcr r0
108         blr
110 L$saveVMX:
111                                 /* We're saving Vector regs too.  */
112                                 /* Restore CR from R0.  No More Branches!  */
113         mtcr r0
115         /* We should really use VRSAVE to figure out which vector regs
116            we actually need to save and restore.  Some other time :-/  */
118         li r11,-192
119         stvx v20,r11,r12
120         li r11,-176
121         stvx v21,r11,r12
122         li r11,-160
123         stvx v22,r11,r12
124         li r11,-144
125         stvx v23,r11,r12
126         li r11,-128
127         stvx v24,r11,r12
128         li r11,-112
129         stvx v25,r11,r12
130         li r11,-96
131         stvx v26,r11,r12
132         li r11,-80
133         stvx v27,r11,r12
134         li r11,-64
135         stvx v28,r11,r12
136         li r11,-48
137         stvx v29,r11,r12
138         li r11,-32
139         stvx v30,r11,r12
140         mfspr r0,VRsave
141         li r11,-16
142         stvx v31,r11,r12        
143         stw r0,0(r12)           /* VRsave lives at -224(R1).  */
144         ori r0,r0,0xfff         /* We just saved these.  */
145         mtspr VRsave,r0
146         blr
148 /* rest_world  is jumped to, not called, so no need to worry about LR.
149    clobbers R0, R7, R11 and R12.  This just undoes the work done above.  */
151         .private_extern rest_world
152 rest_world:
153                                 
154         lwz r11, 0(r1)          /* Pickup previous SP  */
155         li r7, 0                /* Stack offset is zero, r10 is ignored.  */
156         b Lrest_world_eh_r7
158 /* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR.
159    R10 is the C++ EH stack adjust parameter, we return to the caller`s caller.
161    clobbers: R0, R7, R11 and R12
162    uses    : R10
163    RETURNS : C++ EH Data registers (R3 - R6).  */
165         .private_extern eh_rest_world_r10
166 eh_rest_world_r10:
167                                 
168         lwz r11, 0(r1)          /* Pickup previous SP  */
169         mr  r7,r10              /* Stack offset.  */
170         
171         /* pickup the C++ EH data regs (R3 - R6.)  */
172         lwz r6,-420(r11)
173         lwz r5,-424(r11)
174         lwz r4,-428(r11)
175         lwz r3,-432(r11)
177         /* Fall through to Lrest_world_eh_r7.  */
179 /* When we are doing the exception-handling epilog, R7 contains the offset to
180    add to the SP.
182    clobbers: R0, R11 and R12
183    uses    : R7.  */
185 Lrest_world_eh_r7:
186         /* See if we have Altivec.  */
187         bcl 20,31,Lr7$pb
188 Lr7$pb: mflr r12
190         addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7$pb)
191         lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7$pb)(r12)
192         lwz r12,0(r12)          /* R12 := HAS_VEC  */
193         cmpwi r12,0
194         lmw r13,-220(r11)
195         beq L.rest_world_fp_eh
197         /* We have Altivec, restore VRsave and V20..V31  */
198         lwz r0,-224(r11)
199         li r12,-416
200         mtspr VRsave,r0
201         lvx v20,r11,r12
202         li r12,-400
203         lvx v21,r11,r12
204         li r12,-384
205         lvx v22,r11,r12
206         li r12,-368
207         lvx v23,r11,r12
208         li r12,-352
209         lvx v24,r11,r12
210         li r12,-336
211         lvx v25,r11,r12
212         li r12,-320
213         lvx v26,r11,r12
214         li r12,-304
215         lvx v27,r11,r12
216         li r12,-288
217         lvx v28,r11,r12
218         li r12,-272
219         lvx v29,r11,r12
220         li r12,-256
221         lvx v30,r11,r12
222         li r12,-240
223         lvx v31,r11,r12
225 L.rest_world_fp_eh:
226         lwz r0,4(r11)           /* recover saved CR  */
227         lfd f14,-144(r11)
228         lfd f15,-136(r11)
229         lfd f16,-128(r11)
230         lfd f17,-120(r11)
231         lfd f18,-112(r11)
232         lfd f19,-104(r11)
233         lfd f20,-96(r11)
234         lfd f21,-88(r11)
235         lfd f22,-80(r11)
236         lfd f23,-72(r11)
237         lfd f24,-64(r11)
238         lfd f25,-56(r11)
239         lfd f26,-48(r11)
240         lfd f27,-40(r11)
241         lfd f28,-32(r11)
242         lfd f29,-24(r11)
243         lfd f30,-16(r11)
244         mtcr r0                 /* restore the saved cr.  */
245         lwz r0, 8(r11)          /* Pick up the 'real' return address.  */
246         lfd f31,-8(r11)         
247         mtctr r0                /* exception-handler ret. address  */
248         add r1,r11,r7           /* set SP to original value + R7 offset  */
249         bctr
250 #endif
251 /* we should never be called on ppc64 for this ... */
252 /* Done.  */