| ;; Intrinsic patterns description of Andes NDS32 cpu for GNU compiler |
| ;; Copyright (C) 2012-2021 Free Software Foundation, Inc. |
| ;; Contributed by Andes Technology Corporation. |
| ;; |
| ;; This file is part of GCC. |
| ;; |
| ;; GCC is free software; you can redistribute it and/or modify it |
| ;; under the terms of the GNU General Public License as published |
| ;; by the Free Software Foundation; either version 3, or (at your |
| ;; option) any later version. |
| ;; |
| ;; GCC is distributed in the hope that it will be useful, but WITHOUT |
| ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
| ;; License for more details. |
| ;; |
| ;; You should have received a copy of the GNU General Public License |
| ;; along with GCC; see the file COPYING3. If not see |
| ;; <http://www.gnu.org/licenses/>. |
| |
| ;; ------------------------------------------------------------------------ |
| |
| ;; Register Transfer. |
| |
| (define_insn "unspec_volatile_mfsr" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFSR))] |
| "" |
| "mfsr\t%0, %V1" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_volatile_mfusr" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFUSR))] |
| "" |
| "mfusr\t%0, %V1" |
| [(set_attr "type" "misc") |
| (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)] |
| "" |
| "mtsr\t%0, %V1" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_volatile_mtusr" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") |
| (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTUSR)] |
| "" |
| "mtusr\t%0, %V1" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; FPU Register Transfer. |
| |
| (define_insn "unspec_fcpynsd" |
| [(set (match_operand:DF 0 "register_operand" "=f") |
| (unspec:DF [(match_operand:DF 1 "register_operand" "f") |
| (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYNSD))] |
| "" |
| "fcpynsd\t%0, %1, %2" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fcpynss" |
| [(set (match_operand:SF 0 "register_operand" "=f") |
| (unspec:SF [(match_operand:SF 1 "register_operand" "f") |
| (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYNSS))] |
| "" |
| "fcpynss\t%0, %1, %2" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fcpysd" |
| [(set (match_operand:DF 0 "register_operand" "=f") |
| (unspec:DF [(match_operand:DF 1 "register_operand" "f") |
| (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYSD))] |
| "" |
| "fcpysd\t%0, %1, %2" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fcpyss" |
| [(set (match_operand:SF 0 "register_operand" "=f") |
| (unspec:SF [(match_operand:SF 1 "register_operand" "f") |
| (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYSS))] |
| "" |
| "fcpyss\t%0, %1, %2" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fmfcsr" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCSR))] |
| "" |
| "fmfcsr\t%0" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fmtcsr" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_FMTCSR)] |
| "" |
| "fmtcsr\t%0" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_fmfcfg" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCFG))] |
| "" |
| "fmfcfg\t%0" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; ------------------------------------------------------------------------ |
| |
| ;; Interrupt Instructions. |
| |
| (define_insn "unspec_volatile_setgie_en" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_EN)] |
| "" |
| "setgie.e" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_volatile_setgie_dis" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_DIS)] |
| "" |
| "setgie.d" |
| [(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 |
| |
| (define_insn "unspec_volatile_isync" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)] |
| "" |
| "isync\t%0" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_volatile_isb" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_ISB)] |
| "" |
| "isb" |
| [(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 |
| |
| (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")] |
| ) |
| |
| ;;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 |
| |
| (define_expand "unspec_ave" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "register_operand" "")] |
| "" |
| { |
| emit_insn (gen_ave (operands[0], operands[1], operands[2])); |
| DONE; |
| }) |
| |
| (define_expand "unspec_bclr" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "immediate_operand" "")] |
| "" |
| { |
| unsigned HOST_WIDE_INT val = ~(1u << UINTVAL (operands[2])); |
| emit_insn (gen_andsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); |
| DONE; |
| }) |
| |
| (define_expand "unspec_bset" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "immediate_operand" "")] |
| "" |
| { |
| unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]); |
| emit_insn (gen_iorsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); |
| DONE; |
| }) |
| |
| (define_expand "unspec_btgl" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "immediate_operand" "")] |
| "" |
| { |
| unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]); |
| emit_insn (gen_xorsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); |
| DONE; |
| }) |
| |
| (define_expand "unspec_btst" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "immediate_operand" "")] |
| "" |
| { |
| emit_insn (gen_btst (operands[0], operands[1], operands[2])); |
| DONE; |
| }) |
| |
| (define_insn "unspec_clip" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIP))] |
| "" |
| "clip\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_clips" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIPS))] |
| "" |
| "clips\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_clo" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_CLO))] |
| "" |
| "clo\t%0, %1" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_ssabssi2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ss_abs:SI (match_operand:SI 1 "register_operand" "r")))] |
| "" |
| "abs\t%0, %1" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; Performance extension 2 |
| |
| (define_insn "unspec_pbsad" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_PBSAD))] |
| "" |
| "pbsad\t%0, %1, %2" |
| [(set_attr "type" "pbsad") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_pbsada" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "0") |
| (match_operand:SI 2 "register_operand" "r") |
| (match_operand:SI 3 "register_operand" "r")] UNSPEC_PBSADA))] |
| "" |
| "pbsada\t%0, %2, %3" |
| [(set_attr "type" "pbsada") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "bse" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "register_operand" "")] |
| "" |
| { |
| rtx temp0 = gen_reg_rtx (SImode); |
| rtx temp2 = gen_reg_rtx (SImode); |
| |
| emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0])); |
| emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2])); |
| emit_insn (gen_unspec_bse (temp0, operands[1], temp2, temp0, temp2)); |
| emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0); |
| emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2); |
| DONE; |
| } |
| ) |
| |
| (define_insn "unspec_bse" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r") |
| (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSE)) |
| (set (match_operand:SI 4 "register_operand" "=2") |
| (unspec:SI [(match_dup 1) |
| (match_dup 2) |
| (match_dup 0)] UNSPEC_BSE_2))] |
| "" |
| "bse\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "bsp" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "register_operand" "")] |
| "" |
| { |
| rtx temp0 = gen_reg_rtx (SImode); |
| rtx temp2 = gen_reg_rtx (SImode); |
| |
| emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0])); |
| emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2])); |
| emit_insn (gen_unspec_bsp (temp0, operands[1], temp2, temp0, temp2)); |
| emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0); |
| emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2); |
| DONE; |
| } |
| ) |
| |
| (define_insn "unspec_bsp" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r") |
| (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSP)) |
| (set (match_operand:SI 4 "register_operand" "=2") |
| (unspec:SI [(match_dup 1) |
| (match_dup 2) |
| (match_dup 0)] UNSPEC_BSP_2))] |
| "" |
| "bsp\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; String Extension |
| |
| (define_insn "unspec_ffb" |
| [(set (match_operand:SI 0 "register_operand" "=r, r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r, r") |
| (match_operand:SI 2 "nonmemory_operand" "Iu08, r")] UNSPEC_FFB))] |
| "" |
| "@ |
| ffbi\t%0, %1, %2 |
| ffb\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_ffmism" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_FFMISM))] |
| "" |
| "ffmism\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_flmism" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_FLMISM))] |
| "" |
| "flmism\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; SATURATION |
| |
| (define_insn "unspec_kaddw" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ss_plus:SI (match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")))] |
| "" |
| "kaddw\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_ksubw" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ss_minus:SI (match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")))] |
| "" |
| "ksubw\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kaddh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_KADDH))] |
| "" |
| "kaddh\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_ksubh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSUBH))] |
| "" |
| "ksubh\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kaddh_dsp" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")) |
| (const_int 15)] UNSPEC_CLIPS))] |
| "NDS32_EXT_DSP_P ()" |
| "kaddh\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_ksubh_dsp" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(minus:SI (match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")) |
| (const_int 15)] UNSPEC_CLIPS))] |
| "NDS32_EXT_DSP_P ()" |
| "ksubh\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kdmbb" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBB))] |
| "" |
| "kdmbb\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kdmbt" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBT))] |
| "" |
| "kdmbt\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kdmtb" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTB))] |
| "" |
| "kdmtb\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kdmtt" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTT))] |
| "" |
| "kdmtt\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_khmbb" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBB))] |
| "" |
| "khmbb\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_khmbt" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBT))] |
| "" |
| "khmbt\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_khmtb" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTB))] |
| "" |
| "khmtb\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_khmtt" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") |
| (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTT))] |
| "" |
| "khmtt\t%0, %1, %2" |
| [(set_attr "type" "mul") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kslraw" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAW))] |
| "" |
| "kslraw\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_kslrawu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAWU))] |
| "" |
| "kslraw.u\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_volatile_rdov" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_RDOV))] |
| "" |
| "rdov\t%0" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_volatile_clrov" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLROV)] |
| "" |
| "clrov" |
| [(set_attr "type" "misc") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; System |
| |
| (define_insn "unspec_sva" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_SVA))] |
| "" |
| "sva\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_svs" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "register_operand" "r")] UNSPEC_SVS))] |
| "" |
| "svs\t%0, %1, %2" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_insn "unspec_jr_itoff" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_ITOFF)] |
| "" |
| "jr.itoff\t%0" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_jr_toff" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_TOFF)] |
| "" |
| "jr.toff\t%0" |
| [(set_attr "type" "branch")] |
| ) |
| |
| (define_insn "unspec_jral_iton" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_ITON)] |
| "" |
| "jral.iton\t%0" |
| [(set_attr "type" "branch")] |
| ) |
| |
| (define_insn "unspec_jral_ton" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_TON)] |
| "" |
| "jral.ton\t%0" |
| [(set_attr "type" "branch")] |
| ) |
| |
| (define_insn "unspec_ret_itoff" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_ITOFF)] |
| "" |
| "ret.itoff\t%0" |
| [(set_attr "type" "branch")] |
| ) |
| |
| (define_insn "unspec_ret_toff" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_TOFF)] |
| "" |
| "ret.toff\t%0" |
| [(set_attr "type" "branch")] |
| ) |
| |
| (define_insn "unspec_standby_no_wake_grant" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_NO_WAKE_GRANT)] |
| "" |
| "standby\tno_wake_grant" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_standby_wake_grant" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_GRANT)] |
| "" |
| "standby\twake_grant" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_standby_wait_done" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_DONE)] |
| "" |
| "standby\twait_done" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_teqz" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") |
| (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TEQZ)] |
| "" |
| "teqz\t%0, %1" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_tnez" |
| [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") |
| (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TNEZ)] |
| "" |
| "tnez\t%0, %1" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_trap" |
| [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_TRAP)] |
| "" |
| "trap\t%0" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_setend_big" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_BIG)] |
| "" |
| "setend.b" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_setend_little" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_LITTLE)] |
| "" |
| "setend.l" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_break" |
| [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_BREAK)] |
| "" |
| "break\t%0" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_syscall" |
| [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_SYSCALL)] |
| "" |
| "syscall\t%0" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_insn "unspec_nop" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NOP)] |
| "" |
| "nop" |
| [(set_attr "type" "misc")] |
| ) |
| |
| (define_expand "unspec_get_current_sp" |
| [(match_operand:SI 0 "register_operand" "")] |
| "" |
| { |
| emit_move_insn (operands[0], gen_rtx_REG (SImode, SP_REGNUM)); |
| DONE; |
| }) |
| |
| (define_expand "unspec_set_current_sp" |
| [(match_operand:SI 0 "register_operand" "")] |
| "" |
| { |
| emit_move_insn (gen_rtx_REG (SImode, SP_REGNUM), operands[0]); |
| DONE; |
| }) |
| |
| (define_expand "unspec_return_address" |
| [(match_operand:SI 0 "register_operand" "")] |
| "" |
| { |
| emit_move_insn (operands[0], gen_rtx_REG (SImode, LP_REGNUM)); |
| DONE; |
| }) |
| |
| ;; Swap |
| |
| (define_insn "unspec_wsbh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_WSBH))] |
| "" |
| "wsbh\t%0, %1" |
| [(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" |
| [(set (match_operand:HI 0 "register_operand" "") |
| (unspec:HI [(mem:HI (match_operand:SI 1 "register_operand" ""))] UNSPEC_UALOAD_HW))] |
| "" |
| { |
| operands[0] = simplify_gen_subreg (SImode, operands[0], |
| GET_MODE (operands[0]), 0); |
| if (TARGET_ISA_V3M) |
| { |
| nds32_expand_unaligned_load (operands, HImode); |
| } |
| else |
| { |
| emit_insn (gen_unaligned_load_w (operands[0], |
| gen_rtx_MEM (SImode, operands[1]))); |
| |
| if (WORDS_BIG_ENDIAN) |
| emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT(16))); |
| else |
| emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (0xffff))); |
| } |
| |
| DONE; |
| }) |
| |
| (define_expand "unaligned_loadsi" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_W))] |
| "" |
| { |
| if (flag_unaligned_access) |
| { |
| rtx mem = gen_rtx_MEM (SImode, operands[1]); |
| emit_move_insn (operands[0], mem); |
| } |
| else |
| { |
| if (TARGET_ISA_V3M) |
| nds32_expand_unaligned_load (operands, SImode); |
| else |
| emit_insn (gen_unaligned_load_w (operands[0], |
| gen_rtx_MEM (SImode, (operands[1])))); |
| } |
| DONE; |
| }) |
| |
| (define_insn "unaligned_load_w" |
| [(set (match_operand:SI 0 "register_operand" "= r") |
| (unspec:SI [(match_operand:SI 1 "nds32_lmw_smw_base_operand" " Umw")] UNSPEC_UALOAD_W))] |
| "" |
| { |
| return nds32_output_lmw_single_word (operands); |
| } |
| [(set_attr "type" "load") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "unaligned_loaddi" |
| [(set (match_operand:DI 0 "register_operand" "=r") |
| (unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))] |
| "" |
| { |
| if (TARGET_ISA_V3M) |
| { |
| nds32_expand_unaligned_load (operands, DImode); |
| } |
| else |
| emit_insn (gen_unaligned_load_dw (operands[0], operands[1])); |
| DONE; |
| }) |
| |
| (define_insn "unaligned_load_dw" |
| [(set (match_operand:DI 0 "register_operand" "=r") |
| (unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))] |
| "" |
| { |
| rtx otherops[3]; |
| otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0])); |
| otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); |
| otherops[2] = operands[1]; |
| |
| output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops); |
| return ""; |
| } |
| [(set_attr "type" "load") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "unaligned_store_hw" |
| [(set (mem:SI (match_operand:SI 0 "register_operand" "")) |
| (unspec:HI [(match_operand:HI 1 "register_operand" "")] UNSPEC_UASTORE_HW))] |
| "" |
| { |
| operands[1] = simplify_gen_subreg (SImode, operands[1], |
| GET_MODE (operands[1]), 0); |
| nds32_expand_unaligned_store (operands, HImode); |
| DONE; |
| }) |
| |
| (define_expand "unaligned_storesi" |
| [(set (mem:SI (match_operand:SI 0 "register_operand" "r")) |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_UASTORE_W))] |
| "" |
| { |
| if (flag_unaligned_access) |
| { |
| rtx mem = gen_rtx_MEM (SImode, operands[0]); |
| emit_move_insn (mem, operands[1]); |
| } |
| else |
| { |
| if (TARGET_ISA_V3M) |
| nds32_expand_unaligned_store (operands, SImode); |
| else |
| emit_insn (gen_unaligned_store_w (gen_rtx_MEM (SImode, operands[0]), |
| operands[1])); |
| } |
| DONE; |
| }) |
| |
| (define_insn "unaligned_store_w" |
| [(set (match_operand:SI 0 "nds32_lmw_smw_base_operand" "=Umw") |
| (unspec:SI [(match_operand:SI 1 "register_operand" " r")] UNSPEC_UASTORE_W))] |
| "" |
| { |
| return nds32_output_smw_single_word (operands); |
| } |
| [(set_attr "type" "store") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "unaligned_storedi" |
| [(set (mem:DI (match_operand:SI 0 "register_operand" "r")) |
| (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_UASTORE_DW))] |
| "" |
| { |
| if (TARGET_ISA_V3M) |
| nds32_expand_unaligned_store (operands, DImode); |
| else |
| emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[0]), |
| operands[1])); |
| DONE; |
| }) |
| |
| (define_insn "unaligned_store_dw" |
| [(set (match_operand:DI 0 "nds32_lmw_smw_base_operand" "=Umw") |
| (unspec:DI [(match_operand:DI 1 "register_operand" " r")] UNSPEC_UASTORE_DW))] |
| "" |
| { |
| return nds32_output_smw_double_word (operands); |
| } |
| [(set_attr "type" "store") |
| (set_attr "length" "4")] |
| ) |
| |
| (define_expand "unspec_unaligned_feature" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE))] |
| "" |
| { |
| /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ |
| rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); |
| rtx temp_reg = gen_reg_rtx (SImode); |
| rtx temp2_reg = gen_reg_rtx (SImode); |
| |
| emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); |
| emit_move_insn (temp_reg, operands[0]); |
| emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); |
| emit_insn (gen_iorsi3 (operands[0], operands[0], temp2_reg)); |
| emit_insn (gen_unspec_volatile_mtsr (operands[0], system_reg)); |
| emit_insn (gen_unspec_dsb ()); |
| |
| emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); |
| emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); |
| emit_insn (gen_unspec_dsb ()); |
| |
| emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (8))); |
| emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); |
| DONE; |
| }) |
| |
| (define_expand "unspec_enable_unaligned" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)] |
| "" |
| { |
| /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ |
| rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); |
| rtx temp_reg = gen_reg_rtx (SImode); |
| rtx temp2_reg = gen_reg_rtx (SImode); |
| emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); |
| emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); |
| emit_insn (gen_iorsi3 (temp_reg, temp_reg, temp2_reg)); |
| emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); |
| emit_insn (gen_unspec_dsb ()); |
| DONE; |
| }) |
| |
| (define_expand "unspec_disable_unaligned" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)] |
| "" |
| { |
| /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ |
| rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); |
| rtx temp_reg = gen_reg_rtx (SImode); |
| rtx temp2_reg = gen_reg_rtx (SImode); |
| emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); |
| emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); |
| emit_insn (gen_one_cmplsi2 (temp2_reg, temp2_reg)); |
| emit_insn (gen_andsi3 (temp_reg, temp_reg, temp2_reg)); |
| emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); |
| emit_insn (gen_unspec_dsb ()); |
| DONE; |
| }) |
| |
| ;; abs alias kabs |
| |
| (define_insn "unspec_kabs" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_KABS))] |
| "" |
| "kabs\t%0, %1" |
| [(set_attr "type" "alu") |
| (set_attr "length" "4")] |
| ) |
| |
| ;; ------------------------------------------------------------------------ |