nios2.h (SMALL_INT12): New macro.
authorSandra Loosemore <sandra@codesourcery.com>
Tue, 14 Jul 2015 22:34:23 +0000 (18:34 -0400)
committerSandra Loosemore <sandra@gcc.gnu.org>
Tue, 14 Jul 2015 22:34:23 +0000 (18:34 -0400)
2015-07-14  Sandra Loosemore  <sandra@codesourcery.com>
    Cesar Philippidis  <cesar@codesourcery.com>
    Chung-Lin Tang  <cltang@codesourcery.com>

gcc/
* config/nios2/nios2.h (SMALL_INT12): New macro.
* config/nios2/nios2.c (nios2_valid_addr_offset_p): New function.
(nios2_valid_addr_expr_p): Use it.
(nios2_symbol_ref_in_small_data_p): Disallow GP-relative addressing
with implicit "io" instructions on R2.
* config/nios2/constraints.md (w): New constraint.
* config/nios2/predicates.md (ldstio_memory_operand): New.
* config/nios2/nios2.md (ld<bhw_uns>io, ld<bh>io): Update memory
operand predicate and constraint.
(ld<bh>io_signed, st<bhw>io>): Likewise.
* doc/md.texi (Machine Constraints): Document w constraint.

gcc/testsuite/
* gcc.target/nios2/r2-io-range.c: New.
* gcc.target/nios2/r2-stio-1.c: New.
* gcc.target/nios2/r2-stio-2.c: New.
* gcc.target/nios2/nios2-ldxio.c: New.
* gcc.target/nios2/nios2-stxio.c: Change to assemble test instead
of just compile.  Add more tests.

Co-Authored-By: Cesar Philippidis <cesar@codesourcery.com>
Co-Authored-By: Chung-Lin Tang <cltang@codesourcery.com>
From-SVN: r225792

13 files changed:
gcc/ChangeLog
gcc/config/nios2/constraints.md
gcc/config/nios2/nios2.c
gcc/config/nios2/nios2.h
gcc/config/nios2/nios2.md
gcc/config/nios2/predicates.md
gcc/doc/md.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/nios2/nios2-ldxio.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/nios2-stxio.c
gcc/testsuite/gcc.target/nios2/r2-io-range.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/r2-stio-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/r2-stio-2.c [new file with mode: 0644]

index b6026ba64ec35b7b863048ae788916327d9d7e6b..80b38cdb51ef369d7eaed9f826c1268ec04a25b0 100644 (file)
@@ -1,3 +1,19 @@
+2015-07-14  Sandra Loosemore  <sandra@codesourcery.com>
+           Cesar Philippidis  <cesar@codesourcery.com>
+           Chung-Lin Tang  <cltang@codesourcery.com>
+
+       * config/nios2/nios2.h (SMALL_INT12): New macro.
+       * config/nios2/nios2.c (nios2_valid_addr_offset_p): New function.
+       (nios2_valid_addr_expr_p): Use it.
+       (nios2_symbol_ref_in_small_data_p): Disallow GP-relative addressing
+       with implicit "io" instructions on R2.
+       * config/nios2/constraints.md (w): New constraint.
+       * config/nios2/predicates.md (ldstio_memory_operand): New.
+       * config/nios2/nios2.md (ld<bhw_uns>io, ld<bh>io): Update memory
+       operand predicate and constraint.
+       (ld<bh>io_signed, st<bhw>io>): Likewise.
+       * doc/md.texi (Machine Constraints): Document w constraint.
+
 2015-07-14  Sandra Loosemore  <sandra@codesourcery.com>
            Cesar Philippidis  <cesar@codesourcery.com>
            Chung-Lin Tang  <cltang@codesourcery.com>
index b67e87d3b3c85af7285ba6dcc416ea16a0e580e0..7c7afdfb11506785147074d0953692659a741d12 100644 (file)
 ;;  N: 0 to 255 (for custom instruction numbers)
 ;;  O: 0 to 31 (for control register numbers)
 ;;
+;; We use the following constraint letters for memory constraints
+;;
+;;  w: memory operands for load/store IO and cache instructions
+;;
 ;; We use the following built-in register classes:
 ;;
 ;;  r: general purpose register (r0..r31)
