summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/darwin-world.asm
blob: 7ff51b51f11751dce39ae3ff568d39aaa1fdb360 (plain)
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