]>
Commit | Line | Data |
---|---|---|
efdc5d91 AP |
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 | * | |
748086b7 | 5 | * Copyright (C) 2004, 2009 Free Software Foundation, Inc. |
efdc5d91 AP |
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 | |
748086b7 | 9 | * Free Software Foundation; either version 3, or (at your option) any |
efdc5d91 AP |
10 | * later version. |
11 | * | |
efdc5d91 AP |
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 | * | |
748086b7 JJ |
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/>. | |
efdc5d91 AP |
25 | */ |
26 | ||
c4e18b1c | 27 | .machine ppc7400 |
efdc5d91 AP |
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 | |
76419821 SS |
36 | #ifdef __ppc64__ |
37 | .quad 0 | |
38 | #else | |
efdc5d91 | 39 | .long 0 |
76419821 | 40 | #endif |
efdc5d91 AP |
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 |