]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/20288 (AVR assignment of a value through a 16 bit pointer generates...
authorMarek Michalkiewicz <marekm@amelek.gda.pl>
Sun, 13 Mar 2005 21:49:45 +0000 (22:49 +0100)
committerMarek Michalkiewicz <marekm@gcc.gnu.org>
Sun, 13 Mar 2005 21:49:45 +0000 (21:49 +0000)
PR target/20288
* config/avr/avr.c (print_operand): Add 'p' and 'r'.
(out_movhi_r_mr): Read low byte of volatile MEM first.
(out_movhi_mr_r): Write high byte of volatile MEM first.

From-SVN: r96394

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/config/avr/avr.md

index 9a50f151976d302f3ffd087e738381dabc6bdbe6..8a1c6423b23bdf1f8c2da1b450b470fe36b8b64a 100644 (file)
@@ -1,3 +1,10 @@
+2005-03-13  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+       PR target/20288
+       * config/avr/avr.c (print_operand): Add 'p' and 'r'.
+       (out_movhi_r_mr): Read low byte of volatile MEM first.
+       (out_movhi_mr_r): Write high byte of volatile MEM first.
+
 2005-03-10  Aldy Hernandez  <aldyh@redhat.com>
 
         * doc/invoke.texi: Add 8540 to list of cpus in rs6000 cpu section.
index ddd65d9fa5d712df47d14c6fcdaa1dd88b145c60..6b623daee8e6defd08590a756c715f2165d40786 100644 (file)
@@ -1099,6 +1099,16 @@ print_operand (FILE *file, rtx x, int code)
 
          print_operand (file, XEXP (addr, 1), 0);
        }
+      else if (code == 'p' || code == 'r')
+        {
+          if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
+            fatal_insn ("bad address, not post_inc or pre_dec:", addr);
+          
+          if (code == 'p')
+            print_operand_address (file, XEXP (addr, 0));  /* X, Y, Z */
+          else
+            print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
+        }
       else if (GET_CODE (addr) == PLUS)
        {
          print_operand_address (file, XEXP (addr,0));
@@ -1814,6 +1824,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
   rtx base = XEXP (src, 0);
   int reg_dest = true_regnum (dest);
   int reg_base = true_regnum (base);
+  /* "volatile" forces reading low byte first, even if less efficient,
+     for correct operation with 16-bit I/O registers.  */
+  int mem_volatile_p = MEM_VOLATILE_P (src);
   int tmp;
 
   if (!l)
@@ -1907,6 +1920,25 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
        fatal_insn ("incorrect insn:", insn);
 
+      if (mem_volatile_p)
+        {
+          if (REGNO (XEXP (base, 0)) == REG_X)
+            {
+              *l = 4;
+              return (AS2 (sbiw,r26,2)  CR_TAB
+                      AS2 (ld,%A0,X+)   CR_TAB
+                      AS2 (ld,%B0,X)    CR_TAB
+                      AS2 (sbiw,r26,1));
+            }
+          else
+            {
+              *l = 3;
+              return (AS2 (sbiw,%r1,2)   CR_TAB
+                      AS2 (ld,%A0,%p1)  CR_TAB
+                      AS2 (ldd,%B0,%p1+1));
+            }
+        }
+
       *l = 2;
       return (AS2 (ld,%B0,%1) CR_TAB
              AS2 (ld,%A0,%1));
@@ -2487,7 +2519,11 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
   rtx base = XEXP (dest, 0);
   int reg_base = true_regnum (base);
   int reg_src = true_regnum (src);
+  /* "volatile" forces writing high byte first, even if less efficient,
+     for correct operation with 16-bit I/O registers.  */
+  int mem_volatile_p = MEM_VOLATILE_P (dest);
   int tmp;
+
   if (!l)
     l = &tmp;
   if (CONSTANT_ADDRESS_P (base))
@@ -2507,33 +2543,33 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
         {
           if (reg_src == REG_X)
             {
-             /* "st X+,r26" is undefined */
-              if (reg_unused_after (insn, src))
+              /* "st X+,r26" and "st -X,r26" are undefined.  */
+              if (!mem_volatile_p && reg_unused_after (insn, src))
                return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
                              AS2 (st,X,r26)            CR_TAB
                              AS2 (adiw,r26,1)          CR_TAB
                              AS2 (st,X,__tmp_reg__));
               else
                return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
-                             AS2 (st,X,r26)            CR_TAB
                              AS2 (adiw,r26,1)          CR_TAB
                              AS2 (st,X,__tmp_reg__)    CR_TAB
-                             AS2 (sbiw,r26,1));
+                              AS2 (sbiw,r26,1)          CR_TAB
+                              AS2 (st,X,r26));
             }
           else
             {
-              if (reg_unused_after (insn, base))
+              if (!mem_volatile_p && reg_unused_after (insn, base))
                 return *l=2, (AS2 (st,X+,%A1) CR_TAB
                               AS2 (st,X,%B1));
               else
-                return *l=3, (AS2 (st  ,X+,%A1) CR_TAB
-                              AS2 (st  ,X,%B1) CR_TAB
-                              AS2 (sbiw,r26,1));
+                return *l=3, (AS2 (adiw,r26,1) CR_TAB
+                              AS2 (st,X,%B1)   CR_TAB
+                              AS2 (st,-X,%A1));
             }
         }
       else
