* Stack setup for MIPS and MIPSEL

git-svn-id: trunk@21537 -
This commit is contained in:
pierre 2012-06-07 23:19:33 +00:00
parent 4d8ebe5d1e
commit 22eae1b337
2 changed files with 106 additions and 42 deletions

View File

@ -30,8 +30,25 @@ interface
cpubase,cpuinfo, cpubase,cpuinfo,
symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase; symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
const
MIPS_MAX_OFFSET = 20;
MIPS_MAX_REGISTERS_USED_IN_CALL = 6;
MIPS_FIRST_REGISTER_USED_IN_CALL = RS_R4;
type
tparasupregs = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tsuperregister;
tparasupregsused = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of boolean;
tparasupregsoffset = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of longint;
pparasupregs = ^tparasupregs;
const
paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
parainsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
type type
TMIPSParaManager=class(TParaManager) TMIPSParaManager=class(TParaManager)
var
param_offset:array[0..MIPS_MAX_OFFSET] of ^Aint;
intparareg,
parasize : longint;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override; function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override; function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
@ -44,23 +61,16 @@ interface
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
private private
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
var intparareg,parasize:longint);
end; end;
implementation implementation
uses uses
cutils,verbose,systems, cutils,verbose,systems,
defutil, defutil, cpupi, procinfo,
cgutils,cgobj; cgutils,cgobj;
type
tparasupregs = array[0..5] of tsuperregister;
pparasupregs = ^tparasupregs;
const
paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
parainsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
function TMIPSParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet; function TMIPSParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
@ -90,17 +100,22 @@ implementation
begin begin
{ The six first parameters are passed into registers } {MIPS first four} { The six first parameters are passed into registers } {MIPS first four}
dec(nr); dec(nr);
if nr<6 then //MIPSEL nr<6 if nr<MIPS_MAX_REGISTERS_USED_IN_CALL then //MIPSEL nr<6
begin begin
loc:=LOC_REGISTER; loc:=LOC_REGISTER;
register:=newreg(R_INTREGISTER,(RS_R4+nr),R_SUBWHOLE); register:=newreg(R_INTREGISTER,paraoutsupregs[nr],R_SUBWHOLE);
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[nr]:=true;
TMIPSProcInfo(current_procinfo).register_offset[nr]:=nr*4;
end;
end end
else else
begin begin
{ The other parameters are passed on the stack } { The other parameters are passed on the stack }
loc:=LOC_REFERENCE; loc:=LOC_REFERENCE;
reference.index:=NR_STACK_POINTER_REG; reference.index:=NR_STACK_POINTER_REG;
reference.offset:=92+(nr-6)*4; reference.offset:={92+(nr-6)*4;} nr*4;
end; end;
size:=OS_INT; size:=OS_INT;
end; end;
@ -169,12 +184,26 @@ implementation
result.intsize:=def.size; result.intsize:=def.size;
end; end;
result.size:=retcgsize; result.size:=retcgsize;
{ Return is passed as var parameter } { Return is passed as var parameter,
in this case we use the first register R4 for it }
if ret_in_param(def,p.proccalloption) then if ret_in_param(def,p.proccalloption) then
begin begin
paraloc:=result.add_location; { Reserve first register for ret_in_param }
paraloc^.loc:=LOC_REFERENCE; if intparareg=0 then
paraloc^.size:=retcgsize; inc(intparareg);
if side=calleeside then
begin
paraloc:=result.add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
{ return is at offset zero }
paraloc^.reference.offset:=0;
paraloc^.size:=retcgsize;
end
else
begin
getIntParaLoc(p.proccalloption,1,result);
end;
exit; exit;
end; end;
@ -223,11 +252,8 @@ implementation
end end
end; end;
var
param_offset:array[0..20] of ^Aint;
procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist; procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist);
var intparareg,parasize:longint);
var var
paraloc : pcgparalocation; paraloc : pcgparalocation;
i : integer; i : integer;
@ -242,8 +268,8 @@ implementation
hparasupregs:=@parainsupregs; hparasupregs:=@parainsupregs;
for i:=0 to paras.count-1 do for i:=0 to paras.count-1 do
begin begin
if i<=MIPS_MAX_OFFSET then
param_offset[i] := Nil; param_offset[i] := Nil;
hp:=tparavarsym(paras[i]); hp:=tparavarsym(paras[i]);
{ currently only support C-style array of const, { currently only support C-style array of const,
there should be no location assigned to the vararg array itself } there should be no location assigned to the vararg array itself }
@ -283,17 +309,26 @@ implementation
{ ret in param? } { ret in param? }
if vo_is_funcret in hp.varoptions then if vo_is_funcret in hp.varoptions then
begin begin
paraloc^.loc:=LOC_REFERENCE; { This should be the first parameter }
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
end;
//if (intparareg<>1) then
// Comment(V_Warning,'intparareg should be one for funcret in TMipsParaManager.create_paraloc_info_intern');
if side=callerside then if side=callerside then
begin begin
paraloc^.reference.index := NR_STACK_POINTER_REG; paraloc^.loc:=LOC_REGISTER;
paraloc^.reference.offset:=parasize; paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[0],R_SUBWHOLE);
end end
else else
begin begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index := NR_FRAME_POINTER_REG; paraloc^.reference.index := NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=target_info.first_parm_offset+parasize; paraloc^.reference.offset:=0;
param_offset[i] := @paraloc^.reference.offset; if i<=MIPS_MAX_OFFSET then
param_offset[i] := @paraloc^.reference.offset;
end; end;
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint))); inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
end end
@ -303,9 +338,27 @@ implementation
(not(vo_is_parentfp in hp.varoptions) or (not(vo_is_parentfp in hp.varoptions) or
not(po_delphi_nested_cc in p.procoptions)) then not(po_delphi_nested_cc in p.procoptions)) then
begin begin
paraloc^.loc:=LOC_REGISTER; if assigned(current_procinfo) then
paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE); begin
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*4;
end;
if side=callerside then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
//if assigned(current_procinfo) then
// paraloc^.reference.index := current_procinfo.framepointer
//else
paraloc^.reference.index := NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=intparareg*sizeof(aint);
end;
inc(intparareg); inc(intparareg);
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
end end
else else
begin begin
@ -317,9 +370,13 @@ implementation
end end
else else
begin begin
paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG; //if assigned(current_procinfo) then
paraloc^.reference.offset:=target_info.first_parm_offset+parasize; // paraloc^.reference.index := current_procinfo.framepointer
param_offset[i] := @paraloc^.reference.offset; //else
paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=parasize;
if i<=MIPS_MAX_OFFSET then
param_offset[i] := @paraloc^.reference.offset;
end; end;
{ Parameters are aligned at 4 bytes } { Parameters are aligned at 4 bytes }
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint))); inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
@ -338,31 +395,27 @@ implementation
function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
var
intparareg,
parasize : longint;
begin begin
intparareg:=0; intparareg:=0;
parasize:=0; parasize:=0;
{ Create Function result paraloc }
create_funcretloc_info(p,callerside);
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize); create_paraloc_info_intern(p,callerside,p.paras);
{ append the varargs } { append the varargs }
create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize); create_paraloc_info_intern(p,callerside,varargspara);
result:=parasize; result:=parasize;
end; end;
function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint; function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
var
intparareg,
parasize : longint;
begin begin
intparareg:=0; intparareg:=0;
parasize:=0; parasize:=0;
create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
{ Create Function result paraloc } { Create Function result paraloc }
create_funcretloc_info(p,side); create_funcretloc_info(p,side);
create_paraloc_info_intern(p,side,p.paras);
{ We need to return the size allocated on the stack } { We need to return the size allocated on the stack }
result:=parasize; result:=parasize;
end; end;

