* pass varargs float parameters only in integer registers instead of only

in fpu registers for aix abi. Proper fix is to pass them in both, but
    at least gcc under Mac OS X only seems to use the contents in the integer
    registers currently.

git-svn-id: trunk@1576 -
This commit is contained in:
Jonas Maebe 2005-10-23 14:23:16 +00:00
parent 9fd0bb293d
commit 89094457c5
2 changed files with 45 additions and 5 deletions

View File

@ -216,6 +216,21 @@ implementation
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara); cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
end; end;
{$endif x86_64} {$endif x86_64}
{$ifdef powerpc}
LOC_REGISTER,
LOC_CREGISTER :
begin
{ aix abi passes floats of varargs in both fpu and }
{ integer registers }
location_force_mem(exprasmlist,left.location);
{ force integer size }
left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
if (left.location.size in [OS_32,OS_S32]) then
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
else
cg64.a_param64_ref(exprasmlist,left.location.reference,tempcgpara);
end;
{$endif powerpc}
{$if defined(sparc) or defined(arm)} {$if defined(sparc) or defined(arm)}
{ sparc and arm pass floats in normal registers } { sparc and arm pass floats in normal registers }
LOC_REGISTER, LOC_REGISTER,
@ -245,6 +260,19 @@ implementation
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara); cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
end; end;
{$endif x86_64} {$endif x86_64}
{$ifdef powerpc}
{ x86_64 pushes s64comp in normal register }
LOC_REGISTER,
LOC_CREGISTER :
begin
{ force integer size }
left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
if (left.location.size in [OS_32,OS_S32]) then
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
else
cg64.a_param64_ref(exprasmlist,left.location.reference,tempcgpara);
end;
{$endif powerpc}
{$if defined(sparc) or defined(arm) } {$if defined(sparc) or defined(arm) }
{ sparc and arm pass floats in normal registers } { sparc and arm pass floats in normal registers }
LOC_REGISTER, LOC_REGISTER,

View File

@ -45,7 +45,7 @@ unit cpupara;
private private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist; function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
function parseparaloc(p : tparavarsym;const s : string) : boolean;override; function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
end; end;
@ -298,7 +298,7 @@ unit cpupara;
begin begin
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
create_funcretloc_info(p,side); create_funcretloc_info(p,side);
end; end;
@ -306,7 +306,7 @@ unit cpupara;
function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist; function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
var var
stack_offset: longint; stack_offset: longint;
paralen: aint; paralen: aint;
@ -413,6 +413,18 @@ unit cpupara;
end; end;
end end
end; end;
if varargsparas and
(target_info.abi = abi_powerpc_aix) and
(paradef.deftype = floatdef) then
begin
loc := LOC_REGISTER;
if paracgsize = OS_F64 then
paracgsize := OS_64
else
paracgsize := OS_32;
end;
hp.paraloc[side].alignment:=std_param_align; hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize; hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen; hp.paraloc[side].intsize:=paralen;
@ -522,11 +534,11 @@ unit cpupara;
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
firstfloatreg:=curfloatreg; firstfloatreg:=curfloatreg;
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
begin begin
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset); result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
{ varargs routines have to reserve at least 32 bytes for the AIX abi } { varargs routines have to reserve at least 32 bytes for the AIX abi }
if (target_info.abi = abi_powerpc_aix) and if (target_info.abi = abi_powerpc_aix) and
(result < 32) then (result < 32) then