@@ -89,3 +93,7 @@
 (define_constraint "T"
   "A constant unspec offset representing a relocation."
   (match_test "nios2_unspec_reloc_p (op)"))
+
+(define_memory_constraint "w"
+  "A memory operand suitable for load/store IO and cache instructions."
+  (match_operand 0 "ldstio_memory_operand"))
index 7c97a02b521094a2f748e760b69045e27ed8a5af..93e0a869f32de2466d74401d64ca97f8699a3e4c 100644 (file)
@@ -1627,6 +1627,21 @@ nios2_regno_ok_for_base_p (int regno, bool strict_p)
          || regno == ARG_POINTER_REGNUM);
 }
 
+/* Return true if OFFSET is permitted in a load/store address expression.
+   Normally any 16-bit value is permitted, but on R2 if we may be emitting
+   the IO forms of these instructions we must restrict the offset to fit
+   in a 12-bit field instead.  */
+
+static bool
+nios2_valid_addr_offset_p (rtx offset)
+{
+  return (CONST_INT_P (offset)
+         && ((TARGET_ARCH_R2 && (TARGET_BYPASS_CACHE
+                                 || TARGET_BYPASS_CACHE_VOLATILE))
+             ? SMALL_INT12 (INTVAL (offset))
+             : SMALL_INT (INTVAL (offset))));
+}
+
 /* Return true if the address expression formed by BASE + OFFSET is
    valid.  */
 static bool
@@ -1637,7 +1652,7 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
   return (REG_P (base)
          && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
          && (offset == NULL_RTX
-             || const_arith_operand (offset, Pmode)
+             || nios2_valid_addr_offset_p (offset)
              || nios2_unspec_reloc_p (offset)));
 }
 
@@ -1739,6 +1754,13 @@ nios2_symbol_ref_in_small_data_p (rtx sym)
   if (SYMBOL_REF_TLS_MODEL (sym) != 0)
     return false;
 
