Răsfoiți Sursa

* AVR: decide after compiler if a certain subroutine is suitable for avr1, if not, replace it by sleep and warn

git-svn-id: trunk@44133 -
florian 5 ani în urmă
părinte
comite
a905a074b0
5 a modificat fișierele cu 506 adăugiri și 441 ștergeri
  1. 111 51
      compiler/avr/aasmcpu.pas
  2. 3 2
      compiler/avr/cpupi.pas
  3. 4 0
      compiler/msg/errore.msg
  4. 3 2
      compiler/msgidx.inc
  5. 385 386
      compiler/msgtxt.inc

+ 111 - 51
compiler/avr/aasmcpu.pas

@@ -108,7 +108,7 @@ uses
 
     { replaces cond. branches by rjmp/jmp and the inverse cond. branch if needed
       and transforms special instructions to valid instruction encodings }
-    procedure finalizeavrcode(list : TAsmList);
+    function finalizeavrcode(list : TAsmList) : Boolean;
 
 implementation
 
@@ -396,15 +396,42 @@ implementation
       end;
 
 
-    procedure finalizeavrcode(list : TAsmList);
+    function finalizeavrcode(list : TAsmList) : Boolean;
       var
         CurrOffset : longint;
-        curtai : tai;
+        curtai, firstinstruction: tai;
         again : boolean;
         l : tasmlabel;
         inasmblock : Boolean;
+
+      procedure remove_instruction;
+        var
+          i: Integer;
+          hp: tai;
+        begin
+          taicpu(firstinstruction).opcode:=A_SLEEP;
+          for i:=0 to taicpu(firstinstruction).opercnt-1 do
+            taicpu(firstinstruction).freeop(i);
+          taicpu(firstinstruction).opercnt:=0;
+          taicpu(firstinstruction).ops:=0;
+          firstinstruction:=tai(firstinstruction.Next);
+          while assigned(firstinstruction) do
+            begin
+              if firstinstruction.typ in [ait_symbol_end,ait_label] then
+                firstinstruction:=tai(firstinstruction.Next)
+              else
+                begin
+                  hp:=tai(firstinstruction.Next);
+                  list.Remove(firstinstruction);
+                  firstinstruction.free;
+                  firstinstruction:=hp;
+                end;
+            end;
+        end;
+
       begin
         again:=true;
+        Result:=true;
         while again do
           begin
             again:=false;
@@ -439,62 +466,95 @@ implementation
 
             curtai:=tai(list.first);
             inasmblock:=false;
+            firstinstruction:=nil;
             while assigned(curtai) do
               begin
                 case curtai.typ of
                   ait_instruction:
