Переглянути джерело

Merge r22905 and r22906

git-svn-id: trunk@23773 -
florian 12 роки тому
батько
коміт
086ae4b999

+ 17 - 1
compiler/arm/aasmcpu.pas

@@ -180,6 +180,7 @@ uses
 
          constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
          constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+         constructor op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
          constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
          constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
          constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
@@ -473,6 +474,16 @@ implementation
       end;
 
 
+     constructor taicpu.op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadconst(1,aint(_op2));
+         loadconst(2,aint(_op3));
+       end;
+
+
     constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
       begin
          inherited create(op);
@@ -735,11 +746,16 @@ implementation
               { check for pre/post indexed }
               result := operand_read;
           //Thumb2
-          A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV, A_MOVW, A_MOVT, A_MLS:
+          A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV, A_MOVW, A_MOVT, A_MLS, A_BFI:
             if opnr in [0] then
               result:=operand_write
             else
               result:=operand_read;
+          A_BFC:
+            if opnr in [0] then
+              result:=operand_readwrite
+            else
+              result:=operand_read;
           A_LDREX:
             if opnr in [0] then
               result:=operand_write

+ 163 - 26
compiler/arm/aoptcpu.pas

@@ -1035,6 +1035,12 @@ Implementation
                                               A_AND, A_BIC, A_EOR, A_ORR, A_TEQ, A_TST,
                                               A_CMP, A_CMN],
                                         [taicpu(p).condition], [PF_None]) and
+                       (not ((current_settings.cputype in cpu_thumb2) and
+                             (taicpu(hp1).opcode in [A_SBC]) and
+                             (((taicpu(hp1).ops=3) and 
+                               MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^.reg)) or
+                              ((taicpu(hp1).ops=2) and 
+                               MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^.reg))))) and
                        (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
                          regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) and
                        (taicpu(hp1).ops >= 2) and
@@ -1228,13 +1234,13 @@ Implementation
                           end
                         {
                           change
-                          and reg2,reg1,255
+                          and reg2,reg1,$xxxxxxFF
                           strb reg2,[...]
                           dealloc reg2
                           to
                           strb reg1,[...]
                         }
-                        else if (taicpu(p).oper[2]^.val = 255) and
+                        else if ((taicpu(p).oper[2]^.val and $FF) = $FF) and
                           MatchInstruction(p, A_AND, [C_None], [PF_None]) and
                           GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                           MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
@@ -1249,6 +1255,29 @@ Implementation
                             asml.remove(p);
                             p.free;
                             p:=hp1;
