Browse Source

+ AVR: track flag usage
+ AVR: take care of allocated flags when spilling
* AVR: trgcpu.do_spill_read might also use ADIW

florian 3 years ago
parent
commit
0ae45bd2cf

+ 10 - 0
compiler/aasmtai.pas

@@ -388,6 +388,16 @@ interface
         mark_AsmBlockStart,mark_AsmBlockEnd,
         mark_AsmBlockStart,mark_AsmBlockEnd,
         mark_NoLineInfoStart,mark_NoLineInfoEnd,mark_BlockStart,
         mark_NoLineInfoStart,mark_NoLineInfoEnd,mark_BlockStart,
         mark_Position
         mark_Position
+{$ifdef avr}
+        { spilling on avr destroys the flags as it might use adiw/add/adc, so in case
+          the flags are allocated during spilling, this marker must be translated into
+          a push of the flags when assembler post processing is carried out }
+        ,mark_may_store_flags_with_r26
+        { spilling on avr destroys the flags as it might use adiw/add/adc, so in case
+          the flags are allocated during spilling, this marker must be translated into
+          a pop of the flags when assembler post processing is carried out }
+        ,mark_may_restore_flags_with_r26
+{$endif avr}
       );
       );
 
 
       TRegAllocType = (ra_alloc,ra_dealloc,ra_sync,ra_resize,ra_markused);
       TRegAllocType = (ra_alloc,ra_dealloc,ra_sync,ra_resize,ra_markused);

+ 51 - 2
compiler/avr/aasmcpu.pas

@@ -399,10 +399,11 @@ implementation
     function finalizeavrcode(list : TAsmList) : Boolean;
     function finalizeavrcode(list : TAsmList) : Boolean;
       var
       var
         CurrOffset : longint;
         CurrOffset : longint;
-        curtai, firstinstruction: tai;
+        curtai, firstinstruction, hp: tai;
         again : boolean;
         again : boolean;
         l : tasmlabel;
         l : tasmlabel;
-        inasmblock : Boolean;
+        inasmblock, flagsallocated: Boolean;
+        href: treference;
 
 
       procedure remove_instruction;
       procedure remove_instruction;
         var
         var
@@ -467,6 +468,7 @@ implementation
             curtai:=tai(list.first);
             curtai:=tai(list.first);
             inasmblock:=false;
             inasmblock:=false;
             firstinstruction:=nil;
             firstinstruction:=nil;
+            flagsallocated:=false;
             while assigned(curtai) do
             while assigned(curtai) do
               begin
               begin
                 case curtai.typ of
                 case curtai.typ of
@@ -557,12 +559,59 @@ implementation
                           end;
                           end;
                       end;
                       end;
                     end;
                     end;
+                  ait_regalloc:
+                    case tai_regalloc(curtai).ratype of
+                      ra_alloc:
+                        if (tai_regalloc(curtai).reg=NR_DEFAULTFLAGS) then
+                          begin
+                            { there are still douple allocations/deallocations in the cg, so
+                              this ie cannot be enabled
+                              if flagsallocated then
+                                Internalerror(2022050101);
+                            }
+                            flagsallocated:=true;
+                          end;
+                      ra_dealloc:
+                        if (tai_regalloc(curtai).reg=NR_DEFAULTFLAGS) then
+                          begin
+                            { there are still douple allocations/deallocations in the cg, so
+                              this ie cannot be enabled
+                              if not(flagsallocated) then
+                                Internalerror(2022050102);
+                            }
+                            flagsallocated:=false;
+                          end;
+                    end;
                   ait_marker:
                   ait_marker:
                     case tai_marker(curtai).Kind of
                     case tai_marker(curtai).Kind of
                       mark_AsmBlockStart:
                       mark_AsmBlockStart:
                         inasmblock:=true;
                         inasmblock:=true;
                       mark_AsmBlockEnd:
                       mark_AsmBlockEnd:
                         inasmblock:=false;
                         inasmblock:=false;
