annotate libffi/src/arm/sysv.S @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* -----------------------------------------------------------------------
kono
parents:
diff changeset
2 sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
kono
parents:
diff changeset
3 Copyright (c) 2011 Plausible Labs Cooperative, Inc.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 ARM Foreign Function Interface
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 Permission is hereby granted, free of charge, to any person obtaining
kono
parents:
diff changeset
8 a copy of this software and associated documentation files (the
kono
parents:
diff changeset
9 ``Software''), to deal in the Software without restriction, including
kono
parents:
diff changeset
10 without limitation the rights to use, copy, modify, merge, publish,
kono
parents:
diff changeset
11 distribute, sublicense, and/or sell copies of the Software, and to
kono
parents:
diff changeset
12 permit persons to whom the Software is furnished to do so, subject to
kono
parents:
diff changeset
13 the following conditions:
kono
parents:
diff changeset
14
kono
parents:
diff changeset
15 The above copyright notice and this permission notice shall be included
kono
parents:
diff changeset
16 in all copies or substantial portions of the Software.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
kono
parents:
diff changeset
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
kono
parents:
diff changeset
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
kono
parents:
diff changeset
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
kono
parents:
diff changeset
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
kono
parents:
diff changeset
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kono
parents:
diff changeset
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
kono
parents:
diff changeset
25 DEALINGS IN THE SOFTWARE.
kono
parents:
diff changeset
26 ----------------------------------------------------------------------- */
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #define LIBFFI_ASM
kono
parents:
diff changeset
29 #include <fficonfig.h>
kono
parents:
diff changeset
30 #include <ffi.h>
kono
parents:
diff changeset
31 #include <ffi_cfi.h>
kono
parents:
diff changeset
32 #include "internal.h"
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 /* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
kono
parents:
diff changeset
35 #ifndef __ARM_ARCH
kono
parents:
diff changeset
36 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
kono
parents:
diff changeset
37 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
kono
parents:
diff changeset
38 || defined(__ARM_ARCH_7EM__)
kono
parents:
diff changeset
39 # define __ARM_ARCH 7
kono
parents:
diff changeset
40 # elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
kono
parents:
diff changeset
41 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
kono
parents:
diff changeset
42 || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
kono
parents:
diff changeset
43 || defined(__ARM_ARCH_6M__)
kono
parents:
diff changeset
44 # define __ARM_ARCH 6
kono
parents:
diff changeset
45 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
kono
parents:
diff changeset
46 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
kono
parents:
diff changeset
47 || defined(__ARM_ARCH_5TEJ__)
kono
parents:
diff changeset
48 # define __ARM_ARCH 5
kono
parents:
diff changeset
49 # else
kono
parents:
diff changeset
50 # define __ARM_ARCH 4
kono
parents:
diff changeset
51 # endif
kono
parents:
diff changeset
52 #endif
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 /* Conditionally compile unwinder directives. */
kono
parents:
diff changeset
55 .macro UNWIND text:vararg
kono
parents:
diff changeset
56 #ifdef __ARM_EABI__
kono
parents:
diff changeset
57 \text
kono
parents:
diff changeset
58 #endif
kono
parents:
diff changeset
59 .endm
kono
parents:
diff changeset
60 #if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
kono
parents:
diff changeset
61 .cfi_sections .debug_frame
kono
parents:
diff changeset
62 #endif
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 #define CONCAT(a, b) CONCAT2(a, b)
kono
parents:
diff changeset
65 #define CONCAT2(a, b) a ## b
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 #ifdef __USER_LABEL_PREFIX__
kono
parents:
diff changeset
68 # define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
kono
parents:
diff changeset
69 #else
kono
parents:
diff changeset
70 # define CNAME(X) X
kono
parents:
diff changeset
71 #endif
kono
parents:
diff changeset
72 #ifdef __ELF__
kono
parents:
diff changeset
73 # define SIZE(X) .size CNAME(X), . - CNAME(X)
kono
parents:
diff changeset
74 # define TYPE(X, Y) .type CNAME(X), Y
kono
parents:
diff changeset
75 #else
kono
parents:
diff changeset
76 # define SIZE(X)
kono
parents:
diff changeset
77 # define TYPE(X, Y)
kono
parents:
diff changeset
78 #endif
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 #define ARM_FUNC_START(name, gl) \
kono
parents:
diff changeset
81 .align 3; \
kono
parents:
diff changeset
82 .ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
kono
parents:
diff changeset
83 TYPE(name, %function); \
kono
parents:
diff changeset
84 CNAME(name):
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 #define ARM_FUNC_END(name) \
kono
parents:
diff changeset
87 SIZE(name)
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 /* Aid in defining a jump table with 8 bytes between entries. */
kono
parents:
diff changeset
90 .macro E index
kono
parents:
diff changeset
91 .if . - 0b - 8*\index
kono
parents:
diff changeset
92 .error "type table out of sync"
kono
parents:
diff changeset
93 .endif
kono
parents:
diff changeset
94 .endm
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 .text
kono
parents:
diff changeset
97 .syntax unified
kono
parents:
diff changeset
98 .arm
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 /* We require interworking on LDM, which implies ARMv5T,
kono
parents:
diff changeset
101 which implies the existance of BLX. */
kono
parents:
diff changeset
102 .arch armv5t
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 /* Note that we use STC and LDC to encode VFP instructions,
kono
parents:
diff changeset
105 so that we do not need ".fpu vfp", nor get that added to
kono
parents:
diff changeset
106 the object file attributes. These will not be executed
kono
parents:
diff changeset
107 unless the FFI_VFP abi is used. */
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 @ r0: stack
kono
parents:
diff changeset
110 @ r1: frame
kono
parents:
diff changeset
111 @ r2: fn
kono
parents:
diff changeset
112 @ r3: vfp_used
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 ARM_FUNC_START(ffi_call_VFP, 1)
kono
parents:
diff changeset
115 UNWIND .fnstart
kono
parents:
diff changeset
116 cfi_startproc
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 cmp r3, #3 @ load only d0 if possible
kono
parents:
diff changeset
119 ldcle p11, cr0, [r0] @ vldrle d0, [sp]
kono
parents:
diff changeset
120 ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
kono
parents:
diff changeset
121 add r0, r0, #64 @ discard the vfp register args
kono
parents:
diff changeset
122 /* FALLTHRU */
kono
parents:
diff changeset
123 ARM_FUNC_END(ffi_call_VFP)
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 ARM_FUNC_START(ffi_call_SYSV, 1)
kono
parents:
diff changeset
126 stm r1, {fp, lr}
kono
parents:
diff changeset
127 mov fp, r1
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 @ This is a bit of a lie wrt the origin of the unwind info, but
kono
parents:
diff changeset
130 @ now we've got the usual frame pointer and two saved registers.
kono
parents:
diff changeset
131 UNWIND .save {fp,lr}
kono
parents:
diff changeset
132 UNWIND .setfp fp, sp
kono
parents:
diff changeset
133 cfi_def_cfa(fp, 8)
kono
parents:
diff changeset
134 cfi_rel_offset(fp, 0)
kono
parents:
diff changeset
135 cfi_rel_offset(lr, 4)
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 mov sp, r0 @ install the stack pointer
kono
parents:
diff changeset
138 mov lr, r2 @ move the fn pointer out of the way
kono
parents:
diff changeset
139 ldr ip, [fp, #16] @ install the static chain
kono
parents:
diff changeset
140 ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
kono
parents:
diff changeset
141 blx lr @ call fn
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 @ Load r2 with the pointer to storage for the return value
kono
parents:
diff changeset
144 @ Load r3 with the return type code
kono
parents:
diff changeset
145 ldr r2, [fp, #8]
kono
parents:
diff changeset
146 ldr r3, [fp, #12]
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 @ Deallocate the stack with the arguments.
kono
parents:
diff changeset
149 mov sp, fp
kono
parents:
diff changeset
150 cfi_def_cfa_register(sp)
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 @ Store values stored in registers.
kono
parents:
diff changeset
153 .align 3
kono
parents:
diff changeset
154 add pc, pc, r3, lsl #3
kono
parents:
diff changeset
155 nop
kono
parents:
diff changeset
156 0:
kono
parents:
diff changeset
157 E ARM_TYPE_VFP_S
kono
parents:
diff changeset
158 stc p10, cr0, [r2] @ vstr s0, [r2]
kono
parents:
diff changeset
159 pop {fp,pc}
kono
parents:
diff changeset
160 E ARM_TYPE_VFP_D
kono
parents:
diff changeset
161 stc p11, cr0, [r2] @ vstr d0, [r2]
kono
parents:
diff changeset
162 pop {fp,pc}
kono
parents:
diff changeset
163 E ARM_TYPE_VFP_N
kono
parents:
diff changeset
164 stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
kono
parents:
diff changeset
165 pop {fp,pc}
kono
parents:
diff changeset
166 E ARM_TYPE_INT64
kono
parents:
diff changeset
167 str r1, [r2, #4]
kono
parents:
diff changeset
168 nop
kono
parents:
diff changeset
169 E ARM_TYPE_INT
kono
parents:
diff changeset
170 str r0, [r2]
kono
parents:
diff changeset
171 pop {fp,pc}
kono
parents:
diff changeset
172 E ARM_TYPE_VOID
kono
parents:
diff changeset
173 pop {fp,pc}
kono
parents:
diff changeset
174 nop
kono
parents:
diff changeset
175 E ARM_TYPE_STRUCT
kono
parents:
diff changeset
176 pop {fp,pc}
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 cfi_endproc
kono
parents:
diff changeset
179 UNWIND .fnend
kono
parents:
diff changeset
180 ARM_FUNC_END(ffi_call_SYSV)
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /*
kono
parents:
diff changeset
184 int ffi_closure_inner_* (cif, fun, user_data, frame)
kono
parents:
diff changeset
185 */
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 ARM_FUNC_START(ffi_go_closure_SYSV, 1)
kono
parents:
diff changeset
188 cfi_startproc
kono
parents:
diff changeset
189 stmdb sp!, {r0-r3} @ save argument regs
kono
parents:
diff changeset
190 cfi_adjust_cfa_offset(16)
kono
parents:
diff changeset
191 ldr r0, [ip, #4] @ load cif
kono
parents:
diff changeset
192 ldr r1, [ip, #8] @ load fun
kono
parents:
diff changeset
193 mov r2, ip @ load user_data
kono
parents:
diff changeset
194 b 0f
kono
parents:
diff changeset
195 cfi_endproc
kono
parents:
diff changeset
196 ARM_FUNC_END(ffi_go_closure_SYSV)
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 ARM_FUNC_START(ffi_closure_SYSV, 1)
kono
parents:
diff changeset
199 UNWIND .fnstart
kono
parents:
diff changeset
200 cfi_startproc
kono
parents:
diff changeset
201 stmdb sp!, {r0-r3} @ save argument regs
kono
parents:
diff changeset
202 cfi_adjust_cfa_offset(16)
kono
parents:
diff changeset
203 ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
kono
parents:
diff changeset
204 ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
kono
parents:
diff changeset
205 ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
kono
parents:
diff changeset
206 0:
kono
parents:
diff changeset
207 add ip, sp, #16 @ compute entry sp
kono
parents:
diff changeset
208 sub sp, sp, #64+32 @ allocate frame
kono
parents:
diff changeset
209 cfi_adjust_cfa_offset(64+32)
kono
parents:
diff changeset
210 stmdb sp!, {ip,lr}
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 /* Remember that EABI unwind info only applies at call sites.
kono
parents:
diff changeset
213 We need do nothing except note the save of the stack pointer
kono
parents:
diff changeset
214 and the link registers. */
kono
parents:
diff changeset
215 UNWIND .save {sp,lr}
kono
parents:
diff changeset
216 cfi_adjust_cfa_offset(8)
kono
parents:
diff changeset
217 cfi_rel_offset(lr, 4)
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 add r3, sp, #8 @ load frame
kono
parents:
diff changeset
220 bl CNAME(ffi_closure_inner_SYSV)
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 @ Load values returned in registers.
kono
parents:
diff changeset
223 add r2, sp, #8+64 @ load result
kono
parents:
diff changeset
224 adr r3, CNAME(ffi_closure_ret)
kono
parents:
diff changeset
225 add pc, r3, r0, lsl #3
kono
parents:
diff changeset
226 cfi_endproc
kono
parents:
diff changeset
227 UNWIND .fnend
kono
parents:
diff changeset
228 ARM_FUNC_END(ffi_closure_SYSV)
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 ARM_FUNC_START(ffi_go_closure_VFP, 1)
kono
parents:
diff changeset
231 cfi_startproc
kono
parents:
diff changeset
232 stmdb sp!, {r0-r3} @ save argument regs
kono
parents:
diff changeset
233 cfi_adjust_cfa_offset(16)
kono
parents:
diff changeset
234 ldr r0, [ip, #4] @ load cif
kono
parents:
diff changeset
235 ldr r1, [ip, #8] @ load fun
kono
parents:
diff changeset
236 mov r2, ip @ load user_data
kono
parents:
diff changeset
237 b 0f
kono
parents:
diff changeset
238 cfi_endproc
kono
parents:
diff changeset
239 ARM_FUNC_END(ffi_go_closure_VFP)
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 ARM_FUNC_START(ffi_closure_VFP, 1)
kono
parents:
diff changeset
242 UNWIND .fnstart
kono
parents:
diff changeset
243 cfi_startproc
kono
parents:
diff changeset
244 stmdb sp!, {r0-r3} @ save argument regs
kono
parents:
diff changeset
245 cfi_adjust_cfa_offset(16)
kono
parents:
diff changeset
246 ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
kono
parents:
diff changeset
247 ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
kono
parents:
diff changeset
248 ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
kono
parents:
diff changeset
249 0:
kono
parents:
diff changeset
250 add ip, sp, #16
kono
parents:
diff changeset
251 sub sp, sp, #64+32 @ allocate frame
kono
parents:
diff changeset
252 cfi_adjust_cfa_offset(64+32)
kono
parents:
diff changeset
253 stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
kono
parents:
diff changeset
254 stmdb sp!, {ip,lr}
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 /* See above. */
kono
parents:
diff changeset
257 UNWIND .save {sp,lr}
kono
parents:
diff changeset
258 cfi_adjust_cfa_offset(8)
kono
parents:
diff changeset
259 cfi_rel_offset(lr, 4)
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 add r3, sp, #8 @ load frame
kono
parents:
diff changeset
262 bl CNAME(ffi_closure_inner_VFP)
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 @ Load values returned in registers.
kono
parents:
diff changeset
265 add r2, sp, #8+64 @ load result
kono
parents:
diff changeset
266 adr r3, CNAME(ffi_closure_ret)
kono
parents:
diff changeset
267 add pc, r3, r0, lsl #3
kono
parents:
diff changeset
268 cfi_endproc
kono
parents:
diff changeset
269 UNWIND .fnend
kono
parents:
diff changeset
270 ARM_FUNC_END(ffi_closure_VFP)
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 /* Load values returned in registers for both closure entry points.
kono
parents:
diff changeset
273 Note that we use LDM with SP in the register set. This is deprecated
kono
parents:
diff changeset
274 by ARM, but not yet unpredictable. */
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 ARM_FUNC_START(ffi_closure_ret, 0)
kono
parents:
diff changeset
277 cfi_startproc
kono
parents:
diff changeset
278 cfi_rel_offset(sp, 0)
kono
parents:
diff changeset
279 cfi_rel_offset(lr, 4)
kono
parents:
diff changeset
280 0:
kono
parents:
diff changeset
281 E ARM_TYPE_VFP_S
kono
parents:
diff changeset
282 ldc p10, cr0, [r2] @ vldr s0, [r2]
kono
parents:
diff changeset
283 ldm sp, {sp,pc}
kono
parents:
diff changeset
284 E ARM_TYPE_VFP_D
kono
parents:
diff changeset
285 ldc p11, cr0, [r2] @ vldr d0, [r2]
kono
parents:
diff changeset
286 ldm sp, {sp,pc}
kono
parents:
diff changeset
287 E ARM_TYPE_VFP_N
kono
parents:
diff changeset
288 ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
kono
parents:
diff changeset
289 ldm sp, {sp,pc}
kono
parents:
diff changeset
290 E ARM_TYPE_INT64
kono
parents:
diff changeset
291 ldr r1, [r2, #4]
kono
parents:
diff changeset
292 nop
kono
parents:
diff changeset
293 E ARM_TYPE_INT
kono
parents:
diff changeset
294 ldr r0, [r2]
kono
parents:
diff changeset
295 ldm sp, {sp,pc}
kono
parents:
diff changeset
296 E ARM_TYPE_VOID
kono
parents:
diff changeset
297 ldm sp, {sp,pc}
kono
parents:
diff changeset
298 nop
kono
parents:
diff changeset
299 E ARM_TYPE_STRUCT
kono
parents:
diff changeset
300 ldm sp, {sp,pc}
kono
parents:
diff changeset
301 cfi_endproc
kono
parents:
diff changeset
302 ARM_FUNC_END(ffi_closure_ret)
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 #if FFI_EXEC_TRAMPOLINE_TABLE
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 /* ??? The iOS support should be updated. The first insn used to
kono
parents:
diff changeset
307 be STMFD, but that's been moved into ffi_closure_SYSV. If the
kono
parents:
diff changeset
308 writable page is put after this one we can make use of the
kono
parents:
diff changeset
309 pc+8 feature of the architecture. We can also reduce the size
kono
parents:
diff changeset
310 of the thunk to 8 and pack more of these into the page.
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 In the meantime, simply replace the STMFD with a NOP so as to
kono
parents:
diff changeset
313 keep all the magic numbers the same within ffi.c. */
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 .align 12
kono
parents:
diff changeset
316 ARM_FUNC_START(ffi_closure_trampoline_table_page)
kono
parents:
diff changeset
317 .rept 4096 / 12
kono
parents:
diff changeset
318 nop
kono
parents:
diff changeset
319 ldr ip, [pc, #-4092]
kono
parents:
diff changeset
320 ldr pc, [pc, #-4092]
kono
parents:
diff changeset
321 .endr
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 #else
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 ARM_FUNC_START(ffi_arm_trampoline, 1)
kono
parents:
diff changeset
326 0: adr ip, 0b
kono
parents:
diff changeset
327 ldr pc, 1f
kono
parents:
diff changeset
328 1: .long 0
kono
parents:
diff changeset
329 ARM_FUNC_END(ffi_arm_trampoline)
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 #endif /* FFI_EXEC_TRAMPOLINE_TABLE */
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 #if defined __ELF__ && defined __linux__
kono
parents:
diff changeset
334 .section .note.GNU-stack,"",%progbits
kono
parents:
diff changeset
335 #endif