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