This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCHv2 4/7] gcc/arc: Add support for nps400 cmem xld/xst instructions
- From: Andrew Burgess <andrew dot burgess at embecosm dot com>
- To: gcc-patches at gcc dot gnu dot org, gnu at amylaar dot uk
- Cc: noamca at mellanox dot com, Claudiu dot Zissulescu at synopsys dot com, Andrew Burgess <andrew dot burgess at embecosm dot com>
- Date: Thu, 21 Apr 2016 12:39:38 +0100
- Subject: [PATCHv2 4/7] gcc/arc: Add support for nps400 cmem xld/xst instructions
- Authentication-results: sourceware.org; auth=none
- References: <cover dot 1461238348 dot git dot andrew dot burgess at embecosm dot com>
- References: <cover dot 1457097757 dot git dot andrew dot burgess at embecosm dot com> <cover dot 1461238348 dot git dot andrew dot burgess at embecosm dot com>
This commit adds support for NPS400 cmem memory sections. Data to be
placed into cmem memory is placed into a section ".cmem",
".cmem_shared", or ".cmem_private".
There are restrictions on how instructions can be used to operate on
data held in cmem memory, this is reflected by the introduction of new
operand constraints (Uex/Ucm), and modifications to some instructions to
make use of these constraints.
gcc/ChangeLog:
* config/arc/arc.h (SYMBOL_FLAG_CMEM): Define.
(TARGET_NPS_CMEM_DEFAULT): Provide default definition.
* config/arc/arc.c (arc_address_cost): Return 0 for cmem_address.
(arc_encode_section_info): Set SYMBOL_FLAG_CMEM where indicated.
* config/arc/arc.opt (mcmem): New option.
* config/arc/arc.md (*extendqihi2_i): Add r/Uex alternative,
supply length for r/m alternative.
(*extendqisi2_ac): Likewise.
(*extendhisi2_i): Add r/Uex alternative, supply length for r/m and
r/Uex alternative.
(movqi_insn): Add r/Ucm and Ucm/?Rac alternatives.
(movhi_insn): Likewise.
(movsi_insn): Add r/Ucm,Ucm/w alternatives.
(*zero_extendqihi2_i): Add r/Ucm alternative.
(*zero_extendqisi2_ac): Likewise.
(*zero_extendhisi2_i): Likewise.
* config/arc/constraints.md (Uex): New memory constraint.
(Ucm): New define_constraint.
* config/arc/predicates.md (long_immediate_loadstore_operand):
Return 0 for MEM with cmem_address address.
(cmem_address_0): New predicates.
(cmem_address_1): Likewise.
(cmem_address_2): Likewise.
(cmem_address): Likewise.
gcc/testsuite/ChangeLog:
* gcc.target/arc/cmem-1.c: New file.
* gcc.target/arc/cmem-2.c: New file.
* gcc.target/arc/cmem-3.c: New file.
* gcc.target/arc/cmem-4.c: New file.
* gcc.target/arc/cmem-5.c: New file.
* gcc.target/arc/cmem-6.c: New file.
* gcc.target/arc/cmem-7.c: New file.
* gcc.target/arc/cmem-ld.inc: New file.
* gcc.target/arc/cmem-st.inc: New file.
---
gcc/ChangeLog.NPS400 | 28 ++++++++
gcc/config/arc/arc.c | 20 ++++++
gcc/config/arc/arc.h | 9 +++
gcc/config/arc/arc.md | 115 +++++++++++++++++--------------
gcc/config/arc/arc.opt | 8 +++
gcc/config/arc/constraints.md | 14 +++-
gcc/config/arc/predicates.md | 19 +++++
gcc/testsuite/ChangeLog.NPS400 | 19 +++++
gcc/testsuite/gcc.target/arc/cmem-1.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-2.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-3.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-4.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-5.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-6.c | 10 +++
gcc/testsuite/gcc.target/arc/cmem-7.c | 26 +++++++
gcc/testsuite/gcc.target/arc/cmem-ld.inc | 16 +++++
gcc/testsuite/gcc.target/arc/cmem-st.inc | 18 +++++
17 files changed, 301 insertions(+), 51 deletions(-)
create mode 100644 gcc/testsuite/ChangeLog.NPS400
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-1.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-2.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-3.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-4.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-5.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-6.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-7.c
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-ld.inc
create mode 100644 gcc/testsuite/gcc.target/arc/cmem-st.inc
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index ae8772e..890a1a5 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -1789,6 +1789,8 @@ arc_address_cost (rtx addr, machine_mode, addr_space_t, bool speed)
case LABEL_REF :
case SYMBOL_REF :
case CONST :
+ if (TARGET_NPS_CMEM && cmem_address (addr, SImode))
+ return 0;
/* Most likely needs a LIMM. */
return COSTS_N_INSNS (1);
@@ -4263,6 +4265,24 @@ arc_encode_section_info (tree decl, rtx rtl, int first)
SYMBOL_REF_FLAGS (symbol) = flags;
}
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ rtx symbol = XEXP (rtl, 0);
+
+ tree attr = (TREE_TYPE (decl) != error_mark_node
+ ? DECL_ATTRIBUTES (decl) : NULL_TREE);
+
+ tree sec_attr = lookup_attribute ("section", attr);
+ if (sec_attr)
+ {
+ const char *sec_name
+ = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec_attr)));
+ if (strcmp (sec_name, ".cmem") == 0
+ || strcmp (sec_name, ".cmem_shared") == 0
+ || strcmp (sec_name, ".cmem_private") == 0)
+ SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_CMEM;
+ }
+ }
}
/* This is how to output a definition of an internal numbered label where
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index f96bf0f..5ac4115 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#define SYMBOL_FLAG_SHORT_CALL (SYMBOL_FLAG_MACH_DEP << 0)
#define SYMBOL_FLAG_MEDIUM_CALL (SYMBOL_FLAG_MACH_DEP << 1)
#define SYMBOL_FLAG_LONG_CALL (SYMBOL_FLAG_MACH_DEP << 2)
+#define SYMBOL_FLAG_CMEM (SYMBOL_FLAG_MACH_DEP << 3)
/* Check if this symbol has a long_call attribute in its declaration */
#define SYMBOL_REF_LONG_CALL_P(X) \
@@ -313,6 +314,14 @@ along with GCC; see the file COPYING3. If not see
#define MULTILIB_DEFAULTS { "mARC700" }
#endif
+#ifndef UNALIGNED_ACCESS_DEFAULT
+#define UNALIGNED_ACCESS_DEFAULT 0
+#endif
+
+#ifndef TARGET_NPS_CMEM_DEFAULT
+#define TARGET_NPS_CMEM_DEFAULT 0
+#endif
+
/* Target machine storage layout. */
/* We want zero_extract to mean the same
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 99e8e30..33e6dee 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -611,8 +611,8 @@
; The iscompact attribute allows the epilogue expander to know for which
; insns it should lengthen the return insn.
(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w, w,Rcq,S,!*x,r,m,???m")
- (match_operand:QI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,m,c,?Rac"))]
+ [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,w,Rcq,S,!*x,r,r,Ucm,m,???m")
+ (match_operand:QI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"@
@@ -626,13 +626,15 @@
ldb%? %0,%1%&
stb%? %1,%0%&
ldb%? %0,%1%&
+ xldb%U1 %0,%1
ldb%U1%V1 %0,%1
+ xstb%U0 %1,%0
stb%U0%V0 %1,%0
stb%U0%V0 %1,%0"
- [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,store,store")
- (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false")
- (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no")
- (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*")])
+ [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false,false,false")
+ (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no,no,no")
+ (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*")])
(define_expand "movhi"
[(set (match_operand:HI 0 "move_dest_operand" "")
@@ -641,8 +643,8 @@
"if (prepare_move_operands (operands, HImode)) DONE;")
(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w,Rcq#q,w,Rcq,S,r,m,???m,VUsc")
- (match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac, ?i,?i,T,Rcq,m,c,?Rac,i"))]
+ [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,Rcq#q,w,Rcq,S,r,r,Ucm,m,???m,VUsc")
+ (match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,?i,T,Rcq,Ucm,m,?Rac,c,?Rac,i"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)
|| (CONSTANT_P (operands[1])
@@ -661,14 +663,16 @@
mov%? %0,%S1
ld%_%? %0,%1%&
st%_%? %1,%0%&
+ xld%_%U1 %0,%1
ld%_%U1%V1 %0,%1
+ xst%_%U0 %1,%0
st%_%U0%V0 %1,%0
st%_%U0%V0 %1,%0
st%_%U0%V0 %S1,%0"
- [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,store,store,store")
- (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false")
- (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no")
- (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*")])
+ [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false")
+ (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no")
+ (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*")])
(define_expand "movsi"
[(set (match_operand:SI 0 "move_dest_operand" "")
@@ -687,8 +691,8 @@
; insns it should lengthen the return insn.
; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w, w,???w, ?w, w,Rcq#q, w,Rcq, S,Us<,RcqRck,!*x,r,m,???m,VUsc")
- (match_operand:SI 1 "move_src_operand" " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,m,c,?Rac,C32"))]
+ [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w, w,???w, ?w, w,Rcq#q, w,Rcq, S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
+ (match_operand:SI 1 "move_src_operand" " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| (CONSTANT_P (operands[1])
@@ -713,17 +717,19 @@
* return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
* return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
ld%? %0,%1%& ;15
- ld%U1%V1 %0,%1 ;16
- st%U0%V0 %1,%0 ;17
- st%U0%V0 %1,%0 ;18
- st%U0%V0 %S1,%0 ;19"
- [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,store,store,store")
- (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false")
+ xld%U1 %0,%1 ;16
+ ld%U1%V1 %0,%1 ;17
+ xst%U0 %1,%0 ;18
+ st%U0%V0 %1,%0 ;19
+ st%U0%V0 %1,%0 ;20
+ st%U0%V0 %S1,%0 ;21"
+ [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
; Use default length for iscompact to allow for COND_EXEC. But set length
; of Crr to 4.
- (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,*,*,*,8")
- (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no")
- (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+ (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
+ (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
+ (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
;; Sometimes generated by the epilogue code. We don't want to
;; recognize these addresses in general, because the limm is costly,
@@ -1450,18 +1456,19 @@
(define_insn "*zero_extendqihi2_i"
- [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r")
- (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,m")))]
+ [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r,r")
+ (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,Ucm,m")))]
""
"@
extb%? %0,%1%&
extb%? %0,%1%&
bmsk%? %0,%1,7
extb %0,%1
+ xldb%U1 %0,%1
ldb%U1 %0,%1"
- [(set_attr "type" "unary,unary,unary,unary,load")
- (set_attr "iscompact" "maybe,true,false,false,false")
- (set_attr "predicable" "no,no,yes,no,no")])
+ [(set_attr "type" "unary,unary,unary,unary,load,load")
+ (set_attr "iscompact" "maybe,true,false,false,false,false")
+ (set_attr "predicable" "no,no,yes,no,no,no")])
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "dest_reg_operand" "")
@@ -1471,8 +1478,8 @@
)
(define_insn "*zero_extendqisi2_ac"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r")
- (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,m")))]
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r,r")
+ (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,Ucm,m")))]
""
"@
extb%? %0,%1%&
@@ -1481,10 +1488,11 @@
extb %0,%1
ldb%? %0,%1%&
ldb%? %0,%1%&
+ xldb%U1 %0,%1
ldb%U1 %0,%1"
- [(set_attr "type" "unary,unary,unary,unary,load,load,load")
- (set_attr "iscompact" "maybe,true,false,false,true,true,false")
- (set_attr "predicable" "no,no,yes,no,no,no,no")])
+ [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
+ (set_attr "iscompact" "maybe,true,false,false,true,true,false,false")
+ (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
(define_expand "zero_extendqisi2"
[(set (match_operand:SI 0 "dest_reg_operand" "")
@@ -1494,8 +1502,8 @@
)
(define_insn "*zero_extendhisi2_i"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r")
- (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,m")))]
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,Ucm,m")))]
""
"@
ext%_%? %0,%1%&
@@ -1504,10 +1512,11 @@
ext%_ %0,%1
ld%_%? %0,%1%&
ld%_%U1 %0,%1
+ * return TARGET_EM ? \"xldh%U1%V1 %0,%1\" : \"xldw%U1 %0,%1\";
ld%_%U1%V1 %0,%1"
- [(set_attr "type" "unary,unary,unary,unary,load,load,load")
- (set_attr "iscompact" "maybe,true,false,false,true,false,false")
- (set_attr "predicable" "no,no,yes,no,no,no,no")])
+ [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
+ (set_attr "iscompact" "maybe,true,false,false,true,false,false,false")
+ (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
(define_expand "zero_extendhisi2"
@@ -1520,15 +1529,17 @@
;; Sign extension instructions.
(define_insn "*extendqihi2_i"
- [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r")
- (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,m")))]
+ [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r,r")
+ (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,Uex,m")))]
""
"@
sexb%? %0,%1%&
sexb %0,%1
+ ldb.x%U1 %0,%1
ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,unary,load")
- (set_attr "iscompact" "true,false,false")])
+ [(set_attr "type" "unary,unary,load,load")
+ (set_attr "iscompact" "true,false,false,false")
+ (set_attr "length" "*,*,*,8")])
(define_expand "extendqihi2"
@@ -1539,15 +1550,17 @@
)
(define_insn "*extendqisi2_ac"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
- (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
+ (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
""
"@
sexb%? %0,%1%&
sexb %0,%1
+ ldb.x%U1 %0,%1
ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,unary,load")
- (set_attr "iscompact" "true,false,false")])
+ [(set_attr "type" "unary,unary,load,load")
+ (set_attr "iscompact" "true,false,false,false")
+ (set_attr "length" "*,*,*,8")])
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "dest_reg_operand" "")
@@ -1557,15 +1570,17 @@
)
(define_insn "*extendhisi2_i"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
- (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
""
"@
sex%_%? %0,%1%&
sex%_ %0,%1
+ ld%_.x%U1%V1 %0,%1
ld%_.x%U1%V1 %0,%1"
- [(set_attr "type" "unary,unary,load")
- (set_attr "iscompact" "true,false,false")])
+ [(set_attr "type" "unary,unary,load,load")
+ (set_attr "iscompact" "true,false,false,false")
+ (set_attr "length" "*,*,4,8")])
(define_expand "extendhisi2"
[(set (match_operand:SI 0 "dest_reg_operand" "")
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index 14fd2a4..19d4c21 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -462,3 +462,11 @@ Enum(arc_fpu) String(fpus_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD)
EnumValue
Enum(arc_fpu) String(fpud_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPU_DP | FPU_DC | FPU_DF | FPU_DD)
+
+mcmem
+Target Report Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
+Enable use of NPS400 xld/xst extension.
+
+munaligned-access
+Target Report Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
+Enable unaligned word and halfword accesses to packed data.
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index b6954ad..c2992c9 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -269,6 +269,13 @@
(and (match_code "mem")
(match_test "compact_store_memory_operand (op, VOIDmode)")))
+(define_memory_constraint "Uex"
+ "@internal
+ A valid memory operand for limm-free extend instructions"
+ (and (match_code "mem")
+ (match_test "!cmem_address (XEXP (op, 0), SImode)")
+ (not (match_operand 0 "long_immediate_loadstore_operand"))))
+
; Don't use define_memory_constraint here as the relocation patching
; for small data symbols only works within a ld/st instruction and
; define_memory_constraint may result in the address being calculated
@@ -303,6 +310,12 @@
(match_test "REG_P (XEXP (XEXP (op, 0), 0))")
(match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")))
+(define_constraint "Ucm"
+ "@internal
+ cmem access"
+ (and (match_code "mem")
+ (match_test "TARGET_NPS_CMEM && cmem_address (XEXP (op, 0), VOIDmode)")))
+
;; General constraints
(define_constraint "Cbr"
@@ -430,4 +443,3 @@
(define_memory_constraint "ATO"
"A memory with only a base register"
(match_operand 0 "mem_noofs_operand"))
-
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
index 85bbf84..91726db 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -123,6 +123,8 @@
int size = GET_MODE_SIZE (GET_MODE (op));
op = XEXP (op, 0);
+ if (TARGET_NPS_CMEM && cmem_address (op, SImode))
+ return 0;
switch (GET_CODE (op))
{
case SYMBOL_REF :
@@ -806,3 +808,20 @@
(define_predicate "double_register_operand"
(ior (match_test "even_register_operand (op, mode)")
(match_test "arc_double_register_operand (op, mode)")))
+
+(define_predicate "cmem_address_0"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_CMEM")))
+
+(define_predicate "cmem_address_1"
+ (and (match_code "plus")
+ (match_test "cmem_address_0 (XEXP (op, 0), SImode)")))
+
+(define_predicate "cmem_address_2"
+ (and (match_code "const")
+ (match_test "cmem_address_1 (XEXP (op, 0), SImode)")))
+
+(define_predicate "cmem_address"
+ (ior (match_operand:SI 0 "cmem_address_0")
+ (match_operand:SI 0 "cmem_address_1")
+ (match_operand:SI 0 "cmem_address_2")))
diff --git a/gcc/testsuite/gcc.target/arc/cmem-1.c b/gcc/testsuite/gcc.target/arc/cmem-1.c
new file mode 100644
index 0000000..7f36afb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
+
+#include "cmem-st.inc"
+
+/* { dg-final { scan-assembler "xst " } } */
+/* { dg-final { scan-assembler "xstw " } } */
+/* { dg-final { scan-assembler "xstb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-2.c b/gcc/testsuite/gcc.target/arc/cmem-2.c
new file mode 100644
index 0000000..a3d7c130
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
+
+#include "cmem-ld.inc"
+
+/* { dg-final { scan-assembler "xld " } } */
+/* { dg-final { scan-assembler "xldw " } } */
+/* { dg-final { scan-assembler "xldb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-3.c b/gcc/testsuite/gcc.target/arc/cmem-3.c
new file mode 100644
index 0000000..dee73b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
+
+#include "cmem-st.inc"
+
+/* { dg-final { scan-assembler "xst " } } */
+/* { dg-final { scan-assembler "xstw " } } */
+/* { dg-final { scan-assembler "xstb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-4.c b/gcc/testsuite/gcc.target/arc/cmem-4.c
new file mode 100644
index 0000000..1da6bce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
+
+#include "cmem-ld.inc"
+
+/* { dg-final { scan-assembler "xld " } } */
+/* { dg-final { scan-assembler "xldw " } } */
+/* { dg-final { scan-assembler "xldb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-5.c b/gcc/testsuite/gcc.target/arc/cmem-5.c
new file mode 100644
index 0000000..ad6904f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
+
+#include "cmem-st.inc"
+
+/* { dg-final { scan-assembler "xst " } } */
+/* { dg-final { scan-assembler "xstw " } } */
+/* { dg-final { scan-assembler "xstb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-6.c b/gcc/testsuite/gcc.target/arc/cmem-6.c
new file mode 100644
index 0000000..24bc39b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-6.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
+
+#include "cmem-ld.inc"
+
+/* { dg-final { scan-assembler "xld " } } */
+/* { dg-final { scan-assembler "xldw " } } */
+/* { dg-final { scan-assembler "xldb " } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-7.c b/gcc/testsuite/gcc.target/arc/cmem-7.c
new file mode 100644
index 0000000..72ee7bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-7.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=nps400 -mcmem" } */
+
+struct some_struct
+{
+ unsigned char a;
+};
+
+unsigned char other_func (unsigned char);
+
+unsigned char
+some_function ()
+{
+ static struct some_struct ss __attribute__ ((section (".cmem")));
+ static struct some_struct tt;
+
+ ss.a = other_func (ss.a);
+ tt.a = other_func (tt.a);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler "xldb \[^\n\]*@ss" } } */
+/* { dg-final { scan-assembler "xstb \[^\n\]*@ss" } } */
+/* { dg-final { scan-assembler-not "xldb \[^\n\]*@tt" } } */
+/* { dg-final { scan-assembler-not "xstb \[^\n\]*@tt" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-ld.inc b/gcc/testsuite/gcc.target/arc/cmem-ld.inc
new file mode 100644
index 0000000..7b51bb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-ld.inc
@@ -0,0 +1,16 @@
+
+struct foo_type
+{
+ unsigned int a;
+ unsigned short b;
+ unsigned char c;
+};
+
+struct foo_type foo __attribute__ ((section (".cmem")));
+
+unsigned int
+f ()
+{
+ unsigned int tmp = foo.a + foo.b + foo.c;
+ return tmp;
+}
diff --git a/gcc/testsuite/gcc.target/arc/cmem-st.inc b/gcc/testsuite/gcc.target/arc/cmem-st.inc
new file mode 100644
index 0000000..30aeace
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/cmem-st.inc
@@ -0,0 +1,18 @@
+
+struct foo_type
+{
+ unsigned int a;
+ unsigned short b;
+ unsigned char c;
+};
+
+struct foo_type foo CMEM_SECTION_ATTR
+
+int
+f ()
+{
+ foo.a = 3;
+ foo.b = 2;
+ foo.c = 1;
+ return 0;
+}
--
2.6.4