.globl Call_x64_real
Call_x64_real:
pushq %rbp
movq %rsp,%rbp
subq $32,%rsp # keep space for 4 64bit params
# Store register parameters
movq %rcx,16(%rbp) # ApiFunction
movq %rdx,24(%rbp) # int_registers
movq %r8,32(%rbp) # float_registers
movq %r9,40(%rbp) # stack
# Load up integer registers first...
movq 24(%rbp),%rax # rax = int_registers
movq (%rax),%rcx
movq 8(%rax),%rdx
movq 16(%rax),%r8
movq 24(%rax),%r9
# Now floating-point registers
movq 32(%rbp),%rax # rax = float_registers
movsd (%rax),%xmm0
movsd 8(%rax),%xmm1
movsd 16(%rax),%xmm2
movsd 24(%rax),%xmm3
# Now the stack
movq 40(%rbp),%r11 # r11 = stack
movq 48(%rbp),%rax # rax = nstack
# Except not if there isn't any
testq %rax,%rax
je docall
copystack:
subq $1,%rax
movq (%r11,%rax,8),%r10
pushq %r10
testq %rax,%rax
jne copystack
docall:
# And call
movq 16(%rbp),%r10 # r10 = ApiFunction
subq $32,%rsp # Microsoft x64 calling convention - allocate 32 bytes of "shadow space" on the stack
callq *%r10
addq $32,%rsp # restore stack
# Store return value
movq 56(%rbp),%r10 # r10 = iret
movq %rax,(%r10)
movq 64(%rbp),%r10 # r10 = dret
movsd %xmm0,(%r10)
movq %rbp,%rsp
popq %rbp
retq