+2018-04-07 Monk Chiang <sh.chiang04@gmail.com>
+
+ * config/nds32/constants.md (unspec_volatile_element): Add cache
+ control enum values.
+ * config/nds32/nds32-intrinsic.c: Add cache control expand functions.
+ * config/nds32/nds32-intrinsic.md: Add cache control patterns.
+ * config/nds32/nds32.c (nds32_cctl_names): New.
+ (nds32_print_operand): Handle cache control register names.
+ * config/nds32/nds32.h (nds32_builtins): New enum values.
+ * config/nds32/nds32_intrinsic.h: Add cache control enum types and
+ macros.
+ * config/nds32/nds32.md (type): Add mmu.
+ * config/nds32/pipelines.md (simple_insn): Add mmu.
+
2018-04-07 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.md (type): Remove call.
UNSPEC_VOLATILE_FMFCSR
UNSPEC_VOLATILE_FMTCSR
UNSPEC_VOLATILE_FMFCFG
-
+ UNSPEC_VOLATILE_CCTL_L1D_INVALALL
+ UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL
+ UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL
+ UNSPEC_VOLATILE_CCTL_IDX_WRITE
+ UNSPEC_VOLATILE_CCTL_IDX_READ
+ UNSPEC_VOLATILE_CCTL_VA_WBINVAL_L1
+ UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA
+ UNSPEC_VOLATILE_CCTL_IDX_WBINVAL
+ UNSPEC_VOLATILE_CCTL_VA_LCK
UNSPEC_VOLATILE_RELAX_GROUP
UNSPEC_VOLATILE_POP25_RETURN
])
return target;
}
+/* Expand cctl builtins. */
+static rtx
+nds32_expand_cctl_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);
+ int op0_num = return_p ? 1 : 0;
+ int op1_num = return_p ? 2 : 1;
+
+ if (return_p)
+ target = nds32_legitimize_target (icode, target);
+
+ if (!nds32_check_constant_argument (icode, op0_num, op0, name))
+ return NULL_RTX;
+
+ op0 = nds32_legitimize_argument (icode, op0_num, op0);
+ op1 = nds32_legitimize_argument (icode, op1_num, op1);
+
+ /* Emit and return the new instruction. */
+ if (icode == CODE_FOR_cctl_idx_write)
+ {
+ /* cctl_idx_write is three argument,
+ so create operand2 for cctl_idx_write pattern. */
+ rtx op2 = nds32_read_argument (exp, 2);
+ op2 = nds32_legitimize_argument (icode, 2, op2);
+ pat = GEN_FCN (icode) (op0, op1, op2);
+ }
+ else if (return_p)
+ pat = GEN_FCN (icode) (target, op0, op1);
+ else
+ pat = GEN_FCN (icode) (op0, op1);
+
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
struct builtin_description
{
const enum insn_code icode;
};
+
+static struct builtin_description bdesc_cctl[] =
+{
+ NDS32_BUILTIN(cctl_idx_read, "cctl_idx_read", CCTL_IDX_READ)
+ NDS32_NO_TARGET_BUILTIN(cctl_idx_write, "cctl_idx_write", CCTL_IDX_WRITE)
+ NDS32_NO_TARGET_BUILTIN(cctl_va_lck, "cctl_va_lck", CCTL_VA_LCK)
+ NDS32_NO_TARGET_BUILTIN(cctl_idx_wbinval,
+ "cctl_idx_wbinval", CCTL_IDX_WBINVAL)
+ NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_l1,
+ "cctl_va_wbinval_l1", CCTL_VA_WBINVAL_L1)
+ NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_la,
+ "cctl_va_wbinval_la", CCTL_VA_WBINVAL_LA)
+};
+
rtx
nds32_expand_builtin_impl (tree exp,
rtx target,
return target;
case NDS32_BUILTIN_SETGIE_DIS:
emit_insn (gen_unspec_volatile_setgie_dis ());
+ case NDS32_BUILTIN_CCTL_L1D_INVALALL:
+ emit_insn (gen_cctl_l1d_invalall());
+ return target;
+ case NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL:
+ emit_insn (gen_cctl_l1d_wball_alvl());
+ return target;
+ case NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL:
+ emit_insn (gen_cctl_l1d_wball_one_lvl());
+ return target;
return target;
default:
break;
if (d->code == fcode)
return nds32_expand_binop_builtin (d->icode, exp, target, d->return_p);
+ 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,
+ d->return_p, d->name);
return NULL_RTX;
}
ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN);
ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS);
+ /* CCTL */
+ ADD_NDS32_BUILTIN0 ("cctl_l1d_invalall", void, CCTL_L1D_INVALALL);
+ ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_alvl", void, CCTL_L1D_WBALL_ALVL);
+ ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_one_lvl", void, CCTL_L1D_WBALL_ONE_LVL);
+ ADD_NDS32_BUILTIN2 ("cctl_va_lck", void, integer, ptr_uint, CCTL_VA_LCK);
+ ADD_NDS32_BUILTIN2 ("cctl_idx_wbinval", void, integer, unsigned,
+ CCTL_IDX_WBINVAL);
+ ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_l1", void, integer, ptr_uint,
+ CCTL_VA_WBINVAL_L1);
+ ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_la", void, integer, ptr_uint,
+ CCTL_VA_WBINVAL_LA);
+ ADD_NDS32_BUILTIN2 ("cctl_idx_read", unsigned, integer, unsigned,
+ CCTL_IDX_READ);
+ ADD_NDS32_BUILTIN3 ("cctl_idx_write", void, integer, unsigned, unsigned,
+ CCTL_IDX_WRITE);
+
/* Unaligned Load/Store */
ADD_NDS32_BUILTIN1 ("unaligned_load_hw", short_unsigned, ptr_ushort,
UALOAD_HW);
[(set_attr "type" "misc")]
)
+
+;; CCTL
+
+(define_insn "cctl_l1d_invalall"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_INVALALL)]
+ ""
+ "cctl\tL1D_INVALALL"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_l1d_wball_alvl"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL)]
+ ""
+ "cctl\tL1D_WBALL, alevel"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_l1d_wball_one_lvl"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL)]
+ ""
+ "cctl\tL1D_WBALL, 1level"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_idx_read"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")
+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_READ))]
+ ""
+ "cctl\t%0, %2, %X1"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_idx_write"
+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WRITE)]
+ ""
+ "cctl\t%1, %2, %W0"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_va_wbinval_l1"
+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_L1)]
+ ""
+ "cctl\t%1, %U0, 1level"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_va_wbinval_la"
+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA)]
+ ""
+ "cctl\t%1, %U0, alevel"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_idx_wbinval"
+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WBINVAL)]
+ ""
+ "cctl\t%1, %T0"
+ [(set_attr "type" "mmu")]
+)
+
+(define_insn "cctl_va_lck"
+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_LCK)]
+ ""
+ "cctl\t%1, %R0"
+ [(set_attr "type" "mmu")]
+)
;; String Extension
(define_insn "unspec_ffb"
"$ITB"
};
+/* Define instrinsic cctl names. */
+static const char * const nds32_cctl_names[] =
+{
+ "L1D_VA_FILLCK",
+ "L1D_VA_ULCK",
+ "L1I_VA_FILLCK",
+ "L1I_VA_ULCK",
+
+ "L1D_IX_WBINVAL",
+ "L1D_IX_INVAL",
+ "L1D_IX_WB",
+ "L1I_IX_INVAL",
+
+ "L1D_VA_INVAL",
+ "L1D_VA_WB",
+ "L1D_VA_WBINVAL",
+ "L1I_VA_INVAL",
+
+ "L1D_IX_RTAG",
+ "L1D_IX_RWD",
+ "L1I_IX_RTAG",
+ "L1I_IX_RWD",
+
+ "L1D_IX_WTAG",
+ "L1D_IX_WWD",
+ "L1I_IX_WTAG",
+ "L1I_IX_WWD"
+};
/* Defining register allocation order for performance.
We want to allocate callee-saved registers after others.
/* No need to handle following process, so return immediately. */
return;
+ case 'R': /* cctl valck */
+ /* Note the cctl divide to 5 group and share the same name table. */
+ if (op_value < 0 || op_value > 4)
+ error ("CCTL intrinsic function subtype out of range!");
+ fprintf (stream, "%s", nds32_cctl_names[op_value]);
+ return;
+
+ case 'T': /* cctl idxwbinv */
+ /* Note the cctl divide to 5 group and share the same name table. */
+ if (op_value < 0 || op_value > 4)
+ error ("CCTL intrinsic function subtype out of range!");
+ fprintf (stream, "%s", nds32_cctl_names[op_value + 4]);
+ return;
+
+ case 'U': /* cctl vawbinv */
+ /* Note the cctl divide to 5 group and share the same name table. */
+ if (op_value < 0 || op_value > 4)
+ error ("CCTL intrinsic function subtype out of range!");
+ fprintf (stream, "%s", nds32_cctl_names[op_value + 8]);
+ return;
+
+ case 'X': /* cctl idxread */
+ /* Note the cctl divide to 5 group and share the same name table. */
+ if (op_value < 0 || op_value > 4)
+ error ("CCTL intrinsic function subtype out of range!");
+ fprintf (stream, "%s", nds32_cctl_names[op_value + 12]);
+ return;
+
+ case 'W': /* cctl idxwitre */
+ /* Note the cctl divide to 5 group and share the same name table. */
+ if (op_value < 0 || op_value > 4)
+ error ("CCTL intrinsic function subtype out of range!");
+ fprintf (stream, "%s", nds32_cctl_names[op_value + 16]);
+ return;
+
default :
/* Unknown flag. */
output_operand_lossage ("invalid operand output code");
NDS32_BUILTIN_FFB,
NDS32_BUILTIN_FFMISM,
NDS32_BUILTIN_FLMISM,
+ NDS32_BUILTIN_CCTL_VA_LCK,
+ NDS32_BUILTIN_CCTL_IDX_WBINVAL,
+ NDS32_BUILTIN_CCTL_VA_WBINVAL_L1,
+ NDS32_BUILTIN_CCTL_VA_WBINVAL_LA,
+ NDS32_BUILTIN_CCTL_IDX_READ,
+ NDS32_BUILTIN_CCTL_IDX_WRITE,
+ NDS32_BUILTIN_CCTL_L1D_INVALALL,
+ NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL,
+ NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL,
NDS32_BUILTIN_UALOAD_HW,
NDS32_BUILTIN_UALOAD_W,
NDS32_BUILTIN_UALOAD_DW,
;; Insn type, it is used to default other attribute values.
(define_attr "type"
- "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,mul,mac,div,branch,misc,\
+ "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,mul,mac,div,branch,mmu,misc,\
falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore"
(const_string "unknown"))
__NDS32_REG_ITB__
};
+/* The cctl subtype for intrinsic. */
+enum nds32_cctl_valck
+{
+ __NDS32_CCTL_L1D_VA_FILLCK__,
+ __NDS32_CCTL_L1D_VA_ULCK__,
+ __NDS32_CCTL_L1I_VA_FILLCK__,
+ __NDS32_CCTL_L1I_VA_ULCK__
+};
+
+enum nds32_cctl_idxwbinv
+{
+ __NDS32_CCTL_L1D_IX_WBINVAL__,
+ __NDS32_CCTL_L1D_IX_INVAL__,
+ __NDS32_CCTL_L1D_IX_WB__,
+ __NDS32_CCTL_L1I_IX_INVAL__
+};
+
+enum nds32_cctl_vawbinv
+{
+ __NDS32_CCTL_L1D_VA_INVAL__,
+ __NDS32_CCTL_L1D_VA_WB__,
+ __NDS32_CCTL_L1D_VA_WBINVAL__,
+ __NDS32_CCTL_L1I_VA_INVAL__
+};
+
+enum nds32_cctl_idxread
+{
+ __NDS32_CCTL_L1D_IX_RTAG__,
+ __NDS32_CCTL_L1D_IX_RWD__,
+ __NDS32_CCTL_L1I_IX_RTAG__,
+ __NDS32_CCTL_L1I_IX_RWD__
+};
+
+enum nds32_cctl_idxwrite
+{
+ __NDS32_CCTL_L1D_IX_WTAG__,
+ __NDS32_CCTL_L1D_IX_WWD__,
+ __NDS32_CCTL_L1I_IX_WTAG__,
+ __NDS32_CCTL_L1I_IX_WWD__
+};
/* ------------------------------------------------------------------------ */
#define NDS32_USR_IFC_LP __NDS32_REG_IFC_LP__
#define NDS32_USR_ITB __NDS32_REG_ITB__
+#define NDS32_CCTL_L1D_VA_FILLCK __NDS32_CCTL_L1D_VA_FILLCK__
+#define NDS32_CCTL_L1D_VA_ULCK __NDS32_CCTL_L1D_VA_ULCK__
+#define NDS32_CCTL_L1I_VA_FILLCK __NDS32_CCTL_L1I_VA_FILLCK__
+#define NDS32_CCTL_L1I_VA_ULCK __NDS32_CCTL_L1I_VA_ULCK__
+
+#define NDS32_CCTL_L1D_IX_WBINVAL __NDS32_CCTL_L1D_IX_WBINVAL__
+#define NDS32_CCTL_L1D_IX_INVAL __NDS32_CCTL_L1D_IX_INVAL__
+#define NDS32_CCTL_L1D_IX_WB __NDS32_CCTL_L1D_IX_WB__
+#define NDS32_CCTL_L1I_IX_INVAL __NDS32_CCTL_L1I_IX_INVAL__
+
+#define NDS32_CCTL_L1D_VA_INVAL __NDS32_CCTL_L1D_VA_INVAL__
+#define NDS32_CCTL_L1D_VA_WB __NDS32_CCTL_L1D_VA_WB__
+#define NDS32_CCTL_L1D_VA_WBINVAL __NDS32_CCTL_L1D_VA_WBINVAL__
+#define NDS32_CCTL_L1I_VA_INVAL __NDS32_CCTL_L1I_VA_INVAL__
+
+#define NDS32_CCTL_L1D_IX_RTAG __NDS32_CCTL_L1D_IX_RTAG__
+#define NDS32_CCTL_L1D_IX_RWD __NDS32_CCTL_L1D_IX_RWD__
+#define NDS32_CCTL_L1I_IX_RTAG __NDS32_CCTL_L1I_IX_RTAG__
+#define NDS32_CCTL_L1I_IX_RWD __NDS32_CCTL_L1I_IX_RWD__
+
+#define NDS32_CCTL_L1D_IX_WTAG __NDS32_CCTL_L1D_IX_WTAG__
+#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__cctlva_lck(subtype, va) \
+ (__builtin_nds32_cctl_va_lck ((subtype), (va)))
+#define __nds32__cctlidx_wbinval(subtype, idx) \
+ (__builtin_nds32_cctl_idx_wbinval ((subtype), (idx)))
+#define __nds32__cctlva_wbinval_alvl(subtype, va) \
+ (__builtin_nds32_cctl_va_wbinval_la ((subtype), (va)))
+#define __nds32__cctlva_wbinval_one_lvl(subtype, va) \
+ (__builtin_nds32_cctl_va_wbinval_l1 ((subtype), (va)))
+#define __nds32__cctlidx_read(subtype, idx) \
+ (__builtin_nds32_cctl_idx_read ((subtype), (idx)))
+#define __nds32__cctlidx_write(subtype, b, idxw) \
+ (__builtin_nds32_cctl_idx_write ((subtype), (b), (idxw)))
+#define __nds32__cctl_l1d_invalall() \
+ (__builtin_nds32_cctl_l1d_invalall())
+#define __nds32__cctl_l1d_wball_alvl() \
+ (__builtin_nds32_cctl_l1d_wball_alvl())
+#define __nds32__cctl_l1d_wball_one_lvl() \
+ (__builtin_nds32_cctl_l1d_wball_one_lvl())
+
#define __nds32__fcpynsd(a, b) \
(__builtin_nds32_fcpynsd ((a), (b)))
#define __nds32__fcpynss(a, b) \
(define_cpu_unit "general_unit" "nds32_machine")
(define_insn_reservation "simple_insn" 1
- (eq_attr "type" "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,mul,mac,div,branch,misc")
+ (eq_attr "type" "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,mul,mac,div,branch,mmu,misc")
"general_unit")
;; ------------------------------------------------------------------------