mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 09:30:21 +02:00
* add support for HFA parameter passing for ARM hardfloat
(fixes test/cg/tcalext6) git-svn-id: trunk@41421 -
This commit is contained in:
parent
8b9e90dc7a
commit
4e5f48a25e
@ -45,6 +45,8 @@ unit cpupara;
|
||||
function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
|
||||
private
|
||||
function usemmpararegs(calloption: tproccalloption; variadic: boolean): boolean;
|
||||
function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
|
||||
procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg,
|
||||
curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword;
|
||||
var sparesinglereg: tregister);
|
||||
@ -131,7 +133,9 @@ unit cpupara;
|
||||
end;
|
||||
|
||||
|
||||
function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
|
||||
function tcpuparamanager.getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
|
||||
var
|
||||
basedef: tdef;
|
||||
begin
|
||||
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
|
||||
if push_addr_param for the def is true
|
||||
@ -161,7 +165,11 @@ unit cpupara;
|
||||
classrefdef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
recorddef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
if usemmpararegs(calloption,isvariadic) and
|
||||
is_hfa(p,basedef) then
|
||||
getparaloc:=LOC_MMREGISTER
|
||||
else
|
||||
getparaloc:=LOC_REGISTER;
|
||||
objectdef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
stringdef:
|
||||
@ -176,6 +184,9 @@ unit cpupara;
|
||||
arraydef:
|
||||
if is_dynamic_array(p) then
|
||||
getparaloc:=LOC_REGISTER
|
||||
else if usemmpararegs(calloption,isvariadic) and
|
||||
is_hfa(p,basedef) then
|
||||
getparaloc:=LOC_MMREGISTER
|
||||
else
|
||||
getparaloc:=LOC_REFERENCE;
|
||||
setdef:
|
||||
@ -229,12 +240,19 @@ unit cpupara;
|
||||
var
|
||||
i: longint;
|
||||
sym: tsym;
|
||||
basedef: tdef;
|
||||
begin
|
||||
if handle_common_ret_in_param(def,pd,result) then
|
||||
exit;
|
||||
case def.typ of
|
||||
recorddef:
|
||||
begin
|
||||
if usemmpararegs(pd.proccalloption,is_c_variadic(pd)) and
|
||||
is_hfa(def,basedef) then
|
||||
begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
result:=def.size>4;
|
||||
if not result and
|
||||
(target_info.abi in [abi_default,abi_armeb]) then
|
||||
@ -327,11 +345,13 @@ unit cpupara;
|
||||
|
||||
var
|
||||
nextintreg,nextfloatreg,nextmmreg : tsuperregister;
|
||||
paradef : tdef;
|
||||
paradef,
|
||||
hfabasedef : tdef;
|
||||
paraloc : pcgparalocation;
|
||||
stack_offset : aword;
|
||||
hp : tparavarsym;
|
||||
loc : tcgloc;
|
||||
hfabasesize : tcgsize;
|
||||
paracgsize : tcgsize;
|
||||
paralen : longint;
|
||||
i : integer;
|
||||
@ -359,6 +379,31 @@ unit cpupara;
|
||||
end;
|
||||
|
||||
|
||||
procedure updatemmregs(paradef, basedef: tdef);
|
||||
var
|
||||
regsavailable,
|
||||
regsneeded: longint;
|
||||
basesize: asizeint;
|
||||
begin
|
||||
basesize:=basedef.size;
|
||||
regsneeded:=paradef.size div basesize;
|
||||
regsavailable:=ord(RS_D7)-ord(nextmmreg)+1;
|
||||
case basesize of
|
||||
4:
|
||||
regsavailable:=regsavailable*2+ord(sparesinglereg<>NR_NO);
|
||||
8:
|
||||
;
|
||||
else
|
||||
internalerror(2019022301);
|
||||
end;
|
||||
if regsavailable<regsneeded then
|
||||
begin
|
||||
nextmmreg:=succ(RS_D7);
|
||||
sparesinglereg:=NR_NO;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
result:=0;
|
||||
nextintreg:=curintreg;
|
||||
@ -429,6 +474,18 @@ unit cpupara;
|
||||
hp.paraloc[side].def:=paradef;
|
||||
firstparaloc:=true;
|
||||
|
||||
if (loc=LOC_MMREGISTER) and
|
||||
is_hfa(paradef,hfabasedef) then
|
||||
begin
|
||||
updatemmregs(paradef,hfabasedef);
|
||||
hfabasesize:=def_cgsize(hfabasedef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
hfabasedef:=nil;
|
||||
hfabasesize:=OS_NO;
|
||||
end;
|
||||
|
||||
{$ifdef EXTDEBUG}
|
||||
if paralen=0 then
|
||||
internalerror(200410311);
|
||||
@ -514,10 +571,18 @@ unit cpupara;
|
||||
end;
|
||||
LOC_MMREGISTER:
|
||||
begin
|
||||
paraloc^.size:=paracgsize;
|
||||
paraloc^.def:=paradef;
|
||||
if assigned(hfabasedef) then
|
||||
begin
|
||||
paraloc^.def:=hfabasedef;
|
||||
paraloc^.size:=hfabasesize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.size:=paracgsize;
|
||||
paraloc^.def:=paradef;
|
||||
end;
|
||||
if (nextmmreg<=RS_D7) or
|
||||
((paraloc^.size = OS_F32) and
|
||||
((paraloc^.size=OS_F32) and
|
||||
(sparesinglereg<>NR_NO)) then
|
||||
begin
|
||||
paraloc^.loc:=LOC_MMREGISTER;
|
||||
@ -642,35 +707,53 @@ unit cpupara;
|
||||
|
||||
function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
|
||||
var
|
||||
paraloc : pcgparalocation;
|
||||
paraloc: pcgparalocation;
|
||||
retcgsize : tcgsize;
|
||||
basedef: tdef;
|
||||
i: longint;
|
||||
mmreg: tregister;
|
||||
begin
|
||||
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
|
||||
exit;
|
||||
|
||||
paraloc:=result.add_location;
|
||||
{ Return in FPU register? }
|
||||
if result.def.typ=floatdef then
|
||||
basedef:=nil;
|
||||
if (result.def.typ=floatdef) or
|
||||
is_hfa(result.def,basedef) then
|
||||
begin
|
||||
if (target_info.abi=abi_eabihf) or (p.proccalloption=pocall_hardfloat) then
|
||||
if usemmpararegs(p.proccalloption,is_c_variadic(p)) then
|
||||
begin
|
||||
paraloc^.loc:=LOC_MMREGISTER;
|
||||
if assigned(basedef) then
|
||||
begin
|
||||
for i:=2 to result.def.size div basedef.size do
|
||||
result.add_location;
|
||||
retcgsize:=def_cgsize(basedef);
|
||||
end
|
||||
else
|
||||
basedef:=result.def;
|
||||
case retcgsize of
|
||||
OS_64,
|
||||
OS_F64:
|
||||
begin
|
||||
paraloc^.register:=NR_MM_RESULT_REG;
|
||||
mmreg:=NR_MM_RESULT_REG
|
||||
end;
|
||||
OS_32,
|
||||
OS_F32:
|
||||
begin
|
||||
paraloc^.register:=NR_S0;
|
||||
mmreg:=NR_S0;
|
||||
end;
|
||||
else
|
||||
internalerror(2012032501);
|
||||
end;
|
||||
paraloc^.size:=retcgsize;
|
||||
paraloc^.def:=result.def;
|
||||
repeat
|
||||
paraloc^.loc:=LOC_MMREGISTER;
|
||||
paraloc^.register:=mmreg;
|
||||
inc(mmreg);
|
||||
paraloc^.size:=retcgsize;
|
||||
paraloc^.def:=basedef;
|
||||
paraloc:=paraloc^.next;
|
||||
until not assigned(paraloc);
|
||||
end
|
||||
else if (p.proccalloption in [pocall_softfloat]) or
|
||||
(cs_fp_emulation in current_settings.moduleswitches) or
|
||||
@ -764,6 +847,14 @@ unit cpupara;
|
||||
end;
|
||||
|
||||
|
||||
function tcpuparamanager.usemmpararegs(calloption: tproccalloption; variadic: boolean): boolean;
|
||||
begin
|
||||
result:=
|
||||
((target_info.abi=abi_eabihf) or (calloption=pocall_hardfloat)) and
|
||||
(not variadic);
|
||||
end;
|
||||
|
||||
|
||||
function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
|
||||
var
|
||||
cur_stack_offset: aword;
|
||||
|
Loading…
Reference in New Issue
Block a user