1169689Skan/* This file contains the exception-handling save_world and 2169689Skan * restore_world routines, which need to do a run-time check to see if 3169689Skan * they should save and restore the vector registers. 4169689Skan * 5169689Skan * Copyright (C) 2004 Free Software Foundation, Inc. 6169689Skan * 7169689Skan * This file is free software; you can redistribute it and/or modify it 8169689Skan * under the terms of the GNU General Public License as published by the 9169689Skan * Free Software Foundation; either version 2, or (at your option) any 10169689Skan * later version. 11169689Skan * 12169689Skan * In addition to the permissions in the GNU General Public License, the 13169689Skan * Free Software Foundation gives you unlimited permission to link the 14169689Skan * compiled version of this file with other programs, and to distribute 15169689Skan * those programs without any restriction coming from the use of this 16169689Skan * file. (The General Public License restrictions do apply in other 17169689Skan * respects; for example, they cover modification of the file, and 18169689Skan * distribution when not linked into another program.) 19169689Skan * 20169689Skan * This file is distributed in the hope that it will be useful, but 21169689Skan * WITHOUT ANY WARRANTY; without even the implied warranty of 22169689Skan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23169689Skan * General Public License for more details. 24169689Skan * 25169689Skan * You should have received a copy of the GNU General Public License 26169689Skan * along with this program; see the file COPYING. If not, write to 27169689Skan * the Free Software Foundation, 51 Franklin Street, Fifth Floor, 28169689Skan * Boston, MA 02110-1301, USA. 29169689Skan * 30169689Skan * As a special exception, if you link this library with files 31169689Skan * compiled with GCC to produce an executable, this does not cause the 32169689Skan * resulting executable to be covered by the GNU General Public License. 33169689Skan * This exception does not however invalidate any other reasons why the 34169689Skan * executable file might be covered by the GNU General Public License. 35169689Skan */ 36169689Skan 37169689Skan .machine ppc7400 38169689Skan.data 39169689Skan .align 2 40169689Skan 41169689Skan#ifdef __DYNAMIC__ 42169689Skan 43169689Skan.non_lazy_symbol_pointer 44169689SkanL_has_vec$non_lazy_ptr: 45169689Skan .indirect_symbol __cpu_has_altivec 46169689Skan#ifdef __ppc64__ 47169689Skan .quad 0 48169689Skan#else 49169689Skan .long 0 50169689Skan#endif 51169689Skan 52169689Skan#else 53169689Skan 54169689Skan/* For static, "pretend" we have a non-lazy-pointer. */ 55169689Skan 56169689SkanL_has_vec$non_lazy_ptr: 57169689Skan .long __cpu_has_altivec 58169689Skan 59169689Skan#endif 60169689Skan 61169689Skan 62169689Skan.text 63169689Skan .align 2 64169689Skan 65169689Skan/* save_world and rest_world save/restore F14-F31 and possibly V20-V31 66169689Skan (assuming you have a CPU with vector registers; we use a global var 67169689Skan provided by the System Framework to determine this.) 68169689Skan 69169689Skan SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11 70169689Skan (the stack frame size) as parameters. It returns VRsave in R0 if 71169689Skan we`re on a CPU with vector regs. 72169689Skan 73169689Skan With gcc3, we now need to save and restore CR as well, since gcc3's 74169689Skan scheduled prologs can cause comparisons to be moved before calls to 75169689Skan save_world! 76169689Skan 77169689Skan USES: R0 R11 R12 */ 78169689Skan 79169689Skan.private_extern save_world 80169689Skansave_world: 81169689Skan stw r0,8(r1) 82169689Skan mflr r0 83169689Skan bcl 20,31,Ls$pb 84169689SkanLs$pb: mflr r12 85169689Skan addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Ls$pb) 86169689Skan lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12) 87169689Skan mtlr r0 88169689Skan lwz r12,0(r12) 89169689Skan /* grab CR */ 90169689Skan mfcr r0 91169689Skan /* test HAS_VEC */ 92169689Skan cmpwi r12,0 93169689Skan stfd f14,-144(r1) 94169689Skan stfd f15,-136(r1) 95169689Skan stfd f16,-128(r1) 96169689Skan stfd f17,-120(r1) 97169689Skan stfd f18,-112(r1) 98169689Skan stfd f19,-104(r1) 99169689Skan stfd f20,-96(r1) 100169689Skan stfd f21,-88(r1) 101169689Skan stfd f22,-80(r1) 102169689Skan stfd f23,-72(r1) 103169689Skan stfd f24,-64(r1) 104169689Skan stfd f25,-56(r1) 105169689Skan stfd f26,-48(r1) 106169689Skan stfd f27,-40(r1) 107169689Skan stfd f28,-32(r1) 108169689Skan stfd f29,-24(r1) 109169689Skan stfd f30,-16(r1) 110169689Skan stfd f31,-8(r1) 111169689Skan stmw r13,-220(r1) 112169689Skan /* stash CR */ 113169689Skan stw r0,4(r1) 114169689Skan /* set R12 pointing at Vector Reg save area */ 115169689Skan addi r12,r1,-224 116169689Skan /* allocate stack frame */ 117169689Skan stwux r1,r1,r11 118169689Skan /* ...but return if HAS_VEC is zero */ 119169689Skan bne+ L$saveVMX 120169689Skan /* Not forgetting to restore CR. */ 121169689Skan mtcr r0 122169689Skan blr 123169689Skan 124169689SkanL$saveVMX: 125169689Skan /* We're saving Vector regs too. */ 126169689Skan /* Restore CR from R0. No More Branches! */ 127169689Skan mtcr r0 128169689Skan 129169689Skan /* We should really use VRSAVE to figure out which vector regs 130169689Skan we actually need to save and restore. Some other time :-/ */ 131169689Skan 132169689Skan li r11,-192 133169689Skan stvx v20,r11,r12 134169689Skan li r11,-176 135169689Skan stvx v21,r11,r12 136169689Skan li r11,-160 137169689Skan stvx v22,r11,r12 138169689Skan li r11,-144 139169689Skan stvx v23,r11,r12 140169689Skan li r11,-128 141169689Skan stvx v24,r11,r12 142169689Skan li r11,-112 143169689Skan stvx v25,r11,r12 144169689Skan li r11,-96 145169689Skan stvx v26,r11,r12 146169689Skan li r11,-80 147169689Skan stvx v27,r11,r12 148169689Skan li r11,-64 149169689Skan stvx v28,r11,r12 150169689Skan li r11,-48 151169689Skan stvx v29,r11,r12 152169689Skan li r11,-32 153169689Skan stvx v30,r11,r12 154169689Skan mfspr r0,VRsave 155169689Skan li r11,-16 156169689Skan stvx v31,r11,r12 157169689Skan /* VRsave lives at -224(R1) */ 158169689Skan stw r0,0(r12) 159169689Skan blr 160169689Skan 161169689Skan 162169689Skan/* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR. 163169689Skan R10 is the C++ EH stack adjust parameter, we return to the caller`s caller. 164169689Skan 165169689Skan USES: R0 R10 R11 R12 and R7 R8 166169689Skan RETURNS: C++ EH Data registers (R3 - R6.) 167169689Skan 168169689Skan We now set up R7/R8 and jump to rest_world_eh_r7r8. 169169689Skan 170169689Skan rest_world doesn't use the R10 stack adjust parameter, nor does it 171169689Skan pick up the R3-R6 exception handling stuff. */ 172169689Skan 173169689Skan.private_extern rest_world 174169689Skanrest_world: 175169689Skan /* Pickup previous SP */ 176169689Skan lwz r11, 0(r1) 177169689Skan li r7, 0 178169689Skan lwz r8, 8(r11) 179169689Skan li r10, 0 180169689Skan b rest_world_eh_r7r8 181169689Skan 182169689Skan.private_extern eh_rest_world_r10 183169689Skaneh_rest_world_r10: 184169689Skan /* Pickup previous SP */ 185169689Skan lwz r11, 0(r1) 186169689Skan mr r7,r10 187169689Skan lwz r8, 8(r11) 188169689Skan /* pickup the C++ EH data regs (R3 - R6.) */ 189169689Skan lwz r6,-420(r11) 190169689Skan lwz r5,-424(r11) 191169689Skan lwz r4,-428(r11) 192169689Skan lwz r3,-432(r11) 193169689Skan 194169689Skan b rest_world_eh_r7r8 195169689Skan 196169689Skan/* rest_world_eh_r7r8 is jumped to -- not called! -- when we're doing 197169689Skan the exception-handling epilog. R7 contains the offset to add to 198169689Skan the SP, and R8 contains the 'real' return address. 199169689Skan 200169689Skan USES: R0 R11 R12 [R7/R8] 201169689Skan RETURNS: C++ EH Data registers (R3 - R6.) */ 202169689Skan 203169689Skanrest_world_eh_r7r8: 204169689Skan bcl 20,31,Lr7r8$pb 205169689SkanLr7r8$pb: mflr r12 206169689Skan lwz r11,0(r1) 207169689Skan /* R11 := previous SP */ 208169689Skan addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7r8$pb) 209169689Skan lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7r8$pb)(r12) 210169689Skan lwz r0,4(r11) 211169689Skan /* R0 := old CR */ 212169689Skan lwz r12,0(r12) 213169689Skan /* R12 := HAS_VEC */ 214169689Skan mtcr r0 215169689Skan cmpwi r12,0 216169689Skan lmw r13,-220(r11) 217169689Skan beq L.rest_world_fp_eh 218169689Skan /* restore VRsave and V20..V31 */ 219169689Skan lwz r0,-224(r11) 220169689Skan li r12,-416 221169689Skan mtspr VRsave,r0 222169689Skan lvx v20,r11,r12 223169689Skan li r12,-400 224169689Skan lvx v21,r11,r12 225169689Skan li r12,-384 226169689Skan lvx v22,r11,r12 227169689Skan li r12,-368 228169689Skan lvx v23,r11,r12 229169689Skan li r12,-352 230169689Skan lvx v24,r11,r12 231169689Skan li r12,-336 232169689Skan lvx v25,r11,r12 233169689Skan li r12,-320 234169689Skan lvx v26,r11,r12 235169689Skan li r12,-304 236169689Skan lvx v27,r11,r12 237169689Skan li r12,-288 238169689Skan lvx v28,r11,r12 239169689Skan li r12,-272 240169689Skan lvx v29,r11,r12 241169689Skan li r12,-256 242169689Skan lvx v30,r11,r12 243169689Skan li r12,-240 244169689Skan lvx v31,r11,r12 245169689Skan 246169689SkanL.rest_world_fp_eh: 247169689Skan lfd f14,-144(r11) 248169689Skan lfd f15,-136(r11) 249169689Skan lfd f16,-128(r11) 250169689Skan lfd f17,-120(r11) 251169689Skan lfd f18,-112(r11) 252169689Skan lfd f19,-104(r11) 253169689Skan lfd f20,-96(r11) 254169689Skan lfd f21,-88(r11) 255169689Skan lfd f22,-80(r11) 256169689Skan lfd f23,-72(r11) 257169689Skan lfd f24,-64(r11) 258169689Skan lfd f25,-56(r11) 259169689Skan lfd f26,-48(r11) 260169689Skan lfd f27,-40(r11) 261169689Skan lfd f28,-32(r11) 262169689Skan lfd f29,-24(r11) 263169689Skan lfd f30,-16(r11) 264169689Skan /* R8 is the exception-handler's address */ 265169689Skan mtctr r8 266169689Skan lfd f31,-8(r11) 267169689Skan /* set SP to original value + R7 offset */ 268169689Skan add r1,r11,r7 269169689Skan bctr 270