* 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:
mazen 2004-03-15 14:39:56 +00:00
parent 5d851cb954
commit 5962aeb34e

View File

@ -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