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