]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/powerpc64/dl-trampoline.S
Merge glibc-ports into ports/ directory.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / dl-trampoline.S
1 /* PLT trampolines. PPC64 version.
2 Copyright (C) 2005-2012 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #include <sysdep.h>
20 #include <rtld-global-offsets.h>
21
22
23 .section ".text"
24 /* On entry r0 contains the index of the PLT entry we need to fixup
25 and r11 contains the link_map (from PLT0+16). The link_map becomes
26 parm1 (r3) and the index (r0) need to be converted to an offset
27 (index * 24) in parm2 (r4). */
28
29 #define FRAME_SIZE 176
30 /* We need to save the registers used to pass parameters, ie. r3 thru
31 r10; Use local var space rather than the parameter save area,
32 because gcc as of 2010/05 doesn't allocate a proper stack frame for
33 a function that makes no calls except for __tls_get_addr and we
34 might be here resolving the __tls_get_addr call. */
35 #define INT_PARMS 112
36 EALIGN(_dl_runtime_resolve, 4, 0)
37 stdu r1,-FRAME_SIZE(r1)
38 cfi_adjust_cfa_offset (FRAME_SIZE)
39 std r3,INT_PARMS+0(r1)
40 mr r3,r11
41 std r4,INT_PARMS+8(r1)
42 sldi r4,r0,1
43 std r5,INT_PARMS+16(r1)
44 add r4,r4,r0
45 std r6,INT_PARMS+24(r1)
46 sldi r4,r4,3
47 std r7,INT_PARMS+32(r1)
48 mflr r0
49 std r8,INT_PARMS+40(r1)
50 /* Store the LR in the LR Save area. */
51 std r0,FRAME_SIZE+16(r1)
52 cfi_offset (lr, 16)
53 mfcr r0
54 std r9,INT_PARMS+48(r1)
55 std r10,INT_PARMS+56(r1)
56 /* I'm almost certain we don't have to save cr... be safe. */
57 std r0,FRAME_SIZE+8(r1)
58 bl JUMPTARGET(_dl_fixup)
59 #ifndef SHARED
60 nop
61 #endif
62 /* Put the registers back. */
63 ld r0,FRAME_SIZE+16(r1)
64 ld r10,INT_PARMS+56(r1)
65 ld r9,INT_PARMS+48(r1)
66 ld r8,INT_PARMS+40(r1)
67 ld r7,INT_PARMS+32(r1)
68 mtlr r0
69 ld r0,FRAME_SIZE+8(r1)
70 ld r6,INT_PARMS+24(r1)
71 ld r5,INT_PARMS+16(r1)
72 ld r4,INT_PARMS+8(r1)
73 mtcrf 0xFF,r0
74 /* Load the target address, toc and static chain reg from the function
75 descriptor returned by fixup. */
76 ld r0,0(r3)
77 ld r2,8(r3)
78 mtctr r0
79 ld r11,16(r3)
80 ld r3,INT_PARMS+0(r1)
81 /* Unwind the stack frame, and jump. */
82 addi r1,r1,FRAME_SIZE
83 bctr
84 END(_dl_runtime_resolve)
85 #undef FRAME_SIZE
86 #undef INT_PARMS
87
88 /* Stack layout:
89 +592 previous backchain
90 +584 spill_r31
91 +576 spill_r30
92 +560 v1
93 +552 fp4
94 +544 fp3
95 +536 fp2
96 +528 fp1
97 +520 r4
98 +512 r3
99 return values
100 +504 free
101 +496 stackframe
102 +488 lr
103 +480 r1
104 +464 v13
105 +448 v12
106 +432 v11
107 +416 v10
108 +400 v9
109 +384 v8
110 +368 v7
111 +352 v6
112 +336 v5
113 +320 v4
114 +304 v3
115 +288 v2
116 * VMX Parms in V2-V13, V0-V1 are scratch
117 +284 vrsave
118 +280 free
119 +272 fp13
120 +264 fp12
121 +256 fp11
122 +248 fp10
123 +240 fp9
124 +232 fp8
125 +224 fp7
126 +216 fp6
127 +208 fp5
128 +200 fp4
129 +192 fp3
130 +184 fp2
131 +176 fp1
132 * FP Parms in FP1-FP13, FP0 is a scratch register
133 +168 r10
134 +160 r9
135 +152 r8
136 +144 r7
137 +136 r6
138 +128 r5
139 +120 r4
140 +112 r3
141 * Integer parms in R3-R10, R0 is scratch, R1 SP, R2 is TOC
142 +104 parm8
143 +96 parm7
144 +88 parm6
145 +80 parm5
146 +72 parm4
147 +64 parm3
148 +56 parm2
149 +48 parm1
150 * Parameter save area, Allocated by the call, at least 8 double words
151 +40 TOC save area
152 +32 Reserved for linker
153 +24 Reserved for compiler
154 +16 LR save area
155 +8 CR save area
156 r1+0 stack back chain
157 */
158 #define FRAME_SIZE 592
159 #define INT_RTN 512
160 #define FPR_RTN 528
161 #define VR_RTN 560
162 #define STACK_FRAME 496
163 #define CALLING_LR 488
164 #define CALLING_SP 480
165 #define INT_PARMS 112
166 #define FPR_PARMS 176
167 #define VR_PARMS 288
168 #define VR_VRSAVE 284
169 .section ".toc","aw"
170 .LC__dl_hwcap:
171 # ifdef SHARED
172 .tc _rtld_local_ro[TC],_rtld_local_ro
173 # else
174 .tc _dl_hwcap[TC],_dl_hwcap
175 # endif
176 .section ".text"
177
178 .machine "altivec"
179 /* On entry r0 contains the index of the PLT entry we need to fixup
180 and r11 contains the link_map (from PLT0+16). The link_map becomes
181 parm1 (r3) and the index (r0) needs to be converted to an offset
182 (index * 24) in parm2 (r4). */
183 #ifndef PROF
184 EALIGN(_dl_profile_resolve, 4, 0)
185 /* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we
186 need to call _dl_call_pltexit. */
187 std r31,-8(r1)
188 std r30,-16(r1)
189 /* We need to save the registers used to pass parameters, ie. r3 thru
190 r10; the registers are saved in a stack frame. */
191 stdu r1,-FRAME_SIZE(r1)
192 cfi_adjust_cfa_offset (FRAME_SIZE)
193 cfi_offset(r31,-8)
194 cfi_offset(r30,-16)
195 std r3,INT_PARMS+0(r1)
196 mr r3,r11
197 std r4,INT_PARMS+8(r1)
198 sldi r4,r0,1 /* index * 2 */
199 std r5,INT_PARMS+16(r1)
200 add r4,r4,r0 /* index * 3 */
201 std r6,INT_PARMS+24(r1)
202 sldi r4,r4,3 /* index * 24 == PLT offset */
203 mflr r5
204 std r7,INT_PARMS+32(r1)
205 std r8,INT_PARMS+40(r1)
206 /* Store the LR in the LR Save area of the previous frame. */
207 /* XXX Do we have to do this? */
208 la r8,FRAME_SIZE(r1)
209 std r5,FRAME_SIZE+16(r1)
210 cfi_offset (lr, 16)
211 std r5,CALLING_LR(r1)
212 mfcr r0
213 std r9,INT_PARMS+48(r1)
214 std r10,INT_PARMS+56(r1)
215 std r8,CALLING_SP(r1)
216 /* I'm almost certain we don't have to save cr... be safe. */
217 std r0,FRAME_SIZE+8(r1)
218 ld r12,.LC__dl_hwcap@toc(r2)
219 #ifdef SHARED
220 /* Load _rtld_local_ro._dl_hwcap. */
221 ld r12,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r12)
222 #else
223 ld r12,0(r12) /* Load extern _dl_hwcap. */
224 #endif
225 andis. r0,r12,(PPC_FEATURE_HAS_ALTIVEC >> 16)
226 beq L(saveFP)
227 la r10,(VR_PARMS+0)(r1)
228 la r9,(VR_PARMS+16)(r1)
229 li r11,32
230 li r12,64
231 stvx v2,0,r10
232 stvx v3,0,r9
233
234 stvx v4,r11,r10
235 stvx v5,r11,r9
236 addi r11,r11,64
237
238 stvx v6,r12,r10
239 stvx v7,r12,r9
240 addi r12,r12,64
241
242 stvx v8,r11,r10
243 stvx v9,r11,r9
244 addi r11,r11,64
245
246 stvx v10,r12,r10
247 stvx v11,r12,r9
248 mfspr r0,VRSAVE
249
250 stvx v12,r11,r10
251 stvx v13,r11,r9
252 L(saveFP):
253 stw r0,VR_VRSAVE(r1)
254 /* Save floating registers. */
255 stfd fp1,FPR_PARMS+0(r1)
256 stfd fp2,FPR_PARMS+8(r1)
257 stfd fp3,FPR_PARMS+16(r1)
258 stfd fp4,FPR_PARMS+24(r1)
259 stfd fp5,FPR_PARMS+32(r1)
260 stfd fp6,FPR_PARMS+40(r1)
261 stfd fp7,FPR_PARMS+48(r1)
262 stfd fp8,FPR_PARMS+56(r1)
263 stfd fp9,FPR_PARMS+64(r1)
264 stfd fp10,FPR_PARMS+72(r1)
265 stfd fp11,FPR_PARMS+80(r1)
266 li r0,-1
267 stfd fp12,FPR_PARMS+88(r1)
268 stfd fp13,FPR_PARMS+96(r1)
269 /* Load the extra parameters. */
270 addi r6,r1,INT_PARMS
271 addi r7,r1,STACK_FRAME
272 /* Save link_map* and reloc_addr parms for later. */
273 mr r31,r3
274 mr r30,r4
275 std r0,0(r7)
276 bl JUMPTARGET(_dl_profile_fixup)
277 #ifndef SHARED
278 nop
279 #endif
280 /* Test *framesizep > 0 to see if need to do pltexit processing. */
281 ld r0,STACK_FRAME(r1)
282 /* Put the registers back. */
283 lwz r12,VR_VRSAVE(r1)
284 cmpdi cr1,r0,0
285 cmpdi cr0,r12,0
286 bgt cr1,L(do_pltexit)
287 la r10,(VR_PARMS+0)(r1)
288 la r9,(VR_PARMS+16)(r1)
289 /* VRSAVE must be non-zero if VMX is present and VRs are in use. */
290 beq L(restoreFXR)
291 li r11,32
292 li r12,64
293 lvx v2,0,r10
294 lvx v3,0,r9
295
296 lvx v4,r11,r10
297 lvx v5,r11,r9
298 addi r11,r11,64
299
300 lvx v6,r12,r10
301 lvx v7,r12,r9
302 addi r12,r12,64
303
304 lvx v8,r11,r10
305 lvx v9,r11,r9
306 addi r11,r11,64
307
308 lvx v10,r12,r10
309 lvx v11,r12,r9
310
311 lvx v12,r11,r10
312 lvx v13,r11,r9
313 L(restoreFXR):
314 ld r0,FRAME_SIZE+16(r1)
315 ld r10,INT_PARMS+56(r1)
316 ld r9,INT_PARMS+48(r1)
317 ld r8,INT_PARMS+40(r1)
318 ld r7,INT_PARMS+32(r1)
319 mtlr r0
320 ld r0,FRAME_SIZE+8(r1)
321 ld r6,INT_PARMS+24(r1)
322 ld r5,INT_PARMS+16(r1)
323 ld r4,INT_PARMS+8(r1)
324 mtcrf 0xFF,r0
325 /* Load the target address, toc and static chain reg from the function
326 descriptor returned by fixup. */
327 ld r0,0(r3)
328 ld r2,8(r3)
329 ld r11,16(r3)
330 ld r3,INT_PARMS+0(r1)
331 mtctr r0
332 /* Load the floating point registers. */
333 lfd fp1,FPR_PARMS+0(r1)
334 lfd fp2,FPR_PARMS+8(r1)
335 lfd fp3,FPR_PARMS+16(r1)
336 lfd fp4,FPR_PARMS+24(r1)
337 lfd fp5,FPR_PARMS+32(r1)
338 lfd fp6,FPR_PARMS+40(r1)
339 lfd fp7,FPR_PARMS+48(r1)
340 lfd fp8,FPR_PARMS+56(r1)
341 lfd fp9,FPR_PARMS+64(r1)
342 lfd fp10,FPR_PARMS+72(r1)
343 lfd fp11,FPR_PARMS+80(r1)
344 lfd fp12,FPR_PARMS+88(r1)
345 lfd fp13,FPR_PARMS+96(r1)
346 /* Unwind the stack frame, and jump. */
347 ld r31,584(r1)
348 ld r30,576(r1)
349 addi r1,r1,FRAME_SIZE
350 bctr
351 L(do_pltexit):
352 la r10,(VR_PARMS+0)(r1)
353 la r9,(VR_PARMS+16)(r1)
354 beq L(restoreFXR2)
355 li r11,32
356 li r12,64
357 lvx v2,0,r10
358 lvx v3,0,r9
359
360 lvx v4,r11,r10
361 lvx v5,r11,r9
362 addi r11,r11,64
363
364 lvx v6,r12,r10
365 lvx v7,r12,r9
366 addi r12,r12,64
367
368 lvx v8,r11,r10
369 lvx v9,r11,r9
370 addi r11,r11,64
371
372 lvx v10,r12,r10
373 lvx v11,r12,r9
374
375 lvx v12,r11,r10
376 lvx v13,r11,r9
377 L(restoreFXR2):
378 ld r0,FRAME_SIZE+16(r1)
379 ld r10,INT_PARMS+56(r1)
380 ld r9,INT_PARMS+48(r1)
381 ld r8,INT_PARMS+40(r1)
382 ld r7,INT_PARMS+32(r1)
383 mtlr r0
384 ld r0,FRAME_SIZE+8(r1)
385 ld r6,INT_PARMS+24(r1)
386 ld r5,INT_PARMS+16(r1)
387 ld r4,INT_PARMS+8(r1)
388 mtcrf 0xFF,r0
389 /* Load the target address, toc and static chain reg from the function
390 descriptor returned by fixup. */
391 ld r0,0(r3)
392 std r2,40(r1)
393 ld r2,8(r3)
394 ld r11,16(r3)
395 ld r3,INT_PARMS+0(r1)
396 mtctr r0
397 /* Load the floating point registers. */
398 lfd fp1,FPR_PARMS+0(r1)
399 lfd fp2,FPR_PARMS+8(r1)
400 lfd fp3,FPR_PARMS+16(r1)
401 lfd fp4,FPR_PARMS+24(r1)
402 lfd fp5,FPR_PARMS+32(r1)
403 lfd fp6,FPR_PARMS+40(r1)
404 lfd fp7,FPR_PARMS+48(r1)
405 lfd fp8,FPR_PARMS+56(r1)
406 lfd fp9,FPR_PARMS+64(r1)
407 lfd fp10,FPR_PARMS+72(r1)
408 lfd fp11,FPR_PARMS+80(r1)
409 lfd fp12,FPR_PARMS+88(r1)
410 lfd fp13,FPR_PARMS+96(r1)
411 /* Call the target function. */
412 bctrl
413 ld r2,40(r1)
414 lwz r12,VR_VRSAVE(r1)
415 /* But return here and store the return values. */
416 std r3,INT_RTN(r1)
417 std r4,INT_RTN+8(r1)
418 stfd fp1,FPR_PARMS+0(r1)
419 stfd fp2,FPR_PARMS+8(r1)
420 cmpdi cr0,r12,0
421 la r10,VR_RTN(r1)
422 stfd fp3,FPR_PARMS+16(r1)
423 stfd fp4,FPR_PARMS+24(r1)
424 mr r3,r31
425 mr r4,r30
426 beq L(callpltexit)
427 stvx v2,0,r10
428 L(callpltexit):
429 addi r5,r1,INT_PARMS
430 addi r6,r1,INT_RTN
431 bl JUMPTARGET(_dl_call_pltexit)
432 #ifndef SHARED
433 nop
434 #endif
435 /* Restore the return values from target function. */
436 lwz r12,VR_VRSAVE(r1)
437 ld r3,INT_RTN(r1)
438 ld r4,INT_RTN+8(r1)
439 lfd fp1,FPR_PARMS+0(r1)
440 lfd fp2,FPR_PARMS+8(r1)
441 cmpdi cr0,r12,0
442 la r10,VR_RTN(r1)
443 lfd fp3,FPR_PARMS+16(r1)
444 lfd fp4,FPR_PARMS+24(r1)
445 beq L(pltexitreturn)
446 lvx v2,0,r10
447 L(pltexitreturn):
448 ld r0,FRAME_SIZE+16(r1)
449 ld r31,584(r1)
450 ld r30,576(r1)
451 mtlr r0
452 ld r1,0(r1)
453 blr
454 END(_dl_profile_resolve)
455 #endif