1*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM 2*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h> 3*1fd5a2e1SPrashanth Swaminathan#include <ffi.h> 4*1fd5a2e1SPrashanth Swaminathan#include <ffi_cfi.h> 5*1fd5a2e1SPrashanth Swaminathan#include "asmnames.h" 6*1fd5a2e1SPrashanth Swaminathan 7*1fd5a2e1SPrashanth Swaminathan#if defined(HAVE_AS_CFI_PSEUDO_OP) 8*1fd5a2e1SPrashanth Swaminathan .cfi_sections .debug_frame 9*1fd5a2e1SPrashanth Swaminathan#endif 10*1fd5a2e1SPrashanth Swaminathan 11*1fd5a2e1SPrashanth Swaminathan#ifdef X86_WIN64 12*1fd5a2e1SPrashanth Swaminathan#define SEH(...) __VA_ARGS__ 13*1fd5a2e1SPrashanth Swaminathan#define arg0 rcx 14*1fd5a2e1SPrashanth Swaminathan#define arg1 rdx 15*1fd5a2e1SPrashanth Swaminathan#define arg2 r8 16*1fd5a2e1SPrashanth Swaminathan#define arg3 r9 17*1fd5a2e1SPrashanth Swaminathan#else 18*1fd5a2e1SPrashanth Swaminathan#define SEH(...) 19*1fd5a2e1SPrashanth Swaminathan#define arg0 rdi 20*1fd5a2e1SPrashanth Swaminathan#define arg1 rsi 21*1fd5a2e1SPrashanth Swaminathan#define arg2 rdx 22*1fd5a2e1SPrashanth Swaminathan#define arg3 rcx 23*1fd5a2e1SPrashanth Swaminathan#endif 24*1fd5a2e1SPrashanth Swaminathan 25*1fd5a2e1SPrashanth Swaminathan/* This macro allows the safe creation of jump tables without an 26*1fd5a2e1SPrashanth Swaminathan actual table. The entry points into the table are all 8 bytes. 27*1fd5a2e1SPrashanth Swaminathan The use of ORG asserts that we're at the correct location. */ 28*1fd5a2e1SPrashanth Swaminathan/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ 29*1fd5a2e1SPrashanth Swaminathan#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) 30*1fd5a2e1SPrashanth Swaminathan# define E(BASE, X) ALIGN 8 31*1fd5a2e1SPrashanth Swaminathan#else 32*1fd5a2e1SPrashanth Swaminathan# define E(BASE, X) ALIGN 8; ORG BASE + X * 8 33*1fd5a2e1SPrashanth Swaminathan#endif 34*1fd5a2e1SPrashanth Swaminathan 35*1fd5a2e1SPrashanth Swaminathan .CODE 36*1fd5a2e1SPrashanth Swaminathan extern PLT(C(abort)):near 37*1fd5a2e1SPrashanth Swaminathan extern C(ffi_closure_win64_inner):near 38*1fd5a2e1SPrashanth Swaminathan 39*1fd5a2e1SPrashanth Swaminathan/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10) 40*1fd5a2e1SPrashanth Swaminathan 41*1fd5a2e1SPrashanth Swaminathan Bit o trickiness here -- FRAME is the base of the stack frame 42*1fd5a2e1SPrashanth Swaminathan for this function. This has been allocated by ffi_call. We also 43*1fd5a2e1SPrashanth Swaminathan deallocate some of the stack that has been alloca'd. */ 44*1fd5a2e1SPrashanth Swaminathan 45*1fd5a2e1SPrashanth Swaminathan ALIGN 8 46*1fd5a2e1SPrashanth Swaminathan PUBLIC C(ffi_call_win64) 47*1fd5a2e1SPrashanth Swaminathan 48*1fd5a2e1SPrashanth Swaminathan ; SEH(.safesh ffi_call_win64) 49*1fd5a2e1SPrashanth SwaminathanC(ffi_call_win64) proc SEH(frame) 50*1fd5a2e1SPrashanth Swaminathan cfi_startproc 51*1fd5a2e1SPrashanth Swaminathan /* Set up the local stack frame and install it in rbp/rsp. */ 52*1fd5a2e1SPrashanth Swaminathan mov RAX, [RSP] ; movq (%rsp), %rax 53*1fd5a2e1SPrashanth Swaminathan mov [arg1], RBP ; movq %rbp, (arg1) 54*1fd5a2e1SPrashanth Swaminathan mov [arg1 + 8], RAX; movq %rax, 8(arg1) 55*1fd5a2e1SPrashanth Swaminathan mov RBP, arg1; movq arg1, %rbp 56*1fd5a2e1SPrashanth Swaminathan cfi_def_cfa(rbp, 16) 57*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(rbp, 0) 58*1fd5a2e1SPrashanth Swaminathan SEH(.pushreg rbp) 59*1fd5a2e1SPrashanth Swaminathan SEH(.setframe rbp, 0) 60*1fd5a2e1SPrashanth Swaminathan SEH(.endprolog) 61*1fd5a2e1SPrashanth Swaminathan mov RSP, arg0 ; movq arg0, %rsp 62*1fd5a2e1SPrashanth Swaminathan 63*1fd5a2e1SPrashanth Swaminathan mov R10, arg2 ; movq arg2, %r10 64*1fd5a2e1SPrashanth Swaminathan 65*1fd5a2e1SPrashanth Swaminathan /* Load all slots into both general and xmm registers. */ 66*1fd5a2e1SPrashanth Swaminathan mov RCX, [RSP] ; movq (%rsp), %rcx 67*1fd5a2e1SPrashanth Swaminathan movsd XMM0, qword ptr [RSP] ; movsd (%rsp), %xmm0 68*1fd5a2e1SPrashanth Swaminathan mov RDX, [RSP + 8] ;movq 8(%rsp), %rdx 69*1fd5a2e1SPrashanth Swaminathan movsd XMM1, qword ptr [RSP + 8]; movsd 8(%rsp), %xmm1 70*1fd5a2e1SPrashanth Swaminathan mov R8, [RSP + 16] ; movq 16(%rsp), %r8 71*1fd5a2e1SPrashanth Swaminathan movsd XMM2, qword ptr [RSP + 16] ; movsd 16(%rsp), %xmm2 72*1fd5a2e1SPrashanth Swaminathan mov R9, [RSP + 24] ; movq 24(%rsp), %r9 73*1fd5a2e1SPrashanth Swaminathan movsd XMM3, qword ptr [RSP + 24] ;movsd 24(%rsp), %xmm3 74*1fd5a2e1SPrashanth Swaminathan 75*1fd5a2e1SPrashanth Swaminathan CALL qword ptr [RBP + 16] ; call *16(%rbp) 76*1fd5a2e1SPrashanth Swaminathan 77*1fd5a2e1SPrashanth Swaminathan mov ECX, [RBP + 24] ; movl 24(%rbp), %ecx 78*1fd5a2e1SPrashanth Swaminathan mov R8, [RBP + 32] ; movq 32(%rbp), %r8 79*1fd5a2e1SPrashanth Swaminathan LEA R10, ffi_call_win64_tab ; leaq 0f(%rip), %r10 80*1fd5a2e1SPrashanth Swaminathan CMP ECX, FFI_TYPE_SMALL_STRUCT_4B ; cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx 81*1fd5a2e1SPrashanth Swaminathan LEA R10, [R10 + RCX*8] ; leaq (%r10, %rcx, 8), %r10 82*1fd5a2e1SPrashanth Swaminathan JA L99 ; ja 99f 83*1fd5a2e1SPrashanth Swaminathan JMP R10 ; jmp *%r10 84*1fd5a2e1SPrashanth Swaminathan 85*1fd5a2e1SPrashanth Swaminathan/* Below, we're space constrained most of the time. Thus we eschew the 86*1fd5a2e1SPrashanth Swaminathan modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */ 87*1fd5a2e1SPrashanth Swaminathanepilogue macro 88*1fd5a2e1SPrashanth Swaminathan LEAVE 89*1fd5a2e1SPrashanth Swaminathan cfi_remember_state 90*1fd5a2e1SPrashanth Swaminathan cfi_def_cfa(rsp, 8) 91*1fd5a2e1SPrashanth Swaminathan cfi_restore(rbp) 92*1fd5a2e1SPrashanth Swaminathan RET 93*1fd5a2e1SPrashanth Swaminathan cfi_restore_state 94*1fd5a2e1SPrashanth Swaminathanendm 95*1fd5a2e1SPrashanth Swaminathan 96*1fd5a2e1SPrashanth Swaminathan ALIGN 8 97*1fd5a2e1SPrashanth Swaminathanffi_call_win64_tab LABEL NEAR 98*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_VOID) 99*1fd5a2e1SPrashanth Swaminathan epilogue 100*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_INT) 101*1fd5a2e1SPrashanth Swaminathan movsxd rax, eax ; movslq %eax, %rax 102*1fd5a2e1SPrashanth Swaminathan mov qword ptr [r8], rax; movq %rax, (%r8) 103*1fd5a2e1SPrashanth Swaminathan epilogue 104*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_FLOAT) 105*1fd5a2e1SPrashanth Swaminathan movss dword ptr [r8], xmm0 ; movss %xmm0, (%r8) 106*1fd5a2e1SPrashanth Swaminathan epilogue 107*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_DOUBLE) 108*1fd5a2e1SPrashanth Swaminathan movsd qword ptr[r8], xmm0; movsd %xmm0, (%r8) 109*1fd5a2e1SPrashanth Swaminathan epilogue 110*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_LONGDOUBLE) 111*1fd5a2e1SPrashanth Swaminathan call PLT(C(abort)) 112*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_UINT8) 113*1fd5a2e1SPrashanth Swaminathan movzx eax, al ;movzbl %al, %eax 114*1fd5a2e1SPrashanth Swaminathan mov qword ptr[r8], rax; movq %rax, (%r8) 115*1fd5a2e1SPrashanth Swaminathan epilogue 116*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SINT8) 117*1fd5a2e1SPrashanth Swaminathan movsx rax, al ; movsbq %al, %rax 118*1fd5a2e1SPrashanth Swaminathan jmp L98 119*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_UINT16) 120*1fd5a2e1SPrashanth Swaminathan movzx eax, ax ; movzwl %ax, %eax 121*1fd5a2e1SPrashanth Swaminathan mov qword ptr[r8], rax; movq %rax, (%r8) 122*1fd5a2e1SPrashanth Swaminathan epilogue 123*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SINT16) 124*1fd5a2e1SPrashanth Swaminathan movsx rax, ax; movswq %ax, %rax 125*1fd5a2e1SPrashanth Swaminathan jmp L98 126*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_UINT32) 127*1fd5a2e1SPrashanth Swaminathan mov eax, eax; movl %eax, %eax 128*1fd5a2e1SPrashanth Swaminathan mov qword ptr[r8], rax ; movq %rax, (%r8) 129*1fd5a2e1SPrashanth Swaminathan epilogue 130*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SINT32) 131*1fd5a2e1SPrashanth Swaminathan movsxd rax, eax; movslq %eax, %rax 132*1fd5a2e1SPrashanth Swaminathan mov qword ptr [r8], rax; movq %rax, (%r8) 133*1fd5a2e1SPrashanth Swaminathan epilogue 134*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_UINT64) 135*1fd5a2e1SPrashanth SwaminathanL98 LABEL near 136*1fd5a2e1SPrashanth Swaminathan mov qword ptr [r8], rax ; movq %rax, (%r8) 137*1fd5a2e1SPrashanth Swaminathan epilogue 138*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SINT64) 139*1fd5a2e1SPrashanth Swaminathan mov qword ptr [r8], rax;movq %rax, (%r8) 140*1fd5a2e1SPrashanth Swaminathan epilogue 141*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_STRUCT) 142*1fd5a2e1SPrashanth Swaminathan epilogue 143*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_POINTER) 144*1fd5a2e1SPrashanth Swaminathan mov qword ptr [r8], rax ;movq %rax, (%r8) 145*1fd5a2e1SPrashanth Swaminathan epilogue 146*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_COMPLEX) 147*1fd5a2e1SPrashanth Swaminathan call PLT(C(abort)) 148*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SMALL_STRUCT_1B) 149*1fd5a2e1SPrashanth Swaminathan mov byte ptr [r8], al ; movb %al, (%r8) 150*1fd5a2e1SPrashanth Swaminathan epilogue 151*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SMALL_STRUCT_2B) 152*1fd5a2e1SPrashanth Swaminathan mov word ptr [r8], ax ; movw %ax, (%r8) 153*1fd5a2e1SPrashanth Swaminathan epilogue 154*1fd5a2e1SPrashanth SwaminathanE(0b, FFI_TYPE_SMALL_STRUCT_4B) 155*1fd5a2e1SPrashanth Swaminathan mov dword ptr [r8], eax ; movl %eax, (%r8) 156*1fd5a2e1SPrashanth Swaminathan epilogue 157*1fd5a2e1SPrashanth Swaminathan 158*1fd5a2e1SPrashanth Swaminathan align 8 159*1fd5a2e1SPrashanth SwaminathanL99 LABEL near 160*1fd5a2e1SPrashanth Swaminathan call PLT(C(abort)) 161*1fd5a2e1SPrashanth Swaminathan 162*1fd5a2e1SPrashanth Swaminathan epilogue 163*1fd5a2e1SPrashanth Swaminathan 164*1fd5a2e1SPrashanth Swaminathan cfi_endproc 165*1fd5a2e1SPrashanth Swaminathan C(ffi_call_win64) endp 166*1fd5a2e1SPrashanth Swaminathan 167*1fd5a2e1SPrashanth Swaminathan 168*1fd5a2e1SPrashanth Swaminathan/* 32 bytes of outgoing register stack space, 8 bytes of alignment, 169*1fd5a2e1SPrashanth Swaminathan 16 bytes of result, 32 bytes of xmm registers. */ 170*1fd5a2e1SPrashanth Swaminathan#define ffi_clo_FS (32+8+16+32) 171*1fd5a2e1SPrashanth Swaminathan#define ffi_clo_OFF_R (32+8) 172*1fd5a2e1SPrashanth Swaminathan#define ffi_clo_OFF_X (32+8+16) 173*1fd5a2e1SPrashanth Swaminathan 174*1fd5a2e1SPrashanth Swaminathan align 8 175*1fd5a2e1SPrashanth Swaminathan PUBLIC C(ffi_go_closure_win64) 176*1fd5a2e1SPrashanth Swaminathan 177*1fd5a2e1SPrashanth SwaminathanC(ffi_go_closure_win64) proc 178*1fd5a2e1SPrashanth Swaminathan cfi_startproc 179*1fd5a2e1SPrashanth Swaminathan /* Save all integer arguments into the incoming reg stack space. */ 180*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) 181*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) 182*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) 183*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 32], r9 ;movq %r9, 32(%rsp) 184*1fd5a2e1SPrashanth Swaminathan 185*1fd5a2e1SPrashanth Swaminathan mov rcx, qword ptr [r10 + 8]; movq 8(%r10), %rcx /* load cif */ 186*1fd5a2e1SPrashanth Swaminathan mov rdx, qword ptr [r10 + 16]; movq 16(%r10), %rdx /* load fun */ 187*1fd5a2e1SPrashanth Swaminathan mov r8, r10 ; movq %r10, %r8 /* closure is user_data */ 188*1fd5a2e1SPrashanth Swaminathan jmp ffi_closure_win64_2 189*1fd5a2e1SPrashanth Swaminathan cfi_endproc 190*1fd5a2e1SPrashanth Swaminathan C(ffi_go_closure_win64) endp 191*1fd5a2e1SPrashanth Swaminathan 192*1fd5a2e1SPrashanth Swaminathan align 8 193*1fd5a2e1SPrashanth Swaminathan 194*1fd5a2e1SPrashanth SwaminathanPUBLIC C(ffi_closure_win64) 195*1fd5a2e1SPrashanth SwaminathanC(ffi_closure_win64) PROC FRAME 196*1fd5a2e1SPrashanth Swaminathan cfi_startproc 197*1fd5a2e1SPrashanth Swaminathan /* Save all integer arguments into the incoming reg stack space. */ 198*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) 199*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) 200*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) 201*1fd5a2e1SPrashanth Swaminathan mov qword ptr [rsp + 32], r9; movq %r9, 32(%rsp) 202*1fd5a2e1SPrashanth Swaminathan 203*1fd5a2e1SPrashanth Swaminathan mov rcx, qword ptr [FFI_TRAMPOLINE_SIZE + r10] ;movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */ 204*1fd5a2e1SPrashanth Swaminathan mov rdx, qword ptr [FFI_TRAMPOLINE_SIZE + 8 + r10] ; movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */ 205*1fd5a2e1SPrashanth Swaminathan mov r8, qword ptr [FFI_TRAMPOLINE_SIZE+16+r10] ;movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */ 206*1fd5a2e1SPrashanth Swaminathanffi_closure_win64_2 LABEL near 207*1fd5a2e1SPrashanth Swaminathan sub rsp, ffi_clo_FS ;subq $ffi_clo_FS, %rsp 208*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(ffi_clo_FS) 209*1fd5a2e1SPrashanth Swaminathan SEH(.allocstack ffi_clo_FS) 210*1fd5a2e1SPrashanth Swaminathan SEH(.endprolog) 211*1fd5a2e1SPrashanth Swaminathan 212*1fd5a2e1SPrashanth Swaminathan /* Save all sse arguments into the stack frame. */ 213*1fd5a2e1SPrashanth Swaminathan movsd qword ptr [ffi_clo_OFF_X + rsp], xmm0 ; movsd %xmm0, ffi_clo_OFF_X(%rsp) 214*1fd5a2e1SPrashanth Swaminathan movsd qword ptr [ffi_clo_OFF_X+8+rsp], xmm1 ; movsd %xmm1, ffi_clo_OFF_X+8(%rsp) 215*1fd5a2e1SPrashanth Swaminathan movsd qword ptr [ffi_clo_OFF_X+16+rsp], xmm2 ; movsd %xmm2, ffi_clo_OFF_X+16(%rsp) 216*1fd5a2e1SPrashanth Swaminathan movsd qword ptr [ffi_clo_OFF_X+24+rsp], xmm3 ; movsd %xmm3, ffi_clo_OFF_X+24(%rsp) 217*1fd5a2e1SPrashanth Swaminathan 218*1fd5a2e1SPrashanth Swaminathan lea r9, [ffi_clo_OFF_R + rsp] ; leaq ffi_clo_OFF_R(%rsp), %r9 219*1fd5a2e1SPrashanth Swaminathan call C(ffi_closure_win64_inner) 220*1fd5a2e1SPrashanth Swaminathan 221*1fd5a2e1SPrashanth Swaminathan /* Load the result into both possible result registers. */ 222*1fd5a2e1SPrashanth Swaminathan 223*1fd5a2e1SPrashanth Swaminathan mov rax, qword ptr [ffi_clo_OFF_R + rsp] ;movq ffi_clo_OFF_R(%rsp), %rax 224*1fd5a2e1SPrashanth Swaminathan movsd xmm0, qword ptr [rsp + ffi_clo_OFF_R] ;movsd ffi_clo_OFF_R(%rsp), %xmm0 225*1fd5a2e1SPrashanth Swaminathan 226*1fd5a2e1SPrashanth Swaminathan add rsp, ffi_clo_FS ;addq $ffi_clo_FS, %rsp 227*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(-ffi_clo_FS) 228*1fd5a2e1SPrashanth Swaminathan ret 229*1fd5a2e1SPrashanth Swaminathan 230*1fd5a2e1SPrashanth Swaminathan cfi_endproc 231*1fd5a2e1SPrashanth Swaminathan C(ffi_closure_win64) endp 232*1fd5a2e1SPrashanth Swaminathan 233*1fd5a2e1SPrashanth Swaminathan#if defined __ELF__ && defined __linux__ 234*1fd5a2e1SPrashanth Swaminathan .section .note.GNU-stack,"",@progbits 235*1fd5a2e1SPrashanth Swaminathan#endif 236*1fd5a2e1SPrashanth Swaminathan_text ends 237*1fd5a2e1SPrashanth Swaminathanend