1 #define LIBFFI_ASM
2 #include <fficonfig.h>
3 #include <ffi.h>
4
5 /* Constants for ffi_call_win64 */
6 #define STACK 0
7 #define PREP_ARGS_FN 32
8 #define ECIF 40
9 #define CIF_BYTES 48
10 #define CIF_FLAGS 56
11 #define RVALUE 64
12 #define FN 72
13
14 /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
15 extended_cif *ecif, unsigned bytes, unsigned flags,
16 unsigned *rvalue, void (*fn)());
17 */
18
19 #ifdef _MSC_VER
20 PUBLIC ffi_call_win64
21
22 EXTRN __chkstk:NEAR
23 EXTRN ffi_closure_win64_inner:NEAR
24
25 _TEXT SEGMENT
26
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
31 ;;;
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.
34 ;;;
35 ffi_closure_win64 PROC FRAME
36 ;; copy register arguments onto stack
37 test r11, 1
38 jne first_is_float
39 mov QWORD PTR [rsp+8], rcx
40 jmp second
41 first_is_float:
42 movlpd QWORD PTR [rsp+8], xmm0
43
44 second:
45 test r11, 2
46 jne second_is_float
47 mov QWORD PTR [rsp+16], rdx
48 jmp third
49 second_is_float:
50 movlpd QWORD PTR [rsp+16], xmm1
51
52 third:
53 test r11, 4
54 jne third_is_float
55 mov QWORD PTR [rsp+24], r8
56 jmp fourth
57 third_is_float:
58 movlpd QWORD PTR [rsp+24], xmm2
59
60 fourth:
61 test r11, 8
62 jne fourth_is_float
63 mov QWORD PTR [rsp+32], r9
64 jmp done
65 fourth_is_float:
66 movlpd QWORD PTR [rsp+32], xmm3
67
68 done:
69 .ALLOCSTACK 40
70 sub rsp, 40
71 .ENDPROLOG
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
77 add rsp, 40
78 movd xmm0, rax ; If the closure returned a float,
79 ; ffi_closure_win64_inner wrote it to rax
80 ret 0
81 ffi_closure_win64 ENDP
82
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
89 .PUSHREG rbp
90 push rbp
91 .ALLOCSTACK 48
92 sub rsp, 48 ; 00000030H
93 .SETFRAME rbp, 32
94 lea rbp, QWORD PTR [rsp+32]
95 .ENDPROLOG
96
97 mov eax, DWORD PTR CIF_BYTES[rbp]
98 add rax, 15
99 and rax, -16
100 call __chkstk
101 sub rsp, rax
102 lea rax, QWORD PTR [rsp+32]
103 mov QWORD PTR STACK[rbp], rax
104
105 mov rdx, QWORD PTR ECIF[rbp]
106 mov rcx, QWORD PTR STACK[rbp]
107 call QWORD PTR PREP_ARGS_FN[rbp]
108
109 mov rsp, QWORD PTR STACK[rbp]
110
111 movlpd xmm3, QWORD PTR [rsp+24]
112 movd r9, xmm3
113
114 movlpd xmm2, QWORD PTR [rsp+16]
115 movd r8, xmm2
116
117 movlpd xmm1, QWORD PTR [rsp+8]
118 movd rdx, xmm1
119
120 movlpd xmm0, QWORD PTR [rsp]
121 movd rcx, xmm0
122
123 call QWORD PTR FN[rbp]
124 ret_struct4b$:
125 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
126 jne ret_struct2b$
127
128 mov rcx, QWORD PTR RVALUE[rbp]
129 mov DWORD PTR [rcx], eax
130 jmp ret_void$
131
132 ret_struct2b$:
133 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
134 jne ret_struct1b$
135
136 mov rcx, QWORD PTR RVALUE[rbp]
137 mov WORD PTR [rcx], ax
138 jmp ret_void$
139
140 ret_struct1b$:
141 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
142 jne ret_uint8$
143
144 mov rcx, QWORD PTR RVALUE[rbp]
145 mov BYTE PTR [rcx], al
146 jmp ret_void$
147
148 ret_uint8$:
149 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
150 jne ret_sint8$
151
152 mov rcx, QWORD PTR RVALUE[rbp]
153 movzx rax, al
154 mov QWORD PTR [rcx], rax
155 jmp ret_void$
156
157 ret_sint8$:
158 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
159 jne ret_uint16$
160
161 mov rcx, QWORD PTR RVALUE[rbp]
162 movsx rax, al
163 mov QWORD PTR [rcx], rax
164 jmp ret_void$
165
166 ret_uint16$:
167 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
168 jne ret_sint16$
169
170 mov rcx, QWORD PTR RVALUE[rbp]
171 movzx rax, ax
172 mov QWORD PTR [rcx], rax
173 #ifndef GSTREAMER_LITE
174 jmp SHORT ret_void$
175 #else
176 jmp ret_void$
177 #endif // GSTREAMER_LITE
178
179 ret_sint16$:
180 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
181 jne ret_uint32$
182
183 mov rcx, QWORD PTR RVALUE[rbp]
184 movsx rax, ax
185 mov QWORD PTR [rcx], rax
186 #ifndef GSTREAMER_LITE
187 jmp SHORT ret_void$
188 #else
189 jmp ret_void$
190 #endif // GSTREAMER_LITE
191
192 ret_uint32$:
193 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
194 jne ret_sint32$
195
196 mov rcx, QWORD PTR RVALUE[rbp]
197 mov eax, eax
198 mov QWORD PTR [rcx], rax
199 jmp SHORT ret_void$
200
201 ret_sint32$:
202 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
203 jne ret_float$
204
205 mov rcx, QWORD PTR RVALUE[rbp]
206 cdqe
207 mov QWORD PTR [rcx], rax
208 jmp SHORT ret_void$
209
210 ret_float$:
211 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
212 jne SHORT ret_double$
213
214 mov rax, QWORD PTR RVALUE[rbp]
215 movss DWORD PTR [rax], xmm0
216 jmp SHORT ret_void$
217
218 ret_double$:
219 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
220 jne SHORT ret_uint64$
221
222 mov rax, QWORD PTR RVALUE[rbp]
223 movlpd QWORD PTR [rax], xmm0
224 jmp SHORT ret_void$
225
226 ret_uint64$:
227 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64
228 jne SHORT ret_sint64$
229
230 mov rcx, QWORD PTR RVALUE[rbp]
231 mov QWORD PTR [rcx], rax
232 jmp SHORT ret_void$
233
234 ret_sint64$:
235 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
236 jne SHORT ret_pointer$
237
238 mov rcx, QWORD PTR RVALUE[rbp]
239 mov QWORD PTR [rcx], rax
240 jmp SHORT ret_void$
241
242 ret_pointer$:
243 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER
244 jne SHORT ret_int$
245
246 mov rcx, QWORD PTR RVALUE[rbp]
247 mov QWORD PTR [rcx], rax
248 jmp SHORT ret_void$
249
250 ret_int$:
251 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT
252 jne SHORT ret_void$
253
254 mov rcx, QWORD PTR RVALUE[rbp]
255 cdqe
256 mov QWORD PTR [rcx], rax
257 jmp SHORT ret_void$
258
259 ret_void$:
260 xor rax, rax
261
262 lea rsp, QWORD PTR [rbp+16]
263 pop rbp
264 ret 0
265 ffi_call_win64 ENDP
266 _TEXT ENDS
267 END
268
269 #else
270
271 #ifdef SYMBOL_UNDERSCORE
272 #define SYMBOL_NAME(name) _##name
273 #else
274 #define SYMBOL_NAME(name) name
275 #endif
276
277 .text
278
279 .extern SYMBOL_NAME(ffi_closure_win64_inner)
280
281 # ffi_closure_win64 will be called with these registers set:
282 # rax points to 'closure'
283 # r11 contains a bit mask that specifies which of the
284 # first four parameters are float or double
285 #
286 # It must move the parameters passed in registers to their stack location,
287 # call ffi_closure_win64_inner for the actual work, then return the result.
288 #
289 .balign 16
290 .globl SYMBOL_NAME(ffi_closure_win64)
291 .seh_proc SYMBOL_NAME(ffi_closure_win64)
292 SYMBOL_NAME(ffi_closure_win64):
293 # copy register arguments onto stack
294 test $1,%r11
295 jne .Lfirst_is_float
296 mov %rcx, 8(%rsp)
297 jmp .Lsecond
298 .Lfirst_is_float:
299 movlpd %xmm0, 8(%rsp)
300
301 .Lsecond:
302 test $2, %r11
303 jne .Lsecond_is_float
304 mov %rdx, 16(%rsp)
305 jmp .Lthird
306 .Lsecond_is_float:
307 movlpd %xmm1, 16(%rsp)
308
309 .Lthird:
310 test $4, %r11
311 jne .Lthird_is_float
312 mov %r8,24(%rsp)
313 jmp .Lfourth
314 .Lthird_is_float:
315 movlpd %xmm2, 24(%rsp)
316
317 .Lfourth:
318 test $8, %r11
319 jne .Lfourth_is_float
320 mov %r9, 32(%rsp)
321 jmp .Ldone
322 .Lfourth_is_float:
323 movlpd %xmm3, 32(%rsp)
324
325 .Ldone:
326 .seh_stackalloc 40
327 sub $40, %rsp
328 .seh_endprologue
329 mov %rax, %rcx # context is first parameter
330 mov %rsp, %rdx # stack is second parameter
331 add $48, %rdx # point to start of arguments
332 leaq SYMBOL_NAME(ffi_closure_win64_inner)(%rip), %rax
333 callq *%rax # call the real closure function
334 add $40, %rsp
335 movq %rax, %xmm0 # If the closure returned a float,
336 # ffi_closure_win64_inner wrote it to rax
337 retq
338 .seh_endproc
339
340 .balign 16
341 .globl SYMBOL_NAME(ffi_call_win64)
342 .seh_proc SYMBOL_NAME(ffi_call_win64)
343 SYMBOL_NAME(ffi_call_win64):
344 # copy registers onto stack
345 mov %r9,32(%rsp)
346 mov %r8,24(%rsp)
347 mov %rdx,16(%rsp)
348 mov %rcx,8(%rsp)
349 .seh_pushreg rbp
350 push %rbp
351 .seh_stackalloc 48
352 sub $48,%rsp
353 .seh_setframe rbp, 32
354 lea 32(%rsp),%rbp
355 .seh_endprologue
356
357 mov CIF_BYTES(%rbp),%eax
358 add $15, %rax
359 and $-16, %rax
360 cmpq $0x1000, %rax
361 jb Lch_done
362 Lch_probe:
363 subq $0x1000,%rsp
364 orl $0x0, (%rsp)
365 subq $0x1000,%rax
366 cmpq $0x1000,%rax
367 ja Lch_probe
368 Lch_done:
369 subq %rax, %rsp
370 orl $0x0, (%rsp)
371 lea 32(%rsp), %rax
372 mov %rax, STACK(%rbp)
373
374 mov ECIF(%rbp), %rdx
375 mov STACK(%rbp), %rcx
376 callq *PREP_ARGS_FN(%rbp)
377
378 mov STACK(%rbp), %rsp
379
380 movlpd 24(%rsp), %xmm3
381 movd %xmm3, %r9
382
383 movlpd 16(%rsp), %xmm2
384 movd %xmm2, %r8
385
386 movlpd 8(%rsp), %xmm1
387 movd %xmm1, %rdx
388
389 movlpd (%rsp), %xmm0
390 movd %xmm0, %rcx
391
392 callq *FN(%rbp)
393 .Lret_struct4b:
394 cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
395 jne .Lret_struct2b
396
397 mov RVALUE(%rbp), %rcx
398 mov %eax, (%rcx)
399 jmp .Lret_void
400
401 .Lret_struct2b:
402 cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
403 jne .Lret_struct1b
404
405 mov RVALUE(%rbp), %rcx
406 mov %ax, (%rcx)
407 jmp .Lret_void
408
409 .Lret_struct1b:
410 cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
411 jne .Lret_uint8
412
413 mov RVALUE(%rbp), %rcx
414 mov %al, (%rcx)
415 jmp .Lret_void
416
417 .Lret_uint8:
418 cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
419 jne .Lret_sint8
420
421 mov RVALUE(%rbp), %rcx
422 movzbq %al, %rax
423 movq %rax, (%rcx)
424 jmp .Lret_void
425
426 .Lret_sint8:
427 cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
428 jne .Lret_uint16
429
430 mov RVALUE(%rbp), %rcx
431 movsbq %al, %rax
432 movq %rax, (%rcx)
433 jmp .Lret_void
434
435 .Lret_uint16:
436 cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
437 jne .Lret_sint16
438
439 mov RVALUE(%rbp), %rcx
440 movzwq %ax, %rax
441 movq %rax, (%rcx)
442 jmp .Lret_void
443
444 .Lret_sint16:
445 cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
446 jne .Lret_uint32
447
448 mov RVALUE(%rbp), %rcx
449 movswq %ax, %rax
450 movq %rax, (%rcx)
451 jmp .Lret_void
452
453 .Lret_uint32:
454 cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
455 jne .Lret_sint32
456
457 mov RVALUE(%rbp), %rcx
458 movl %eax, %eax
459 movq %rax, (%rcx)
460 jmp .Lret_void
461
462 .Lret_sint32:
463 cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
464 jne .Lret_float
465
466 mov RVALUE(%rbp), %rcx
467 cltq
468 movq %rax, (%rcx)
469 jmp .Lret_void
470
471 .Lret_float:
472 cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
473 jne .Lret_double
474
475 mov RVALUE(%rbp), %rax
476 movss %xmm0, (%rax)
477 jmp .Lret_void
478
479 .Lret_double:
480 cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
481 jne .Lret_uint64
482
483 mov RVALUE(%rbp), %rax
484 movlpd %xmm0, (%rax)
485 jmp .Lret_void
486
487 .Lret_uint64:
488 cmpl $FFI_TYPE_UINT64, CIF_FLAGS(%rbp)
489 jne .Lret_sint64
490
491 mov RVALUE(%rbp), %rcx
492 mov %rax, (%rcx)
493 jmp .Lret_void
494
495 .Lret_sint64:
496 cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
497 jne .Lret_pointer
498
499 mov RVALUE(%rbp), %rcx
500 mov %rax, (%rcx)
501 jmp .Lret_void
502
503 .Lret_pointer:
504 cmpl $FFI_TYPE_POINTER, CIF_FLAGS(%rbp)
505 jne .Lret_int
506
507 mov RVALUE(%rbp), %rcx
508 mov %rax, (%rcx)
509 jmp .Lret_void
510
511 .Lret_int:
512 cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp)
513 jne .Lret_void
514
515 mov RVALUE(%rbp), %rcx
516 cltq
517 movq %rax, (%rcx)
518 jmp .Lret_void
519
520 .Lret_void:
521 xor %rax, %rax
522
523 lea 16(%rbp), %rsp
524 pop %rbp
525 retq
526 .seh_endproc
527 #endif /* !_MSC_VER */
528
|
1 #ifdef __x86_64__
2 #define LIBFFI_ASM
3 #include <fficonfig.h>
4 #include <ffi.h>
5 #include <ffi_cfi.h>
6 #include "asmnames.h"
7
8 #if defined(HAVE_AS_CFI_PSEUDO_OP)
9 .cfi_sections .debug_frame
10 #endif
11
12 #ifdef X86_WIN64
13 #define SEH(...) __VA_ARGS__
14 #define arg0 %rcx
15 #define arg1 %rdx
16 #define arg2 %r8
17 #define arg3 %r9
18 #else
19 #define SEH(...)
20 #define arg0 %rdi
21 #define arg1 %rsi
22 #define arg2 %rdx
23 #define arg3 %rcx
24 #endif
25
26 /* This macro allows the safe creation of jump tables without an
27 actual table. The entry points into the table are all 8 bytes.
28 The use of ORG asserts that we're at the correct location. */
29 /* ??? The clang assembler doesn't handle .org with symbolic expressions. */
30 #if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
31 # define E(BASE, X) .balign 8
32 #else
33 # define E(BASE, X) .balign 8; .org BASE + X * 8
34 #endif
35
36 .text
37
38 /* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10)
39
40 Bit o trickiness here -- FRAME is the base of the stack frame
41 for this function. This has been allocated by ffi_call. We also
42 deallocate some of the stack that has been alloca'd. */
43
44 .align 8
45 .globl C(ffi_call_win64)
46 FFI_HIDDEN(C(ffi_call_win64))
47
48 SEH(.seh_proc ffi_call_win64)
49 C(ffi_call_win64):
50 cfi_startproc
51 /* Set up the local stack frame and install it in rbp/rsp. */
52 movq (%rsp), %rax
53 movq %rbp, (arg1)
54 movq %rax, 8(arg1)
55 movq arg1, %rbp
56 cfi_def_cfa(%rbp, 16)
57 cfi_rel_offset(%rbp, 0)
58 SEH(.seh_pushreg %rbp)
59 SEH(.seh_setframe %rbp, 0)
60 SEH(.seh_endprologue)
61 movq arg0, %rsp
62
63 movq arg2, %r10
64
65 /* Load all slots into both general and xmm registers. */
66 movq (%rsp), %rcx
67 movsd (%rsp), %xmm0
68 movq 8(%rsp), %rdx
69 movsd 8(%rsp), %xmm1
70 movq 16(%rsp), %r8
71 movsd 16(%rsp), %xmm2
72 movq 24(%rsp), %r9
73 movsd 24(%rsp), %xmm3
74
75 call *16(%rbp)
76
77 movl 24(%rbp), %ecx
78 movq 32(%rbp), %r8
79 leaq 0f(%rip), %r10
80 cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx
81 leaq (%r10, %rcx, 8), %r10
82 ja 99f
83 jmp *%r10
84
85 /* Below, we're space constrained most of the time. Thus we eschew the
86 modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */
87 .macro epilogue
88 leaveq
89 cfi_remember_state
90 cfi_def_cfa(%rsp, 8)
91 cfi_restore(%rbp)
92 ret
93 cfi_restore_state
94 .endm
95
96 .align 8
97 0:
98 E(0b, FFI_TYPE_VOID)
99 epilogue
100 E(0b, FFI_TYPE_INT)
101 movslq %eax, %rax
102 movq %rax, (%r8)
103 epilogue
104 E(0b, FFI_TYPE_FLOAT)
105 movss %xmm0, (%r8)
106 epilogue
107 E(0b, FFI_TYPE_DOUBLE)
108 movsd %xmm0, (%r8)
109 epilogue
110 E(0b, FFI_TYPE_LONGDOUBLE)
111 call PLT(C(abort))
112 E(0b, FFI_TYPE_UINT8)
113 movzbl %al, %eax
114 movq %rax, (%r8)
115 epilogue
116 E(0b, FFI_TYPE_SINT8)
117 movsbq %al, %rax
118 jmp 98f
119 E(0b, FFI_TYPE_UINT16)
120 movzwl %ax, %eax
121 movq %rax, (%r8)
122 epilogue
123 E(0b, FFI_TYPE_SINT16)
124 movswq %ax, %rax
125 jmp 98f
126 E(0b, FFI_TYPE_UINT32)
127 movl %eax, %eax
128 movq %rax, (%r8)
129 epilogue
130 E(0b, FFI_TYPE_SINT32)
131 movslq %eax, %rax
132 movq %rax, (%r8)
133 epilogue
134 E(0b, FFI_TYPE_UINT64)
135 98: movq %rax, (%r8)
136 epilogue
137 E(0b, FFI_TYPE_SINT64)
138 movq %rax, (%r8)
139 epilogue
140 E(0b, FFI_TYPE_STRUCT)
141 epilogue
142 E(0b, FFI_TYPE_POINTER)
143 movq %rax, (%r8)
144 epilogue
145 E(0b, FFI_TYPE_COMPLEX)
146 call PLT(C(abort))
147 E(0b, FFI_TYPE_SMALL_STRUCT_1B)
148 movb %al, (%r8)
149 epilogue
150 E(0b, FFI_TYPE_SMALL_STRUCT_2B)
151 movw %ax, (%r8)
152 epilogue
153 E(0b, FFI_TYPE_SMALL_STRUCT_4B)
154 movl %eax, (%r8)
155 epilogue
156
157 .align 8
158 99: call PLT(C(abort))
159
160 epilogue
161
162 cfi_endproc
163 SEH(.seh_endproc)
164
165
166 /* 32 bytes of outgoing register stack space, 8 bytes of alignment,
167 16 bytes of result, 32 bytes of xmm registers. */
168 #define ffi_clo_FS (32+8+16+32)
169 #define ffi_clo_OFF_R (32+8)
170 #define ffi_clo_OFF_X (32+8+16)
171
172 .align 8
173 .globl C(ffi_go_closure_win64)
174 FFI_HIDDEN(C(ffi_go_closure_win64))
175
176 SEH(.seh_proc ffi_go_closure_win64)
177 C(ffi_go_closure_win64):
178 cfi_startproc
179 /* Save all integer arguments into the incoming reg stack space. */
180 movq %rcx, 8(%rsp)
181 movq %rdx, 16(%rsp)
182 movq %r8, 24(%rsp)
183 movq %r9, 32(%rsp)
184
185 movq 8(%r10), %rcx /* load cif */
186 movq 16(%r10), %rdx /* load fun */
187 movq %r10, %r8 /* closure is user_data */
188 jmp 0f
189 cfi_endproc
190 SEH(.seh_endproc)
191
192 .align 8
193 .globl C(ffi_closure_win64)
194 FFI_HIDDEN(C(ffi_closure_win64))
195
196 SEH(.seh_proc ffi_closure_win64)
197 C(ffi_closure_win64):
198 cfi_startproc
199 /* Save all integer arguments into the incoming reg stack space. */
200 movq %rcx, 8(%rsp)
201 movq %rdx, 16(%rsp)
202 movq %r8, 24(%rsp)
203 movq %r9, 32(%rsp)
204
205 movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */
206 movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */
207 movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */
208 0:
209 subq $ffi_clo_FS, %rsp
210 cfi_adjust_cfa_offset(ffi_clo_FS)
211 SEH(.seh_stackalloc ffi_clo_FS)
212 SEH(.seh_endprologue)
213
214 /* Save all sse arguments into the stack frame. */
215 movsd %xmm0, ffi_clo_OFF_X(%rsp)
216 movsd %xmm1, ffi_clo_OFF_X+8(%rsp)
217 movsd %xmm2, ffi_clo_OFF_X+16(%rsp)
218 movsd %xmm3, ffi_clo_OFF_X+24(%rsp)
219
220 leaq ffi_clo_OFF_R(%rsp), %r9
221 call PLT(C(ffi_closure_win64_inner))
222
223 /* Load the result into both possible result registers. */
224 movq ffi_clo_OFF_R(%rsp), %rax
225 movsd ffi_clo_OFF_R(%rsp), %xmm0
226
227 addq $ffi_clo_FS, %rsp
228 cfi_adjust_cfa_offset(-ffi_clo_FS)
229 ret
230
231 cfi_endproc
232 SEH(.seh_endproc)
233 #endif /* __x86_64__ */
234
235 #if defined __ELF__ && defined __linux__
236 .section .note.GNU-stack,"",@progbits
237 #endif
|