+                      mark_may_store_flags_with_r26:
+                        begin
+                          if flagsallocated then
+                            begin
+                              hp:=taicpu.op_reg_const(A_IN,NR_R26,63);
+                              list.insertafter(hp,curtai);
+                              list.insertafter(taicpu.op_reg(A_PUSH,NR_R26),hp);
+                              list.Remove(curtai);
+                              curtai.Free;
+                              curtai:=hp;
+                            end;
+                        end;
+                      mark_may_restore_flags_with_r26:
+                        begin
+                          if flagsallocated then
+                            begin
+                              hp:=taicpu.op_reg(A_POP,NR_R26);
+                              list.insertafter(hp,curtai);
+                              list.insertafter(taicpu.op_const_reg(A_OUT,63,NR_R26),hp);
+                              list.Remove(curtai);
+                              curtai.Free;
+                              curtai:=hp;
+                            end;
+                        end;
                     end;
                     end;
                 end;
                 end;
                 curtai:=tai(curtai.next);
                 curtai:=tai(curtai.next);

+ 52 - 1
compiler/avr/cgcpu.pas

@@ -442,6 +442,7 @@ unit cgcpu;
                  else
                  else
                    list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
                    list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
              end;
              end;
+           cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
            list.concat(taicpu.op_reg(A_DEC,countreg));
            list.concat(taicpu.op_reg(A_DEC,countreg));
            a_jmp_flags(list,F_NE,l1);
            a_jmp_flags(list,F_NE,l1);
            executionweight:=oldexecutionweight;
            executionweight:=oldexecutionweight;
@@ -806,22 +807,34 @@ unit cgcpu;
          case op of
          case op of
            OP_ADD:
            OP_ADD:
              begin
              begin
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
+
                list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
                list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
                for i:=2 to tcgsize2size[size] do
                for i:=2 to tcgsize2size[size] do
                  begin
                  begin
                    NextSrcDstPreInc;
                    NextSrcDstPreInc;
                    list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
                    list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
                  end;
                  end;
+
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
              end;
              end;
 
 
            OP_SUB:
            OP_SUB:
              begin
              begin
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
+
                list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
                list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
                for i:=2 to tcgsize2size[size] do
                for i:=2 to tcgsize2size[size] do
                  begin
                  begin
                    NextSrcDstPreInc;
                    NextSrcDstPreInc;
                    list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
                    list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
                  end;
                  end;
+
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
              end;
              end;
 
 
            OP_NEG:
            OP_NEG:
@@ -847,6 +860,9 @@ unit cgcpu;
                        if i<tcgsize2size[size] then
                        if i<tcgsize2size[size] then
                          NextTmp;
                          NextTmp;
                      end;
                      end;
+                   if tcgsize2size[size]>1 then
+                     cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
+
                    list.concat(taicpu.op_reg(A_NEG,dst));
                    list.concat(taicpu.op_reg(A_NEG,dst));
                    tmpreg:=GetNextReg(dst);
                    tmpreg:=GetNextReg(dst);
                    for i:=2 to tcgsize2size[size] do
                    for i:=2 to tcgsize2size[size] do
@@ -856,6 +872,9 @@ unit cgcpu;
                        if i<tcgsize2size[size] then
                        if i<tcgsize2size[size] then
                          NextTmp;
                          NextTmp;
                    end;
                    end;
+
+                   if tcgsize2size[size]>1 then
+                     cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
                  end
                  end
                else if size in [OS_S8,OS_8] then
                else if size in [OS_S8,OS_8] then
                  list.concat(taicpu.op_reg(A_NEG,dst))
                  list.concat(taicpu.op_reg(A_NEG,dst))
@@ -898,6 +917,7 @@ unit cgcpu;
                current_asmdata.getjumplabel(l2);
                current_asmdata.getjumplabel(l2);
                countreg:=getintregister(list,OS_8);
                countreg:=getintregister(list,OS_8);
                a_load_reg_reg(list,size,OS_8,src,countreg);
                a_load_reg_reg(list,size,OS_8,src,countreg);
