summaryrefslogtreecommitdiff
path: root/gcc/config/nios2
diff options
context:
space:
mode:
authorsandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-14 23:43:48 +0000
committersandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-14 23:43:48 +0000
commit804de48f8b7b51653944857f702117ea645b5346 (patch)
treea1ebc88c554b085e5722372d81bb1fb10519908b /gcc/config/nios2
parentf22b250dbdcd0bb213963d40c97f726a46f64cfa (diff)
downloadgcc-804de48f8b7b51653944857f702117ea645b5346.tar.gz
2015-07-14 Sandra Loosemore <sandra@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com> Chung-Lin Tang <cltang@codesourcery.com> gcc/ * config/nios2/constraints.md (U, v): New constraints. * config/nios2/predicates.md (rdprs_dcache_operand): New. (ldstex_memory_operand): New. * config/nios2/sync.md: New file. * config/nios2/nios2.md (unspecv): Add new builtin function UNSPECV codes. (rdprs, flushd, flushda, wrpie, eni): New patterns. (top-level): Include sync.md. * config/nios2/nios2.c (N2_FTYPES): Add function types for new builtins. (N2_BUILTINS): Add arch field setting, add new builtins. (enum nios2_builtin_code,nios2_builtins): Update N2_BUILTIN_DEF for arch field. (nios2_expand_ldst_builtin): Rename from nios2_expand_ldstio_builtin. Also handle ldex/stex/ldsex/stsex builtins. (nios2_expand_rdprs_builtin): New function. (nios2_expand_cache_builtin): New function. (nios2_expand_wrpie_builtin): New function. (nios2_expand_eni_builtin): New function. (nios2_expand_builtin): Add arch field handling and new builtin cases. * doc/extend.texi (Altera Nios II Built-in Functions): Document new builtins. * doc/md.texi (Machine Constraints): Document U and v constraints. gcc/testsuite/ * gcc.target/nios2/nios2-flushd.c: New. * gcc.target/nios2/nios2-rdprs.c: New. * gcc.target/nios2/r2-atomic.c: New. * gcc.target/nios2/r2-eni.c: New. * gcc.target/nios2/r2-wrpie.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@225800 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nios2')
-rw-r--r--gcc/config/nios2/constraints.md13
-rw-r--r--gcc/config/nios2/nios2.c165
-rw-r--r--gcc/config/nios2/nios2.md55
-rw-r--r--gcc/config/nios2/predicates.md13
-rw-r--r--gcc/config/nios2/sync.md45
5 files changed, 270 insertions, 21 deletions
diff --git a/gcc/config/nios2/constraints.md b/gcc/config/nios2/constraints.md
index 0ec817fd771..6f7afa4358f 100644
--- a/gcc/config/nios2/constraints.md
+++ b/gcc/config/nios2/constraints.md
@@ -28,9 +28,11 @@
;; M: 0
;; N: 0 to 255 (for custom instruction numbers)
;; O: 0 to 31 (for control register numbers)
+;; U: -32768 to 32767 under R1, -2048 to 2047 under R2
;;
;; We use the following constraint letters for memory constraints
;;
+;; v: memory operands for R2 load/store exclusive instructions
;; w: memory operands for load/store IO and cache instructions
;;
;; We use the following built-in register classes:
@@ -100,6 +102,17 @@
"A constant unspec offset representing a relocation."
(match_test "nios2_unspec_reloc_p (op)"))
+(define_constraint "U"
+ "A 12-bit or 16-bit constant (for RDPRS and DCACHE)."
+ (and (match_code "const_int")
+ (if_then_else (match_test "TARGET_ARCH_R2")
+ (match_test "SMALL_INT12 (ival)")
+ (match_test "SMALL_INT (ival)"))))
+
+(define_memory_constraint "v"
+ "A memory operand suitable for R2 load/store exclusive instructions."
+ (match_operand 0 "ldstex_memory_operand"))
+
(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 2d7c4a2169f..a780c512060 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -135,12 +135,16 @@ static bool custom_code_conflict = false;
N2_FTYPE(2, (SI, SF)) \
N2_FTYPE(3, (SI, SF, SF)) \
N2_FTYPE(2, (SI, SI)) \
+ N2_FTYPE(3, (SI, SI, SI)) \
+ N2_FTYPE(3, (SI, VPTR, SI)) \
N2_FTYPE(2, (UI, CVPTR)) \
N2_FTYPE(2, (UI, DF)) \
N2_FTYPE(2, (UI, SF)) \
N2_FTYPE(2, (VOID, DF)) \
N2_FTYPE(2, (VOID, SF)) \
+ N2_FTYPE(2, (VOID, SI)) \
N2_FTYPE(3, (VOID, SI, SI)) \
+ N2_FTYPE(2, (VOID, VPTR)) \
N2_FTYPE(3, (VOID, VPTR, SI))
#define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
@@ -3266,33 +3270,43 @@ nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
struct nios2_builtin_desc
{
enum insn_code icode;
+ enum nios2_arch_type arch;
enum nios2_ftcode ftype;
const char *name;
};
#define N2_BUILTINS \
- N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
- N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
- N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
- N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
- N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
- N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
- N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
- N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
- N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
- N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
- N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
+ N2_BUILTIN_DEF (sync, R1, N2_FTYPE_VOID_VOID) \
+ N2_BUILTIN_DEF (ldbio, R1, N2_FTYPE_SI_CVPTR) \
+ N2_BUILTIN_DEF (ldbuio, R1, N2_FTYPE_UI_CVPTR) \
+ N2_BUILTIN_DEF (ldhio, R1, N2_FTYPE_SI_CVPTR) \
+ N2_BUILTIN_DEF (ldhuio, R1, N2_FTYPE_UI_CVPTR) \
+ N2_BUILTIN_DEF (ldwio, R1, N2_FTYPE_SI_CVPTR) \
+ N2_BUILTIN_DEF (stbio, R1, N2_FTYPE_VOID_VPTR_SI) \
+ N2_BUILTIN_DEF (sthio, R1, N2_FTYPE_VOID_VPTR_SI) \
+ N2_BUILTIN_DEF (stwio, R1, N2_FTYPE_VOID_VPTR_SI) \
+ N2_BUILTIN_DEF (rdctl, R1, N2_FTYPE_SI_SI) \
+ N2_BUILTIN_DEF (wrctl, R1, N2_FTYPE_VOID_SI_SI) \
+ N2_BUILTIN_DEF (rdprs, R1, N2_FTYPE_SI_SI_SI) \
+ N2_BUILTIN_DEF (flushd, R1, N2_FTYPE_VOID_VPTR) \
+ N2_BUILTIN_DEF (flushda, R1, N2_FTYPE_VOID_VPTR) \
+ N2_BUILTIN_DEF (wrpie, R2, N2_FTYPE_SI_SI) \
+ N2_BUILTIN_DEF (eni, R2, N2_FTYPE_VOID_SI) \
+ N2_BUILTIN_DEF (ldex, R2, N2_FTYPE_SI_CVPTR) \
+ N2_BUILTIN_DEF (ldsex, R2, N2_FTYPE_SI_CVPTR) \
+ N2_BUILTIN_DEF (stex, R2, N2_FTYPE_SI_VPTR_SI) \
+ N2_BUILTIN_DEF (stsex, R2, N2_FTYPE_SI_VPTR_SI)
enum nios2_builtin_code {
-#define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
+#define N2_BUILTIN_DEF(name, arch, ftype) NIOS2_BUILTIN_ ## name,
N2_BUILTINS
#undef N2_BUILTIN_DEF
NUM_FIXED_NIOS2_BUILTINS
};
static const struct nios2_builtin_desc nios2_builtins[] = {
-#define N2_BUILTIN_DEF(name, ftype) \
- { CODE_FOR_ ## name, ftype, "__builtin_" #name },
+#define N2_BUILTIN_DEF(name, arch, ftype) \
+ { CODE_FOR_ ## name, ARCH_ ## arch, ftype, "__builtin_" #name },
N2_BUILTINS
#undef N2_BUILTIN_DEF
};
@@ -3373,10 +3387,11 @@ nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
}
}
-/* Expand ldio/stio form load-store instruction builtins. */
+/* Expand ldio/stio and ldex/ldsex/stex/stsex form load-store
+ instruction builtins. */
static rtx
-nios2_expand_ldstio_builtin (tree exp, rtx target,
- const struct nios2_builtin_desc *d)
+nios2_expand_ldst_builtin (tree exp, rtx target,
+ const struct nios2_builtin_desc *d)
{
bool has_target_p;
rtx addr, mem, val;
@@ -3388,14 +3403,21 @@ nios2_expand_ldstio_builtin (tree exp, rtx target,
if (insn_data[d->icode].operand[0].allows_mem)
{
- /* stxio. */
+ /* stxio/stex/stsex. */
val = expand_normal (CALL_EXPR_ARG (exp, 1));
if (CONST_INT_P (val))
val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
create_output_operand (&ops[0], mem, mode);
create_input_operand (&ops[1], val, mode);
- has_target_p = false;
+ if (insn_data[d->icode].n_operands == 3)
+ {
+ /* stex/stsex status value, returned as result of function. */
+ create_output_operand (&ops[2], target, mode);
+ has_target_p = true;
+ }
+ else
+ has_target_p = false;
}
else
{
@@ -3404,7 +3426,8 @@ nios2_expand_ldstio_builtin (tree exp, rtx target,
create_input_operand (&ops[1], mem, mode);
has_target_p = true;
}
- return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
+ return nios2_expand_builtin_insn (d, insn_data[d->icode].n_operands, ops,
+ has_target_p);
}
/* Expand rdctl/wrctl builtins. */
@@ -3436,6 +3459,81 @@ nios2_expand_rdwrctl_builtin (tree exp, rtx target,
return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
}
+static rtx
+nios2_expand_rdprs_builtin (tree exp, rtx target,
+ const struct nios2_builtin_desc *d)
+{
+ rtx reg = expand_normal (CALL_EXPR_ARG (exp, 0));
+ rtx imm = expand_normal (CALL_EXPR_ARG (exp, 1));
+ struct expand_operand ops[MAX_RECOG_OPERANDS];
+
+ if (!rdwrctl_operand (reg, VOIDmode))
+ {
+ error ("Register number must be in range 0-31 for %s",
+ d->name);
+ return gen_reg_rtx (SImode);
+ }
+
+ if (!rdprs_dcache_operand (imm, VOIDmode))
+ {
+ error ("The immediate value must fit into a %d-bit integer for %s",
+ (TARGET_ARCH_R2) ? 12 : 16, d->name);
+ return gen_reg_rtx (SImode);
+ }
+
+ create_output_operand (&ops[0], target, SImode);
+ create_input_operand (&ops[1], reg, SImode);
+ create_integer_operand (&ops[2], INTVAL (imm));
+
+ return nios2_expand_builtin_insn (d, 3, ops, true);
+}
+
+static rtx
+nios2_expand_cache_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+ const struct nios2_builtin_desc *d)
+{
+ rtx mem, addr;
+ struct expand_operand ops[MAX_RECOG_OPERANDS];
+
+ addr = expand_normal (CALL_EXPR_ARG (exp, 0));
+ mem = gen_rtx_MEM (SImode, addr);
+
+ create_input_operand (&ops[0], mem, SImode);
+
+ return nios2_expand_builtin_insn (d, 1, ops, false);
+}
+
+static rtx
+nios2_expand_wrpie_builtin (tree exp, rtx target,
+ const struct nios2_builtin_desc *d)
+{
+ rtx val;
+ struct expand_operand ops[MAX_RECOG_OPERANDS];
+
+ val = expand_normal (CALL_EXPR_ARG (exp, 0));
+ create_input_operand (&ops[1], val, SImode);
+ create_output_operand (&ops[0], target, SImode);
+
+ return nios2_expand_builtin_insn (d, 2, ops, true);
+}
+
+static rtx
+nios2_expand_eni_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+ const struct nios2_builtin_desc *d)
+{
+ rtx imm = expand_normal (CALL_EXPR_ARG (exp, 0));
+ struct expand_operand ops[MAX_RECOG_OPERANDS];
+
+ if (INTVAL (imm) != 0 && INTVAL (imm) != 1)
+ {
+ error ("The ENI instruction operand must be either 0 or 1");
+ return const0_rtx;
+ }
+ create_integer_operand (&ops[0], INTVAL (imm));
+
+ return nios2_expand_builtin_insn (d, 1, ops, false);
+}
+
/* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
a built-in function, with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -3454,6 +3552,14 @@ nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
{
const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
+ if (d->arch > nios2_arch_option)
+ {
+ error ("Builtin function %s requires Nios II R%d",
+ d->name, (int) d->arch);
+ /* Given it is invalid, just generate a normal call. */
+ return expand_call (exp, target, ignore);
+ }
+
switch (fcode)
{
case NIOS2_BUILTIN_sync:
@@ -3468,12 +3574,29 @@ nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case NIOS2_BUILTIN_stbio:
case NIOS2_BUILTIN_sthio:
case NIOS2_BUILTIN_stwio:
- return nios2_expand_ldstio_builtin (exp, target, d);
+ case NIOS2_BUILTIN_ldex:
+ case NIOS2_BUILTIN_ldsex:
+ case NIOS2_BUILTIN_stex:
+ case NIOS2_BUILTIN_stsex:
+ return nios2_expand_ldst_builtin (exp, target, d);
case NIOS2_BUILTIN_rdctl:
case NIOS2_BUILTIN_wrctl:
return nios2_expand_rdwrctl_builtin (exp, target, d);
+ case NIOS2_BUILTIN_rdprs:
+ return nios2_expand_rdprs_builtin (exp, target, d);
+
+ case NIOS2_BUILTIN_flushd:
+ case NIOS2_BUILTIN_flushda:
+ return nios2_expand_cache_builtin (exp, target, d);
+
+ case NIOS2_BUILTIN_wrpie:
+ return nios2_expand_wrpie_builtin (exp, target, d);
+
+ case NIOS2_BUILTIN_eni:
+ return nios2_expand_eni_builtin (exp, target, d);
+
default:
gcc_unreachable ();
}
diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
index 23f236d85cb..88e689b00bf 100644
--- a/gcc/config/nios2/nios2.md
+++ b/gcc/config/nios2/nios2.md
@@ -62,6 +62,15 @@
UNSPECV_CUSTOM_XNXX
UNSPECV_LDXIO
UNSPECV_STXIO
+ UNSPECV_RDPRS
+ UNSPECV_FLUSHD
+ UNSPECV_FLUSHDA
+ UNSPECV_WRPIE
+ UNSPECV_ENI
+ UNSPECV_LDEX
+ UNSPECV_LDSEX
+ UNSPECV_STEX
+ UNSPECV_STSEX
])
(define_c_enum "unspec" [
@@ -1127,6 +1136,48 @@
"wrctl\\tctl%0, %z1"
[(set_attr "type" "control")])
+(define_insn "rdprs"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
+ (match_operand:SI 2 "arith_operand" "U")]
+ UNSPECV_RDPRS))]
+ ""
+ "rdprs\\t%0, %1, %2"
+ [(set_attr "type" "control")])
+
+;; Cache Instructions
+
+(define_insn "flushd"
+ [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
+ UNSPECV_FLUSHD)]
+ ""
+ "flushd\\t%0"
+ [(set_attr "type" "control")])
+
+(define_insn "flushda"
+ [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
+ UNSPECV_FLUSHDA)]
+ ""
+ "flushda\\t%0"
+ [(set_attr "type" "control")])
+
+;; R2 Instructions
+
+(define_insn "wrpie"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPECV_WRPIE))]
+ "TARGET_ARCH_R2"
+ "wrpie\\t%0, %1"
+ [(set_attr "type" "control")])
+
+(define_insn "eni"
+ [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
+ UNSPECV_ENI)]
+ "TARGET_ARCH_R2"
+ "eni\\t%0"
+ [(set_attr "type" "control")])
+
;; Trap patterns
(define_insn "trap"
[(trap_if (const_int 1) (const_int 3))]
@@ -1172,6 +1223,10 @@
emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
DONE;
})
+
+;; Synchronization Primitives
+(include "sync.md")
+
;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
(include "ldstwm.md")
diff --git a/gcc/config/nios2/predicates.md b/gcc/config/nios2/predicates.md
index 3f2d441c4ea..f1de2f4edb3 100644
--- a/gcc/config/nios2/predicates.md
+++ b/gcc/config/nios2/predicates.md
@@ -81,6 +81,12 @@
(and (match_code "const_int")
(match_test "RDWRCTL_INT (INTVAL (op))")))
+(define_predicate "rdprs_dcache_operand"
+ (and (match_code "const_int")
+ (if_then_else (match_test "TARGET_ARCH_R2")
+ (match_test "SMALL_INT12 (INTVAL (op))")
+ (match_test "SMALL_INT (INTVAL (op))"))))
+
(define_predicate "custom_insn_opcode"
(and (match_code "const_int")
(match_test "CUSTOM_INSN_OPCODE (INTVAL (op))")))
@@ -144,3 +150,10 @@
}
return memory_operand (op, mode);
})
+
+(define_predicate "ldstex_memory_operand"
+ (match_code "mem")
+{
+ /* ldex/ldsex/stex/stsex cannot handle memory addresses with offsets. */
+ return GET_CODE (XEXP (op, 0)) == REG;
+})
diff --git a/gcc/config/nios2/sync.md b/gcc/config/nios2/sync.md
new file mode 100644
index 00000000000..405aa38e9aa
--- /dev/null
+++ b/gcc/config/nios2/sync.md
@@ -0,0 +1,45 @@
+;; Machine Description for Altera Nios II synchronization primitives.
+;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
+;; Contributed by Mentor Graphics, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_int_iterator UNSPECV_LOAD_EXCLUSIVE [UNSPECV_LDEX UNSPECV_LDSEX])
+(define_int_attr load_exclusive [(UNSPECV_LDEX "ldex")
+ (UNSPECV_LDSEX "ldsex")])
+(define_insn "<load_exclusive>"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "ldstex_memory_operand" "v")]
+ UNSPECV_LOAD_EXCLUSIVE))]
+ "TARGET_ARCH_R2"
+ "<load_exclusive>\\t%0, %A1"
+ [(set_attr "type" "ld")])
+
+(define_int_iterator UNSPECV_STORE_EXCLUSIVE [UNSPECV_STEX UNSPECV_STSEX])
+(define_int_attr store_exclusive [(UNSPECV_STEX "stex")
+ (UNSPECV_STSEX "stsex")])
+(define_insn "<store_exclusive>"
+ [(set (match_operand:SI 2 "register_operand" "=r")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_STORE_EXCLUSIVE))
+ (set (match_operand:SI 0 "ldstex_memory_operand" "=v")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")]
+ UNSPECV_STORE_EXCLUSIVE))]
+ "TARGET_ARCH_R2"
+ "<store_exclusive>\\t%2, %z1, %A0"
+ [(set_attr "type" "st")])