mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 09:28:19 +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/t4cc1.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/tabstrcl.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
|
||||
not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
|
||||
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;
|
||||
|
||||
|
||||
@ -597,14 +615,28 @@ unit cpupara;
|
||||
responsibility to sign or zero-extend arguments having fewer
|
||||
than 32 bits, and that unused bits in a register are
|
||||
unspecified. In iOS, however, the caller must perform such
|
||||
extensions, up to 32 bits." }
|
||||
if (target_info.abi=abi_aarch64_darwin) and
|
||||
(side=callerside) and
|
||||
is_ordinal(paradef) and
|
||||
(paradef.size<4) then
|
||||
extensions, up to 32 bits."
|
||||
Zero extend an argument at caller side for iOS and
|
||||
ignore the argument's unspecified high bits at callee side for
|
||||
all other platforms. }
|
||||
if (paradef.size<4) and is_ordinal(paradef) then
|
||||
begin
|
||||
paraloc^.size:=OS_32;
|
||||
paraloc^.def:=u32inttype;
|
||||
if target_info.abi=abi_aarch64_darwin then
|
||||
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;
|
||||
|
||||
{ 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