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 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. 11 * 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.) 19 * 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. 24 * 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, 51 Franklin Street, Fifth Floor, 28 * Boston, MA 02110-1301, USA. 29 * 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 */ 36 37 .machine ppc7400 38.data 39 .align 2 40 41#ifdef __DYNAMIC__ 42 43.non_lazy_symbol_pointer 44L_has_vec$non_lazy_ptr: 45 .indirect_symbol __cpu_has_altivec 46#ifdef __ppc64__ 47 .quad 0 48#else 49 .long 0 50#endif 51 52#else 53 54/* For static, "pretend" we have a non-lazy-pointer. */ 55 56L_has_vec$non_lazy_ptr: 57 .long __cpu_has_altivec 58 59#endif 60 61 62.text 63 .align 2 64 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.) 68 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. 72 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! 76 77 USES: R0 R11 R12 */ 78 79.private_extern save_world 80save_world: 81 stw r0,8(r1) 82 mflr r0 83 bcl 20,31,Ls$pb 84Ls$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 122 blr 123 124L$saveVMX: 125 /* We're saving Vector regs too. */ 126 /* Restore CR from R0. No More Branches! */ 127 mtcr r0 128 129 /* We should really use VRSAVE to figure out which vector regs 130 we actually need to save and restore. Some other time :-/ */ 131 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) 159 blr 160 161 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. 164 165 USES: R0 R10 R11 R12 and R7 R8 166 RETURNS: C++ EH Data registers (R3 - R6.) 167 168 We now set up R7/R8 and jump to rest_world_eh_r7r8. 169 170 rest_world doesn't use the R10 stack adjust parameter, nor does it 171 pick up the R3-R6 exception handling stuff. */ 172 173.private_extern rest_world 174rest_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 181 182.private_extern eh_rest_world_r10 183eh_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) 193 194 b rest_world_eh_r7r8 195 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. 199 200 USES: R0 R11 R12 [R7/R8] 201 RETURNS: C++ EH Data registers (R3 - R6.) */ 202 203rest_world_eh_r7r8: 204 bcl 20,31,Lr7r8$pb 205Lr7r8$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 245 246L.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 270