.extern memcpy .type memcpy, @function .global callvm_invoke_i .type callvm_invoke_i, @function # %rdi = (function ptr) impl # %rsi = (struct callvm) context callvm_invoke_i: # save the stack frame pointer push %rbp mov %rsp, %rbp # store function pointer for later push %r12 push %r13 push %r14 push %r15 # move our parameters out of the way mov %rdi, %r11 mov %rsi, %r12 # calculate the amount of stack space needed for the varargs movq 32(%r12), %r13 shl $3, %r13 # allocate the stack space push %rsp sub %r13, %rsp andq $0xFFFFFFFFFFFFFFF0, %rsp # re-align the stack # copy the excess args to the stack mov %rsp, %rdi mov 160(%r12), %rsi mov %r13, %rdx call memcpy # Next, set up the fixed integer arguments movq 48(%r12), %rdi # int arg 0 movq 56(%r12), %rsi # int arg 1 movq 64(%r12), %rdx # int arg 2 movq 72(%r12), %rcx # int arg 3 movq 80(%r12), %r8 # int arg 4 movq 88(%r12), %r9 # int arg 5 # Finally, set up the fixed double arguments movq 96(%r12), %xmm0 # double arg 0 movq 104(%r12), %xmm1 # double arg 1 movq 112(%r12), %xmm2 # double arg 2 movq 120(%r12), %xmm3 # double arg 3 movq 128(%r12), %xmm4 # double arg 4 movq 136(%r12), %xmm5 # double arg 5 movq 144(%r12), %xmm6 # double arg 6 movq 152(%r12), %xmm7 # double arg 7 # set the number of vararg double parameters # as required by the ABI mov 168(%r12), %rax # call the function implementation call *%r11 # Restore the stack pointer (deallocating the varargs buffer) mov -40(%rbp), %rsp # Restore callee-saved registers pop %r15 pop %r14 pop %r13 pop %r12 # restore the saved stack frame pop %rbp ret .global callvm_invoke_d .type callvm_invoke_d, @function # %rdi = (function ptr) impl # %rsi = (struct callvm *) context callvm_invoke_d: jmp callvm_invoke_i .global callvm_invoke_v .type callvm_invoke_v, @function # %rdi = (function ptr) impl # %rsi = (struct callvm *) context callvm_invoke_v: jmp callvm_invoke_i