-        return  *l=2, (AS2 (st ,%0,%A1)    CR_TAB
-                       AS2 (std,%0+1,%B1));
+        return  *l=2, (AS2 (std,%0+1,%B1) CR_TAB
+                       AS2 (st,%0,%A1));
     }
   else if (GET_CODE (base) == PLUS)
     {
@@ -2546,14 +2582,14 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
            return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
-                           AS2 (std,Y+62,%A1)    CR_TAB
                            AS2 (std,Y+63,%B1)    CR_TAB
+                           AS2 (std,Y+62,%A1)    CR_TAB
                            AS2 (sbiw,r28,%o0-62));
 
          return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
                          AS2 (sbci,r29,hi8(-%o0)) CR_TAB
-                         AS2 (st,Y,%A1)           CR_TAB
                          AS2 (std,Y+1,%B1)        CR_TAB
+                         AS2 (st,Y,%A1)           CR_TAB
                          AS2 (subi,r28,lo8(%o0))  CR_TAB
                          AS2 (sbci,r29,hi8(%o0)));
        }
@@ -2561,31 +2597,53 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
        {
          /* (X + d) = R */
          if (reg_src == REG_X)
-           {
+            {
              *l = 7;
              return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
                      AS2 (mov,__zero_reg__,r27) CR_TAB
-                     AS2 (adiw,r26,%o0)         CR_TAB
-                     AS2 (st,X+,__tmp_reg__)    CR_TAB
+                      AS2 (adiw,r26,%o0+1)       CR_TAB
                      AS2 (st,X,__zero_reg__)    CR_TAB
+                     AS2 (st,-X,__tmp_reg__)    CR_TAB
                      AS1 (clr,__zero_reg__)     CR_TAB
-                     AS2 (sbiw,r26,%o0+1));
+                      AS2 (sbiw,r26,%o0));
            }
          *l = 4;
-         return (AS2 (adiw,r26,%o0) CR_TAB
-                 AS2 (st,X+,%A1)    CR_TAB
-                 AS2 (st,X,%B1)     CR_TAB
-                 AS2 (sbiw,r26,%o0+1));
+          return (AS2 (adiw,r26,%o0+1) CR_TAB
+                  AS2 (st,X,%B1)       CR_TAB
+                  AS2 (st,-X,%A1)      CR_TAB
+                  AS2 (sbiw,r26,%o0));
        }
-      return *l=2, (AS2 (std,%A0,%A1)    CR_TAB
-                   AS2 (std,%B0,%B1));
+      return *l=2, (AS2 (std,%B0,%B1)    CR_TAB
+                    AS2 (std,%A0,%A1));
     }
   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
     return *l=2, (AS2 (st,%0,%B1) CR_TAB
                  AS2 (st,%0,%A1));
   else if (GET_CODE (base) == POST_INC) /* (R++) */
-    return *l=2, (AS2 (st,%0,%A1)  CR_TAB
-                 AS2 (st,%0,%B1));
+    {
+      if (mem_volatile_p)
+        {
+          if (REGNO (XEXP (base, 0)) == REG_X)
+            {
+              *l = 4;
+              return (AS2 (adiw,r26,1)  CR_TAB
+                      AS2 (st,X,%B1)    CR_TAB
+                      AS2 (st,-X,%A1)   CR_TAB
+                      AS2 (adiw,r26,2));
+            }
+          else
+            {
+              *l = 3;
+              return (AS2 (std,%p0+1,%B1) CR_TAB
+                      AS2 (st,%p0,%A1)    CR_TAB
+                      AS2 (adiw,%r0,2));
+            }
+        }
+
+      *l = 2;
+      return (AS2 (st,%0,%A1)  CR_TAB
+            AS2 (st,%0,%B1));
+    }
   fatal_insn ("unknown move insn:",insn);
   return "";
 }
index 7823545b9da6b8832261be8cc912e9df268bf7d8..aadbaf6ed4ea2d9bb40159b34ba136e305bf907c 100644 (file)
@@ -30,6 +30,8 @@
 ;;  j  Branch condition.
 ;;  k  Reverse branch condition.
 ;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
+;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z)
+;;  r  POST_INC or PRE_DEC address as a register (r26, r28, r30)
 ;;  ~  Output 'r' if not AVR_MEGA.
 
 ;; UNSPEC usage: