From: Monk Chiang Date: Sat, 7 Apr 2018 07:40:49 +0000 (+0000) Subject: [NDS32] Add intrinsic functions for atomic load/store and memory sync. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=154e3ea6f70cbbea4355c7c7b90a626d08eed3de;p=gcc.git [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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85cf26a8800..ffc87d71032 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2018-04-07 Monk Chiang + + * 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 PR tree-optimization/85257 diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md index 92181fd850b..77d96892102 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 3dc9aa29aad..fb67e6fe5d5 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 d9f1eb07dbe..5b58fc9229a 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 353034eb828..8f1ac32c704 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 24f6516d16e..4aa299c8832 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) \