+               cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
                list.concat(taicpu.op_reg(A_TST,countreg));
                list.concat(taicpu.op_reg(A_TST,countreg));
                a_jmp_flags(list,F_EQ,l2);
                a_jmp_flags(list,F_EQ,l2);
                cg.a_label(list,l1);
                cg.a_label(list,l1);
@@ -951,7 +971,7 @@ unit cgcpu;
                        end;
                        end;
                    end;
                    end;
                  end;
                  end;
-
+               cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
                list.concat(taicpu.op_reg(A_DEC,countreg));
                list.concat(taicpu.op_reg(A_DEC,countreg));
                a_jmp_flags(list,F_NE,l1);
                a_jmp_flags(list,F_NE,l1);
                { keep registers alive }
                { keep registers alive }
@@ -1086,6 +1106,7 @@ unit cgcpu;
                if (op=OP_SAR) and (a>=(tcgsize2size[size]*8-1)) then
                if (op=OP_SAR) and (a>=(tcgsize2size[size]*8-1)) then
                  begin
                  begin
                    current_asmdata.getjumplabel(l1);
                    current_asmdata.getjumplabel(l1);
+                   cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
                    list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
                    list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
                    a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1));
                    a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1));
                    a_jmp_flags(list,F_PL,l1);
                    a_jmp_flags(list,F_PL,l1);
@@ -1097,6 +1118,7 @@ unit cgcpu;
                else if (op=OP_SHR) and (a=(tcgsize2size[size]*8-1)) then
                else if (op=OP_SHR) and (a=(tcgsize2size[size]*8-1)) then
                  begin
                  begin
                    current_asmdata.getjumplabel(l1);
                    current_asmdata.getjumplabel(l1);
+                   cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
                    list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
                    list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
                    a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,0));
                    a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,0));
                    a_jmp_flags(list,F_PL,l1);
                    a_jmp_flags(list,F_PL,l1);
@@ -1171,6 +1193,10 @@ unit cgcpu;
            OP_ADD:
            OP_ADD:
              begin
              begin
                curvalue:=a and mask;
                curvalue:=a and mask;
+
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
+
                if curvalue=0 then
                if curvalue=0 then
                  list.concat(taicpu.op_reg_reg(A_ADD,reg,GetDefaultZeroReg))
                  list.concat(taicpu.op_reg_reg(A_ADD,reg,GetDefaultZeroReg))
                else if (curvalue=1) and (tcgsize2size[size]=1) then
                else if (curvalue=1) and (tcgsize2size[size]=1) then
@@ -1201,6 +1227,8 @@ unit cgcpu;
                          end;
                          end;
                      end;
                      end;
                  end;
                  end;
+               if tcgsize2size[size]>1 then
+                 cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
              end;
              end;
          else
          else
            begin
            begin
@@ -1308,8 +1336,10 @@ unit cgcpu;
             emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
             emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
             if ref.index<>NR_NO then
             if ref.index<>NR_NO then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
             if ref.offset>0 then
             if ref.offset>0 then
               list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
               list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
@@ -1340,13 +1370,17 @@ unit cgcpu;
 
 
             if (ref.base<>NR_NO) then
             if (ref.base<>NR_NO) then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
             if (ref.index<>NR_NO) then
             if (ref.index<>NR_NO) then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
             ref.symbol:=nil;
             ref.symbol:=nil;
             ref.offset:=0;
             ref.offset:=0;
@@ -1359,8 +1393,10 @@ unit cgcpu;
             emit_mov(list,tmpreg,ref.base);
             emit_mov(list,tmpreg,ref.base);
             maybegetcpuregister(list,GetNextReg(tmpreg));
             maybegetcpuregister(list,GetNextReg(tmpreg));
             emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
             emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
+            cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
             list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
             list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
             list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
             list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