View File

@ -28,7 +28,7 @@ interface
uses uses
cutils, cutils,
globtype, globtype,
procinfo,cpuinfo, procinfo,cpuinfo,cpupara,
psub; psub;
type type
@ -40,6 +40,8 @@ interface
floatregstart : aint; floatregstart : aint;
intregssave, intregssave,
floatregssave : byte; floatregssave : byte;
register_used : tparasupregsused;
register_offset : tparasupregsoffset;
constructor create(aparent:tprocinfo);override; constructor create(aparent:tprocinfo);override;
function calc_stackframe_size:longint;override; function calc_stackframe_size:longint;override;
procedure set_first_temp_offset;override; procedure set_first_temp_offset;override;
@ -53,8 +55,16 @@ implementation
tgobj,paramgr,symconst; tgobj,paramgr,symconst;
constructor TMIPSProcInfo.create(aparent: tprocinfo); constructor TMIPSProcInfo.create(aparent: tprocinfo);
var
i : longint;
begin begin
inherited create(aparent); inherited create(aparent);
for i:=low(tparasupregs) to high(tparasupregs) do
begin
register_used[i]:=false;
register_offset[i]:=-1;
end;
floatregssave:=11; floatregssave:=11;
intregssave:=10; intregssave:=10;
end; end;
@ -81,6 +91,7 @@ implementation
floatregstart:=result; floatregstart:=result;
inc(result,floatregssave*4); inc(result,floatregssave*4);
intregstart:=result; intregstart:=result;
inc(result,intregssave*4);
result:=Align(tg.lasttemp,max(current_settings.alignment.localalignmin,8)); result:=Align(tg.lasttemp,max(current_settings.alignment.localalignmin,8));
end; end;