define LIBFFI_ASM include <fficonfig.h> include <ffi.h>
Constants for ffi_call_win64
define STACK 0 define PREP_ARGS_FN 32 define ECIF 40 define CIF_BYTES 48 define CIF_FLAGS 56 define RVALUE 64 define FN 72
ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *), extended_cif *ecif, unsigned bytes, unsigned flags, unsigned *rvalue, void (*fn)()); /
ifdef _MSC_VER PUBLIC ffi_call_win64
EXTRN __chkstk:NEAR EXTRN ffi_closure_win64_inner:NEAR
_TEXT SEGMENT
;;; ffi_closure_win64 will be called with these registers set: ;;; rax points to 'closure' ;;; r11 contains a bit mask that specifies which of the ;;; first four parameters are float or double ;;; ;;; It must move the parameters passed in registers to their stack location, ;;; call ffi_closure_win64_inner for the actual work, then return the result. ;;; ffi_closure_win64 PROC FRAME
;; copy register arguments onto stack test r11, 1 jne first_is_float mov QWORD PTR [rsp+8], rcx jmp second
first_is_float:
movlpd QWORD PTR [rsp+8], xmm0
second:
test r11, 2 jne second_is_float mov QWORD PTR [rsp+16], rdx jmp third
second_is_float:
movlpd QWORD PTR [rsp+16], xmm1
third:
test r11, 4 jne third_is_float mov QWORD PTR [rsp+24], r8 jmp fourth
third_is_float:
movlpd QWORD PTR [rsp+24], xmm2
fourth:
test r11, 8 jne fourth_is_float mov QWORD PTR [rsp+32], r9 jmp done
fourth_is_float:
movlpd QWORD PTR [rsp+32], xmm3
done:
.ALLOCSTACK 40 sub rsp, 40 .ENDPROLOG mov rcx, rax ; context is first parameter mov rdx, rsp ; stack is second parameter add rdx, 48 ; point to start of arguments mov rax, ffi_closure_win64_inner call rax ; call the real closure function add rsp, 40 movd xmm0, rax ; If the closure returned a float, ; ffi_closure_win64_inner wrote it to rax ret 0
ffi_closure_win64 ENDP
ffi_call_win64 PROC FRAME
;; copy registers onto stack mov QWORD PTR [rsp+32], r9 mov QWORD PTR [rsp+24], r8 mov QWORD PTR [rsp+16], rdx mov QWORD PTR [rsp+8], rcx .PUSHREG rbp push rbp .ALLOCSTACK 48 sub rsp, 48 ; 00000030H .SETFRAME rbp, 32 lea rbp, QWORD PTR [rsp+32] .ENDPROLOG mov eax, DWORD PTR CIF_BYTES[rbp] add rax, 15 and rax, -16 call __chkstk sub rsp, rax lea rax, QWORD PTR [rsp+32] mov QWORD PTR STACK[rbp], rax mov rdx, QWORD PTR ECIF[rbp] mov rcx, QWORD PTR STACK[rbp] call QWORD PTR PREP_ARGS_FN[rbp] mov rsp, QWORD PTR STACK[rbp] movlpd xmm3, QWORD PTR [rsp+24] movd r9, xmm3 movlpd xmm2, QWORD PTR [rsp+16] movd r8, xmm2 movlpd xmm1, QWORD PTR [rsp+8] movd rdx, xmm1 movlpd xmm0, QWORD PTR [rsp] movd rcx, xmm0 call QWORD PTR FN[rbp]
ret_struct4b$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B jne ret_struct2b$ mov rcx, QWORD PTR RVALUE[rbp] mov DWORD PTR [rcx], eax jmp ret_void$
ret_struct2b$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B jne ret_struct1b$ mov rcx, QWORD PTR RVALUE[rbp] mov WORD PTR [rcx], ax jmp ret_void$
ret_struct1b$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B jne ret_uint8$ mov rcx, QWORD PTR RVALUE[rbp] mov BYTE PTR [rcx], al jmp ret_void$
ret_uint8$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8 jne ret_sint8$ mov rcx, QWORD PTR RVALUE[rbp] movzx rax, al mov QWORD PTR [rcx], rax jmp ret_void$
ret_sint8$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8 jne ret_uint16$ mov rcx, QWORD PTR RVALUE[rbp] movsx rax, al mov QWORD PTR [rcx], rax jmp ret_void$
ret_uint16$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16 jne ret_sint16$ mov rcx, QWORD PTR RVALUE[rbp] movzx rax, ax mov QWORD PTR [rcx], rax jmp SHORT ret_void$
ret_sint16$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16 jne ret_uint32$ mov rcx, QWORD PTR RVALUE[rbp] movsx rax, ax mov QWORD PTR [rcx], rax jmp SHORT ret_void$
ret_uint32$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32 jne ret_sint32$ mov rcx, QWORD PTR RVALUE[rbp] mov eax, eax mov QWORD PTR [rcx], rax jmp SHORT ret_void$
ret_sint32$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32 jne ret_float$ mov rcx, QWORD PTR RVALUE[rbp] cdqe mov QWORD PTR [rcx], rax jmp SHORT ret_void$
ret_float$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT jne SHORT ret_double$ mov rax, QWORD PTR RVALUE[rbp] movss DWORD PTR [rax], xmm0 jmp SHORT ret_void$
ret_double$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE jne SHORT ret_sint64$ mov rax, QWORD PTR RVALUE[rbp] movlpd QWORD PTR [rax], xmm0 jmp SHORT ret_void$
ret_sint64$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 jne ret_void$ mov rcx, QWORD PTR RVALUE[rbp] mov QWORD PTR [rcx], rax jmp SHORT ret_void$
ret_void$:
xor rax, rax lea rsp, QWORD PTR [rbp+16] pop rbp ret 0
ffi_call_win64 ENDP _TEXT ENDS END
else
ifdef SYMBOL_UNDERSCORE define SYMBOL_NAME(name) _##name else define SYMBOL_NAME(name) name endif
.text
.extern SYMBOL_NAME(ffi_closure_win64_inner)
# ffi_closure_win64 will be called with these registers set: # rax points to 'closure' # r11 contains a bit mask that specifies which of the # first four parameters are float or double # # It must move the parameters passed in registers to their stack location, # call ffi_closure_win64_inner for the actual work, then return the result. #
.balign 16 .globl SYMBOL_NAME(ffi_closure_win64)
SYMBOL_NAME(ffi_closure_win64):
# copy register arguments onto stack test $1,%r11 jne .Lfirst_is_float mov %rcx, 8(%rsp) jmp .Lsecond
.Lfirst_is_float:
movlpd %xmm0, 8(%rsp)
.Lsecond:
test $2, %r11 jne .Lsecond_is_float mov %rdx, 16(%rsp) jmp .Lthird
.Lsecond_is_float:
movlpd %xmm1, 16(%rsp)
.Lthird:
test $4, %r11 jne .Lthird_is_float mov %r8,24(%rsp) jmp .Lfourth
.Lthird_is_float:
movlpd %xmm2, 24(%rsp)
.Lfourth:
test $8, %r11 jne .Lfourth_is_float mov %r9, 32(%rsp) jmp .Ldone
.Lfourth_is_float:
movlpd %xmm3, 32(%rsp)
.Ldone: #.ALLOCSTACK 40
sub $40, %rsp
#.ENDPROLOG
mov %rax, %rcx # context is first parameter mov %rsp, %rdx # stack is second parameter add $48, %rdx # point to start of arguments mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax callq *%rax # call the real closure function add $40, %rsp movq %rax, %xmm0 # If the closure returned a float, # ffi_closure_win64_inner wrote it to rax retq
.ffi_closure_win64_end:
.balign 16 .globl SYMBOL_NAME(ffi_call_win64)
SYMBOL_NAME(ffi_call_win64):
# copy registers onto stack mov %r9,32(%rsp) mov %r8,24(%rsp) mov %rdx,16(%rsp) mov %rcx,8(%rsp) #.PUSHREG rbp push %rbp #.ALLOCSTACK 48 sub $48,%rsp #.SETFRAME rbp, 32 lea 32(%rsp),%rbp #.ENDPROLOG mov CIF_BYTES(%rbp),%eax add $15, %rax and $-16, %rax cmpq $0x1000, %rax jb Lch_done
Lch_probe:
subq $0x1000,%rsp orl $0x0, (%rsp) subq $0x1000,%rax cmpq $0x1000,%rax ja Lch_probe
Lch_done:
subq %rax, %rsp orl $0x0, (%rsp) lea 32(%rsp), %rax mov %rax, STACK(%rbp) mov ECIF(%rbp), %rdx mov STACK(%rbp), %rcx callq *PREP_ARGS_FN(%rbp) mov STACK(%rbp), %rsp movlpd 24(%rsp), %xmm3 movd %xmm3, %r9 movlpd 16(%rsp), %xmm2 movd %xmm2, %r8 movlpd 8(%rsp), %xmm1 movd %xmm1, %rdx movlpd (%rsp), %xmm0 movd %xmm0, %rcx callq *FN(%rbp)
.Lret_struct4b:
cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp) jne .Lret_struct2b mov RVALUE(%rbp), %rcx mov %eax, (%rcx) jmp .Lret_void
.Lret_struct2b:
cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp) jne .Lret_struct1b mov RVALUE(%rbp), %rcx mov %ax, (%rcx) jmp .Lret_void
.Lret_struct1b:
cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp) jne .Lret_uint8 mov RVALUE(%rbp), %rcx mov %al, (%rcx) jmp .Lret_void
.Lret_uint8:
cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp) jne .Lret_sint8 mov RVALUE(%rbp), %rcx movzbq %al, %rax movq %rax, (%rcx) jmp .Lret_void
.Lret_sint8:
cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp) jne .Lret_uint16 mov RVALUE(%rbp), %rcx movsbq %al, %rax movq %rax, (%rcx) jmp .Lret_void
.Lret_uint16:
cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp) jne .Lret_sint16 mov RVALUE(%rbp), %rcx movzwq %ax, %rax movq %rax, (%rcx) jmp .Lret_void
.Lret_sint16:
cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp) jne .Lret_uint32 mov RVALUE(%rbp), %rcx movswq %ax, %rax movq %rax, (%rcx) jmp .Lret_void
.Lret_uint32:
cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp) jne .Lret_sint32 mov RVALUE(%rbp), %rcx movl %eax, %eax movq %rax, (%rcx) jmp .Lret_void
.Lret_sint32:
cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp) jne .Lret_float mov RVALUE(%rbp), %rcx cltq movq %rax, (%rcx) jmp .Lret_void
.Lret_float:
cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp) jne .Lret_double mov RVALUE(%rbp), %rax movss %xmm0, (%rax) jmp .Lret_void
.Lret_double:
cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) jne .Lret_sint64 mov RVALUE(%rbp), %rax movlpd %xmm0, (%rax) jmp .Lret_void
.Lret_sint64:
cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) jne .Lret_void mov RVALUE(%rbp), %rcx mov %rax, (%rcx) jmp .Lret_void
.Lret_void:
xor %rax, %rax lea 16(%rbp), %rsp pop %rbp retq
.ffi_call_win64_end: endif /* !_MSC_VER