LoongArch: Fix soft-float bug about _dl_runtime_resolve{,lsx,lasx}
[glibc.git] / sysdeps / loongarch / dl-trampoline.S
blobf6ba5e443c9dceb10bf5eac891bec159aa7db852
1 /* PLT trampolines.
2    Copyright (C) 2022-2023 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
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    <https://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <sys/asm.h>
22 #if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float
23 #define USE_LASX
24 #define _dl_runtime_resolve _dl_runtime_resolve_lasx
25 #include "dl-trampoline.h"
26 #undef FRAME_SIZE
27 #undef USE_LASX
28 #undef _dl_runtime_resolve
30 #define USE_LSX
31 #define _dl_runtime_resolve _dl_runtime_resolve_lsx
32 #include "dl-trampoline.h"
33 #undef FRAME_SIZE
34 #undef USE_LSX
35 #undef _dl_runtime_resolve
36 #endif
38 #include "dl-trampoline.h"
40 #include "dl-link.h"
42 ENTRY (_dl_runtime_profile)
43        /* LoongArch we get called with:
44         t0            linkr_map pointer
45         t1            the scaled offset stored in t0, which can be used
46                       to calculate the offset of the current symbol in .rela.plt
47         t2            %hi(%pcrel(.got.plt)) stored in t2, no use in this function
48         t3            dl resolver entry point, no use in this function
50         Stack frame layout:
51         [sp,    #96] La_loongarch_regs
52         [sp,    #48] La_loongarch_retval
53         [sp,    #40] frame size return from pltenter
54         [sp,    #32] dl_profile_call saved a1
55         [sp,    #24] dl_profile_call saved a0
56         [sp,    #16] T1
57         [sp,     #0] ra, fp   <- fp
58        */
60 # define OFFSET_T1              16
61 # define OFFSET_SAVED_CALL_A0   OFFSET_T1 + 8
62 # define OFFSET_FS              OFFSET_SAVED_CALL_A0 + 16
63 # define OFFSET_RV              OFFSET_FS + 8
64 # define OFFSET_RG              OFFSET_RV + DL_SIZEOF_RV
66 # define SF_SIZE                (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK))
68         /* Save arguments to stack. */
69         ADDI    sp, sp, -SF_SIZE
70         REG_S   ra, sp, 0
71         REG_S   fp, sp, 8
73         or      fp, sp, zero
75         REG_S   a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
76         REG_S   a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
77         REG_S   a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
78         REG_S   a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
79         REG_S   a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
80         REG_S   a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
81         REG_S   a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
82         REG_S   a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
84 #ifndef __loongarch_soft_float
85         FREG_S  fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
86         FREG_S  fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
87         FREG_S  fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
88         FREG_S  fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
89         FREG_S  fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
90         FREG_S  fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
91         FREG_S  fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
92         FREG_S  fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
93 #endif
95         /* Update .got.plt and obtain runtime address of callee.  */
96         SLLI    a1, t1, 1
97         or      a0, t0, zero
98         ADD     a1, a1, t1
99         or      a2, ra, zero            /* return addr */
100         ADDI    a3, fp, OFFSET_RG       /* La_loongarch_regs pointer */
101         ADDI    a4, fp, OFFSET_FS       /* frame size return from pltenter */
103         REG_S   a0, fp, OFFSET_SAVED_CALL_A0
104         REG_S   a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
106         la      t2, _dl_profile_fixup
107         jirl    ra, t2, 0
109         REG_L   t3, fp, OFFSET_FS
110         bge     t3, zero, 1f
112         /* Save the return.  */
113         or      t4, v0, zero
115         /* Restore arguments from stack.  */
116         REG_L   a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
117         REG_L   a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
118         REG_L   a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
119         REG_L   a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
120         REG_L   a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
121         REG_L   a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
122         REG_L   a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
123         REG_L   a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
125 #ifndef __loongarch_soft_float
126         FREG_L  fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
127         FREG_L  fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
128         FREG_L  fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
129         FREG_L  fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
130         FREG_L  fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
131         FREG_L  fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
132         FREG_L  fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
133         FREG_L  fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
134 #endif
136         REG_L   ra, fp, 0
137         REG_L   fp, fp, SZREG
139         ADDI    sp, sp, SF_SIZE
140         jirl    zero, t4, 0
143         /* The new frame size is in t3.  */
144         SUB     sp, fp, t3
145         BSTRINS sp, zero, 3, 0
147         REG_S   a0, fp, OFFSET_T1
149         or      a0, sp, zero
150         ADDI    a1, fp, SF_SIZE
151         or      a2, t3, zero
152         la      t5, memcpy
153         jirl    ra, t5, 0
155         REG_L   t6, fp, OFFSET_T1
157         /* Call the function.  */
158         REG_L   a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
159         REG_L   a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
160         REG_L   a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
161         REG_L   a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
162         REG_L   a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
163         REG_L   a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
164         REG_L   a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
165         REG_L   a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
167 #ifndef __loongarch_soft_float
168         FREG_L  fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
169         FREG_L  fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
170         FREG_L  fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
171         FREG_L  fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
172         FREG_L  fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
173         FREG_L  fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
174         FREG_L  fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
175         FREG_L  fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
176 #endif
177         jirl    ra, t6, 0
179         REG_S   a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0
180         REG_S   a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG
182 #ifndef __loongarch_soft_float
183         FREG_S  fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0
184         FREG_S  fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 + SZFREG
185 #endif
187         /* Setup call to pltexit.  */
188         REG_L   a0, fp, OFFSET_SAVED_CALL_A0
189         REG_L   a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
190         ADDI    a2, fp, OFFSET_RG
191         ADDI    a3, fp, OFFSET_RV
192         la      t7, _dl_audit_pltexit
193         jirl    ra, t7, 0
195         REG_L   a0, fp, OFFSET_RV + DL_OFFSET_RV_A0
196         REG_L   a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG
198 #ifndef __loongarch_soft_float
199         FREG_L  fa0, fp, OFFSET_RV + DL_OFFSET_RV_FA0
200         FREG_L  fa1, fp, OFFSET_RV + DL_OFFSET_RV_FA0 + SZFREG
201 #endif
203         /* RA from within La_loongarch_reg.  */
204         REG_L   ra, fp, OFFSET_RG + DL_OFFSET_RG_RA
205         or      sp, fp, zero
206         ADDI    sp, sp, SF_SIZE
207         REG_S   fp, fp, SZREG
209         jirl    zero, ra, 0
211 END (_dl_runtime_profile)