;; Machine Description for MIPS MSA ASE
;; Based on the MIPS MSA spec Revision 1.11 8/4/2014
;;
;; Copyright (C) 2015-2020 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_BNEG
UNSPEC_MSA_BNEGI
UNSPEC_MSA_BSET
UNSPEC_MSA_BSETI
UNSPEC_MSA_BRANCH_V
UNSPEC_MSA_BRANCH
UNSPEC_MSA_CFCMSA
UNSPEC_MSA_CTCMSA
UNSPEC_MSA_FCAF
UNSPEC_MSA_FCLASS
UNSPEC_MSA_FCUNE
UNSPEC_MSA_FEXDO
UNSPEC_MSA_FEXP2
UNSPEC_MSA_FEXUPL
UNSPEC_MSA_FEXUPR
UNSPEC_MSA_FFQL
UNSPEC_MSA_FFQR
UNSPEC_MSA_FLOG2
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_FTQ
UNSPEC_MSA_MADD_Q
UNSPEC_MSA_MADDR_Q
UNSPEC_MSA_MSUB_Q
UNSPEC_MSA_MSUBR_Q
UNSPEC_MSA_MUL_Q
UNSPEC_MSA_MULR_Q
UNSPEC_MSA_NLOC
UNSPEC_MSA_SAT_S
UNSPEC_MSA_SAT_U
UNSPEC_MSA_SLD
UNSPEC_MSA_SLDI
UNSPEC_MSA_SPLAT
UNSPEC_MSA_SPLATI
UNSPEC_MSA_SRAR
UNSPEC_MSA_SRARI
UNSPEC_MSA_SRLR
UNSPEC_MSA_SRLRI
UNSPEC_MSA_SUBS_S
UNSPEC_MSA_SUBS_U
UNSPEC_MSA_SUBSUU_S
UNSPEC_MSA_SUBSUS_U
UNSPEC_MSA_VSHF
])
;; All vector modes with 128 bits.
(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 used for splitting insert_d and copy_{u,s}.d.
(define_mode_iterator MSA_D [V2DI V2DF])
;; Only used for copy_{u,s}.w.
(define_mode_iterator MSA_W [V4SI V4SF])
;; Only integer modes.
(define_mode_iterator IMSA [V2DI V4SI V8HI V16QI])
;; As IMSA but excludes V16QI.
(define_mode_iterator IMSA_DWH [V2DI V4SI V8HI])
;; As IMSA but excludes V2DI.
(define_mode_iterator IMSA_WHB [V4SI V8HI V16QI])
;; Only integer modes equal or larger than a word.
(define_mode_iterator IMSA_DW [V2DI V4SI])
;; Only integer modes smaller than a word.
(define_mode_iterator IMSA_HB [V8HI V16QI])
;; Only integer modes for fixed-point madd_q/maddr_q.
(define_mode_iterator IMSA_WH [V4SI V8HI])
;; Only floating-point modes.
(define_mode_iterator FMSA [V2DF V4SF])
;; Only used for immediate set shuffle elements instruction.
(define_mode_iterator MSA_WHB_W [V4SI V8HI V16QI V4SF])
;; 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")])
;; The attribute gives half modes for vector modes.
(define_mode_attr VHMODE
[(V8HI "V16QI")
(V4SI "V8HI")
(V2DI "V4SI")])
;; The attribute gives double modes for vector modes.
(define_mode_attr VDMODE
[(V4SI "V2DI")
(V8HI "V4SI")
(V16QI "V8HI")])
;; The attribute gives half modes with same number of elements for vector modes.
(define_mode_attr VTRUNCMODE
[(V8HI "V8QI")
(V4SI "V4HI")
(V2DI "V2SI")])
;; This attribute gives the mode of the result for "copy_s_b, copy_u_b" etc.
(define_mode_attr VRES
[(V2DF "DF")
(V4SF "SF")
(V2DI "DI")
(V4SI "SI")
(V8HI "SI")
(V16QI "SI")])
;; Only used with MSA_D iterator.
(define_mode_attr msa_d
[(V2DI "reg_or_0")
(V2DF "register")])
;; 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 suffix for MSA instructions.
(define_mode_attr msafmt
[(V2DF "d")
(V4SF "w")
(V2DI "d")
(V4SI "w")
(V8HI "h")
(V16QI "b")])
;; This attribute gives suffix for integers in VHMODE.
(define_mode_attr hmsafmt
[(V2DI "w")
(V4SI "h")
(V8HI "b")])
;; This attribute gives define_insn suffix for MSA instructions that 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")])
;; 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")])
;; This attribute represents 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 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;
})
;; pckev pattern with implicit type conversion.
(define_insn "vec_pack_trunc_"
[(set (match_operand: 0 "register_operand" "=f")
(vec_concat:
(truncate:
(match_operand:IMSA_DWH 1 "register_operand" "f"))
(truncate:
(match_operand:IMSA_DWH 2 "register_operand" "f"))))]
"ISA_HAS_MSA"
"pckev.\t%w0,%w2,%w1"
[(set_attr "type" "simd_permute")
(set_attr "mode" "")])
(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")
(match_dup 2))))]
"ISA_HAS_MSA"
{
operands[2] = mips_msa_vec_parallel_const_half (V4SFmode, true/*high_p*/);
})
(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")
(match_dup 2))))]
"ISA_HAS_MSA"
{
operands[2] = mips_msa_vec_parallel_const_half (V4SFmode, false/*high_p*/);
})
(define_expand "vec_unpacks_hi_"
[(match_operand: 0 "register_operand")
(match_operand:IMSA_WHB 1 "register_operand")]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, false/*unsigned_p*/, true/*high_p*/);
DONE;
})
(define_expand "vec_unpacks_lo_"
[(match_operand: 0 "register_operand")
(match_operand:IMSA_WHB 1 "register_operand")]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, false/*unsigned_p*/, false/*high_p*/);
DONE;
})
(define_expand "vec_unpacku_hi_"
[(match_operand: 0 "register_operand")
(match_operand:IMSA_WHB 1 "register_operand")]
"ISA_HAS_MSA"
{
mips_expand_vec_unpack (operands, true/*unsigned_p*/, true/*high_p*/);
DONE;
})
(define_expand "vec_unpacku_lo_"
[(match_operand: 0 "register_operand")
(match_operand:IMSA_WHB 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 = INTVAL (operands[2]);
if (val == 0)
temp = operands[1];
else
{
/* We need to do the SLDI operation in V16QImode and adjust
operands[2] accordingly. */
rtx wd = gen_reg_rtx (V16QImode);
rtx ws = gen_reg_rtx (V16QImode);
emit_move_insn (ws, gen_lowpart (V16QImode, operands[1]));
rtx n = GEN_INT (val * GET_MODE_SIZE (mode));
gcc_assert (INTVAL (n) < GET_MODE_NUNITS (V16QImode));
emit_insn (gen_msa_sldi_b (wd, ws, ws, n));
temp = gen_reg_rtx (mode);
emit_move_insn (temp, gen_lowpart (mode, wd));
}
emit_insn (gen_msa_vec_extract_ (operands[0], temp));
DONE;
})
(define_insn_and_split "msa_vec_extract_"
[(set (match_operand: 0 "register_operand" "=f")
(vec_select:
(match_operand:FMSA 1 "register_operand" "f")
(parallel [(const_int 0)])))]
"ISA_HAS_MSA"
"#"
"&& reload_completed"
[(set (match_dup 0) (match_dup 1))]
{
/* An MSA register cannot be reinterpreted as a single precision
register when using -mno-odd-spreg and the MSA register is
an odd number. */
if (mode == SFmode && !TARGET_ODD_SPREG
&& (REGNO (operands[1]) & 1))
{
emit_move_insn (gen_rtx_REG (mode, REGNO (operands[0])),
operands[1]);
operands[1] = operands[0];
}
else
operands[1] = gen_rtx_REG (mode, REGNO (operands[1]));
}
[(set_attr "move_type" "fmove")
(set_attr "mode" "")])
(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"
{
rtx index = GEN_INT (1 << INTVAL (operands[2]));
emit_insn (gen_msa_insert_ (operands[0], operands[1],
operands[0], index));
DONE;
})
(define_expand "vec_set"
[(match_operand:FMSA 0 "register_operand")
(match_operand: 1 "register_operand")
(match_operand 2 "const__operand")]
"ISA_HAS_MSA"
{
rtx index = GEN_INT (1 << INTVAL (operands[2]));
emit_insn (gen_msa_insve__scalar (operands[0], operands[1],
operands[0], index));
DONE;
})
(define_expand "vcondu"
[(match_operand:MSA 0 "register_operand")
(match_operand:MSA 1 "reg_or_m1_operand")
(match_operand:MSA 2 "reg_or_0_operand")
(match_operator 3 ""
[(match_operand:IMSA 4 "register_operand")
(match_operand:IMSA 5 "register_operand")])]
"ISA_HAS_MSA
&& (GET_MODE_NUNITS (mode) == GET_MODE_NUNITS (mode))"
{
mips_expand_vec_cond_expr (mode, mode, operands);
DONE;
})
(define_expand "vcond"
[(match_operand:MSA 0 "register_operand")
(match_operand:MSA 1 "reg_or_m1_operand")
(match_operand:MSA 2 "reg_or_0_operand")
(match_operator 3 ""
[(match_operand:MSA_2 4 "register_operand")
(match_operand:MSA_2 5 "register_operand")])]
"ISA_HAS_MSA
&& (GET_MODE_NUNITS (mode) == GET_MODE_NUNITS (mode))"
{
mips_expand_vec_cond_expr (mode, mode, operands);
DONE;
})
(define_insn "msa_insert_"
[(set (match_operand:MSA 0 "register_operand" "=f,f")
(vec_merge:MSA
(vec_duplicate:MSA
(match_operand: 1 "reg_or_0_operand" "dJ,f"))
(match_operand:MSA 2 "register_operand" "0,0")
(match_operand 3 "const__operand" "")))]
"ISA_HAS_MSA"
{
if (which_alternative == 1)
return "insve.\t%w0[%y3],%w1[0]";
if (!TARGET_64BIT && (mode == V2DImode || mode == V2DFmode))
return "#";
else
return "insert.\t%w0[%y3],%z1";
}
[(set_attr "type" "simd_insert")
(set_attr "mode" "")])
(define_split
[(set (match_operand:MSA_D 0 "register_operand")
(vec_merge:MSA_D
(vec_duplicate:MSA_D
(match_operand: 1 "_operand"))
(match_operand:MSA_D 2 "register_operand")
(match_operand 3 "const__operand")))]
"reload_completed && ISA_HAS_MSA && !TARGET_64BIT"
[(const_int 0)]
{
if (REG_P (operands[1]) && FP_REG_P (REGNO (operands[1])))
FAIL;
mips_split_msa_insert_d (operands[0], operands[2], operands[3], operands[1]);
DONE;
})
(define_insn "msa_insve_"
[(set (match_operand:MSA 0 "register_operand" "=f")
(vec_merge:MSA
(vec_duplicate:MSA
(vec_select:
(match_operand:MSA 1 "register_operand" "f")
(parallel [(const_int 0)])))
(match_operand:MSA 2 "register_operand" "0")
(match_operand 3 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%y3],%w1[0]"
[(set_attr "type" "simd_insert")
(set_attr "mode" "")])
;; Operand 3 is a scalar.
(define_insn "msa_insve__scalar"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(vec_merge:FMSA
(vec_duplicate:FMSA
(match_operand: 1 "register_operand" "f"))
(match_operand:FMSA 2 "register_operand" "0")
(match_operand 3 "const__operand" "")))]
"ISA_HAS_MSA"
"insve.\t%w0[%y3],%w1[0]"
[(set_attr "type" "simd_insert")
(set_attr "mode" "")])
(define_insn "msa_copy__"
[(set (match_operand: 0 "register_operand" "=d")
(any_extend:
(vec_select:
(match_operand:IMSA_HB 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")]))))]
"ISA_HAS_MSA"
"copy_.\t%0,%w1[%2]"
[(set_attr "type" "simd_copy")
(set_attr "mode" "")])
(define_insn "msa_copy_u_w"
[(set (match_operand:DI 0 "register_operand" "=d")
(zero_extend:DI
(vec_select:SI
(match_operand:V4SI 1 "register_operand" "f")
(parallel [(match_operand 2 "const_0_to_3_operand" "")]))))]
"ISA_HAS_MSA && TARGET_64BIT"
"copy_u.w\t%0,%w1[%2]"
[(set_attr "type" "simd_copy")
(set_attr "mode" "V4SI")])
(define_insn "msa_copy_s__64bit"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI
(vec_select:
(match_operand:MSA_W 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")]))))]
"ISA_HAS_MSA && TARGET_64BIT"
"copy_s.\t%0,%w1[%2]"
[(set_attr "type" "simd_copy")
(set_attr "mode" "")])
(define_insn "msa_copy_s_"
[(set (match_operand: 0 "register_operand" "=d")
(vec_select:
(match_operand:MSA_W 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")])))]
"ISA_HAS_MSA"
"copy_s.\t%0,%w1[%2]"
[(set_attr "type" "simd_copy")
(set_attr "mode" "")])
(define_insn_and_split "msa_copy_s_"
[(set (match_operand: 0 "register_operand" "=d")
(vec_select:
(match_operand:MSA_D 1 "register_operand" "f")
(parallel [(match_operand 2 "const__operand" "")])))]
"ISA_HAS_MSA"
{
if (TARGET_64BIT)
return "copy_s.\t%0,%w1[%2]";
else
return "#";
}
"reload_completed && ISA_HAS_MSA && !TARGET_64BIT"
[(const_int 0)]
{
mips_split_msa_copy_d (operands[0], operands[1], operands[2],
gen_msa_copy_s_w);
DONE;
}
[(set_attr "type" "simd_copy")
(set_attr "mode" "")])
(define_expand "abs2"
[(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_move_insn (reg, CONST0_RTX (mode));
emit_insn (gen_msa_add_a_ (operands[0], operands[1], reg));
DONE;
})
(define_expand "neg2"
[(set (match_operand:MSA 0 "register_operand")
(minus:MSA (match_dup 2)
(match_operand:MSA 1 "register_operand")))]
"ISA_HAS_MSA"
{
rtx reg = gen_reg_rtx (mode);
emit_move_insn (reg, CONST0_RTX (mode));
operands[2] = reg;
})
(define_expand "msa_ldi"
[(match_operand:IMSA 0 "register_operand")
(match_operand 1 "const_imm10_operand")]
"ISA_HAS_MSA"
{
if (mode == V16QImode)
operands[1] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]),
mode));
emit_move_insn (operands[0],
mips_gen_const_int_vector (mode, INTVAL (operands[1])));
DONE;
})
(define_insn "vec_perm"
[(set (match_operand:MSA 0 "register_operand" "=f")
(unspec:MSA [(match_operand:MSA 1 "register_operand" "f")
(match_operand:MSA 2 "register_operand" "f")
(match_operand: 3 "register_operand" "0")]
UNSPEC_MSA_VSHF))]
"ISA_HAS_MSA"
"vshf.\t%w0,%w2,%w1"
[(set_attr "type" "simd_sld")
(set_attr "mode" "")])
(define_expand "mov"
[(set (match_operand:MSA 0)
(match_operand:MSA 1))]
"ISA_HAS_MSA"
{
if (mips_legitimize_move (mode, operands[0], operands[1]))
DONE;
})
(define_expand "movmisalign"
[(set (match_operand:MSA 0)
(match_operand:MSA 1))]
"ISA_HAS_MSA"
{
if (mips_legitimize_move (mode, operands[0], operands[1]))
DONE;
})
;; 128-bit MSA modes can only exist 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"))]
"ISA_HAS_MSA"
{ return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "simd_move,simd_load,simd_store,simd_copy,simd_insert")
(set_attr "mode" "")])
(define_split
[(set (match_operand:MSA 0 "nonimmediate_operand")
(match_operand:MSA 1 "move_operand"))]
"reload_completed && ISA_HAS_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:
return "addvi.\t%w0,%w1,%E2";
default:
gcc_unreachable ();
}
}
[(set_attr "alu_type" "simd_add")
(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "sub3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f")
(minus:IMSA
(match_operand:IMSA 1 "register_operand" "f,f")
(match_operand:IMSA 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
"ISA_HAS_MSA"
"@
subv.\t%w0,%w1,%w2
subvi.\t%w0,%w1,%E2"
[(set_attr "alu_type" "simd_add")
(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(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" "simd_mul")
(set_attr "mode" "")])
(define_insn "msa_maddv_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(plus:IMSA (mult:IMSA (match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f"))
(match_operand:IMSA 3 "register_operand" "0")))]
"ISA_HAS_MSA"
"maddv.\t%w0,%w1,%w2"
[(set_attr "type" "simd_mul")
(set_attr "mode" "")])
(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" "simd_mul")
(set_attr "mode" "")])
(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" "simd_div")
(set_attr "mode" "")])
(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" "simd_div")
(set_attr "mode" "")])
(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" "simd_div")
(set_attr "mode" "")])
(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" "simd_div")
(set_attr "mode" "")])
(define_insn "xor3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
(xor:IMSA
(match_operand:IMSA 1 "register_operand" "f,f,f")
(match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
"ISA_HAS_MSA"
"@
xor.v\t%w0,%w1,%w2
bnegi.%v0\t%w0,%w1,%V2
xori.b\t%w0,%w1,%B2"
[(set_attr "type" "simd_logic,simd_bit,simd_logic")
(set_attr "mode" "")])
(define_insn "ior3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
(ior:IMSA
(match_operand:IMSA 1 "register_operand" "f,f,f")
(match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
"ISA_HAS_MSA"
"@
or.v\t%w0,%w1,%w2
bseti.%v0\t%w0,%w1,%V2
ori.b\t%w0,%w1,%B2"
[(set_attr "type" "simd_logic,simd_bit,simd_logic")
(set_attr "mode" "")])
(define_insn "and3"
[(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
(and:IMSA
(match_operand:IMSA 1 "register_operand" "f,f,f")
(match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YZ,Urv8")))]
"ISA_HAS_MSA"
{
switch (which_alternative)
{
case 0:
return "and.v\t%w0,%w1,%w2";
case 1:
{
rtx elt0 = CONST_VECTOR_ELT (operands[2], 0);
unsigned HOST_WIDE_INT val = ~UINTVAL (elt0);
operands[2] = mips_gen_const_int_vector (mode, val & (-val));
return "bclri.%v0\t%w0,%w1,%V2";
}
case 2:
return "andi.b\t%w0,%w1,%B2";
default:
gcc_unreachable ();
}
}
[(set_attr "type" "simd_logic,simd_bit,simd_logic")
(set_attr "mode" "")])
(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 "type" "simd_logic")
(set_attr "mode" "TI")])
(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"
"@
srl.\t%w0,%w1,%w2
srli.\t%w0,%w1,%E2"
[(set_attr "type" "simd_shift")
(set_attr "mode" "")])
(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"
"@
sra.\t%w0,%w1,%w2
srai.\t%w0,%w1,%E2"
[(set_attr "type" "simd_shift")
(set_attr "mode" "")])
(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"
"@
sll.\t%w0,%w1,%w2
slli.\t%w0,%w1,%E2"
[(set_attr "type" "simd_shift")
(set_attr "mode" "")])
;; 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" "simd_fadd")
(set_attr "mode" "")])
(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" "simd_fadd")
(set_attr "mode" "")])
(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" "simd_fmul")
(set_attr "mode" "")])
(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" "simd_fdiv")
(set_attr "mode" "")])
(define_insn "fma4"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(fma:FMSA (match_operand:FMSA 1 "register_operand" "f")
(match_operand:FMSA 2 "register_operand" "f")
(match_operand:FMSA 3 "register_operand" "0")))]
"ISA_HAS_MSA"
"fmadd.\t%w0,%w1,%w2"
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "")])
(define_insn "fnma4"
[(set (match_operand:FMSA 0 "register_operand" "=f")
(fma:FMSA (neg:FMSA (match_operand:FMSA 1 "register_operand" "f"))
(match_operand:FMSA 2 "register_operand" "f")
(match_operand:FMSA 3 "register_operand" "0")))]
"ISA_HAS_MSA"
"fmsub.\t%w0,%w1,%w2"
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "")])
(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" "simd_fdiv")
(set_attr "mode" "")])
;; 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" "simd_int_arith")
(set_attr "mode" "")])
(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" "simd_int_arith")
(set_attr "mode" "")])
(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" "simd_int_arith")
(set_attr "mode" "")])
(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.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_asub_s_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_ASUB_S))]
"ISA_HAS_MSA"
"asub_s.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_asub_u_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_ASUB_U))]
"ISA_HAS_MSA"
"asub_u.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_ave_s_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_AVE_S))]
"ISA_HAS_MSA"
"ave_s.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_ave_u_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_AVE_U))]
"ISA_HAS_MSA"
"ave_u.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_aver_s_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_AVER_S))]
"ISA_HAS_MSA"
"aver_s.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_aver_u_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_AVER_U))]
"ISA_HAS_MSA"
"aver_u.\t%w0,%w1,%w2"
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "")])
(define_insn "msa_bclr_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand:IMSA 2 "register_operand" "f")]
UNSPEC_MSA_BCLR))]
"ISA_HAS_MSA"
"bclr.\t%w0,%w1,%w2"
[(set_attr "type" "simd_bit")
(set_attr "mode" "")])
(define_insn "msa_bclri_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
(match_operand 2 "const__operand" "")]
UNSPEC_MSA_BCLRI))]
"ISA_HAS_MSA"
"bclri.\t%w0,%w1,%2"
[(set_attr "type" "simd_bit")
(set_attr "mode" "")])
(define_insn "msa_binsl_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
(match_operand:IMSA 2 "register_operand" "f")
(match_operand:IMSA 3 "register_operand" "f")]
UNSPEC_MSA_BINSL))]
"ISA_HAS_MSA"
"binsl.\t%w0,%w2,%w3"
[(set_attr "type" "simd_bitins")
(set_attr "mode" "")])
(define_insn "msa_binsli_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
(match_operand:IMSA 2 "register_operand" "f")
(match_operand 3 "const__operand" "")]
UNSPEC_MSA_BINSLI))]
"ISA_HAS_MSA"
"binsli.\t%w0,%w2,%3"
[(set_attr "type" "simd_bitins")
(set_attr "mode" "")])
(define_insn "msa_binsr_"
[(set (match_operand:IMSA 0 "register_operand" "=f")
(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
(match_operand:IMSA 2 "register_operand" "f")
(match_operand:IMSA 3 "register_operand" "f")]
UNSPEC_MSA_BINSR))]
"ISA_HAS_MSA"
"binsr.