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