1686 lines
48 KiB
Markdown
1686 lines
48 KiB
Markdown
|
;; 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")]
|
||
|
)
|
||
|
|
||
|
;; ------------------------------------------------------------------------
|