1 /* PLT trampolines. PPC64 version.
2 Copyright (C) 2005-2012 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
20 #include <rtld-global-offsets.h>
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). */
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. */
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)
41 std r4,INT_PARMS+8(r1)
43 std r5,INT_PARMS+16(r1)
45 std r6,INT_PARMS+24(r1)
47 std r7,INT_PARMS+32(r1)
49 std r8,INT_PARMS+40(r1)
50 /* Store the LR in the LR Save area. */
51 std r0,FRAME_SIZE+16(r1)
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)
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)
69 ld r0,FRAME_SIZE+8(r1)
70 ld r6,INT_PARMS+24(r1)
71 ld r5,INT_PARMS+16(r1)
74 /* Load the target address, toc and static chain reg from the function
75 descriptor returned by fixup. */
81 /* Unwind the stack frame, and jump. */
84 END(_dl_runtime_resolve)
89 +592 previous backchain
116 * VMX Parms in V2-V13, V0-V1 are scratch
132 * FP Parms in FP1-FP13, FP0 is a scratch register
141 * Integer parms in R3-R10, R0 is scratch, R1 SP, R2 is TOC
150 * Parameter save area, Allocated by the call, at least 8 double words
152 +32 Reserved for linker
153 +24 Reserved for compiler
156 r1+0 stack back chain
158 #define FRAME_SIZE 592
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
168 #define VR_VRSAVE 284
172 .tc _rtld_local_ro[TC],_rtld_local_ro
174 .tc _dl_hwcap[TC],_dl_hwcap
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). */
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. */
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)
195 std r3,INT_PARMS+0(r1)
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 */
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? */
209 std r5,FRAME_SIZE+16(r1)
211 std r5,CALLING_LR(r1)
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)
220 /* Load _rtld_local_ro._dl_hwcap. */
221 ld r12,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r12)
223 ld r12,0(r12) /* Load extern _dl_hwcap. */
225 andis. r0,r12,(PPC_FEATURE_HAS_ALTIVEC >> 16)
227 la r10,(VR_PARMS+0)(r1)
228 la r9,(VR_PARMS+16)(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)
267 stfd fp12,FPR_PARMS+88(r1)
268 stfd fp13,FPR_PARMS+96(r1)
269 /* Load the extra parameters. */
271 addi r7,r1,STACK_FRAME
272 /* Save link_map* and reloc_addr parms for later. */
276 bl JUMPTARGET(_dl_profile_fixup)
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)
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. */
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)
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)
325 /* Load the target address, toc and static chain reg from the function
326 descriptor returned by fixup. */
330 ld r3,INT_PARMS+0(r1)
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. */
349 addi r1,r1,FRAME_SIZE
352 la r10,(VR_PARMS+0)(r1)
353 la r9,(VR_PARMS+16)(r1)
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)
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)
389 /* Load the target address, toc and static chain reg from the function
390 descriptor returned by fixup. */
395 ld r3,INT_PARMS+0(r1)
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. */
414 lwz r12,VR_VRSAVE(r1)
415 /* But return here and store the return values. */
418 stfd fp1,FPR_PARMS+0(r1)
419 stfd fp2,FPR_PARMS+8(r1)
422 stfd fp3,FPR_PARMS+16(r1)
423 stfd fp4,FPR_PARMS+24(r1)
431 bl JUMPTARGET(_dl_call_pltexit)
435 /* Restore the return values from target function. */
436 lwz r12,VR_VRSAVE(r1)
439 lfd fp1,FPR_PARMS+0(r1)
440 lfd fp2,FPR_PARMS+8(r1)
443 lfd fp3,FPR_PARMS+16(r1)
444 lfd fp4,FPR_PARMS+24(r1)
448 ld r0,FRAME_SIZE+16(r1)
454 END(_dl_profile_resolve)