Update copyright notices with scripts/update-copyrights.
[glibc.git] / ports / sysdeps / aarch64 / dl-trampoline.S
blob94c69a0e2dab0320be0c0a27914eaa2520bf6fb6
1 /* Copyright (C) 2005-2013 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 License as
7    published by the Free Software Foundation; either version 2.1 of the
8    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    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <libc-symbols.h>
22 #include "dl-link.h"
24 #define ip0 x16
25 #define ip1 x17
26 #define lr  x30
28         .text
29         .globl _dl_runtime_resolve
30         .type _dl_runtime_resolve, #function
31         cfi_startproc
32         .align 2
33 _dl_runtime_resolve:
34         /* AArch64 we get called with:
35            ip0          &PLTGOT[2]
36            ip1          temp(dl resolver entry point)
37            [sp, #8]     lr
38            [sp, #0]     &PLTGOT[n]
39          */
41         cfi_rel_offset (lr, 8)
43         /* Save arguments.  */
44         stp     x8, x9, [sp, #-80]!
45         cfi_adjust_cfa_offset (80)
46         cfi_rel_offset (x8, 0)
47         cfi_rel_offset (x9, 8)
49         stp     x6, x7, [sp,  #16]
50         cfi_rel_offset (x6, 16)
51         cfi_rel_offset (x7, 24)
53         stp     x4, x5, [sp,  #32]
54         cfi_rel_offset (x4, 32)
55         cfi_rel_offset (x5, 40)
57         stp     x2, x3, [sp,  #48]
58         cfi_rel_offset (x2, 48)
59         cfi_rel_offset (x3, 56)
61         stp     x0, x1, [sp,  #64]
62         cfi_rel_offset (x0, 64)
63         cfi_rel_offset (x1, 72)
65         /* Get pointer to linker struct.  */
66         ldr     x0, [ip0, #-8]
68         /* Prepare to call _dl_fixup().  */
69         ldr     x1, [sp, 80]    /* Recover &PLTGOT[n] */
71         sub     x1, x1, ip0
72         add     x1, x1, x1, lsl #1
73         lsl     x1, x1, #3
74         sub     x1, x1, #192
75         lsr     x1, x1, #3
77         /* Call fixup routine.  */
78         bl      _dl_fixup
80         /* Save the return.  */
81         mov     ip0, x0
83         /* Get arguments and return address back.  */
84         ldp     x0, x1, [sp, #64]
85         ldp     x2, x3, [sp, #48]
86         ldp     x4, x5, [sp, #32]
87         ldp     x6, x7, [sp, #16]
88         ldp     x8, x9, [sp], #80
89         cfi_adjust_cfa_offset (-80)
91         ldp     ip1, lr, [sp], #16
92         cfi_adjust_cfa_offset (-16)
94         /* Jump to the newly found address.  */
95         br      ip0
97         cfi_endproc
98         .size _dl_runtime_resolve, .-_dl_runtime_resolve
99 #ifndef PROF
100         .globl _dl_runtime_profile
101         .type _dl_runtime_profile, #function
102         cfi_startproc
103         .align 2
104 _dl_runtime_profile:
105         /* AArch64 we get called with:
106            ip0          &PLTGOT[2]
107            ip1          temp(dl resolver entry point)
108            [sp, #8]     lr
109            [sp, #0]     &PLTGOT[n]
111            Stack frame layout:
112            [sp,   #...] lr
113            [sp,   #...] &PLTGOT[n]
114            [sp,    #96] La_aarch64_regs
115            [sp,    #48] La_aarch64_retval
116            [sp,    #40] frame size return from pltenter
117            [sp,    #32] dl_profile_call saved x1
118            [sp,    #24] dl_profile_call saved x0
119            [sp,    #16] t1
120            [sp,     #0] x29, lr   <- x29
121          */
123 # define OFFSET_T1              16
124 # define OFFSET_SAVED_CALL_X0   OFFSET_T1 + 8
125 # define OFFSET_FS              OFFSET_SAVED_CALL_X0 + 16
126 # define OFFSET_RV              OFFSET_FS + 8
127 # define OFFSET_RG              OFFSET_RV + DL_SIZEOF_RV
129 # define SF_SIZE                OFFSET_RG + DL_SIZEOF_RG
131 # define OFFSET_PLTGOTN         SF_SIZE
132 # define OFFSET_LR              OFFSET_PLTGOTN + 8
134         /* Save arguments.  */
135         sub     sp, sp, #SF_SIZE
136         cfi_adjust_cfa_offset (SF_SIZE)
137         stp     x29, x30, [SP, #0]
138         mov     x29, sp
139         cfi_def_cfa_register (x29)
140         cfi_rel_offset (x29, 0)
141         cfi_rel_offset (lr, 8)
143         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
144         cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
145         cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
146         stp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
147         cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
148         cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
149         stp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
150         cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
151         cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
152         stp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
153         cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
154         cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
156         stp     d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
157         cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0)
158         cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8)
159         stp     d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1]
160         cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0)
161         cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8)
162         stp     d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
163         cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0)
164         cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8)
165         stp     d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
166         cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0)
167         cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8)
169         add     x0, x29, #SF_SIZE + 16
170         ldr     x1, [x29, #OFFSET_LR]
171         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP]
173         /* Get pointer to linker struct.  */
174         ldr     x0, [ip0, #-8]
176         /* Prepare to call _dl_profile_fixup().  */
177         ldr     x1, [x29, OFFSET_PLTGOTN]       /* Recover &PLTGOT[n] */
179         sub     x1, x1, ip0
180         add     x1, x1, x1, lsl #1
181         lsl     x1, x1, #3
182         sub     x1, x1, #192
183         lsr     x1, x1, #3
185         stp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
187         /* Set up extra args for _dl_profile_fixup */
188         ldr     x2, [x29, #OFFSET_LR]           /* load saved LR */
189         add     x3, x29, #OFFSET_RG             /* address of La_aarch64_reg */
190         add     x4, x29, #OFFSET_FS             /* address of framesize */
191         bl      _dl_profile_fixup
193         ldr     ip0, [x29, #OFFSET_FS]          /* framesize == 0 */
194         cmp     ip0, #0
195         bge     1f
196         cfi_remember_state
198         /* Save the return.  */
199         mov     ip0, x0
201         /* Get arguments and return address back.  */
202         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
203         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
204         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
205         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
206         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
207         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
208         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
209         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
211         cfi_def_cfa_register (sp)
212         ldp     x29, x30, [x29, #0]
213         cfi_restore(x29)
214         cfi_restore(x30)
216         add     sp, sp, SF_SIZE + 16
217         cfi_adjust_cfa_offset (- SF_SIZE - 16)
219         /* Jump to the newly found address.  */
220         br      ip0
222         cfi_restore_state
224         /* The new frame size is in ip0.  */
226         sub     x1, x29, ip0
227         and     sp, x1, #0xfffffffffffffff0
229         str     x0, [x29, #OFFSET_T1]
231         mov     x0, sp
232         add     x1, x29, #SF_SIZE + 16
233         mov     x2, ip0
234         bl      memcpy
236         ldr     ip0, [x29, #OFFSET_T1]
238         /* Call the function.  */
239         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
240         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
241         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
242         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
243         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
244         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
245         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
246         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
247         blr     ip0
248         stp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
249         stp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
250         stp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
252         /* Setup call to pltexit  */
253         ldp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
254         add     x2, x29, #OFFSET_RG
255         add     x3, x29, #OFFSET_RV
256         bl      _dl_call_pltexit
258         ldp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
259         ldp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
260         ldp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
261         /* LR from within La_aarch64_reg */
262         ldr     lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
263         cfi_restore(lr)
264         mov     sp, x29
265         cfi_def_cfa_register (sp)
266         ldr     x29, [x29, #0]
267         cfi_restore(x29)
268         add     sp, sp, SF_SIZE + 16
269         cfi_adjust_cfa_offset (- SF_SIZE - 16)
271         br      lr
273         cfi_endproc
274         .size _dl_runtime_profile, .-_dl_runtime_profile
275 #endif
276         .previous