+            cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
             ref.base:=tmpreg;
             ref.base:=tmpreg;
             ref.index:=NR_NO;
             ref.index:=NR_NO;
           end
           end
@@ -1921,6 +1957,8 @@ unit cgcpu;
                 end;
                 end;
             end;
             end;
 
 
+            cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
+
             { If doing a signed test for x<0, we can simply test the sign bit
             { If doing a signed test for x<0, we can simply test the sign bit
               of the most significant byte }
               of the most significant byte }
             if (cmp_op in [OC_LT,OC_GTE]) and
             if (cmp_op in [OC_LT,OC_GTE]) and
@@ -1949,6 +1987,8 @@ unit cgcpu;
               end;
               end;
 
 
             a_jmp_cond(list,cmp_op,l);
             a_jmp_cond(list,cmp_op,l);
+
+            cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
           end
           end
         else
         else
           inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
           inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
@@ -1992,6 +2032,9 @@ unit cgcpu;
             reg1:=reg2;
             reg1:=reg2;
             reg2:=tmpreg;
             reg2:=tmpreg;
           end;
           end;
+
+        cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
+
         list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
         list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
 
 
         for i:=2 to tcgsize2size[size] do
         for i:=2 to tcgsize2size[size] do
@@ -2002,6 +2045,7 @@ unit cgcpu;
           end;
           end;
 
 
         a_jmp_cond(list,cmp_op,l);
         a_jmp_cond(list,cmp_op,l);
+        cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
       end;
       end;
 
 
 
 
@@ -2574,13 +2618,17 @@ unit cgcpu;
 
 
             if (ref.base<>NR_NO) then
             if (ref.base<>NR_NO) then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
             if (ref.index<>NR_NO) then
             if (ref.index<>NR_NO) then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
           end
           end
         else if (ref.base<>NR_NO)then
         else if (ref.base<>NR_NO)then
@@ -2589,8 +2637,10 @@ unit cgcpu;
             emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
             emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
             if (ref.index<>NR_NO) then
             if (ref.index<>NR_NO) then
               begin
               begin
+                cg.a_reg_alloc(list, NR_DEFAULTFLAGS);
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
                 list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
+                cg.a_reg_dealloc(list, NR_DEFAULTFLAGS);
               end;
               end;
           end
           end
         else if (ref.index<>NR_NO) then
         else if (ref.index<>NR_NO) then
@@ -2698,6 +2748,7 @@ unit cgcpu;
             list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
             list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
             list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
             list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
             cg.ungetcpuregister(list,GetDefaultTmpReg);
             cg.ungetcpuregister(list,GetDefaultTmpReg);
+            cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
             if tcgsize2size[countregsize] = 1 then
             if tcgsize2size[countregsize] = 1 then
               list.concat(taicpu.op_reg(A_DEC,countreg))
               list.concat(taicpu.op_reg(A_DEC,countreg))
             else
             else

+ 4 - 0
compiler/avr/navradd.pas

@@ -135,6 +135,8 @@ interface
         var
         var
           i : byte;
           i : byte;
         begin
         begin
+          cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+
           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,tmpreg2));
           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,tmpreg2));
           for i:=2 to tcgsize2size[left.location.size] do
           for i:=2 to tcgsize2size[left.location.size] do
             begin
             begin
@@ -203,6 +205,8 @@ interface
               hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
               hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
           end;
           end;
 
 
+        cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+
         if (not unsigned) and
         if (not unsigned) and
           (right.location.loc=LOC_CONSTANT) and
           (right.location.loc=LOC_CONSTANT) and
           (right.location.value=0) and
           (right.location.value=0) and

+ 2 - 0
compiler/avr/navrmat.pas

@@ -103,12 +103,14 @@ implementation
               case left.location.loc of
               case left.location.loc of
                  LOC_FLAGS :
                  LOC_FLAGS :
                    begin
                    begin
+                     cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                      location_copy(location,left.location);
                      location_copy(location,left.location);
                      inverse_flags(location.resflags);
                      inverse_flags(location.resflags);
                    end;
                    end;
                  LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
                  LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
                  LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
                  LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
                    begin
                    begin
