]> git.ipfire.org Git - thirdparty/gcc.git/blame - libffi/src/x86/win64.S
libffi: Sync with libffi 3.4.2
[thirdparty/gcc.git] / libffi / src / x86 / win64.S
CommitLineData
92456a4e 1#ifdef __x86_64__
062b8279
AH
2#define LIBFFI_ASM
3#include <fficonfig.h>
4#include <ffi.h>
b1760f7f 5#include <ffi_cfi.h>
92456a4e 6#include "asmnames.h"
54fde020 7
b1760f7f
RH
8#if defined(HAVE_AS_CFI_PSEUDO_OP)
9 .cfi_sections .debug_frame
10#endif
34fa7690 11
92456a4e
L
12#ifdef X86_WIN64
13#define SEH(...) __VA_ARGS__
b1760f7f
RH
14#define arg0 %rcx
15#define arg1 %rdx
16#define arg2 %r8
17#define arg3 %r9
34fa7690 18#else
92456a4e
L
19#define SEH(...)
20#define arg0 %rdi
21#define arg1 %rsi
22#define arg2 %rdx
23#define arg3 %rcx
34fa7690
AG
24#endif
25
92456a4e
L
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
b1760f7f
RH
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
92456a4e
L
45 .globl C(ffi_call_win64)
46 FFI_HIDDEN(C(ffi_call_win64))
b1760f7f 47
92456a4e
L
48 SEH(.seh_proc ffi_call_win64)
49C(ffi_call_win64):
b1760f7f 50 cfi_startproc
92456a4e 51 _CET_ENDBR
b1760f7f
RH
52 /* Set up the local stack frame and install it in rbp/rsp. */
53 movq (%rsp), %rax
54 movq %rbp, (arg1)
55 movq %rax, 8(arg1)
56 movq arg1, %rbp
57 cfi_def_cfa(%rbp, 16)
58 cfi_rel_offset(%rbp, 0)
92456a4e
L
59 SEH(.seh_pushreg %rbp)
60 SEH(.seh_setframe %rbp, 0)
61 SEH(.seh_endprologue)
b1760f7f
RH
62 movq arg0, %rsp
63
64 movq arg2, %r10
65
66 /* Load all slots into both general and xmm registers. */
67 movq (%rsp), %rcx
68 movsd (%rsp), %xmm0
69 movq 8(%rsp), %rdx
70 movsd 8(%rsp), %xmm1
71 movq 16(%rsp), %r8
72 movsd 16(%rsp), %xmm2
73 movq 24(%rsp), %r9
74 movsd 24(%rsp), %xmm3
75
76 call *16(%rbp)
77
78 movl 24(%rbp), %ecx
79 movq 32(%rbp), %r8
80 leaq 0f(%rip), %r10
81 cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx
82 leaq (%r10, %rcx, 8), %r10
83 ja 99f
92456a4e 84 _CET_NOTRACK jmp *%r10
b1760f7f
RH
85
86/* Below, we're space constrained most of the time. Thus we eschew the
87 modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */
88.macro epilogue
89 leaveq
90 cfi_remember_state
91 cfi_def_cfa(%rsp, 8)
92 cfi_restore(%rbp)
93 ret
94 cfi_restore_state
95.endm
96
97 .align 8
980:
92456a4e 99E(0b, FFI_TYPE_VOID)
b1760f7f 100 epilogue
92456a4e 101E(0b, FFI_TYPE_INT)
b1760f7f
RH
102 movslq %eax, %rax
103 movq %rax, (%r8)
104 epilogue
92456a4e 105E(0b, FFI_TYPE_FLOAT)
b1760f7f
RH
106 movss %xmm0, (%r8)
107 epilogue
92456a4e 108E(0b, FFI_TYPE_DOUBLE)
b1760f7f
RH
109 movsd %xmm0, (%r8)
110 epilogue
92456a4e
L
111// FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here.
112E(0b, FFI_TYPE_DOUBLE + 1)
113 call PLT(C(abort))
114E(0b, FFI_TYPE_UINT8)
b1760f7f
RH
115 movzbl %al, %eax
116 movq %rax, (%r8)
117 epilogue
92456a4e 118E(0b, FFI_TYPE_SINT8)
b1760f7f
RH
119 movsbq %al, %rax
120 jmp 98f
92456a4e 121E(0b, FFI_TYPE_UINT16)
b1760f7f
RH
122 movzwl %ax, %eax
123 movq %rax, (%r8)
124 epilogue
92456a4e 125E(0b, FFI_TYPE_SINT16)
b1760f7f
RH
126 movswq %ax, %rax
127 jmp 98f
92456a4e 128E(0b, FFI_TYPE_UINT32)
b1760f7f
RH
129 movl %eax, %eax
130 movq %rax, (%r8)
131 epilogue
92456a4e 132E(0b, FFI_TYPE_SINT32)
b1760f7f
RH
133 movslq %eax, %rax
134 movq %rax, (%r8)
135 epilogue
92456a4e 136E(0b, FFI_TYPE_UINT64)
b1760f7f
RH
13798: movq %rax, (%r8)
138 epilogue
92456a4e 139E(0b, FFI_TYPE_SINT64)
b1760f7f
RH
140 movq %rax, (%r8)
141 epilogue
92456a4e 142E(0b, FFI_TYPE_STRUCT)
b1760f7f 143 epilogue
92456a4e 144E(0b, FFI_TYPE_POINTER)
b1760f7f
RH
145 movq %rax, (%r8)
146 epilogue
92456a4e
L
147E(0b, FFI_TYPE_COMPLEX)
148 call PLT(C(abort))
149E(0b, FFI_TYPE_SMALL_STRUCT_1B)
b1760f7f
RH
150 movb %al, (%r8)
151 epilogue
92456a4e 152E(0b, FFI_TYPE_SMALL_STRUCT_2B)
b1760f7f
RH
153 movw %ax, (%r8)
154 epilogue
92456a4e 155E(0b, FFI_TYPE_SMALL_STRUCT_4B)
b1760f7f
RH
156 movl %eax, (%r8)
157 epilogue
158
159 .align 8
92456a4e 16099: call PLT(C(abort))
b1760f7f 161
92456a4e 162 epilogue
b1760f7f
RH
163
164 cfi_endproc
92456a4e 165 SEH(.seh_endproc)
062b8279 166
54fde020 167
b1760f7f
RH
168/* 32 bytes of outgoing register stack space, 8 bytes of alignment,
169 16 bytes of result, 32 bytes of xmm registers. */
170#define ffi_clo_FS (32+8+16+32)
171#define ffi_clo_OFF_R (32+8)
172#define ffi_clo_OFF_X (32+8+16)
173
174 .align 8
92456a4e
L
175 .globl C(ffi_go_closure_win64)
176 FFI_HIDDEN(C(ffi_go_closure_win64))
b1760f7f 177
92456a4e
L
178 SEH(.seh_proc ffi_go_closure_win64)
179C(ffi_go_closure_win64):
b1760f7f 180 cfi_startproc
92456a4e 181 _CET_ENDBR
b1760f7f 182 /* Save all integer arguments into the incoming reg stack space. */
92456a4e
L
183 movq %rcx, 8(%rsp)
184 movq %rdx, 16(%rsp)
185 movq %r8, 24(%rsp)
186 movq %r9, 32(%rsp)
187
188 movq 8(%r10), %rcx /* load cif */
189 movq 16(%r10), %rdx /* load fun */
190 movq %r10, %r8 /* closure is user_data */
b1760f7f
RH
191 jmp 0f
192 cfi_endproc
92456a4e 193 SEH(.seh_endproc)
54fde020 194
b1760f7f 195 .align 8
92456a4e
L
196 .globl C(ffi_closure_win64)
197 FFI_HIDDEN(C(ffi_closure_win64))
b1760f7f 198
92456a4e
L
199 SEH(.seh_proc ffi_closure_win64)
200C(ffi_closure_win64):
b1760f7f 201 cfi_startproc
92456a4e 202 _CET_ENDBR
b1760f7f 203 /* Save all integer arguments into the incoming reg stack space. */
92456a4e
L
204 movq %rcx, 8(%rsp)
205 movq %rdx, 16(%rsp)
206 movq %r8, 24(%rsp)
207 movq %r9, 32(%rsp)
208
209 movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */
210 movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */
211 movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */
b1760f7f
RH
2120:
213 subq $ffi_clo_FS, %rsp
214 cfi_adjust_cfa_offset(ffi_clo_FS)
92456a4e
L
215 SEH(.seh_stackalloc ffi_clo_FS)
216 SEH(.seh_endprologue)
062b8279 217
b1760f7f
RH
218 /* Save all sse arguments into the stack frame. */
219 movsd %xmm0, ffi_clo_OFF_X(%rsp)
220 movsd %xmm1, ffi_clo_OFF_X+8(%rsp)
221 movsd %xmm2, ffi_clo_OFF_X+16(%rsp)
222 movsd %xmm3, ffi_clo_OFF_X+24(%rsp)
54fde020 223
92456a4e
L
224 leaq ffi_clo_OFF_R(%rsp), %r9
225 call PLT(C(ffi_closure_win64_inner))
54fde020 226
b1760f7f
RH
227 /* Load the result into both possible result registers. */
228 movq ffi_clo_OFF_R(%rsp), %rax
229 movsd ffi_clo_OFF_R(%rsp), %xmm0
54fde020 230
b1760f7f
RH
231 addq $ffi_clo_FS, %rsp
232 cfi_adjust_cfa_offset(-ffi_clo_FS)
233 ret
062b8279 234
b1760f7f 235 cfi_endproc
92456a4e
L
236 SEH(.seh_endproc)
237
238#if defined(FFI_EXEC_STATIC_TRAMP)
239 .align 8
240 .globl C(ffi_closure_win64_alt)
241 FFI_HIDDEN(C(ffi_closure_win64_alt))
242
243 SEH(.seh_proc ffi_closure_win64_alt)
244C(ffi_closure_win64_alt):
245 _CET_ENDBR
246 movq 8(%rsp), %r10
247 addq $16, %rsp
248 jmp C(ffi_closure_win64)
249 SEH(.seh_endproc)
250#endif
251#endif /* __x86_64__ */
252
253#if defined __ELF__ && defined __linux__
254 .section .note.GNU-stack,"",@progbits
255#endif