+                            result:=true;
+                          end
+                        {
+                          change
+                          and reg2,reg1,255
+                          uxtb/uxth reg3,reg2
+                          dealloc reg2
+                          to
+                          and reg3,reg1,x
+                        }
+                        else if (taicpu(p).oper[2]^.val = $FF) and
+                          MatchInstruction(p, A_AND, [C_None], [PF_None]) and
+                          GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                          MatchInstruction(hp1, [A_UXTB,A_UXTH], [C_None], [PF_None]) and
+                          assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) and
+                          MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                          { reg1 might not be modified inbetween }
+                          not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                          begin
+                            DebugMsg('Peephole AndUxt2And done', p);
+                            taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
+                            asml.remove(hp1);
+                            result:=true;
                           end
                         {
                           from
@@ -1455,9 +1484,11 @@ Implementation
                       begin
                         DebugMsg('Peephole UxtbStrb2Strb done', p);
                         taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
                         asml.remove(p);
                         p.free;
-                        p:=hp1;
+                        p:=hp2;
+                        result:=true;
                       end
                     {
                       change
@@ -1471,16 +1502,18 @@ Implementation
                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                       MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
                       (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
-                       (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[0]^.reg)) and
+                       (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) and
                       { reg1 might not be modified inbetween }
                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
                       begin
                         DebugMsg('Peephole UxtbUxth2Uxtb done', p);
                         taicpu(hp1).opcode:=A_UXTB;
                         taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
                         asml.remove(p);
                         p.free;
-                        p:=hp1;
+                        p:=hp2;
+                        result:=true;
                       end
                     {
                       change
@@ -1494,43 +1527,64 @@ Implementation
                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                       MatchInstruction(hp1, A_UXTB, [C_None], [PF_None]) and
                       (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
-                       (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[0]^.reg)) and
+                       (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) and
                       { reg1 might not be modified inbetween }
                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
                       begin
                         DebugMsg('Peephole UxtbUxtb2Uxtb done', p);
                         taicpu(hp1).opcode:=A_UXTB;
                         taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
                         asml.remove(p);
                         p.free;
-                        p:=hp1;
+                        p:=hp2;
+                        result:=true;
                       end
                     {
                       change
-                      uxth reg2,reg1
-                      uxth reg3,reg2
+                      uxtb reg2,reg1
+                      and reg3,reg2,#0x*FF
                       dealloc reg2
                       to
-                      uxth reg3,reg1
+                      uxtb reg3,reg1
                     }
-                    else if MatchInstruction(p, A_UXTH, [C_None], [PF_None]) and
+                    else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and
                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
-                      MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
+                      MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops=3) and
+                      (taicpu(hp1).oper[2]^.typ=top_const) and
+                      ((taicpu(hp1).oper[2]^.val and $FF)=$FF) and
                       (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
-                       (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[0]^.reg)) and
+                      (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) and
                       { reg1 might not be modified inbetween }
                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
                       begin
-                        DebugMsg('Peephole UxthUxth2Uxth done', p);
-                        taicpu(hp1).opcode:=A_UXTH;
+                        DebugMsg('Peephole UxtbAndImm2Uxtb done', p);
+                        taicpu(hp1).opcode:=A_UXTB;
+                        taicpu(hp1).ops:=2;
                         taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
                         asml.remove(p);
                         p.free;
-                        p:=hp1;
+                        p:=hp2;
+                        result:=true;
+                      end
+                    else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
+                      begin
+                        //if (taicpu(p).ops=3) then
+                          RemoveSuperfluousMove(p, hp1, 'UxtbMov2Data');
                       end;
                   end;
                 A_UXTH:
                   begin
+                    {
+                      change
+                      uxth reg2,reg1
+                      strh reg2,[...]
+                      dealloc reg2
+                      to
+                      strh reg1,[...]
+                    }
                     if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                       MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
@@ -1545,6 +1599,64 @@ Implementation
                         asml.remove(p);
                         p.free;
                         p:=hp1;
+                        result:=true;
+                      end
+                    {
+                      change
+                      uxth reg2,reg1
+                      uxth reg3,reg2
+                      dealloc reg2
+                      to
+                      uxth reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_UXTH, [C_None], [PF_None]) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
+                      (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
+                      (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole UxthUxth2Uxth done', p);
+                        taicpu(hp1).opcode:=A_UXTH;
+                        taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end
+                    {
+                      change
+                      uxth reg2,reg1
+                      and reg3,reg2,#65535
+                      dealloc reg2
+                      to
+                      uxth reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_UXTH, [C_None], [PF_None]) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops=3) and
+                      (taicpu(hp1).oper[2]^.typ=top_const) and
+                      ((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) and
+                      (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
+                      (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole UxthAndImm2Uxth done', p);
+                        taicpu(hp1).opcode:=A_UXTH;
+                        taicpu(hp1).ops:=2;
+                        taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end
+                    else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
+                      begin
+                        //if (taicpu(p).ops=3) then
+                          RemoveSuperfluousMove(p, hp1, 'UxthMov2Data');
                       end;
                   end;
                 A_CMP:
@@ -2091,12 +2203,16 @@ Implementation
       hp : taicpu;
       hp1,hp2 : tai;
     begin
-      if (p.typ=ait_instruction) and
+      result:=false;
+      if inherited PeepHoleOptPass1Cpu(p) then
+        result:=true
+      else if (p.typ=ait_instruction) and
         MatchInstruction(p, A_STM, [C_None], [PF_FD,PF_DB]) and
         (taicpu(p).oper[0]^.ref^.addressmode=AM_PREINDEXED) and
         (taicpu(p).oper[0]^.ref^.index=NR_STACK_POINTER_REG) and
         ((taicpu(p).oper[1]^.regset^*[8..13,15])=[]) then
         begin
+          DebugMsg('Peephole Stm2Push done', p);
           hp := taicpu.op_regset(A_PUSH, R_INTREGISTER, R_SUBWHOLE, taicpu(p).oper[1]^.regset^);
           AsmL.InsertAfter(hp, p);
           asml.Remove(p);
@@ -2110,6 +2226,7 @@ Implementation
         (taicpu(p).oper[1]^.ref^.offset=-4) and
         (getsupreg(taicpu(p).oper[0]^.reg) in [0..7,14]) then
         begin
+          DebugMsg('Peephole Str2Push done', p);
           hp := taicpu.op_regset(A_PUSH, R_INTREGISTER, R_SUBWHOLE, [getsupreg(taicpu(p).oper[0]^.reg)]);
           asml.InsertAfter(hp, p);
           asml.Remove(p);
@@ -2123,6 +2240,7 @@ Implementation
         (taicpu(p).oper[0]^.ref^.index=NR_STACK_POINTER_REG) and
         ((taicpu(p).oper[1]^.regset^*[8..14])=[]) then
         begin
+          DebugMsg('Peephole Ldm2Pop done', p);
           hp := taicpu.op_regset(A_POP, R_INTREGISTER, R_SUBWHOLE, taicpu(p).oper[1]^.regset^);
           asml.InsertBefore(hp, p);
           asml.Remove(p);
@@ -2137,6 +2255,7 @@ Implementation
         (taicpu(p).oper[1]^.ref^.offset=4) and
         (getsupreg(taicpu(p).oper[0]^.reg) in [0..7,15]) then
         begin
+          DebugMsg('Peephole Ldr2Pop done', p);
           hp := taicpu.op_regset(A_POP, R_INTREGISTER, R_SUBWHOLE, [getsupreg(taicpu(p).oper[0]^.reg)]);
           asml.InsertBefore(hp, p);
           asml.Remove(p);
@@ -2151,6 +2270,7 @@ Implementation
         (taicpu(p).oper[1]^.val < 256) and
         (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs)) then
         begin
+          DebugMsg('Peephole Mov2Movs done', p);
           asml.InsertBefore(tai_regalloc.alloc(NR_DEFAULTFLAGS,p), p);
           asml.InsertAfter(tai_regalloc.dealloc(NR_DEFAULTFLAGS,p), p);
           IncludeRegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs);
@@ -2162,6 +2282,7 @@ Implementation
         (taicpu(p).oper[1]^.typ=top_reg) and
         (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs)) then
         begin
+          DebugMsg('Peephole Mvn2Mvns done', p);
           asml.InsertBefore(tai_regalloc.alloc(NR_DEFAULTFLAGS,p), p);
           asml.InsertAfter(tai_regalloc.dealloc(NR_DEFAULTFLAGS,p), p);
           IncludeRegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs);
@@ -2178,6 +2299,7 @@ Implementation
         (taicpu(p).oper[2]^.val < 256) and
         (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs)) then
         begin
+          DebugMsg('Peephole AddSub2*s done', p);
           asml.InsertBefore(tai_regalloc.alloc(NR_DEFAULTFLAGS,p), p);
           asml.InsertAfter(tai_regalloc.dealloc(NR_DEFAULTFLAGS,p), p);
           IncludeRegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs);
