Move some fenv.h override macros to generic math_private.h.
[glibc.git] / sysdeps / aarch64 / dl-trampoline.S
bloba86d0722d4a0415b43b5fc6788ffd785bcf43a7d
1 /* Copyright (C) 2005-2018 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 ip0l PTR_REG (16)
26 #define ip1 x17
27 #define lr  x30
29 /* RELA relocatons are 3 pointers */
30 #define RELA_SIZE (PTR_SIZE * 3)
32         .text
33         .globl _dl_runtime_resolve
34         .type _dl_runtime_resolve, #function
35         cfi_startproc
36         .align 2
37 _dl_runtime_resolve:
38         /* AArch64 we get called with:
39            ip0          &PLTGOT[2]
40            ip1          temp(dl resolver entry point)
41            [sp, #8]     lr
42            [sp, #0]     &PLTGOT[n]
43          */
45         cfi_rel_offset (lr, 8)
47         /* Save arguments.  */
48         stp     x8, x9, [sp, #-(80+8*16)]!
49         cfi_adjust_cfa_offset (80+8*16)
50         cfi_rel_offset (x8, 0)
51         cfi_rel_offset (x9, 8)
53         stp     x6, x7, [sp,  #16]
54         cfi_rel_offset (x6, 16)
55         cfi_rel_offset (x7, 24)
57         stp     x4, x5, [sp,  #32]
58         cfi_rel_offset (x4, 32)
59         cfi_rel_offset (x5, 40)
61         stp     x2, x3, [sp,  #48]
62         cfi_rel_offset (x2, 48)
63         cfi_rel_offset (x3, 56)
65         stp     x0, x1, [sp,  #64]
66         cfi_rel_offset (x0, 64)
67         cfi_rel_offset (x1, 72)
69         stp     q0, q1, [sp, #(80+0*16)]
70         cfi_rel_offset (q0, 80+0*16)
71         cfi_rel_offset (q1, 80+1*16)
73         stp     q2, q3, [sp, #(80+2*16)]
74         cfi_rel_offset (q0, 80+2*16)
75         cfi_rel_offset (q1, 80+3*16)
77         stp     q4, q5, [sp, #(80+4*16)]
78         cfi_rel_offset (q0, 80+4*16)
79         cfi_rel_offset (q1, 80+5*16)
81         stp     q6, q7, [sp, #(80+6*16)]
82         cfi_rel_offset (q0, 80+6*16)
83         cfi_rel_offset (q1, 80+7*16)
85         /* Get pointer to linker struct.  */
86         ldr     PTR_REG (0), [ip0, #-PTR_SIZE]
88         /* Prepare to call _dl_fixup().  */
89         ldr     x1, [sp, 80+8*16]       /* Recover &PLTGOT[n] */
91         sub     x1, x1, ip0
92         add     x1, x1, x1, lsl #1
93         lsl     x1, x1, #3
94         sub     x1, x1, #(RELA_SIZE<<3)
95         lsr     x1, x1, #3
97         /* Call fixup routine.  */
98         bl      _dl_fixup
100         /* Save the return.  */
101         mov     ip0, x0
103         /* Get arguments and return address back.  */
104         ldp     q0, q1, [sp, #(80+0*16)]
105         ldp     q2, q3, [sp, #(80+2*16)]
106         ldp     q4, q5, [sp, #(80+4*16)]
107         ldp     q6, q7, [sp, #(80+6*16)]
108         ldp     x0, x1, [sp, #64]
109         ldp     x2, x3, [sp, #48]
110         ldp     x4, x5, [sp, #32]
111         ldp     x6, x7, [sp, #16]
112         ldp     x8, x9, [sp], #(80+8*16)
113         cfi_adjust_cfa_offset (-(80+8*16))
115         ldp     ip1, lr, [sp], #16
116         cfi_adjust_cfa_offset (-16)
118         /* Jump to the newly found address.  */
119         br      ip0
121         cfi_endproc
122         .size _dl_runtime_resolve, .-_dl_runtime_resolve
123 #ifndef PROF
124         .globl _dl_runtime_profile
125         .type _dl_runtime_profile, #function
126         cfi_startproc
127         .align 2
128 _dl_runtime_profile:
129         /* AArch64 we get called with:
130            ip0          &PLTGOT[2]
131            ip1          temp(dl resolver entry point)
132            [sp, #8]     lr
133            [sp, #0]     &PLTGOT[n]
135            Stack frame layout:
136            [sp,   #...] lr
137            [sp,   #...] &PLTGOT[n]
138            [sp,    #96] La_aarch64_regs
139            [sp,    #48] La_aarch64_retval
140            [sp,    #40] frame size return from pltenter
141            [sp,    #32] dl_profile_call saved x1
142            [sp,    #24] dl_profile_call saved x0
143            [sp,    #16] t1
144            [sp,     #0] x29, lr   <- x29
145          */
147 # define OFFSET_T1              16
148 # define OFFSET_SAVED_CALL_X0   OFFSET_T1 + 8
149 # define OFFSET_FS              OFFSET_SAVED_CALL_X0 + 16
150 # define OFFSET_RV              OFFSET_FS + 8
151 # define OFFSET_RG              OFFSET_RV + DL_SIZEOF_RV
153 # define SF_SIZE                OFFSET_RG + DL_SIZEOF_RG
155 # define OFFSET_PLTGOTN         SF_SIZE
156 # define OFFSET_LR              OFFSET_PLTGOTN + 8
158         /* Save arguments.  */
159         sub     sp, sp, #SF_SIZE
160         cfi_adjust_cfa_offset (SF_SIZE)
161         stp     x29, x30, [SP, #0]
162         mov     x29, sp
163         cfi_def_cfa_register (x29)
164         cfi_rel_offset (x29, 0)
165         cfi_rel_offset (lr, 8)
167         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
168         cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
169         cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
170         stp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
171         cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
172         cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
173         stp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
174         cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
175         cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
176         stp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
177         cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
178         cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
180         stp     d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
181         cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0)
182         cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8)
183         stp     d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1]
184         cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0)
185         cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8)
186         stp     d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
187         cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0)
188         cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8)
189         stp     d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
190         cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0)
191         cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8)
193         add     x0, x29, #SF_SIZE + 16
194         ldr     x1, [x29, #OFFSET_LR]
195         stp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP]
197         /* Get pointer to linker struct.  */
198         ldr     PTR_REG (0), [ip0, #-PTR_SIZE]
200         /* Prepare to call _dl_profile_fixup().  */
201         ldr     x1, [x29, OFFSET_PLTGOTN]       /* Recover &PLTGOT[n] */
203         sub     x1, x1, ip0
204         add     x1, x1, x1, lsl #1
205         lsl     x1, x1, #3
206         sub     x1, x1, #(RELA_SIZE<<3)
207         lsr     x1, x1, #3
209         stp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
211         /* Set up extra args for _dl_profile_fixup */
212         ldr     x2, [x29, #OFFSET_LR]           /* load saved LR */
213         add     x3, x29, #OFFSET_RG             /* address of La_aarch64_reg */
214         add     x4, x29, #OFFSET_FS             /* address of framesize */
215         bl      _dl_profile_fixup
217         ldr     ip0l, [x29, #OFFSET_FS]         /* framesize == 0 */
218         cmp     ip0l, #0
219         bge     1f
220         cfi_remember_state
222         /* Save the return.  */
223         mov     ip0, x0
225         /* Get arguments and return address back.  */
226         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
227         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
228         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
229         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
230         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
231         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
232         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
233         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
235         cfi_def_cfa_register (sp)
236         ldp     x29, x30, [x29, #0]
237         cfi_restore(x29)
238         cfi_restore(x30)
240         add     sp, sp, SF_SIZE + 16
241         cfi_adjust_cfa_offset (- SF_SIZE - 16)
243         /* Jump to the newly found address.  */
244         br      ip0
246         cfi_restore_state
248         /* The new frame size is in ip0.  */
250         sub     PTR_REG (1), PTR_REG (29), ip0l
251         and     sp, x1, #0xfffffffffffffff0
253         str     x0, [x29, #OFFSET_T1]
255         mov     x0, sp
256         add     x1, x29, #SF_SIZE + 16
257         mov     x2, ip0
258         bl      memcpy
260         ldr     ip0, [x29, #OFFSET_T1]
262         /* Call the function.  */
263         ldp     x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
264         ldp     x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
265         ldp     x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
266         ldp     x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
267         ldp     d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
268         ldp     d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
269         ldp     d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
270         ldp     d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
271         blr     ip0
272         stp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
273         stp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
274         stp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
276         /* Setup call to pltexit  */
277         ldp     x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
278         add     x2, x29, #OFFSET_RG
279         add     x3, x29, #OFFSET_RV
280         bl      _dl_call_pltexit
282         ldp     x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
283         ldp     d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
284         ldp     d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
285         /* LR from within La_aarch64_reg */
286         ldr     lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
287         cfi_restore(lr)
288         mov     sp, x29
289         cfi_def_cfa_register (sp)
290         ldr     x29, [x29, #0]
291         cfi_restore(x29)
292         add     sp, sp, SF_SIZE + 16
293         cfi_adjust_cfa_offset (- SF_SIZE - 16)
295         br      lr
297         cfi_endproc
298         .size _dl_runtime_profile, .-_dl_runtime_profile
299 #endif
300         .previous