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