summaryrefslogtreecommitdiff
path: root/libgcc/config/rs6000/darwin-world.S
blob: 4d72532870001074341a7e8c5227584f28f96c58 (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
/*  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-2014 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/>.
 */ 

#ifndef __ppc64__

	.machine ppc7400
.data
	.align 2

#ifdef __DYNAMIC__

.non_lazy_symbol_pointer
L_has_vec$non_lazy_ptr:
	.indirect_symbol __cpu_has_altivec
	.long	0
#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 the updated VRsave
   in R0 if we`re on a CPU with vector regs.

   For gcc3 onward, we need to save and restore CR as well, since 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	
	stw r0,0(r12)		/* VRsave lives at -224(R1).  */
	ori r0,r0,0xfff		/* We just saved these.  */
	mtspr VRsave,r0
	blr

/* rest_world  is jumped to, not called, so no need to worry about LR.
   clobbers R0, R7, R11 and R12.  This just undoes the work done above.  */

	.private_extern rest_world
rest_world:
				
	lwz r11, 0(r1)		/* Pickup previous SP  */
	li r7, 0		/* Stack offset is zero, r10 is ignored.  */
	b Lrest_world_eh_r7

/* 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.

   clobbers: R0, R7, R11 and R12
   uses    : R10
   RETURNS : C++ EH Data registers (R3 - R6).  */

	.private_extern eh_rest_world_r10
eh_rest_world_r10:
				
	lwz r11, 0(r1)		/* Pickup previous SP  */
	mr  r7,r10		/* Stack offset.  */
	
	/* pickup the C++ EH data regs (R3 - R6.)  */
	lwz r6,-420(r11)
	lwz r5,-424(r11)
	lwz r4,-428(r11)
	lwz r3,-432(r11)

	/* Fall through to Lrest_world_eh_r7.  */

/* When we are doing the exception-handling epilog, R7 contains the offset to
   add to the SP.

   clobbers: R0, R11 and R12
   uses    : R7.  */

Lrest_world_eh_r7:
	/* See if we have Altivec.  */
	bcl 20,31,Lr7$pb
Lr7$pb: mflr r12

	addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7$pb)
	lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7$pb)(r12)
	lwz r12,0(r12)		/* R12 := HAS_VEC  */
	cmpwi r12,0
	lmw r13,-220(r11)
	beq L.rest_world_fp_eh

	/* We have Altivec, 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:
	lwz r0,4(r11)		/* recover saved CR  */
	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)
	mtcr r0			/* restore the saved cr.  */
	lwz r0, 8(r11)		/* Pick up the 'real' return address.  */
	lfd f31,-8(r11)		
	mtctr r0		/* exception-handler ret. address  */
	add r1,r11,r7		/* set SP to original value + R7 offset  */
	bctr
#endif
/* we should never be called on ppc64 for this ... */
/* Done.  */