Browse Source

+ patch by Jeppe Johansen to support automatic interrupt table generation by using the interrupt directive with an offset. Not activated yet because it requires to change also the startup code of the different mcus.

git-svn-id: trunk@17279 -
florian 14 years ago
parent
commit
3ce9ff93f1

+ 16 - 1
compiler/arm/cpuinfo.pas

@@ -99,7 +99,9 @@ Const
      pocall_softfloat,
      pocall_softfloat,
      { same as stdcall (requires that all const records are passed by
      { same as stdcall (requires that all const records are passed by
        reference, but that's already done for stdcall) }
        reference, but that's already done for stdcall) }
-     pocall_mwpascal
+     pocall_mwpascal,
+     { used for interrupt handling }
+     pocall_interrupt
    ];
    ];
 
 
    cputypestr : array[tcputype] of string[8] = ('',
    cputypestr : array[tcputype] of string[8] = ('',
@@ -147,6 +149,19 @@ Const
       'STELLARIS'
       'STELLARIS'
      );
      );
 
 
+   interruptvectors : array[tcontrollertype] of longint =
+     (0,
+      8,
+      8,
+      8,
+      8,
+      8,
+      8,
+      8,
+      12+59, { XL-density }
+      12 { No model specified }
+     );
+
    vfp_scalar = [fpu_vfpv2,fpu_vfpv3];
    vfp_scalar = [fpu_vfpv2,fpu_vfpv3];
 
 
    { Supported optimizations, only used for information }
    { Supported optimizations, only used for information }

+ 2 - 1
compiler/globals.pas

@@ -1007,7 +1007,8 @@ implementation
          'SAFECALL',
          'SAFECALL',
          'STDCALL',
          'STDCALL',
          'SOFTFLOAT',
          'SOFTFLOAT',
-         'MWPASCAL'
+         'MWPASCAL',
+         'INTERRUPT'
         );
         );
       var
       var
         t  : tproccalloption;
         t  : tproccalloption;

+ 5 - 2
compiler/globtype.pas

@@ -360,7 +360,9 @@ interface
          pocall_softfloat,
          pocall_softfloat,
          { Metrowerks Pascal. Special case on Mac OS (X): passes all }
          { Metrowerks Pascal. Special case on Mac OS (X): passes all }
          { constant records by reference.                            }
          { constant records by reference.                            }
-         pocall_mwpascal
+         pocall_mwpascal,
+         { Special interrupt handler for embedded systems }
+         pocall_interrupt
        );
        );
        tproccalloptions = set of tproccalloption;
        tproccalloptions = set of tproccalloption;
 
 
@@ -377,7 +379,8 @@ interface
            'SafeCall',
            'SafeCall',
            'StdCall',
            'StdCall',
            'SoftFloat',
            'SoftFloat',
-           'MWPascal'
+           'MWPascal',
+           'Interrupt'
          );
          );
 
 
        { Default calling convention }
        { Default calling convention }

+ 2 - 1
compiler/ncgrtti.pas

@@ -636,7 +636,8 @@ implementation
               { pocall_safecall   } 4,
               { pocall_safecall   } 4,
               { pocall_stdcall    } 3,
               { pocall_stdcall    } 3,
               { pocall_softfloat  } 10,
               { pocall_softfloat  } 10,
-              { pocall_mwpascal   } 11
+              { pocall_mwpascal   } 11,
+              { pocall_interrupt  } 12
              );
              );
 
 
            procedure write_para(parasym:tparavarsym);
            procedure write_para(parasym:tparavarsym);

+ 13 - 0
compiler/pdecsub.pas

@@ -1611,9 +1611,22 @@ begin
 end;
 end;
 
 
 procedure pd_interrupt(pd:tabstractprocdef);
 procedure pd_interrupt(pd:tabstractprocdef);
+
+var v: Tconstexprint;
+
 begin
 begin
   if pd.parast.symtablelevel>normal_function_level then
   if pd.parast.symtablelevel>normal_function_level then
     Message(parser_e_dont_nest_interrupt);
     Message(parser_e_dont_nest_interrupt);
