7 #if defined(HAVE_AS_CFI_PSEUDO_OP)
8 .cfi_sections .debug_frame
12 #define SEH(...) __VA_ARGS__
25 /* This macro allows the safe creation of jump tables without an
26 actual table. The entry points into the table are all 8 bytes.
27 The use of ORG asserts that we're at the correct location. */
28 /* ??? The clang assembler doesn't handle .org with symbolic expressions. */
29 #if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
30 # define E(BASE, X) ALIGN 8
32 # define E(BASE, X) ALIGN 8; ORG BASE + (X) * 8
36 extern PLT(C(abort)):near
37 extern C(ffi_closure_win64_inner):near
39 /* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10)
41 Bit o trickiness here -- FRAME is the base of the stack frame
42 for this function. This has been allocated by ffi_call. We also
43 deallocate some of the stack that has been alloca'd. */
46 PUBLIC C(ffi_call_win64)
48 ; SEH(.safesh ffi_call_win64)
49 C(ffi_call_win64) proc SEH(frame)
51 /* Set up the local stack frame and install it in rbp/rsp. */
52 mov RAX, [RSP] ; movq (%rsp), %rax
53 mov [arg1], RBP ; movq %rbp, (arg1)
54 mov [arg1 + 8], RAX; movq %rax, 8(arg1)
55 mov RBP, arg1; movq arg1, %rbp
57 cfi_rel_offset(rbp, 0)
61 mov RSP, arg0 ; movq arg0, %rsp
63 mov R10, arg2 ; movq arg2, %r10
65 /* Load all slots into both general and xmm registers. */
66 mov RCX, [RSP] ; movq (%rsp), %rcx
67 movsd XMM0, qword ptr [RSP] ; movsd (%rsp), %xmm0
68 mov RDX, [RSP + 8] ;movq 8(%rsp), %rdx
69 movsd XMM1, qword ptr [RSP + 8]; movsd 8(%rsp), %xmm1
70 mov R8, [RSP + 16] ; movq 16(%rsp), %r8
71 movsd XMM2, qword ptr [RSP + 16] ; movsd 16(%rsp), %xmm2
72 mov R9, [RSP + 24] ; movq 24(%rsp), %r9
73 movsd XMM3, qword ptr [RSP + 24] ;movsd 24(%rsp), %xmm3
75 CALL qword ptr [RBP + 16] ; call *16(%rbp)
77 mov ECX, [RBP + 24] ; movl 24(%rbp), %ecx
78 mov R8, [RBP + 32] ; movq 32(%rbp), %r8
79 LEA R10, ffi_call_win64_tab ; leaq 0f(%rip), %r10
80 CMP ECX, FFI_TYPE_SMALL_STRUCT_4B ; cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx
81 LEA R10, [R10 + RCX*8] ; leaq (%r10, %rcx, 8), %r10
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). */
97 ffi_call_win64_tab LABEL NEAR
101 movsxd rax, eax ; movslq %eax, %rax
102 mov qword ptr [r8], rax; movq %rax, (%r8)
104 E(0b, FFI_TYPE_FLOAT)
105 movss dword ptr [r8], xmm0 ; movss %xmm0, (%r8)
107 E(0b, FFI_TYPE_DOUBLE)
108 movsd qword ptr[r8], xmm0; movsd %xmm0, (%r8)
110 // FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here.
111 E(0b, FFI_TYPE_DOUBLE + 1)
113 E(0b, FFI_TYPE_UINT8)
114 movzx eax, al ;movzbl %al, %eax
115 mov qword ptr[r8], rax; movq %rax, (%r8)
117 E(0b, FFI_TYPE_SINT8)
118 movsx rax, al ; movsbq %al, %rax
120 E(0b, FFI_TYPE_UINT16)
121 movzx eax, ax ; movzwl %ax, %eax
122 mov qword ptr[r8], rax; movq %rax, (%r8)
124 E(0b, FFI_TYPE_SINT16)
125 movsx rax, ax; movswq %ax, %rax
127 E(0b, FFI_TYPE_UINT32)
128 mov eax, eax; movl %eax, %eax
129 mov qword ptr[r8], rax ; movq %rax, (%r8)
131 E(0b, FFI_TYPE_SINT32)
132 movsxd rax, eax; movslq %eax, %rax
133 mov qword ptr [r8], rax; movq %rax, (%r8)
135 E(0b, FFI_TYPE_UINT64)
137 mov qword ptr [r8], rax ; movq %rax, (%r8)
139 E(0b, FFI_TYPE_SINT64)
140 mov qword ptr [r8], rax;movq %rax, (%r8)
142 E(0b, FFI_TYPE_STRUCT)
144 E(0b, FFI_TYPE_POINTER)
145 mov qword ptr [r8], rax ;movq %rax, (%r8)
147 E(0b, FFI_TYPE_COMPLEX)
149 E(0b, FFI_TYPE_SMALL_STRUCT_1B)
150 mov byte ptr [r8], al ; movb %al, (%r8)
152 E(0b, FFI_TYPE_SMALL_STRUCT_2B)
153 mov word ptr [r8], ax ; movw %ax, (%r8)
155 E(0b, FFI_TYPE_SMALL_STRUCT_4B)
156 mov dword ptr [r8], eax ; movl %eax, (%r8)
166 C(ffi_call_win64) endp
169 /* 32 bytes of outgoing register stack space, 8 bytes of alignment,
170 16 bytes of result, 32 bytes of xmm registers. */
171 #define ffi_clo_FS (32+8+16+32)
172 #define ffi_clo_OFF_R (32+8)
173 #define ffi_clo_OFF_X (32+8+16)
176 PUBLIC C(ffi_go_closure_win64)
178 C(ffi_go_closure_win64) proc
180 /* Save all integer arguments into the incoming reg stack space. */
181 mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp)
182 mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp)
183 mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp)
184 mov qword ptr [rsp + 32], r9 ;movq %r9, 32(%rsp)
186 mov rcx, qword ptr [r10 + 8]; movq 8(%r10), %rcx /* load cif */
187 mov rdx, qword ptr [r10 + 16]; movq 16(%r10), %rdx /* load fun */
188 mov r8, r10 ; movq %r10, %r8 /* closure is user_data */
189 jmp ffi_closure_win64_2
191 C(ffi_go_closure_win64) endp
195 PUBLIC C(ffi_closure_win64)
196 C(ffi_closure_win64) PROC FRAME
198 /* Save all integer arguments into the incoming reg stack space. */
199 mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp)
200 mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp)
201 mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp)
202 mov qword ptr [rsp + 32], r9; movq %r9, 32(%rsp)
204 mov rcx, qword ptr [FFI_TRAMPOLINE_SIZE + r10] ;movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */
205 mov rdx, qword ptr [FFI_TRAMPOLINE_SIZE + 8 + r10] ; movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */
206 mov r8, qword ptr [FFI_TRAMPOLINE_SIZE+16+r10] ;movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */
207 ffi_closure_win64_2 LABEL near
208 sub rsp, ffi_clo_FS ;subq $ffi_clo_FS, %rsp
209 cfi_adjust_cfa_offset(ffi_clo_FS)
210 SEH(.allocstack ffi_clo_FS)
213 /* Save all sse arguments into the stack frame. */
214 movsd qword ptr [ffi_clo_OFF_X + rsp], xmm0 ; movsd %xmm0, ffi_clo_OFF_X(%rsp)
215 movsd qword ptr [ffi_clo_OFF_X+8+rsp], xmm1 ; movsd %xmm1, ffi_clo_OFF_X+8(%rsp)
216 movsd qword ptr [ffi_clo_OFF_X+16+rsp], xmm2 ; movsd %xmm2, ffi_clo_OFF_X+16(%rsp)
217 movsd qword ptr [ffi_clo_OFF_X+24+rsp], xmm3 ; movsd %xmm3, ffi_clo_OFF_X+24(%rsp)
219 lea r9, [ffi_clo_OFF_R + rsp] ; leaq ffi_clo_OFF_R(%rsp), %r9
220 call C(ffi_closure_win64_inner)
222 /* Load the result into both possible result registers. */
224 mov rax, qword ptr [ffi_clo_OFF_R + rsp] ;movq ffi_clo_OFF_R(%rsp), %rax
225 movsd xmm0, qword ptr [rsp + ffi_clo_OFF_R] ;movsd ffi_clo_OFF_R(%rsp), %xmm0
227 add rsp, ffi_clo_FS ;addq $ffi_clo_FS, %rsp
228 cfi_adjust_cfa_offset(-ffi_clo_FS)
232 C(ffi_closure_win64) endp
234 #if defined __ELF__ && defined __linux__
235 .section .note.GNU-stack,"",@progbits