]>
Commit | Line | Data |
---|---|---|
390b6370 | 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 | * | |
fbd26352 | 5 | * Copyright (C) 2004-2019 Free Software Foundation, Inc. |
390b6370 | 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 | |
6bc9506f | 9 | * Free Software Foundation; either version 3, or (at your option) any |
390b6370 | 10 | * later version. |
11 | * | |
390b6370 | 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 | * | |
6bc9506f | 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/>. | |
390b6370 | 25 | */ |
26 | ||
d42ef213 | 27 | #ifndef __ppc64__ |
28 | ||
19f8705d | 29 | .machine ppc7400 |
390b6370 | 30 | .data |
31 | .align 2 | |
32 | ||
33 | #ifdef __DYNAMIC__ | |
34 | ||
35 | .non_lazy_symbol_pointer | |
36 | L_has_vec$non_lazy_ptr: | |
37 | .indirect_symbol __cpu_has_altivec | |
38 | .long 0 | |
390b6370 | 39 | #else |
40 | ||
41 | /* For static, "pretend" we have a non-lazy-pointer. */ | |
42 | ||
43 | L_has_vec$non_lazy_ptr: | |
44 | .long __cpu_has_altivec | |
45 | ||
46 | #endif | |
47 | ||
48 | ||
49 | .text | |
50 | .align 2 | |
51 | ||
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.) | |
55 | ||
56 | SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11 | |
d42ef213 | 57 | (the stack frame size) as parameters. It returns the updated VRsave |
58 | in R0 if we`re on a CPU with vector regs. | |
390b6370 | 59 | |
d42ef213 | 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. | |
390b6370 | 62 | |
63 | USES: R0 R11 R12 */ | |
64 | ||
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 | |
109 | ||
110 | L$saveVMX: | |
111 | /* We're saving Vector regs too. */ | |
112 | /* Restore CR from R0. No More Branches! */ | |
113 | mtcr r0 | |
114 | ||
115 | /* We should really use VRSAVE to figure out which vector regs | |
116 | we actually need to save and restore. Some other time :-/ */ | |
117 | ||
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 | |
d42ef213 | 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 | |
390b6370 | 146 | blr |
147 | ||
d42ef213 | 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. */ | |
150 | ||
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 | |
390b6370 | 157 | |
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. | |
160 | ||
d42ef213 | 161 | clobbers: R0, R7, R11 and R12 |
162 | uses : R10 | |
163 | RETURNS : C++ EH Data registers (R3 - R6). */ | |
390b6370 | 164 | |
d42ef213 | 165 | .private_extern eh_rest_world_r10 |
390b6370 | 166 | eh_rest_world_r10: |
d42ef213 | 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.) */ | |
390b6370 | 172 | lwz r6,-420(r11) |
173 | lwz r5,-424(r11) | |
174 | lwz r4,-428(r11) | |
175 | lwz r3,-432(r11) | |
176 | ||
d42ef213 | 177 | /* Fall through to Lrest_world_eh_r7. */ |
390b6370 | 178 | |
d42ef213 | 179 | /* When we are doing the exception-handling epilog, R7 contains the offset to |
180 | add to the SP. | |
390b6370 | 181 | |
d42ef213 | 182 | clobbers: R0, R11 and R12 |
183 | uses : R7. */ | |
390b6370 | 184 | |
d42ef213 | 185 | Lrest_world_eh_r7: |
186 | /* See if we have Altivec. */ | |
187 | bcl 20,31,Lr7$pb | |
188 | Lr7$pb: mflr r12 | |
189 | ||
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 */ | |
390b6370 | 193 | cmpwi r12,0 |
194 | lmw r13,-220(r11) | |
195 | beq L.rest_world_fp_eh | |
d42ef213 | 196 | |
197 | /* We have Altivec, restore VRsave and V20..V31 */ | |
390b6370 | 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 | |
224 | ||
225 | L.rest_world_fp_eh: | |
d42ef213 | 226 | lwz r0,4(r11) /* recover saved CR */ |
390b6370 | 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) | |
d42ef213 | 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 */ | |
390b6370 | 249 | bctr |
d42ef213 | 250 | #endif |
251 | /* we should never be called on ppc64 for this ... */ | |
252 | /* Done. */ |