mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 05:08:06 +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
|
||||
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);
|
||||
|
||||
helplist:=TAsmList.Create;
|
||||
@ -1236,15 +1236,12 @@ begin
|
||||
mask:=0;
|
||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||
include(saveregs,RS_R31);
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
||||
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
|
||||
include(saveregs,RS_R31);
|
||||
if (pi_needs_stackframe in current_procinfo.flags) then
|
||||
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;
|
||||
framesave:=nil;
|
||||
gp_save:=nil;
|
||||
ra_save:=nil;
|
||||
|
||||
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)
|
||||
else if (reg=RS_R31) then
|
||||
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
|
||||
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
|
||||
inc(nextoffset,4);
|
||||
@ -1311,10 +1304,11 @@ begin
|
||||
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));
|
||||
end;
|
||||
if assigned(gp_save) then
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
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));
|
||||
end;
|
||||
|
||||
@ -1338,11 +1332,6 @@ begin
|
||||
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
|
||||
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);
|
||||
helplist.Free;
|
||||
end;
|
||||
@ -1382,12 +1371,11 @@ begin
|
||||
|
||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||
include(saveregs,RS_R31);
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
||||
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
|
||||
include(saveregs,RS_R31);
|
||||
if (pi_needs_stackframe in current_procinfo.flags) then
|
||||
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);
|
||||
// GP does not need to be restored on exit
|
||||
for reg:=RS_R1 to RS_R31 do
|
||||
begin
|
||||
if reg in saveregs then
|
||||
|
@ -450,7 +450,7 @@ implementation
|
||||
begin
|
||||
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
||||
if assigned(current_procinfo) then
|
||||
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
|
||||
include(current_procinfo.flags,pi_needs_stackframe);
|
||||
end;
|
||||
paraloc^.reference.offset:=intparasize;
|
||||
|
||||
|
@ -29,7 +29,7 @@ interface
|
||||
cutils,
|
||||
globtype,symdef,
|
||||
procinfo,cpuinfo,cpupara,
|
||||
psub;
|
||||
psub,aasmdata,cgutils;
|
||||
|
||||
type
|
||||
|
||||
@ -40,17 +40,18 @@ interface
|
||||
floatregstart : aint;
|
||||
intregssave,
|
||||
floatregssave : byte;
|
||||
needs_frame_pointer: boolean;
|
||||
register_used : tparasupregsused;
|
||||
register_size : tparasupregsize;
|
||||
register_name : tparasuprename;
|
||||
register_offset : tparasupregsoffset;
|
||||
computed_local_size : longint;
|
||||
save_gp_ref: treference;
|
||||
//intparareg,
|
||||
//parasize : longint;
|
||||
constructor create(aparent:tprocinfo);override;
|
||||
function calc_stackframe_size:longint;override;
|
||||
procedure set_first_temp_offset;override;
|
||||
procedure allocate_got_register(list:tasmlist);override;
|
||||
end;
|
||||
|
||||
{ Used by Stabs debug info generator }
|
||||
@ -61,7 +62,7 @@ implementation
|
||||
|
||||
uses
|
||||
systems,globals,verbose,
|
||||
cpubase,cgbase,cgutils,cgobj,
|
||||
cpubase,cgbase,cgobj,
|
||||
tgobj,paramgr,symconst;
|
||||
|
||||
constructor TMIPSProcInfo.create(aparent: tprocinfo);
|
||||
@ -69,9 +70,9 @@ implementation
|
||||
i : longint;
|
||||
begin
|
||||
inherited create(aparent);
|
||||
{ will call _mcount if profiling }
|
||||
if cs_profile in current_settings.moduleswitches then
|
||||
include(flags,pi_do_call);
|
||||
{ if (cs_generate_stackframes in current_settings.localswitches) or
|
||||
not (cs_opt_stackframe in current_settings.optimizerswitches) then }
|
||||
include(flags,pi_needs_stackframe);
|
||||
for i:=low(tparasupregs) to high(tparasupregs) do
|
||||
begin
|
||||
register_used[i]:=false;
|
||||
@ -80,9 +81,7 @@ implementation
|
||||
register_offset[i]:=-1;
|
||||
end;
|
||||
floatregssave:=12; { f20-f31 }
|
||||
intregssave:=12; { r16-r23,r28-r31 }
|
||||
{ for testing }
|
||||
needs_frame_pointer := true;//false;
|
||||
intregssave:=10; { r16-r23,r30,r31 }
|
||||
computed_local_size:=-1;
|
||||
{ pi_needs_got is not yet set correctly
|
||||
so include it always if creating PIC code }
|
||||
@ -98,28 +97,42 @@ implementation
|
||||
|
||||
procedure TMIPSProcInfo.set_first_temp_offset;
|
||||
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
|
||||
the necessary space because the used registers aren't known before
|
||||
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
|
||||
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;
|
||||
{ will call _mcount if profiling }
|
||||
if (cs_profile in current_settings.moduleswitches) and
|
||||
not (po_nostackframe in procdef.procoptions) then
|
||||
include(flags,pi_do_call);
|
||||
|
||||
{ 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
|
||||
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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user