diff options
Diffstat (limited to 'ports/sysdeps/hppa/dl-trampoline.S')
-rw-r--r-- | ports/sysdeps/hppa/dl-trampoline.S | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/ports/sysdeps/hppa/dl-trampoline.S b/ports/sysdeps/hppa/dl-trampoline.S new file mode 100644 index 0000000000..21be0a04af --- /dev/null +++ b/ports/sysdeps/hppa/dl-trampoline.S @@ -0,0 +1,288 @@ +/* PLT trampolines. hppa version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +/* This code gets called via the .plt stub, and is used in + dl-runtime.c to call the `_dl_fixup' function and then redirect + to the address it returns. `_dl_fixup' takes two arguments, however + `_dl_profile_fixup' takes a number of parameters for use with + library auditing (LA). + + WARNING: This template is also used by gcc's __cffc, and expects + that the "bl" for _dl_runtime_resolve exist at a particular offset. + Do not change this template without changing gcc, while the prefix + "bl" should fix everything so gcc finds the right spot, it will + slow down __cffc when it attempts to call fixup to resolve function + descriptor references. Please refer to gcc/gcc/config/pa/fptr.c + + Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */ + + /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ + .text + /* THIS CODE DOES NOT EXECUTE */ + bl _dl_fixup, %r2 + .text + .global _dl_runtime_resolve + .type _dl_runtime_resolve,@function + cfi_startproc + .align 4 +_dl_runtime_resolve: + .PROC + .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 + .ENTRY + /* SAVE_RP says we do */ + stw %rp, -20(%sp) + + /* Save static link register */ + stw %r29,-16(%sp) + /* Save argument registers */ + stw %r26,-36(%sp) + stw %r25,-40(%sp) + stw %r24,-44(%sp) + stw %r23,-48(%sp) + + /* Build a call frame, and save structure pointer. */ + copy %sp, %r1 /* Copy previous sp */ + /* Save function result address (on entry) */ + stwm %r28,128(%sp) + /* Fillin some frame info to follow ABI */ + stw %r1,-4(%sp) /* Previous sp */ + stw %r21,-32(%sp) /* PIC register value */ + + /* Save input floating point registers. This must be done + in the new frame since the previous frame doesn't have + enough space */ + ldo -56(%sp),%r1 + fstd,ma %fr4,-8(%r1) + fstd,ma %fr5,-8(%r1) + fstd,ma %fr6,-8(%r1) + fstd,ma %fr7,-8(%r1) + + /* Set up args to fixup func, needs only two arguments */ + ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ + copy %r19,%r25 /* (2) reloc offset */ + + /* Call the real address resolver. */ + bl _dl_fixup,%rp + copy %r21,%r19 /* set fixup func ltp */ + + /* Load up the returned func descriptor */ + copy %r28, %r22 + copy %r29, %r19 + + /* Reload arguments fp args */ + ldo -56(%sp),%r1 + fldd,ma -8(%r1),%fr4 + fldd,ma -8(%r1),%fr5 + fldd,ma -8(%r1),%fr6 + fldd,ma -8(%r1),%fr7 + + /* Adjust sp, and restore function result address*/ + ldwm -128(%sp),%r28 + + /* Reload static link register */ + ldw -16(%sp),%r29 + /* Reload general args */ + ldw -36(%sp),%r26 + ldw -40(%sp),%r25 + ldw -44(%sp),%r24 + ldw -48(%sp),%r23 + + /* Jump to new function, but return to previous function */ + bv %r0(%r22) + ldw -20(%sp),%rp + .EXIT + .PROCEND + cfi_endproc + .size _dl_runtime_resolve, . - _dl_runtime_resolve + + .text + .global _dl_runtime_profile + .type _dl_runtime_profile,@function + cfi_startproc + .align 4 +_dl_runtime_profile: + .PROC + .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 + .ENTRY + + /* SAVE_RP says we do */ + stw %rp, -20(%sp) + /* Save static link register */ + stw %r29,-16(%sp) + + /* Build a call frame, and save structure pointer. */ + copy %sp, %r1 /* Copy previous sp */ + /* Save function result address (on entry) */ + stwm %r28,192(%sp) + /* Fillin some frame info to follow ABI */ + stw %r1,-4(%sp) /* Previous sp */ + stw %r21,-32(%sp) /* PIC register value */ + + /* Create La_hppa_retval */ + /* -140, lrv_r28 + -136, lrv_r29 + -132, 4 byte pad + -128, lr_fr4 (8 bytes) */ + + /* Create save space for _dl_profile_fixup arguments + -120, Saved reloc offset + -116, Saved struct link_map + -112, *framesizep */ + + /* Create La_hppa_regs */ + /* 32-bit registers */ + stw %r26,-108(%sp) + stw %r25,-104(%sp) + stw %r24,-100(%sp) + stw %r23,-96(%sp) + /* -92, 4 byte pad */ + /* 64-bit floating point registers */ + ldo -88(%sp),%r1 + fstd,ma %fr4,8(%r1) + fstd,ma %fr5,8(%r1) + fstd,ma %fr6,8(%r1) + fstd,ma %fr7,8(%r1) + /* 32-bit stack pointer and return register */ + stw %sp,-56(%sp) + stw %r2,-52(%sp) + + + /* Set up args to fixup func, needs five arguments */ + ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ + stw %r26,-116(%sp) /* Save struct link_map */ + copy %r19,%r25 /* (2) reloc offset */ + stw %r25,-120(%sp) /* Save reloc offset */ + copy %rp,%r24 /* (3) profile_fixup needs rp */ + ldo -56(%sp),%r23 /* (4) La_hppa_regs */ + ldo -112(%sp), %r1 + stw %r1, -52(%sp) /* (5) long int *framesizep */ + + /* Call the real address resolver. */ + bl _dl_profile_fixup,%rp + copy %r21,%r19 /* set fixup func ltp */ + + /* Load up the returned function descriptor */ + copy %r28, %r22 + copy %r29, %r19 + + /* Restore gr/fr/sp/rp */ + ldw -108(%sp),%r26 + ldw -104(%sp),%r25 + ldw -100(%sp),%r24 + ldw -96(%sp),%r23 + /* -92, 4 byte pad, skip */ + ldo -88(%sp),%r1 + fldd,ma 8(%r1),%fr4 + fldd,ma 8(%r1),%fr5 + fldd,ma 8(%r1),%fr6 + fldd,ma 8(%r1),%fr7 + ldw -52(%sp),%rp + + /* Reload static link register -(192+16) without adjusting stack */ + ldw -208(%sp),%r29 + + /* *framesizep is >= 0 if we have to run pltexit */ + ldw -112(%sp),%r28 + cmpb,>>=,N %r0,%r28,L(cpe) + + /* Adjust sp, and restore function result address*/ + ldwm -192(%sp),%r28 + /* Jump to new function, but return to previous function */ + bv %r0(%r22) + ldw -20(%sp),%rp + /* NO RETURN */ + +L(nf): + /* Call the returned function descriptor */ + bv %r0(%r22) + nop + b,n L(cont) + +L(cpe): + /* We are going to call the resolved function, but we have a + stack frame in the middle. We use the value of framesize to + guess how much extra frame we need, and how much frame to + copy forward. */ + + /* Round to nearest multiple of 64 */ + addi 63, %r28, %r28 + depi 0, 27, 6, %r28 + + /* Calcualte start of stack copy */ + ldo -192(%sp),%r2 + + /* Increate the stack by *framesizep */ + copy %sp, %r1 + add %sp, %r28, %sp + /* Save stack pointer */ + stw %r1, -4(%sp) + + /* Single byte copy of prevous stack onto newly allocated stack */ +1: ldb %r28(%r2), %r1 + add %r28, %sp, %r26 + stb %r1, 0(%r26) + addi,< -1,%r28,%r28 + b,n 1b + + /* Retore r28 and r27 and r2 already points at -192(%sp) */ + ldw 0(%r2),%r28 + ldw 84(%r2),%r26 + + /* Calculate address of L(cont) */ + b,l L(nf),%r2 + depwi 0,31,2,%r2 +L(cont): + /* Undo fake stack */ + ldw -4(%sp),%r1 + copy %r1, %sp + + /* Arguments to _dl_call_pltexit */ + ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ + ldw -120(%sp), %r25 /* (2) reloc offsets */ + ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ + ldo -124(%sp), %r23 /* (4) *La_hppa_retval */ + + /* Fill *La_hppa_retval */ + stw %r28,-140(%sp) + stw %r29,-136(%sp) + ldo -128(%sp), %r1 + fstd %fr4,0(%r1) + + /* Call _dl_call_pltexit */ + bl _dl_call_pltexit,%rp + nop + + /* Restore *La_hppa_retval */ + ldw -140(%sp), %r28 + ldw -136(%sp), %r29 + ldo -128(%sp), %r1 + fldd 0(%r1), %fr4 + + /* Unwind the stack */ + ldo 192(%sp),%sp + /* Retore callers rp */ + ldw -20(%sp),%rp + /* Return */ + bv,n 0(%r2) + .EXIT + .PROCEND + cfi_endproc + .size _dl_runtime_profile, . - _dl_runtime_profile + |