avr.c (avr_legitimize_address): Force constant addresses outside [0,0xc0] into a...
authorGeorg-Johann Lay <avr@gjlay.de>
Wed, 20 Jul 2016 14:46:57 +0000 (14:46 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Wed, 20 Jul 2016 14:46:57 +0000 (14:46 +0000)
gcc/
* gcc/config/avr.c (avr_legitimize_address) [AVR_TINY]: Force
constant addresses outside [0,0xc0] into a register.
(avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn.  And handle
cases where the base address register is unused after.
(avr_out_movhi_r_mr_reg_disp_tiny): Same.
(avr_out_movhi_mr_r_reg_disp_tiny): Same.
(avr_out_store_psi_reg_disp_tiny): Same.

gcc/testsuite/
* gcc.target/avr/torture/get-mem.c: New test.
* gcc.target/avr/torture/set-mem.c: New test.

From-SVN: r238528

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/avr/torture/get-mem.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/set-mem.c [new file with mode: 0644]

index 167c46a1ca2d3792f3b4b3c962dbe279400780eb..36c13358443fb343d7bc046b63be298ab6518560 100644 (file)
@@ -1,3 +1,13 @@
+2016-07-20  Georg-Johann Lay  <avr@gjlay.de>
+
+       * gcc/config/avr.c (avr_legitimize_address) [AVR_TINY]: Force
+       constant addresses outside [0,0xc0] into a register.
+       (avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn.  And handle
+       cases where the base address register is unused after.
+       (avr_out_movhi_r_mr_reg_disp_tiny): Same.
+       (avr_out_movhi_mr_r_reg_disp_tiny): Same.
+       (avr_out_store_psi_reg_disp_tiny): Same.
+
 2016-07-20  Georg-Johann Lay  <avr@gjlay.de>
 
        Implement attribute progmem on reduced Tiny cores by adding
index 95f691c7ac749361d2225d2c425d31003d86a143..8beda9f110345675918da645b3d406c829731d17 100644 (file)
@@ -1926,6 +1926,16 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
 
   x = oldx;
 
+  if (AVR_TINY)
+    {
+      if (CONSTANT_ADDRESS_P (x)
+          && !(CONST_INT_P (x)
+               && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode))))
+        {
+          x = force_reg (Pmode, x);
+        }
+    }
+
   if (GET_CODE (oldx) == PLUS
       && REG_P (XEXP (oldx, 0)))
     {
@@ -3537,7 +3547,7 @@ out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
 
 static const char*
-avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -3551,17 +3561,20 @@ avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
                        "ld %B0,%1"          CR_TAB
                        "mov %A0,__tmp_reg__", op, plen, -3);
 
-  return avr_asm_len ("ld %A0,%1"             CR_TAB
-                      TINY_ADIW (%E1, %F1, 1) CR_TAB
-                      "ld %B0,%1"             CR_TAB
-                      TINY_SBIW (%E1, %F1, 1), op, plen, -6);
+  avr_asm_len ("ld %A0,%1+"                  CR_TAB
+               "ld %B0,%1", op, plen, -2);
+
+  if (!reg_unused_after (insn, base))
+    avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
+
+  return "";
 }
 
 
 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
 
 static const char*
-avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -3579,10 +3592,14 @@ avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
     }
   else
     {
-      return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-                          "ld %A0,%b1+"             CR_TAB
-                          "ld %B0,%b1"              CR_TAB
-                          TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
+      avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+                   "ld %A0,%b1+"             CR_TAB
+                   "ld %B0,%b1", op, plen, -4);
+
+      if (!reg_unused_after (insn, XEXP (base, 0)))
+        avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
+
+      return "";
     }
 }
 
@@ -3630,7 +3647,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
   if (reg_base > 0)
     {
       if (AVR_TINY)
-        return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
+        return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
 
       if (reg_dest == reg_base)         /* R = (R) */
         return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
@@ -3655,7 +3672,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
       int reg_base = true_regnum (XEXP (base, 0));
 
       if (AVR_TINY)
-        return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
+        return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
 
       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
         {
@@ -4404,8 +4421,8 @@ avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
                   "ld %B0,%1+"  CR_TAB
                   "ld %C0,%1", op, plen, -3);
 
-      if (reg_dest != reg_base - 2 &&
-          !reg_unused_after (insn, base))
+      if (reg_dest != reg_base - 2
+          && !reg_unused_after (insn, base))
         {
           avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
         }
@@ -4435,13 +4452,13 @@ avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
   else
     {
       avr_asm_len (TINY_ADIW (%I1, %J1, %o1)   CR_TAB
-                          "ld %A0,%b1+"              CR_TAB
-                          "ld %B0,%b1+"              CR_TAB
-                          "ld %C0,%b1", op, plen, -5);
+                   "ld %A0,%b1+"               CR_TAB
+                   "ld %B0,%b1+"               CR_TAB
+                   "ld %C0,%b1", op, plen, -5);
 
-      if (reg_dest != (reg_base - 2)
+      if (reg_dest != reg_base - 2
           && !reg_unused_after (insn, XEXP (base, 0)))
-          avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
+        avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
 
       return "";
     }
@@ -4626,7 +4643,7 @@ avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
 }
 
 static const char*
-avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
+avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -4635,31 +4652,29 @@ avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
   int reg_src = true_regnum (src);
 
   if (reg_src == reg_base)
-    {
-      return avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
-                          "mov __zero_reg__,%B1"         CR_TAB
-                          TINY_ADIW (%I0, %J0, %o0)      CR_TAB
-                          "st %b0+,__tmp_reg__"          CR_TAB
-                          "st %b0+,__zero_reg__"         CR_TAB
-                          "st %b0,%C1"                   CR_TAB
-                          "clr __zero_reg__"             CR_TAB
-                          TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
-    }
+    avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
+                 "mov __zero_reg__,%B1"         CR_TAB
+                 TINY_ADIW (%I0, %J0, %o0)      CR_TAB
+                 "st %b0+,__tmp_reg__"          CR_TAB
+                 "st %b0+,__zero_reg__"         CR_TAB
+                 "st %b0,%C1"                   CR_TAB
+                 "clr __zero_reg__", op, plen, -8);
   else if (reg_src == reg_base - 2)
-    {
-      return avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB
-                          TINY_ADIW (%I0, %J0, %o0)      CR_TAB
-                          "st %b0+,%A1"                  CR_TAB
-                          "st %b0+,%B1"                  CR_TAB
-                          "st %b0,__tmp_reg__"           CR_TAB
-                          TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8);
-    }
+    avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB
+                 TINY_ADIW (%I0, %J0, %o0)      CR_TAB
+                 "st %b0+,%A1"                  CR_TAB
+                 "st %b0+,%B1"                  CR_TAB
+                 "st %b0,__tmp_reg__", op, plen, -6);
+  else
+    avr_asm_len (TINY_ADIW (%I0, %J0, %o0)      CR_TAB
+                 "st %b0+,%A1"                  CR_TAB
+                 "st %b0+,%B1"                  CR_TAB
+                 "st %b0,%C1", op, plen, -5);
 
-  return avr_asm_len (TINY_ADIW (%I0, %J0, %o0)      CR_TAB
-                          "st %b0+,%A1"                  CR_TAB
-                          "st %b0+,%B1"                  CR_TAB
-                          "st %b0,%C1"                   CR_TAB
-                          TINY_SBIW (%I0, %J0, %o0+2), op, plen, -7);
+  if (!reg_unused_after (insn, XEXP (base, 0)))
+    avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
+
+  return "";
 }
 
 /* Handle store of 24-bit type from register or zero to memory.  */
@@ -4708,7 +4723,7 @@ avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
       int disp = INTVAL (XEXP (base, 1));
 
       if (AVR_TINY)
-        return avr_out_store_psi_reg_disp_tiny (op, plen);
+        return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
 
       reg_base = REGNO (XEXP (base, 0));
 
@@ -4842,7 +4857,7 @@ avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
     else
     {
       avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
-          "st %b0,%1" , op, plen, -3);
+                   "st %b0,%1", op, plen, -3);
     }
 
   if (!reg_unused_after (insn, XEXP (x,0)))
@@ -5066,7 +5081,7 @@ avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 }
 
 static const char*
-avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -5074,19 +5089,22 @@ avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
   int reg_base = REGNO (XEXP (base, 0));
   int reg_src = true_regnum (src);
 
-  return reg_src == reg_base
-        ? avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
-                       "mov __zero_reg__,%B1"         CR_TAB
-                       TINY_ADIW (%I0, %J0, %o0+1)    CR_TAB
-                       "st %b0,__zero_reg__"          CR_TAB
-                       "st -%b0,__tmp_reg__"          CR_TAB
-                       "clr __zero_reg__"             CR_TAB
-                       TINY_SBIW (%I0, %J0, %o0), op, plen, -9)
+  if (reg_src == reg_base)
+    avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
+                 "mov __zero_reg__,%B1"         CR_TAB
+                 TINY_ADIW (%I0, %J0, %o0+1)    CR_TAB
+                 "st %b0,__zero_reg__"          CR_TAB
+                 "st -%b0,__tmp_reg__"          CR_TAB
+                 "clr __zero_reg__", op, plen, -7);
+  else
+    avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
+                 "st %b0,%B1"                CR_TAB
+                 "st -%b0,%A1", op, plen, -4);
+
+  if (!reg_unused_after (insn, XEXP (base, 0)))
+    avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
 
