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