+  /* On Nios II R2, there is no GP-relative relocation that can be
+     used with "io" instructions.  So, if we are implicitly generating
+     those instructions, we cannot emit GP-relative accesses.  */
+  if (TARGET_ARCH_R2
+      && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
+    return false;
+
   /* If the user has explicitly placed the symbol in a small data section
      via an attribute, generate gp-relative addressing even if the symbol
      is external, weak, or larger than we'd automatically put in the
index c3c958a083d8e0fe91814a1cca028f38892808d8..58afaec69ce10186da166b89d23ee5015d730a57 100644 (file)
@@ -216,6 +216,7 @@ enum reg_class
 /* Tests for various kinds of constants used in the Nios II port.  */
 
 #define SMALL_INT(X) ((unsigned HOST_WIDE_INT)(X) + 0x8000 < 0x10000)
+#define SMALL_INT12(X) ((unsigned HOST_WIDE_INT)(X) + 0x800 < 0x1000)
 #define SMALL_INT_UNSIGNED(X) ((X) >= 0 && (X) < 0x10000)
 #define UPPER16_INT(X) (((X) & 0xffff) == 0)
 #define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
index 70977802009261210d33b9e2858ebd7825f57237..8cf2347e05cc851e58073638bac3b3effb649383 100644 (file)
 (define_insn "ld<bhw_uns>io"
   [(set (match_operand:BHW 0 "register_operand" "=r")
         (unspec_volatile:BHW
-          [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
+          [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
   ""
   "ld<bhw_uns>io\\t%0, %1"
   [(set_attr "type" "ld")])
 
 (define_expand "ld<bh>io"
   [(set (match_operand:BH 0 "register_operand" "=r")
-        (match_operand:BH 1 "memory_operand"    "m"))]
+        (match_operand:BH 1 "ldstio_memory_operand" "w"))]
   ""
 {
   rtx tmp = gen_reg_rtx (SImode);
   [(set (match_operand:SI 0 "register_operand" "=r")
         (sign_extend:SI
           (unspec_volatile:BH
-            [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
+            [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
   ""
   "ld<bh>io\\t%0, %1"
   [(set_attr "type" "ld")])
 
 (define_insn "st<bhw>io"
-  [(set (match_operand:BHW 0 "memory_operand" "=m")
+  [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
         (unspec_volatile:BHW
           [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
   ""
index 37cecf774f29a235b0e1dc2220a677b28f6e9314..fa578035ccad3373a3f6702b855532f6d46f8c85 100644 (file)
                                          &XEXP (op, 0), &XEXP (op, 1),
                                          false));
 })
+
+(define_predicate "ldstio_memory_operand"
+  (match_code "mem")
+{
+  if (TARGET_ARCH_R2)
+    {
+      rtx addr = XEXP (op, 0);
+      if (REG_P (addr))
+        return true;
+      else if (GET_CODE (addr) == PLUS)
+        return (REG_P (XEXP (addr, 0))
+                && CONST_INT_P (XEXP (addr, 1))
+                && SMALL_INT12 (INTVAL (XEXP (addr, 1))));
+      return false;
+    }
+  return memory_operand (op, mode);
+})
index e991286afcc6e8d464815800e002cf18b7ab2896..84c39a853e9adf39e2e85b55333188fb1b76cd9d 100644 (file)
@@ -2996,6 +2996,10 @@ Matches immediates which are addresses in the small
 data section and therefore can be added to @code{gp}
 as a 16-bit immediate to re-create their 32-bit value.
 
+@item w
+A memory operand suitable for load/store IO and cache
+instructions.
+
 @ifset INTERNALS
 @item T
 A @code{const} wrapped @code{UNSPEC} expression,
index 801e46285a91795ded888e255fc80c0a3a99ed4b..6dd4feb719d75b52ec9c13cd03de2b1d5d2bef0d 100644 (file)
@@ -1,3 +1,14 @@
+2015-07-14  Sandra Loosemore  <sandra@codesourcery.com>
+           Cesar Philippidis  <cesar@codesourcery.com>
+           Chung-Lin Tang  <cltang@codesourcery.com>
+
+       * gcc.target/nios2/r2-io-range.c: New.
+       * gcc.target/nios2/r2-stio-1.c: New.
+       * gcc.target/nios2/r2-stio-2.c: New.
+       * gcc.target/nios2/nios2-ldxio.c: New.
+       * gcc.target/nios2/nios2-stxio.c: Change to assemble test instead
+       of just compile.  Add more tests.
+
 2015-07-14  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        gfortran.dg/pr66864.f90: New test.
diff --git a/gcc/testsuite/gcc.target/nios2/nios2-ldxio.c b/gcc/testsuite/gcc.target/nios2/nios2-ldxio.c
new file mode 100644 (file)
index 0000000..ac661a0
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do assemble } */
+/* { dg-options "-O" } */
+
+void test_ldbio (unsigned char* p1, unsigned char* p2)
+{
+  __builtin_ldbio (p1);
+  __builtin_ldbio (p2);
+  __builtin_ldbio (p2 + 1);
+  __builtin_ldbio (p2 + 2);
+  __builtin_ldbio (p2 + 2047);
+  __builtin_ldbio (p2 + 2048);
+}
+
+void test_ldbuio (unsigned char* p1, unsigned char* p2)
+{
+  __builtin_ldbuio (p1);
+  __builtin_ldbuio (p2);
+  __builtin_ldbuio (p2 + 1);
+  __builtin_ldbuio (p2 + 2);
+  __builtin_ldbuio (p2 + 2047);
+  __builtin_ldbuio (p2 + 2048);
+}
+
+void test_ldhio (unsigned short* p1, unsigned short* p2)
+{
+  __builtin_ldhio (p1);
+  __builtin_ldhio (p2);
+  __builtin_ldhio (p2 + 1);
+  __builtin_ldhio (p2 + 2);
+  __builtin_ldhio (p2 + 1023);
+  __builtin_ldhio (p2 + 1024);
+}
+
+void test_ldhuio (unsigned short* p1, unsigned short* p2)
+{
+  __builtin_ldhuio (p1);
+  __builtin_ldhuio (p2);
+  __builtin_ldhuio (p2 + 1);
+  __builtin_ldhuio (p2 + 2);
+  __builtin_ldhuio (p2 + 1023);
+  __builtin_ldhuio (p2 + 1024);
+}
+
+void test_ldwio (unsigned int* p1, unsigned int* p2)
+{
+  __builtin_ldwio (p1);
+  __builtin_ldwio (p2);
+  __builtin_ldwio (p2 + 1);
+  __builtin_ldwio (p2 + 2);
+  __builtin_ldwio (p2 + 511);
+  __builtin_ldwio (p2 + 512);
+}
index af079d641c74e65d01d7feefee329c11699ffb49..0e675be39626461813b1c807b208c80acee519af 100644 (file)
@@ -1,4 +1,5 @@
-/* { dg-do compile } */
+/* { dg-do assemble } */
+/* { dg-options "-O" } */
 
 void test_stbio (unsigned char* p1, unsigned char* p2)
 {
@@ -6,6 +7,8 @@ void test_stbio (unsigned char* p1, unsigned char* p2)
   __builtin_stbio (p2, 0);
   __builtin_stbio (p2 + 1, 0x80);
   __builtin_stbio (p2 + 2, 0x7f);
+  __builtin_stbio (p2 + 2047, 0x80);
+  __builtin_stbio (p2 + 2048, 0x7f);
 }
 
 void test_sthio (unsigned short* p1, unsigned short* p2)
@@ -14,6 +17,8 @@ void test_sthio (unsigned short* p1, unsigned short* p2)
   __builtin_sthio (p2, 0);
   __builtin_sthio (p2 + 1, 0x8000);
   __builtin_sthio (p2 + 2, 0x7fff);
+  __builtin_sthio (p2 + 1023, 0x8000);
+  __builtin_sthio (p2 + 1024, 0x7fff);
 }
 
 void test_stwio (unsigned int* p1, unsigned int* p2)
@@ -22,4 +27,7 @@ void test_stwio (unsigned int* p1, unsigned int* p2)
   __builtin_stwio (p2, 0);
   __builtin_stwio (p2 + 1, 0x80000000);
   __builtin_stwio (p2 + 2, 0x7fffffff);
+  __builtin_stwio (p2 + 511, 5);
+  __builtin_stwio (p2 + 512, 5);
 }
+
diff --git a/gcc/testsuite/gcc.target/nios2/r2-io-range.c b/gcc/testsuite/gcc.target/nios2/r2-io-range.c
new file mode 100644 (file)
index 0000000..2064ff6
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=r2 -mbypass-cache" } */
+
+/* Check that the compiler is aware of the reduced offset range for ldio/stio
+   instructions in the Nios II R2 encoding.  */
+
+unsigned int too_big (unsigned int *p)
+{
+  return *(p + 0x400);
+}
+
+unsigned int small_enough (unsigned int *p)
+{
+  return *(p + 0x100);
+}
+
+/* { dg-final { scan-assembler-not "\tldwio\t.*, 4096\\(r.*\\)" } }  */
+/* { dg-final { scan-assembler "\tldwio\t.*, 1024\\(r.*\\)" } }  */
diff --git a/gcc/testsuite/gcc.target/nios2/r2-stio-1.c b/gcc/testsuite/gcc.target/nios2/r2-stio-1.c
new file mode 100644 (file)
index 0000000..5aadd20
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mgpopt -march=r2" } */
+
+/* The ldio/stio builtins must not use GP-relative addresses for
+   small data objects in R2.  This is because the address offset field
+   has been reduced to 12 bits in R2, and %gprel is a 16-bit relocation.  */
+
+extern volatile unsigned int frob;
+
+volatile unsigned int frob = 0;
+
+void foo (unsigned int val)
+{
+  __builtin_stwio (&frob, val);
+}
+
+/* { dg-final { scan-assembler "stwio\\t" } } */
+/* { dg-final { scan-assembler-not "stwio\\t.*%gprel(frob)" } } */
+
diff --git a/gcc/testsuite/gcc.target/nios2/r2-stio-2.c b/gcc/testsuite/gcc.target/nios2/r2-stio-2.c
new file mode 100644 (file)
index 0000000..0a6de90
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mgpopt -march=r2 -mbypass-cache" } */
+
+/* Implicit ldio/stio operations must not use GP-relative addresses for
+   small data objects in R2.  This is because the address offset field
+   has been reduced to 12 bits in R2, and %gprel is a 16-bit relocation.  */
+
+extern volatile unsigned int frob;
+
+volatile unsigned int frob = 0;
+
+void foo (unsigned int val)
+{
+  frob = val;
+}
+
+/* { dg-final { scan-assembler "stwio\\t" } } */
+/* { dg-final { scan-assembler-not "stwio\\t.*%gprel(frob)" } } */
+