1PUBLIC ffi_call_AMD64 2 3EXTRN __chkstk:NEAR 4EXTRN 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;;; 16ffi_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 22first_is_float: 23 movlpd QWORD PTR [rsp+8], xmm0 24 25second: 26 test r11, 2 27 jne second_is_float 28 mov QWORD PTR [rsp+16], rdx 29 jmp third 30second_is_float: 31 movlpd QWORD PTR [rsp+16], xmm1 32 33third: 34 test r11, 4 35 jne third_is_float 36 mov QWORD PTR [rsp+24], r8 37 jmp forth 38third_is_float: 39 movlpd QWORD PTR [rsp+24], xmm2 40 41forth: 42 test r11, 8 43 jne forth_is_float 44 mov QWORD PTR [rsp+32], r9 45 jmp done 46forth_is_float: 47 movlpd QWORD PTR [rsp+32], xmm3 48 49done: 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 62ffi_closure_OUTER ENDP 63 64 65;;; ffi_call_AMD64 66 67stack$ = 0 68prepfunc$ = 32 69ecif$ = 40 70bytes$ = 48 71flags$ = 56 72rvalue$ = 64 73fn$ = 72 74 75ffi_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] 116ret_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 124ret_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 132ret_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 140ret_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 148ret_nothing$: 149 xor eax, eax 150 151 lea rsp, QWORD PTR [rbp+16] 152 pop rbp 153 ret 0 154ffi_call_AMD64 ENDP 155_TEXT ENDS 156END 157