-                    case taicpu(curtai).opcode of
-                      A_BRxx:
-                        if (taicpu(curtai).oper[0]^.typ=top_ref) and ((taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>64) or
-                          (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<-63)) then
+                    begin
+                      if not(assigned(firstinstruction)) then
+                        firstinstruction:=curtai;
+                      case taicpu(curtai).opcode of
+                        A_BRxx:
+                          if (taicpu(curtai).oper[0]^.typ=top_ref) and ((taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>64) or
+                            (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<-63)) then
+                            begin
+                              if inasmblock then
+                                Message(asmw_e_brxx_out_of_range)
+                              else
+                                begin
+                                  current_asmdata.getjumplabel(l);
+                                  list.insertafter(tai_label.create(l),curtai);
+                                  if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
+                                    list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai)
+                                  else
+                                    list.insertafter(taicpu.op_sym(A_RJMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai);
+                                  taicpu(curtai).oper[0]^.ref^.symbol:=l;
+                                  taicpu(curtai).condition:=inverse_cond(taicpu(curtai).condition);
+                                  again:=true;
+                                end;
+                            end;
+                        A_JMP:
+                          { replace JMP by RJMP? ...
+                            ... but do not mess with asm block }
+                          if not(inasmblock) and (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<=2048) and
+                          (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>=-2047) and
+                          { jmps to function go outside the currently considered scope, so do not mess with them.
+                            Those are generated by the peephole optimizer from call/ret sequences }
+                          not(taicpu(curtai).oper[0]^.ref^.symbol.typ=AT_FUNCTION) then
                           begin
-                            if inasmblock then
-                              Message(asmw_e_brxx_out_of_range)
-                            else
+                            taicpu(curtai).opcode:=A_RJMP;
+                            again:=true;
+                          end;
+                        A_STS:
+                          begin
+                            if current_settings.cputype=cpu_avr1 then
                               begin
-                                current_asmdata.getjumplabel(l);
-                                list.insertafter(tai_label.create(l),curtai);
-                                if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
-                                  list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai)
-                                else
-                                  list.insertafter(taicpu.op_sym(A_RJMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai);
-                                taicpu(curtai).oper[0]^.ref^.symbol:=l;
-                                taicpu(curtai).condition:=inverse_cond(taicpu(curtai).condition);
-                                again:=true;
+                                remove_instruction;
+                                result:=false;
+                              end
+                            else if current_settings.cputype=cpu_avrtiny then
+                              with taicpu(curtai).oper[0]^ do
+                                if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
+                                  begin
+                                    taicpu(curtai).opcode:=A_OUT;
+                                    taicpu(curtai).loadconst(0,ref^.offset);
+                                  end;
+                          end;
+                        A_LDS:
+                          begin
+                            if current_settings.cputype=cpu_avr1 then
+                              begin
+                                remove_instruction;
+                                result:=false;
+                              end
+                            else if current_settings.cputype=cpu_avrtiny then
+                              with taicpu(curtai).oper[1]^ do
+                                if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
+                                  begin
+                                    taicpu(curtai).opcode:=A_IN;
+                                    taicpu(curtai).loadconst(1,ref^.offset)
+                                  end;
+                          end;
+                        A_SBIW,
+                        A_MULS,
+                        A_ICALL,
+                        A_IJMP,
+                        A_STD,
+                        A_LD,
+                        A_LDD,
+                        A_ST,
+                        A_ROR,
+                        A_POP,
+                        A_PUSH:
+                          begin
+                            if current_settings.cputype=cpu_avr1 then
+                              begin
+                                remove_instruction;
+                                result:=false;
                               end;
                           end;
-                      A_JMP:
-                        { replace JMP by RJMP? ...
-                          ... but do not mess with asm block }
-                        if not(inasmblock) and (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<=2048) and
-                        (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>=-2047) and
-                        { jmps to function go outside the currently considered scope, so do not mess with them.
-                          Those are generated by the peephole optimizer from call/ret sequences }
-                        not(taicpu(curtai).oper[0]^.ref^.symbol.typ=AT_FUNCTION) then
-                        begin
-                          taicpu(curtai).opcode:=A_RJMP;
-                          again:=true;
-                        end;
-                      A_STS:
-                        begin
-                          if (current_settings.cputype=cpu_avrtiny) then
-                            with taicpu(curtai).oper[0]^ do
-                              if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
-                                begin
-                                  taicpu(curtai).opcode:=A_OUT;
-                                  taicpu(curtai).loadconst(0,ref^.offset);
-                                end;
-                        end;
-                      A_LDS:
-                        begin
-                          if (current_settings.cputype=cpu_avrtiny) then
-                            with taicpu(curtai).oper[1]^ do
-                              if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
-                                begin
-                                  taicpu(curtai).opcode:=A_IN;
-                                  taicpu(curtai).loadconst(1,ref^.offset)
-                                end;
-                        end;
+                      end;
                     end;
                   ait_marker:
                     case tai_marker(curtai).Kind of

+ 3 - 2
compiler/avr/cpupi.pas

@@ -44,7 +44,7 @@ unit cpupi;
   implementation
 
     uses
-       globals,systems,
+       globals,systems,verbose,
        cpubase,
        aasmtai,aasmdata,
        tgobj,
@@ -80,7 +80,8 @@ unit cpupi;
       begin
         { because of the limited branch distance of cond. branches, they must be replaced
           sometimes by normal jmps and an inverse branch }
-        finalizeavrcode(aktproccode);
+        if not(finalizeavrcode(aktproccode)) then
+          message1(cg_w_cannot_compile_subroutine,procdef.fullprocname(false));
       end;
 
 begin

+ 4 - 0
compiler/msg/errore.msg

@@ -2537,6 +2537,10 @@ cg_e_case_missing_value=06059_E_Case statement does not handle ordinal value "$1
 # that this value can be passed to the case statement. This is a compile-time error in ISO and Extended Pascal.
 cg_w_case_incomplete=06060_W_Case statement does not handle all possible cases
 % The case statement does not contain labels for all possible values of the operand, and no else statement is present.
+cg_w_cannot_compile_subroutine=06061_W_The current subroutine "$1" cannot be compiled for the target CPU, creating dummy
+% Some processors have a very limited instruction set so some routines cannot be compiled for them. As it is not always
+% clear from the beginning if a subroutine can be compiled for a certain CPU or not, the compiler checks afterwards
+% and creates a dummy if it cannot compile the subroutine.
 %
 % \end{description}
 # EndOfTeX

+ 3 - 2
compiler/msgidx.inc

@@ -704,6 +704,7 @@ const
   cg_n_no_inline=06058;
   cg_e_case_missing_value=06059;
   cg_w_case_incomplete=06060;
+  cg_w_cannot_compile_subroutine=06061;
   asmr_d_start_reading=07000;
   asmr_d_finish_reading=07001;
   asmr_e_none_label_contain_at=07002;
@@ -1119,9 +1120,9 @@ const
   option_info=11024;
   option_help_pages=11025;
 
-  MsgTxtSize = 84379;
+  MsgTxtSize = 84469;
 
   MsgIdxMax : array[1..20] of longint=(
-    28,106,354,127,99,61,143,35,223,68,
+    28,106,354,127,99,62,143,35,223,68,
     62,20,30,1,1,1,1,1,1,1
   );

Fișier diff suprimat deoarece este prea mare
+ 385 - 386
compiler/msgtxt.inc


Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff