[NDS32] Add intrinsic functions for interrupt control.
authorMonk Chiang <sh.chiang04@gmail.com>
Sun, 8 Apr 2018 14:28:44 +0000 (14:28 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Sun, 8 Apr 2018 14:28:44 +0000 (14:28 +0000)
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.

From-SVN: r259223

gcc/ChangeLog
gcc/config.gcc
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 f1d773b..2bffb97 100644 (file)
@@ -1,3 +1,15 @@
+2018-04-08  Monk Chiang  <sh.chiang04@gmail.com>
+
+       * 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  <jasonwucj@gmail.com>
 
        * config/nds32/nds32.c (nds32_init_machine_status,
index 099c2f6..55c314a 100644 (file)
@@ -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-*-*)
index 50594c3..c54cc92 100644 (file)
   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
 ])
index c4d75d6..a835029 100644 (file)
@@ -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);
index 9975e4a..c7b3102 100644 (file)
   [(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
index d68820c..8203ab8 100644 (file)
@@ -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
 };
 
index 3feb587..a299c6a 100644 (file)
@@ -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 */