+
+  if target_info.system in systems_interrupt_table then
+    begin
+      if token<>_SEMICOLON then
+        begin
+          pd.proccalloption:=pocall_interrupt;
+          v:=get_intconst;
+          Tprocdef(pd).interruptvector:=v.uvalue;
+        end;
+    end;
 end;
 end;
 
 
 procedure pd_abstract(pd:tabstractprocdef);
 procedure pd_abstract(pd:tabstractprocdef);

+ 88 - 2
compiler/pmodules.pas

@@ -49,10 +49,10 @@ implementation
        wpobase,
        wpobase,
        scanner,pbase,pexpr,psystem,psub,pdecsub,ptype
        scanner,pbase,pexpr,psystem,psub,pdecsub,ptype
        ,cpuinfo
        ,cpuinfo
-{$ifdef i386}
+{$if defined(i386) or defined(ARM)}
        { fix me! }
        { fix me! }
        ,cpubase
        ,cpubase
-{$endif i386}
+{$endif defined(i386) or defined(ARM)}
        ;
        ;
 
 
 
 
@@ -472,6 +472,89 @@ implementation
       end;
       end;
 
 
 
 
+    procedure InsertInterruptTable;
+
+      procedure WriteVector(const name: string);
+        var
+          ai: taicpu;
+        begin
+{$IFDEF arm}
+          if current_settings.cputype in [cpu_armv7m, cpu_cortexm3] then
+            current_asmdata.asmlists[al_globals].concat(tai_const.Createname(name,0))
+          else
+            begin
+              ai:=taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(name));
+              ai.is_jmp:=true;
+              current_asmdata.asmlists[al_globals].concat(ai);
+            end;
+{$ENDIF arm}
+        end;
+
+      function GetInterruptTableLength: longint;
+        begin
+{$if defined(ARM)}
+          result:=interruptvectors[current_settings.controllertype];
+{$else}
+          result:=0;
+{$endif}
+        end;
+
+      var
+        hp: tused_unit;
+        sym: tsym;
+        i, i2: longint;
+        interruptTable: array of tprocdef;
+        pd: tprocdef;
+      begin
+        SetLength(interruptTable, GetInterruptTableLength);
+        FillChar(interruptTable[0], length(interruptTable)*sizeof(pointer), 0);
+
+        hp:=tused_unit(usedunits.first);
+        while assigned(hp) do
+          begin
+            for i := 0 to hp.u.symlist.Count-1 do
+              begin
+                sym:=tsym(hp.u.symlist[i]);
+                if not assigned(sym) then
+                  continue;
+                if sym.typ = procsym then
+                  begin
+                    for i2 := 0 to tprocsym(sym).ProcdefList.Count-1 do
+                      begin
+                        pd:=tprocdef(tprocsym(sym).ProcdefList[i2]);
+                        if pd.interruptvector >= 0 then
+                          begin
+                            if pd.interruptvector > high(interruptTable) then
+                              Internalerror(2011030602);
+                            if interruptTable[pd.interruptvector] <> nil then
+                              internalerror(2011030601);
+
+                            interruptTable[pd.interruptvector]:=pd;
+                            break;
+                          end;
+                      end;
+                  end;
+              end;
+            hp:=tused_unit(hp.next);
+          end;
+
+        new_section(current_asmdata.asmlists[al_globals],sec_init,'VECTORS',sizeof(pint));
+        current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('VECTORS',AT_DATA,0));
+{$IFDEF arm}
+        if current_settings.cputype in [cpu_armv7m, cpu_cortexm3] then
+          current_asmdata.asmlists[al_globals].concat(tai_const.Createname('_stack_top',0)); { ARMv7-M processors have the initial stack value at address 0 }
+{$ENDIF arm}
+
+        for i:=0 to high(interruptTable) do
+          begin
+            if interruptTable[i]<>nil then
+              writeVector(interruptTable[i].mangledname)
+            else
+              writeVector('DefaultHandler'); { Default handler name }
+          end;
+      end;
+
+
     procedure InsertMemorySizes;
     procedure InsertMemorySizes;
 {$IFDEF POWERPC}
 {$IFDEF POWERPC}
       var
       var
