1 PUBLIC ffi_call_AMD64 2 3 EXTRN __chkstk:NEAR 4 EXTRN ffi_closure_SYSV:NEAR 5 6 _TEXT SEGMENT 7 8 ;;; ffi_closure_OUTER will be called with these registers set: 9 ;;; rax points to 'closure' 10 ;;; r11 contains a bit mask that specifies which of the 11 ;;; first four parameters are float or double 12 ;;; 13 ;;; It must move the parameters passed in registers to their stack location, 14 ;;; call ffi_closure_SYSV for the actual work, then return the result. 15 ;;; 16 ffi_closure_OUTER PROC FRAME 17 ;; save actual arguments to their stack space. 18 test r11, 1 19 jne first_is_float 20 mov QWORD PTR [rsp+8], rcx 21 jmp second 22 first_is_float: 23 movlpd QWORD PTR [rsp+8], xmm0 24 25 second: 26 test r11, 2 27 jne second_is_float 28 mov QWORD PTR [rsp+16], rdx 29 jmp third 30 second_is_float: 31 movlpd QWORD PTR [rsp+16], xmm1 32 33 third: 34 test r11, 4 35 jne third_is_float 36 mov QWORD PTR [rsp+24], r8 37 jmp forth 38 third_is_float: 39 movlpd QWORD PTR [rsp+24], xmm2 40 41 forth: 42 test r11, 8 43 jne forth_is_float 44 mov QWORD PTR [rsp+32], r9 45 jmp done 46 forth_is_float: 47 movlpd QWORD PTR [rsp+32], xmm3 48 49 done: 50 .ALLOCSTACK 40 51 sub rsp, 40 52 .ENDPROLOG 53 mov rcx, rax ; context is first parameter 54 mov rdx, rsp ; stack is second parameter 55 add rdx, 40 ; correct our own area 56 mov rax, ffi_closure_SYSV 57 call rax ; call the real closure function 58 ;; Here, code is missing that handles float return values 59 add rsp, 40 60 movd xmm0, rax ; In case the closure returned a float. 61 ret 0 62 ffi_closure_OUTER ENDP 63 64 65 ;;; ffi_call_AMD64 66 67 stack$ = 0 68 prepfunc$ = 32 69 ecif$ = 40 70 bytes$ = 48 71 flags$ = 56 72 rvalue$ = 64 73 fn$ = 72 74 75 ffi_call_AMD64 PROC FRAME 76 77 mov QWORD PTR [rsp+32], r9 78 mov QWORD PTR [rsp+24], r8 79 mov QWORD PTR [rsp+16], rdx 80 mov QWORD PTR [rsp+8], rcx 81 .PUSHREG rbp 82 push rbp 83 .ALLOCSTACK 48 84 sub rsp, 48 ; 00000030H 85 .SETFRAME rbp, 32 86 lea rbp, QWORD PTR [rsp+32] 87 .ENDPROLOG 88 89 mov eax, DWORD PTR bytes$[rbp] 90 add rax, 15 91 and rax, -16 92 call __chkstk 93 sub rsp, rax 94 lea rax, QWORD PTR [rsp+32] 95 mov QWORD PTR stack$[rbp], rax 96 97 mov rdx, QWORD PTR ecif$[rbp] 98 mov rcx, QWORD PTR stack$[rbp] 99 call QWORD PTR prepfunc$[rbp] 100 101 mov rsp, QWORD PTR stack$[rbp] 102 103 movlpd xmm3, QWORD PTR [rsp+24] 104 movd r9, xmm3 105 106 movlpd xmm2, QWORD PTR [rsp+16] 107 movd r8, xmm2 108 109 movlpd xmm1, QWORD PTR [rsp+8] 110 movd rdx, xmm1 111 112 movlpd xmm0, QWORD PTR [rsp] 113 movd rcx, xmm0 114 115 call QWORD PTR fn$[rbp] 116 ret_int$: 117 cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT 118 jne ret_float$ 119 120 mov rcx, QWORD PTR rvalue$[rbp] 121 mov DWORD PTR [rcx], eax 122 jmp SHORT ret_nothing$ 123 124 ret_float$: 125 cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT 126 jne SHORT ret_double$ 127 128 mov rax, QWORD PTR rvalue$[rbp] 129 movlpd QWORD PTR [rax], xmm0 130 jmp SHORT ret_nothing$ 131 132 ret_double$: 133 cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE 134 jne SHORT ret_int64$ 135 136 mov rax, QWORD PTR rvalue$[rbp] 137 movlpd QWORD PTR [rax], xmm0 138 jmp SHORT ret_nothing$ 139 140 ret_int64$: 141 cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64 142 jne ret_nothing$ 143 144 mov rcx, QWORD PTR rvalue$[rbp] 145 mov QWORD PTR [rcx], rax 146 jmp SHORT ret_nothing$ 147 148 ret_nothing$: 149 xor eax, eax 150 151 lea rsp, QWORD PTR [rbp+16] 152 pop rbp 153 ret 0 154 ffi_call_AMD64 ENDP 155 _TEXT ENDS 156 END 157