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