• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
49C(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
970:
98E(0b, FFI_TYPE_VOID)
99	epilogue
100E(0b, FFI_TYPE_INT)
101	movslq	%eax, %rax
102	movq	%rax, (%r8)
103	epilogue
104E(0b, FFI_TYPE_FLOAT)
105	movss	%xmm0, (%r8)
106	epilogue
107E(0b, FFI_TYPE_DOUBLE)
108	movsd	%xmm0, (%r8)
109	epilogue
110E(0b, FFI_TYPE_LONGDOUBLE)
111	call	PLT(C(abort))
112E(0b, FFI_TYPE_UINT8)
113	movzbl	%al, %eax
114	movq	%rax, (%r8)
115	epilogue
116E(0b, FFI_TYPE_SINT8)
117	movsbq	%al, %rax
118	jmp	98f
119E(0b, FFI_TYPE_UINT16)
120	movzwl	%ax, %eax
121	movq	%rax, (%r8)
122	epilogue
123E(0b, FFI_TYPE_SINT16)
124	movswq	%ax, %rax
125	jmp	98f
126E(0b, FFI_TYPE_UINT32)
127	movl	%eax, %eax
128	movq	%rax, (%r8)
129	epilogue
130E(0b, FFI_TYPE_SINT32)
131	movslq	%eax, %rax
132	movq	%rax, (%r8)
133	epilogue
134E(0b, FFI_TYPE_UINT64)
13598:	movq	%rax, (%r8)
136	epilogue
137E(0b, FFI_TYPE_SINT64)
138	movq	%rax, (%r8)
139	epilogue
140E(0b, FFI_TYPE_STRUCT)
141	epilogue
142E(0b, FFI_TYPE_POINTER)
143	movq	%rax, (%r8)
144	epilogue
145E(0b, FFI_TYPE_COMPLEX)
146	call	PLT(C(abort))
147E(0b, FFI_TYPE_SMALL_STRUCT_1B)
148	movb	%al, (%r8)
149	epilogue
150E(0b, FFI_TYPE_SMALL_STRUCT_2B)
151	movw	%ax, (%r8)
152	epilogue
153E(0b, FFI_TYPE_SMALL_STRUCT_4B)
154	movl	%eax, (%r8)
155	epilogue
156
157	.align	8
15899:	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)
177C(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)
197C(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 */
2080:
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
238