[NDS32] Add intrinsic functions for atomic load/store and memory sync.
authorMonk Chiang <sh.chiang04@gmail.com>
Sat, 7 Apr 2018 07:40:49 +0000 (07:40 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Sat, 7 Apr 2018 07:40:49 +0000 (07:40 +0000)
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

gcc/ChangeLog
gcc/config/nds32/constants.md
gcc/config/nds32/nds32-intrinsic.c
gcc/config/nds32/nds32-intrinsic.md
gcc/config/nds32/nds32.h
gcc/config/nds32/nds32_intrinsic.h

index 85cf26a8800e172f86833f3d4d619d54decd76b9..ffc87d710327ab369d2a3a77b6394cadb8d65dc6 100644 (file)
@@ -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
index 92181fd850b162f3fcab163752675c57a5cfab1a..77d96892102579bb5227b6d302eeaf639d22f04d 100644 (file)
   UNSPEC_FFB
   UNSPEC_FFMISM
   UNSPEC_FLMISM
+  UNSPEC_LWUP
+  UNSPEC_LBUP
+  UNSPEC_SWUP
+  UNSPEC_SBUP
   UNSPEC_UALOAD_HW
   UNSPEC_UALOAD_W
   UNSPEC_UALOAD_DW
 (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
index 3dc9aa29aadab83483309f94462cddf73f25d04b..fb67e6fe5d546fd91d9bbf3313e3a771e0c9543e 100644 (file)
@@ -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);
index d9f1eb07dbec3aa11bcf20758d853dcd61b8da81..5b58fc9229af1bbc4f833d970f4e865968605d2f 100644 (file)
    (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)]
   [(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
 
index 353034eb828e07f3c55988e721e1d99a9bff6308..8f1ac32c704ab777154a374d800818fd34636cc8 100644 (file)
@@ -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,
index 24f6516d16e784f6596e81551cdbaf2a3eae0cb0..4aa299c88326f095f065025b74805536c7ccc596 100644 (file)
@@ -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) \