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
|
/* 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, 2009 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 3, or (at your option) any
* later version.
*
* 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.
*
* Under Section 7 of GPL version 3, you are granted additional
* permissions described in the GCC Runtime Library Exception, version
* 3.1, as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License and
* a copy of the GCC Runtime Library Exception along with this program;
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
* <http://www.gnu.org/licenses/>.
*/
.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
|