Fixed several catastrophic bugs related to functions with > 6 arguments. Also optimised away some useless stack prodding. Pls re-copy/paste if there's anybody out there, lol...
macro unix64call proc,[arg]
{
common
local G_ARG_INDEX
local F_ARG_INDEX
local ARG_IS_FLOAT
local ARG_IS_STRING
local G_ARG0_STORED
local G_ARG1_STORED
local G_ARG2_STORED
local G_ARG3_STORED
local G_ARG4_STORED
local F_ARG0_STORED
local F_ARG1_STORED
local F_ARG2_STORED
local F_ARG3_STORED
local F_ARG4_STORED
local F_ARG5_STORED
local F_ARG6_STORED
local NUM_XMM_ARGS
local NUM_FLOAT_ARGS
local NUM_GENERAL_ARGS
local NUM_STACK_ARGS
local NUM_ARGS_PUSHED
G_ARG_INDEX = 0
F_ARG_INDEX = 0
ARG_IS_FLOAT = 0
ARG_IS_STRING = 0
G_ARG0_STORED = 0
G_ARG1_STORED = 0
G_ARG2_STORED = 0
G_ARG3_STORED = 0
G_ARG4_STORED = 0
F_ARG0_STORED = 0
F_ARG1_STORED = 0
F_ARG2_STORED = 0
F_ARG3_STORED = 0
F_ARG4_STORED = 0
F_ARG5_STORED = 0
F_ARG6_STORED = 0
NUM_XMM_ARGS = 0
NUM_FLOAT_ARGS = 0
NUM_GENERAL_ARGS = 0
NUM_STACK_ARGS = 0
NUM_ARGS_PUSHED = 0
forward
if G_ARG_INDEX > 5 | F_ARG_INDEX > 7
NUM_STACK_ARGS = NUM_STACK_ARGS + 1
end if
match =float mem_float, arg
\{
ARG_IS_FLOAT = 1
\}
if arg eqtype 1.0 | arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7> | ARG_IS_FLOAT
F_ARG_INDEX = F_ARG_INDEX + 1
NUM_FLOAT_ARGS = NUM_FLOAT_ARGS + 1
else if ~(arg eq )
G_ARG_INDEX = G_ARG_INDEX + 1
NUM_GENERAL_ARGS = NUM_GENERAL_ARGS + 1
end if
ARG_IS_FLOAT = 0
common
if NUM_GENERAL_ARGS + NUM_FLOAT_ARGS
if ~((NUM_STACK_ARGS = 0) | ((NUM_STACK_ARGS mod 2) = 0))
sub rsp, 8
else
sub rsp, 16
end if
mov [rsp], rax
G_ARG_INDEX = 0
F_ARG_INDEX = 0
end if
common
F_ARG_INDEX = NUM_FLOAT_ARGS
G_ARG_INDEX = NUM_GENERAL_ARGS
reverse
if NUM_GENERAL_ARGS + NUM_FLOAT_ARGS
match =float mem_float, arg
\{
ARG_IS_FLOAT = 1
\}
contains_strings ARG_IS_STRING, arg
if arg eqtype 1.0 | arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7> | ARG_IS_FLOAT
F_ARG_INDEX = F_ARG_INDEX - 1
else
G_ARG_INDEX = G_ARG_INDEX - 1
end if
if arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
if F_ARG_INDEX > 7
sub rsp, 8
movq [rsp], arg
NUM_ARGS_PUSHED = NUM_ARGS_PUSHED + 1
end if
else if arg eqtype 1.0
if F_ARG_INDEX > 7
mov rax, arg
push rax
NUM_ARGS_PUSHED = NUM_ARGS_PUSHED + 1
end if
else if ARG_IS_FLOAT
if F_ARG_INDEX > 7
match =float mem_float, arg
\{
push mem_float
NUM_ARGS_PUSHED = NUM_ARGS_PUSHED + 1
\}
end if
else if ARG_IS_STRING
if G_ARG_INDEX > 5
call @f
db arg, 0
@@:
NUM_ARGS_PUSHED = NUM_ARGS_PUSHED + 1
end if
else if G_ARG_INDEX > 5
if arg eq rax
push qword [rsp + 8 * NUM_ARGS_PUSHED]
else
push arg
end if
NUM_ARGS_PUSHED = NUM_ARGS_PUSHED + 1
end if
ARG_IS_FLOAT = 0
ARG_IS_STRING = 0
end if
common
F_ARG_INDEX = 0
G_ARG_INDEX = 0
forward
if NUM_GENERAL_ARGS + NUM_FLOAT_ARGS
if G_ARG_INDEX < 6 & arg eq rax
push rax
else if G_ARG_INDEX = 0 & arg in <rsi,rdx,rcx,r8,r9>
push arg
G_ARG0_STORED = 1
else if G_ARG_INDEX = 1 & arg in <rdx,rcx,r8,r9>
push arg
G_ARG1_STORED = 1
else if G_ARG_INDEX = 2 & arg in <rcx,r8,r9>
push arg
G_ARG2_STORED = 1
else if G_ARG_INDEX = 3 & arg in <r8,r9>
push arg
G_ARG3_STORED = 1
else if G_ARG_INDEX = 4 & arg in <r9>
push arg
G_ARG4_STORED = 1
else if F_ARG_INDEX = 0 & arg in <xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
movq rax, arg
push rax
F_ARG0_STORED = 1
else if F_ARG_INDEX = 1 & arg in <xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
movq rax, arg
push rax
F_ARG1_STORED = 1
else if F_ARG_INDEX = 2 & arg in <xmm3,xmm4,xmm5,xmm6,xmm7>
movq rax, arg
push rax
F_ARG2_STORED = 1
else if F_ARG_INDEX = 3 & arg in <xmm4,xmm5,xmm6,xmm7>
movq rax, arg
push rax
F_ARG3_STORED = 1
else if F_ARG_INDEX = 4 & arg in <xmm5,xmm6,xmm7>
movq rax, arg
push rax
F_ARG4_STORED = 1
else if F_ARG_INDEX = 5 & arg in <xmm6,xmm7>
movq rax, arg
push rax
F_ARG5_STORED = 1
else if F_ARG_INDEX = 6 & arg in <xmm7>
movq rax, arg
push rax
F_ARG6_STORED = 1
end if
match =float mem_float, arg
\{
ARG_IS_FLOAT = 1
\}
if arg eqtype 1.0 | arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7> | ARG_IS_FLOAT
F_ARG_INDEX = F_ARG_INDEX + 1
else
G_ARG_INDEX = G_ARG_INDEX + 1
end if
ARG_IS_FLOAT = 0
end if
common
F_ARG_INDEX = NUM_FLOAT_ARGS
G_ARG_INDEX = NUM_GENERAL_ARGS
reverse
if NUM_GENERAL_ARGS + NUM_FLOAT_ARGS
match =float mem_float, arg
\{
ARG_IS_FLOAT = 1
\}
contains_strings ARG_IS_STRING, arg
if arg eqtype 1.0 | arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7> | ARG_IS_FLOAT
if NUM_XMM_ARGS < 8
NUM_XMM_ARGS = NUM_XMM_ARGS + 1
end if
F_ARG_INDEX = F_ARG_INDEX - 1
else
G_ARG_INDEX = G_ARG_INDEX - 1
end if
if arg in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
if F_ARG_INDEX = 7 & ~(arg eq xmm7)
movq xmm7, arg
else if F_ARG_INDEX = 6 & F_ARG6_STORED
pop rax
movq xmm6, rax
else if F_ARG_INDEX = 6 & ~(arg eq xmm6)
movq xmm6, arg
else if F_ARG_INDEX = 5 & F_ARG5_STORED
pop rax
movq xmm5, rax
else if F_ARG_INDEX = 5 & ~(arg eq xmm5)
movq xmm5, arg
else if F_ARG_INDEX = 4 & F_ARG4_STORED
pop rax
movq xmm4, rax
else if F_ARG_INDEX = 4 & ~(arg eq xmm4)
movq xmm4, arg
else if F_ARG_INDEX = 3 & F_ARG3_STORED
pop rax
movq xmm3, rax
else if F_ARG_INDEX = 3 & ~(arg eq xmm3)
movq xmm3, arg
else if F_ARG_INDEX = 2 & F_ARG2_STORED
pop rax
movq xmm2, rax
else if F_ARG_INDEX = 2 & ~(arg eq xmm2)
movq xmm2, arg
else if F_ARG_INDEX = 1 & F_ARG1_STORED
pop rax
movq xmm1, rax
else if F_ARG_INDEX = 1 & ~(arg eq xmm1)
movq xmm1, arg
else if F_ARG_INDEX = 0 & F_ARG0_STORED
pop rax
movq xmm0, rax
else if F_ARG_INDEX = 0 & ~(arg eq xmm0)
movq xmm0, arg
end if
else if arg eqtype 1.0
if F_ARG_INDEX = 7
mov rax, arg
movq xmm7, rax
else if F_ARG_INDEX = 6
mov rax, arg
movq xmm6, rax
else if F_ARG_INDEX = 5
mov rax, arg
movq xmm5, rax
else if F_ARG_INDEX = 4
mov rax, arg
movq xmm4, rax
else if F_ARG_INDEX = 3
mov rax, arg
movq xmm3, rax
else if F_ARG_INDEX = 2
mov rax, arg
movq xmm2, rax
else if F_ARG_INDEX = 1
mov rax, arg
movq xmm1, rax
else if F_ARG_INDEX = 0
mov rax, arg
movq xmm0, rax
end if
else if ARG_IS_FLOAT
match =float mem_float, arg
\{
if F_ARG_INDEX = 7
movq xmm7, mem_float
else if F_ARG_INDEX = 6
movq xmm6, mem_float
else if F_ARG_INDEX = 5
movq xmm5, mem_float
else if F_ARG_INDEX = 4
movq xmm4, mem_float
else if F_ARG_INDEX = 3
movq xmm3, mem_float
else if F_ARG_INDEX = 2
movq xmm2, mem_float
else if F_ARG_INDEX = 1
movq xmm1, mem_float
else if F_ARG_INDEX = 0
movq xmm0, mem_float
end if
\}
else if ARG_IS_STRING
if G_ARG_INDEX < 6
call @f
db arg, 0
@@:
if G_ARG_INDEX = 5
pop r9
else if G_ARG_INDEX = 4
pop r8
else if G_ARG_INDEX = 3
pop rcx
else if G_ARG_INDEX = 2
pop rdx
else if G_ARG_INDEX = 1
pop rsi
else if G_ARG_INDEX = 0
pop rdi
end if
end if
else
if G_ARG_INDEX = 5 & arg eq rax
pop r9
else if G_ARG_INDEX = 5 & ~(arg eq r9)
mov r9, arg
else if G_ARG_INDEX = 4 & (G_ARG4_STORED | arg eq rax)
pop r8
else if G_ARG_INDEX = 4 & ~(arg eq r8)
mov r8, arg
else if G_ARG_INDEX = 3 & (G_ARG3_STORED | arg eq rax)
pop rcx
else if G_ARG_INDEX = 3 & ~(arg eq rcx)
mov rcx, arg
else if G_ARG_INDEX = 2 & (G_ARG2_STORED | arg eq rax)
pop rdx
else if G_ARG_INDEX = 2 & ~(arg eq rdx)
mov rdx, arg
else if G_ARG_INDEX = 1 & (G_ARG1_STORED | arg eq rax)
pop rsi
else if G_ARG_INDEX = 1 & ~(arg eq rsi)
mov rsi, arg
else if G_ARG_INDEX = 0 & (G_ARG0_STORED | arg eq rax)
pop rdi
else if G_ARG_INDEX = 0 & ~(arg eq rdi)
mov rdi, arg
end if
end if
ARG_IS_FLOAT = 0
ARG_IS_STRING = 0
end if
common
mov rax, NUM_XMM_ARGS
call proc
if NUM_GENERAL_ARGS + NUM_FLOAT_ARGS
if ~((NUM_STACK_ARGS = 0) | ((NUM_STACK_ARGS mod 2) = 0))
add rsp, 8 * (NUM_STACK_ARGS + 1)
else
add rsp, 8 * (NUM_STACK_ARGS + 2)
end if
end if
}
macro contains_strings result, [arg]
{
result = 0
forward
if arg eqtype "fasm"
result = 1
end if
}