+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>
;; 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)
(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"))
|| 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
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)));
}
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
/* 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)
(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))]
""
&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);
+})
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,
+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.
--- /dev/null
+/* { 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);
+}
-/* { dg-do compile } */
+/* { dg-do assemble } */
+/* { dg-options "-O" } */
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)
__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)
__builtin_stwio (p2, 0);
__builtin_stwio (p2 + 1, 0x80000000);
__builtin_stwio (p2 + 2, 0x7fffffff);
+ __builtin_stwio (p2 + 511, 5);
+ __builtin_stwio (p2 + 512, 5);
}
+
--- /dev/null
+/* { 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.*\\)" } } */
--- /dev/null
+/* { 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)" } } */
+
--- /dev/null
+/* { 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)" } } */
+