@@ -2192,6 +2314,7 @@ Implementation
         MatchOperand(taicpu(p).oper[0]^, taicpu(p).oper[1]^) and
         (taicpu(p).oper[2]^.typ=top_reg) then
         begin
+          DebugMsg('Peephole AddRRR2AddRR done', p);
           taicpu(p).ops := 2;
           taicpu(p).loadreg(1,taicpu(p).oper[2]^.reg);
           result:=true;
@@ -2211,6 +2334,19 @@ Implementation
           taicpu(p).oppostfix:=PF_S;
           result:=true;
         end
+      else if (p.typ=ait_instruction) and
+        MatchInstruction(p, [A_AND,A_ORR,A_EOR,A_BIC,A_LSL,A_LSR,A_ASR,A_ROR], [C_None], [PF_S]) and
+        (taicpu(p).ops = 3) and
+        MatchOperand(taicpu(p).oper[0]^, taicpu(p).oper[1]^) and
+        (taicpu(p).oper[2]^.typ in [top_reg,top_const]) then
+        begin
+          taicpu(p).ops := 2;
+          if taicpu(p).oper[2]^.typ=top_reg then
+            taicpu(p).loadreg(1,taicpu(p).oper[2]^.reg)
+          else
+            taicpu(p).loadconst(1,taicpu(p).oper[2]^.val);
+          result:=true;
+        end
       else if (p.typ=ait_instruction) and
         MatchInstruction(p, [A_AND,A_ORR,A_EOR], [C_None], [PF_None,PF_S]) and
         (taicpu(p).ops = 3) and
@@ -2229,19 +2365,15 @@ Implementation
         (taicpu(p).ops=3) and
         (taicpu(p).oper[2]^.typ=top_shifterop) and
         (taicpu(p).oper[2]^.shifterop^.shiftmode in [SM_LSL,SM_LSR,SM_ASR,SM_ROR]) and
-        MatchOperand(taicpu(p).oper[0]^, taicpu(p).oper[1]^) and
+        //MatchOperand(taicpu(p).oper[0]^, taicpu(p).oper[1]^) and
         (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs)) then
         begin
+          DebugMsg('Peephole Mov2Shift done', p);
           asml.InsertBefore(tai_regalloc.alloc(NR_DEFAULTFLAGS,p), p);
           asml.InsertAfter(tai_regalloc.dealloc(NR_DEFAULTFLAGS,p), p);
           IncludeRegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs);
           taicpu(p).oppostfix:=PF_S;
-          taicpu(p).ops := 2;
-
-          if taicpu(p).oper[2]^.shifterop^.rs<>NR_NO then
-            taicpu(p).loadreg(1, taicpu(p).oper[2]^.shifterop^.rs)
-          else
-            taicpu(p).loadconst(1, taicpu(p).oper[2]^.shifterop^.shiftimm);
+          //taicpu(p).ops := 2;
 
           case taicpu(p).oper[2]^.shifterop^.shiftmode of
             SM_LSL: taicpu(p).opcode:=A_LSL;
@@ -2249,6 +2381,11 @@ Implementation
             SM_ASR: taicpu(p).opcode:=A_ASR;
             SM_ROR: taicpu(p).opcode:=A_ROR;
           end;
