.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 mov %rdi, %r11 mov %rsi, %r12 # First, set up the fixed arguments # %r13 = fixed arg count movq (%r12), %r13 # arg[0] cmp $0, %r13 jle .idone movq 48(%r12), %rdi # arg[1] cmp $1, %r13 jle .idone movq 56(%r12), %rsi # arg[2] cmp $2, %r13 jle .idone movq 64(%r12), %rdx # arg[3] cmp $3, %r13 jle .idone movq 72(%r12), %rcx # arg[4] cmp $4, %r13 jle .idone movq 80(%r12), %r8 # arg[5] cmp $5, %r13 jle .idone movq 88(%r12), %r9 .idone: # Next, set up the fixed double arguments # r13 = fixed double arg count movq 8(%r12), %r13 # arg[0] cmp $0, %r13 jle .vdone movq 96(%r12), %xmm0 # arg[1] cmp $1, %r13 jle .vdone movq 104(%r12), %xmm1 # arg[2] cmp $2, %r13 jle .vdone movq 112(%r12), %xmm2 # arg[3] cmp $3, %r13 jle .vdone movq 120(%r12), %xmm3 # arg[4] cmp $4, %r13 jle .vdone movq 128(%r12), %xmm4 # arg[5] cmp $5, %r13 jle .vdone movq 136(%r12), %xmm5 # arg[6] cmp $6, %r13 jle .vdone movq 144(%r12), %xmm6 # arg[7] cmp $7, %r13 jle .vdone movq 152(%r12), %xmm7 .vdone: # Finally, set up the variable arguments # x8 = excess arg count movq 32(%r12), %r13 # calculate the amount of stack space needed for the varargs shl $3, %r13 andq $0xFFFFFFFFFFFFFFF0, %r13 addq $0x10, %r13 # allocate the stack space sub %r13, %rsp mov %rsp, %r14 # convert buffer size back to number of arguments movq 32(%r12), %r13 # r13: number of var args (decrements with every iteration) # r14: var arg dest pointer (increments with every iteration) # r15: arg src buffer (increments with every iteration) mov 160(%r12), %r15 .loop: cmp $0, %r13 je .loop_end # read the arg value from the src pointer mov (%r15), %rax # write it to the stack, and increment the dest pointer mov %rax, (%r14) add $8, %r14 # increment the src pointer, decrement the arg count sub $1, %r13 add $8, %r15 jmp .loop .loop_end: # call the function implementation mov 168(%r12), %rax call *%r11 # de-allocate the stack varargs buffer (the size is now stored in x19) movq 32(%r12), %r13 shl $3, %r13 andq $0xFFFFFFFFFFFFFFF0, %r13 addq $0x10, %r13 addq %r13, %rsp pop %r15 pop %r14 pop %r13 pop %r12 # restore the saved stack frame and link pointer 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