* framepointer fixes for sparc

* parent framepointer code more generic
This commit is contained in:
peter 2003-07-06 17:58:22 +00:00
parent ae8e74b45b
commit 32d076480b
17 changed files with 339 additions and 303 deletions

View File

@ -77,7 +77,7 @@ unit cgbase;
On the PowerPC, this is used to store the offset where the
frame pointer from the outer procedure is stored.
}
framepointer_offset : longint;
parent_framepointer_offset : longint;
{# firsttemp position }
firsttemp_offset : longint;
@ -114,23 +114,21 @@ unit cgbase;
constructor create(aparent:tprocinfo);virtual;
destructor destroy;override;
procedure allocate_interrupt_parameter;virtual;
procedure allocate_parent_framepointer_parameter;virtual;
procedure allocate_implicit_parameter;virtual;
procedure allocate_interrupt_parameter;virtual;
{ Allocate framepointer so it can not be used by the
register allocator }
procedure allocate_framepointer;virtual;
procedure allocate_framepointer_reg;virtual;
procedure allocate_push_parasize(size:longint);virtual;
function calc_stackframe_size:longint;virtual;
{ Does the necessary stuff before a procedure body is compiled }
procedure handle_body_start;virtual;
{ This is called by parser, after the header of a subroutine is parsed.
If the local symtable offset depends on the para symtable size, the
necessary stuff must be done here.
}
procedure after_header;virtual;
{ This procedure is called after the pass 1 of the subroutine body is done.
Here the address fix ups to generate code for the body must be done.
}
@ -319,7 +317,7 @@ implementation
begin
parent:=aparent;
procdef:=nil;
framepointer_offset:=0;
parent_framepointer_offset:=0;
firsttemp_offset:=0;
flags:=[];
framepointer.enum:=R_INTREGISTER;
@ -340,16 +338,34 @@ implementation
end;
procedure tprocinfo.allocate_parent_framepointer_parameter;
begin
parent_framepointer_offset:=procdef.parast.address_fixup;
inc(procdef.parast.address_fixup,POINTER_SIZE);
end;
procedure tprocinfo.allocate_interrupt_parameter;
begin
end;
procedure tprocinfo.allocate_framepointer;
procedure tprocinfo.allocate_framepointer_reg;
begin
end;
procedure tprocinfo.allocate_push_parasize(size:longint);
begin
end;
function tprocinfo.calc_stackframe_size:longint;
begin
result:=procdef.localst.datasize+tg.gettempsize;
end;
procedure tprocinfo.handle_body_start;
var
paramloc : tparalocation;
@ -395,22 +411,6 @@ implementation
end;
procedure tprocinfo.allocate_implicit_parameter;
begin
{ Insert implicit parameters, will be removed in the future }
if (procdef.parast.symtablelevel>normal_function_level) then
begin
framepointer_offset:=procdef.parast.address_fixup;
inc(procdef.parast.address_fixup,POINTER_SIZE);
end;
end;
procedure tprocinfo.after_header;
begin
end;
procedure tprocinfo.after_pass1;
begin
end;
@ -571,7 +571,11 @@ implementation
end.
{
$Log$
Revision 1.56 2003-06-13 21:19:30 peter
Revision 1.57 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.56 2003/06/13 21:19:30 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.55 2003/06/12 16:43:07 peter

View File

@ -311,6 +311,9 @@ unit cgobj;
}
procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual;
procedure g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister);
procedure g_save_parent_framepointer_param(list:taasmoutput);virtual;
procedure g_maybe_testself(list : taasmoutput;reg:tregister);
procedure g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
{# This should emit the opcode to copy len bytes from the source
@ -1353,6 +1356,31 @@ unit cgobj;
end;
procedure tcg.g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister);
var
href : treference;
i : integer;
begin
{ make a reference }
reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET);
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg);
{ walk parents }
i:=current_procinfo.procdef.parast.symtablelevel-1;
while (i>parentsymtable.symtablelevel) do
begin
{ make a reference }
reference_reset_base(href,reg,PARENT_FRAMEPOINTER_OFFSET);
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg);
dec(i);
end;
end;
procedure tcg.g_save_parent_framepointer_param(list:taasmoutput);
begin
end;
procedure tcg.g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte;delsource,loadref : boolean);
begin
{$ifdef FPC}
@ -1767,7 +1795,11 @@ finalization
end.
{
$Log$
Revision 1.113 2003-07-02 22:18:04 peter
Revision 1.114 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.113 2003/07/02 22:18:04 peter
* paraloc splitted in callerparaloc,calleeparaloc
* sparc calling convention updates

View File

@ -181,6 +181,9 @@
fpu_result_reg = R_ST;
mmresultreg = R_MM0;
{ Offset where the parent framepointer is pushed }
PARENT_FRAMEPOINTER_OFFSET = 8;
{*****************************************************************************
GCC /ABI linking information
*****************************************************************************}
@ -205,7 +208,11 @@
{
$Log$
Revision 1.6 2003-06-03 13:01:59 daniel
Revision 1.7 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.6 2003/06/03 13:01:59 daniel
* Register allocator finished
Revision 1.5 2003/05/31 15:05:28 peter

View File

@ -34,7 +34,7 @@ unit cpupi;
type
ti386procinfo = class(tcgprocinfo)
procedure allocate_interrupt_parameter;override;
procedure allocate_framepointer;override;
procedure allocate_framepointer_reg;override;
end;
@ -52,7 +52,7 @@ unit cpupi;
end;
procedure ti386procinfo.allocate_framepointer;
procedure ti386procinfo.allocate_framepointer_reg;
begin
if framepointer.number=NR_EBP then
begin
@ -69,7 +69,11 @@ begin
end.
{
$Log$
Revision 1.8 2003-06-13 21:19:31 peter
Revision 1.9 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.8 2003/06/13 21:19:31 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.7 2003/06/12 18:12:49 jonas

View File

@ -90,9 +90,6 @@ implementation
{$else cpu64bit}
cg64f32,
{$endif cpu64bit}
{$ifdef powerpc}
cpupi,
{$endif powerpc}
ncgutil,cgobj,tgobj,regvars,rgobj,rgcpu;
@ -370,12 +367,11 @@ implementation
var
href : treference;
hregister : tregister;
i : integer;
begin
{ this routine is itself not nested }
if current_procinfo.procdef.parast.symtablelevel=(tprocdef(procdefinition).parast.symtablelevel) then
begin
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.parent_framepointer_offset);
cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(exprasmlist,1));
end
{ one nesting level }
@ -384,18 +380,10 @@ implementation
cg.a_param_reg(exprasmlist,OS_ADDR,current_procinfo.framepointer,paramanager.getintparaloc(exprasmlist,1));
end
{ very complex nesting level ... }
else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then
else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then
begin
hregister:=rg.getaddressregister(exprasmlist);
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
i:=current_procinfo.procdef.parast.symtablelevel;
while (i>tprocdef(procdefinition).parast.symtablelevel) do
begin
reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
dec(i);
end;
cg.g_load_parent_framepointer(exprasmlist,tprocdef(procdefinition).parast,hregister);
cg.a_param_reg(exprasmlist,OS_ADDR,hregister,paramanager.getintparaloc(exprasmlist,1));
rg.ungetaddressregister(exprasmlist,hregister);
end;
@ -1050,11 +1038,8 @@ implementation
if pop_size>0 then
pop_parasize(pop_size);
{$ifdef powerpc}
{ this calculation must be done in pass_1 anyway, so don't worry }
if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
{$endif powerpc}
{ Reserve space for storing parameters that will be pushed }
current_procinfo.allocate_push_parasize(pushedparasize);
{ Restore }
pushedparasize:=oldpushedparasize;
@ -1252,9 +1237,6 @@ implementation
{$endif extdebug}
end;
{ Calculate offsets }
current_procinfo.after_header;
exprasmList.concat(Tai_Marker.Create(InlineStart));
{$ifdef extdebug}
exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
@ -1398,11 +1380,8 @@ implementation
{ process the inline code }
secondpass(inlinecode);
{$ifdef powerpc}
{ this calculation must be done in pass_1 anyway, so don't worry }
if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
{$endif powerpc}
{ Reserve space for storing parameters that will be pushed }
current_procinfo.allocate_push_parasize(pushedparasize);
{ Restore }
pushedparasize:=oldpushedparasize;
@ -1541,7 +1520,11 @@ begin
end.
{
$Log$
Revision 1.98 2003-07-06 15:31:20 daniel
Revision 1.99 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.98 2003/07/06 15:31:20 daniel
* Fixed register allocator. *Lots* of fixes.
Revision 1.97 2003/07/05 20:21:26 jonas

View File

@ -213,22 +213,7 @@ implementation
if (current_procinfo.procdef.parast.symtablelevel>symtable.symtablelevel) then
begin
hregister:=rg.getaddressregister(exprasmlist);
{ make a reference }
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
{ walk parents }
i:=current_procinfo.procdef.parast.symtablelevel-1;
while (i>symtable.symtablelevel) do
begin
{ make a reference }
{$ifdef powerpc}
reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
{$else powerpc}
reference_reset_base(href,hregister,target_info.first_parm_offset);
{$endif powerpc}
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
dec(i);
end;
cg.g_load_parent_framepointer(exprasmlist,symtable,hregister);
location.reference.base:=hregister;
end;
end;
@ -954,7 +939,11 @@ begin
end.
{
$Log$
Revision 1.73 2003-07-06 15:25:54 jonas
Revision 1.74 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.73 2003/07/06 15:25:54 jonas
* newra fix for threadvars
Revision 1.72 2003/06/15 15:13:12 jonas

View File

@ -68,7 +68,7 @@ interface
procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
procedure gen_stackalloc_code(list:Taasmoutput);
procedure gen_exit_code(list:Taasmoutput;inlined:boolean);
(*
@ -1567,32 +1567,34 @@ implementation
code, since temp. allocation might occur before - carl
}
if assigned(current_procinfo.procdef.parast) then
if assigned(current_procinfo.procdef.parast) and
not (po_assembler in current_procinfo.procdef.procoptions) then
begin
if not (po_assembler in current_procinfo.procdef.procoptions) then
begin
{ move register parameters which aren't regable into memory }
{ we do this before init_paras because that one calls routines which may overwrite these }
{ registers and it also expects the values to be in memory }
hp:=tparaitem(current_procinfo.procdef.para.first);
while assigned(hp) do
begin
if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then
internalerror(200301081);
if (tvarsym(hp.parasym).reg.enum<>R_NO) then
begin
cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg);
end
else if (hp.calleeparaloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
(tvarsym(hp.parasym).reg.enum=R_NO) then
begin
reference_reset_base(href,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address);
cg.a_load_param_ref(list,hp.calleeparaloc,href);
end;
hp:=tparaitem(hp.next);
end;
end;
{ save framepointer in memory }
if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
cg.g_save_parent_framepointer_param(list);
{ move register parameters which aren't regable into memory }
{ we do this before init_paras because that one calls routines which may overwrite these }
{ registers and it also expects the values to be in memory }
hp:=tparaitem(current_procinfo.procdef.para.first);
while assigned(hp) do
begin
if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then
internalerror(200301081);
if (tvarsym(hp.parasym).reg.enum<>R_NO) then
begin
cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg);
end
else if (hp.calleeparaloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
(tvarsym(hp.parasym).reg.enum=R_NO) then
begin
reference_reset_base(href,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address);
cg.a_load_param_ref(list,hp.calleeparaloc,href);
end;
hp:=tparaitem(hp.next);
end;
end;
{ for the save all registers we can simply use a pusha,popa which
@ -1618,76 +1620,73 @@ implementation
end;
procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
var hs:string;
begin
{************************* Stack allocation **************************}
{ and symbol entry point as well as debug information }
{ will be inserted in front of the rest of this list. }
{ Insert alignment and assembler names }
{ Align, gprof uses 16 byte granularity }
if (cs_profile in aktmoduleswitches) then
list.concat(Tai_align.create(16))
else
list.concat(Tai_align.create(aktalignment.procalign));
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) then
begin
if (po_public in current_procinfo.procdef.procoptions) then
Tprocsym(current_procinfo.procdef.procsym).is_global:=true;
current_procinfo.procdef.concatstabto(list);
Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true;
end;
{$endif GDB}
repeat
hs:=current_procinfo.procdef.aliasnames.getfirst;
if hs='' then
break;
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) and
target_info.use_function_relative_addresses then
list.concat(Tai_stab_function_name.create(strpnew(hs)));
{$endif GDB}
if (cs_profile in aktmoduleswitches) or
(po_public in current_procinfo.procdef.procoptions) then
list.concat(Tai_symbol.createname_global(hs,0))
procedure gen_stackalloc_code(list:Taasmoutput);
var
hs : string;
stackframe : longint;
begin
{************************* Stack allocation **************************}
{ and symbol entry point as well as debug information }
{ will be inserted in front of the rest of this list. }
{ Insert alignment and assembler names }
{ Align, gprof uses 16 byte granularity }
if (cs_profile in aktmoduleswitches) then
list.concat(Tai_align.create(16))
else
list.concat(Tai_symbol.createname(hs,0));
until false;
list.concat(Tai_align.create(aktalignment.procalign));
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) then
begin
if (po_public in current_procinfo.procdef.procoptions) then
Tprocsym(current_procinfo.procdef.procsym).is_global:=true;
current_procinfo.procdef.concatstabto(list);
Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true;
end;
{$endif GDB}
repeat
hs:=current_procinfo.procdef.aliasnames.getfirst;
if hs='' then
break;
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) and
target_info.use_function_relative_addresses then
list.concat(Tai_stab_function_name.create(strpnew(hs)));
{$endif GDB}
if (cs_profile in aktmoduleswitches) or
(po_public in current_procinfo.procdef.procoptions) then
list.concat(Tai_symbol.createname_global(hs,0))
else
list.concat(Tai_symbol.createname(hs,0));
until false;
{ Calculate size of stackframe }
stackframe:=current_procinfo.calc_stackframe_size;
stackframe:=stackframe+tg.gettempsize;
{$ifndef m68k}
{ give a warning if the limit of local variables is reached }
if stackframe>maxlocalsize then
message(cg_w_localsize_too_big);
{$endif}
{$ifndef powerpc}
{ at least for the ppc this applies always, so this code isn't usable (FK) }
{ omit stack frame ? }
if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
begin
CGmessage(cg_d_stackframe_omited);
if stackframe<>0 then
cg.g_stackpointer_alloc(list,stackframe);
end
else
{ at least for the ppc this applies always, so this code isn't usable (FK) }
{ omit stack frame ? }
if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
begin
CGmessage(cg_d_stackframe_omited);
if stackframe<>0 then
cg.g_stackpointer_alloc(list,stackframe);
end
else
{$endif powerpc}
begin
if (po_interrupt in current_procinfo.procdef.procoptions) then
cg.g_interrupt_stackframe_entry(list);
begin
if (po_interrupt in current_procinfo.procdef.procoptions) then
cg.g_interrupt_stackframe_entry(list);
cg.g_stackframe_entry(list,stackframe);
cg.g_stackframe_entry(list,stackframe);
{Never call stack checking before the standard system unit
has been initialized.}
if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then
cg.g_stackcheck(list,stackframe);
end;
end;
{Never call stack checking before the standard system unit
has been initialized.}
if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then
cg.g_stackcheck(list,stackframe);
end;
end;
procedure gen_exit_code(list : TAAsmoutput;inlined:boolean);
@ -1789,7 +1788,7 @@ implementation
(current_procinfo.procdef.parast.symtablelevel>normal_function_level) then
list.concat(Tai_stabs.Create(strpnew(
'"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.framepointer_offset))));
tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.parent_framepointer_offset))));
if (not is_void(current_procinfo.procdef.rettype.def)) then
begin
@ -1988,7 +1987,11 @@ implementation
end.
{
$Log$
Revision 1.129 2003-07-06 15:31:20 daniel
Revision 1.130 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.129 2003/07/06 15:31:20 daniel
* Fixed register allocator. *Lots* of fixes.
Revision 1.128 2003/07/02 22:18:04 peter

View File

@ -302,7 +302,7 @@ implementation
// cleanup_regvars(current_procinfo.aktexitcode);
{$endif i386}
current_procinfo.allocate_framepointer;
current_procinfo.allocate_framepointer_reg;
do_secondpass(p);
@ -316,7 +316,11 @@ implementation
end.
{
$Log$
Revision 1.60 2003-07-06 15:31:20 daniel
Revision 1.61 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.60 2003/07/06 15:31:20 daniel
* Fixed register allocator. *Lots* of fixes.
Revision 1.59 2003/07/06 10:18:47 jonas

View File

@ -768,7 +768,7 @@ implementation
internalerror(200304253);
end;
include(current_procinfo.flags,pi_do_call);
gen_stackalloc_code(list,0);
gen_stackalloc_code(list);
gen_entry_code(list,false);
gen_initialize_code(list,false);
gen_finalize_code(list,false);
@ -1312,12 +1312,6 @@ implementation
pd:=create_main_proc('main',potype_proginit,st);
pd.aliasnames.insert('PASCALMAIN');
end;
{$IFDEF SPARC}
current_procinfo.After_Header;
{main function is declared as
PROCEDURE main(ArgC:Integer;ArgV,EnvP:ARRAY OF PChar):Integer;CDECL;
So, all parameters are passerd into registers in sparc architecture.}
{$ENDIF SPARC}
tcgprocinfo(current_procinfo).parse_body;
tcgprocinfo(current_procinfo).generate_code;
tcgprocinfo(current_procinfo).resetprocdef;
@ -1452,7 +1446,11 @@ So, all parameters are passerd into registers in sparc architecture.}
end.
{
$Log$
Revision 1.114 2003-06-13 21:19:31 peter
Revision 1.115 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.114 2003/06/13 21:19:31 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.113 2003/06/09 12:23:30 peter

View File

@ -654,7 +654,7 @@ implementation
end;
stackalloccode:=Taasmoutput.create;
gen_stackalloc_code(stackalloccode,0);
gen_stackalloc_code(stackalloccode);
stackalloccode.convert_registers;
aktproccode.insertlist(stackalloccode);
stackalloccode.destroy;
@ -1076,15 +1076,13 @@ implementation
pd.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_init_paras,nil);
{ Update parameter information }
current_procinfo.allocate_implicit_parameter;
if (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then
current_procinfo.allocate_parent_framepointer_parameter;
{ add implicit pushes for interrupt routines }
if (po_interrupt in pd.procoptions) then
current_procinfo.allocate_interrupt_parameter;
{ Calculate offsets }
current_procinfo.after_header;
{ set _FAIL as keyword if constructor }
if (pd.proctypeoption=potype_constructor) then
begin
@ -1254,7 +1252,11 @@ begin
end.
{
$Log$
Revision 1.131 2003-07-06 15:31:21 daniel
Revision 1.132 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.131 2003/07/06 15:31:21 daniel
* Fixed register allocator. *Lots* of fixes.
Revision 1.130 2003/07/05 20:15:24 jonas

View File

@ -74,6 +74,7 @@ interface
procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override;
procedure g_save_parent_framepointer_param(list:taasmoutput);override;
procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
procedure g_restore_frame_pointer(list:TAasmOutput);override;
@ -637,10 +638,10 @@ implementation
end;
end
else
list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r));
list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),r));
end
else
list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,ref.offset,r));
list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,aword(ref.offset),r));
end
else
{ Both base and index }
@ -868,6 +869,19 @@ implementation
{ *********** entry/exit code and address loading ************ }
procedure tcgsparc.g_save_parent_framepointer_param(list:taasmoutput);
var
hreg : tregister;
href : treference;
begin
reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET);
{ Parent framepointer is always pushed in o0 }
hreg.enum:=R_INTREGISTER;
hreg.number:=NR_O0;
a_load_reg_ref(list,OS_ADDR,OS_ADDR,hreg,href);
end;
procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
var
r : tregister;
@ -1241,7 +1255,11 @@ begin
end.
{
$Log$
Revision 1.62 2003-07-03 21:09:53 peter
Revision 1.63 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.62 2003/07/03 21:09:53 peter
* delay slot NOPs and comments added
* a_loadaddr_ref_reg fixed and optimized to reuse passed register
if it is not used by the ref

View File

@ -785,9 +785,10 @@ type
usableregsaddr = [];
c_countusableregsaddr = 0;
firstsaveintreg = RS_G0; { L0..L7 are already saved, I0..O7 are parameter }
lastsaveintreg = RS_G7;
firstsavefpureg = R_F0;
{$warning firstsaveintreg shall be RS_NO}
firstsaveintreg = RS_L0; { Temporary, having RS_NO is broken }
lastsaveintreg = RS_L0; { L0..L7 are already saved, I0..O7 are parameter }
firstsavefpureg = R_F2; { F0..F1 is used for return value }
lastsavefpureg = R_F31;
firstsavemmreg = R_NO;
lastsavemmreg = R_NO;
@ -933,6 +934,8 @@ type
FPU_RESULT_REG = R_F0;
mmresultreg = R_NO;
PARENT_FRAMEPOINTER_OFFSET = 68; { o0 }
{*****************************************************************************
GCC /ABI linking information
*****************************************************************************}
@ -1051,7 +1054,11 @@ implementation
end.
{
$Log$
Revision 1.44 2003-07-02 22:18:04 peter
Revision 1.45 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.44 2003/07/02 22:18:04 peter
* paraloc splitted in callerparaloc,calleeparaloc
* sparc calling convention updates

View File

@ -122,14 +122,15 @@ implementation
procedure TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee);
var
nextintreg : tsuperregister;
nextfloatreg : toldregister;
stack_offset : longint;
hp : tparaitem;
is_64bit : boolean;
paraloc : tparalocation;
begin
nextintreg:=RS_O0;
nextfloatreg:=R_F0;
{ Nested procedures have the parent framepoint in o0 }
if p.parast.symtablelevel>normal_function_level then
inc(NextIntReg);
stack_offset:=92;
hp:=TParaItem(p.para.First);
while assigned(hp) do
@ -275,7 +276,11 @@ begin
end.
{
$Log$
Revision 1.23 2003-07-05 20:11:41 jonas
Revision 1.24 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.23 2003/07/05 20:11:41 jonas
* create_paraloc_info() is now called separately for the caller and
callee info
* fixed ppc cycle

View File

@ -1,4 +1,4 @@
{*****************************************************************************
{
$Id$
Copyright (c) 2002 by Florian Klaempfl
@ -18,11 +18,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************}
{ This unit contains the CPU specific part of tprocinfo. }
****************************************************************************
}
unit cpupi;
{$I fpcdefs.inc}
{$i fpcdefs.inc}
interface
@ -33,75 +33,64 @@ interface
type
TSparcProcInfo=class(tcgprocinfo)
{ overall size of allocated stack space, currently this is used for the
PowerPC only }
LocalSize:aword;
{max of space need for parameters, currently used by the PowerPC port only}
maxpushedparasize:aword;
private
maxpushedparasize : longint;
public
constructor create(aparent:tprocinfo);override;
{ According the the SPARC ABI the standard stack frame must include :
* 16 word save for the in and local registers in case of overflow/underflow.
this save area always must exist at the %o6+0,
* software conventions requires space for the aggregate return value pointer, even if the word is not used,
* althogh the first six words of arguments reside in registers, the standard
stack frame reserves space for them. Arguments beond the sixth reside on the
stack as in the Intel architecture,
* other areas depend on the compiler and the code being compiled. The
standard calling sequence does not define a maximum stack frame size, nor does
it restrict how a language system uses the "unspecified" areas of the standard
stack frame.}
procedure after_header;override;
procedure after_pass1;override;
procedure allocate_push_parasize(size:longint);override;
function calc_stackframe_size:longint;override;
end;
implementation
uses
tgobj,paramgr,symsym,systems;
constructor TSparcprocinfo.create(aparent:tprocinfo);
begin
inherited create(aparent);
maxpushedparasize:=0;
LocalSize:=(16+1)*4;
{First 16 words are in the frame are used to save registers in case of a
register overflow/underflow.The 17th word is used to save the address of
the variable which will receive the return value of the called function}
// Return_Offset:=16*4;
end;
uses
globtype,systems,
tgobj,paramgr,symconst,symsym;
procedure TSparcprocinfo.after_header;
constructor tsparcprocinfo.create(aparent:tprocinfo);
begin
{ this value is necessary for nested procedures }
if assigned(procdef.localst) then
procdef.localst.address_fixup:=align(procdef.parast.address_fixup+procdef.parast.datasize,16);
inherited create(aparent);
maxpushedparasize:=0;
end;
procedure TSparcProcInfo.after_pass1;
begin
with ProcDef do
procedure tsparcprocinfo.allocate_push_parasize(size:longint);
begin
{Reserve the stack for copying parameters passed into registers. By
default we reserve space for the 6 input registers if the function had
less parameters. Otherwise, we allocate data sizeof parameters}
if parast.datasize>6*4
then
localst.address_fixup:=parast.address_fixup+parast.datasize
else
procdef.localst.address_fixup:=parast.address_fixup+6*4;
firsttemp_offset:=localst.address_fixup+localst.datasize;
with tg do
begin
SetFirstTemp(firsttemp_offset);
//LastTemp:=firsttemp_offset;
end;
if size>maxpushedparasize then
maxpushedparasize:=size;
end;
end;
function TSparcProcInfo.calc_stackframe_size:longint;
var
savearea : longint;
begin
{ ABI requires at least space to save 6 arguments }
savearea:=procdef.parast.address_fixup+max(maxpushedparasize,6*4);
{
Stackframe layout:
%fp
<locals>
<temp>
<arguments for calling>
<return pointer for calling>
<register window save area for calling>
%sp
}
result:=procdef.localst.datasize+tg.gettempsize+savearea;
end;
begin
cprocinfo:=TSparcProcInfo;
end.
{
$Log$
Revision 1.17 2003-06-13 21:19:32 peter
Revision 1.18 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.17 2003/06/13 21:19:32 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.16 2003/05/30 23:57:08 peter

View File

@ -1,8 +1,8 @@
{******************************************************************************
{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl
Generate SPARC assembler for in call nodes
Generate sparc assembler for in call nodes
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,51 +18,37 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************}
****************************************************************************
}
unit ncpucall;
{$INCLUDE fpcdefs.inc}
{$i fpcdefs.inc}
interface
uses
symdef,node,ncal,ncgcal;
type
TSparcCallNode=class(TCgCallNode)
function pass_1:TNode;override;
{Under SPARC, the frame pointer is automatically set by the SAVE instruction
which is part of the stardrad calling mechanism. This function will do nothing.
the frame pointer register is the stack pointer register of the caller, and is
set when generating function prologue in cgcpu.tcgSPARC.g_stackframe_entry}
procedure push_framepointer;override;
end;
uses
ncgcal;
type
tsparccallnode = class(tcgcallnode)
end;
implementation
uses
systems,
cutils,verbose,
paramgr,
cgbase,
nmem,nld,ncnv,
cgobj,tgobj,rgobj,rgcpu,cgcpu,cpupi;
function TSparcCallNode.pass_1:TNode;
begin
result:=inherited pass_1;
if assigned(result)
then
exit;
if ProcDefinition is TProcDef
then
with TProcDef(procdefinition).parast do
if datasize>TSparcProcInfo(current_procinfo).maxpushedparasize
then
TSparcProcInfo(current_procinfo).maxpushedparasize:=datasize;
end;
procedure TSparcCallNode.push_framepointer;
begin
end;
uses
ncal;
begin
ccallnode:=TSparcCallNode;
ccallnode:=TSparcCallNode;
end.
{
$Log$
Revision 1.12 2003-06-13 21:19:32 peter
Revision 1.13 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.12 2003/06/13 21:19:32 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.11 2003/04/28 09:49:58 mazen

View File

@ -403,8 +403,8 @@ unit i_linux;
localalignmin : 0;
localalignmax : 4;
paraalign : 4;
recordalignmin : 0;
recordalignmax : 2;
recordalignmin : 4;
recordalignmax : 4;
maxCrecordalign : 4
);
first_parm_offset : (16+1)*4;
@ -447,14 +447,18 @@ initialization
{$endif CPUSPARC}
{$ifdef CPUPOWERPC}
{$ifdef linux}
set_source_info(system_powerpc_linux_info);
set_source_info(system_powerpc_linux_info);
{$endif linux}
{$endif CPUPOWERPC}
end.
{
$Log$
Revision 1.8 2003-05-31 18:14:06 jonas
Revision 1.9 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.8 2003/05/31 18:14:06 jonas
* add default system for ppc
Revision 1.7 2003/05/19 12:15:28 florian

View File

@ -157,9 +157,6 @@ unit tgobj;
{$else powerpc}
direction:=-1;
{$endif powerpc}
{$IFDEF SPARC}
Direction:=1;
{$ENDIF SPARC}
end;
@ -554,7 +551,11 @@ finalization
end.
{
$Log$
Revision 1.35 2003-06-03 13:01:59 daniel
Revision 1.36 2003-07-06 17:58:22 peter
* framepointer fixes for sparc
* parent framepointer code more generic
Revision 1.35 2003/06/03 13:01:59 daniel
* Register allocator finished
Revision 1.34 2003/05/17 13:30:08 jonas