+
+          if taicpu(p).oper[2]^.shifterop^.rs<>NR_NO then
+            taicpu(p).loadreg(2, taicpu(p).oper[2]^.shifterop^.rs)
+          else
+            taicpu(p).loadconst(2, taicpu(p).oper[2]^.shifterop^.shiftimm);
           result:=true;
         end
       else if (p.typ=ait_instruction) and
@@ -2258,6 +2395,7 @@ Implementation
         ((taicpu(p).oper[1]^.val=255) or
          (taicpu(p).oper[1]^.val=65535)) then
         begin
+          DebugMsg('Peephole AndR2Uxt done', p);
           if taicpu(p).oper[1]^.val=255 then
             taicpu(p).opcode:=A_UXTB
           else
@@ -2274,6 +2412,7 @@ Implementation
         ((taicpu(p).oper[2]^.val=255) or
          (taicpu(p).oper[2]^.val=65535)) then
         begin
+          DebugMsg('Peephole AndRR2Uxt done', p);
           if taicpu(p).oper[2]^.val=255 then
             taicpu(p).opcode:=A_UXTB
           else
@@ -2383,8 +2522,6 @@ Implementation
 
           result := true;
         end}
-      else
-        Result := inherited PeepHoleOptPass1Cpu(p);
     end;
 
   procedure TCpuThumb2AsmOptimizer.PeepHoleOptPass2;

+ 2 - 2
compiler/arm/armatt.inc

@@ -241,6 +241,8 @@
 'sxtah',
 'sxtb',
 'sxtb16',
+'uxtb',
+'uxth',
 'sxth',
 'uadd16',
 'uadd8',
@@ -269,9 +271,7 @@
 'uxtab',
 'uxtab16',
 'uxtah',
-'uxtb',
 'uxtb16',
-'uxth',
 'wfe',
 'wfi',
 'yield',

+ 4 - 3
compiler/arm/armins.dat

@@ -662,6 +662,10 @@ reg32,reg32,reg32,reg32  \x16\x00\x80\x90		 ARM7
 [SXTAHcc]
 [SXTBcc]
 [SXTB16cc]
+
+[UXTBcc]
+[UXTHcc]
+
 [SXTHcc]
 
 [UADD16cc]
@@ -699,10 +703,7 @@ reg32,reg32,reg32,reg32  \x16\x00\x80\x90		 ARM7
 [UXTABcc]
 [UXTAB16cc]
 [UXTAHcc]
-
-[UXTBcc]
 [UXTB16cc]
-[UXTHcc]
 
 [WFEcc]
 [WFIcc]

+ 2 - 2
compiler/arm/armop.inc

@@ -241,6 +241,8 @@ A_SXTAB16,
 A_SXTAH,
 A_SXTB,
 A_SXTB16,
+A_UXTB,
+A_UXTH,
 A_SXTH,
 A_UADD16,
 A_UADD8,
@@ -269,9 +271,7 @@ A_USUB8,
 A_UXTAB,
 A_UXTAB16,
 A_UXTAH,
-A_UXTB,
 A_UXTB16,
-A_UXTH,
 A_WFE,
 A_WFI,
 A_YIELD,

+ 28 - 3
compiler/arm/cgcpu.pas

@@ -186,6 +186,7 @@ unit cgcpu;
         procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
         procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
 
+        procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
         procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
         procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
 
@@ -1540,12 +1541,12 @@ unit cgcpu;
             list.Concat(taicpu.op_reg_reg_const(A_RSB,dst,dst,31));
             list.Concat(taicpu.op_reg_reg_const(A_AND,dst,dst,255));
           end
-        { it is decided during the compilation of the system unit if this code is used or not 
+        { it is decided during the compilation of the system unit if this code is used or not
           so no additional check for rbit is needed                                           }
         else
           begin
             list.Concat(taicpu.op_reg_reg(A_RBIT,dst,src));
-            list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst));            
+            list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst));
             a_reg_alloc(list,NR_DEFAULTFLAGS);
             list.Concat(taicpu.op_reg_const(A_CMP,dst,32));
             if current_settings.cputype in cpu_thumb2 then
@@ -4021,9 +4022,26 @@ unit cgcpu;
        end;
 
 
+    procedure tthumb2cgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+      begin
+        if op = OP_NOT then
+          begin
+            list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
+            case size of
+              OS_8: list.concat(taicpu.op_reg_reg(A_UXTB,dst,dst));
+              OS_S8: list.concat(taicpu.op_reg_reg(A_SXTB,dst,dst));
+              OS_16: list.concat(taicpu.op_reg_reg(A_UXTH,dst,dst));
+              OS_S16: list.concat(taicpu.op_reg_reg(A_SXTH,dst,dst));
+            end;
+          end
+        else
+          inherited a_op_reg_reg(list, op, size, src, dst);
+      end;
+
+
     procedure tthumb2cgarm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
       var
