1 1.1 mrg /* This file contains the exception-handling save_world and 2 1.1 mrg * restore_world routines, which need to do a run-time check to see if 3 1.1 mrg * they should save and restore the vector registers. 4 1.1 mrg * 5 1.10 mrg * Copyright (C) 2004-2022 Free Software Foundation, Inc. 6 1.1 mrg * 7 1.1 mrg * This file is free software; you can redistribute it and/or modify it 8 1.1 mrg * under the terms of the GNU General Public License as published by the 9 1.1 mrg * Free Software Foundation; either version 3, or (at your option) any 10 1.1 mrg * later version. 11 1.1 mrg * 12 1.1 mrg * This file is distributed in the hope that it will be useful, but 13 1.1 mrg * WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 1.1 mrg * General Public License for more details. 16 1.1 mrg * 17 1.1 mrg * Under Section 7 of GPL version 3, you are granted additional 18 1.1 mrg * permissions described in the GCC Runtime Library Exception, version 19 1.1 mrg * 3.1, as published by the Free Software Foundation. 20 1.1 mrg * 21 1.1 mrg * You should have received a copy of the GNU General Public License and 22 1.1 mrg * a copy of the GCC Runtime Library Exception along with this program; 23 1.1 mrg * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 1.1 mrg * <http://www.gnu.org/licenses/>. 25 1.1 mrg */ 26 1.1 mrg 27 1.1 mrg #ifndef __ppc64__ 28 1.1 mrg 29 1.1 mrg .machine ppc7400 30 1.1 mrg .data 31 1.1 mrg .align 2 32 1.1 mrg 33 1.1 mrg #ifdef __DYNAMIC__ 34 1.1 mrg 35 1.1 mrg .non_lazy_symbol_pointer 36 1.1 mrg L_has_vec$non_lazy_ptr: 37 1.1 mrg .indirect_symbol __cpu_has_altivec 38 1.1 mrg .long 0 39 1.1 mrg #else 40 1.1 mrg 41 1.1 mrg /* For static, "pretend" we have a non-lazy-pointer. */ 42 1.1 mrg 43 1.1 mrg L_has_vec$non_lazy_ptr: 44 1.1 mrg .long __cpu_has_altivec 45 1.1 mrg 46 1.1 mrg #endif 47 1.1 mrg 48 1.1 mrg 49 1.1 mrg .text 50 1.1 mrg .align 2 51 1.1 mrg 52 1.1 mrg /* save_world and rest_world save/restore F14-F31 and possibly V20-V31 53 1.1 mrg (assuming you have a CPU with vector registers; we use a global var 54 1.1 mrg provided by the System Framework to determine this.) 55 1.1 mrg 56 1.1 mrg SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11 57 1.1 mrg (the stack frame size) as parameters. It returns the updated VRsave 58 1.1 mrg in R0 if we`re on a CPU with vector regs. 59 1.1 mrg 60 1.1 mrg For gcc3 onward, we need to save and restore CR as well, since scheduled 61 1.1 mrg prologs can cause comparisons to be moved before calls to save_world. 62 1.1 mrg 63 1.1 mrg USES: R0 R11 R12 */ 64 1.1 mrg 65 1.1 mrg .private_extern save_world 66 1.1 mrg save_world: 67 1.1 mrg stw r0,8(r1) 68 1.1 mrg mflr r0 69 1.1 mrg bcl 20,31,Ls$pb 70 1.1 mrg Ls$pb: mflr r12 71 1.1 mrg addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Ls$pb) 72 1.1 mrg lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12) 73 1.1 mrg mtlr r0 74 1.1 mrg lwz r12,0(r12) 75 1.1 mrg /* grab CR */ 76 1.1 mrg mfcr r0 77 1.1 mrg /* test HAS_VEC */ 78 1.1 mrg cmpwi r12,0 79 1.1 mrg stfd f14,-144(r1) 80 1.1 mrg stfd f15,-136(r1) 81 1.1 mrg stfd f16,-128(r1) 82 1.1 mrg stfd f17,-120(r1) 83 1.1 mrg stfd f18,-112(r1) 84 1.1 mrg stfd f19,-104(r1) 85 1.1 mrg stfd f20,-96(r1) 86 1.1 mrg stfd f21,-88(r1) 87 1.1 mrg stfd f22,-80(r1) 88 1.1 mrg stfd f23,-72(r1) 89 1.1 mrg stfd f24,-64(r1) 90 1.1 mrg stfd f25,-56(r1) 91 1.1 mrg stfd f26,-48(r1) 92 1.1 mrg stfd f27,-40(r1) 93 1.1 mrg stfd f28,-32(r1) 94 1.1 mrg stfd f29,-24(r1) 95 1.1 mrg stfd f30,-16(r1) 96 1.1 mrg stfd f31,-8(r1) 97 1.1 mrg stmw r13,-220(r1) 98 1.1 mrg /* stash CR */ 99 1.1 mrg stw r0,4(r1) 100 1.1 mrg /* set R12 pointing at Vector Reg save area */ 101 1.1 mrg addi r12,r1,-224 102 1.1 mrg /* allocate stack frame */ 103 1.1 mrg stwux r1,r1,r11 104 1.1 mrg /* ...but return if HAS_VEC is zero */ 105 1.1 mrg bne+ L$saveVMX 106 1.1 mrg /* Not forgetting to restore CR. */ 107 1.1 mrg mtcr r0 108 1.1 mrg blr 109 1.1 mrg 110 1.1 mrg L$saveVMX: 111 1.1 mrg /* We're saving Vector regs too. */ 112 1.1 mrg /* Restore CR from R0. No More Branches! */ 113 1.1 mrg mtcr r0 114 1.1 mrg 115 1.1 mrg /* We should really use VRSAVE to figure out which vector regs 116 1.1 mrg we actually need to save and restore. Some other time :-/ */ 117 1.1 mrg 118 1.1 mrg li r11,-192 119 1.1 mrg stvx v20,r11,r12 120 1.1 mrg li r11,-176 121 1.1 mrg stvx v21,r11,r12 122 1.1 mrg li r11,-160 123 1.1 mrg stvx v22,r11,r12 124 1.1 mrg li r11,-144 125 1.1 mrg stvx v23,r11,r12 126 1.1 mrg li r11,-128 127 1.1 mrg stvx v24,r11,r12 128 1.1 mrg li r11,-112 129 1.1 mrg stvx v25,r11,r12 130 1.1 mrg li r11,-96 131 1.1 mrg stvx v26,r11,r12 132 1.1 mrg li r11,-80 133 1.1 mrg stvx v27,r11,r12 134 1.1 mrg li r11,-64 135 1.1 mrg stvx v28,r11,r12 136 1.1 mrg li r11,-48 137 1.1 mrg stvx v29,r11,r12 138 1.1 mrg li r11,-32 139 1.1 mrg stvx v30,r11,r12 140 1.1 mrg mfspr r0,VRsave 141 1.1 mrg li r11,-16 142 1.1 mrg stvx v31,r11,r12 143 1.1 mrg stw r0,0(r12) /* VRsave lives at -224(R1). */ 144 1.1 mrg ori r0,r0,0xfff /* We just saved these. */ 145 1.1 mrg mtspr VRsave,r0 146 1.1 mrg blr 147 1.1 mrg 148 1.1 mrg /* rest_world is jumped to, not called, so no need to worry about LR. 149 1.1 mrg clobbers R0, R7, R11 and R12. This just undoes the work done above. */ 150 1.1 mrg 151 1.1 mrg .private_extern rest_world 152 1.1 mrg rest_world: 153 1.1 mrg 154 1.1 mrg lwz r11, 0(r1) /* Pickup previous SP */ 155 1.1 mrg li r7, 0 /* Stack offset is zero, r10 is ignored. */ 156 1.1 mrg b Lrest_world_eh_r7 157 1.1 mrg 158 1.1 mrg /* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR. 159 1.1 mrg R10 is the C++ EH stack adjust parameter, we return to the caller`s caller. 160 1.1 mrg 161 1.1 mrg clobbers: R0, R7, R11 and R12 162 1.1 mrg uses : R10 163 1.1 mrg RETURNS : C++ EH Data registers (R3 - R6). */ 164 1.1 mrg 165 1.1 mrg .private_extern eh_rest_world_r10 166 1.1 mrg eh_rest_world_r10: 167 1.1 mrg 168 1.1 mrg lwz r11, 0(r1) /* Pickup previous SP */ 169 1.1 mrg mr r7,r10 /* Stack offset. */ 170 1.1 mrg 171 1.1 mrg /* pickup the C++ EH data regs (R3 - R6.) */ 172 1.1 mrg lwz r6,-420(r11) 173 1.1 mrg lwz r5,-424(r11) 174 1.1 mrg lwz r4,-428(r11) 175 1.1 mrg lwz r3,-432(r11) 176 1.1 mrg 177 1.1 mrg /* Fall through to Lrest_world_eh_r7. */ 178 1.1 mrg 179 1.1 mrg /* When we are doing the exception-handling epilog, R7 contains the offset to 180 1.1 mrg add to the SP. 181 1.1 mrg 182 1.1 mrg clobbers: R0, R11 and R12 183 1.1 mrg uses : R7. */ 184 1.1 mrg 185 1.1 mrg Lrest_world_eh_r7: 186 1.1 mrg /* See if we have Altivec. */ 187 1.1 mrg bcl 20,31,Lr7$pb 188 1.1 mrg Lr7$pb: mflr r12 189 1.1 mrg 190 1.1 mrg addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7$pb) 191 1.1 mrg lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7$pb)(r12) 192 1.1 mrg lwz r12,0(r12) /* R12 := HAS_VEC */ 193 1.1 mrg cmpwi r12,0 194 1.1 mrg lmw r13,-220(r11) 195 1.1 mrg beq L.rest_world_fp_eh 196 1.1 mrg 197 1.1 mrg /* We have Altivec, restore VRsave and V20..V31 */ 198 1.1 mrg lwz r0,-224(r11) 199 1.1 mrg li r12,-416 200 1.1 mrg mtspr VRsave,r0 201 1.1 mrg lvx v20,r11,r12 202 1.1 mrg li r12,-400 203 1.1 mrg lvx v21,r11,r12 204 1.1 mrg li r12,-384 205 1.1 mrg lvx v22,r11,r12 206 1.1 mrg li r12,-368 207 1.1 mrg lvx v23,r11,r12 208 1.1 mrg li r12,-352 209 1.1 mrg lvx v24,r11,r12 210 1.1 mrg li r12,-336 211 1.1 mrg lvx v25,r11,r12 212 1.1 mrg li r12,-320 213 1.1 mrg lvx v26,r11,r12 214 1.1 mrg li r12,-304 215 1.1 mrg lvx v27,r11,r12 216 1.1 mrg li r12,-288 217 1.1 mrg lvx v28,r11,r12 218 1.1 mrg li r12,-272 219 1.1 mrg lvx v29,r11,r12 220 1.1 mrg li r12,-256 221 1.1 mrg lvx v30,r11,r12 222 1.1 mrg li r12,-240 223 1.1 mrg lvx v31,r11,r12 224 1.1 mrg 225 1.1 mrg L.rest_world_fp_eh: 226 1.1 mrg lwz r0,4(r11) /* recover saved CR */ 227 1.1 mrg lfd f14,-144(r11) 228 1.1 mrg lfd f15,-136(r11) 229 1.1 mrg lfd f16,-128(r11) 230 1.1 mrg lfd f17,-120(r11) 231 1.1 mrg lfd f18,-112(r11) 232 1.1 mrg lfd f19,-104(r11) 233 1.1 mrg lfd f20,-96(r11) 234 1.1 mrg lfd f21,-88(r11) 235 1.1 mrg lfd f22,-80(r11) 236 1.1 mrg lfd f23,-72(r11) 237 1.1 mrg lfd f24,-64(r11) 238 1.1 mrg lfd f25,-56(r11) 239 1.1 mrg lfd f26,-48(r11) 240 1.1 mrg lfd f27,-40(r11) 241 1.1 mrg lfd f28,-32(r11) 242 1.1 mrg lfd f29,-24(r11) 243 1.1 mrg lfd f30,-16(r11) 244 1.1 mrg mtcr r0 /* restore the saved cr. */ 245 1.1 mrg lwz r0, 8(r11) /* Pick up the 'real' return address. */ 246 1.1 mrg lfd f31,-8(r11) 247 1.1 mrg mtctr r0 /* exception-handler ret. address */ 248 1.1 mrg add r1,r11,r7 /* set SP to original value + R7 offset */ 249 1.1 mrg bctr 250 1.1 mrg #endif 251 1.1 mrg /* we should never be called on ppc64 for this ... */ 252 1.1 mrg /* Done. */ 253