Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / aarch64 / dl-trampoline.S
blobc007165ad5c8f8e493d0e61a9ead003986cdf0e1
1 /* Copyright (C) 2005-2014 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+8*16)]!
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         stp     q0, q1, [sp, #(80+0*16)]
66         cfi_rel_offset (q0, 80+0*16)
67         cfi_rel_offset (q1, 80+1*16)
69         stp     q2, q3, [sp, #(80+2*16)]
70         cfi_rel_offset (q0, 80+2*16)
71         cfi_rel_offset (q1, 80+3*16)
73         stp     q4, q5, [sp, #(80+4*16)]
74         cfi_rel_offset (q0, 80+4*16)
75         cfi_rel_offset (q1, 80+5*16)
77         stp     q6, q7, [sp, #(80+6*16)]
78         cfi_rel_offset (q0, 80+6*16)
79         cfi_rel_offset (q1, 80+7*16)
81         /* Get pointer to linker struct.  */
82         ldr     x0, [ip0, #-8]
84         /* Prepare to call _dl_fixup().  */
85         ldr     x1, [sp, 80+8*16]       /* Recover &PLTGOT[n] */
87         sub     x1, x1, ip0
88         add     x1, x1, x1, lsl #1
89         lsl     x1, x1, #3
90         sub     x1, x1, #192
91         lsr     x1, x1, #3
93         /* Call fixup routine.  */
94         bl      _dl_fixup
96         /* Save the return.  */
97         mov     ip0, x0
99         /* Get arguments and return address back.  */
100         ldp     q0, q1, [sp, #(80+0*16)]
101         ldp     q2, q3, [sp, #(80+2*16)]
102         ldp     q4, q5, [sp, #(80+4*16)]
103         ldp     q6, q7, [sp, #(80+6*16)]
104         ldp     x0, x1, [sp, #64]
105         ldp     x2, x3, [sp, #48]
106         ldp     x4, x5, [sp, #32]
107         ldp     x6, x7, [sp, #16]
108         ldp     x8, x9, [sp], #(80+8*16)
109         cfi_adjust_cfa_offset (-(80+8*16))
111         ldp     ip1, lr, [sp], #16
112         cfi_adjust_cfa_offset (-16)
114         /* Jump to the newly found address.  */
115         br      ip0
117         cfi_endproc
118         .size _dl_runtime_resolve, .-_dl_runtime_resolve
119 #ifndef PROF
120         .globl _dl_runtime_profile
121         .type _dl_runtime_profile, #function
122         cfi_startproc
123         .align 2
124 _dl_runtime_profile:
125         /* AArch64 we get called with:
126            ip0          &PLTGOT[2]
127            ip1          temp(dl resolver entry point)
128            [sp, #8]     lr
129            [sp, #0]     &PLTGOT[n]
131            Stack frame layout:
132            [sp,   #...] lr
133            [sp,   #...] &PLTGOT[n]
134            [sp,    #96] La_aarch64_regs
135            [sp,    #48] La_aarch64_retval
136            [sp,    #40] frame size return from pltenter
137            [sp,    #32] dl_profile_call saved x1
138            [sp,    #24] dl_profile_call saved x0
139            [sp,    #16] t1
140            [sp,     #0] x29, lr   <- x29
141          */
143 # define OFFSET_T1              16
144 # define OFFSET_SAVED_CALL_X0   OFFSET_T1 + 8
145 # define OFFSET_FS              OFFSET_SAVED_CALL_X0 + 16
146 # define OFFSET_RV              OFFSET_FS + 8
147 # define OFFSET_RG              OFFSET_RV + DL_SIZEOF_RV
149 # define SF_SIZE                OFFSET_RG + DL_SIZEOF_RG
151 # define OFFSET_PLTGOTN         SF_SIZE
152 # define OFFSET_LR              OFFSET_PLTGOTN + 8
154         /* Save arguments.  */
155         sub     sp, sp, #SF_SIZE
156         cfi_adjust_cfa_offset (SF_SIZE)
157         stp     x29, x30, [SP, #0]
158         mov     x29, sp
159         cfi_def_cfa_register (x29)
160         cfi_rel_offset (x29, 0)
161         cfi_rel_offset (lr, 8)
163         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
164         cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
165         cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
166         stp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
167         cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
168         cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
169         stp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
170         cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
171         cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
172         stp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
173         cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
174         cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
176         stp     d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
177         cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0)
178         cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8)
179         stp     d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1]
180         cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0)
181         cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8)
182         stp     d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
183         cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0)
184         cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8)
185         stp     d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
186         cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0)
187         cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8)
189         add     x0, x29, #SF_SIZE + 16
190         ldr     x1, [x29, #OFFSET_LR]
191         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP]
193         /* Get pointer to linker struct.  */
194         ldr     x0, [ip0, #-8]
196         /* Prepare to call _dl_profile_fixup().  */
197         ldr     x1, [x29, OFFSET_PLTGOTN]       /* Recover &PLTGOT[n] */
199         sub     x1, x1, ip0
200         add     x1, x1, x1, lsl #1
201         lsl     x1, x1, #3
202         sub     x1, x1, #192
203         lsr     x1, x1, #3
205         stp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
207         /* Set up extra args for _dl_profile_fixup */
208         ldr     x2, [x29, #OFFSET_LR]           /* load saved LR */
209         add     x3, x29, #OFFSET_RG             /* address of La_aarch64_reg */
210         add     x4, x29, #OFFSET_FS             /* address of framesize */
211         bl      _dl_profile_fixup
213         ldr     ip0, [x29, #OFFSET_FS]          /* framesize == 0 */
214         cmp     ip0, #0
215         bge     1f
216         cfi_remember_state
218         /* Save the return.  */
219         mov     ip0, x0
221         /* Get arguments and return address back.  */
222         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
223         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
224         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
225         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
226         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
227         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
228         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
229         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
231         cfi_def_cfa_register (sp)
232         ldp     x29, x30, [x29, #0]
233         cfi_restore(x29)
234         cfi_restore(x30)
236         add     sp, sp, SF_SIZE + 16
237         cfi_adjust_cfa_offset (- SF_SIZE - 16)
239         /* Jump to the newly found address.  */
240         br      ip0
242         cfi_restore_state
244         /* The new frame size is in ip0.  */
246         sub     x1, x29, ip0
247         and     sp, x1, #0xfffffffffffffff0
249         str     x0, [x29, #OFFSET_T1]
251         mov     x0, sp
252         add     x1, x29, #SF_SIZE + 16
253         mov     x2, ip0
254         bl      memcpy
256         ldr     ip0, [x29, #OFFSET_T1]
258         /* Call the function.  */
259         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
260         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
261         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
262         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
263         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
264         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
265         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
266         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
267         blr     ip0
268         stp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
269         stp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
270         stp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
272         /* Setup call to pltexit  */
273         ldp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
274         add     x2, x29, #OFFSET_RG
275         add     x3, x29, #OFFSET_RV
276         bl      _dl_call_pltexit
278         ldp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
279         ldp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
280         ldp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
281         /* LR from within La_aarch64_reg */
282         ldr     lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
283         cfi_restore(lr)
284         mov     sp, x29
285         cfi_def_cfa_register (sp)
286         ldr     x29, [x29, #0]
287         cfi_restore(x29)
288         add     sp, sp, SF_SIZE + 16
289         cfi_adjust_cfa_offset (- SF_SIZE - 16)
291         br      lr
293         cfi_endproc
294         .size _dl_runtime_profile, .-_dl_runtime_profile
295 #endif
296         .previous