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]
238 .extern _ffi_closure_win64_inner
240 # ffi_closure_win64 will be called with these registers set:
241 # rax points to 'closure'
242 # r11 contains a bit mask that specifies which of the
243 # first four parameters are float or double
245 # It must move the parameters passed in registers to their stack location,
246 # call ffi_closure_win64_inner for the actual work, then return the result.
249 .globl _ffi_closure_win64
251 # copy register arguments onto stack
257 movlpd %xmm0, 8(%rsp)
261 jne .Lsecond_is_float
265 movlpd %xmm1, 16(%rsp)
273 movlpd %xmm2, 24(%rsp)
277 jne .Lfourth_is_float
281 movlpd %xmm3, 32(%rsp)
287 mov %rax, %rcx # context is first parameter
288 mov %rsp, %rdx # stack is second parameter
289 add $48, %rdx # point to start of arguments
290 mov $_ffi_closure_win64_inner, %rax
291 callq *%rax # call the real closure function
293 movq %rax, %xmm0 # If the closure returned a float,
294 # ffi_closure_win64_inner wrote it to rax
296 .ffi_closure_win64_end:
299 .globl _ffi_call_win64
301 # copy registers onto stack
314 mov CIF_BYTES(%rbp),%eax
329 mov %rax, STACK(%rbp)
332 mov STACK(%rbp), %rcx
333 callq *PREP_ARGS_FN(%rbp)
335 mov STACK(%rbp), %rsp
337 movlpd 24(%rsp), %xmm3
340 movlpd 16(%rsp), %xmm2
343 movlpd 8(%rsp), %xmm1
351 cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
354 mov RVALUE(%rbp), %rcx
359 cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
362 mov RVALUE(%rbp), %rcx
367 cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
370 mov RVALUE(%rbp), %rcx
375 cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
378 mov RVALUE(%rbp), %rcx
384 cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
387 mov RVALUE(%rbp), %rcx
393 cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
396 mov RVALUE(%rbp), %rcx
402 cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
405 mov RVALUE(%rbp), %rcx
411 cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
414 mov RVALUE(%rbp), %rcx
420 cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
423 mov RVALUE(%rbp), %rcx
429 cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
432 mov RVALUE(%rbp), %rax
437 cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
440 mov RVALUE(%rbp), %rax
445 cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
448 mov RVALUE(%rbp), %rcx
459 #endif /* !_MSC_VER */