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-2016 Free Software Foundation, Inc.
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
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.
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.
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/>.
35 .non_lazy_symbol_pointer
36 L_has_vec$non_lazy_ptr:
37 .indirect_symbol __cpu_has_altivec
41 /* For static, "pretend" we have a non-lazy-pointer. */
43 L_has_vec$non_lazy_ptr:
44 .long __cpu_has_altivec
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.
65 .private_extern save_world
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)
100 /* set R12 pointing at Vector Reg save area */
102 /* allocate stack frame */
104 /* ...but return if HAS_VEC is zero */
106 /* Not forgetting to restore CR. */
111 /* We're saving Vector regs too. */
112 /* Restore CR from R0. No More Branches! */
115 /* We should really use VRSAVE to figure out which vector regs
116 we actually need to save and restore. Some other time :-/ */
143 stw r0,0(r12) /* VRsave lives at -224(R1). */
144 ori r0,r0,0xfff /* We just saved these. */
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
154 lwz r11, 0(r1) /* Pickup previous SP */
155 li r7, 0 /* Stack offset is zero, r10 is ignored. */
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
163 RETURNS : C++ EH Data registers (R3 - R6). */
165 .private_extern eh_rest_world_r10
168 lwz r11, 0(r1) /* Pickup previous SP */
169 mr r7,r10 /* Stack offset. */
171 /* pickup the C++ EH data regs (R3 - R6.) */
177 /* Fall through to Lrest_world_eh_r7. */
179 /* When we are doing the exception-handling epilog, R7 contains the offset to
182 clobbers: R0, R11 and R12
186 /* See if we have Altivec. */
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 */
195 beq L.rest_world_fp_eh
197 /* We have Altivec, restore VRsave and V20..V31 */
226 lwz r0,4(r11) /* recover saved CR */
244 mtcr r0 /* restore the saved cr. */
245 lwz r0, 8(r11) /* Pick up the 'real' return address. */
247 mtctr r0 /* exception-handler ret. address */
248 add r1,r11,r7 /* set SP to original value + R7 offset */
251 /* we should never be called on ppc64 for this ... */