PUBLIC ffi_call_AMD64 EXTRN __chkstk:NEAR EXTRN ffi_closure_SYSV:NEAR _TEXT SEGMENT ;;; ffi_closure_OUTER 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_SYSV for the actual work, then return the result. ;;; ffi_closure_OUTER PROC FRAME ;; save actual arguments to their stack space. 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 forth third_is_float: movlpd QWORD PTR [rsp+24], xmm2 forth: test r11, 8 jne forth_is_float mov QWORD PTR [rsp+32], r9 jmp done forth_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, 40 ; correct our own area mov rax, ffi_closure_SYSV call rax ; call the real closure function ;; Here, code is missing that handles float return values add rsp, 40 movd xmm0, rax ; In case the closure returned a float. ret 0 ffi_closure_OUTER ENDP ;;; ffi_call_AMD64 stack$ = 0 prepfunc$ = 32 ecif$ = 40 bytes$ = 48 flags$ = 56 rvalue$ = 64 fn$ = 72 ffi_call_AMD64 PROC FRAME 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 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 prepfunc$[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_int$: cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT jne ret_float$ mov rcx, QWORD PTR rvalue$[rbp] mov DWORD PTR [rcx], eax jmp SHORT ret_nothing$ ret_float$: cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT jne SHORT ret_double$ mov rax, QWORD PTR rvalue$[rbp] movlpd QWORD PTR [rax], xmm0 jmp SHORT ret_nothing$ ret_double$: cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE jne SHORT ret_int64$ mov rax, QWORD PTR rvalue$[rbp] movlpd QWORD PTR [rax], xmm0 jmp SHORT ret_nothing$ ret_int64$: cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64 jne ret_nothing$ mov rcx, QWORD PTR rvalue$[rbp] mov QWORD PTR [rcx], rax jmp SHORT ret_nothing$ ret_nothing$: xor eax, eax lea rsp, QWORD PTR [rbp+16] pop rbp ret 0 ffi_call_AMD64 ENDP _TEXT ENDS END