From 57aaf0cc9e8bd98c3aac58f21d2ff4f610bc637a Mon Sep 17 00:00:00 2001 From: Monk Chiang Date: Sun, 8 Apr 2018 03:21:08 +0000 Subject: [PATCH] [NDS32] Add intrinsic functions for TLB operation and data prefech. gcc/ * config/nds32/constants.md (unspec_volatile_element): Add values for TLB operation and data prefetch. * config/nds32/nds32-intrinsic.c: Implementation of intrinsic functions for TLB operation and data prefetch. * config/nds32/nds32-intrinsic.md: Likewise. * config/nds32/nds32_intrinsic.h: Likewise. * config/nds32/nds32.c (nds32_dpref_names): Likewise. (nds32_print_operand): Likewise. * config/nds32/nds32.h (nds32_builtins): Likewise. From-SVN: r259216 --- gcc/ChangeLog | 12 ++++ gcc/config/nds32/constants.md | 12 ++++ gcc/config/nds32/nds32-intrinsic.c | 78 +++++++++++++++++++++ gcc/config/nds32/nds32-intrinsic.md | 101 ++++++++++++++++++++++++++++ gcc/config/nds32/nds32.c | 14 ++++ gcc/config/nds32/nds32.h | 12 ++++ gcc/config/nds32/nds32_intrinsic.h | 43 ++++++++++++ 7 files changed, 272 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2430cce0968..1cd8f38d86d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2018-04-08 Monk Chiang + + * config/nds32/constants.md (unspec_volatile_element): Add values for + TLB operation and data prefetch. + * config/nds32/nds32-intrinsic.c: Implementation of intrinsic + functions for TLB operation and data prefetch. + * config/nds32/nds32-intrinsic.md: Likewise. + * config/nds32/nds32_intrinsic.h: Likewise. + * config/nds32/nds32.c (nds32_dpref_names): Likewise. + (nds32_print_operand): Likewise. + * config/nds32/nds32.h (nds32_builtins): Likewise. + 2018-04-07 Thomas Koenig Andrew Pinski diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md index a9593f7894c..50594c3e9dc 100644 --- a/gcc/config/nds32/constants.md +++ b/gcc/config/nds32/constants.md @@ -110,6 +110,18 @@ UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA UNSPEC_VOLATILE_CCTL_IDX_WBINVAL UNSPEC_VOLATILE_CCTL_VA_LCK + UNSPEC_VOLATILE_DPREF_QW + UNSPEC_VOLATILE_DPREF_HW + UNSPEC_VOLATILE_DPREF_W + UNSPEC_VOLATILE_DPREF_DW + UNSPEC_VOLATILE_TLBOP_TRD + UNSPEC_VOLATILE_TLBOP_TWR + UNSPEC_VOLATILE_TLBOP_RWR + UNSPEC_VOLATILE_TLBOP_RWLK + UNSPEC_VOLATILE_TLBOP_UNLK + UNSPEC_VOLATILE_TLBOP_PB + UNSPEC_VOLATILE_TLBOP_INV + UNSPEC_VOLATILE_TLBOP_FLUA UNSPEC_VOLATILE_RELAX_GROUP UNSPEC_VOLATILE_POP25_RETURN ]) diff --git a/gcc/config/nds32/nds32-intrinsic.c b/gcc/config/nds32/nds32-intrinsic.c index 49b03f3f740..c4d75d67466 100644 --- a/gcc/config/nds32/nds32-intrinsic.c +++ b/gcc/config/nds32/nds32-intrinsic.c @@ -305,6 +305,42 @@ nds32_expand_triop_builtin (enum insn_code icode, tree exp, rtx target, return target; } +/* Expand builtins that take three operands and the third is immediate. */ +static rtx +nds32_expand_triopimm_builtin (enum insn_code icode, tree exp, rtx target, + bool return_p, const char *name) +{ + rtx pat; + rtx op0 = nds32_read_argument (exp, 0); + rtx op1 = nds32_read_argument (exp, 1); + rtx op2 = nds32_read_argument (exp, 2); + int op0_num = return_p ? 1 : 0; + int op1_num = return_p ? 2 : 1; + int op2_num = return_p ? 3 : 2; + + if (return_p) + target = nds32_legitimize_target (icode, target); + + if (!nds32_check_constant_argument (icode, op2_num, op2, name)) + return NULL_RTX; + + op0 = nds32_legitimize_argument (icode, op0_num, op0); + op1 = nds32_legitimize_argument (icode, op1_num, op1); + op2 = nds32_legitimize_argument (icode, op2_num, op2); + + /* Emit and return the new instruction. */ + if (return_p) + pat = GEN_FCN (icode) (target, op0, op1, op2); + else + pat = GEN_FCN (icode) (op0, op1, op2); + + if (! pat) + return NULL_RTX; + + emit_insn (pat); + return target; +} + /* Expand builtins for load. */ static rtx nds32_expand_builtin_load (enum insn_code icode, tree exp, rtx target) @@ -463,6 +499,7 @@ static struct builtin_description bdesc_1arg[] = NDS32_BUILTIN(clzsi2, "clz", CLZ) NDS32_BUILTIN(unspec_clo, "clo", CLO) NDS32_BUILTIN(unspec_wsbh, "wsbh", WSBH) + NDS32_BUILTIN(unspec_tlbop_pb, "tlbop_pb",TLBOP_PB) NDS32_BUILTIN(unaligned_load_hw, "unaligned_load_hw", UALOAD_HW) NDS32_BUILTIN(unaligned_loadsi, "unaligned_load_w", UALOAD_W) NDS32_BUILTIN(unaligned_loaddi, "unaligned_load_dw", UALOAD_DW) @@ -473,6 +510,12 @@ static struct builtin_description bdesc_1arg[] = NDS32_NO_TARGET_BUILTIN(unspec_jral_ton, "jral_ton", JRAL_TON) NDS32_NO_TARGET_BUILTIN(unspec_ret_toff, "ret_toff", RET_TOFF) NDS32_NO_TARGET_BUILTIN(unspec_jral_iton, "jral_iton",JRAL_ITON) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_trd, "tlbop_trd", TLBOP_TRD) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_twr, "tlbop_twr", TLBOP_TWR) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwr, "tlbop_rwr", TLBOP_RWR) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwlk, "tlbop_rwlk", TLBOP_RWLK) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_unlk, "tlbop_unlk", TLBOP_UNLK) + NDS32_NO_TARGET_BUILTIN(unspec_tlbop_inv, "tlbop_inv", TLBOP_INV) NDS32_NO_TARGET_BUILTIN(unspec_ret_itoff, "ret_itoff", RET_ITOFF) NDS32_NO_TARGET_BUILTIN(unspec_set_current_sp, "set_current_sp", SET_CURRENT_SP) @@ -534,6 +577,15 @@ static struct builtin_description bdesc_3arg[] = NDS32_NO_TARGET_BUILTIN(bsp, "bsp", BSP) }; +/* Three-argument intrinsics with an immediate third argument. */ +static struct builtin_description bdesc_3argimm[] = +{ + NDS32_NO_TARGET_BUILTIN(prefetch_qw, "prefetch_qw", DPREF_QW) + NDS32_NO_TARGET_BUILTIN(prefetch_hw, "prefetch_hw", DPREF_HW) + NDS32_NO_TARGET_BUILTIN(prefetch_w, "prefetch_w", DPREF_W) + NDS32_NO_TARGET_BUILTIN(prefetch_dw, "prefetch_dw", DPREF_DW) +}; + /* Intrinsics that load a value. */ static struct builtin_description bdesc_load[] = { @@ -717,6 +769,9 @@ nds32_expand_builtin_impl (tree exp, case NDS32_BUILTIN_SCHE_BARRIER: emit_insn (gen_blockage ()); return target; + case NDS32_BUILTIN_TLBOP_FLUA: + emit_insn (gen_unspec_tlbop_flua ()); + return target; case NDS32_BUILTIN_SCW: return nds32_expand_scw_builtin (CODE_FOR_unspec_volatile_scw, exp, target); @@ -752,6 +807,11 @@ nds32_expand_builtin_impl (tree exp, if (d->code == fcode) return nds32_expand_triop_builtin (d->icode, exp, target, d->return_p); + for (i = 0, d = bdesc_3argimm; i < ARRAY_SIZE (bdesc_3argimm); i++, d++) + if (d->code == fcode) + return nds32_expand_triopimm_builtin (d->icode, exp, target, + d->return_p, d->name); + 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); @@ -876,6 +936,13 @@ nds32_init_builtins_impl (void) ADD_NDS32_BUILTIN3 ("cctl_idx_write", void, integer, unsigned, unsigned, CCTL_IDX_WRITE); + /* PREFETCH */ + ADD_NDS32_BUILTIN3 ("dpref_qw", void, ptr_uchar, unsigned, integer, DPREF_QW); + ADD_NDS32_BUILTIN3 ("dpref_hw", void, ptr_ushort, unsigned, integer, + DPREF_HW); + ADD_NDS32_BUILTIN3 ("dpref_w", void, ptr_uint, unsigned, integer, DPREF_W); + ADD_NDS32_BUILTIN3 ("dpref_dw", void, ptr_ulong, unsigned, integer, DPREF_DW); + /* Performance Extension */ ADD_NDS32_BUILTIN1 ("pe_abs", integer, integer, ABS); ADD_NDS32_BUILTIN2 ("pe_ave", integer, integer, integer, AVE); @@ -933,6 +1000,17 @@ nds32_init_builtins_impl (void) /* Schedule Barrier */ ADD_NDS32_BUILTIN0 ("schedule_barrier", void, SCHE_BARRIER); + + /* TLBOP */ + ADD_NDS32_BUILTIN1 ("tlbop_trd", void, unsigned, TLBOP_TRD); + ADD_NDS32_BUILTIN1 ("tlbop_twr", void, unsigned, TLBOP_TWR); + ADD_NDS32_BUILTIN1 ("tlbop_rwr", void, unsigned, TLBOP_RWR); + ADD_NDS32_BUILTIN1 ("tlbop_rwlk", void, unsigned, TLBOP_RWLK); + ADD_NDS32_BUILTIN1 ("tlbop_unlk", void, unsigned, TLBOP_UNLK); + ADD_NDS32_BUILTIN1 ("tlbop_pb", unsigned, unsigned, TLBOP_PB); + ADD_NDS32_BUILTIN1 ("tlbop_inv", void, unsigned, TLBOP_INV); + ADD_NDS32_BUILTIN0 ("tlbop_flua", void, TLBOP_FLUA); + /* Unaligned Load/Store */ ADD_NDS32_BUILTIN1 ("unaligned_load_hw", short_unsigned, ptr_ushort, UALOAD_HW); diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md index 52437a47e61..9975e4af498 100644 --- a/gcc/config/nds32/nds32-intrinsic.md +++ b/gcc/config/nds32/nds32-intrinsic.md @@ -340,6 +340,47 @@ [(set_attr "type" "mmu")] ) +;;PREFETCH + +(define_insn "prefetch_qw" + [(unspec_volatile:QI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "nonmemory_operand" "r") + (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_QW)] + "" + "dpref\t%Z2, [%0 + %1]" + [(set_attr "type" "misc")] +) + +(define_insn "prefetch_hw" + [(unspec_volatile:HI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "nonmemory_operand" "r") + (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_HW)] + "" + "dpref\t%Z2, [%0 + (%1<<1)]" + [(set_attr "type" "misc")] +) + +(define_insn "prefetch_w" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" " r, r") + (match_operand:SI 1 "nonmemory_operand" "Is15, r") + (match_operand:SI 2 "immediate_operand" " i, i")] UNSPEC_VOLATILE_DPREF_W)] + "" + "@ + dprefi.w\t%Z2, [%0 + %1] + dpref\t%Z2, [%0 + (%1<<2)]" + [(set_attr "type" "misc")] +) + +(define_insn "prefetch_dw" + [(unspec_volatile:DI [(match_operand:SI 0 "register_operand" " r, r") + (match_operand:SI 1 "nonmemory_operand" "Is15, r") + (match_operand:SI 2 "immediate_operand" " i, i")] UNSPEC_VOLATILE_DPREF_DW)] + "" + "@ + dprefi.d\t%Z2, [%0 + %1] + dpref\t%Z2, [%0 + (%1<<3)]" + [(set_attr "type" "misc")] +) ;; Performance Extension @@ -734,6 +775,66 @@ [(set_attr "type" "alu") (set_attr "length" "4")] ) + +;; TLBOP Intrinsic + +(define_insn "unspec_tlbop_trd" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TRD)] + "" + "tlbop\t%0, TRD" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_twr" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TWR)] + "" + "tlbop\t%0, TWR" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_rwr" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWR)] + "" + "tlbop\t%0, RWR" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_rwlk" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWLK)] + "" + "tlbop\t%0, RWLK" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_unlk" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_UNLK)] + "" + "tlbop\t%0, UNLK" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_pb" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_PB))] + "" + "tlbop\t%0, %1, PB" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_inv" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_INV)] + "" + "tlbop\t%0, INV" + [(set_attr "type" "mmu")] +) + +(define_insn "unspec_tlbop_flua" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_TLBOP_FLUA)] + "" + "tlbop\tFLUA" + [(set_attr "type" "mmu")] +) + ;;Unaligned Load/Store (define_expand "unaligned_load_hw" diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 0ad0e858876..9bd7f3fdb0c 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -266,6 +266,16 @@ static const char * const nds32_cctl_names[] = "L1I_IX_WWD" }; +static const char * const nds32_dpref_names[] = +{ + "SRD", + "MRD", + "SWR", + "MWR", + "PTE", + "CLWR" +}; + /* Defining register allocation order for performance. We want to allocate callee-saved registers after others. It may be used by nds32_adjust_reg_alloc_order(). */ @@ -3002,6 +3012,10 @@ nds32_print_operand (FILE *stream, rtx x, int code) fprintf (stream, "%s", nds32_cctl_names[op_value + 16]); return; + case 'Z': /* dpref */ + fprintf (stream, "%s", nds32_dpref_names[op_value]); + return; + default : /* Unknown flag. */ output_operand_lossage ("invalid operand output code"); diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h index 3bb5a720896..13664f187e5 100644 --- a/gcc/config/nds32/nds32.h +++ b/gcc/config/nds32/nds32.h @@ -466,6 +466,18 @@ enum nds32_builtins NDS32_BUILTIN_CCTL_L1D_INVALALL, NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL, NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL, + NDS32_BUILTIN_DPREF_QW, + NDS32_BUILTIN_DPREF_HW, + NDS32_BUILTIN_DPREF_W, + NDS32_BUILTIN_DPREF_DW, + NDS32_BUILTIN_TLBOP_TRD, + NDS32_BUILTIN_TLBOP_TWR, + NDS32_BUILTIN_TLBOP_RWR, + NDS32_BUILTIN_TLBOP_RWLK, + NDS32_BUILTIN_TLBOP_UNLK, + NDS32_BUILTIN_TLBOP_PB, + NDS32_BUILTIN_TLBOP_INV, + NDS32_BUILTIN_TLBOP_FLUA, NDS32_BUILTIN_UALOAD_HW, NDS32_BUILTIN_UALOAD_W, NDS32_BUILTIN_UALOAD_DW, diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h index 01e1a8e3e60..3feb587a8e2 100644 --- a/gcc/config/nds32/nds32_intrinsic.h +++ b/gcc/config/nds32/nds32_intrinsic.h @@ -226,6 +226,16 @@ enum nds32_cctl_idxwrite __NDS32_CCTL_L1I_IX_WWD__ }; +enum nds32_dpref +{ + __NDS32_DPREF_SRD__, + __NDS32_DPREF_MRD__, + __NDS32_DPREF_SWR__, + __NDS32_DPREF_MWR__, + __NDS32_DPREF_PTE__, + __NDS32_DPREF_CLWR__ +}; + /* ------------------------------------------------------------------------ */ /* Define intrinsic register name macro for compatibility. */ @@ -409,6 +419,14 @@ enum nds32_cctl_idxwrite #define NDS32_CCTL_L1D_IX_WWD __NDS32_CCTL_L1D_IX_WWD__ #define NDS32_CCTL_L1I_IX_WTAG __NDS32_CCTL_L1I_IX_WTAG__ #define NDS32_CCTL_L1I_IX_WWD __NDS32_CCTL_L1I_IX_WWD__ + +#define NDS32_DPREF_SRD __NDS32_DPREF_SRD__ +#define NDS32_DPREF_MRD __NDS32_DPREF_MRD__ +#define NDS32_DPREF_SWR __NDS32_DPREF_SWR__ +#define NDS32_DPREF_MWR __NDS32_DPREF_MWR__ +#define NDS32_DPREF_PTE __NDS32_DPREF_PTE__ +#define NDS32_DPREF_CLWR __NDS32_DPREF_CLWR__ + /* ------------------------------------------------------------------------ */ @@ -501,6 +519,14 @@ enum nds32_cctl_idxwrite (__builtin_nds32_svs ((a), (b))) #define __nds32__sva(a, b) \ (__builtin_nds32_sva ((a), (b))) +#define __nds32__dpref_qw(a, b, subtype) \ + (__builtin_nds32_dpref_qw ((a), (b), (subtype))) +#define __nds32__dpref_hw(a, b, subtype) \ + (__builtin_nds32_dpref_hw ((a), (b), (subtype))) +#define __nds32__dpref_w(a, b, subtype) \ + (__builtin_nds32_dpref_w ((a), (b), (subtype))) +#define __nds32__dpref_dw(a, b, subtype) \ + (__builtin_nds32_dpref_dw ((a), (b), (subtype))) #define __nds32__teqz(a, swid) \ (__builtin_nds32_teqz ((a), (swid))) @@ -573,4 +599,21 @@ enum nds32_cctl_idxwrite #define __nds32__fmfcfg() \ (__builtin_nds32_fmfcfg()) +#define __nds32__tlbop_trd(a) \ + (__builtin_nds32_tlbop_trd ((a))) +#define __nds32__tlbop_twr(a) \ + (__builtin_nds32_tlbop_twr ((a))) +#define __nds32__tlbop_rwr(a) \ + (__builtin_nds32_tlbop_rwr ((a))) +#define __nds32__tlbop_rwlk(a) \ + (__builtin_nds32_tlbop_rwlk ((a))) +#define __nds32__tlbop_unlk(a) \ + (__builtin_nds32_tlbop_unlk ((a))) +#define __nds32__tlbop_pb(a) \ + (__builtin_nds32_tlbop_pb ((a))) +#define __nds32__tlbop_inv(a) \ + (__builtin_nds32_tlbop_inv ((a))) +#define __nds32__tlbop_flua() \ +(__builtin_nds32_tlbop_flua()) + #endif /* nds32_intrinsic.h */ -- 2.30.2