mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-21 05:09:31 +02:00
* Stack setup for MIPS and MIPSEL
git-svn-id: trunk@21537 -
This commit is contained in:
parent
4d8ebe5d1e
commit
22eae1b337
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user