-        shift : byte;
+        shift, width : byte;
         tmpreg : tregister;
         so : tshifterop;
         l1 : longint;
@@ -4198,8 +4216,15 @@ unit cgcpu;
               list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,not(dword(a))))}
             else if (op = OP_AND) and is_thumb32_imm(a) then
               list.concat(taicpu.op_reg_reg_const(A_MOV,dst,src,dword(a)))
+            else if (op = OP_AND) and (a = $FFFF) then
+              list.concat(taicpu.op_reg_reg(A_UXTH,dst,src))
             else if (op = OP_AND) and is_thumb32_imm(not(dword(a))) then
               list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,not(dword(a))))
+            else if (op = OP_AND) and is_continuous_mask(not(a), shift, width) then
+              begin
+                a_load_reg_reg(list,size,size,src,dst);
+                list.concat(taicpu.op_reg_const_const(A_BFC,dst,shift,width))
+              end
             else
               begin
                 tmpreg:=getintregister(list,size);

+ 14 - 1
compiler/arm/cpubase.pas

@@ -46,7 +46,7 @@ unit cpubase;
       TAsmOp= {$i armop.inc}
       {This is a bit of a hack, because there are more than 256 ARM Assembly Ops
        But FPC currently can't handle more than 256 elements in a set.}
-      TCommonAsmOps = Set of A_None .. A_UQASX;
+      TCommonAsmOps = Set of A_None .. A_UADD16;
 
       { This should define the array of instructions as string }
       op2strtable=array[tasmop] of string[11];
@@ -368,6 +368,7 @@ unit cpubase;
       doesn't handle ROR_C detection }
     function is_thumb32_imm(d : aint) : boolean;
     function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword):boolean;
+    function is_continuous_mask(d : aint;var lsb, width: byte) : boolean;
     function dwarf_reg(r:tregister):shortint;
 
     function IsIT(op: TAsmOp) : boolean;
@@ -595,6 +596,18 @@ unit cpubase;
             exit;
           end;
       end;
+    
+    function is_continuous_mask(d : aint;var lsb, width: byte) : boolean;
+      var
+        msb : byte;
+      begin
+        lsb:=BsfDword(d);
+        msb:=BsrDword(d);
+        
+        width:=msb-lsb+1;
+        
+        result:=(lsb<>255) and (msb<>255) and ((((1 shl (msb-lsb+1))-1) shl lsb) = d);
+      end;
 
 
     function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword) : boolean;

+ 24 - 12
compiler/arm/cpuinfo.pas

@@ -197,7 +197,9 @@ Type
       ct_lm3s9b92,
       ct_lm3s9b95,
       ct_lm3s9b96,
-      
+
+      ct_lm3s5d51,
+
       { TI Stellaris }
       ct_lm4f120h5,
       
@@ -943,7 +945,7 @@ Const
         sramsize:$00010000
         ),
 
