eda/EDASQLite: Improved SQL Custom Functions support, now taking an arbitrary set...
[sdk] / deps / libffi-3.0.11 / src / arm / sysv.S
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
3             Copyright (c) 2011 Plausible Labs Cooperative, Inc.
4    
5    ARM Foreign Function Interface 
6
7    Permission is hereby granted, free of charge, to any person obtaining
8    a copy of this software and associated documentation files (the
9    ``Software''), to deal in the Software without restriction, including
10    without limitation the rights to use, copy, modify, merge, publish,
11    distribute, sublicense, and/or sell copies of the Software, and to
12    permit persons to whom the Software is furnished to do so, subject to
13    the following conditions:
14
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17
18    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25    DEALINGS IN THE SOFTWARE.
26    ----------------------------------------------------------------------- */
27
28 #define LIBFFI_ASM      
29 #include <fficonfig.h>
30 #include <ffi.h>
31 #ifdef HAVE_MACHINE_ASM_H
32 #include <machine/asm.h>
33 #else
34 #ifdef __USER_LABEL_PREFIX__
35 #define CONCAT1(a, b) CONCAT2(a, b)
36 #define CONCAT2(a, b) a ## b
37
38 /* Use the right prefix for global labels.  */
39 #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
40 #else
41 #define CNAME(x) x
42 #endif
43 #ifdef __APPLE__
44 #define ENTRY(x) .globl _##x; _##x:
45 #else
46 #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
47 #endif /* __APPLE__ */
48 #endif
49
50 #ifdef __ELF__
51 #define LSYM(x) .x
52 #else
53 #define LSYM(x) x
54 #endif
55
56 /* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
57   Function Call Guide */
58 #ifdef __APPLE__
59 #define __SOFTFP__
60 #endif
61
62 /* We need a better way of testing for this, but for now, this is all 
63    we can do.  */
64 @ This selects the minimum architecture level required.
65 #define __ARM_ARCH__ 3
66
67 #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
68 # undef __ARM_ARCH__
69 # define __ARM_ARCH__ 4
70 #endif
71         
72 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
73         || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
74         || defined(__ARM_ARCH_5TEJ__)
75 # undef __ARM_ARCH__
76 # define __ARM_ARCH__ 5
77 #endif
78
79 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
80         || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
81         || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
82         || defined(__ARM_ARCH_6M__)
83 # undef __ARM_ARCH__
84 # define __ARM_ARCH__ 6
85 #endif
86
87 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
88         || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
89         || defined(__ARM_ARCH_7EM__)
90 # undef __ARM_ARCH__
91 # define __ARM_ARCH__ 7
92 #endif
93
94 #if __ARM_ARCH__ >= 5
95 # define call_reg(x)    blx     x
96 #elif defined (__ARM_ARCH_4T__)
97 # define call_reg(x)    mov     lr, pc ; bx     x
98 # if defined(__thumb__) || defined(__THUMB_INTERWORK__)
99 #  define __INTERWORKING__
100 # endif
101 #else
102 # define call_reg(x)    mov     lr, pc ; mov    pc, x
103 #endif
104
105 /* Conditionally compile unwinder directives.  */
106 #ifdef __ARM_EABI__
107 #define UNWIND
108 #else
109 #define UNWIND @
110 #endif  
111
112         
113 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
114 .macro  ARM_FUNC_START name
115         .text
116         .align 0
117         .thumb
118         .thumb_func
119 #ifdef __APPLE__
120         ENTRY($0)
121 #else
122         ENTRY(\name)
123 #endif
124         bx      pc
125         nop
126         .arm
127         UNWIND .fnstart
128 /* A hook to tell gdb that we've switched to ARM mode.  Also used to call
129    directly from other local arm routines.  */
130 #ifdef __APPLE__
131 _L__$0:
132 #else
133 _L__\name:
134 #endif
135 .endm
136 #else
137 .macro  ARM_FUNC_START name
138         .text
139         .align 0
140         .arm
141 #ifdef __APPLE__
142         ENTRY($0)
143 #else
144         ENTRY(\name)
145 #endif
146         UNWIND .fnstart
147 .endm
148 #endif
149
150 .macro  RETLDM  regs=, cond=, dirn=ia
151 #if defined (__INTERWORKING__)
152         .ifc "\regs",""
153         ldr\cond        lr, [sp], #4
154         .else
155         ldm\cond\dirn   sp!, {\regs, lr}
156         .endif
157         bx\cond lr
158 #else
159         .ifc "\regs",""
160         ldr\cond        pc, [sp], #4
161         .else
162         ldm\cond\dirn   sp!, {\regs, pc}
163         .endif
164 #endif
165 .endm
166
167         @ r0:   ffi_prep_args
168         @ r1:   &ecif
169         @ r2:   cif->bytes
170         @ r3:   fig->flags
171         @ sp+0: ecif.rvalue
172
173         @ This assumes we are using gas.
174 ARM_FUNC_START ffi_call_SYSV
175         @ Save registers
176         stmfd   sp!, {r0-r3, fp, lr}
177         UNWIND .save    {r0-r3, fp, lr}
178         mov     fp, sp
179
180         UNWIND .setfp   fp, sp
181
182         @ Make room for all of the new args.
183         sub     sp, fp, r2
184
185         @ Place all of the ffi_prep_args in position
186         mov     r0, sp
187         @     r1 already set
188
189         @ Call ffi_prep_args(stack, &ecif)
190         bl      CNAME(ffi_prep_args)
191
192         @ move first 4 parameters in registers
193         ldmia   sp, {r0-r3}
194
195         @ and adjust stack
196         sub     lr, fp, sp      @ cif->bytes == fp - sp
197         ldr     ip, [fp]        @ load fn() in advance
198         cmp     lr, #16
199         movhs   lr, #16
200         add     sp, sp, lr
201
202         @ call (fn) (...)
203         call_reg(ip)
204         
205         @ Remove the space we pushed for the args
206         mov     sp, fp
207
208         @ Load r2 with the pointer to storage for the return value
209         ldr     r2, [sp, #24]
210
211         @ Load r3 with the return type code 
212         ldr     r3, [sp, #12]
213
214         @ If the return value pointer is NULL, assume no return value.
215         cmp     r2, #0
216         beq     LSYM(Lepilogue)
217
218 @ return INT
219         cmp     r3, #FFI_TYPE_INT
220 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
221         cmpne   r3, #FFI_TYPE_FLOAT
222 #endif
223         streq   r0, [r2]
224         beq     LSYM(Lepilogue)
225
226         @ return INT64
227         cmp     r3, #FFI_TYPE_SINT64
228 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
229         cmpne   r3, #FFI_TYPE_DOUBLE
230 #endif
231         stmeqia r2, {r0, r1}
232
233 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
234         beq     LSYM(Lepilogue)
235
236 @ return FLOAT
237         cmp     r3, #FFI_TYPE_FLOAT
238         stfeqs  f0, [r2]
239         beq     LSYM(Lepilogue)
240
241 @ return DOUBLE or LONGDOUBLE
242         cmp     r3, #FFI_TYPE_DOUBLE
243         stfeqd  f0, [r2]
244 #endif
245
246 LSYM(Lepilogue):
247 #if defined (__INTERWORKING__)
248         ldmia   sp!, {r0-r3,fp, lr}
249         bx      lr
250 #else
251         ldmia   sp!, {r0-r3,fp, pc}
252 #endif
253
254 .ffi_call_SYSV_end:
255         UNWIND .fnend
256 #ifdef __ELF__
257         .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
258 #endif
259
260
261 /*
262         unsigned int FFI_HIDDEN
263         ffi_closure_SYSV_inner (closure, respp, args)
264              ffi_closure *closure;
265              void **respp;
266              void *args;
267 */
268
269 ARM_FUNC_START ffi_closure_SYSV
270         UNWIND .pad #16
271         add     ip, sp, #16
272         stmfd   sp!, {ip, lr}
273         UNWIND .save    {r0, lr}
274         add     r2, sp, #8
275         UNWIND .pad #16
276         sub     sp, sp, #16
277         str     sp, [sp, #8]
278         add     r1, sp, #8
279         bl      CNAME(ffi_closure_SYSV_inner)
280         cmp     r0, #FFI_TYPE_INT
281         beq     .Lretint
282
283         cmp     r0, #FFI_TYPE_FLOAT
284 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
285         beq     .Lretint
286 #else
287         beq     .Lretfloat
288 #endif
289
290         cmp     r0, #FFI_TYPE_DOUBLE
291 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
292         beq     .Lretlonglong
293 #else
294         beq     .Lretdouble
295 #endif
296
297         cmp     r0, #FFI_TYPE_LONGDOUBLE
298 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
299         beq     .Lretlonglong
300 #else
301         beq     .Lretlongdouble
302 #endif
303
304         cmp     r0, #FFI_TYPE_SINT64
305         beq     .Lretlonglong
306 .Lclosure_epilogue:
307         add     sp, sp, #16
308         ldmfd   sp, {sp, pc}
309 .Lretint:
310         ldr     r0, [sp]
311         b       .Lclosure_epilogue
312 .Lretlonglong:
313         ldr     r0, [sp]
314         ldr     r1, [sp, #4]
315         b       .Lclosure_epilogue
316
317 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
318 .Lretfloat:
319         ldfs    f0, [sp]
320         b       .Lclosure_epilogue
321 .Lretdouble:
322         ldfd    f0, [sp]
323         b       .Lclosure_epilogue
324 .Lretlongdouble:
325         ldfd    f0, [sp]
326         b       .Lclosure_epilogue
327 #endif
328
329 .ffi_closure_SYSV_end:
330         UNWIND .fnend
331 #ifdef __ELF__
332         .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
333 #endif
334
335
336 /* Below are VFP hard-float ABI call and closure implementations.
337    Add VFP FPU directive here. This is only compiled into the library
338    under EABI.  */
339 #ifdef __ARM_EABI__
340         .fpu    vfp
341
342         @ r0:   fn
343         @ r1:   &ecif
344         @ r2:   cif->bytes
345         @ r3:   fig->flags
346         @ sp+0: ecif.rvalue
347
348 ARM_FUNC_START ffi_call_VFP
349         @ Save registers
350         stmfd   sp!, {r0-r3, fp, lr}
351         UNWIND .save    {r0-r3, fp, lr}
352         mov     fp, sp
353         UNWIND .setfp   fp, sp
354
355         @ Make room for all of the new args.
356         sub     sp, sp, r2
357
358         @ Make room for loading VFP args
359         sub     sp, sp, #64
360
361         @ Place all of the ffi_prep_args in position
362         mov     r0, sp
363         @     r1 already set
364         sub     r2, fp, #64   @ VFP scratch space
365
366         @ Call ffi_prep_args(stack, &ecif, vfp_space)
367         bl      CNAME(ffi_prep_args)
368
369         @ Load VFP register args if needed
370         cmp     r0, #0
371         beq     LSYM(Lbase_args)
372
373         @ Load only d0 if possible
374         cmp     r0, #3
375         sub     ip, fp, #64
376         flddle  d0, [ip]
377         fldmiadgt       ip, {d0-d7}
378
379 LSYM(Lbase_args):
380         @ move first 4 parameters in registers
381         ldmia   sp, {r0-r3}
382
383         @ and adjust stack
384         sub     lr, ip, sp      @ cif->bytes == (fp - 64) - sp
385         ldr     ip, [fp]        @ load fn() in advance
386         cmp     lr, #16
387         movhs   lr, #16
388         add     sp, sp, lr
389
390         @ call (fn) (...)
391         call_reg(ip)
392
393         @ Remove the space we pushed for the args
394         mov     sp, fp
395
396         @ Load r2 with the pointer to storage for
397         @ the return value
398         ldr     r2, [sp, #24]
399
400         @ Load r3 with the return type code 
401         ldr     r3, [sp, #12]
402
403         @ If the return value pointer is NULL,
404         @ assume no return value.
405         cmp     r2, #0
406         beq     LSYM(Lepilogue_vfp)
407
408         cmp     r3, #FFI_TYPE_INT
409         streq   r0, [r2]
410         beq     LSYM(Lepilogue_vfp)
411
412         cmp     r3, #FFI_TYPE_SINT64
413         stmeqia r2, {r0, r1}
414         beq     LSYM(Lepilogue_vfp)
415
416         cmp     r3, #FFI_TYPE_FLOAT
417         fstseq  s0, [r2]
418         beq     LSYM(Lepilogue_vfp)
419         
420         cmp     r3, #FFI_TYPE_DOUBLE
421         fstdeq  d0, [r2]
422         beq     LSYM(Lepilogue_vfp)
423
424         cmp     r3, #FFI_TYPE_STRUCT_VFP_FLOAT
425         cmpne   r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
426         fstmiadeq       r2, {d0-d3}
427
428 LSYM(Lepilogue_vfp):
429         RETLDM  "r0-r3,fp"
430
431 .ffi_call_VFP_end:
432         UNWIND .fnend
433         .size    CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
434
435
436 ARM_FUNC_START ffi_closure_VFP
437         fstmfdd sp!, {d0-d7}
438         @ r0-r3, then d0-d7
439         UNWIND .pad #80
440         add     ip, sp, #80
441         stmfd   sp!, {ip, lr}
442         UNWIND .save    {r0, lr}
443         add     r2, sp, #72
444         add     r3, sp, #8
445         UNWIND .pad #72
446         sub     sp, sp, #72
447         str     sp, [sp, #64]
448         add     r1, sp, #64
449         bl      CNAME(ffi_closure_SYSV_inner)
450
451         cmp     r0, #FFI_TYPE_INT
452         beq     .Lretint_vfp
453
454         cmp     r0, #FFI_TYPE_FLOAT
455         beq     .Lretfloat_vfp
456
457         cmp     r0, #FFI_TYPE_DOUBLE
458         cmpne   r0, #FFI_TYPE_LONGDOUBLE
459         beq     .Lretdouble_vfp
460
461         cmp     r0, #FFI_TYPE_SINT64
462         beq     .Lretlonglong_vfp
463
464         cmp     r0, #FFI_TYPE_STRUCT_VFP_FLOAT
465         beq     .Lretfloat_struct_vfp
466
467         cmp     r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
468         beq     .Lretdouble_struct_vfp
469         
470 .Lclosure_epilogue_vfp:
471         add     sp, sp, #72
472         ldmfd   sp, {sp, pc}
473
474 .Lretfloat_vfp:
475         flds    s0, [sp]
476         b       .Lclosure_epilogue_vfp
477 .Lretdouble_vfp:
478         fldd    d0, [sp]
479         b       .Lclosure_epilogue_vfp
480 .Lretint_vfp:
481         ldr     r0, [sp]
482         b       .Lclosure_epilogue_vfp
483 .Lretlonglong_vfp:
484         ldmia   sp, {r0, r1}
485         b       .Lclosure_epilogue_vfp
486 .Lretfloat_struct_vfp:
487         fldmiad sp, {d0-d1}
488         b       .Lclosure_epilogue_vfp
489 .Lretdouble_struct_vfp:
490         fldmiad sp, {d0-d3}
491         b       .Lclosure_epilogue_vfp
492
493 .ffi_closure_VFP_end:
494         UNWIND .fnend
495         .size    CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
496 #endif
497
498 ENTRY(ffi_arm_trampoline)
499         stmfd sp!, {r0-r3}
500         ldr r0, [pc]
501         ldr pc, [pc]
502
503 #if defined __ELF__ && defined __linux__
504         .section        .note.GNU-stack,"",%progbits
505 #endif