]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/powerpc64/dl-trampoline.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / dl-trampoline.S
1 /* PLT trampolines. PPC64 version.
2 Copyright (C) 2005-2019 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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/>. */
18
19 #include <sysdep.h>
20 #include <rtld-global-offsets.h>
21
22
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). */
28
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 ENTRY (_dl_runtime_resolve, 4)
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
82
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"
191
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 ENTRY (_dl_profile_resolve, 4)
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
243
244 stvx v4,r11,r10
245 stvx v5,r11,r9
246 addi r11,r11,64
247
248 stvx v6,r12,r10
249 stvx v7,r12,r9
250 addi r12,r12,64
251
252 stvx v8,r11,r10
253 stvx v9,r11,r9
254 addi r11,r11,64
255
256 stvx v10,r12,r10
257 stvx v11,r12,r9
258 mfspr r0,VRSAVE
259
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
305
306 lvx v4,r11,r10
307 lvx v5,r11,r9
308 addi r11,r11,64
309
310 lvx v6,r12,r10
311 lvx v7,r12,r9
312 addi r12,r12,64
313
314 lvx v8,r11,r10
315 lvx v9,r11,r9
316 addi r11,r11,64
317
318 lvx v10,r12,r10
319 lvx v11,r12,r9
320
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
359
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
368
369 lvx v4,r11,r10
370 lvx v5,r11,r9
371 addi r11,r11,64
372
373 lvx v6,r12,r10
374 lvx v7,r12,r9
375 addi r12,r12,64
376
377 lvx v8,r11,r10
378 lvx v9,r11,r9
379 addi r11,r11,64
380
381 lvx v10,r12,r10
382 lvx v11,r12,r9
383
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