Subject: | x64 asm is broken for ::API, >4 param crash |
If there are over 4 parameters on x64 with GCC, there is a crash.
Remember every function on x64 has 4 parameters without exception. RSI
and R10 is filled with garbage with the 2 POPs at the end. The stack
pusher loop is broken. RSI in Call_asm is the retval struct pointer on
-O2 (strawberry perl's default). On -O0 it doesn't crash, IDK and don't
care why.
Show quoted text
________________________
.globl Call_x64_real
Call_x64_real:
pushq %rbp
movq %rsp,%rbp
subq $32,%rsp # keep space for 4 64bit params
ADD 32 to RSP A FIXED AMOUNT
# 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
# Save regs we are gonna use
pushq %rsi
ADD 8 to RSP A FIXED AMOUNT
pushq %r10
ADD 8 to RSP A FIXED AMOUNT
# 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),%rsi # rsi = stack
movq 48(%rbp),%rax # rax = nstack
NSTACK IS NUMBER OF STACK PARAMS
FROM Call_asm
required_stack = nparams > 4 ? nparams - 4 : 0;
NSTACK IS required_stack IN THE CALLER Call_asm
END COMMENT
# Except not if there isn't any
testq %rax,%rax
je docall
copystack:
subq $1,%rax
movq (%rsi,%rax,8),%r10
pushq %r10
ADD MANY 8s TO RSP THIS IS A LOOP VARIABLE AMOUNT
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
ADD 32 TO RSP, A FIXED AMOUNT
callq *%r10
addq $32,%rsp # restore stack
REMOVE 32 FROM RSP, A FIXED AMOUNT
# Store return value
movq 56(%rbp),%r10 # r10 = iret
movq %rax,(%r10)
movq 64(%rbp),%r10 # r10 = dret
movsd %xmm0,(%r10)
# Restore regs
popq %r10
REMOVE 8 FROM RSP, A FIXED AMOUNT
popq %rsi
REMOVE 8 FROM RSP, A FIXED AMOUNT
movq %rbp,%rsp
popq %rbp
retq
____________________________________________
This bug is in the public 0.68, and my personal API versions
(0.69/0.70). Its only on x64 and on GCC Perl. I'll investigate whether
the same bug is in MSVC x64 side.