* 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,
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
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 get_volatile_registers_int(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;
private
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var intparareg,parasize:longint);
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
end;
implementation
uses
cutils,verbose,systems,
defutil,
defutil, cpupi, procinfo,
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;
@ -90,17 +100,22 @@ implementation
begin
{ The six first parameters are passed into registers } {MIPS first four}
dec(nr);
if nr<6 then //MIPSEL nr<6
if nr<MIPS_MAX_REGISTERS_USED_IN_CALL then //MIPSEL nr<6
begin
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
else
begin
{ The other parameters are passed on the stack }
loc:=LOC_REFERENCE;
reference.index:=NR_STACK_POINTER_REG;
reference.offset:=92+(nr-6)*4;
reference.offset:={92+(nr-6)*4;} nr*4;
end;
size:=OS_INT;
end;
@ -169,12 +184,26 @@ implementation
result.intsize:=def.size;
end;
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
begin
paraloc:=result.add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=retcgsize;
{ Reserve first register for ret_in_param }
if intparareg=0 then
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;
end;
@ -223,11 +252,8 @@ implementation
end
end;
var
param_offset:array[0..20] of ^Aint;
procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
var intparareg,parasize:longint);
procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist);
var
paraloc : pcgparalocation;
i : integer;
@ -242,8 +268,8 @@ implementation
hparasupregs:=@parainsupregs;
for i:=0 to paras.count-1 do
begin
param_offset[i] := Nil;
if i<=MIPS_MAX_OFFSET then
param_offset[i] := Nil;
hp:=tparavarsym(paras[i]);
{ currently only support C-style array of const,
there should be no location assigned to the vararg array itself }
@ -283,17 +309,26 @@ implementation
{ ret in param? }
if vo_is_funcret in hp.varoptions then
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
begin
paraloc^.reference.index := NR_STACK_POINTER_REG;
paraloc^.reference.offset:=parasize;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[0],R_SUBWHOLE);
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index := NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
param_offset[i] := @paraloc^.reference.offset;
paraloc^.reference.offset:=0;
if i<=MIPS_MAX_OFFSET then
param_offset[i] := @paraloc^.reference.offset;
end;
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
end
@ -303,9 +338,27 @@ implementation
(not(vo_is_parentfp in hp.varoptions) or
not(po_delphi_nested_cc in p.procoptions)) then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
if assigned(current_procinfo) then
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(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
end
else
begin
@ -317,9 +370,13 @@ implementation
end
else
begin
paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
param_offset[i] := @paraloc^.reference.offset;
//if assigned(current_procinfo) then
// paraloc^.reference.index := current_procinfo.framepointer
//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;
{ Parameters are aligned at 4 bytes }
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
@ -338,31 +395,27 @@ implementation
function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
var
intparareg,
parasize : longint;
begin
intparareg:=0;
parasize:=0;
{ Create Function result paraloc }
create_funcretloc_info(p,callerside);
{ 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 }
create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
create_paraloc_info_intern(p,callerside,varargspara);
result:=parasize;
end;
function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
var
intparareg,
parasize : longint;
begin
intparareg:=0;
parasize:=0;
create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
{ Create Function result paraloc }
create_funcretloc_info(p,side);
create_paraloc_info_intern(p,side,p.paras);
{ We need to return the size allocated on the stack }
result:=parasize;
end;

View File

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