* sysdeps/powerpc/powerpc64/Makefile (no-special-regs): New variable.
[glibc.git] / sysdeps / powerpc / powerpc64 / dl-trampoline.S
blobc5afe5a3fa30f800fb1e8d1bc80b1021b18e207e
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         std     r30,-16(r1)
180 /* We need to save the registers used to pass parameters, ie. r3 thru
181    r10; the registers are saved in a stack frame.  */
182         stdu    r1,-FRAME_SIZE(r1)
183         cfi_adjust_cfa_offset (FRAME_SIZE)
184         std     r3,INT_PARMS+0(r1)
185         mr      r3,r11
186         std     r4,INT_PARMS+8(r1)
187         sldi    r4,r0,1         /* index * 2 */
188         std     r5,INT_PARMS+16(r1)
189         add     r4,r4,r0        /* index * 3 */
190         std     r6,INT_PARMS+24(r1)
191         sldi    r4,r4,3         /* index * 24  == PLT offset */
192         mflr    r5
193         std     r7,INT_PARMS+32(r1)
194         std     r8,INT_PARMS+40(r1)
195 /* Store the LR in the LR Save area of the previous frame.  */
196 /* XXX Do we have to do this?  */
197         la      r8,FRAME_SIZE(r1)
198         std     r5,FRAME_SIZE+16(r1)
199         cfi_offset (lr, 16)
200         std     r5,CALLING_LR(r1)
201         mfcr    r0
202         std     r9,INT_PARMS+48(r1)
203         std     r10,INT_PARMS+56(r1)
204         std     r8,CALLING_SP(r1)
205 /* I'm almost certain we don't have to save cr...  be safe.  */
206         std     r0,8(r1)
207         ld      r12,.LC__dl_hwcap@toc(r2)
208 #ifdef SHARED
209         /* Load _rtld-global._dl_hwcap.  */
210         ld      r12,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r12)
211 #else
212         ld      r12,0(r12) /* Load extern _dl_hwcap.  */
213 #endif
214         andis.  r0,r12,(PPC_FEATURE_HAS_ALTIVEC >> 16)
215         beq     L(saveFP)
216         la      r10,(VR_PARMS+0)(r1)
217         la      r9,(VR_PARMS+16)(r1)
218         li      r11,32
219         li      r12,64
220         stvx    v2,0,r10
221         stvx    v3,0,r9
223         stvx    v4,r11,r10
224         stvx    v5,r11,r9
225         addi    r11,r11,64
227         stvx    v6,r12,r10
228         stvx    v7,r12,r9
229         addi    r12,r12,64
231         stvx    v8,r11,r10
232         stvx    v9,r11,r9
233         addi    r11,r11,64
235         stvx    v10,r12,r10
236         stvx    v11,r12,r9
237         mfspr   r0,VRSAVE
239         stvx    v12,r11,r10
240         stvx    v13,r11,r9
241 L(saveFP):
242         stw     r0,VR_VRSAVE(r1)
243 /* Save floating registers.  */
244         stfd    fp1,FPR_PARMS+0(r1)
245         stfd    fp2,FPR_PARMS+8(r1)
246         stfd    fp3,FPR_PARMS+16(r1)
247         stfd    fp4,FPR_PARMS+24(r1)
248         stfd    fp5,FPR_PARMS+32(r1)
249         stfd    fp6,FPR_PARMS+40(r1)
250         stfd    fp7,FPR_PARMS+48(r1)
251         stfd    fp8,FPR_PARMS+56(r1)
252         stfd    fp9,FPR_PARMS+64(r1)
253         stfd    fp10,FPR_PARMS+72(r1)
254         stfd    fp11,FPR_PARMS+80(r1)
255         li      r0,-1
256         stfd    fp12,FPR_PARMS+88(r1)
257         stfd    fp13,FPR_PARMS+96(r1)
258 /* Load the extra parameters.  */
259         addi    r6,r1,INT_PARMS
260         addi    r7,r1,STACK_FRAME
261 /* Save  link_map* and reloc_addr parms for later.  */
262         mr      r31,r3
263         mr      r30,r4
264         std     r0,0(r7)
265         bl      JUMPTARGET(_dl_profile_fixup)
266         nop
267 /* Test *framesizep > 0 to see if need to do pltexit processing.  */
268         ld      r0,STACK_FRAME(r1)
269 /* Put the registers back.  */
270         lwz     r12,VR_VRSAVE(r1)
271         cmpdi   cr1,r0,0
272         cmpdi   cr0,r12,0
273         bgt     cr1,L(do_pltexit)
274         la      r10,(VR_PARMS+0)(r1)
275         la      r9,(VR_PARMS+16)(r1)
276 /* VRSAVE must be non-zero if VMX is present and VRs are in use. */
277         beq     L(restoreFXR)
278         li      r11,32
279         li      r12,64
280         lvx     v2,0,r10
281         lvx     v3,0,r9
283         lvx     v4,r11,r10
284         lvx     v5,r11,r9
285         addi    r11,r11,64
287         lvx     v6,r12,r10
288         lvx     v7,r12,r9
289         addi    r12,r12,64
291         lvx     v8,r11,r10
292         lvx     v9,r11,r9
293         addi    r11,r11,64
295         lvx     v10,r12,r10
296         lvx     v11,r12,r9
298         lvx     v12,r11,r10
299         lvx     v13,r11,r9
300 L(restoreFXR):
301         ld      r0,FRAME_SIZE+16(r1)
302         ld      r10,INT_PARMS+56(r1)
303         ld      r9,INT_PARMS+48(r1)
304         ld      r8,INT_PARMS+40(r1)
305         ld      r7,INT_PARMS+32(r1)
306         mtlr    r0
307         ld      r0,8(r1)
308         ld      r6,INT_PARMS+24(r1)
309         ld      r5,INT_PARMS+16(r1)
310         ld      r4,INT_PARMS+8(r1)
311         mtcrf   0xFF,r0
312 /* Load the target address, toc and static chain reg from the function
313    descriptor returned by fixup.  */
314         ld      r0,0(r3)
315         ld      r2,8(r3)
316         ld      r11,16(r3)
317         ld      r3,INT_PARMS+0(r1)
318         mtctr   r0
319 /* Load the floating point registers.  */
320         lfd     fp1,FPR_PARMS+0(r1)
321         lfd     fp2,FPR_PARMS+8(r1)
322         lfd     fp3,FPR_PARMS+16(r1)
323         lfd     fp4,FPR_PARMS+24(r1)
324         lfd     fp5,FPR_PARMS+32(r1)
325         lfd     fp6,FPR_PARMS+40(r1)
326         lfd     fp7,FPR_PARMS+48(r1)
327         lfd     fp8,FPR_PARMS+56(r1)
328         lfd     fp9,FPR_PARMS+64(r1)
329         lfd     fp10,FPR_PARMS+72(r1)
330         lfd     fp11,FPR_PARMS+80(r1)
331         lfd     fp12,FPR_PARMS+88(r1)
332         lfd     fp13,FPR_PARMS+96(r1)
333 /* Unwind the stack frame, and jump.  */
334         ld      r31,584(r1)
335         ld      r30,576(r1)
336         addi    r1,r1,FRAME_SIZE
337         bctr
338 L(do_pltexit):
339         la      r10,(VR_PARMS+0)(r1)
340         la      r9,(VR_PARMS+16)(r1)
341         beq     L(restoreFXR2)
342         li      r11,32
343         li      r12,64
344         lvx     v2,0,r10
345         lvx     v3,0,r9
347         lvx     v4,r11,r10
348         lvx     v5,r11,r9
349         addi    r11,r11,64
351         lvx     v6,r12,r10
352         lvx     v7,r12,r9
353         addi    r12,r12,64
355         lvx     v8,r11,r10
356         lvx     v9,r11,r9
357         addi    r11,r11,64
359         lvx     v10,r12,r10
360         lvx     v11,r12,r9
362         lvx     v12,r11,r10
363         lvx     v13,r11,r9
364 L(restoreFXR2):
365         ld      r0,FRAME_SIZE+16(r1)
366         ld      r10,INT_PARMS+56(r1)
367         ld      r9,INT_PARMS+48(r1)
368         ld      r8,INT_PARMS+40(r1)
369         ld      r7,INT_PARMS+32(r1)
370         mtlr    r0
371         ld      r0,8(r1)
372         ld      r6,INT_PARMS+24(r1)
373         ld      r5,INT_PARMS+16(r1)
374         ld      r4,INT_PARMS+8(r1)
375         mtcrf   0xFF,r0
376 /* Load the target address, toc and static chain reg from the function
377    descriptor returned by fixup.  */
378         ld      r0,0(r3)
379         std     r2,40(r1)
380         ld      r2,8(r3)
381         ld      r11,16(r3)
382         ld      r3,INT_PARMS+0(r1)
383         mtctr   r0
384 /* Load the floating point registers.  */
385         lfd     fp1,FPR_PARMS+0(r1)
386         lfd     fp2,FPR_PARMS+8(r1)
387         lfd     fp3,FPR_PARMS+16(r1)
388         lfd     fp4,FPR_PARMS+24(r1)
389         lfd     fp5,FPR_PARMS+32(r1)
390         lfd     fp6,FPR_PARMS+40(r1)
391         lfd     fp7,FPR_PARMS+48(r1)
392         lfd     fp8,FPR_PARMS+56(r1)
393         lfd     fp9,FPR_PARMS+64(r1)
394         lfd     fp10,FPR_PARMS+72(r1)
395         lfd     fp11,FPR_PARMS+80(r1)
396         lfd     fp12,FPR_PARMS+88(r1)
397         lfd     fp13,FPR_PARMS+96(r1)
398 /* Call the target function.  */
399         bctrl
400         ld      r2,40(r1)
401         lwz     r12,VR_VRSAVE(r1)
402 /* But return here and store the return values.  */
403         std     r3,INT_RTN(r1)
404         std     r4,INT_RTN+8(r1)
405         stfd    fp1,FPR_PARMS+0(r1)
406         stfd    fp2,FPR_PARMS+8(r1)
407         cmpdi   cr0,r12,0
408         la      r10,VR_RTN(r1)
409         stfd    fp3,FPR_PARMS+16(r1)
410         stfd    fp4,FPR_PARMS+24(r1)
411         mr      r3,r31
412         mr      r4,r30
413         beq     L(callpltexit)
414         stvx    v2,0,r10
415 L(callpltexit):
416         addi    r5,r1,INT_PARMS
417         addi    r6,r1,INT_RTN
418         bl      JUMPTARGET(_dl_call_pltexit)
419         nop
420 /* Restore the return values from target function.  */
421         lwz     r12,VR_VRSAVE(r1)
422         ld      r3,INT_RTN(r1)
423         ld      r4,INT_RTN+8(r1)
424         lfd     fp1,FPR_PARMS+0(r1)
425         lfd     fp2,FPR_PARMS+8(r1)
426         cmpdi   cr0,r12,0
427         la      r10,VR_RTN(r1)
428         lfd     fp3,FPR_PARMS+16(r1)
429         lfd     fp4,FPR_PARMS+24(r1)
430         beq     L(pltexitreturn)
431         lvx     v2,0,r10
432 L(pltexitreturn):
433         ld      r0,FRAME_SIZE+16(r1)
434         ld      r31,584(r1)
435         ld      r30,576(r1)
436         mtlr    r0
437         ld      r1,0(r1)
438         blr
439 END(_dl_profile_resolve)
440 #endif