mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 20:09:18 +02:00
* aarch64: According to ARM64 ABI, function's arguments and the result are not required to be sign/zero extended to a full register size. Obey this rule for all targets except iOS where sign/zero extension is required.
git-svn-id: trunk@41412 -
This commit is contained in:
parent
e9c4042023
commit
382d5060a0
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -12745,6 +12745,7 @@ tests/test/packages/win-base/tdispvar1.pp svneol=native#text/plain
|
|||||||
tests/test/packages/zlib/tzlib1.pp svneol=native#text/plain
|
tests/test/packages/zlib/tzlib1.pp svneol=native#text/plain
|
||||||
tests/test/t4cc1.pp svneol=native#text/plain
|
tests/test/t4cc1.pp svneol=native#text/plain
|
||||||
tests/test/t4cc2.pp svneol=native#text/plain
|
tests/test/t4cc2.pp svneol=native#text/plain
|
||||||
|
tests/test/taarch64abi.pp svneol=native#text/plain
|
||||||
tests/test/tabstract1.pp svneol=native#text/pascal
|
tests/test/tabstract1.pp svneol=native#text/pascal
|
||||||
tests/test/tabstrcl.pp svneol=native#text/plain
|
tests/test/tabstrcl.pp svneol=native#text/plain
|
||||||
tests/test/tabsvr1.pp svneol=native#text/plain
|
tests/test/tabsvr1.pp svneol=native#text/plain
|
||||||
|
@ -364,6 +364,24 @@ unit cpupara;
|
|||||||
if not assigned(result.location) or
|
if not assigned(result.location) or
|
||||||
not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
|
not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
|
||||||
internalerror(2014113001);
|
internalerror(2014113001);
|
||||||
|
{
|
||||||
|
According to ARM64 ABI: "If the size of the argument is less than 8 bytes then
|
||||||
|
the size of the argument is set to 8 bytes. The effect is as if the argument
|
||||||
|
was copied to the least significant bits of a 64-bit register and the remaining
|
||||||
|
bits filled with unspecified values."
|
||||||
|
|
||||||
|
Therefore at caller side force the ordinal result to be always 64-bit, so it
|
||||||
|
will be stripped to the required size and uneeded bits are discarded.
|
||||||
|
|
||||||
|
This is not required for iOS, where the result is zero/sign extended.
|
||||||
|
}
|
||||||
|
if (target_info.abi<>abi_aarch64_darwin) and
|
||||||
|
(side=callerside) and (result.location^.loc = LOC_REGISTER) and
|
||||||
|
(result.def.size<8) and is_ordinal(result.def) then
|
||||||
|
begin
|
||||||
|
result.location^.size:=OS_64;
|
||||||
|
result.location^.def:=u64inttype;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -597,14 +615,28 @@ unit cpupara;
|
|||||||
responsibility to sign or zero-extend arguments having fewer
|
responsibility to sign or zero-extend arguments having fewer
|
||||||
than 32 bits, and that unused bits in a register are
|
than 32 bits, and that unused bits in a register are
|
||||||
unspecified. In iOS, however, the caller must perform such
|
unspecified. In iOS, however, the caller must perform such
|
||||||
extensions, up to 32 bits." }
|
extensions, up to 32 bits."
|
||||||
if (target_info.abi=abi_aarch64_darwin) and
|
Zero extend an argument at caller side for iOS and
|
||||||
(side=callerside) and
|
ignore the argument's unspecified high bits at callee side for
|
||||||
is_ordinal(paradef) and
|
all other platforms. }
|
||||||
(paradef.size<4) then
|
if (paradef.size<4) and is_ordinal(paradef) then
|
||||||
begin
|
begin
|
||||||
paraloc^.size:=OS_32;
|
if target_info.abi=abi_aarch64_darwin then
|
||||||
paraloc^.def:=u32inttype;
|
begin
|
||||||
|
if side=callerside then
|
||||||
|
begin
|
||||||
|
paraloc^.size:=OS_32;
|
||||||
|
paraloc^.def:=u32inttype;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if side=calleeside then
|
||||||
|
begin
|
||||||
|
paraloc^.size:=OS_32;
|
||||||
|
paraloc^.def:=u32inttype;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ in case it's a composite, "The argument is passed as though
|
{ in case it's a composite, "The argument is passed as though
|
||||||
|
84
tests/test/taarch64abi.pp
Normal file
84
tests/test/taarch64abi.pp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
{ %CPU=aarch64 }
|
||||||
|
{ %skiptarget=darwin }
|
||||||
|
|
||||||
|
{
|
||||||
|
Tests that arguments and the result are not required to be sign/zero extended.
|
||||||
|
}
|
||||||
|
|
||||||
|
procedure ProcByte(p: byte);
|
||||||
|
begin
|
||||||
|
if p <> $78 then
|
||||||
|
Halt(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ProcWord(p: word);
|
||||||
|
begin
|
||||||
|
if p <> $5678 then
|
||||||
|
Halt(2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ProcDWord(p: dword);
|
||||||
|
begin
|
||||||
|
if p <> $12345678 then
|
||||||
|
Halt(3);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RetByte: byte;
|
||||||
|
var
|
||||||
|
q: qword;
|
||||||
|
begin
|
||||||
|
q:=$1111111112345678;
|
||||||
|
asm
|
||||||
|
ldr x0,q
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RetWord: word;
|
||||||
|
var
|
||||||
|
q: qword;
|
||||||
|
begin
|
||||||
|
q:=$1111111112345678;
|
||||||
|
asm
|
||||||
|
ldr x0,q
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RetDWord: dword;
|
||||||
|
var
|
||||||
|
q: qword;
|
||||||
|
begin
|
||||||
|
q:=$1111111112345678;
|
||||||
|
asm
|
||||||
|
ldr x0,q
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TestParams;
|
||||||
|
var
|
||||||
|
q: qword;
|
||||||
|
begin
|
||||||
|
q:=$1111111112345678;
|
||||||
|
asm
|
||||||
|
ldr x0,q
|
||||||
|
bl ProcByte
|
||||||
|
ldr x0,q
|
||||||
|
bl ProcWord
|
||||||
|
ldr x0,q
|
||||||
|
bl ProcDWord
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TestReturns;
|
||||||
|
begin
|
||||||
|
if RetByte <> $78 then
|
||||||
|
Halt(11);
|
||||||
|
if RetWord <> $5678 then
|
||||||
|
Halt(12);
|
||||||
|
if RetDWord <> $12345678 then
|
||||||
|
Halt(13);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
TestParams;
|
||||||
|
TestReturns;
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user