aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonk Chiang <sh.chiang04@gmail.com>2018-04-07 07:40:49 +0000
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>2018-04-07 07:40:49 +0000
commit154e3ea6f70cbbea4355c7c7b90a626d08eed3de (patch)
tree519a0f9cbdc64cce97bc8bc622c2e2daeca63e0c
parenteda71a9eeaaf1ea16ba56d8cc5a4eb194f6025f7 (diff)
downloadgcc-154e3ea6f70cbbea4355c7c7b90a626d08eed3de.zip
gcc-154e3ea6f70cbbea4355c7c7b90a626d08eed3de.tar.gz
gcc-154e3ea6f70cbbea4355c7c7b90a626d08eed3de.tar.bz2
[NDS32] Add intrinsic functions for atomic load/store and memory sync.
gcc/ * config/nds32/constants.md (unspec_element, unspec_volatile_element): Add enum values for atomic load/store and memory sync. * config/nds32/nds32-intrinsic.c: Implementation for atomic load/store and memory sync. * config/nds32/nds32-intrinsic.md: Likewise. * config/nds32/nds32_intrinsic.h: Likewise. * config/nds32/nds32.h (nds32_builtins): Likewise. From-SVN: r259207
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/nds32/constants.md10
-rw-r--r--gcc/config/nds32/nds32-intrinsic.c167
-rw-r--r--gcc/config/nds32/nds32-intrinsic.md104
-rw-r--r--gcc/config/nds32/nds32.h11
-rw-r--r--gcc/config/nds32/nds32_intrinsic.h22
6 files changed, 324 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85cf26a..ffc87d7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2018-04-07 Monk Chiang <sh.chiang04@gmail.com>
+
+ * config/nds32/constants.md (unspec_element, unspec_volatile_element):
+ Add enum values for atomic load/store and memory sync.
+ * config/nds32/nds32-intrinsic.c: Implementation for atomic load/store
+ and memory sync.
+ * config/nds32/nds32-intrinsic.md: Likewise.
+ * config/nds32/nds32_intrinsic.h: Likewise.
+ * config/nds32/nds32.h (nds32_builtins): Likewise.
+
2018-04-07 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/85257
diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md
index 92181fd..77d9689 100644
--- a/gcc/config/nds32/constants.md
+++ b/gcc/config/nds32/constants.md
@@ -40,6 +40,10 @@
UNSPEC_FFB
UNSPEC_FFMISM
UNSPEC_FLMISM
+ UNSPEC_LWUP
+ UNSPEC_LBUP
+ UNSPEC_SWUP
+ UNSPEC_SBUP
UNSPEC_UALOAD_HW
UNSPEC_UALOAD_W
UNSPEC_UALOAD_DW
@@ -52,6 +56,10 @@
(define_c_enum "unspec_volatile_element" [
UNSPEC_VOLATILE_ISYNC
UNSPEC_VOLATILE_ISB
+ UNSPEC_VOLATILE_DSB
+ UNSPEC_VOLATILE_MSYNC
+ UNSPEC_VOLATILE_MSYNC_ALL
+ UNSPEC_VOLATILE_MSYNC_STORE
UNSPEC_VOLATILE_MFSR
UNSPEC_VOLATILE_MFUSR
UNSPEC_VOLATILE_MTSR
@@ -61,6 +69,8 @@
UNSPEC_VOLATILE_FMFCSR
UNSPEC_VOLATILE_FMTCSR
UNSPEC_VOLATILE_FMFCFG
+ UNSPEC_VOLATILE_LLW
+ UNSPEC_VOLATILE_SCW
UNSPEC_VOLATILE_CCTL_L1D_INVALALL
UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL
UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL
diff --git a/gcc/config/nds32/nds32-intrinsic.c b/gcc/config/nds32/nds32-intrinsic.c
index 3dc9aa2..fb67e6f 100644
--- a/gcc/config/nds32/nds32-intrinsic.c
+++ b/gcc/config/nds32/nds32-intrinsic.c
@@ -135,6 +135,23 @@ nds32_check_constant_argument (enum insn_code icode, int opnum, rtx opval,
return true;
}
+/* Expand builtins that return target. */
+static rtx
+nds32_expand_noarg_builtin (enum insn_code icode, rtx target)
+{
+ rtx pat;
+
+ target = nds32_legitimize_target (icode, target);
+
+ /* Emit and return the new instruction. */
+ pat = GEN_FCN (icode) (target);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
/* Expand builtins that take one operand. */
static rtx
nds32_expand_unop_builtin (enum insn_code icode, tree exp, rtx target,
@@ -222,6 +239,61 @@ nds32_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
return target;
}
+/* Expand builtins for load. */
+static rtx
+nds32_expand_builtin_load (enum insn_code icode, tree exp, rtx target)
+{
+ /* Load address format is [$ra + $rb],
+ but input arguments not enough,
+ so we need another temp register as $rb.
+ Generating assembly code:
+ movi $temp, 0
+ llw $rt, [$ra + $temp] */
+ rtx pat;
+ rtx op0 = nds32_read_argument (exp, 0);
+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
+
+ target = nds32_legitimize_target (icode, target);
+ op0 = nds32_legitimize_argument (icode, 1, op0);
+
+ /* Emit and return the new instruction. */
+ pat = GEN_FCN (icode) (target, op0, addr_helper);
+ if (!pat)
+ return NULL_RTX;
+
+ emit_move_insn (addr_helper, GEN_INT (0));
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand builtins for store. */
+static rtx
+nds32_expand_builtin_store (enum insn_code icode, tree exp, rtx target)
+{
+ /* Store address format is [$ra + $rb],
+ but input arguments not enough,
+ so we need another temp register as $rb.
+ Generating assembly code:
+ movi $temp, 0
+ store $rt, [$ra + $temp] */
+ rtx pat;
+ rtx op0 = nds32_read_argument (exp, 0);
+ rtx op1 = nds32_read_argument (exp, 1);
+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
+
+ op0 = nds32_legitimize_argument (icode, 0, op0);
+ op1 = nds32_legitimize_argument (icode, 2, op1);
+
+ /* Emit and return the new instruction. */
+ pat = GEN_FCN (icode) (op0, addr_helper, op1);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_move_insn (addr_helper, GEN_INT (0));
+ emit_insn (pat);
+ return target;
+}
+
/* Expand cctl builtins. */
static rtx
nds32_expand_cctl_builtin (enum insn_code icode, tree exp, rtx target,
@@ -263,6 +335,36 @@ nds32_expand_cctl_builtin (enum insn_code icode, tree exp, rtx target,
return target;
}
+/* Expand scw builtins. */
+static rtx
+nds32_expand_scw_builtin (enum insn_code icode, tree exp, rtx target)
+{
+ /* SCW address format is [$ra + $rb], but input arguments not enough,
+ so we need another temp register as $rb.
+ Generating assembly code:
+ movi $temp, 0
+ scw $rt, [$ra + $temp] */
+ rtx pat;
+ rtx op0 = nds32_read_argument (exp, 0);
+ rtx op1 = nds32_read_argument (exp, 1);
+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
+
+ target = nds32_legitimize_target (icode, target);
+ op0 = nds32_legitimize_argument (icode, 1, op0);
+ op1 = nds32_legitimize_argument (icode, 2, op1);
+
+ /* Emit and return the new instruction. */
+ pat = GEN_FCN (icode) (target, op0, addr_helper, target);
+
+ if (!pat)
+ return NULL_RTX;
+
+ emit_move_insn (addr_helper, GEN_INT (0));
+ emit_move_insn (target, op1);
+ emit_insn (pat);
+ return target;
+}
+
struct builtin_description
{
const enum insn_code icode;
@@ -313,6 +415,8 @@ static struct builtin_description bdesc_2arg[] =
NDS32_BUILTIN(unspec_ffb, "ffb", FFB)
NDS32_BUILTIN(unspec_ffmism, "ffmsim", FFMISM)
NDS32_BUILTIN(unspec_flmism, "flmism", FLMISM)
+ NDS32_NO_TARGET_BUILTIN(mtsr_isb, "mtsr_isb", MTSR_ISB)
+ NDS32_NO_TARGET_BUILTIN(mtsr_dsb, "mtsr_dsb", MTSR_DSB)
NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtsr, "mtsr", MTSR)
NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtusr, "mtusr", MTUSR)
NDS32_NO_TARGET_BUILTIN(unaligned_store_hw, "unaligned_store_hw", UASTORE_HW)
@@ -321,6 +425,20 @@ static struct builtin_description bdesc_2arg[] =
};
+/* Intrinsics that load a value. */
+static struct builtin_description bdesc_load[] =
+{
+ NDS32_BUILTIN(unspec_volatile_llw, "llw", LLW)
+ NDS32_BUILTIN(unspec_lwup, "lwup", LWUP)
+ NDS32_BUILTIN(unspec_lbup, "lbup", LBUP)
+};
+
+/* Intrinsics that store a value. */
+static struct builtin_description bdesc_store[] =
+{
+ NDS32_BUILTIN(unspec_swup, "swup", SWUP)
+ NDS32_BUILTIN(unspec_sbup, "sbup", SBUP)
+};
static struct builtin_description bdesc_cctl[] =
{
@@ -375,6 +493,21 @@ nds32_expand_builtin_impl (tree exp,
return NULL_RTX;
}
break;
+
+ /* Load and Store */
+ case NDS32_BUILTIN_LLW:
+ case NDS32_BUILTIN_LWUP:
+ case NDS32_BUILTIN_LBUP:
+ case NDS32_BUILTIN_SCW:
+ case NDS32_BUILTIN_SWUP:
+ case NDS32_BUILTIN_SBUP:
+ if (TARGET_ISA_V3M)
+ {
+ error ("this builtin function not support "
+ "on the v3m toolchain");
+ return NULL_RTX;
+ }
+ break;
/* String Extension */
case NDS32_BUILTIN_FFB:
case NDS32_BUILTIN_FFMISM:
@@ -396,6 +529,15 @@ nds32_expand_builtin_impl (tree exp,
case NDS32_BUILTIN_ISB:
emit_insn (gen_unspec_volatile_isb ());
return target;
+ case NDS32_BUILTIN_DSB:
+ emit_insn (gen_unspec_dsb ());
+ return target;
+ case NDS32_BUILTIN_MSYNC_ALL:
+ emit_insn (gen_unspec_msync_all ());
+ return target;
+ case NDS32_BUILTIN_MSYNC_STORE:
+ emit_insn (gen_unspec_msync_store ());
+ return target;
case NDS32_BUILTIN_SETGIE_EN:
emit_insn (gen_unspec_volatile_setgie_en ());
return target;
@@ -410,6 +552,9 @@ nds32_expand_builtin_impl (tree exp,
case NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL:
emit_insn (gen_cctl_l1d_wball_one_lvl());
return target;
+ case NDS32_BUILTIN_SCW:
+ return nds32_expand_scw_builtin (CODE_FOR_unspec_volatile_scw,
+ exp, target);
return target;
default:
break;
@@ -433,6 +578,14 @@ nds32_expand_builtin_impl (tree exp,
if (d->code == fcode)
return nds32_expand_binop_builtin (d->icode, exp, target, d->return_p);
+ for (i = 0, d = bdesc_load; i < ARRAY_SIZE (bdesc_load); i++, d++)
+ if (d->code == fcode)
+ return nds32_expand_builtin_load (d->icode, exp, target);
+
+ for (i = 0, d = bdesc_store; i < ARRAY_SIZE (bdesc_store); i++, d++)
+ if (d->code == fcode)
+ return nds32_expand_builtin_store (d->icode, exp, target);
+
for (i = 0, d = bdesc_cctl; i < ARRAY_SIZE (bdesc_cctl); i++, d++)
if (d->code == fcode)
return nds32_expand_cctl_builtin (d->icode, exp, target,
@@ -492,6 +645,7 @@ nds32_init_builtins_impl (void)
NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
/* Looking for return type and argument can be found in tree.h file. */
+ tree ptr_uchar_type_node = build_pointer_type (unsigned_char_type_node);
tree ptr_ushort_type_node = build_pointer_type (short_unsigned_type_node);
tree ptr_uint_type_node = build_pointer_type (unsigned_type_node);
tree ptr_ulong_type_node = build_pointer_type (long_long_unsigned_type_node);
@@ -499,11 +653,16 @@ nds32_init_builtins_impl (void)
/* Cache. */
ADD_NDS32_BUILTIN1 ("isync", void, ptr_uint, ISYNC);
ADD_NDS32_BUILTIN0 ("isb", void, ISB);
+ ADD_NDS32_BUILTIN0 ("dsb", void, DSB);
+ ADD_NDS32_BUILTIN0 ("msync_all", void, MSYNC_ALL);
+ ADD_NDS32_BUILTIN0 ("msync_store", void, MSYNC_STORE);
/* Register Transfer. */
ADD_NDS32_BUILTIN1 ("mfsr", unsigned, integer, MFSR);
ADD_NDS32_BUILTIN1 ("mfusr", unsigned, integer, MFUSR);
ADD_NDS32_BUILTIN2 ("mtsr", void, unsigned, integer, MTSR);
+ ADD_NDS32_BUILTIN2 ("mtsr_isb", void, unsigned, integer, MTSR_ISB);
+ ADD_NDS32_BUILTIN2 ("mtsr_dsb", void, unsigned, integer, MTSR_DSB);
ADD_NDS32_BUILTIN2 ("mtusr", void, unsigned, integer, MTUSR);
/* FPU Register Transfer. */
@@ -519,6 +678,14 @@ nds32_init_builtins_impl (void)
ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN);
ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS);
+ /* Load and Store */
+ ADD_NDS32_BUILTIN1 ("llw", unsigned, ptr_uint, LLW);
+ ADD_NDS32_BUILTIN1 ("lwup", unsigned, ptr_uint, LWUP);
+ ADD_NDS32_BUILTIN1 ("lbup", char, ptr_uchar, LBUP);
+ ADD_NDS32_BUILTIN2 ("scw", unsigned, ptr_uint, unsigned, SCW);
+ ADD_NDS32_BUILTIN2 ("swup", void, ptr_uint, unsigned, SWUP);
+ ADD_NDS32_BUILTIN2 ("sbup", void, ptr_uchar, char, SBUP);
+
/* CCTL */
ADD_NDS32_BUILTIN0 ("cctl_l1d_invalall", void, CCTL_L1D_INVALALL);
ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_alvl", void, CCTL_L1D_WBALL_ALVL);
diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md
index d9f1eb0..5b58fc9 100644
--- a/gcc/config/nds32/nds32-intrinsic.md
+++ b/gcc/config/nds32/nds32-intrinsic.md
@@ -40,6 +40,26 @@
(set_attr "length" "4")]
)
+(define_expand "mtsr_isb"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "immediate_operand" ""))]
+ ""
+{
+ emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1]));
+ emit_insn (gen_unspec_volatile_isb());
+ DONE;
+})
+
+(define_expand "mtsr_dsb"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "immediate_operand" ""))]
+ ""
+{
+ emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1]));
+ emit_insn (gen_unspec_dsb());
+ DONE;
+})
+
(define_insn "unspec_volatile_mtsr"
[(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)]
@@ -162,6 +182,90 @@
[(set_attr "type" "misc")]
)
+(define_insn "unspec_dsb"
+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_DSB)]
+ ""
+ "dsb"
+ [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_msync"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_MSYNC)]
+ ""
+ "msync\t%0"
+ [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_msync_all"
+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_ALL)]
+ ""
+ "msync\tall"
+ [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_msync_store"
+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_STORE)]
+ ""
+ "msync\tstore"
+ [(set_attr "type" "misc")]
+)
+
+;; Load and Store
+
+(define_insn "unspec_volatile_llw"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_VOLATILE_LLW))]
+ ""
+ "llw\t%0, [%1 + %2]"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_lwup"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LWUP))]
+ ""
+ "lwup\t%0, [%1 + %2]"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_lbup"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LBUP))]
+ ""
+ "lbup\t%0, [%1 + %2]"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_volatile_scw"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))
+ (match_operand:SI 3 "register_operand" "0")] UNSPEC_VOLATILE_SCW))]
+ ""
+ "scw\t%0, [%1 + %2]"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_swup"
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r")))
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SWUP))]
+ ""
+ "swup\t%2, [%0 + %1]"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_sbup"
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r")))
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SBUP))]
+ ""
+ "sbup\t%2, [%0 + %1]"
+ [(set_attr "length" "4")]
+)
;; CCTL
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
index 353034e..8f1ac32 100644
--- a/gcc/config/nds32/nds32.h
+++ b/gcc/config/nds32/nds32.h
@@ -436,9 +436,14 @@ enum nds32_builtins
{
NDS32_BUILTIN_ISYNC,
NDS32_BUILTIN_ISB,
+ NDS32_BUILTIN_DSB,
+ NDS32_BUILTIN_MSYNC_ALL,
+ NDS32_BUILTIN_MSYNC_STORE,
NDS32_BUILTIN_MFSR,
NDS32_BUILTIN_MFUSR,
NDS32_BUILTIN_MTSR,
+ NDS32_BUILTIN_MTSR_ISB,
+ NDS32_BUILTIN_MTSR_DSB,
NDS32_BUILTIN_MTUSR,
NDS32_BUILTIN_SETGIE_EN,
NDS32_BUILTIN_SETGIE_DIS,
@@ -452,6 +457,12 @@ enum nds32_builtins
NDS32_BUILTIN_FFB,
NDS32_BUILTIN_FFMISM,
NDS32_BUILTIN_FLMISM,
+ NDS32_BUILTIN_LLW,
+ NDS32_BUILTIN_LWUP,
+ NDS32_BUILTIN_LBUP,
+ NDS32_BUILTIN_SCW,
+ NDS32_BUILTIN_SWUP,
+ NDS32_BUILTIN_SBUP,
NDS32_BUILTIN_CCTL_VA_LCK,
NDS32_BUILTIN_CCTL_IDX_WBINVAL,
NDS32_BUILTIN_CCTL_VA_WBINVAL_L1,
diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h
index 24f6516..4aa299c 100644
--- a/gcc/config/nds32/nds32_intrinsic.h
+++ b/gcc/config/nds32/nds32_intrinsic.h
@@ -411,6 +411,20 @@ enum nds32_cctl_idxwrite
#define NDS32_CCTL_L1I_IX_WWD __NDS32_CCTL_L1I_IX_WWD__
/* ------------------------------------------------------------------------ */
+
+/* Map __nds32__xxx() to __builtin_xxx() functions for compatibility. */
+#define __nds32__llw(a) \
+ (__builtin_nds32_llw ((a)))
+#define __nds32__lwup(a) \
+ (__builtin_nds32_lwup ((a)))
+#define __nds32__lbup(a) \
+ (__builtin_nds32_lbup ((a)))
+#define __nds32__scw(a, b) \
+ (__builtin_nds32_scw ((a), (b)))
+#define __nds32__swup(a, b) \
+ (__builtin_nds32_swup ((a), (b)))
+#define __nds32__sbup(a, b) \
+ (__builtin_nds32_sbup ((a), (b)))
#define __nds32__cctlva_lck(subtype, va) \
(__builtin_nds32_cctl_va_lck ((subtype), (va)))
#define __nds32__cctlidx_wbinval(subtype, idx) \
@@ -430,6 +444,14 @@ enum nds32_cctl_idxwrite
#define __nds32__cctl_l1d_wball_one_lvl() \
(__builtin_nds32_cctl_l1d_wball_one_lvl())
+#define __nds32__dsb() \
+ (__builtin_nds32_dsb())
+#define __nds32__isb() \
+ (__builtin_nds32_isb())
+#define __nds32__msync_store() \
+ (__builtin_nds32_msync_store())
+#define __nds32__msync_all() \
+ (__builtin_nds32_msync_all())
#define __nds32__fcpynsd(a, b) \
(__builtin_nds32_fcpynsd ((a), (b)))
#define __nds32__fcpynss(a, b) \