mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-01 03:39:19 +02:00
* make sparc para manager quite similar to ppc one to help
copying evolutions. + Add support to var args in registers. need to be verfied as it was just copying ppc's one
This commit is contained in:
parent
5d851cb954
commit
5962aeb34e
@ -25,9 +25,11 @@ unit cpupara;
|
||||
interface
|
||||
|
||||
uses
|
||||
cpubase,cgbase,
|
||||
aasmtai,globtype,
|
||||
symconst,symtype,symdef,paramgr;
|
||||
globtype,
|
||||
cclasses,
|
||||
aasmtai,
|
||||
cpubase,cpuinfo,
|
||||
symconst,symbase,symtype,symdef,paramgr,cgbase;
|
||||
|
||||
type
|
||||
TSparcParaManager=class(TParaManager)
|
||||
@ -41,52 +43,22 @@ interface
|
||||
function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
|
||||
procedure allocparaloc(list: taasmoutput; const loc: tparalocation);override;
|
||||
procedure freeparaloc(list: taasmoutput; const loc: tparalocation);override;
|
||||
function create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;override;
|
||||
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargspara):longint;override;
|
||||
procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);override;
|
||||
private
|
||||
procedure init_values(var curintreg :tsuperregister; var cur_stack_offset: aWord);
|
||||
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
|
||||
var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose,
|
||||
defutil,cgobj;
|
||||
|
||||
function tsparcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
|
||||
begin
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
|
||||
{ true if a parameter is too large to copy and only the address is pushed }
|
||||
function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
|
||||
begin
|
||||
result:=false;
|
||||
{ var,out always require address }
|
||||
if varspez in [vs_var,vs_out] then
|
||||
begin
|
||||
result:=true;
|
||||
exit;
|
||||
end;
|
||||
case def.deftype of
|
||||
recorddef,
|
||||
arraydef,
|
||||
variantdef,
|
||||
formaldef :
|
||||
push_addr_param:=true;
|
||||
objectdef :
|
||||
result:=is_object(def);
|
||||
stringdef :
|
||||
result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
|
||||
procvardef :
|
||||
result:=(po_methodpointer in tprocvardef(def).procoptions);
|
||||
setdef :
|
||||
result:=(tsetdef(def).settype<>smallset);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function tsparcparamanager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
|
||||
function TSparcParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
|
||||
begin
|
||||
result:=[RS_G1];
|
||||
end;
|
||||
@ -125,38 +97,178 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
|
||||
function getparaloc(p : tdef) : tcgloc;
|
||||
|
||||
begin
|
||||
if (loc.loc=LOC_REFERENCE) and
|
||||
(loc.low_in_reg) then
|
||||
cg.GetExplicitRegister(list,loc.lowreg);
|
||||
inherited allocparaloc(list,loc);
|
||||
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
|
||||
if push_addr_param for the def is true
|
||||
}
|
||||
case p.deftype of
|
||||
orddef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
floatdef:
|
||||
getparaloc:=LOC_FPUREGISTER;
|
||||
enumdef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
pointerdef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
formaldef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
classrefdef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
recorddef:
|
||||
getparaloc:=LOC_REFERENCE;
|
||||
objectdef:
|
||||
if is_object(p) then
|
||||
getparaloc:=LOC_REFERENCE
|
||||
else
|
||||
getparaloc:=LOC_REGISTER;
|
||||
stringdef:
|
||||
if is_shortstring(p) or is_longstring(p) then
|
||||
getparaloc:=LOC_REFERENCE
|
||||
else
|
||||
getparaloc:=LOC_REGISTER;
|
||||
procvardef:
|
||||
if (po_methodpointer in tprocvardef(p).procoptions) then
|
||||
getparaloc:=LOC_REFERENCE
|
||||
else
|
||||
getparaloc:=LOC_REGISTER;
|
||||
filedef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
arraydef:
|
||||
getparaloc:=LOC_REFERENCE;
|
||||
setdef:
|
||||
if is_smallset(p) then
|
||||
getparaloc:=LOC_REGISTER
|
||||
else
|
||||
getparaloc:=LOC_REFERENCE;
|
||||
variantdef:
|
||||
getparaloc:=LOC_REFERENCE;
|
||||
{ avoid problems with errornous definitions }
|
||||
errordef:
|
||||
getparaloc:=LOC_REGISTER;
|
||||
else
|
||||
internalerror(2002071001);
|
||||
end;
|
||||
end;
|
||||
function tsparcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
|
||||
begin
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
|
||||
procedure tsparcparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
|
||||
{ true if a parameter is too large to copy and only the address is pushed }
|
||||
function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
|
||||
begin
|
||||
if (loc.loc=LOC_REFERENCE) and
|
||||
(loc.low_in_reg) then
|
||||
cg.UnGetRegister(list,loc.lowreg);
|
||||
inherited freeparaloc(list,loc);
|
||||
result:=false;
|
||||
{ var,out always require address }
|
||||
if varspez in [vs_var,vs_out] then
|
||||
begin
|
||||
result:=true;
|
||||
exit;
|
||||
end;
|
||||
case def.deftype of
|
||||
recorddef,
|
||||
arraydef,
|
||||
variantdef,
|
||||
formaldef :
|
||||
push_addr_param:=true;
|
||||
objectdef :
|
||||
result:=is_object(def);
|
||||
stringdef :
|
||||
result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
|
||||
procvardef :
|
||||
result:=(po_methodpointer in tprocvardef(def).procoptions);
|
||||
setdef :
|
||||
result:=(tsetdef(def).settype<>smallset);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TSparcParaManager.init_values(var curintreg: tsuperregister; var cur_stack_offset: aWord);
|
||||
begin
|
||||
CurIntReg:=RS_O0;
|
||||
cur_stack_offset:=92;
|
||||
end;
|
||||
|
||||
|
||||
function TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;
|
||||
var
|
||||
paraloc : tparalocation;
|
||||
stack_offset : aWord;
|
||||
nextintreg : tsuperregister;
|
||||
stack_offset : longint;
|
||||
hp : tparaitem;
|
||||
is_64bit : boolean;
|
||||
paraloc : tparalocation;
|
||||
begin
|
||||
nextintreg:=RS_O0;
|
||||
init_values(NextIntReg,stack_offset);
|
||||
{ Nested procedures have the parent framepoint in o0 }
|
||||
if p.parast.symtablelevel>normal_function_level then
|
||||
inc(NextIntReg);
|
||||
stack_offset:=92;
|
||||
hp:=TParaItem(p.para.First);
|
||||
result := create_paraloc_info_intern(p,side,TParaItem(p.para.First),NextIntReg,stack_offset);
|
||||
|
||||
{ Function return }
|
||||
fillchar(paraloc,sizeof(tparalocation),0);
|
||||
paraloc.size:=def_cgsize(p.rettype.def);
|
||||
paraloc.Alignment:= std_param_align;
|
||||
{ Return in FPU register? }
|
||||
if p.rettype.def.deftype=floatdef then
|
||||
begin
|
||||
paraloc.loc:=LOC_FPUREGISTER;
|
||||
paraloc.register:=NR_FPU_RESULT_REG;
|
||||
end
|
||||
else
|
||||
{ Return in register? }
|
||||
if not ret_in_param(p.rettype.def,p.proccalloption) then
|
||||
begin
|
||||
paraloc.loc:=LOC_REGISTER;
|
||||
{$ifndef cpu64bit}
|
||||
if paraloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
paraloc.lochigh:=LOC_REGISTER;
|
||||
if side=callerside then
|
||||
paraloc.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
if side=callerside then
|
||||
paraloc.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
if side=callerside then
|
||||
paraloc.register:=NR_FUNCTION_RESULT_REG
|
||||
else
|
||||
paraloc.register:=NR_FUNCTION_RETURN_REG;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc.loc:=LOC_REFERENCE;
|
||||
end;
|
||||
p.funcret_paraloc[side]:=paraloc;
|
||||
{ Size on stack is not used }
|
||||
result:=0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function TSparcParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
|
||||
var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
|
||||
var
|
||||
stack_offset: aword;
|
||||
nextintreg : tsuperregister;
|
||||
paradef : tdef;
|
||||
paraloc : tparalocation;
|
||||
hp : tparaitem;
|
||||
loc : tcgloc;
|
||||
is_64bit: boolean;
|
||||
begin
|
||||
result:=0;
|
||||
nextintreg := curintreg;
|
||||
stack_offset := cur_stack_offset;
|
||||
hp:=firstpara;
|
||||
while assigned(hp) do
|
||||
begin
|
||||
fillchar(paraloc,sizeof(paraloc),0);
|
||||
@ -222,54 +334,28 @@ implementation
|
||||
end;
|
||||
hp:=TParaItem(hp.Next);
|
||||
end;
|
||||
|
||||
{ Function return }
|
||||
fillchar(paraloc,sizeof(tparalocation),0);
|
||||
paraloc.size:=def_cgsize(p.rettype.def);
|
||||
paraloc.Alignment:= std_param_align;
|
||||
{ Return in FPU register? }
|
||||
if p.rettype.def.deftype=floatdef then
|
||||
begin
|
||||
paraloc.loc:=LOC_FPUREGISTER;
|
||||
paraloc.register:=NR_FPU_RESULT_REG;
|
||||
end
|
||||
else
|
||||
{ Return in register? }
|
||||
if not ret_in_param(p.rettype.def,p.proccalloption) then
|
||||
begin
|
||||
paraloc.loc:=LOC_REGISTER;
|
||||
{$ifndef cpu64bit}
|
||||
if paraloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
paraloc.lochigh:=LOC_REGISTER;
|
||||
if side=callerside then
|
||||
paraloc.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
if side=callerside then
|
||||
paraloc.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
if side=callerside then
|
||||
paraloc.register:=NR_FUNCTION_RESULT_REG
|
||||
else
|
||||
paraloc.register:=NR_FUNCTION_RETURN_REG;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc.loc:=LOC_REFERENCE;
|
||||
end;
|
||||
p.funcret_paraloc[side]:=paraloc;
|
||||
{ Size on stack is not used }
|
||||
result:=0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
|
||||
begin
|
||||
if (loc.loc=LOC_REFERENCE) and
|
||||
(loc.low_in_reg) then
|
||||
cg.GetExplicitRegister(list,loc.lowreg);
|
||||
inherited allocparaloc(list,loc);
|
||||
end;
|
||||
|
||||
|
||||
procedure tsparcparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
|
||||
begin
|
||||
if (loc.loc=LOC_REFERENCE) and
|
||||
(loc.low_in_reg) then
|
||||
cg.UnGetRegister(list,loc.lowreg);
|
||||
inherited freeparaloc(list,loc);
|
||||
end;
|
||||
|
||||
procedure tsparcparamanager.splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);
|
||||
begin
|
||||
{ Word 0 is in register, word 1 is in reference }
|
||||
@ -291,13 +377,56 @@ implementation
|
||||
else
|
||||
inherited splitparaloc64(locpara,loclopara,lochipara);
|
||||
end;
|
||||
function TSparcParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargspara):longint;
|
||||
var
|
||||
cur_stack_offset: aword;
|
||||
parasize, l: longint;
|
||||
curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
|
||||
hp: tparaitem;
|
||||
paraloc: tparalocation;
|
||||
begin
|
||||
init_values(curintreg,cur_stack_offset);
|
||||
firstfloatreg:=curfloatreg;
|
||||
|
||||
result := create_paraloc_info_intern(p,callerside,tparaitem(p.para.first),curintreg,cur_stack_offset);
|
||||
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
|
||||
{ just continue loading the parameters in the registers }
|
||||
result := create_paraloc_info_intern(p,callerside,tparaitem(varargspara.first),curintreg,cur_stack_offset)
|
||||
else
|
||||
begin
|
||||
hp := tparaitem(varargspara.first);
|
||||
parasize := cur_stack_offset;
|
||||
while assigned(hp) do
|
||||
begin
|
||||
paraloc.size:=def_cgsize(hp.paratype.def);
|
||||
paraloc.lochigh:=LOC_INVALID;
|
||||
paraloc.loc:=LOC_REFERENCE;
|
||||
paraloc.alignment:=4;
|
||||
paraloc.reference.index:=NR_STACK_POINTER_REG;
|
||||
l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
|
||||
paraloc.reference.offset:=parasize;
|
||||
parasize:=parasize+l;
|
||||
hp.paraloc[callerside]:=paraloc;
|
||||
hp:=tparaitem(hp.next);
|
||||
end;
|
||||
result := parasize;
|
||||
end;
|
||||
if curfloatreg<>firstfloatreg then
|
||||
include(varargspara.varargsinfo,va_uses_float_reg);
|
||||
end;
|
||||
|
||||
begin
|
||||
ParaManager:=TSparcParaManager.create;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.37 2004-03-09 13:05:49 mazen
|
||||
Revision 1.38 2004-03-15 14:39:56 mazen
|
||||
* make sparc para manager quite similar to ppc one to help
|
||||
copying evolutions.
|
||||
+ Add support to var args in registers. need to be verfied as it
|
||||
was just copying ppc's one
|
||||
|
||||
Revision 1.37 2004/03/09 13:05:49 mazen
|
||||
+ give location for 64bit to fix IE 200402061
|
||||
|
||||
Revision 1.36 2004/02/25 14:25:47 mazen
|
||||
|
Loading…
Reference in New Issue
Block a user