From 1144471c5235be3bae7449ce9b2beb451192c968 Mon Sep 17 00:00:00 2001 From: jasonwucj Date: Sun, 8 Apr 2018 14:28:44 +0000 Subject: [PATCH] [NDS32] Add intrinsic functions for interrupt control. gcc/ * config.gcc (nds32le-*-*, nds32be-*-*): Add nds32/nds32_intrinsic.h into tm_file. * config/nds32/constants.md (unspec_volatile_element): Add enum values for interrupt control. * config/nds32/nds32-intrinsic.c: Implementation of intrinsic functions for interrupt control. * config/nds32/nds32-intrinsic.md: Likewise. * config/nds32/nds32_intrinsic.h: Likewise. * config/nds32/nds32.h (nds32_builtins): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259223 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 + gcc/config.gcc | 4 +- gcc/config/nds32/constants.md | 12 + gcc/config/nds32/nds32-intrinsic.c | 77 +++++++ gcc/config/nds32/nds32-intrinsic.md | 439 ++++++++++++++++++++++++++++++++++++ gcc/config/nds32/nds32.h | 14 ++ gcc/config/nds32/nds32_intrinsic.h | 104 +++++++++ 7 files changed, 660 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f1d773b2ab1..2bffb97cb30 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2018-04-08 Monk Chiang + + * config.gcc (nds32le-*-*, nds32be-*-*): Add nds32/nds32_intrinsic.h + into tm_file. + * config/nds32/constants.md (unspec_volatile_element): Add enum values + for interrupt control. + * config/nds32/nds32-intrinsic.c: Implementation of intrinsic + functions for interrupt control. + * config/nds32/nds32-intrinsic.md: Likewise. + * config/nds32/nds32_intrinsic.h: Likewise. + * config/nds32/nds32.h (nds32_builtins): Likewise. + 2018-04-08 Chung-Ju Wu * config/nds32/nds32.c (nds32_init_machine_status, diff --git a/gcc/config.gcc b/gcc/config.gcc index 099c2f6fa83..55c314afdbd 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2335,13 +2335,13 @@ msp430*-*-*) nds32le-*-*) target_cpu_default="0" tm_defines="${tm_defines}" - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h" tmake_file="nds32/t-nds32 nds32/t-mlibs" ;; nds32be-*-*) target_cpu_default="0|MASK_BIG_ENDIAN" tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h" tmake_file="nds32/t-nds32 nds32/t-mlibs" ;; nios2-*-*) diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md index 50594c3e9dc..c54cc92b5e7 100644 --- a/gcc/config/nds32/constants.md +++ b/gcc/config/nds32/constants.md @@ -122,6 +122,18 @@ UNSPEC_VOLATILE_TLBOP_PB UNSPEC_VOLATILE_TLBOP_INV UNSPEC_VOLATILE_TLBOP_FLUA + UNSPEC_VOLATILE_ENABLE_INT + UNSPEC_VOLATILE_DISABLE_INT + UNSPEC_VOLATILE_SET_PENDING_SWINT + UNSPEC_VOLATILE_CLR_PENDING_SWINT + UNSPEC_VOLATILE_CLR_PENDING_HWINT + UNSPEC_VOLATILE_GET_ALL_PENDING_INT + UNSPEC_VOLATILE_GET_PENDING_INT + UNSPEC_VOLATILE_SET_INT_PRIORITY + UNSPEC_VOLATILE_GET_INT_PRIORITY + UNSPEC_VOLATILE_SET_TRIG_LEVEL + UNSPEC_VOLATILE_SET_TRIG_EDGE + UNSPEC_VOLATILE_GET_TRIG_TYPE 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 c4d75d67466..a835029fd52 100644 --- a/gcc/config/nds32/nds32-intrinsic.c +++ b/gcc/config/nds32/nds32-intrinsic.c @@ -467,6 +467,37 @@ nds32_expand_scw_builtin (enum insn_code icode, tree exp, rtx target) return target; } +/* Expand set int priority builtins. */ +static rtx +nds32_expand_priority_builtin (enum insn_code icode, tree exp, rtx target, + const char *name) +{ + rtx pat; + rtx op0 = nds32_read_argument (exp, 0); + rtx op1 = nds32_read_argument (exp, 1); + + /* set_int_priority intrinsic function that two arguments are immediate, + so check whether auguments are immedite. */ + + if (!nds32_check_constant_argument (icode, 0, op0, name)) + return NULL_RTX; + + if (!nds32_check_constant_argument (icode, 1, op1, name)) + return NULL_RTX; + + op0 = nds32_legitimize_argument (icode, 0, op0); + op1 = nds32_legitimize_argument (icode, 1, op1); + + /* Emit and return the new instruction. */ + pat = GEN_FCN (icode) (op0, op1); + + if (! pat) + return NULL_RTX; + + emit_insn (pat); + return target; +} + struct builtin_description { const enum insn_code icode; @@ -490,6 +521,8 @@ static struct builtin_description bdesc_noarg[] = NDS32_BUILTIN(unspec_fmfcsr, "fmfcsr", FMFCSR) NDS32_BUILTIN(unspec_get_current_sp, "get_current_sp", GET_CURRENT_SP) NDS32_BUILTIN(unspec_return_address, "return_address", RETURN_ADDRESS) + NDS32_BUILTIN(unspec_get_all_pending_int, "get_all_pending_int", + GET_ALL_PENDING_INT) }; /* Intrinsics that take just one argument. */ @@ -526,9 +559,20 @@ static struct builtin_description bdesc_1argimm[] = { NDS32_BUILTIN(unspec_volatile_mfsr, "mfsr", MFSR) NDS32_BUILTIN(unspec_volatile_mfusr, "mfsr", MFUSR) + NDS32_BUILTIN(unspec_get_pending_int, "get_pending_int", GET_PENDING_INT) + NDS32_BUILTIN(unspec_get_int_priority, "get_int_priority", GET_INT_PRIORITY) NDS32_NO_TARGET_BUILTIN(unspec_trap, "trap", TRAP) NDS32_NO_TARGET_BUILTIN(unspec_break, "break", BREAK) NDS32_NO_TARGET_BUILTIN(unspec_syscall, "syscall", SYSCALL) + NDS32_NO_TARGET_BUILTIN(unspec_enable_int, "enable_int", ENABLE_INT) + NDS32_NO_TARGET_BUILTIN(unspec_disable_int, "disable_int", DISABLE_INT) + NDS32_NO_TARGET_BUILTIN(unspec_clr_pending_hwint, "clr_pending_hwint", + CLR_PENDING_HWINT) + NDS32_NO_TARGET_BUILTIN(unspec_set_trig_level, "set_trig_level", + SET_TRIG_LEVEL) + NDS32_NO_TARGET_BUILTIN(unspec_set_trig_edge, "set_trig_edge", + SET_TRIG_EDGE) + NDS32_BUILTIN(unspec_get_trig_type, "get_trig_type", GET_TRIG_TYPE) }; /* Intrinsics that take two arguments. */ @@ -739,6 +783,20 @@ nds32_expand_builtin_impl (tree exp, emit_insn (gen_unspec_volatile_setgie_dis ()); emit_insn (gen_unspec_dsb ()); return target; + case NDS32_BUILTIN_GIE_DIS: + emit_insn (gen_unspec_volatile_setgie_dis ()); + emit_insn (gen_unspec_dsb ()); + return target; + case NDS32_BUILTIN_GIE_EN: + emit_insn (gen_unspec_volatile_setgie_en ()); + emit_insn (gen_unspec_dsb ()); + return target; + case NDS32_BUILTIN_SET_PENDING_SWINT: + emit_insn (gen_unspec_set_pending_swint ()); + return target; + case NDS32_BUILTIN_CLR_PENDING_SWINT: + emit_insn (gen_unspec_clr_pending_swint ()); + return target; case NDS32_BUILTIN_CCTL_L1D_INVALALL: emit_insn (gen_cctl_l1d_invalall()); return target; @@ -775,6 +833,10 @@ nds32_expand_builtin_impl (tree exp, case NDS32_BUILTIN_SCW: return nds32_expand_scw_builtin (CODE_FOR_unspec_volatile_scw, exp, target); + case NDS32_BUILTIN_SET_INT_PRIORITY: + return nds32_expand_priority_builtin (CODE_FOR_unspec_set_int_priority, + exp, target, + "__nds32__set_int_priority"); return target; default: break; @@ -911,6 +973,21 @@ nds32_init_builtins_impl (void) /* Interrupt. */ ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN); ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS); + ADD_NDS32_BUILTIN0 ("gie_en", void, GIE_EN); + ADD_NDS32_BUILTIN0 ("gie_dis", void, GIE_DIS); + ADD_NDS32_BUILTIN1 ("enable_int", void, integer, ENABLE_INT); + ADD_NDS32_BUILTIN1 ("disable_int", void, integer, DISABLE_INT); + ADD_NDS32_BUILTIN0 ("set_pending_swint", void, SET_PENDING_SWINT); + ADD_NDS32_BUILTIN0 ("clr_pending_swint", void, CLR_PENDING_SWINT); + ADD_NDS32_BUILTIN0 ("get_all_pending_int", unsigned, GET_ALL_PENDING_INT); + ADD_NDS32_BUILTIN1 ("get_pending_int", unsigned, integer, GET_PENDING_INT); + ADD_NDS32_BUILTIN1 ("get_int_priority", unsigned, integer, GET_INT_PRIORITY); + ADD_NDS32_BUILTIN2 ("set_int_priority", void, integer, integer, + SET_INT_PRIORITY); + ADD_NDS32_BUILTIN1 ("clr_pending_hwint", void, integer, CLR_PENDING_HWINT); + ADD_NDS32_BUILTIN1 ("set_trig_level", void, integer, SET_TRIG_LEVEL); + ADD_NDS32_BUILTIN1 ("set_trig_edge", void, integer, SET_TRIG_EDGE); + ADD_NDS32_BUILTIN1 ("get_trig_type", unsigned, integer, GET_TRIG_TYPE); /* Load and Store */ ADD_NDS32_BUILTIN1 ("llw", unsigned, ptr_uint, LLW); diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md index 9975e4af498..c7b3102ab59 100644 --- a/gcc/config/nds32/nds32-intrinsic.md +++ b/gcc/config/nds32/nds32-intrinsic.md @@ -164,6 +164,445 @@ [(set_attr "type" "misc")] ) +(define_expand "unspec_enable_int" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_ENABLE_INT)] + "" +{ + rtx system_reg; + rtx temp_reg = gen_reg_rtx (SImode); + + /* Set system register form nds32_intrinsic_register_names[]. */ + if ((INTVAL (operands[0]) >= NDS32_INT_H16) + && (INTVAL (operands[0]) <= NDS32_INT_H31)) + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK2__); + operands[0] = GEN_INT (1 << (INTVAL (operands[0]))); + } + else if ((INTVAL (operands[0]) >= NDS32_INT_H32) + && (INTVAL (operands[0]) <= NDS32_INT_H63)) + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK3__); + operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 32)); + } + else + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK__); + + if (INTVAL (operands[0]) == NDS32_INT_SWI) + operands[0] = GEN_INT (1 << 16); + else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ) + && (INTVAL (operands[0]) <= NDS32_INT_DSSIM)) + operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 4)); + else + operands[0] = GEN_INT (1 << (INTVAL (operands[0]))); + } + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_iorsi3 (temp_reg, temp_reg, operands[0])); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + DONE; +}) + +(define_expand "unspec_disable_int" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_DISABLE_INT)] + "" +{ + rtx system_reg; + rtx temp_reg = gen_reg_rtx (SImode); + + /* Set system register form nds32_intrinsic_register_names[]. */ + if ((INTVAL (operands[0]) >= NDS32_INT_H16) + && (INTVAL (operands[0]) <= NDS32_INT_H31)) + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK2__); + operands[0] = GEN_INT (~(1 << INTVAL (operands[0]))); + } + else if ((INTVAL (operands[0]) >= NDS32_INT_H32) + && (INTVAL (operands[0]) <= NDS32_INT_H63)) + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK3__); + operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 32))); + } + else + { + system_reg = GEN_INT (__NDS32_REG_INT_MASK__); + + if (INTVAL (operands[0]) == NDS32_INT_SWI) + operands[0] = GEN_INT (~(1 << 16)); + else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ) + && (INTVAL (operands[0]) <= NDS32_INT_DSSIM)) + operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 4))); + else + operands[0] = GEN_INT (~(1 << INTVAL (operands[0]))); + } + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_andsi3 (temp_reg, temp_reg, operands[0])); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + DONE; +}) + +(define_expand "unspec_set_pending_swint" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SET_PENDING_SWINT)] + "" +{ + /* Get $INT_PEND system register form nds32_intrinsic_register_names[] */ + rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + rtx temp_reg = gen_reg_rtx (SImode); + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_iorsi3 (temp_reg, temp_reg, GEN_INT (65536))); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + DONE; +}) + +(define_expand "unspec_clr_pending_swint" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLR_PENDING_SWINT)] + "" +{ + /* Get $INT_PEND system register form nds32_intrinsic_register_names[] */ + rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + rtx temp_reg = gen_reg_rtx (SImode); + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_andsi3 (temp_reg, temp_reg, GEN_INT (~(1 << 16)))); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + DONE; +}) + +(define_expand "unspec_clr_pending_hwint" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_CLR_PENDING_HWINT)] + "" +{ + rtx system_reg = NULL_RTX; + rtx temp_reg = gen_reg_rtx (SImode); + rtx clr_hwint; + unsigned offset = 0; + + /* Set system register form nds32_intrinsic_register_names[]. */ + if ((INTVAL (operands[0]) >= NDS32_INT_H0) + && (INTVAL (operands[0]) <= NDS32_INT_H15)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + } + else if ((INTVAL (operands[0]) >= NDS32_INT_H16) + && (INTVAL (operands[0]) <= NDS32_INT_H31)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND2__); + } + else if ((INTVAL (operands[0]) >= NDS32_INT_H32) + && (INTVAL (operands[0]) <= NDS32_INT_H63)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND3__); + offset = 32; + } + else + error ("__nds32__clr_pending_hwint not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + /* $INT_PEND type is write one clear. */ + clr_hwint = GEN_INT (1 << (INTVAL (operands[0]) - offset)); + + if (system_reg != NULL_RTX) + { + emit_move_insn (temp_reg, clr_hwint); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + } + DONE; +}) + +(define_expand "unspec_get_all_pending_int" + [(set (match_operand:SI 0 "register_operand" "") + (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_GET_ALL_PENDING_INT))] + "" +{ + rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); + emit_insn (gen_unspec_dsb ()); + DONE; +}) + +(define_expand "unspec_get_pending_int" + [(set (match_operand:SI 0 "register_operand" "") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_PENDING_INT))] + "" +{ + rtx system_reg = NULL_RTX; + + /* Set system register form nds32_intrinsic_register_names[]. */ + if ((INTVAL (operands[1]) >= NDS32_INT_H0) + && (INTVAL (operands[1]) <= NDS32_INT_H15)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + operands[2] = GEN_INT (31 - INTVAL (operands[1])); + } + else if (INTVAL (operands[1]) == NDS32_INT_SWI) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND__); + operands[2] = GEN_INT (15); + } + else if ((INTVAL (operands[1]) >= NDS32_INT_H16) + && (INTVAL (operands[1]) <= NDS32_INT_H31)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND2__); + operands[2] = GEN_INT (31 - INTVAL (operands[1])); + } + else if ((INTVAL (operands[1]) >= NDS32_INT_H32) + && (INTVAL (operands[1]) <= NDS32_INT_H63)) + { + system_reg = GEN_INT (__NDS32_REG_INT_PEND3__); + operands[2] = GEN_INT (31 - (INTVAL (operands[1]) - 32)); + } + else + error ("get_pending_int not support NDS32_INT_ALZ," + " NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + /* mfsr op0, sytem_reg */ + if (system_reg != NULL_RTX) + { + emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); + emit_insn (gen_ashlsi3 (operands[0], operands[0], operands[2])); + emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); + emit_insn (gen_unspec_dsb ()); + } + DONE; +}) + +(define_expand "unspec_set_int_priority" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "") + (match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_SET_INT_PRIORITY)] + "" +{ + rtx system_reg = NULL_RTX; + rtx priority = NULL_RTX; + rtx mask = NULL_RTX; + rtx temp_reg = gen_reg_rtx (SImode); + rtx mask_reg = gen_reg_rtx (SImode); + rtx set_reg = gen_reg_rtx (SImode); + unsigned offset = 0; + + /* Get system register form nds32_intrinsic_register_names[]. */ + if (INTVAL (operands[0]) <= NDS32_INT_H15) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI__); + offset = 0; + } + else if (INTVAL (operands[0]) >= NDS32_INT_H16 + && INTVAL (operands[0]) <= NDS32_INT_H31) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI2__); + /* The $INT_PRI2 first bit correspond to H16, so need + subtract 16. */ + offset = 16; + } + else if (INTVAL (operands[0]) >= NDS32_INT_H32 + && INTVAL (operands[0]) <= NDS32_INT_H47) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI3__); + /* The $INT_PRI3 first bit correspond to H32, so need + subtract 32. */ + offset = 32; + } + else if (INTVAL (operands[0]) >= NDS32_INT_H48 + && INTVAL (operands[0]) <= NDS32_INT_H63) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI4__); + /* The $INT_PRI3 first bit correspond to H48, so need + subtract 48. */ + offset = 48; + } + else + error ("set_int_priority not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + mask = GEN_INT (~(3 << 2 * (INTVAL (operands[0]) - offset))); + priority = GEN_INT ((int) (INTVAL (operands[1]) + << ((INTVAL (operands[0]) - offset) * 2))); + + if (system_reg != NULL_RTX) + { + emit_move_insn (mask_reg, mask); + emit_move_insn (set_reg, priority); + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_andsi3 (temp_reg, temp_reg, mask_reg)); + emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_reg)); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + emit_insn (gen_unspec_dsb ()); + } + DONE; +}) + +(define_expand "unspec_get_int_priority" + [(set (match_operand:SI 0 "register_operand" "") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_INT_PRIORITY))] + "" +{ + rtx system_reg = NULL_RTX; + rtx priority = NULL_RTX; + unsigned offset = 0; + + /* Get system register form nds32_intrinsic_register_names[] */ + if (INTVAL (operands[1]) <= NDS32_INT_H15) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI__); + offset = 0; + } + else if (INTVAL (operands[1]) >= NDS32_INT_H16 + && INTVAL (operands[1]) <= NDS32_INT_H31) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI2__); + /* The $INT_PRI2 first bit correspond to H16, so need + subtract 16. */ + offset = 16; + } + else if (INTVAL (operands[1]) >= NDS32_INT_H32 + && INTVAL (operands[1]) <= NDS32_INT_H47) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI3__); + /* The $INT_PRI3 first bit correspond to H32, so need + subtract 32. */ + offset = 32; + } + else if (INTVAL (operands[1]) >= NDS32_INT_H48 + && INTVAL (operands[1]) <= NDS32_INT_H63) + { + system_reg = GEN_INT (__NDS32_REG_INT_PRI4__); + /* The $INT_PRI4 first bit correspond to H48, so need + subtract 48. */ + offset = 48; + } + else + error ("set_int_priority not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + priority = GEN_INT (31 - 2 * (INTVAL (operands[1]) - offset)); + + if (system_reg != NULL_RTX) + { + emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); + emit_insn (gen_ashlsi3 (operands[0], operands[0], priority)); + emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (30))); + emit_insn (gen_unspec_dsb ()); + } + DONE; +}) + +(define_expand "unspec_set_trig_level" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_LEVEL)] + "" +{ + rtx system_reg = NULL_RTX; + rtx temp_reg = gen_reg_rtx (SImode); + rtx set_level; + unsigned offset = 0; + + if (INTVAL (operands[0]) >= NDS32_INT_H0 + && INTVAL (operands[0]) <= NDS32_INT_H31) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); + offset = 0; + } + else if (INTVAL (operands[0]) >= NDS32_INT_H32 + && INTVAL (operands[0]) <= NDS32_INT_H63) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); + offset = 32; + } + else + error ("__nds32__set_trig_type_level not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + if (system_reg != NULL_RTX) + { + /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */ + set_level = GEN_INT (~(1 << (INTVAL (operands[0]) - offset))); + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_andsi3 (temp_reg, temp_reg, set_level)); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + } + DONE; +}) + +(define_expand "unspec_set_trig_edge" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_EDGE)] + "" +{ + rtx system_reg = NULL_RTX; + rtx temp_reg = gen_reg_rtx (SImode); + rtx set_level; + unsigned offset = 0; + + if (INTVAL (operands[0]) >= NDS32_INT_H0 + && INTVAL (operands[0]) <= NDS32_INT_H31) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); + offset = 0; + } + else if (INTVAL (operands[0]) >= NDS32_INT_H32 + && INTVAL (operands[0]) <= NDS32_INT_H63) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); + offset = 32; + } + else + error ("__nds32__set_trig_type_edge not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + if (system_reg != NULL_RTX) + { + /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */ + set_level = GEN_INT ((1 << (INTVAL (operands[0]) - offset))); + + emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); + emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_level)); + emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); + } + DONE; +}) + +(define_expand "unspec_get_trig_type" + [(set (match_operand:SI 0 "register_operand" "") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_TRIG_TYPE))] + "" +{ + rtx system_reg = NULL_RTX; + rtx trig_type; + unsigned offset = 0; + + if (INTVAL (operands[1]) >= NDS32_INT_H0 + && INTVAL (operands[1]) <= NDS32_INT_H31) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); + offset = 0; + } + else if (INTVAL (operands[1]) >= NDS32_INT_H32 + && INTVAL (operands[1]) <= NDS32_INT_H63) + { + system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); + offset = 32; + } + else + error ("__nds32__get_trig_type not support NDS32_INT_SWI," + " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); + + if (system_reg != NULL_RTX) + { + trig_type = GEN_INT (31 - (INTVAL (operands[1]) - offset)); + + emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); + emit_insn (gen_ashlsi3 (operands[0], operands[0], trig_type)); + emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); + emit_insn (gen_unspec_dsb ()); + } + DONE; +}) + ;; ------------------------------------------------------------------------ ;; Cache Synchronization Instructions diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h index d68820c422b..8203ab82d89 100644 --- a/gcc/config/nds32/nds32.h +++ b/gcc/config/nds32/nds32.h @@ -498,6 +498,20 @@ enum nds32_builtins NDS32_BUILTIN_UASTORE_HW, NDS32_BUILTIN_UASTORE_W, NDS32_BUILTIN_UASTORE_DW, + NDS32_BUILTIN_GIE_DIS, + NDS32_BUILTIN_GIE_EN, + NDS32_BUILTIN_ENABLE_INT, + NDS32_BUILTIN_DISABLE_INT, + NDS32_BUILTIN_SET_PENDING_SWINT, + NDS32_BUILTIN_CLR_PENDING_SWINT, + NDS32_BUILTIN_CLR_PENDING_HWINT, + NDS32_BUILTIN_GET_ALL_PENDING_INT, + NDS32_BUILTIN_GET_PENDING_INT, + NDS32_BUILTIN_SET_INT_PRIORITY, + NDS32_BUILTIN_GET_INT_PRIORITY, + NDS32_BUILTIN_SET_TRIG_LEVEL, + NDS32_BUILTIN_SET_TRIG_EDGE, + NDS32_BUILTIN_GET_TRIG_TYPE, NDS32_BUILTIN_COUNT }; diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h index 3feb587a8e2..a299c6a1ed7 100644 --- a/gcc/config/nds32/nds32_intrinsic.h +++ b/gcc/config/nds32/nds32_intrinsic.h @@ -238,6 +238,78 @@ enum nds32_dpref /* ------------------------------------------------------------------------ */ +/* Define interrupt number for intrinsic function. */ +#define NDS32_INT_H0 0 +#define NDS32_INT_H1 1 +#define NDS32_INT_H2 2 +#define NDS32_INT_H3 3 +#define NDS32_INT_H4 4 +#define NDS32_INT_H5 5 +#define NDS32_INT_H6 6 +#define NDS32_INT_H7 7 +#define NDS32_INT_H8 8 +#define NDS32_INT_H9 9 +#define NDS32_INT_H10 10 +#define NDS32_INT_H11 11 +#define NDS32_INT_H12 12 +#define NDS32_INT_H13 13 +#define NDS32_INT_H14 14 +#define NDS32_INT_H15 15 +#define NDS32_INT_H16 16 +#define NDS32_INT_H17 17 +#define NDS32_INT_H18 18 +#define NDS32_INT_H19 19 +#define NDS32_INT_H20 20 +#define NDS32_INT_H21 21 +#define NDS32_INT_H22 22 +#define NDS32_INT_H23 23 +#define NDS32_INT_H24 24 +#define NDS32_INT_H25 25 +#define NDS32_INT_H26 26 +#define NDS32_INT_H27 27 +#define NDS32_INT_H28 28 +#define NDS32_INT_H29 29 +#define NDS32_INT_H30 30 +#define NDS32_INT_H31 31 +#define NDS32_INT_H32 32 +#define NDS32_INT_H33 33 +#define NDS32_INT_H34 34 +#define NDS32_INT_H35 35 +#define NDS32_INT_H36 36 +#define NDS32_INT_H37 37 +#define NDS32_INT_H38 38 +#define NDS32_INT_H39 39 +#define NDS32_INT_H40 40 +#define NDS32_INT_H41 41 +#define NDS32_INT_H42 42 +#define NDS32_INT_H43 43 +#define NDS32_INT_H44 44 +#define NDS32_INT_H45 45 +#define NDS32_INT_H46 46 +#define NDS32_INT_H47 47 +#define NDS32_INT_H48 48 +#define NDS32_INT_H49 49 +#define NDS32_INT_H50 50 +#define NDS32_INT_H51 51 +#define NDS32_INT_H52 52 +#define NDS32_INT_H53 53 +#define NDS32_INT_H54 54 +#define NDS32_INT_H55 55 +#define NDS32_INT_H56 56 +#define NDS32_INT_H57 57 +#define NDS32_INT_H58 58 +#define NDS32_INT_H59 59 +#define NDS32_INT_H60 60 +#define NDS32_INT_H61 61 +#define NDS32_INT_H62 62 +#define NDS32_INT_H63 63 +#define NDS32_INT_SWI 64 +#define NDS32_INT_ALZ 65 +#define NDS32_INT_IDIVZE 66 +#define NDS32_INT_DSSIM 67 + +/* ------------------------------------------------------------------------ */ + /* Define intrinsic register name macro for compatibility. */ #define NDS32_SR_CPU_VER __NDS32_REG_CPU_VER__ #define NDS32_SR_ICM_CFG __NDS32_REG_ICM_CFG__ @@ -502,6 +574,9 @@ enum nds32_dpref #define __nds32__setend_little() \ (__builtin_nds32_setend_little()) #define __nds32__setgie_en() \ + (__builtin_nds32_setgie_en()) +#define __nds32__setgie_dis() \ + (__builtin_nds32_setgie_dis()) #define __nds32__jr_itoff(a) \ (__builtin_nds32_jr_itoff ((a))) @@ -616,4 +691,33 @@ enum nds32_dpref #define __nds32__tlbop_flua() \ (__builtin_nds32_tlbop_flua()) +#define __nds32__gie_dis() \ + (__builtin_nds32_gie_dis()) +#define __nds32__gie_en() \ + (__builtin_nds32_gie_en()) +#define __nds32__enable_int(a) \ + (__builtin_nds32_enable_int ((a))) +#define __nds32__disable_int(a) \ + (__builtin_nds32_disable_int ((a))) +#define __nds32__set_pending_swint() \ + (__builtin_nds32_set_pending_swint()) +#define __nds32__clr_pending_swint() \ + (__builtin_nds32_clr_pending_swint()) +#define __nds32__clr_pending_hwint(a) \ + (__builtin_nds32_clr_pending_hwint(a)) +#define __nds32__get_all_pending_int() \ + (__builtin_nds32_get_all_pending_int()) +#define __nds32__get_pending_int(a) \ + (__builtin_nds32_get_pending_int ((a))) +#define __nds32__set_int_priority(a, b) \ + (__builtin_nds32_set_int_priority ((a), (b))) +#define __nds32__get_int_priority(a) \ + (__builtin_nds32_get_int_priority ((a))) +#define __nds32__set_trig_type_level(a) \ + (__builtin_nds32_set_trig_level(a)) +#define __nds32__set_trig_type_edge(a) \ + (__builtin_nds32_set_trig_edge(a)) +#define __nds32__get_trig_type(a) \ + (__builtin_nds32_get_trig_type ((a))) + #endif /* nds32_intrinsic.h */ -- 2.11.4.GIT