mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 10:20:21 +02:00
* 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:
parent
9fd0bb293d
commit
89094457c5
compiler
@ -216,6 +216,21 @@ implementation
|
||||
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
|
||||
end;
|
||||
{$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)}
|
||||
{ sparc and arm pass floats in normal registers }
|
||||
LOC_REGISTER,
|
||||
@ -245,6 +260,19 @@ implementation
|
||||
cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
|
||||
end;
|
||||
{$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) }
|
||||
{ sparc and arm pass floats in normal registers }
|
||||
LOC_REGISTER,
|
||||
|
@ -45,7 +45,7 @@ unit cpupara;
|
||||
private
|
||||
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
|
||||
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;
|
||||
end;
|
||||
|
||||
@ -298,7 +298,7 @@ unit cpupara;
|
||||
begin
|
||||
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);
|
||||
end;
|
||||
@ -306,7 +306,7 @@ unit cpupara;
|
||||
|
||||
|
||||
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
|
||||
stack_offset: longint;
|
||||
paralen: aint;
|
||||
@ -413,6 +413,18 @@ unit cpupara;
|
||||
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].size:=paracgsize;
|
||||
hp.paraloc[side].intsize:=paralen;
|
||||
@ -522,11 +534,11 @@ unit cpupara;
|
||||
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
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
|
||||
{ just continue loading the parameters in the registers }
|
||||
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 }
|
||||
if (target_info.abi = abi_powerpc_aix) and
|
||||
(result < 32) then
|
||||
|
Loading…
Reference in New Issue
Block a user