aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/nios2
diff options
context:
space:
mode:
authorsandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-14 22:34:23 +0000
committersandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-14 22:34:23 +0000
commit7eb60b4dda7cb3e5b67d4adbb7701b48d7076b67 (patch)
treebf04fdbea43651a05a4d5427cd7eeafe6ceca391 /gcc/config/nios2
parent9515cb26b8b1c09770cce6e2f57eb3273d4a1fd7 (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@225792 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nios2')
-rw-r--r--gcc/config/nios2/constraints.md8
-rw-r--r--gcc/config/nios2/nios2.c24
-rw-r--r--gcc/config/nios2/nios2.h1
-rw-r--r--gcc/config/nios2/nios2.md8
-rw-r--r--gcc/config/nios2/predicates.md17
5 files changed, 53 insertions, 5 deletions
diff --git a/gcc/config/nios2/constraints.md b/gcc/config/nios2/constraints.md
index b67e87d3b3c..7c7afdfb115 100644
--- a/gcc/config/nios2/constraints.md
+++ b/gcc/config/nios2/constraints.md
@@ -28,6 +28,10 @@
;; 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"))
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 7c97a02b521..93e0a869f32 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -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
diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h
index c3c958a083d..58afaec69ce 100644
--- a/gcc/config/nios2/nios2.h
+++ b/gcc/config/nios2/nios2.h
@@ -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)
diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
index 70977802009..8cf2347e05c 100644
--- a/gcc/config/nios2/nios2.md
+++ b/gcc/config/nios2/nios2.md
@@ -221,14 +221,14 @@
(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);
@@ -241,13 +241,13 @@
[(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))]
""
diff --git a/gcc/config/nios2/predicates.md b/gcc/config/nios2/predicates.md
index 37cecf774f2..fa578035cca 100644
--- a/gcc/config/nios2/predicates.md
+++ b/gcc/config/nios2/predicates.md
@@ -83,3 +83,20 @@
&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);
+})