@@ -2363,6 +2446,9 @@ implementation
          InsertWideInitsTablesTable;
          InsertWideInitsTablesTable;
          InsertMemorySizes;
          InsertMemorySizes;
 
 
+         if target_info.system in systems_interrupt_table then
+           InsertInterruptTable;
+
          { Insert symbol to resource info }
          { Insert symbol to resource info }
          InsertResourceInfo(resources_used);
          InsertResourceInfo(resources_used);
 
 

+ 7 - 0
compiler/symdef.pas

@@ -551,6 +551,8 @@ interface
           interfacedef : boolean;
           interfacedef : boolean;
           { true if the procedure has a forward declaration }
           { true if the procedure has a forward declaration }
           hasforward  : boolean;
           hasforward  : boolean;
+          { interrupt vector }
+          interruptvector : longint;
           constructor create(level:byte);
           constructor create(level:byte);
           constructor ppuload(ppufile:tcompilerppufile);
           constructor ppuload(ppufile:tcompilerppufile);
           destructor  destroy;override;
           destructor  destroy;override;
@@ -3331,6 +3333,7 @@ implementation
 {$ifdef i386}
 {$ifdef i386}
           fpu_used:=maxfpuregs;
           fpu_used:=maxfpuregs;
 {$endif i386}
 {$endif i386}
+         interruptvector:=-1;
       end;
       end;
 
 
 
 
@@ -3369,6 +3372,8 @@ implementation
          else
          else
            import_name:=nil;
            import_name:=nil;
          import_nr:=ppufile.getword;
          import_nr:=ppufile.getword;
+         if target_info.system in systems_interrupt_table then
+           interruptvector:=ppufile.getlongint;
          if (po_msgint in procoptions) then
          if (po_msgint in procoptions) then
            messageinf.i:=ppufile.getlongint;
            messageinf.i:=ppufile.getlongint;
          if (po_msgstr in procoptions) then
          if (po_msgstr in procoptions) then
@@ -3505,6 +3510,8 @@ implementation
          if po_has_importname in procoptions then
          if po_has_importname in procoptions then
            ppufile.putstring(import_name^);
            ppufile.putstring(import_name^);
          ppufile.putword(import_nr);
          ppufile.putword(import_nr);
+         if target_info.system in systems_interrupt_table then
+           ppufile.putlongint(interruptvector);
          if (po_msgint in procoptions) then
          if (po_msgint in procoptions) then
            ppufile.putlongint(messageinf.i);
            ppufile.putlongint(messageinf.i);
          if (po_msgstr in procoptions) then
          if (po_msgstr in procoptions) then

+ 2 - 0
compiler/systems.pas

@@ -449,6 +449,8 @@ interface
 
 
        systems_internal_sysinit = [system_i386_linux,system_i386_win32];
        systems_internal_sysinit = [system_i386_linux,system_i386_win32];
 
 
+       systems_interrupt_table = [{system_arm_embedded}];
+
        { all symbian systems }
        { all symbian systems }
        systems_symbian = [system_i386_symbian,system_arm_symbian];
        systems_symbian = [system_i386_symbian,system_arm_symbian];
 
 

+ 1 - 1
compiler/systems/t_embed.pas

@@ -267,7 +267,7 @@ begin
       Add('{');
       Add('{');
       Add('     .text :');
       Add('     .text :');
       Add('    {');
       Add('    {');
-      Add('    *(.init, .init.*)');
+      Add('    KEEP(*(.init, .init.*))');
       Add('    *(.text, .text.*)');
       Add('    *(.text, .text.*)');
       Add('    *(.strings)');
       Add('    *(.strings)');
       Add('    *(.rodata, .rodata.*)');
       Add('    *(.rodata, .rodata.*)');