-        : avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
-                       "st %b0,%B1"                CR_TAB
-                       "st -%b0,%A1"               CR_TAB
-                       TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
+  return "";
 }
 
 static const char*
@@ -5163,7 +5181,7 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
       int disp = INTVAL (XEXP (base, 1));
 
       if (AVR_TINY)
-        return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
+        return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
 
       reg_base = REGNO (XEXP (base, 0));
       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
index 952513711ca16d41c06899ef4d1deeb1d4380dc6..7e801c00a448993da9068bdc4ea9910dedeaf1d1 100644 (file)
@@ -1,3 +1,8 @@
+2016-07-20  Georg-Johann Lay  <avr@gjlay.de>
+
+       * gcc.target/avr/torture/get-mem.c: New test.
+       * gcc.target/avr/torture/set-mem.c: New test.
+
 2016-07-20  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/71948
diff --git a/gcc/testsuite/gcc.target/avr/torture/get-mem.c b/gcc/testsuite/gcc.target/avr/torture/get-mem.c
new file mode 100644 (file)
index 0000000..46f47f1
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+#define NI __attribute__((noinline, noclone))
+
+typedef __INT8_TYPE__ s8;
+typedef __INT16_TYPE__ s16;
+typedef __int24 s24;
+typedef __INT32_TYPE__ s32;
+
+static const s8 arr8[] = { 12, 23, 34 };
+static const s16 arr16[] = { 123, 234, 345 };
+static const s24 arr24[] = { 1234, 2345, 3456 };
+static const s32 arr32[] = { 12345, 23456, 34567 };
+
+NI s8  add8  (const s8  *p) { return p[0] + p[1] + p[2]; }
+NI s16 add16 (const s16 *p) { return p[0] + p[1] + p[2]; }
+NI s24 add24 (const s24 *p) { return p[0] + p[1] + p[2]; }
+NI s32 add32 (const s32 *p) { return p[0] + p[1] + p[2]; }
+
+void test8 (void)
+{
+  if (add8 (arr8) != arr8[0] + arr8[1] + arr8[2])
+    __builtin_abort();
+}
+
+void test16 (void)
+{
+  if (add16 (arr16) != arr16[0] + arr16[1] + arr16[2])
+    __builtin_abort();
+}
+
+void test24 (void)
+{
+  if (add24 (arr24) != arr24[0] + arr24[1] + arr24[2])
+    __builtin_abort();
+}
+
+void test32 (void)
+{
+  if (add32 (arr32) != arr32[0] + arr32[1] + arr32[2])
+    __builtin_abort();
+}
+
+int main (void)
+{
+  test8();
+  test16();
+  test24();
+  test32();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/torture/set-mem.c b/gcc/testsuite/gcc.target/avr/torture/set-mem.c
new file mode 100644 (file)
index 0000000..60ded19
--- /dev/null
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+
+#define NI __attribute__((noinline, noclone))
+
+typedef __INT8_TYPE__ s8;
+typedef __INT16_TYPE__ s16;
+typedef __int24 s24;
+typedef __INT32_TYPE__ s32;
+
+static s8 arr8[3];
+static s16 arr16[3];
+static s24 arr24[3];
+static s32 arr32[3];
+
+NI void set8  (s8  *p) { p[0] = -123; p[1]  = -23; p[2]  = -34; }
+NI void set16 (s16 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
+NI void set24 (s24 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
+NI void set32 (s32 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
+
+void test8 (void)
+{
+  set8 (arr8);
+  if (arr8[0] != -123 || arr8[1] != -23 || arr8[2] != -34)
+    __builtin_abort();
+}
+
+void test16 (void)
+{
+  set16 (arr16);
+  if (arr16[0] != -123 || arr16[1] != -234 || arr16[2] != -345)
+    __builtin_abort();
+}
+
+void test24 (void)
+{
+  set24 (arr24);
+  if (arr24[0] != -123 || arr24[1] != -234 || arr24[2] != -345)
+    __builtin_abort();
+}
+
+void test32 (void)
+{
+  set32 (arr32);
+  if (arr32[0] != -123 || arr32[1] != -234 || arr32[2] != -345)
+    __builtin_abort();
+}
+
+int main (void)
+{
+  test8();
+  test16();
+  test24();
+  test32();
+  return 0;
+}