mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 03:39:33 +02:00
* stack frame optimizations
git-svn-id: trunk@2172 -
This commit is contained in:
parent
21d51d8815
commit
3462426b1d
@ -136,6 +136,9 @@ implementation
|
|||||||
{$ifdef powerpc}
|
{$ifdef powerpc}
|
||||||
, cpupi
|
, cpupi
|
||||||
{$endif}
|
{$endif}
|
||||||
|
{$ifdef powerpc64}
|
||||||
|
, cpupi
|
||||||
|
{$endif}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -1346,10 +1349,10 @@ implementation
|
|||||||
case paraloc.loc of
|
case paraloc.loc of
|
||||||
LOC_REGISTER :
|
LOC_REGISTER :
|
||||||
begin
|
begin
|
||||||
{$IFDEF CPUPOWERPC64}
|
{$IFDEF POWERPC64}
|
||||||
if (paraloc.shiftval <> 0) then
|
if (paraloc.shiftval <> 0) then
|
||||||
cg.a_op_const_reg_reg(list, OP_SHL, OS_INT, paraloc.shiftval, paraloc.register, paraloc.register);
|
cg.a_op_const_reg_reg(list, OP_SHL, OS_INT, paraloc.shiftval, paraloc.register, paraloc.register);
|
||||||
{$ENDIF CPUPOWERPC64}
|
{$ENDIF POWERPC64}
|
||||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
|
cg.a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
|
||||||
end;
|
end;
|
||||||
LOC_MMREGISTER :
|
LOC_MMREGISTER :
|
||||||
@ -1576,6 +1579,7 @@ implementation
|
|||||||
{$ifdef powerpc64}
|
{$ifdef powerpc64}
|
||||||
{ unget the register that contains the stack pointer before the procedure entry, }
|
{ unget the register that contains the stack pointer before the procedure entry, }
|
||||||
{ which is used to access the parameters in their original callee-side location }
|
{ which is used to access the parameters in their original callee-side location }
|
||||||
|
if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
|
||||||
cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
|
cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
|
||||||
{$endif powerpc64}
|
{$endif powerpc64}
|
||||||
end;
|
end;
|
||||||
|
@ -129,6 +129,8 @@ type
|
|||||||
{ the sum of part of the original reference }
|
{ the sum of part of the original reference }
|
||||||
function fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
function fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
||||||
|
|
||||||
|
function load_got_symbol(list : taasmoutput; symbol : string) : tregister;
|
||||||
|
|
||||||
{ returns whether a reference can be used immediately in a powerpc }
|
{ returns whether a reference can be used immediately in a powerpc }
|
||||||
{ instruction }
|
{ instruction }
|
||||||
function issimpleref(const ref: treference): boolean;
|
function issimpleref(const ref: treference): boolean;
|
||||||
@ -1304,7 +1306,8 @@ begin
|
|||||||
{ determine whether we need to save the link register }
|
{ determine whether we need to save the link register }
|
||||||
needslinkreg :=
|
needslinkreg :=
|
||||||
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or
|
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or
|
||||||
((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0)));
|
((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0))) or
|
||||||
|
([cs_lineinfo, cs_debuginfo] * aktmoduleswitches <> []);
|
||||||
|
|
||||||
a_reg_alloc(list, NR_STACK_POINTER_REG);
|
a_reg_alloc(list, NR_STACK_POINTER_REG);
|
||||||
a_reg_alloc(list, NR_R0);
|
a_reg_alloc(list, NR_R0);
|
||||||
@ -1316,7 +1319,7 @@ begin
|
|||||||
save_standard_registers;
|
save_standard_registers;
|
||||||
|
|
||||||
{ save old stack frame pointer }
|
{ save old stack frame pointer }
|
||||||
if (localsize > 0) then begin
|
if (tppcprocinfo(current_procinfo).needs_frame_pointer) then begin
|
||||||
a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
|
a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
|
||||||
list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
|
list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
|
||||||
end;
|
end;
|
||||||
@ -1441,7 +1444,8 @@ begin
|
|||||||
{ determine whether we need to restore the link register }
|
{ determine whether we need to restore the link register }
|
||||||
needslinkreg :=
|
needslinkreg :=
|
||||||
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or
|
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or
|
||||||
((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0)));
|
((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0))) or
|
||||||
|
([cs_lineinfo, cs_debuginfo] * aktmoduleswitches <> []);
|
||||||
|
|
||||||
{ calculate stack frame }
|
{ calculate stack frame }
|
||||||
localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
|
localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
|
||||||
@ -1819,13 +1823,41 @@ begin
|
|||||||
(ref.offset = 0)));
|
(ref.offset = 0)));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function tcgppc.load_got_symbol(list: taasmoutput; symbol : string) : tregister;
|
||||||
|
var
|
||||||
|
l: tasmsymbol;
|
||||||
|
ref: treference;
|
||||||
|
begin
|
||||||
|
l:=objectlibrary.getasmsymbol(symbol+'$got');
|
||||||
|
if not(assigned(l)) then begin
|
||||||
|
l:=objectlibrary.newasmsymbol(symbol+'$got',AB_COMMON,AT_DATA);
|
||||||
|
asmlist[al_picdata].concat(tai_symbol.create(l,0));
|
||||||
|
asmlist[al_picdata].concat(tai_const.create_indirect_sym(objectlibrary.newasmsymbol(symbol,AB_EXTERNAL,AT_DATA)));
|
||||||
|
asmlist[al_picdata].concat(tai_const.create_32bit(0));
|
||||||
|
end;
|
||||||
|
reference_reset_symbol(ref,l,0);
|
||||||
|
ref.base := NR_R2;
|
||||||
|
result := cg.rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
||||||
|
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
|
||||||
|
end;
|
||||||
|
|
||||||
function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
||||||
var
|
var
|
||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
needsAlign : boolean;
|
name : string;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
needsAlign := size in [OS_S32, OS_64, OS_S64];
|
if (cs_create_pic in aktmoduleswitches) and (assigned(ref.symbol)) and (ref.symbol.defbind = AB_EXTERNAL) then begin
|
||||||
|
if (length(name) > 100) then internalerror(123456);
|
||||||
|
tmpreg := load_got_symbol(list, ref.symbol.name);
|
||||||
|
if (ref.base = NR_NO) then
|
||||||
|
ref.base := tmpreg
|
||||||
|
else if (ref.index = NR_NO) then
|
||||||
|
ref.index := tmpreg
|
||||||
|
else
|
||||||
|
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.base,tmpreg));
|
||||||
|
ref.symbol := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
if (ref.base = NR_NO) then begin
|
if (ref.base = NR_NO) then begin
|
||||||
ref.base := ref.index;
|
ref.base := ref.index;
|
||||||
|
@ -370,6 +370,10 @@ const
|
|||||||
|
|
||||||
ELF_STACK_ALIGN = 16;
|
ELF_STACK_ALIGN = 16;
|
||||||
|
|
||||||
|
{ the size of the "red zone" which must not be changed by asynchronous calls
|
||||||
|
in the stack frame and can be used for storing temps }
|
||||||
|
RED_ZONE_SIZE = 288;
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
Helpers
|
Helpers
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
@ -62,7 +62,8 @@ implementation
|
|||||||
uses
|
uses
|
||||||
verbose, systems,
|
verbose, systems,
|
||||||
defutil,
|
defutil,
|
||||||
cgutils;
|
cgutils,
|
||||||
|
procinfo, cpupi;
|
||||||
|
|
||||||
function tppcparamanager.get_volatile_registers_int(calloption:
|
function tppcparamanager.get_volatile_registers_int(calloption:
|
||||||
tproccalloption): tcpuregisterset;
|
tproccalloption): tcpuregisterset;
|
||||||
@ -417,9 +418,11 @@ begin
|
|||||||
paraloc^.size := int_cgsize(paralen);
|
paraloc^.size := int_cgsize(paralen);
|
||||||
if (side = callerside) then
|
if (side = callerside) then
|
||||||
paraloc^.reference.index := NR_STACK_POINTER_REG
|
paraloc^.reference.index := NR_STACK_POINTER_REG
|
||||||
else
|
else begin
|
||||||
{ during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
|
{ during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
|
||||||
paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
|
paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
|
||||||
|
tppcprocinfo(current_procinfo).needs_frame_pointer := true;
|
||||||
|
end;
|
||||||
paraloc^.reference.offset := stack_offset;
|
paraloc^.reference.offset := stack_offset;
|
||||||
|
|
||||||
{ align temp contents to next register size }
|
{ align temp contents to next register size }
|
||||||
|
@ -40,6 +40,8 @@ type
|
|||||||
procedure allocate_push_parasize(size: longint); override;
|
procedure allocate_push_parasize(size: longint); override;
|
||||||
function calc_stackframe_size: longint; override;
|
function calc_stackframe_size: longint; override;
|
||||||
function calc_stackframe_size(numgpr, numfpr : longint): longint;
|
function calc_stackframe_size(numgpr, numfpr : longint): longint;
|
||||||
|
|
||||||
|
needs_frame_pointer : boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -57,6 +59,7 @@ constructor tppcprocinfo.create(aparent: tprocinfo);
|
|||||||
begin
|
begin
|
||||||
inherited create(aparent);
|
inherited create(aparent);
|
||||||
maxpushedparasize := 0;
|
maxpushedparasize := 0;
|
||||||
|
needs_frame_pointer := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tppcprocinfo.set_first_temp_offset;
|
procedure tppcprocinfo.set_first_temp_offset;
|
||||||
@ -100,8 +103,12 @@ begin
|
|||||||
{ more or less copied from cgcpu.pas/g_stackframe_entry }
|
{ more or less copied from cgcpu.pas/g_stackframe_entry }
|
||||||
if not (po_assembler in procdef.procoptions) then begin
|
if not (po_assembler in procdef.procoptions) then begin
|
||||||
// no VMX support
|
// no VMX support
|
||||||
result := align(align(numgpr * tcgsize2size[OS_INT] +
|
result := align(numgpr * tcgsize2size[OS_INT] +
|
||||||
numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN) + tg.lasttemp, ELF_STACK_ALIGN);
|
numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN);
|
||||||
|
|
||||||
|
if not ((not (pi_do_call in flags)) and (tg.lasttemp = tg.firsttemp) and
|
||||||
|
(result <= RED_ZONE_SIZE)) then
|
||||||
|
result := align(result + tg.lasttemp, ELF_STACK_ALIGN);
|
||||||
end else
|
end else
|
||||||
result := align(tg.lasttemp, ELF_STACK_ALIGN);
|
result := align(tg.lasttemp, ELF_STACK_ALIGN);
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user