x86-64 uses FPU instructions to prepare stack arguments.
On x86-64/win64
, this code:
{$mode objfpc} {$longstrings on}
var
dummyString: string;
procedure DoSomething1(p0, p1, p2, p3, p4: uint32; p5: double);
begin
WriteStr(dummyString, p0, p1, p2, p3, p4, p5);
end;
procedure DoSomething2(p5: double; p0, p1, p2, p3, p4: uint32);
begin
WriteStr(dummyString, p0, p1, p2, p3, p4, p5);
end;
begin
DoSomething1(1, 2, 3, 4, 5, 123.45);
DoSomething2(123.45, 1, 2, 3, 4, 5);
end.
compiles (-O3
) into:
; [16] DoSomething1(1, 2, 3, 4, 5, 123.45);
movl $5,32(%rsp)
fldl _$PROGRAM$_Ld1(%rip)
fstpl 40(%rsp)
movl $3,%r8d
movl $2,%edx
movl $1,%ecx
movl $4,%r9d
call P$PROGRAM_$$_DOSOMETHING1$LONGWORD$LONGWORD$LONGWORD$LONGWORD$LONGWORD$DOUBLE
; [17] DoSomething2(123.45, 1, 2, 3, 4, 5);
movl $5,40(%rsp)
movl $4,32(%rsp)
movsd _$PROGRAM$_Ld1(%rip),%xmm0
movl $3,%r9d
movl $2,%r8d
movl $1,%edx
call P$PROGRAM_$$_DOSOMETHING2$DOUBLE$LONGWORD$LONGWORD$LONGWORD$LONGWORD$LONGWORD
Are these FLD
and FSTP
intended? I mean, FLD RIP-relative + FSTP to address with 1-byte offset
occupy 10 bytes which is 2 bytes shorter than their alternative MOV RIP-relative to 64-bit reg + MOV 64-bit reg to address with 1-byte offset
that occupy 12, but isn’t FPU deprecated?