View Issue Details

IDProjectCategoryView StatusLast Update
0038958FPCCompilerpublic2021-06-04 05:38
ReporterChristo Crause Assigned ToFlorian  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version3.3.1 
Fixed in Version3.3.1 
Summary0038958: AVR [patch] Invalid code generated for avrtiny
DescriptionWhen assigning a local 16 bit value to a 16 bit IO register the compiler generates an LDD instruction which is not supported on this subarch. When the example below is compiled, the following instructions are generated for the assignment:

# [7] OCR0A := x;
    ldi r30,lo8(2)
    ldi r31,hi8(2)
    add r30,r28
    adc r31,r29
    ldd r16,Z+1 <<<< Invalid instruction for avrtiny
    out 39,r16
    ld r16,Z+
    out 38,r16

The attached patch fix the code generation sequence to only use the LD instruction.
Steps To Reproduceprogram test16bitreg;

procedure t;
var x: word;
begin
  OCR0A := x;
end;

begin
  t;
end.
TagsNo tags attached.
Fixed in Revision49473
FPCOldBugId
FPCTarget-
Attached Files

Activities

Christo Crause

2021-06-03 16:49

reporter  

avrtiny.patch (4,931 bytes)   
Index: compiler/avr/cgcpu.pas
===================================================================
--- compiler/avr/cgcpu.pas	(revision 49466)
+++ compiler/avr/cgcpu.pas	(working copy)
@@ -120,6 +120,7 @@
         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,7 +1085,15 @@
           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
         tmpref : treference;
@@ -1372,8 +1381,7 @@
              // 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 @@
               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 @@
                   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 @@
                     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);
avrtiny.patch (4,931 bytes)   

Florian

2021-06-03 18:49

administrator   ~0131141

Thanks, applied.

Christo Crause

2021-06-04 05:38

reporter   ~0131144

Thanks!

Issue History

Date Modified Username Field Change
2021-06-03 16:49 Christo Crause New Issue
2021-06-03 16:49 Christo Crause File Added: avrtiny.patch
2021-06-03 18:49 Florian Assigned To => Florian
2021-06-03 18:49 Florian Status new => resolved
2021-06-03 18:49 Florian Resolution open => fixed
2021-06-03 18:49 Florian Fixed in Version => 3.3.1
2021-06-03 18:49 Florian Fixed in Revision => 49473
2021-06-03 18:49 Florian FPCTarget => -
2021-06-03 18:49 Florian Note Added: 0131141
2021-06-04 05:38 Christo Crause Status resolved => closed
2021-06-04 05:38 Christo Crause Note Added: 0131144