* optimized generation of and generated entry and exit code:

* no stack frame generated anymore if it's not necessary
    * only the necessary stack space is now reserved, instead of
      room for all non-volatile registers
    * less usage of helper registers

git-svn-id: trunk@2082 -
This commit is contained in:
Jonas Maebe 2005-12-30 17:20:07 +00:00
parent 8bece84c5b
commit c3f27eee06
2 changed files with 234 additions and 253 deletions

View File

@ -1044,10 +1044,9 @@ const
{ allocator here, because the register colouring has already occured !! } { allocator here, because the register colouring has already occured !! }
var regcounter,firstregfpu,firstreggpr: TSuperRegister; var regcounter,firstregfpu,firstregint: TSuperRegister;
href : treference; href : treference;
usesfpr,usesgpr,gotgot : boolean; usesfpr,usesgpr,gotgot : boolean;
regcounter2, firstfpureg: Tsuperregister;
cond : tasmcond; cond : tasmcond;
instr : taicpu; instr : taicpu;
@ -1057,99 +1056,57 @@ const
{ following is the entry code as described in "Altivec Programming } { following is the entry code as described in "Altivec Programming }
{ Interface Manual", bar the saving of AltiVec registers } { Interface Manual", bar the saving of AltiVec registers }
a_reg_alloc(list,NR_STACK_POINTER_REG); a_reg_alloc(list,NR_STACK_POINTER_REG);
a_reg_alloc(list,NR_R0);
usesfpr:=false; usesgpr := false;
if not (po_assembler in current_procinfo.procdef.procoptions) then usesfpr := false;
{ FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit } if not(po_assembler in current_procinfo.procdef.procoptions) then
case target_info.abi of begin
abi_powerpc_aix: { save link register? }
firstfpureg := RS_F14; if (pi_do_call in current_procinfo.flags) or
abi_powerpc_sysv: ([cs_lineinfo,cs_debuginfo] * aktmoduleswitches <> []) then
firstfpureg := RS_F14;
else
internalerror(2003122903);
end;
for regcounter:=firstfpureg to RS_F31 do
begin
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:= true;
firstregfpu:=regcounter;
break;
end;
end;
usesgpr:=false;
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
firstreggpr:=regcounter2;
break;
end;
end;
{ save link register? }
if not (po_assembler in current_procinfo.procdef.procoptions) then
if (pi_do_call in current_procinfo.flags) or
([cs_lineinfo,cs_debuginfo] * aktmoduleswitches <> []) then
begin
{ save return address... }
list.concat(taicpu.op_reg(A_MFLR,NR_R0));
{ ... in caller's frame }
case target_info.abi of
abi_powerpc_aix:
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
abi_powerpc_sysv:
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV);
end;
list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
a_reg_dealloc(list,NR_R0);
end;
{ save the CR if necessary in callers frame. }
if not (po_assembler in current_procinfo.procdef.procoptions) then
if target_info.abi = abi_powerpc_aix then
if false then { Not needed at the moment. }
begin begin
a_reg_alloc(list,NR_R0); a_reg_alloc(list,NR_R0);
list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR)); { save return address... }
reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX); list.concat(taicpu.op_reg(A_MFLR,NR_R0));
{ ... in caller's frame }
case target_info.abi of
abi_powerpc_aix:
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
abi_powerpc_sysv:
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV);
end;
list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href)); list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
a_reg_dealloc(list,NR_R0); a_reg_dealloc(list,NR_R0);
end; end;
{ !!! always allocate space for all registers for now !!! } (*
if not (po_assembler in current_procinfo.procdef.procoptions) then { save the CR if necessary in callers frame. }
{ if usesfpr or usesgpr then } if target_info.abi = abi_powerpc_aix then
begin if false then { Not needed at the moment. }
a_reg_alloc(list,NR_R12); begin
{ save end of fpr save area } a_reg_alloc(list,NR_R0);
list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG)); list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR));
end; reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
a_reg_dealloc(list,NR_R0);
end;
*)
firstregfpu := tppcprocinfo(current_procinfo).get_first_save_fpu_reg;
firstregint := tppcprocinfo(current_procinfo).get_first_save_int_reg;
usesgpr := firstregint <> 32;
usesfpr := firstregfpu <> 32;
if (not nostackframe) and { !!! always allocate space for all registers for now !!! }
(localsize <> 0) then { if usesfpr or usesgpr then }
begin if (localsize <> 0) and
if (localsize <= high(smallint)) then { check is imperfect, is actualy only necessary if there are }
{ parameters to copy }
(tppcprocinfo(current_procinfo).uses_stack_temps) then
begin begin
reference_reset_base(href,NR_STACK_POINTER_REG,-localsize); a_reg_alloc(list,NR_R12);
a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href); { save end of fpr save area }
end list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG));
else
begin
reference_reset_base(href,NR_STACK_POINTER_REG,0);
{ can't use getregisterint here, the register colouring }
{ is already done when we get here }
href.index := NR_R11;
a_reg_alloc(list,href.index);
a_load_const_reg(list,OS_S32,-localsize,href.index);
a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
a_reg_dealloc(list,href.index);
end; end;
end; end;
@ -1157,7 +1114,7 @@ const
gotgot:=false; gotgot:=false;
if usesfpr then if usesfpr then
begin begin
{ save floating-point registers { save floating-point registers
if (cs_create_pic in aktmoduleswitches) and not(usesgpr) then if (cs_create_pic in aktmoduleswitches) and not(usesgpr) then
begin begin
a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g',AB_EXTERNAL,AT_FUNCTION)); a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g',AB_EXTERNAL,AT_FUNCTION));
@ -1165,23 +1122,20 @@ const
end end
else else
a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14),AB_EXTERNAL,AT_FUNCTION)); a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14),AB_EXTERNAL,AT_FUNCTION));
} }
reference_reset_base(href,NR_R12,-8);
for regcounter:=firstregfpu to RS_F31 do
begin
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
a_loadfpu_reg_ref(list,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
dec(href.offset,8);
end;
end;
reference_reset_base(href,NR_R1,-8);
for regcounter:=firstregfpu to RS_F31 do
begin
a_loadfpu_reg_ref(list,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
dec(href.offset,8);
end;
{ compute start of gpr save area } { compute start of gpr save area }
inc(href.offset,4); inc(href.offset,4);
end end
else else
{ compute start of gpr save area } { compute start of gpr save area }
reference_reset_base(href,NR_R12,-4); reference_reset_base(href,NR_R1,-4);
{ save gprs and fetch GOT pointer } { save gprs and fetch GOT pointer }
if usesgpr then if usesgpr then
@ -1195,33 +1149,27 @@ const
else else
a_call_name(objectlibrary.newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14),AB_EXTERNAL,AT_FUNCTION)) a_call_name(objectlibrary.newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14),AB_EXTERNAL,AT_FUNCTION))
} }
for regcounter2:=RS_R13 to RS_R31 do if (firstregint <= RS_R22) or
((cs_littlesize in aktglobalswitches) and
{ with RS_R30 it's also already smaller, but too big a speed trade-off to make }
(firstregint <= RS_R29)) then
begin begin
if regcounter2 in rg[R_INTREGISTER].used_in_proc then dec(href.offset,(RS_R31-firstregint+1)*sizeof(aint));
begin list.concat(taicpu.op_reg_ref(A_STMW,newreg(R_INTREGISTER,firstregint,R_SUBNONE),href));
usesgpr:=true; end
if (regcounter2 <= RS_R22) or else
((cs_littlesize in aktglobalswitches) and for regcounter:=firstregint to RS_R31 do
{ with RS_R30 it's also already smaller, but too big a speed trade-off to make } begin
(regcounter2 <= RS_R29)) then a_load_reg_ref(list,OS_INT,OS_INT,newreg(R_INTREGISTER,regcounter,R_SUBNONE),href);
begin dec(href.offset,4);
dec(href.offset,(RS_R31-regcounter2+1)*sizeof(aint)); end;
list.concat(taicpu.op_reg_ref(A_STMW,newreg(R_INTREGISTER,regcounter2,R_SUBNONE),href));
break;
end
else
begin
a_load_reg_ref(list,OS_INT,OS_INT,newreg(R_INTREGISTER,regcounter2,R_SUBNONE),href);
dec(href.offset,4);
end;
end;
end;
{ {
r.enum:=R_INTREGISTER; r.enum:=R_INTREGISTER;
r.:=; r.:=;
reference_reset_base(href,NR_R12,-((NR_R31-firstreggpr) shr 8+1)*4); reference_reset_base(href,NR_R12,-((NR_R31-firstreggpr) shr 8+1)*4);
list.concat(taicpu.op_reg_ref(A_STMW,firstreggpr,href)); list.concat(taicpu.op_reg_ref(A_STMW,firstreggpr,href));
} }
end; end;
{ see "!!! always allocate space for all registers for now !!!" above } { see "!!! always allocate space for all registers for now !!!" above }
@ -1258,122 +1206,105 @@ const
end; end;
end; end;
*) *)
{ save the CR if necessary ( !!! always done currently ) }
{ still need to find out where this has to be done for SystemV if (not nostackframe) and
(localsize <> 0) then
begin
if (localsize <= high(smallint)) then
begin
reference_reset_base(href,NR_STACK_POINTER_REG,-localsize);
a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href);
end
else
begin
reference_reset_base(href,NR_STACK_POINTER_REG,0);
{ can't use getregisterint here, the register colouring }
{ is already done when we get here }
href.index := NR_R11;
a_reg_alloc(list,href.index);
a_load_const_reg(list,OS_S32,-localsize,href.index);
a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
a_reg_dealloc(list,href.index);
end;
end;
{ save the CR if necessary ( !!! never done currently ) }
{ still need to find out where this has to be done for SystemV
a_reg_alloc(list,R_0); a_reg_alloc(list,R_0);
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR); list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
list.concat(taicpu.op_reg_ref(A_STW,scratch_register, list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
new_reference(STACK_POINTER_REG,LA_CR))); new_reference(STACK_POINTER_REG,LA_CR)));
a_reg_dealloc(list,R_0); } a_reg_dealloc(list,R_0);
}
{ now comes the AltiVec context save, not yet implemented !!! } { now comes the AltiVec context save, not yet implemented !!! }
end; end;
procedure tcgppc.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean); procedure tcgppc.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
{ This procedure may be called before, as well as after g_stackframe_entry } { This procedure may be called before, as well as after g_stackframe_entry }
{ is called. NOTE registers are not to be allocated through the register } { is called. NOTE registers are not to be allocated through the register }
{ allocator here, because the register colouring has already occured !! } { allocator here, because the register colouring has already occured !! }
var var
regcounter,firstregfpu,firstreggpr: TsuperRegister; regcounter,firstregfpu,firstregint: TsuperRegister;
href : treference; href : treference;
usesfpr,usesgpr,genret : boolean; usesfpr,usesgpr,genret : boolean;
regcounter2, firstfpureg:Tsuperregister;
localsize: aint; localsize: aint;
begin begin
{ AltiVec context restore, not yet implemented !!! } { AltiVec context restore, not yet implemented !!! }
usesfpr:=false; usesfpr:=false;
if not (po_assembler in current_procinfo.procdef.procoptions) then
begin
{ FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
case target_info.abi of
abi_powerpc_aix:
firstfpureg := RS_F14;
abi_powerpc_sysv:
firstfpureg := RS_F14;
else
internalerror(2003122903);
end;
for regcounter:=firstfpureg to RS_F31 do
begin
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:=true;
firstregfpu:=regcounter;
break;
end;
end;
end;
usesgpr:=false; usesgpr:=false;
if not (po_assembler in current_procinfo.procdef.procoptions) then if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do begin
begin firstregfpu := tppcprocinfo(current_procinfo).get_first_save_fpu_reg;
if regcounter2 in rg[R_INTREGISTER].used_in_proc then firstregint := tppcprocinfo(current_procinfo).get_first_save_int_reg;
begin usesgpr := firstregint <> 32;
usesgpr:=true; usesfpr := firstregfpu <> 32;
firstreggpr:=regcounter2; end;
break;
end;
end;
localsize:= tppcprocinfo(current_procinfo).calc_stackframe_size; localsize:= tppcprocinfo(current_procinfo).calc_stackframe_size;
{ adjust r1 }
{ (register allocator is no longer valid at this time and an add of 0 }
{ is translated into a move, which is then registered with the register }
{ allocator, causing a crash }
if (not nostackframe) and
(localsize <> 0) then
a_op_const_reg(list,OP_ADD,OS_ADDR,localsize,NR_R1);
{ no return (blr) generated yet } { no return (blr) generated yet }
genret:=true; genret:=true;
if usesgpr or usesfpr then if usesfpr then
begin begin
{ address of gpr save area to r11 } reference_reset_base(href,NR_R1,-8);
{ (register allocator is no longer valid at this time and an add of 0 } for regcounter := firstregfpu to RS_F31 do
{ is translated into a move, which is then registered with the register }
{ allocator, causing a crash }
if (localsize <> 0) then
a_op_const_reg_reg(list,OP_ADD,OS_ADDR,localsize,NR_STACK_POINTER_REG,NR_R12)
else
list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG));
if usesfpr then
begin
reference_reset_base(href,NR_R12,-8);
for regcounter := firstregfpu to RS_F31 do
begin
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
a_loadfpu_ref_reg(list,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
dec(href.offset,8);
end;
end;
inc(href.offset,4);
end
else
reference_reset_base(href,NR_R12,-4);
for regcounter2:=RS_R13 to RS_R31 do
begin begin
if regcounter2 in rg[R_INTREGISTER].used_in_proc then a_loadfpu_ref_reg(list,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
begin dec(href.offset,8);
usesgpr:=true;
if (regcounter2 <= RS_R22) or
((cs_littlesize in aktglobalswitches) and
{ with RS_R30 it's also already smaller, but too big a speed trade-off to make }
(regcounter2 <= RS_R29)) then
begin
dec(href.offset,(RS_R31-regcounter2+1)*sizeof(aint));
list.concat(taicpu.op_reg_ref(A_LMW,newreg(R_INTREGISTER,regcounter2,R_SUBNONE),href));
break;
end
else
begin
a_load_ref_reg(list,OS_INT,OS_INT,href,newreg(R_INTREGISTER,regcounter2,R_SUBNONE));
dec(href.offset,4);
end;
end;
end; end;
inc(href.offset,4);
end
else
reference_reset_base(href,NR_R1,-4);
(* if (usesgpr) then
reference_reset_base(href,r2,-((NR_R31-ord(firstreggpr)) shr 8+1)*4); begin
list.concat(taicpu.op_reg_ref(A_LMW,firstreggpr,href)); if (firstregint <= RS_R22) or
*) ((cs_littlesize in aktglobalswitches) and
{ with RS_R30 it's also already smaller, but too big a speed trade-off to make }
(firstregint <= RS_R29)) then
begin
dec(href.offset,(RS_R31-firstregint+1)*sizeof(aint));
list.concat(taicpu.op_reg_ref(A_LMW,newreg(R_INTREGISTER,firstregint,R_SUBNONE),href));
end
else
for regcounter:=firstregint to RS_R31 do
begin
a_load_ref_reg(list,OS_INT,OS_INT,href,newreg(R_INTREGISTER,regcounter,R_SUBNONE));
dec(href.offset,4);
end;
end; end;
(* (*
@ -1396,47 +1327,42 @@ const
end; end;
*) *)
{ if we didn't generate the return code, we've to do it now } { if we didn't generate the return code, we've to do it now }
if genret then if genret then
begin begin
{ adjust r1 } { load link register? }
{ (register allocator is no longer valid at this time and an add of 0 } if not (po_assembler in current_procinfo.procdef.procoptions) then
{ is translated into a move, which is then registered with the register } begin
{ allocator, causing a crash } if (pi_do_call in current_procinfo.flags) then
if (not nostackframe) and begin
(localsize <> 0) then case target_info.abi of
a_op_const_reg(list,OP_ADD,OS_ADDR,localsize,NR_R1); abi_powerpc_aix:
{ load link register? } reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
if not (po_assembler in current_procinfo.procdef.procoptions) then abi_powerpc_sysv:
begin reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV);
if (pi_do_call in current_procinfo.flags) then end;
begin list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
case target_info.abi of list.concat(taicpu.op_reg(A_MTLR,NR_R0));
abi_powerpc_aix: end;
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
abi_powerpc_sysv: (*
reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV); { restore the CR if necessary from callers frame}
if target_info.abi = abi_powerpc_aix then
if false then { Not needed at the moment. }
begin
reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
a_reg_dealloc(list,NR_R0);
end; end;
list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href)); *)
list.concat(taicpu.op_reg(A_MTLR,NR_R0)); end;
end;
{ restore the CR if necessary from callers frame} list.concat(taicpu.op_none(A_BLR));
if target_info.abi = abi_powerpc_aix then
if false then { Not needed at the moment. }
begin
reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
a_reg_dealloc(list,NR_R0);
end;
end;
list.concat(taicpu.op_none(A_BLR));
end; end;
end; end;
function tcgppc.save_regs(list : taasmoutput):longint; function tcgppc.save_regs(list : taasmoutput):longint;
{Generates code which saves used non-volatile registers in {Generates code which saves used non-volatile registers in
the save area right below the address the stackpointer point to. the save area right below the address the stackpointer point to.

View File

@ -28,7 +28,8 @@ unit cpupi;
interface interface
uses uses
cutils, cutils,globtype,
cgbase,
procinfo,cpuinfo,psub; procinfo,cpuinfo,psub;
type type
@ -39,16 +40,24 @@ unit cpupi;
procedure set_first_temp_offset;override; procedure set_first_temp_offset;override;
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 uses_stack_temps: boolean;
private
start_temp_offset: aint;
first_save_int_reg, first_save_fpu_reg: tsuperregister;
public
property get_first_save_int_reg: tsuperregister read first_save_int_reg;
property get_first_save_fpu_reg: tsuperregister read first_save_fpu_reg;
end; end;
implementation implementation
uses uses
globtype,globals,systems, globals,systems,
cpubase, cpubase,
aasmtai, aasmtai,
tgobj, tgobj,cgobj,
symconst,symsym,paramgr,symutil, symconst,symsym,paramgr,symutil,
verbose; verbose;
@ -57,6 +66,9 @@ unit cpupi;
begin begin
inherited create(aparent); inherited create(aparent);
maxpushedparasize:=0; maxpushedparasize:=0;
start_temp_offset:=-1;
first_save_int_reg:=-1;
first_save_fpu_reg:=-1;
end; end;
@ -69,21 +81,26 @@ unit cpupi;
begin begin
case target_info.abi of case target_info.abi of
abi_powerpc_aix: abi_powerpc_aix:
ofs:=align(maxpushedparasize+LinkageAreaSizeAIX,16); ofs:=maxpushedparasize+LinkageAreaSizeAIX;
abi_powerpc_sysv: abi_powerpc_sysv:
ofs:=align(maxpushedparasize+LinkageAreaSizeSYSV,16); ofs:=maxpushedparasize+LinkageAreaSizeSYSV;
else else
internalerror(200402191); internalerror(200402191);
end; end;
tg.setfirsttemp(ofs); tg.setfirsttemp(ofs);
start_temp_offset := ofs;
end end
else else
begin begin
locals := 0; locals := 0;
start_temp_offset := 0;
current_procinfo.procdef.localst.foreach_static(@count_locals,@locals); current_procinfo.procdef.localst.foreach_static(@count_locals,@locals);
if locals <> 0 then if locals <> 0 then
{ at 0(r1), the previous value of r1 will be stored } begin
tg.setfirsttemp(4); { at 0(r1), the previous value of r1 will be stored }
tg.setfirsttemp(4);
start_temp_offset := 4;
end;
end; end;
end; end;
@ -118,22 +135,59 @@ unit cpupi;
end; end;
function tppcprocinfo.uses_stack_temps: boolean;
begin
if (start_temp_offset = -1) then
internalerror(200512301);
result := start_temp_offset <> tg.lasttemp;
end;
function tppcprocinfo.calc_stackframe_size:longint; function tppcprocinfo.calc_stackframe_size:longint;
var var
first_save_fpu_register: longint; low_nonvol_fpu_reg, regcounter: tsuperregister;
begin begin
{ more or less copied from cgcpu.pas/g_stackframe_entry }
{ FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
case target_info.abi of
abi_powerpc_aix:
first_save_fpu_register := 14;
abi_powerpc_sysv:
first_save_fpu_register := 9;
else
internalerror(2003122903);
end;
if not (po_assembler in procdef.procoptions) then if not (po_assembler in procdef.procoptions) then
result := align(align((31-13+1)*4+(31-first_save_fpu_register+1)*8,16)+tg.lasttemp,16) begin
first_save_fpu_reg := 32;
first_save_int_reg := 32;
{ FIXME: has to be R_F14 instead of R_F8 for SYSV-64bit }
case target_info.abi of
abi_powerpc_aix:
low_nonvol_fpu_reg := RS_F14;
abi_powerpc_sysv:
low_nonvol_fpu_reg := RS_F14;
else
internalerror(2003122903);
end;
for regcounter := low_nonvol_fpu_reg to RS_F31 do
begin
if regcounter in cg.rg[R_FPUREGISTER].used_in_proc then
begin
first_save_fpu_reg := ord(regcounter) - ord(RS_F0);
break;
end;
end;
for regcounter := RS_R13 to RS_R31 do
begin
if regcounter in cg.rg[R_INTREGISTER].used_in_proc then
begin
first_save_int_reg := ord(regcounter) - ord(RS_R0);
break;
end;
end;
if not(pi_do_call in flags) and
(not uses_stack_temps) and
(((target_info.abi = abi_powerpc_aix) and
((32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8 <= 220)) or
((target_info.abi = abi_powerpc_sysv) and
(first_save_int_reg + first_save_fpu_reg = 64))) then
{ don't allocate a stack frame }
result := (32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8
else
result := (32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8+tg.lasttemp;
result := align(result,16);
end
else else
result := align(tg.lasttemp,16); result := align(tg.lasttemp,16);
end; end;
@ -142,3 +196,4 @@ unit cpupi;
begin begin
cprocinfo:=tppcprocinfo; cprocinfo:=tppcprocinfo;
end. end.