+                     cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
                      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,left.location.register));
                      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,left.location.register));
 
 

+ 27 - 4
compiler/avr/rgcpu.pas

@@ -95,19 +95,40 @@ unit rgcpu;
         helpins  : tai;
         helpins  : tai;
         tmpref   : treference;
         tmpref   : treference;
         helplist : TAsmList;
         helplist : TAsmList;
+        ofs      : asizeint;
       begin
       begin
         if (abs(spilltemp.offset)>63) or (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
         if (abs(spilltemp.offset)>63) or (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
           begin
           begin
             helplist:=TAsmList.create;
             helplist:=TAsmList.create;
 
 
-            helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
-            helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
-            helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
-            helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
+            helplist.concat(tai_regalloc.alloc(NR_R26,nil));
+            helplist.concat(tai_regalloc.alloc(NR_R27,nil));
+            helplist.concat(tai_marker.Create(mark_may_store_flags_with_r26));
+            if (CPUAVR_HAS_ADIW in cpu_capabilities[current_settings.cputype]) and (ofs>0) and (ofs<=126) then
+              begin
+                { this might be converted into movw }
+                helplist.concat(taicpu.op_reg_reg(A_MOV,NR_R26,spilltemp.base));
+                helplist.concat(taicpu.op_reg_reg(A_MOV,NR_R27,cg.GetNextReg(spilltemp.base)));
+                while ofs>0 do
+                  begin
+                    helplist.concat(taicpu.op_reg_const(A_ADIW,NR_R26,min(63,ofs)));
+                    dec(ofs,min(63,ofs));
+                  end;
+              end
+            else
+              begin
+                helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
+                helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
+                helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
+                helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
+              end;
 
 
             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
             helpins:=spilling_create_load(tmpref,tempreg);
             helpins:=spilling_create_load(tmpref,tempreg);
             helplist.concat(helpins);
             helplist.concat(helpins);
+            helplist.concat(tai_marker.Create(mark_may_restore_flags_with_r26));
+            helplist.concat(tai_regalloc.dealloc(NR_R26,nil));
+            helplist.concat(tai_regalloc.dealloc(NR_R27,nil));
             list.insertlistafter(pos,helplist);
             list.insertlistafter(pos,helplist);
             helplist.free;
             helplist.free;
           end
           end
@@ -129,6 +150,7 @@ unit rgcpu;
 
 
             helplist.concat(tai_regalloc.alloc(NR_R26,nil));
             helplist.concat(tai_regalloc.alloc(NR_R26,nil));
             helplist.concat(tai_regalloc.alloc(NR_R27,nil));
             helplist.concat(tai_regalloc.alloc(NR_R27,nil));
+            helplist.concat(tai_marker.Create(mark_may_store_flags_with_r26));
             if (CPUAVR_HAS_ADIW in cpu_capabilities[current_settings.cputype]) and (ofs>0) and (ofs<=126) then
             if (CPUAVR_HAS_ADIW in cpu_capabilities[current_settings.cputype]) and (ofs>0) and (ofs<=126) then
               begin
               begin
                 { this might be converted into movw }
                 { this might be converted into movw }
@@ -150,6 +172,7 @@ unit rgcpu;
 
 
             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
             helplist.concat(spilling_create_store(tempreg,tmpref));
             helplist.concat(spilling_create_store(tempreg,tmpref));
+            helplist.concat(tai_marker.Create(mark_may_restore_flags_with_r26));
             helplist.concat(tai_regalloc.dealloc(NR_R26,nil));
             helplist.concat(tai_regalloc.dealloc(NR_R26,nil));
             helplist.concat(tai_regalloc.dealloc(NR_R27,nil));
             helplist.concat(tai_regalloc.dealloc(NR_R27,nil));
             list.insertlistafter(pos,helplist);
             list.insertlistafter(pos,helplist);