;; Machine Description for MIPS MSA ASE
;; Based on the MIPS MSA spec Revision 1.07 30/8/2013
;; Contributed by Chao-ying Fu (fu@mips.com), MIPS Technologies, Inc.
;;
;; Copyright (C) 2014 Free Software Foundation, Inc.
;;
;; 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
;; .
;;
(define_c_enum "unspec" [
UNSPEC_MSA_ASUB_S
UNSPEC_MSA_ASUB_U
UNSPEC_MSA_AVE_S
UNSPEC_MSA_AVE_U
UNSPEC_MSA_AVER_S
UNSPEC_MSA_AVER_U
UNSPEC_MSA_BCLR
UNSPEC_MSA_BCLRI
UNSPEC_MSA_BINSL
UNSPEC_MSA_BINSLI
UNSPEC_MSA_BINSR
UNSPEC_MSA_BINSRI
UNSPEC_MSA_BMNZ_V
UNSPEC_MSA_BMNZI_B
UNSPEC_MSA_BMZ_V
UNSPEC_MSA_BMZI_B
UNSPEC_MSA_BNEG
UNSPEC_MSA_BNEGI
UNSPEC_MSA_BSEL_V
UNSPEC_MSA_BSELI_B
UNSPEC_MSA_BSET
UNSPEC_MSA_BSETI
UNSPEC_MSA_BNZ_V
UNSPEC_MSA_BZ_V
UNSPEC_MSA_BNZ
UNSPEC_MSA_BZ
UNSPEC_MSA_CFCMSA
UNSPEC_MSA_CMPI
UNSPEC_MSA_CTCMSA
UNSPEC_MSA_DOTP_S
UNSPEC_MSA_DOTP_U
UNSPEC_MSA_DPADD_S
UNSPEC_MSA_DPADD_U
UNSPEC_MSA_DPSUB_S
UNSPEC_MSA_DPSUB_U
UNSPEC_MSA_FCAF
UNSPEC_MSA_FCLASS
UNSPEC_MSA_FCUNE
UNSPEC_MSA_FEXDO
UNSPEC_MSA_FEXP2
UNSPEC_MSA_FEXUPL
UNSPEC_MSA_FEXUPR
UNSPEC_MSA_FFINT_S
UNSPEC_MSA_FFINT_U
UNSPEC_MSA_FFQL
UNSPEC_MSA_FFQR
UNSPEC_MSA_FLOG2
UNSPEC_MSA_FMAX_A
UNSPEC_MSA_FMIN_A
UNSPEC_MSA_FRCP
UNSPEC_MSA_FRINT
UNSPEC_MSA_FRSQRT
UNSPEC_MSA_FSAF
UNSPEC_MSA_FSEQ
UNSPEC_MSA_FSLE
UNSPEC_MSA_FSLT
UNSPEC_MSA_FSNE
UNSPEC_MSA_FSOR
UNSPEC_MSA_FSUEQ
UNSPEC_MSA_FSULE
UNSPEC_MSA_FSULT
UNSPEC_MSA_FSUN
UNSPEC_MSA_FSUNE
UNSPEC_MSA_FTINT_S
UNSPEC_MSA_FTINT_U
UNSPEC_MSA_FTRUNC_S
UNSPEC_MSA_FTRUNC_U
UNSPEC_MSA_FTQ
UNSPEC_MSA_HADD_S
UNSPEC_MSA_HADD_U
UNSPEC_MSA_HSUB_S
UNSPEC_MSA_HSUB_U
UNSPEC_MSA_MADD_Q
UNSPEC_MSA_MADDR_Q
UNSPEC_MSA_MAX_A
UNSPEC_MSA_MAXI_S
UNSPEC_MSA_MAXI_U
UNSPEC_MSA_MIN_A
UNSPEC_MSA_MINI_S
UNSPEC_MSA_MINI_U
UNSPEC_MSA_MSUB_Q
UNSPEC_MSA_MSUBR_Q
UNSPEC_MSA_MUL_Q
UNSPEC_MSA_MULR_Q
UNSPEC_MSA_NLOC
UNSPEC_MSA_NLZC
UNSPEC_MSA_NORI_B
UNSPEC_MSA_ORI_B
UNSPEC_MSA_PCKEV
UNSPEC_MSA_PCKOD
UNSPEC_MSA_PCNT
UNSPEC_MSA_SAT_S
UNSPEC_MSA_SAT_U
UNSPEC_MSA_SHF
UNSPEC_MSA_SLD
UNSPEC_MSA_SLDI
UNSPEC_MSA_SLLI
UNSPEC_MSA_SPLAT
UNSPEC_MSA_SPLATI
UNSPEC_MSA_SRAI
UNSPEC_MSA_SRAR
UNSPEC_MSA_SRARI
UNSPEC_MSA_SRLI
UNSPEC_MSA_SRLR
UNSPEC_MSA_SRLRI
UNSPEC_MSA_SUBS_S
UNSPEC_MSA_SUBS_U
UNSPEC_MSA_SUBSUU_S
UNSPEC_MSA_SUBSUS_U
UNSPEC_MSA_SUBVI
UNSPEC_MSA_TSTNZ_V
UNSPEC_MSA_TSTZ_V
UNSPEC_MSA_TSTNZ
UNSPEC_MSA_TSTZ
UNSPEC_MSA_VSHF
UNSPEC_MSA_XORI_B
UNSPEC_MSA_CAST_TO_SCALAR
UNSPEC_MSA_CAST_TO_VECTOR
])
;; Attributes to categorize MSA instructions based on execution units
(define_attr "msa_execunit"
"unknown, msa_eu_div, msa_eu_float2, msa_eu_float2_l,
msa_eu_float4, msa_eu_float5, msa_eu_float8, msa_eu_logic,
msa_eu_logic3, msa_eu_logic_l, msa_eu_mult, msa_eu_cmp,
msa_eu_store4, msa_eu_int_add, msa_eu_fdiv, msa_eu_logic_l2, msa_eu_logic2"
(const_string "unknown"))
(define_attr "datafmt"
"unknown, d, w, h, b"
(const_string "unknown"))
;; All vector modes with 128 bits.
(define_mode_iterator MODE128 [V2DF V4SF V2DI V4SI V8HI V16QI])
(define_mode_iterator MSA [V2DF V4SF V2DI V4SI V8HI V16QI])
;; Same as MSA. Used by vcond to iterate two modes.
(define_mode_iterator MSA_2 [V2DF V4SF V2DI V4SI V8HI V16QI])
;; Only integer modes.
(define_mode_iterator IMSA [V2DI V4SI V8HI V16QI])
;; mode that can combine a copy+insert into insve.
(define_mode_iterator INSVE [V2DI V4SI])
;; mode that can be combine copy+insert with subreg info insve.
(define_mode_iterator INSVE_2 [V8HI V16QI])
;; As IMSA but excludes V16QI.
(define_mode_iterator IMSA_X [V2DI V4SI V8HI])
;; As IMSA but excludes V2DI
(define_mode_iterator IMSA_X2 [V4SI V8HI V16QI])
;; Only integer modes for fixed-point madd_q/maddr_q.
(define_mode_iterator QMSA [V4SI V8HI])
;; Only floating-point modes.
(define_mode_iterator FMSA [V2DF V4SF])
;; Only integer modes for dot product.
(define_mode_iterator IDOTP128 [V2DI V4SI V8HI])
;; Only used in spliters
(define_mode_iterator SPLIT [V2DI V2DF])
(define_mode_attr DMSA
[(V2DI "V4DI")
(V4SI "V8SI")
(V8HI "V16HI")
(V16QI "V32QI")])
;; Only used with SPLIT iterator
(define_mode_attr predicate
[(V2DI "reg_or_0")
(V2DF "register")])
(define_mode_attr VHALFMODE
[(V8HI "V16QI")
(V4SI "V8HI")
(V2DI "V4SI")
(V2DF "V4SF")])
(define_mode_attr VDMODE
[(V4SI "V2DI")
(V8HI "V4SI")
(V16QI "V8HI")])
;; The attribute gives the integer vector mode with same size.
(define_mode_attr VIMODE
[(V2DF "V2DI")
(V4SF "V4SI")
(V2DI "V2DI")
(V4SI "V4SI")
(V8HI "V8HI")
(V16QI "V16QI")])
;; This attribute gives the integer vector mode with same size.
(define_mode_attr mode_i
[(V2DF "v2di")
(V4SF "v4si")
(V2DI "v2di")
(V4SI "v4si")
(V8HI "v8hi")
(V16QI "v16qi")])
;; This attribute gives the mode of the result for "copy_s_b, copy_u_b" etc.
(define_mode_attr RES
[(V2DF "DF")
(V4SF "SF")
(V2DI "DI")
(V4SI "SI")
(V8HI "SI")
(V16QI "SI")])
;; This attribute gives suffix for MSA instructions.
(define_mode_attr msafmt
[(V2DF "d")
(V4SF "w")
(V2DI "d")
(V4SI "w")
(V8HI "h")
(V16QI "b")])
;; This is used in msa_cast* to output mov.s or mov.d.
(define_mode_attr unitfmt
[(V2DF "d")
(V4SF "s")])
;; This attribute gives define_insn suffix for MSA instructions with need
;; distinction between integer and floating point.
(define_mode_attr msafmt_f
[(V2DF "d_f")
(V4SF "w_f")
(V2DI "d")
(V4SI "w")
(V8HI "h")
(V16QI "b")])
;; The mask for shift amounts.
(define_mode_attr shift_mask
[(V2DI "63")
(V4SI "31")
(V8HI "15")
(V16QI "7")])
;; This is used to form an immediate operand constraint using
;; "const__operand".
(define_mode_attr indeximm
[(V2DF "0_or_1")
(V4SF "0_to_3")
(V2DI "0_or_1")
(V4SI "0_to_3")
(V8HI "uimm3")
(V16QI "uimm4")])
;; To represent bitmask needed for vec_merge using "const__operand".
(define_mode_attr bitmask
[(V2DF "exp_2")
(V4SF "exp_4")
(V2DI "exp_2")
(V4SI "exp_4")
(V8HI "exp_8")
(V16QI "exp_16")])
;; This attribute is used to form the MODE of an input operand
;; when some builtins (insert snd fill) take an input operand other than
;; UNITMODE mode. See the msa_insert and msa_fill for an examples.
(define_mode_attr EXCEPT
[(V2DI "DI")
(V4SI "SI")
(V8HI "SI")
(V16QI "SI")])
;; This attribute used to form an immediate operand constraint using
;; "const__operand".
(define_mode_attr bitimm
[(V16QI "uimm3")
(V8HI "uimm4")
(V4SI "uimm5")
(V2DI "uimm6")
])
(define_expand "vec_init"
[(match_operand:MSA 0 "register_operand")
(match_operand:MSA 1 "")]
"ISA_HAS_MSA"
{
mips_expand_vector_init (operands[0], operands[1]);
DONE;
})
(define_mode_attr hmsafmt
[(V2DI "w")
(V4SI "h")
(V8HI "b")])
(define_expand "fixuns_trunc2"
[(set (match_operand: 0 "register_operand" "=f")
(unsigned_fix: (match_operand:FMSA 1 "register_operand" "f")))]
"ISA_HAS_MSA"
{
emit_insn (gen_msa_ftrunc_u_ (operands[0], operands[1]));
DONE;
})
(define_expand "fix_trunc2"
[(set (match_operand: 0 "register_operand" "=f")
(fix: (match_operand:FMSA 1 "register_operand" "f")))]
"ISA_HAS_MSA"
{
emit_insn (gen_msa_ftrunc_s_ (operands[0], operands[1]));
DONE;
})
(define_expand "vec_pack_trunc_v2df"
[(set (match_operand:V4SF 0 "register_operand")
(vec_concat:V4SF
(float_truncate:V2SF (match_operand:V2DF 1 "register_operand"))
(float_truncate:V2SF (match_operand:V2DF 2 "register_operand"))))]
"ISA_HAS_MSA"
"")
;; pckev pattern with implicit type conversion.
(define_insn "vec_pack_trunc_"
[(set (match_operand: 0 "register_operand" "=f")
(unspec: [(match_operand:IMSA_X 1 "register_operand" "f")
(match_operand:IMSA_X 2 "register_operand" "f")]
UNSPEC_MSA_PCKEV))]
"ISA_HAS_MSA"
"pckev.\t%w0,%w2,%w1"
[(set_attr "alu_type" "add")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic")])
(define_expand "vec_unpacks_hi_v4sf"
[(set (match_operand:V2DF 0 "register_operand" "=f")
(float_extend:V2DF
(vec_select:V2SF
(match_operand:V4SF 1 "register_operand" "f")
(parallel [(const_int 0) (const_int 1)])
)))]
"ISA_HAS_MSA"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_msa_fexupr_d (operands[0], operands[1]));
else
emit_insn (gen_msa_fexupl_d (operands[0], operands[1]));
DONE;
})
(define_expand "vec_unpacks_lo_v4sf"
[(set (match_operand:V2DF 0 "register_operand" "=f")
(float_extend:V2DF
(vec_select:V2SF
(match_operand:V4SF 1 "register_operand" "f")
(parallel [(const_int 0) (const_int 1)])
)))]
"ISA_HAS_MSA"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_msa_fexupl_d (operands[0], operands[1]));
else
emit_insn (gen_msa_fexupr_d (operands[0], operands[1]));
DONE;
})
(define_expand "vec_unpacks_hi_"
[(set (match_operand: 0 "register_operand")
(match_operand:IMSA_X2 1 "register_operand"))]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, false/*unsigned_p*/, true/*high_p*/);
DONE;
})
(define_expand "vec_unpacks_lo_"
[(set (match_operand: 0 "register_operand")
(match_operand:IMSA_X2 1 "register_operand"))]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, false/*unsigned_p*/, false/*high_p*/);
DONE;
})
(define_expand "vec_unpacku_hi_"
[(set (match_operand: 0 "register_operand")
(match_operand:IMSA_X2 1 "register_operand"))]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, true/*unsigned_p*/, true/*high_p*/);
DONE;
})
(define_expand "vec_unpacku_lo_"
[(set (match_operand: 0 "register_operand")
(match_operand:IMSA_X2 1 "register_operand"))]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, true/*unsigned_p*/, false/*high_p*/);
DONE;
})
(define_expand "vec_extract"
[(match_operand: 0 "register_operand")
(match_operand:IMSA 1 "register_operand")
(match_operand 2 "const__operand")]
"ISA_HAS_MSA"
{
if (mode == QImode || mode == HImode)
{
rtx dest1 = gen_reg_rtx (SImode);
emit_insn (gen_msa_copy_s_ (dest1, operands[1], operands[2]));
emit_move_insn (operands[0],
gen_lowpart (mode, dest1));
}
else
emit_insn (gen_msa_copy_s_ (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_extract"
[(match_operand: 0 "register_operand")
(match_operand:FMSA 1 "register_operand")
(match_operand 2 "const__operand")]
"ISA_HAS_MSA"
{
rtx temp;
HOST_WIDE_INT val = UINTVAL (operands[2]);
if (val == 0)
temp = operands[1];
else
{
/* We need to do the SLDI operation in V16QImode and adjust
operand[2] accordingly. */
rtx tempb = gen_reg_rtx (V16QImode);
rtx op1b = gen_reg_rtx (V16QImode);
emit_move_insn (op1b, gen_rtx_SUBREG (V16QImode, operands[1], 0));
rtx op2b = GEN_INT (val * GET_MODE_SIZE (mode));
gcc_assert (UINTVAL (op2b) < GET_MODE_NUNITS (V16QImode));
emit_insn (gen_msa_sldi_b (tempb, op1b, op1b, op2b));
temp = gen_reg_rtx (mode);
emit_move_insn (temp, gen_rtx_SUBREG (mode, tempb, 0));
}
emit_insn (gen_msa_cast_to_scalar_ (operands[0], temp));
DONE;
})
(define_expand "vec_set"
[(match_operand:IMSA 0 "register_operand")
(match_operand: 1 "reg_or_0_operand")
(match_operand 2 "const__operand")]
"ISA_HAS_MSA"
{
emit_insn (gen_msa_insert__insn (operands[0], operands[1],
operands[0], GEN_INT(1 << INTVAL (operands[2]))));
DONE;
})
(define_expand "vec_set"
[(match_operand:FMSA 0 "register_operand")
(match_operand: 1 "register_operand")
(match_operand 2 "const__operand")]
"ISA_HAS_MSA"
{
emit_insn (gen_msa_insve__s (operands[0], operands[0],
GEN_INT(1 << INTVAL (operands[2])), operands[1]));
DONE;
})
(define_expand "vcondu"
[(set (match_operand:MSA_2 0 "register_operand")
(if_then_else:MSA_2
(match_operator 3 ""
[(match_operand:IMSA 4 "register_operand")
(match_operand:IMSA 5 "register_operand")])
(match_operand:MSA_2 1 "reg_or_m1_operand")
(match_operand:MSA_2 2 "reg_or_0_operand")))]
"ISA_HAS_MSA
&& (GET_MODE_NUNITS (mode)
== GET_MODE_NUNITS (mode))"
{
mips_expand_vec_cond_expr (mode,
mode,
operands,
gen_and3,
gen_msa_nor_v_,
gen_ior3);
DONE;
})
(define_expand "vcond"
[(set (match_operand:MSA_2 0 "register_operand")
(if_then_else:MSA_2
(match_operator 3 ""
[(match_operand:MSA 4 "register_operand")
(match_operand:MSA 5 "register_operand")])
(match_operand:MSA_2 1 "reg_or_m1_operand")
(match_operand:MSA_2 2 "reg_or_0_operand")))]
"ISA_HAS_MSA
&& (GET_MODE_NUNITS (mode)
== GET_MODE_NUNITS (mode))"
{
mips_expand_vec_cond_expr (mode,
mode,
operands,
gen_and3,
gen_msa_nor_v_,
gen_ior3);
DONE;
})
;; Note used directly by builtins but via the following define_expand.
(define_insn "msa_insert__insn"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(vec_merge:IMSA (vec_duplicate:IMSA
(match_operand: 1 "reg_or_0_operand" "dJ"))
(match_operand:IMSA 2 "register_operand" "0")
(match_operand 3 "const__operand" "")))]
"ISA_HAS_MSA"
"insert.\t%w0[%K3],%z1"
[(set_attr "type" "mtc")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; Expand builtin catoring for HImode and QImode which take SImode.
(define_expand "msa_insert_"
[(match_operand:IMSA 0 "register_operand")
(match_operand:IMSA 1 "register_operand")
(match_operand 2 "const__operand")
(match_operand: 3 "reg_or_0_operand")]
"ISA_HAS_MSA"
{
if ((GET_MODE_SIZE (mode) < GET_MODE_SIZE (mode))
&& (REG_P (operands[3]) || (GET_CODE (operands[3]) == SUBREG
&& REG_P (SUBREG_REG (operands[3])))))
{
unsigned int offset = GET_MODE_SIZE (mode)
- GET_MODE_SIZE (mode);
operands[3] = simplify_gen_subreg (mode, operands[3],
GET_MODE (operands[3]),
BYTES_BIG_ENDIAN ? offset : 0);
}
emit_insn (gen_msa_insert__insn (operands[0], operands[3],
operands[1], GEN_INT(1 << INTVAL (operands[2]))));
DONE;
})
(define_expand "msa_insert_"
[(match_operand:FMSA 0 "register_operand")
(match_operand:FMSA 1 "register_operand")
(match_operand 2 "const__operand")
(match_operand: 3 "reg_or_0_operand")]
"ISA_HAS_MSA"
{
emit_insn (gen_msa_insert__insn (operands[0], operands[3],
operands[1], GEN_INT(1 << INTVAL (operands[2]))));
DONE;
})
(define_insn "msa_insert__insn"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(vec_merge:FMSA (vec_duplicate:FMSA
(match_operand: 1 "register_operand" "d"))
(match_operand:FMSA 2 "register_operand" "0")
(match_operand 3 "const__operand" "")))]
"ISA_HAS_MSA"
"insert.\t%w0[%K3],%z1"
[(set_attr "type" "mtc")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
(define_split
[(set (match_operand:SPLIT 0 "register_operand")
(vec_merge:SPLIT
(vec_duplicate:SPLIT
(match_operand: 1 "_operand"))
(match_operand:SPLIT 2 "register_operand")
(match_operand 3 "const__operand")))]
"reload_completed && TARGET_MSA && !TARGET_64BIT"
[(const_int 0)]
{
mips_split_msa_insert_d (operands[0], operands[2], operands[3], operands[1]);
DONE;
})
;; Used by combine to convert a copy_s + insert into an insve
(define_insn "msa_insve_s_insn_"
[(set (match_operand:INSVE 0 "register_operand" "=f")
(vec_merge:INSVE
(vec_duplicate:INSVE
(sign_extend:
(vec_select:
(match_operand:INSVE 3 "register_operand" "f")
(parallel [(match_operand 4 "const_0_operand" "")]))))
(match_operand:INSVE 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; Used by combine to convert a copy_u + insert into an insve
(define_insn "msa_insve_u_insn_"
[(set (match_operand:INSVE 0 "register_operand" "=f")
(vec_merge:INSVE
(vec_duplicate:INSVE
(zero_extend:
(vec_select:
(match_operand:INSVE 3 "register_operand" "f")
(parallel [(match_operand 4 "const_0_operand" "")]))))
(match_operand:INSVE 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; Used by combine to convert a copy_s + insert with subreg into an insve
(define_insn "*msa_insve_sext_insn_"
[(set (match_operand:INSVE_2 0 "register_operand" "=f")
(vec_merge:INSVE_2
(vec_duplicate:INSVE_2
(subreg:
(sign_extend:
(vec_select:
(match_operand:INSVE_2 3 "register_operand" "f")
(parallel [(match_operand 4 "const_0_operand" "")]))) 0))
(match_operand:INSVE_2 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; Used by combine to convert a copy_u + insert with subreg into an insve
(define_insn "*msa_insve_zext_insn_"
[(set (match_operand:INSVE_2 0 "register_operand" "=f")
(vec_merge:INSVE_2
(vec_duplicate:INSVE_2
(subreg:
(zero_extend:
(vec_select:
(match_operand:INSVE_2 3 "register_operand" "f")
(parallel [(match_operand 4 "const_0_operand" "")]))) 0))
(match_operand:INSVE_2 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
(define_expand "msa_insve_"
[(set (match_operand:MSA 0 "register_operand")
(vec_merge:MSA (vec_duplicate:MSA
(vec_select:
(match_operand:MSA 3 "register_operand")
(parallel [(const_int 0)])))
(match_operand:MSA 1 "register_operand")
(match_operand 2 "const__operand")))]
"ISA_HAS_MSA"
{
operands[2] = GEN_INT ((1 << INTVAL (operands[2])));
})
(define_insn "msa_insve__insn"
[(set (match_operand:MSA 0 "register_operand" "=f")
(vec_merge:MSA (vec_duplicate:MSA
(vec_select:
(match_operand:MSA 3 "register_operand" "f")
(parallel [(const_int 0)])))
(match_operand:MSA 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; operand 3 is a scalar
(define_insn "msa_insve__f_s"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(vec_merge:FMSA (vec_duplicate:FMSA
(match_operand: 3 "register_operand" "f"))
(match_operand:FMSA 1 "register_operand" "0")
(match_operand 2 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%K2],%w3[0]"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic_l")])
;; Note that copy_s.d and copy_s.d_f will be split later if !TARGET_64BIT.
(define_insn "msa_copy_s_"
[(set (match_operand: 0 "register_operand" "=d")
(sign_extend:
(vec_select:
(match_operand:MSA 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")]))))]
"ISA_HAS_MSA"
"copy_s.\t%0,%w1[%2]"
[(set_attr "type" "mfc")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_store4")])
(define_split
[(set (match_operand: 0 "register_operand")
(sign_extend:
(vec_select:
(match_operand:SPLIT 1 "register_operand")
(parallel [(match_operand 2 "const_0_or_1_operand")]))))]
"reload_completed && TARGET_MSA && !TARGET_64BIT"
[(const_int 0)]
{
mips_split_msa_copy_d (operands[0], operands[1], operands[2], gen_msa_copy_s_w);
DONE;
})
;; Note that copy_u.d and copy_u.d_f will be split later if !TARGET_64BIT.
(define_insn "msa_copy_u_"
[(set (match_operand: 0 "register_operand" "=d")
(zero_extend:
(vec_select:
(match_operand:MSA 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")]))))]
"ISA_HAS_MSA"
"copy_u.\t%0,%w1[%2]"
[(set_attr "type" "mfc")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_store4")])
(define_split
[(set (match_operand: 0 "register_operand")
(zero_extend:
(vec_select:
(match_operand:SPLIT 1 "register_operand")
(parallel [(match_operand 2 "const_0_or_1_operand")]))))]
"reload_completed && TARGET_MSA && !TARGET_64BIT"
[(const_int 0)]
{
mips_split_msa_copy_d (operands[0], operands[1], operands[2], gen_msa_copy_u_w);
DONE;
})
(define_expand "vec_perm"
[(match_operand:MSA 0 "register_operand")
(match_operand:MSA 1 "register_operand")
(match_operand:MSA 2 "register_operand")
(match_operand: 3 "register_operand")]
"ISA_HAS_MSA"
{
/* The optab semantics are that index 0 selects the first element
of operands[1] and the highest index selects the last element
of operands[2]. This is the oppossite order from "vshf.df wd,rs,wt"
where index 0 selects the first element of wt and the highest index
selects the last element of ws. We therefore swap the operands here. */
emit_insn (gen_msa_vshf (operands[0], operands[3], operands[2],
operands[1]));
DONE;
})
(define_expand "vec_perm_const"
[(match_operand:MSA 0 "register_operand")
(match_operand:MSA 1 "register_operand")
(match_operand:MSA 2 "register_operand")
(match_operand: 3 "")]
"ISA_HAS_MSA"
{
if (mips_expand_vec_perm_const (operands))
DONE;
else
FAIL;
})
(define_expand "abs2"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(abs:IMSA (match_operand:IMSA 1 "register_operand" "f")))]
"ISA_HAS_MSA"
{
rtx reg = gen_reg_rtx (mode);
emit_insn (gen_msa_ldi (reg, const0_rtx));
emit_insn (gen_msa_add_a_ (operands[0], operands[1], reg));
DONE;
})
(define_expand "neg2"
[(match_operand:IMSA 0 "register_operand")
(match_operand:IMSA 1 "register_operand")]
"ISA_HAS_MSA"
{
rtx reg = gen_reg_rtx (mode);
emit_insn (gen_msa_ldi (reg, const0_rtx));
emit_insn (gen_sub3 (operands[0], reg, operands[1]));
DONE;
})
(define_expand "neg2"
[(match_operand:FMSA 0 "register_operand")
(match_operand:FMSA 1 "register_operand")]
"ISA_HAS_MSA"
{
rtx reg = gen_reg_rtx (mode);
emit_move_insn (reg, CONST0_RTX (mode));
emit_insn (gen_sub3 (operands[0], reg, operands[1]));
DONE;
})
(define_expand "msa_ldi"
[(match_operand:IMSA 0 "register_operand")
(match_operand 1 "const_imm10_operand")]
"ISA_HAS_MSA"
{
unsigned n_elts = GET_MODE_NUNITS (mode);
rtvec v = rtvec_alloc (n_elts);
HOST_WIDE_INT val = INTVAL (operands[1]);
unsigned int i;
if (mode != V16QImode)
{
unsigned shift = HOST_BITS_PER_WIDE_INT - 10;
val = trunc_int_for_mode ((val << shift) >> shift, mode);
}
else
val = trunc_int_for_mode (val, mode);
for (i = 0; i < n_elts; i++)
RTVEC_ELT (v, i) = GEN_INT (val);
emit_move_insn (operands[0],
gen_rtx_CONST_VECTOR (mode, v));
DONE;
})
(define_insn "msa_vshf"
[(set (match_operand:MSA 0 "register_operand" "=f")
(unspec:MSA [(match_operand: 1 "register_operand" "0")
(match_operand:MSA 2 "register_operand" "f")
(match_operand:MSA 3 "register_operand" "f")]
UNSPEC_MSA_VSHF))]
"ISA_HAS_MSA"
"vshf.\t%w0,%w2,%w3"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (eq_attr "cpu" "i6400")
(const_string "msa_eu_logic_l2")
(const_string "msa_eu_logic_l")))])
(define_expand "mov"
[(set (match_operand:MSA 0)
(match_operand:MSA 1))]
"TARGET_MSA"
{
if (mips_legitimize_move (mode, operands[0], operands[1]))
DONE;
})
(define_expand "movmisalign"
[(set (match_operand:MSA 0)
(match_operand:MSA 1))]
"TARGET_MSA"
{
if (mips_legitimize_move (mode, operands[0], operands[1]))
DONE;
})
;; 128bit MSA modes only in msa registers or memory. An exception is allowing
;; MSA modes for GP registers for arguments and return values.
(define_insn "mov_msa"
[(set (match_operand:MSA 0 "nonimmediate_operand" "=f,f,R,*d,*f")
(match_operand:MSA 1 "move_operand" "fYGYI,R,f,*f,*d"))]
"TARGET_MSA"
{ return mips_output_move (operands[0], operands[1]); }
[(set_attr "move_type" "fmove,fpload,fpstore,mfc,mtc")
(set_attr "mode" "TI")])
(define_split
[(set (match_operand:MSA 0 "nonimmediate_operand")
(match_operand:MSA 1 "move_operand"))]
"reload_completed && TARGET_MSA
&& mips_split_move_insn_p (operands[0], operands[1], insn)"
[(const_int 0)]
{
mips_split_move_insn (operands[0], operands[1], curr_insn);
DONE;
})
;; Offset load
(define_expand "msa_ld_"
[(match_operand:MSA 0 "register_operand")
(match_operand 1 "pmode_register_operand")
(match_operand 2 "aq10_operand")]
"ISA_HAS_MSA"
{
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
INTVAL (operands[2]));
mips_emit_move (operands[0], gen_rtx_MEM (mode, addr));
DONE;
})
;; Offset store
(define_expand "msa_st_"
[(match_operand:MSA 0 "register_operand")
(match_operand 1 "pmode_register_operand")
(match_operand 2 "aq10_operand")]
"ISA_HAS_MSA"
{
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
INTVAL (operands[2]));
mips_emit_move (gen_rtx_MEM (mode, addr), operands[0]);
DONE;
})
;; Integer operations
(define_insn "add3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
(plus:IMSA (match_operand:IMSA 1 "register_operand" "f,f,f")
(match_operand:IMSA 2 "reg_or_vector_same_ximm5_operand" "f,Unv5,Uuv5")))]
"ISA_HAS_MSA"
{
switch (which_alternative)
{
case 0:
return "addv.\t%w0,%w1,%w2";
case 1:
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
operands[2] = GEN_INT (-val);
return "subvi.\t%w0,%w1,%d2";
}
case 2:
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
operands[2] = GEN_INT (val);
return "addvi.\t%w0,%w1,%d2";
}
default:
gcc_unreachable ();
}
}
[(set_attr "alu_type" "add, unknown, unknown")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_int_add")])
(define_insn "sub3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
(minus:IMSA (match_operand:IMSA 1 "register_operand" "f,f,f")
(match_operand:IMSA 2 "reg_or_vector_same_ximm5_operand" "f,Unv5,Uuv5")))]
"ISA_HAS_MSA"
{
switch (which_alternative)
{
case 0:
return "subv.\t%w0,%w1,%w2";
case 1:
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
operands[2] = GEN_INT (-val);
return "addvi.\t%w0,%w1,%d2";
}
case 2:
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
operands[2] = GEN_INT (val);
return "subvi.\t%w0,%w1,%d2";
}
default:
gcc_unreachable ();
}
}
[(set_attr "alu_type" "sub, unknown, unknown")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_int_add")])
(define_insn "mul3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(mult:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"mulv.\t%w0,%w1,%w2"
[(set_attr "type" "imul3")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_mult")])
(define_insn "msa_maddv_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(plus:IMSA (mult:IMSA (match_operand:IMSA 2 "register_operand" "f")
(match_operand:IMSA 3 "register_operand" "f"))
(match_operand:IMSA 1 "register_operand" "0")))]
"ISA_HAS_MSA"
"maddv.\t%w0,%w2,%w3"
[(set_attr "type" "imadd")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_mult")])
(define_insn "msa_msubv_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(minus:IMSA (match_operand:IMSA 1 "register_operand" "0")
(mult:IMSA (match_operand:IMSA 2 "register_operand" "f")
(match_operand:IMSA 3 "register_operand" "f"))))]
"ISA_HAS_MSA"
"msubv.\t%w0,%w2,%w3"
[(set_attr "type" "imadd")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_mult")])
(define_insn "div3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(div:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
{ return mips_msa_output_division ("div_s.\t%w0,%w1,%w2", operands); }
[(set_attr "type" "idiv3")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_div")])
(define_insn "udiv3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(udiv:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
{ return mips_msa_output_division ("div_u.\t%w0,%w1,%w2", operands); }
[(set_attr "type" "idiv3")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_div")])
(define_insn "mod3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(mod:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
{ return mips_msa_output_division ("mod_s.\t%w0,%w1,%w2", operands); }
[(set_attr "type" "idiv3")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_div")])
(define_insn "umod3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(umod:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
{ return mips_msa_output_division ("mod_u.\t%w0,%w1,%w2", operands); }
[(set_attr "type" "idiv3")
(set_attr "mode" "TI")
(set_attr "datafmt" "")
(set_attr "msa_execunit" "msa_eu_div")])
(define_insn "xorv16qi3"
[(set (match_operand:V16QI 0 "register_operand" "=f,f")
(xor:V16QI (match_operand:V16QI 1 "register_operand" "f,f")
(match_operand:V16QI 2 "reg_or_vector_same_byte_operand" "f,Ubv8")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
operands[2] = CONST_VECTOR_ELT (operands[2], 0);
return "xori.b\t%w0,%w1,%B2";
}
else
return "xor.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "xor")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic")])
(define_insn "xor3"
[(set (match_operand:IMSA_X 0 "register_operand" "=f,f")
(xor:IMSA_X (match_operand:IMSA_X 1 "register_operand" "f,f")
(match_operand:IMSA_X 2 "reg_or_vector_same__set_operand" "f,YC")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
int vlog2 = exact_log2 (val);
gcc_assert (vlog2 != -1);
operands[2] = GEN_INT (vlog2);
return "bnegi.%v0\t%w0,%w1,%2";
}
else
return "xor.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "xor")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (and (eq_attr "cpu" "i6400")
(eq_attr "alternative" "1"))
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
(define_insn "iorv16qi3"
[(set (match_operand:V16QI 0 "register_operand" "=f,f")
(ior:V16QI (match_operand:V16QI 1 "register_operand" "f,f")
(match_operand:V16QI 2 "reg_or_vector_same_byte_operand" "f,Ubv8")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
operands[2] = CONST_VECTOR_ELT (operands[2], 0);
return "ori.b\t%w0,%w1,%B2";
}
else
return "or.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "or")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic")])
(define_insn "ior3"
[(set (match_operand:IMSA_X 0 "register_operand" "=f,f")
(ior:IMSA_X (match_operand:IMSA_X 1 "register_operand" "f,f")
(match_operand:IMSA_X 2 "reg_or_vector_same__set_operand" "f,YC")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
int vlog2 = exact_log2 (val);
gcc_assert (vlog2 != -1);
operands[2] = GEN_INT (vlog2);
return "bseti.%v0\t%w0,%w1,%2";
}
else
return "or.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "or")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (and (eq_attr "cpu" "i6400")
(eq_attr "alternative" "1"))
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
(define_insn "andv16qi3"
[(set (match_operand:V16QI 0 "register_operand" "=f,f")
(and:V16QI (match_operand:V16QI 1 "register_operand" "f,f")
(match_operand:V16QI 2 "reg_or_vector_same_byte_operand" "f,Ubv8")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
operands[2] = CONST_VECTOR_ELT (operands[2], 0);
return "andi.b\t%w0,%w1,%B2";
}
else
return "and.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "and")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic")])
(define_insn "and3"
[(set (match_operand:IMSA_X 0 "register_operand" "=f,f")
(and:IMSA_X (match_operand:IMSA_X 1 "register_operand" "f,f")
(match_operand:IMSA_X 2 "reg_or_vector_same__clr_operand" "f,YZ")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
{
HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
int vlog2 = exact_log2 (~val);
gcc_assert (vlog2 != -1);
operands[2] = GEN_INT (vlog2);
return "bclri.%v0\t%w0,%w1,%2";
}
else
return "and.v\t%w0,%w1,%w2";
}
[(set_attr "alu_type" "and")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (and (eq_attr "cpu" "i6400")
(eq_attr "alternative" "1"))
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
(define_insn "one_cmpl2"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(not:IMSA (match_operand:IMSA 1 "register_operand" "f")))]
"ISA_HAS_MSA"
"nor.v\t%w0,%w1,%w1"
[(set_attr "alu_type" "nor")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_logic")])
(define_insn "vlshr3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f")
(lshiftrt:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
(match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
"ISA_HAS_MSA"
{
if (which_alternative == 0)
return "srl.\t%w0,%w1,%w2";
operands[2] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[2], 0))
& );
return "srli.\t%w0,%w1,%2";
}
[(set_attr "type" "shift")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (eq_attr "cpu" "i6400")
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
(define_insn "vashr3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f")
(ashiftrt:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
(match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
"ISA_HAS_MSA"
{
if (which_alternative == 0)
return "sra.\t%w0,%w1,%w2";
operands[2] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[2], 0))
& );
return "srai.\t%w0,%w1,%2";
}
[(set_attr "type" "shift")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (eq_attr "cpu" "i6400")
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
(define_insn "vashl3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f")
(ashift:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
(match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
"ISA_HAS_MSA"
{
if (which_alternative == 0)
return "sll.\t%w0,%w1,%w2";
operands[2] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[2], 0))
& );
return "slli.\t%w0,%w1,%2";
}
[(set_attr "type" "shift")
(set_attr "mode" "TI")
(set (attr "msa_execunit")
(if_then_else (eq_attr "cpu" "i6400")
(const_string "msa_eu_logic2")
(const_string "msa_eu_logic")))])
;; Floating-point operations
(define_insn "add3"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(plus:FMSA (match_operand:FMSA 1 "register_operand" "f")
(match_operand:FMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"fadd.\t%w0,%w1,%w2"
[(set_attr "type" "fadd")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_float4")])
(define_insn "sub3"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(minus:FMSA (match_operand:FMSA 1 "register_operand" "f")
(match_operand:FMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"fsub.\t%w0,%w1,%w2"
[(set_attr "type" "fadd")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_float4")])
(define_insn "mul3"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(mult:FMSA (match_operand:FMSA 1 "register_operand" "f")
(match_operand:FMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"fmul.\t%w0,%w1,%w2"
[(set_attr "type" "fmul")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_float5")])
(define_insn "div3"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(div:FMSA (match_operand:FMSA 1 "register_operand" "f")
(match_operand:FMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"fdiv.\t%w0,%w1,%w2"
[(set_attr "type" "fdiv")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_fdiv")])
(define_insn "msa_fmadd_"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(plus:FMSA (mult:FMSA (match_operand:FMSA 2 "register_operand" "f")
(match_operand:FMSA 3 "register_operand" "f"))
(match_operand:FMSA 1 "register_operand" "0")))]
"ISA_HAS_MSA"
"fmadd.\t%w0,%w2,%w3"
[(set_attr "type" "fmadd")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_float8")])
(define_insn "msa_fmsub_"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(minus:FMSA (match_operand:FMSA 1 "register_operand" "0")
(mult:FMSA (match_operand:FMSA 2 "register_operand" "f")
(match_operand:FMSA 3 "register_operand" "f"))))]
"ISA_HAS_MSA"
"fmsub.\t%w0,%w2,%w3"
[(set_attr "type" "fmadd")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_float8")])
(define_insn "sqrt2"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(sqrt:FMSA (match_operand:FMSA 1 "register_operand" "f")))]
"ISA_HAS_MSA"
"fsqrt.\t%w0,%w1"
[(set_attr "type" "fsqrt")
(set_attr "mode" "")
(set_attr "msa_execunit" "msa_eu_fdiv")])
;; Built-in functions
(define_insn "msa_add_a_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(plus:IMSA (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
(abs:IMSA (match_operand:IMSA 2 "register_operand" "f"))))]
"ISA_HAS_MSA"
"add_a.\t%w0,%w1,%w2"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_int_add")])
(define_insn "msa_adds_a_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(ss_plus:IMSA (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
(abs:IMSA (match_operand:IMSA 2 "register_operand" "f"))))]
"ISA_HAS_MSA"
"adds_a.\t%w0,%w1,%w2"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_int_add")])
(define_insn "ssadd3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(ss_plus:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"adds_s.\t%w0,%w1,%w2"
[(set_attr "type" "arith")
(set_attr "mode" "TI")
(set_attr "msa_execunit" "msa_eu_int_add")])
(define_insn "usadd3"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(us_plus:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")))]
"ISA_HAS_MSA"
"adds_u.