Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / powerpc / powerpc64 / dl-trampoline.S
blob4519af48e2389e8e9aa69a278758d1cdf5c8f1e4
1 /* PLT trampolines.  PPC64 version.
2    Copyright (C) 2005-2014 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/>.  */
19 #include <sysdep.h>
20 #include <rtld-global-offsets.h>
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).  */
29 #define FRAME_SIZE (FRAME_MIN_SIZE+64)
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 FRAME_MIN_SIZE
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+FRAME_LR_SAVE(r1)
52         cfi_offset (lr, FRAME_LR_SAVE)
53         std     r9,INT_PARMS+48(r1)
54         std     r10,INT_PARMS+56(r1)
55         bl      JUMPTARGET(_dl_fixup)
56 #ifndef SHARED
57         nop
58 #endif
59 /* Put the registers back.  */
60         ld      r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
61         ld      r10,INT_PARMS+56(r1)
62         ld      r9,INT_PARMS+48(r1)
63         ld      r8,INT_PARMS+40(r1)
64         ld      r7,INT_PARMS+32(r1)
65         mtlr    r0
66         ld      r6,INT_PARMS+24(r1)
67         ld      r5,INT_PARMS+16(r1)
68         ld      r4,INT_PARMS+8(r1)
69 /* Prepare for calling the function returned by fixup.  */
70         PPC64_LOAD_FUNCPTR r3
71         ld      r3,INT_PARMS+0(r1)
72 #if _CALL_ELF == 2
73 /* Restore the caller's TOC in case we jump to a local entry point.  */
74         ld      r2,FRAME_SIZE+FRAME_TOC_SAVE(r1)
75 #endif
76 /* Unwind the stack frame, and jump.  */
77         addi    r1,r1,FRAME_SIZE
78         bctr
79 END(_dl_runtime_resolve)
80 #undef FRAME_SIZE
81 #undef INT_PARMS
83         /* Stack layout:                ELFv2 ABI.
84                                         +752   previous backchain
85                                         +744   spill_r31
86                                         +736   spill_r30
87                                         +720   v8
88                                         +704   v7
89                                         +688   v6
90                                         +672   v5
91                                         +656   v4
92                                         +640   v3
93                                         +624   v2
94                                         +608   v1
95                                         +600   fp10
96           ELFv1 ABI                     +592   fp9
97           +592   previous backchain     +584   fp8
98           +584   spill_r31              +576   fp7
99           +576   spill_r30              +568   fp6
100           +560   v1                     +560   fp5
101           +552   fp4                    +552   fp4
102           +544   fp3                    +544   fp3
103           +536   fp2                    +536   fp2
104           +528   fp1                    +528   fp1
105           +520   r4                     +520   r4
106           +512   r3                     +512   r3
107            return values
108           +504   free
109           +496   stackframe
110           +488   lr
111           +480   r1
112           +464   v13
113           +448   v12
114           +432   v11
115           +416   v10
116           +400   v9
117           +384   v8
118           +368   v7
119           +352   v6
120           +336   v5
121           +320   v4
122           +304   v3
123           +288   v2
124          * VMX Parms in V2-V13, V0-V1 are scratch
125           +284   vrsave
126           +280   free
127           +272   fp13
128           +264   fp12
129           +256   fp11
130           +248   fp10
131           +240   fp9
132           +232   fp8
133           +224   fp7
134           +216   fp6
135           +208   fp5
136           +200   fp4
137           +192   fp3
138           +184   fp2
139           +176   fp1
140          * FP Parms in FP1-FP13, FP0 is a scratch register
141           +168   r10
142           +160   r9
143           +152   r8
144           +144   r7
145           +136   r6
146           +128   r5
147           +120   r4
148           +112   r3
149          * Integer parms in R3-R10, R0 is scratch, R1 SP, R2 is TOC
150           +104   parm8
151           +96    parm7
152           +88    parm6
153           +80    parm5
154           +72    parm4
155           +64    parm3
156           +56    parm2
157           +48    parm1
158          * Parameter save area
159          * (v1 ABI: Allocated by the call, at least 8 double words)
160           +40    v1 ABI: TOC save area
161           +32    v1 ABI: Reserved for linker
162           +24    v1 ABI: Reserved for compiler / v2 ABI: TOC save area
163           +16    LR save area
164           +8     CR save area
165         r1+0     stack back chain
166         */
167 #if _CALL_ELF == 2
168 # define FRAME_SIZE 752
169 # define VR_RTN 608
170 #else
171 # define FRAME_SIZE 592
172 # define VR_RTN 560
173 #endif
174 #define INT_RTN 512
175 #define FPR_RTN 528
176 #define STACK_FRAME 496
177 #define CALLING_LR 488
178 #define CALLING_SP 480
179 #define INT_PARMS 112
180 #define FPR_PARMS 176
181 #define VR_PARMS 288
182 #define VR_VRSAVE 284
183         .section        ".toc","aw"
184 .LC__dl_hwcap:
185 # ifdef SHARED
186         .tc _rtld_local_ro[TC],_rtld_local_ro
187 # else
188         .tc _dl_hwcap[TC],_dl_hwcap
189 # endif
190         .section ".text"
192         .machine        "altivec"
193 /* On entry r0 contains the index of the PLT entry we need to fixup
194    and r11 contains the link_map (from PLT0+16).  The link_map becomes
195    parm1 (r3) and the index (r0) needs to be converted to an offset
196    (index * 24) in parm2 (r4).  */
197 #ifndef PROF
198 EALIGN(_dl_profile_resolve, 4, 0)
199 /* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we
200    need to call _dl_call_pltexit.  */
201         std     r31,-8(r1)
202         std     r30,-16(r1)
203 /* We need to save the registers used to pass parameters, ie. r3 thru
204    r10; the registers are saved in a stack frame.  */
205         stdu    r1,-FRAME_SIZE(r1)
206         cfi_adjust_cfa_offset (FRAME_SIZE)
207         cfi_offset(r31,-8)
208         cfi_offset(r30,-16)
209         std     r3,INT_PARMS+0(r1)
210         mr      r3,r11
211         std     r4,INT_PARMS+8(r1)
212         sldi    r4,r0,1         /* index * 2 */
213         std     r5,INT_PARMS+16(r1)
214         add     r4,r4,r0        /* index * 3 */
215         std     r6,INT_PARMS+24(r1)
216         sldi    r4,r4,3         /* index * 24  == PLT offset */
217         mflr    r5
218         std     r7,INT_PARMS+32(r1)
219         std     r8,INT_PARMS+40(r1)
220 /* Store the LR in the LR Save area.  */
221         la      r8,FRAME_SIZE(r1)
222         std     r5,FRAME_SIZE+FRAME_LR_SAVE(r1)
223         cfi_offset (lr, FRAME_LR_SAVE)
224         std     r5,CALLING_LR(r1)
225         std     r9,INT_PARMS+48(r1)
226         std     r10,INT_PARMS+56(r1)
227         std     r8,CALLING_SP(r1)
228         ld      r12,.LC__dl_hwcap@toc(r2)
229 #ifdef SHARED
230         /* Load _rtld_local_ro._dl_hwcap.  */
231         ld      r12,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r12)
232 #else
233         ld      r12,0(r12) /* Load extern _dl_hwcap.  */
234 #endif
235         andis.  r0,r12,(PPC_FEATURE_HAS_ALTIVEC >> 16)
236         beq     L(saveFP)
237         la      r10,(VR_PARMS+0)(r1)
238         la      r9,(VR_PARMS+16)(r1)
239         li      r11,32
240         li      r12,64
241         stvx    v2,0,r10
242         stvx    v3,0,r9
244         stvx    v4,r11,r10
245         stvx    v5,r11,r9
246         addi    r11,r11,64
248         stvx    v6,r12,r10
249         stvx    v7,r12,r9
250         addi    r12,r12,64
252         stvx    v8,r11,r10
253         stvx    v9,r11,r9
254         addi    r11,r11,64
256         stvx    v10,r12,r10
257         stvx    v11,r12,r9
258         mfspr   r0,VRSAVE
260         stvx    v12,r11,r10
261         stvx    v13,r11,r9
262 L(saveFP):
263         stw     r0,VR_VRSAVE(r1)
264 /* Save floating registers.  */
265         stfd    fp1,FPR_PARMS+0(r1)
266         stfd    fp2,FPR_PARMS+8(r1)
267         stfd    fp3,FPR_PARMS+16(r1)
268         stfd    fp4,FPR_PARMS+24(r1)
269         stfd    fp5,FPR_PARMS+32(r1)
270         stfd    fp6,FPR_PARMS+40(r1)
271         stfd    fp7,FPR_PARMS+48(r1)
272         stfd    fp8,FPR_PARMS+56(r1)
273         stfd    fp9,FPR_PARMS+64(r1)
274         stfd    fp10,FPR_PARMS+72(r1)
275         stfd    fp11,FPR_PARMS+80(r1)
276         li      r0,-1
277         stfd    fp12,FPR_PARMS+88(r1)
278         stfd    fp13,FPR_PARMS+96(r1)
279 /* Load the extra parameters.  */
280         addi    r6,r1,INT_PARMS
281         addi    r7,r1,STACK_FRAME
282 /* Save  link_map* and reloc_addr parms for later.  */
283         mr      r31,r3
284         mr      r30,r4
285         std     r0,0(r7)
286         bl      JUMPTARGET(_dl_profile_fixup)
287 #ifndef SHARED
288         nop
289 #endif
290 /* Test *framesizep > 0 to see if need to do pltexit processing.  */
291         ld      r0,STACK_FRAME(r1)
292 /* Put the registers back.  */
293         lwz     r12,VR_VRSAVE(r1)
294         cmpdi   cr1,r0,0
295         cmpdi   cr0,r12,0
296         bgt     cr1,L(do_pltexit)
297         la      r10,(VR_PARMS+0)(r1)
298         la      r9,(VR_PARMS+16)(r1)
299 /* VRSAVE must be non-zero if VMX is present and VRs are in use. */
300         beq     L(restoreFXR)
301         li      r11,32
302         li      r12,64
303         lvx     v2,0,r10
304         lvx     v3,0,r9
306         lvx     v4,r11,r10
307         lvx     v5,r11,r9
308         addi    r11,r11,64
310         lvx     v6,r12,r10
311         lvx     v7,r12,r9
312         addi    r12,r12,64
314         lvx     v8,r11,r10
315         lvx     v9,r11,r9
316         addi    r11,r11,64
318         lvx     v10,r12,r10
319         lvx     v11,r12,r9
321         lvx     v12,r11,r10
322         lvx     v13,r11,r9
323 L(restoreFXR):
324         ld      r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
325         ld      r10,INT_PARMS+56(r1)
326         ld      r9,INT_PARMS+48(r1)
327         ld      r8,INT_PARMS+40(r1)
328         ld      r7,INT_PARMS+32(r1)
329         mtlr    r0
330         ld      r6,INT_PARMS+24(r1)
331         ld      r5,INT_PARMS+16(r1)
332         ld      r4,INT_PARMS+8(r1)
333 /* Prepare for calling the function returned by fixup.  */
334         PPC64_LOAD_FUNCPTR r3
335         ld      r3,INT_PARMS+0(r1)
336 #if _CALL_ELF == 2
337 /* Restore the caller's TOC in case we jump to a local entry point.  */
338         ld      r2,FRAME_SIZE+FRAME_TOC_SAVE(r1)
339 #endif
340 /* Load the floating point registers.  */
341         lfd     fp1,FPR_PARMS+0(r1)
342         lfd     fp2,FPR_PARMS+8(r1)
343         lfd     fp3,FPR_PARMS+16(r1)
344         lfd     fp4,FPR_PARMS+24(r1)
345         lfd     fp5,FPR_PARMS+32(r1)
346         lfd     fp6,FPR_PARMS+40(r1)
347         lfd     fp7,FPR_PARMS+48(r1)
348         lfd     fp8,FPR_PARMS+56(r1)
349         lfd     fp9,FPR_PARMS+64(r1)
350         lfd     fp10,FPR_PARMS+72(r1)
351         lfd     fp11,FPR_PARMS+80(r1)
352         lfd     fp12,FPR_PARMS+88(r1)
353         lfd     fp13,FPR_PARMS+96(r1)
354 /* Unwind the stack frame, and jump.  */
355         ld      r31,FRAME_SIZE-8(r1)
356         ld      r30,FRAME_SIZE-16(r1)
357         addi    r1,r1,FRAME_SIZE
358         bctr
360 L(do_pltexit):
361         la      r10,(VR_PARMS+0)(r1)
362         la      r9,(VR_PARMS+16)(r1)
363         beq     L(restoreFXR2)
364         li      r11,32
365         li      r12,64
366         lvx     v2,0,r10
367         lvx     v3,0,r9
369         lvx     v4,r11,r10
370         lvx     v5,r11,r9
371         addi    r11,r11,64
373         lvx     v6,r12,r10
374         lvx     v7,r12,r9
375         addi    r12,r12,64
377         lvx     v8,r11,r10
378         lvx     v9,r11,r9
379         addi    r11,r11,64
381         lvx     v10,r12,r10
382         lvx     v11,r12,r9
384         lvx     v12,r11,r10
385         lvx     v13,r11,r9
386 L(restoreFXR2):
387         ld      r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
388         ld      r10,INT_PARMS+56(r1)
389         ld      r9,INT_PARMS+48(r1)
390         ld      r8,INT_PARMS+40(r1)
391         ld      r7,INT_PARMS+32(r1)
392         mtlr    r0
393         ld      r6,INT_PARMS+24(r1)
394         ld      r5,INT_PARMS+16(r1)
395         ld      r4,INT_PARMS+8(r1)
396 /* Prepare for calling the function returned by fixup.  */
397         std     r2,FRAME_TOC_SAVE(r1)
398         PPC64_LOAD_FUNCPTR r3
399         ld      r3,INT_PARMS+0(r1)
400 /* Load the floating point registers.  */
401         lfd     fp1,FPR_PARMS+0(r1)
402         lfd     fp2,FPR_PARMS+8(r1)
403         lfd     fp3,FPR_PARMS+16(r1)
404         lfd     fp4,FPR_PARMS+24(r1)
405         lfd     fp5,FPR_PARMS+32(r1)
406         lfd     fp6,FPR_PARMS+40(r1)
407         lfd     fp7,FPR_PARMS+48(r1)
408         lfd     fp8,FPR_PARMS+56(r1)
409         lfd     fp9,FPR_PARMS+64(r1)
410         lfd     fp10,FPR_PARMS+72(r1)
411         lfd     fp11,FPR_PARMS+80(r1)
412         lfd     fp12,FPR_PARMS+88(r1)
413         lfd     fp13,FPR_PARMS+96(r1)
414 /* Call the target function.  */
415         bctrl
416         ld      r2,FRAME_TOC_SAVE(r1)
417         lwz     r12,VR_VRSAVE(r1)
418 /* But return here and store the return values.  */
419         std     r3,INT_RTN(r1)
420         std     r4,INT_RTN+8(r1)
421         stfd    fp1,FPR_RTN+0(r1)
422         stfd    fp2,FPR_RTN+8(r1)
423         cmpdi   cr0,r12,0
424         la      r10,VR_RTN(r1)
425         stfd    fp3,FPR_RTN+16(r1)
426         stfd    fp4,FPR_RTN+24(r1)
427 #if _CALL_ELF == 2
428         la      r12,VR_RTN+16(r1)
429         stfd    fp5,FPR_RTN+32(r1)
430         stfd    fp6,FPR_RTN+40(r1)
431         li      r5,32
432         li      r6,64
433         stfd    fp7,FPR_RTN+48(r1)
434         stfd    fp8,FPR_RTN+56(r1)
435         stfd    fp9,FPR_RTN+64(r1)
436         stfd    fp10,FPR_RTN+72(r1)
437 #endif
438         mr      r3,r31
439         mr      r4,r30
440         beq     L(callpltexit)
441         stvx    v2,0,r10
442 #if _CALL_ELF == 2
443         stvx    v3,0,r12
444         stvx    v4,r5,r10
445         stvx    v5,r5,r12
446         addi    r5,r5,64
447         stvx    v6,r6,r10
448         stvx    v7,r6,r12
449         stvx    v8,r5,r10
450         stvx    v9,r5,r12
451 #endif
452 L(callpltexit):
453         addi    r5,r1,INT_PARMS
454         addi    r6,r1,INT_RTN
455         bl      JUMPTARGET(_dl_call_pltexit)
456 #ifndef SHARED
457         nop
458 #endif
459 /* Restore the return values from target function.  */
460         lwz     r12,VR_VRSAVE(r1)
461         ld      r3,INT_RTN(r1)
462         ld      r4,INT_RTN+8(r1)
463         lfd     fp1,FPR_RTN+0(r1)
464         lfd     fp2,FPR_RTN+8(r1)
465         cmpdi   cr0,r12,0
466         la      r11,VR_RTN(r1)
467         lfd     fp3,FPR_RTN+16(r1)
468         lfd     fp4,FPR_RTN+24(r1)
469 #if _CALL_ELF == 2
470         la      r12,VR_RTN+16(r1)
471         lfd     fp5,FPR_RTN+32(r1)
472         lfd     fp6,FPR_RTN+40(r1)
473         li      r30,32
474         li      r31,64
475         lfd     fp7,FPR_RTN+48(r1)
476         lfd     fp8,FPR_RTN+56(r1)
477         lfd     fp9,FPR_RTN+64(r1)
478         lfd     fp10,FPR_RTN+72(r1)
479 #endif
480         beq     L(pltexitreturn)
481         lvx     v2,0,r11
482 #if _CALL_ELF == 2
483         lvx     v3,0,r12
484         lvx     v4,r30,r11
485         lvx     v5,r30,r12
486         addi    r30,r30,64
487         lvx     v6,r31,r11
488         lvx     v7,r31,r12
489         lvx     v8,r30,r11
490         lvx     v9,r30,r12
491 #endif
492 L(pltexitreturn):
493         ld      r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
494         ld      r31,FRAME_SIZE-8(r1)
495         ld      r30,FRAME_SIZE-16(r1)
496         mtlr    r0
497         ld      r1,0(r1)
498         blr
499 END(_dl_profile_resolve)
500 #endif