5 /* Constants for ffi_call_win64 */
7 #define PREP_ARGS_FN 32
14 /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
15 extended_cif *ecif, unsigned bytes, unsigned flags,
16 unsigned *rvalue, void (*fn)());
23 EXTRN ffi_closure_win64_inner:NEAR
27 ;;; ffi_closure_win64 will be called with these registers set:
28 ;;; rax points to 'closure'
29 ;;; r11 contains a bit mask that specifies which of the
30 ;;; first four parameters are float or double
32 ;;; It must move the parameters passed in registers to their stack location,
33 ;;; call ffi_closure_win64_inner for the actual work, then return the result.
35 ffi_closure_win64 PROC FRAME
36 ;; copy register arguments onto stack
39 mov QWORD PTR [rsp+8], rcx
42 movlpd QWORD PTR [rsp+8], xmm0
47 mov QWORD PTR [rsp+16], rdx
50 movlpd QWORD PTR [rsp+16], xmm1
55 mov QWORD PTR [rsp+24], r8
58 movlpd QWORD PTR [rsp+24], xmm2
63 mov QWORD PTR [rsp+32], r9
66 movlpd QWORD PTR [rsp+32], xmm3
72 mov rcx, rax ; context is first parameter
73 mov rdx, rsp ; stack is second parameter
74 add rdx, 48 ; point to start of arguments
75 mov rax, ffi_closure_win64_inner
76 call rax ; call the real closure function
78 movd xmm0, rax ; If the closure returned a float,
79 ; ffi_closure_win64_inner wrote it to rax
81 ffi_closure_win64 ENDP
83 ffi_call_win64 PROC FRAME
84 ;; copy registers onto stack
85 mov QWORD PTR [rsp+32], r9
86 mov QWORD PTR [rsp+24], r8
87 mov QWORD PTR [rsp+16], rdx
88 mov QWORD PTR [rsp+8], rcx
92 sub rsp, 48 ; 00000030H
94 lea rbp, QWORD PTR [rsp+32]
97 mov eax, DWORD PTR CIF_BYTES[rbp]
102 lea rax, QWORD PTR [rsp+32]
103 mov QWORD PTR STACK[rbp], rax
105 mov rdx, QWORD PTR ECIF[rbp]
106 mov rcx, QWORD PTR STACK[rbp]
107 call QWORD PTR PREP_ARGS_FN[rbp]
109 mov rsp, QWORD PTR STACK[rbp]
111 movlpd xmm3, QWORD PTR [rsp+24]
114 movlpd xmm2, QWORD PTR [rsp+16]
117 movlpd xmm1, QWORD PTR [rsp+8]
120 movlpd xmm0, QWORD PTR [rsp]
123 call QWORD PTR FN[rbp]
125 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
128 mov rcx, QWORD PTR RVALUE[rbp]
129 mov DWORD PTR [rcx], eax
133 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
136 mov rcx, QWORD PTR RVALUE[rbp]
137 mov WORD PTR [rcx], ax
141 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
144 mov rcx, QWORD PTR RVALUE[rbp]
145 mov BYTE PTR [rcx], al
149 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
152 mov rcx, QWORD PTR RVALUE[rbp]
154 mov QWORD PTR [rcx], rax
158 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
161 mov rcx, QWORD PTR RVALUE[rbp]
163 mov QWORD PTR [rcx], rax
167 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
170 mov rcx, QWORD PTR RVALUE[rbp]
172 mov QWORD PTR [rcx], rax
176 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
179 mov rcx, QWORD PTR RVALUE[rbp]
181 mov QWORD PTR [rcx], rax
185 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
188 mov rcx, QWORD PTR RVALUE[rbp]
190 mov QWORD PTR [rcx], rax
194 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
197 mov rcx, QWORD PTR RVALUE[rbp]
199 mov QWORD PTR [rcx], rax
203 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
204 jne SHORT ret_double$
206 mov rax, QWORD PTR RVALUE[rbp]
207 movss DWORD PTR [rax], xmm0
211 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
212 jne SHORT ret_sint64$
214 mov rax, QWORD PTR RVALUE[rbp]
215 movlpd QWORD PTR [rax], xmm0
219 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
222 mov rcx, QWORD PTR RVALUE[rbp]
223 mov QWORD PTR [rcx], rax
229 lea rsp, QWORD PTR [rbp+16]
239 .extern _ffi_closure_win64_inner
241 # ffi_closure_win64 will be called with these registers set:
242 # rax points to 'closure'
243 # r11 contains a bit mask that specifies which of the
244 # first four parameters are float or double
246 # It must move the parameters passed in registers to their stack location,
247 # call ffi_closure_win64_inner for the actual work, then return the result.
250 .globl _ffi_closure_win64
252 # copy register arguments onto stack
258 movlpd %xmm0, 8(%rsp)
262 jne .Lsecond_is_float
266 movlpd %xmm1, 16(%rsp)
274 movlpd %xmm2, 24(%rsp)
278 jne .Lfourth_is_float
282 movlpd %xmm3, 32(%rsp)
288 mov %rax, %rcx # context is first parameter
289 mov %rsp, %rdx # stack is second parameter
290 add $48, %rdx # point to start of arguments
291 mov $_ffi_closure_win64_inner, %rax
292 callq *%rax # call the real closure function
294 movq %rax, %xmm0 # If the closure returned a float,
295 # ffi_closure_win64_inner wrote it to rax
297 .ffi_closure_win64_end:
300 .globl _ffi_call_win64
302 # copy registers onto stack
315 mov CIF_BYTES(%rbp),%eax
331 mov %rax, STACK(%rbp)
334 mov STACK(%rbp), %rcx
335 callq *PREP_ARGS_FN(%rbp)
337 mov STACK(%rbp), %rsp
339 movlpd 24(%rsp), %xmm3
342 movlpd 16(%rsp), %xmm2
345 movlpd 8(%rsp), %xmm1
353 cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
356 mov RVALUE(%rbp), %rcx
361 cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
364 mov RVALUE(%rbp), %rcx
369 cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
372 mov RVALUE(%rbp), %rcx
377 cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
380 mov RVALUE(%rbp), %rcx
386 cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
389 mov RVALUE(%rbp), %rcx
395 cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
398 mov RVALUE(%rbp), %rcx
404 cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
407 mov RVALUE(%rbp), %rcx
413 cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
416 mov RVALUE(%rbp), %rcx
422 cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
425 mov RVALUE(%rbp), %rcx
431 cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
434 mov RVALUE(%rbp), %rax
439 cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
442 mov RVALUE(%rbp), %rax
447 cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
450 mov RVALUE(%rbp), %rcx
461 #endif /* !_MSC_VER */