mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 20:49:19 +02:00
MIPS procinfo improvements:
- Removed TMIPSProcInfo.needs_frame_pointer, it duplicates pi_needs_stackframe flag. - Don't save RA for leaf procedures. * GP is caller-saved register, it does not need saving/restoring as nonvolatile registers. Handle its restore position as a "normal" temp, whose offset is known before secondpass. This allows to handle PIC calls without involving GAS macro processing. git-svn-id: trunk@23885 -
This commit is contained in:
parent
d5985b4f0e
commit
1c652eb8f9
@ -1203,7 +1203,7 @@ begin
|
|||||||
if nostackframe then
|
if nostackframe then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
if (pi_needs_stackframe in current_procinfo.flags) then
|
||||||
a_reg_alloc(list,NR_FRAME_POINTER_REG);
|
a_reg_alloc(list,NR_FRAME_POINTER_REG);
|
||||||
|
|
||||||
helplist:=TAsmList.Create;
|
helplist:=TAsmList.Create;
|
||||||
@ -1236,15 +1236,12 @@ begin
|
|||||||
mask:=0;
|
mask:=0;
|
||||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||||
include(saveregs,RS_R31);
|
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
|
||||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
include(saveregs,RS_R31);
|
||||||
|
if (pi_needs_stackframe in current_procinfo.flags) then
|
||||||
include(saveregs,RS_FRAME_POINTER_REG);
|
include(saveregs,RS_FRAME_POINTER_REG);
|
||||||
if (cs_create_pic in current_settings.moduleswitches) and
|
|
||||||
(pi_needs_got in current_procinfo.flags) then
|
|
||||||
include(saveregs,RS_GP);
|
|
||||||
lastintoffset:=LocalSize;
|
lastintoffset:=LocalSize;
|
||||||
framesave:=nil;
|
framesave:=nil;
|
||||||
gp_save:=nil;
|
|
||||||
ra_save:=nil;
|
ra_save:=nil;
|
||||||
|
|
||||||
for reg:=RS_R1 to RS_R31 do
|
for reg:=RS_R1 to RS_R31 do
|
||||||
@ -1258,10 +1255,6 @@ begin
|
|||||||
framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
|
framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
|
||||||
else if (reg=RS_R31) then
|
else if (reg=RS_R31) then
|
||||||
ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
|
ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
|
||||||
else if (reg=RS_GP) and
|
|
||||||
(cs_create_pic in current_settings.moduleswitches) and
|
|
||||||
(pi_needs_got in current_procinfo.flags) then
|
|
||||||
gp_save:=taicpu.op_const(A_P_CPRESTORE,nextoffset)
|
|
||||||
else
|
else
|
||||||
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
|
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
|
||||||
inc(nextoffset,4);
|
inc(nextoffset,4);
|
||||||
@ -1311,10 +1304,11 @@ begin
|
|||||||
even use AT register, which is why we use R9 instead of AT here for -LocalSize }
|
even use AT register, which is why we use R9 instead of AT here for -LocalSize }
|
||||||
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
|
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
|
||||||
end;
|
end;
|
||||||
if assigned(gp_save) then
|
if (cs_create_pic in current_settings.moduleswitches) and
|
||||||
|
(pi_needs_got in current_procinfo.flags) then
|
||||||
begin
|
begin
|
||||||
list.concat(Taicpu.op_none(A_P_SET_MACRO));
|
list.concat(Taicpu.op_none(A_P_SET_MACRO));
|
||||||
list.concat(gp_save);
|
list.concat(Taicpu.op_const(A_P_CPRESTORE,TMIPSProcinfo(current_procinfo).save_gp_ref.offset));
|
||||||
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
|
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1338,11 +1332,6 @@ begin
|
|||||||
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
|
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if (cs_create_pic in current_settings.moduleswitches) and
|
|
||||||
(pi_needs_got in current_procinfo.flags) then
|
|
||||||
begin
|
|
||||||
current_procinfo.got := NR_GP;
|
|
||||||
end;
|
|
||||||
list.concatList(helplist);
|
list.concatList(helplist);
|
||||||
helplist.Free;
|
helplist.Free;
|
||||||
end;
|
end;
|
||||||
@ -1382,12 +1371,11 @@ begin
|
|||||||
|
|
||||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||||
include(saveregs,RS_R31);
|
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
|
||||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
include(saveregs,RS_R31);
|
||||||
|
if (pi_needs_stackframe in current_procinfo.flags) then
|
||||||
include(saveregs,RS_FRAME_POINTER_REG);
|
include(saveregs,RS_FRAME_POINTER_REG);
|
||||||
if (cs_create_pic in current_settings.moduleswitches) and
|
// GP does not need to be restored on exit
|
||||||
(pi_needs_got in current_procinfo.flags) then
|
|
||||||
include(saveregs,RS_GP);
|
|
||||||
for reg:=RS_R1 to RS_R31 do
|
for reg:=RS_R1 to RS_R31 do
|
||||||
begin
|
begin
|
||||||
if reg in saveregs then
|
if reg in saveregs then
|
||||||
|
@ -450,7 +450,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
||||||
if assigned(current_procinfo) then
|
if assigned(current_procinfo) then
|
||||||
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
|
include(current_procinfo.flags,pi_needs_stackframe);
|
||||||
end;
|
end;
|
||||||
paraloc^.reference.offset:=intparasize;
|
paraloc^.reference.offset:=intparasize;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ interface
|
|||||||
cutils,
|
cutils,
|
||||||
globtype,symdef,
|
globtype,symdef,
|
||||||
procinfo,cpuinfo,cpupara,
|
procinfo,cpuinfo,cpupara,
|
||||||
psub;
|
psub,aasmdata,cgutils;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -40,17 +40,18 @@ interface
|
|||||||
floatregstart : aint;
|
floatregstart : aint;
|
||||||
intregssave,
|
intregssave,
|
||||||
floatregssave : byte;
|
floatregssave : byte;
|
||||||
needs_frame_pointer: boolean;
|
|
||||||
register_used : tparasupregsused;
|
register_used : tparasupregsused;
|
||||||
register_size : tparasupregsize;
|
register_size : tparasupregsize;
|
||||||
register_name : tparasuprename;
|
register_name : tparasuprename;
|
||||||
register_offset : tparasupregsoffset;
|
register_offset : tparasupregsoffset;
|
||||||
computed_local_size : longint;
|
computed_local_size : longint;
|
||||||
|
save_gp_ref: treference;
|
||||||
//intparareg,
|
//intparareg,
|
||||||
//parasize : longint;
|
//parasize : longint;
|
||||||
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;
|
||||||
|
procedure allocate_got_register(list:tasmlist);override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Used by Stabs debug info generator }
|
{ Used by Stabs debug info generator }
|
||||||
@ -61,7 +62,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
systems,globals,verbose,
|
systems,globals,verbose,
|
||||||
cpubase,cgbase,cgutils,cgobj,
|
cpubase,cgbase,cgobj,
|
||||||
tgobj,paramgr,symconst;
|
tgobj,paramgr,symconst;
|
||||||
|
|
||||||
constructor TMIPSProcInfo.create(aparent: tprocinfo);
|
constructor TMIPSProcInfo.create(aparent: tprocinfo);
|
||||||
@ -69,9 +70,9 @@ implementation
|
|||||||
i : longint;
|
i : longint;
|
||||||
begin
|
begin
|
||||||
inherited create(aparent);
|
inherited create(aparent);
|
||||||
{ will call _mcount if profiling }
|
{ if (cs_generate_stackframes in current_settings.localswitches) or
|
||||||
if cs_profile in current_settings.moduleswitches then
|
not (cs_opt_stackframe in current_settings.optimizerswitches) then }
|
||||||
include(flags,pi_do_call);
|
include(flags,pi_needs_stackframe);
|
||||||
for i:=low(tparasupregs) to high(tparasupregs) do
|
for i:=low(tparasupregs) to high(tparasupregs) do
|
||||||
begin
|
begin
|
||||||
register_used[i]:=false;
|
register_used[i]:=false;
|
||||||
@ -80,9 +81,7 @@ implementation
|
|||||||
register_offset[i]:=-1;
|
register_offset[i]:=-1;
|
||||||
end;
|
end;
|
||||||
floatregssave:=12; { f20-f31 }
|
floatregssave:=12; { f20-f31 }
|
||||||
intregssave:=12; { r16-r23,r28-r31 }
|
intregssave:=10; { r16-r23,r30,r31 }
|
||||||
{ for testing }
|
|
||||||
needs_frame_pointer := true;//false;
|
|
||||||
computed_local_size:=-1;
|
computed_local_size:=-1;
|
||||||
{ pi_needs_got is not yet set correctly
|
{ pi_needs_got is not yet set correctly
|
||||||
so include it always if creating PIC code }
|
so include it always if creating PIC code }
|
||||||
@ -98,28 +97,42 @@ implementation
|
|||||||
|
|
||||||
procedure TMIPSProcInfo.set_first_temp_offset;
|
procedure TMIPSProcInfo.set_first_temp_offset;
|
||||||
begin
|
begin
|
||||||
|
{ MIPS stack frame is always "optimized" }
|
||||||
|
framepointer:=NR_STACK_POINTER_REG;
|
||||||
|
tg.direction:=1;
|
||||||
|
|
||||||
{ We allocate enough space to save all registers because we can't determine
|
{ We allocate enough space to save all registers because we can't determine
|
||||||
the necessary space because the used registers aren't known before
|
the necessary space because the used registers aren't known before
|
||||||
secondpass is run. }
|
secondpass is run. }
|
||||||
if tg.direction = -1 then
|
|
||||||
tg.setfirsttemp(0)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ Fixes the case when there are calls done by low-level means
|
|
||||||
(cg.a_call_name) but no child callnode. !!For assembler procedure
|
|
||||||
there is no clean way to determine what it calls, unless it is
|
|
||||||
also declared as nostackframe and everything is managed manually. }
|
|
||||||
if (pi_do_call in flags) or
|
|
||||||
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
|
|
||||||
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
|
|
||||||
|
|
||||||
if not (po_nostackframe in procdef.procoptions) then
|
{ will call _mcount if profiling }
|
||||||
tg.setfirsttemp(Align(maxpushedparasize+
|
if (cs_profile in current_settings.moduleswitches) and
|
||||||
floatregssave*sizeof(aint)+intregssave*sizeof(aint)
|
not (po_nostackframe in procdef.procoptions) then
|
||||||
,max(current_settings.alignment.localalignmin,8)))
|
include(flags,pi_do_call);
|
||||||
else
|
|
||||||
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
|
{ Fixes the case when there are calls done by low-level means
|
||||||
end;
|
(cg.a_call_name) but no child callnode. !!For assembler procedure
|
||||||
|
there is no clean way to determine what it calls, unless it is
|
||||||
|
also declared as nostackframe and everything is managed manually. }
|
||||||
|
if (pi_do_call in flags) or
|
||||||
|
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
|
||||||
|
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
|
||||||
|
|
||||||
|
if not (po_nostackframe in procdef.procoptions) then
|
||||||
|
tg.setfirsttemp(Align(maxpushedparasize+
|
||||||
|
floatregssave*sizeof(aint)+intregssave*sizeof(aint)
|
||||||
|
,max(current_settings.alignment.localalignmin,8)))
|
||||||
|
else
|
||||||
|
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TMIPSProcInfo.allocate_got_register(list:tasmlist);
|
||||||
|
begin
|
||||||
|
if (cs_create_pic in current_settings.moduleswitches) and
|
||||||
|
(pi_needs_got in flags) and
|
||||||
|
not (po_nostackframe in procdef.procoptions) then
|
||||||
|
tg.gettemp(list,sizeof(aint),sizeof(aint),tt_noreuse,save_gp_ref);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user