209 lines
4.7 KiB
ArmAsm
209 lines
4.7 KiB
ArmAsm
/* -----------------------------------------------------------------------
|
|
sysv.S - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
|
|
|
|
AVR32 Foreign Function Interface
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
``Software''), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
--------------------------------------------------------------------- */
|
|
|
|
#define LIBFFI_ASM
|
|
#include <fficonfig.h>
|
|
#include <ffi.h>
|
|
|
|
/* r12: ffi_prep_args
|
|
* r11: &ecif
|
|
* r10: size
|
|
* r9: cif->flags
|
|
* r8: ecif.rvalue
|
|
* sp+0: cif->rstruct_flag
|
|
* sp+4: fn */
|
|
|
|
.text
|
|
.align 1
|
|
.globl ffi_call_SYSV
|
|
.type ffi_call_SYSV, @function
|
|
ffi_call_SYSV:
|
|
stm --sp, r0,r1,lr
|
|
stm --sp, r8-r12
|
|
mov r0, sp
|
|
|
|
/* Make room for all of the new args. */
|
|
sub sp, r10
|
|
/* Pad to make way for potential skipped registers */
|
|
sub sp, 20
|
|
|
|
/* Call ffi_prep_args(stack, &ecif). */
|
|
/* r11 already set */
|
|
mov r1, r12
|
|
mov r12, sp
|
|
icall r1
|
|
|
|
/* Save new argument size */
|
|
mov r1, r12
|
|
|
|
/* Move first 5 parameters in registers. */
|
|
ldm sp++, r8-r12
|
|
|
|
/* call (fn) (...). */
|
|
ld.w r1, r0[36]
|
|
icall r1
|
|
|
|
/* Remove the space we pushed for the args. */
|
|
mov sp, r0
|
|
|
|
/* Load r1 with the rstruct flag. */
|
|
ld.w r1, sp[32]
|
|
|
|
/* Load r9 with the return type code. */
|
|
ld.w r9, sp[12]
|
|
|
|
/* Load r8 with the return value pointer. */
|
|
ld.w r8, sp[16]
|
|
|
|
/* If the return value pointer is NULL, assume no return value. */
|
|
cp.w r8, 0
|
|
breq .Lend
|
|
|
|
/* Check if return type is actually a struct */
|
|
cp.w r1, 0
|
|
breq 1f
|
|
|
|
/* Return 8bit */
|
|
cp.w r9, FFI_TYPE_UINT8
|
|
breq .Lstore8
|
|
|
|
/* Return 16bit */
|
|
cp.w r9, FFI_TYPE_UINT16
|
|
breq .Lstore16
|
|
|
|
1:
|
|
/* Return 32bit */
|
|
cp.w r9, FFI_TYPE_UINT32
|
|
breq .Lstore32
|
|
cp.w r9, FFI_TYPE_UINT16
|
|
breq .Lstore32
|
|
cp.w r9, FFI_TYPE_UINT8
|
|
breq .Lstore32
|
|
|
|
/* Return 64bit */
|
|
cp.w r9, FFI_TYPE_UINT64
|
|
breq .Lstore64
|
|
|
|
/* Didn't match anything */
|
|
bral .Lend
|
|
|
|
.Lstore64:
|
|
st.w r8[0], r11
|
|
st.w r8[4], r10
|
|
bral .Lend
|
|
|
|
.Lstore32:
|
|
st.w r8[0], r12
|
|
bral .Lend
|
|
|
|
.Lstore16:
|
|
st.h r8[0], r12
|
|
bral .Lend
|
|
|
|
.Lstore8:
|
|
st.b r8[0], r12
|
|
bral .Lend
|
|
|
|
.Lend:
|
|
sub sp, -20
|
|
ldm sp++, r0,r1,pc
|
|
|
|
.size ffi_call_SYSV, . - ffi_call_SYSV
|
|
|
|
|
|
/* r12: __ctx
|
|
* r11: __rstruct_flag
|
|
* r10: __inner */
|
|
|
|
.align 1
|
|
.globl ffi_closure_SYSV
|
|
.type ffi_closure_SYSV, @function
|
|
ffi_closure_SYSV:
|
|
stm --sp, r0,lr
|
|
mov r0, r11
|
|
mov r8, r10
|
|
sub r10, sp, -8
|
|
sub sp, 12
|
|
st.w sp[8], sp
|
|
sub r11, sp, -8
|
|
icall r8
|
|
|
|
/* Check if return type is actually a struct */
|
|
cp.w r0, 0
|
|
breq 1f
|
|
|
|
/* Return 8bit */
|
|
cp.w r12, FFI_TYPE_UINT8
|
|
breq .Lget8
|
|
|
|
/* Return 16bit */
|
|
cp.w r12, FFI_TYPE_UINT16
|
|
breq .Lget16
|
|
|
|
1:
|
|
/* Return 32bit */
|
|
cp.w r12, FFI_TYPE_UINT32
|
|
breq .Lget32
|
|
cp.w r12, FFI_TYPE_UINT16
|
|
breq .Lget32
|
|
cp.w r12, FFI_TYPE_UINT8
|
|
breq .Lget32
|
|
|
|
/* Return 64bit */
|
|
cp.w r12, FFI_TYPE_UINT64
|
|
breq .Lget64
|
|
|
|
/* Didn't match anything */
|
|
bral .Lclend
|
|
|
|
.Lget64:
|
|
ld.w r11, sp[0]
|
|
ld.w r10, sp[4]
|
|
bral .Lclend
|
|
|
|
.Lget32:
|
|
ld.w r12, sp[0]
|
|
bral .Lclend
|
|
|
|
.Lget16:
|
|
ld.uh r12, sp[0]
|
|
bral .Lclend
|
|
|
|
.Lget8:
|
|
ld.ub r12, sp[0]
|
|
bral .Lclend
|
|
|
|
.Lclend:
|
|
sub sp, -12
|
|
ldm sp++, r0,lr
|
|
sub sp, -20
|
|
mov pc, lr
|
|
|
|
.size ffi_closure_SYSV, . - ffi_closure_SYSV
|
|
|
|
#if defined __ELF__ && defined __linux__
|
|
.section .note.GNU-stack,"",@progbits
|
|
#endif
|