-        { TI - Tempest parts - 256 K Flash, 64 K SRAM }
+        { TI - Tempest parts - up to 512 K Flash, 96 K SRAM }
         // ct_lm3s5951,
         (
     	controllertypestr:'LM3S5951';
@@ -969,7 +971,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s2b93,
         (
@@ -978,7 +980,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s5b91,
         (
@@ -987,7 +989,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s9b81,
         (
@@ -996,7 +998,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s9b90,
         (
@@ -1005,7 +1007,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s9b92,
         (
@@ -1014,7 +1016,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s9b95,
         (
@@ -1023,7 +1025,7 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
         ),
         // ct_lm3s9b96,
         (
@@ -1032,7 +1034,17 @@ Const
         flashbase:$00000000;
         flashsize:$00040000;
         srambase:$20000000;
-        sramsize:$00010000
+        sramsize:$00018000
+        ),
+        
+        // ct_lm3s5d51,
+        (
+    	controllertypestr:'LM3S5D51';
+        controllerunitstr:'LM3TEMPEST';
+        flashbase:$00000000;
+        flashsize:$00080000;
+        srambase:$20000000;
+        sramsize:$00018000
         ),
         
         // ct_lm4f120h5,
@@ -1060,9 +1072,9 @@ Const
     	controllertypestr:'THUMB2_BARE';
         controllerunitstr:'THUMB2_BARE';
         flashbase:$00000000;
-        flashsize:$00100000;
+        flashsize:$00002000;
         srambase:$20000000;
-        sramsize:$00100000
+        sramsize:$00000400
         )
     );
 

+ 2 - 0
compiler/systems/t_embed.pas

@@ -339,6 +339,8 @@ begin
       ct_lm3s9b95,
       ct_lm3s9b96,
       
+      ct_lm3s5d51,
+      
       { TI - Stellaris something }
       ct_lm4f120h5,
       

+ 95 - 71
rtl/embedded/arm/lm3tempest.pp

@@ -6,7 +6,7 @@ based on stm32f103 created by Jeppe Johansen 2009 - [email protected]
 }
 {$goto on}
 unit lm3tempest;
-
+{$define highspeedports}
   interface
 
     type
@@ -17,8 +17,20 @@ unit lm3tempest;
       PeripheralBase 	= $40000000;
       PPBbase		= $E0000fff;
       APBbase 		= PeripheralBase;
-      AHBbase 		= PeripheralBase+$54000;
-      portAoffset=APBbase+$4000;
+      
+{$ifdef highspeedports}
+      portAoffset=APBbase+$58000;     
+      portBoffset=APBbase+$59000;
+      portCoffset=APBbase+$5A000;
+      portDoffset=APBbase+$5B000;
+      portEoffset=APBbase+$5C000;
+      portFoffset=APBbase+$5D000;
+      portGoffset=APBbase+$5E000;
+      portHoffset=APBbase+$5F000;
+      portJoffset=APBbase+$60000;
+      
+{$else}
+      portAoffset=APBbase+$4000;     
       portBoffset=APBbase+$5000;
       portCoffset=APBbase+$6000;
       portDoffset=APBbase+$7000;
@@ -27,9 +39,9 @@ unit lm3tempest;
       portGoffset=APBbase+$26000;
       portHoffset=APBbase+$27000;
       portJoffset=APBbase+$3d000;
+{$endif}
       sysconoffset=APBbase+$fe000;
-
-
+      
     type
       TgpioPort=record
         data:array[0..255] of dword;dir,_is,ibe,iev,im,ris,mis,icr,
@@ -57,9 +69,9 @@ unit lm3tempest;
       PortJ			:Tgpioport	absolute portJoffset;
 
       syscon			:Tsyscon	absolute sysconoffset;
-      rcgc0			:dword absolute (sysconoffset+$100);
-      rcgc1			:dword absolute (sysconoffset+$104);
-      rcgc2			:dword absolute (sysconoffset+$108);
+    //  rcgc0			:dword absolute (sysconoffset+$100);
+   //   rcgc1			:dword absolute (sysconoffset+$104);
+    //  rcgc2			:dword absolute (sysconoffset+$108);
 	
   implementation
 
@@ -85,6 +97,7 @@ procedure PWM_Fault_Interrupt; external name 'PWM_Fault_Interrupt';
 procedure PWM_Generator_0_Interrupt; external name 'PWM_Generator_0_Interrupt';
 procedure PWM_Generator_1_Interrupt; external name 'PWM_Generator_1_Interrupt';
 procedure PWM_Generator_2_Interrupt; external name 'PWM_Generator_2_Interrupt';
+procedure PWM_Generator_3_Interrupt; external name 'PWM_Generator_3_Interrupt';
 procedure QEI0_Interrupt; external name 'QEI0_Interrupt';
 procedure ADC0_Sequence_0_Interrupt; external name 'ADC0_Sequence_0_Interrupt';
 procedure ADC0_Sequence_1_Interrupt; external name 'ADC0_Sequence_1_Interrupt';
@@ -99,6 +112,7 @@ procedure Timer_2A_Interrupt; external name 'Timer_2A_Interrupt';
 procedure Timer_2B_Interrupt; external name 'Timer_2B_Interrupt';
 procedure Analog_Comparator_0_Interrupt; external name 'Analog_Comparator_0_Interrupt';
 procedure Analog_Comparator_1_Interrupt; external name 'Analog_Comparator_1_Interrupt';
+procedure Analog_Comparator_2_Interrupt; external name 'Analog_Comparator_2_Interrupt';
 procedure System_Control_Interrupt; external name 'System_Control_Interrupt';
 procedure Flash_Memory_Control_Interrupt; external name 'Flash_Memory_Control_Interrupt';
 procedure GPIO_Port_F_Interrupt; external name 'GPIO_Port_F_Interrupt';
@@ -112,6 +126,7 @@ procedure I2C1_Interrupt; external name 'I2C1_Interrupt';
 procedure QEI1_Interrupt; external name 'QEI1_Interrupt';
 procedure CAN0_Interrupt; external name 'CAN0_Interrupt';
 procedure CAN1_Interrupt; external name 'CAN1_Interrupt';
+procedure ETH_Interrupt; external name 'ETH_Interrupt';
 procedure Hibernation_Module_Interrupt; external name 'Hibernation_Module_Interrupt';
 procedure USB_Interrupt; external name 'USB_Interrupt';
 procedure uDMA_Software_Interrupt; external name 'uDMA_Software_Interrupt';
@@ -121,6 +136,7 @@ procedure ADC1_Sequence_1_Interrupt; external name 'ADC1_Sequence_1_Interrupt';
 procedure ADC1_Sequence_2_Interrupt; external name 'ADC1_Sequence_2_Interrupt';
 procedure ADC1_Sequence_3_Interrupt; external name 'ADC1_Sequence_3_Interrupt';
 procedure I2S0_Interrupt; external name 'I2S0_Interrupt';
+procedure EPI_interrupt; external name 'EPI_Interrupt';
 procedure GPIO_Port_J_Interrupt; external name 'GPIO_Port_J_Interrupt';
 
 {$i cortexm3_start.inc}
@@ -174,7 +190,7 @@ interrupt_vectors:
   .long Timer_2B_Interrupt
   .long Analog_Comparator_0_Interrupt
   .long Analog_Comparator_1_Interrupt
-  .long 0
+  .long Analog_Comparator_2_Interrupt
   .long System_Control_Interrupt
   .long Flash_Memory_Control_Interrupt
   .long GPIO_Port_F_Interrupt
@@ -189,10 +205,10 @@ interrupt_vectors:
   .long CAN0_Interrupt
   .long CAN1_Interrupt
   .long 0
-  .long 0
+  .long ETH_Interrupt
   .long Hibernation_Module_Interrupt
   .long USB_Interrupt
-  .long 0
+  .long PWM_Generator_3_Interrupt
   .long uDMA_Software_Interrupt
   .long uDMA_Error_Interrupt
   .long ADC1_Sequence_0_Interrupt
@@ -200,7 +216,7 @@ interrupt_vectors:
   .long ADC1_Sequence_2_Interrupt
   .long ADC1_Sequence_3_Interrupt
   .long I2S0_Interrupt
-  .long 0
+  .long EPI_Interrupt
   .long GPIO_Port_J_Interrupt
   
   .weak NMI_interrupt
@@ -226,6 +242,7 @@ interrupt_vectors:
   .weak PWM_Generator_0_Interrupt
   .weak PWM_Generator_1_Interrupt
   .weak PWM_Generator_2_Interrupt
+  .weak PWM_Generator_3_Interrupt
   .weak QEI0_Interrupt
   .weak ADC0_Sequence_0_Interrupt
   .weak ADC0_Sequence_1_Interrupt
@@ -240,6 +257,7 @@ interrupt_vectors:
   .weak Timer_2B_Interrupt
   .weak Analog_Comparator_0_Interrupt
   .weak Analog_Comparator_1_Interrupt
+  .weak Analog_Comparator_2_Interrupt
   .weak System_Control_Interrupt
   .weak Flash_Memory_Control_Interrupt
   .weak GPIO_Port_F_Interrupt
@@ -253,6 +271,7 @@ interrupt_vectors:
   .weak QEI1_Interrupt
   .weak CAN0_Interrupt
   .weak CAN1_Interrupt
+  .weak ETH_Interrupt
   .weak Hibernation_Module_Interrupt
   .weak USB_Interrupt
   .weak uDMA_Software_Interrupt
@@ -262,68 +281,73 @@ interrupt_vectors:
   .weak ADC1_Sequence_2_Interrupt
   .weak ADC1_Sequence_3_Interrupt
   .weak I2S0_Interrupt
+  .weak EPI_Interrupt
   .weak GPIO_Port_J_Interrupt
   
-  .set NMI_interrupt, Startup
-  .set Hardfault_interrupt, Startup
-  .set MemManage_interrupt, Startup
-  .set BusFault_interrupt, Startup
-  .set UsageFault_interrupt, Startup
-  .set SWI_interrupt, Startup
-  .set DebugMonitor_interrupt, Startup
-  .set PendingSV_interrupt, Startup
-  .set SysTick_interrupt, Startup
+  .set NMI_interrupt, haltproc
+  .set Hardfault_interrupt, haltproc
+  .set MemManage_interrupt, haltproc
+  .set BusFault_interrupt, haltproc
+  .set UsageFault_interrupt, haltproc
+  .set SWI_interrupt, haltproc
+  .set DebugMonitor_interrupt, haltproc
+  .set PendingSV_interrupt, haltproc
+  .set SysTick_interrupt, haltproc
 
-  .set GPIO_Port_A_Interrupt, Startup
-  .set GPIO_Port_B_Interrupt, Startup
-  .set GPIO_Port_C_Interrupt, Startup
-  .set GPIO_Port_D_Interrupt, Startup
-  .set GPIO_Port_E_Interrupt, Startup
-  .set UART0_Interrupt, Startup
-  .set UART1_Interrupt, Startup
-  .set SSI0_Interrupt, Startup
-  .set I2C0_Interrupt, Startup
-  .set PWM_Fault_Interrupt, Startup
-  .set PWM_Generator_0_Interrupt, Startup
-  .set PWM_Generator_1_Interrupt, Startup
-  .set PWM_Generator_2_Interrupt, Startup
-  .set QEI0_Interrupt, Startup
-  .set ADC0_Sequence_0_Interrupt, Startup
-  .set ADC0_Sequence_1_Interrupt, Startup
-  .set ADC0_Sequence_2_Interrupt, Startup
-  .set ADC0_Sequence_3_Interrupt, Startup
-  .set Watchdog_Timers_0_and_1_Interrupt, Startup
-  .set Timer_0A_Interrupt, Startup
-  .set Timer_0B_Interrupt, Startup
-  .set Timer_1A_Interrupt, Startup
-  .set Timer_1B_Interrupt, Startup
-  .set Timer_2A_Interrupt, Startup
-  .set Timer_2B_Interrupt, Startup
-  .set Analog_Comparator_0_Interrupt, Startup
-  .set Analog_Comparator_1_Interrupt, Startup
-  .set System_Control_Interrupt, Startup
-  .set Flash_Memory_Control_Interrupt, Startup
-  .set GPIO_Port_F_Interrupt, Startup
-  .set GPIO_Port_G_Interrupt, Startup
-  .set GPIO_Port_H_Interrupt, Startup
-  .set UART2_Interrupt, Startup
-  .set SSI1_Interrupt, Startup
-  .set Timer_3A_Interrupt, Startup
-  .set Timer_3B_Interrupt, Startup
-  .set I2C1_Interrupt, Startup
-  .set QEI1_Interrupt, Startup
-  .set CAN0_Interrupt, Startup
-  .set CAN1_Interrupt, Startup
-  .set Hibernation_Module_Interrupt, Startup
-  .set USB_Interrupt, Startup
-  .set uDMA_Software_Interrupt, Startup
-  .set uDMA_Error_Interrupt, Startup
-  .set ADC1_Sequence_0_Interrupt, Startup
-  .set ADC1_Sequence_1_Interrupt, Startup
-  .set ADC1_Sequence_2_Interrupt, Startup
-  .set ADC1_Sequence_3_Interrupt, Startup
-  .set I2S0_Interrupt, Startup
-  .set GPIO_Port_J_Interrupt, Startup
+  .set GPIO_Port_A_Interrupt, haltproc
+  .set GPIO_Port_B_Interrupt, haltproc
+  .set GPIO_Port_C_Interrupt, haltproc
+  .set GPIO_Port_D_Interrupt, haltproc
+  .set GPIO_Port_E_Interrupt, haltproc
+  .set UART0_Interrupt, haltproc
+  .set UART1_Interrupt, haltproc
+  .set SSI0_Interrupt, haltproc
+  .set I2C0_Interrupt, haltproc
+  .set PWM_Fault_Interrupt, haltproc
+  .set PWM_Generator_0_Interrupt, haltproc
+  .set PWM_Generator_1_Interrupt, haltproc
+  .set PWM_Generator_2_Interrupt, haltproc
+  .set PWM_Generator_3_Interrupt, haltproc
+  .set QEI0_Interrupt, haltproc
+  .set ADC0_Sequence_0_Interrupt, haltproc
+  .set ADC0_Sequence_1_Interrupt, haltproc
+  .set ADC0_Sequence_2_Interrupt, haltproc
+  .set ADC0_Sequence_3_Interrupt, haltproc
+  .set Watchdog_Timers_0_and_1_Interrupt, haltproc
+  .set Timer_0A_Interrupt, haltproc
+  .set Timer_0B_Interrupt, haltproc
+  .set Timer_1A_Interrupt, haltproc
+  .set Timer_1B_Interrupt, haltproc
+  .set Timer_2A_Interrupt, haltproc
+  .set Timer_2B_Interrupt, haltproc
+  .set Analog_Comparator_0_Interrupt, haltproc
+  .set Analog_Comparator_1_Interrupt, haltproc
+  .set Analog_Comparator_2_Interrupt, haltproc
+  .set System_Control_Interrupt, haltproc
+  .set Flash_Memory_Control_Interrupt, haltproc
+  .set GPIO_Port_F_Interrupt, haltproc
+  .set GPIO_Port_G_Interrupt, haltproc
+  .set GPIO_Port_H_Interrupt, haltproc
+  .set UART2_Interrupt, haltproc
+  .set SSI1_Interrupt, haltproc
+  .set Timer_3A_Interrupt, haltproc
+  .set Timer_3B_Interrupt, haltproc
+  .set I2C1_Interrupt, haltproc
+  .set QEI1_Interrupt, haltproc
+  .set CAN0_Interrupt, haltproc
+  .set CAN1_Interrupt, haltproc
+  .set ETH_Interrupt, haltproc
+  .set Hibernation_Module_Interrupt, haltproc
+  .set USB_Interrupt, haltproc
+  .set uDMA_Software_Interrupt, haltproc
+  .set uDMA_Error_Interrupt, haltproc
+  .set ADC1_Sequence_0_Interrupt, haltproc
+  .set ADC1_Sequence_1_Interrupt, haltproc
+  .set ADC1_Sequence_2_Interrupt, haltproc
+  .set ADC1_Sequence_3_Interrupt, haltproc
+  .set I2S0_Interrupt, haltproc
+  .set EPI_Interrupt, haltproc
+  .set GPIO_Port_J_Interrupt, haltproc
   
   .text
 end;