ソースを参照

* patch by Christo Crause: do not generate LDD for avrtiny, resolves #38958

git-svn-id: trunk@49473 -
florian 4 年 前
コミット
9d6ceda532
1 ファイル変更32 行追加11 行削除
  1. 32 11
      compiler/avr/cgcpu.pas

+ 32 - 11
compiler/avr/cgcpu.pas

@@ -120,6 +120,7 @@ unit cgcpu;
         procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
         procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
         procedure maybegetcpuregister(list : tasmlist; reg : tregister);
+        function addr_is_io_register(const addr: integer): boolean;
       end;
 
       tcg64favr = class(tcg64f32)
@@ -1084,6 +1085,14 @@ unit cgcpu;
           getcpuregister(list,reg);
       end;
 
+    { Returns true if dataspace address falls in I/O register range }
+    function tcgavr.addr_is_io_register(const addr: integer): boolean;
+    begin
+      result := (not(current_settings.cputype in [cpu_avrxmega3,cpu_avrtiny]) and (addr>31)) or
+                ((current_settings.cputype in [cpu_avrxmega3,cpu_avrtiny]) and (addr>=0)) and
+                (addr<cpuinfo.embedded_controllers[current_settings.controllertype].srambase);
+    end;
+
 
     function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
       var
@@ -1372,8 +1381,7 @@ unit cgcpu;
              // Avrxmega3: write low byte first then high byte
              // See e.g. megaAVR-0 family data sheet 7.5.6 Accessing 16-bit registers
              if (current_settings.cputype <> cpu_avrxmega3) and
-               (fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31) and
-               (href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
+               (fromsize in [OS_16, OS_S16]) and QuickRef and addr_is_io_register(href.offset) then
                begin
                  tmpreg:=GetNextReg(reg);
                  href.addressmode:=AM_UNCHANGED;
@@ -2601,16 +2609,14 @@ unit cgcpu;
               end;
 
               // CC
-              // If dest is an ioreg (31 < offset < srambase) and size = 16 bit then
+              // If dest is an ioreg and size = 16 bit then
               // write high byte first, then low byte
               // but not for avrxmega3
               if (len = 2) and DestQuickRef and (current_settings.cputype <> cpu_avrxmega3) and
-                (dest.offset > 31) and
-                (dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
+                  addr_is_io_register(dest.offset) then
                 begin
                   // If src is also a 16 bit ioreg then read low byte then high byte
-                  if SrcQuickRef and (srcref.offset > 31)
-                    and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
+                  if SrcQuickRef and addr_is_io_register(srcref.offset) then
                     begin
                       // First read source into temp registers
                       tmpreg:=getintregister(list, OS_16);
@@ -2627,8 +2633,20 @@ unit cgcpu;
                   end
                 else
                   begin
-                    srcref.addressmode:=AM_UNCHANGED;
-                    inc(srcref.offset);
+                    { avrtiny doesn't have LDD instruction, so use
+                      predecrement version of LD with pre-incremented pointer  }
+                    if current_settings.cputype = cpu_avrtiny then
+                      begin
+                        srcref.addressmode:=AM_PREDRECEMENT;
+                        list.concat(taicpu.op_reg_const(A_SUBI,srcref.base,-2));
+                        list.concat(taicpu.op_reg_const(A_SBCI,GetNextReg(srcref.base),$FF));
+                      end
+                    else
+                      begin
+                        srcref.addressmode:=AM_UNCHANGED;
+                        inc(srcref.offset);
+                      end;
+
                     dstref.addressmode:=AM_UNCHANGED;
                     inc(dstref.offset);
 
@@ -2637,12 +2655,15 @@ unit cgcpu;
                     list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
                     cg.ungetcpuregister(list,GetDefaultTmpReg);
 
-                    if not(SrcQuickRef) then
+                    if not(SrcQuickRef) and (current_settings.cputype <> cpu_avrtiny) then
                       srcref.addressmode:=AM_POSTINCREMENT
+                    else if current_settings.cputype = cpu_avrtiny then
+                      srcref.addressmode:=AM_PREDRECEMENT
                     else
                       srcref.addressmode:=AM_UNCHANGED;
 
-                    dec(srcref.offset);
+                    if current_settings.cputype <> cpu_avrtiny then
+                      dec(srcref.offset);
                     dec(dstref.offset);
 
                     cg.getcpuregister(list,GetDefaultTmpReg);