From 5ec4d38231da95911cadf69af2a360c66817bc4e Mon Sep 17 00:00:00 2001 From: Jeppe Johansen Date: Sun, 22 Nov 2015 00:37:10 +0000 Subject: [PATCH] Add support for ram-less AVR chips and simultanously optimize flash/ram size the initfinal calling sequence. git-svn-id: trunk@32448 - --- .gitattributes | 1 + compiler/avr/cgcpu.pas | 13 ++- compiler/avr/cpunode.pas | 3 +- compiler/avr/navrutil.pas | 198 ++++++++++++++++++++++++++++++++++++++ compiler/hlcgobj.pas | 4 + rtl/avr/avr.inc | 8 +- rtl/embedded/system.pp | 11 +-- rtl/inc/system.inc | 7 ++ 8 files changed, 225 insertions(+), 20 deletions(-) create mode 100644 compiler/avr/navrutil.pas diff --git a/.gitattributes b/.gitattributes index bcc3ef34eb..1803e253ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -121,6 +121,7 @@ compiler/avr/itcpugas.pas svneol=native#text/plain compiler/avr/navradd.pas svneol=native#text/plain compiler/avr/navrcnv.pas svneol=native#text/plain compiler/avr/navrmat.pas svneol=native#text/plain +compiler/avr/navrutil.pas svneol=native#text/pascal compiler/avr/raavr.pas svneol=native#text/plain compiler/avr/raavrgas.pas svneol=native#text/plain compiler/avr/ravrcon.inc svneol=native#text/plain diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index 4ea93aef55..9968e9199b 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -402,11 +402,18 @@ unit cgcpu; procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean); + var + sym: TAsmSymbol; begin - if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then - list.concat(taicpu.op_sym(A_CALL,current_asmdata.RefAsmSymbol(s))) + if weak then + sym:=current_asmdata.WeakRefAsmSymbol(s) else - list.concat(taicpu.op_sym(A_RCALL,current_asmdata.RefAsmSymbol(s))); + sym:=current_asmdata.RefAsmSymbol(s); + + if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then + list.concat(taicpu.op_sym(A_CALL,sym)) + else + list.concat(taicpu.op_sym(A_RCALL,sym)); include(current_procinfo.flags,pi_do_call); end; diff --git a/compiler/avr/cpunode.pas b/compiler/avr/cpunode.pas index 9a1af52634..0160fd065f 100644 --- a/compiler/avr/cpunode.pas +++ b/compiler/avr/cpunode.pas @@ -36,7 +36,8 @@ unit cpunode; } ,navradd ,navrmat - ,navrcnv, + ,navrcnv + ,navrutil, { symtable } symcpu ; diff --git a/compiler/avr/navrutil.pas b/compiler/avr/navrutil.pas new file mode 100644 index 0000000000..775bd70f64 --- /dev/null +++ b/compiler/avr/navrutil.pas @@ -0,0 +1,198 @@ +{ + Copyright (c) 2015 by Jeppe Johansen + + AVR version of some node tree helper routines + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +unit navrutil; + +{$i fpcdefs.inc} + +interface + + uses + node,nbas, + ngenutil, + symtype,symconst,symsym,symdef; + + + type + tavrnodeutils = class(tnodeutils) + class procedure InsertInitFinalTable; override; + end; + +implementation + + uses + verbose,cutils,globtype,globals,constexp,fmodule, + cclasses, + aasmdata,aasmtai,aasmcpu,aasmcnst,aasmbase, + cpubase, + symbase,symcpu,symtable,defutil, + ncnv,ncon,ninl,ncal,nld,nmem, + systems, + CPUInfo, + ppu, + pass_1; + + + procedure AddToStructInits(p:TObject;arg:pointer); + var + StructList: TFPList absolute arg; + begin + if (tdef(p).typ in [objectdef,recorddef]) and + not (df_generic in tdef(p).defoptions) then + begin + { first add the class... } + if ([oo_has_class_constructor,oo_has_class_destructor] * tabstractrecorddef(p).objectoptions <> []) then + StructList.Add(p); + { ... and then also add all subclasses } + tabstractrecorddef(p).symtable.deflist.foreachcall(@AddToStructInits,arg); + end; + end; + + + class procedure tavrnodeutils.InsertInitFinalTable; + var + hp : tused_unit; + op: TAsmOp; + initCount, finalCount: longint; + + procedure write_struct_inits(InitList, FinalizeList: TAsmList; u: tmodule); + var + i: integer; + structlist: TFPList; + pd: tprocdef; + begin + structlist := TFPList.Create; + if assigned(u.globalsymtable) then + u.globalsymtable.DefList.ForEachCall(@AddToStructInits,structlist); + u.localsymtable.DefList.ForEachCall(@AddToStructInits,structlist); + { write structures } + for i:=0 to structlist.Count-1 do + begin + pd:=tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_constructor); + if assigned(pd) then + begin + InitList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(pd.mangledname))); + inc(initCount); + end; + + pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_destructor); + if assigned(pd) then + begin + FinalizeList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(pd.mangledname))); + inc(finalCount); + end; + end; + structlist.free; + end; + + var + initList, finalList, header: TAsmList; + begin + initList:=TAsmList.create; + finalList:=TAsmList.create; + + initCount:=0; + finalCount:=0; + + if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then + op:=A_CALL + else + op:=A_RCALL; + + hp:=tused_unit(usedunits.first); + while assigned(hp) do + begin + if (hp.u.flags and uf_classinits) <> 0 then + write_struct_inits(initList, finalList, hp.u); + + if (hp.u.flags and (uf_init or uf_finalize))<>0 then + begin + if (hp.u.flags and uf_init)<>0 then + begin + initList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(make_mangledname('INIT$',hp.u.globalsymtable,'')))); + inc(initCount); + end; + + if (hp.u.flags and uf_finalize)<>0 then + begin + finalList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(make_mangledname('FINALIZE$',hp.u.globalsymtable,'')))); + inc(finalCount); + end; + end; + + hp:=tused_unit(hp.next); + end; + + { insert class constructors/destructor of the program } + if (current_module.flags and uf_classinits) <> 0 then + write_struct_inits(initList, finalList, current_module); + + { Insert initialization/finalization of the program } + if (current_module.flags and (uf_init or uf_finalize))<>0 then + begin + if (current_module.flags and uf_init)<>0 then + begin + initList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(make_mangledname('INIT$',current_module.localsymtable,'')))); + inc(initCount); + end; + + if (current_module.flags and uf_finalize)<>0 then + begin + finalList.Concat(taicpu.op_sym(op,current_asmdata.RefAsmSymbol(make_mangledname('FINALIZE$',current_module.localsymtable,'')))); + inc(finalCount); + end; + end; + + initList.Concat(taicpu.op_none(A_RET)); + finalList.Concat(taicpu.op_none(A_RET)); + + begin + header:=TAsmList.create; + new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1); + header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0)); + + initList.insertList(header); + header.free; + + current_asmdata.AsmLists[al_procedures].concatList(initList); + end; + + begin + header:=TAsmList.create; + new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1); + header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0)); + + finalList.insertList(header); + header.free; + + current_asmdata.AsmLists[al_procedures].concatList(finalList); + end; + + initList.Free; + finalList.Free; + + inherited InsertInitFinalTable; + end; + +begin + cnodeutils:=tavrnodeutils; +end. + diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 90d7354787..7fabef2027 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -4605,7 +4605,11 @@ implementation begin { initialize units } if not(current_module.islibrary) then +{$ifdef AVR} + cg.a_call_name(list,'FPC_INIT_FUNC_TABLE',false) +{$else AVR} g_call_system_proc(list,'fpc_initializeunits',[],nil) +{$endif AVR} else g_call_system_proc(list,'fpc_libinitializeunits',[],nil); end; diff --git a/rtl/avr/avr.inc b/rtl/avr/avr.inc index dbb4f87eaf..f32a938011 100644 --- a/rtl/avr/avr.inc +++ b/rtl/avr/avr.inc @@ -17,17 +17,11 @@ {$asmmode gas} -Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif} +procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif} begin end; -procedure fpc_cpuinit; - begin - SysInitFPU; - end; - - {$define FPC_SYSTEM_HAS_MOVE} procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE']; var diff --git a/rtl/embedded/system.pp b/rtl/embedded/system.pp index 6f471213f0..a1f597515c 100644 --- a/rtl/embedded/system.pp +++ b/rtl/embedded/system.pp @@ -163,16 +163,9 @@ const calculated_cmdline:Pchar=nil; Misc. System Dependent Functions *****************************************************************************} -procedure haltproc(e:longint);cdecl;external name '_haltproc'; +procedure haltproc;cdecl;external name '_haltproc'; -procedure System_exit;noreturn; -begin -{$ifdef FPC_HAS_FEATURE_EXITCODE} - haltproc(ExitCode); -{$else FPC_HAS_FEATURE_EXITCODE} - haltproc(0); -{$endif FPC_HAS_FEATURE_EXITCODE} -End; +procedure System_exit;noreturn;external name '_haltproc'; {$ifdef FPC_HAS_FEATURE_PROCESSES} diff --git a/rtl/inc/system.inc b/rtl/inc/system.inc index 4c003a3523..c9b68c633a 100644 --- a/rtl/inc/system.inc +++ b/rtl/inc/system.inc @@ -915,6 +915,10 @@ begin end; +{$ifdef CPUAVR} +procedure FinalizeUnits; external name 'FPC_FINALIZE_FUNC_TABLE'; + +{$else CPUAVR} procedure FinalizeUnits;[public,alias:'FPC_FINALIZEUNITS']; begin {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION} @@ -933,6 +937,7 @@ begin end; end; end; +{$endif CPUAVR} {***************************************************************************** Error / Exit / ExitProc @@ -974,6 +979,7 @@ Begin {$ifdef SYSTEMDEBUG} writeln('InternalExit'); {$endif SYSTEMDEBUG} +{$ifndef CPUAVR} while exitProc<>nil Do Begin InOutRes:=0; @@ -981,6 +987,7 @@ Begin exitProc:=nil; current_exit(); End; +{$endif CPUAVR} {$ifdef FPC_HAS_FEATURE_CONSOLEIO} { the embedded system unit itself contains no routines for console i/o