;; Arm M-profile Vector Extension Machine Description
;; Copyright (C) 2019-2022 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_insn "*mve_mov"
[(set (match_operand:MVE_types 0 "nonimmediate_operand" "=w,w,r,w,w,r,w,Ux,w")
(match_operand:MVE_types 1 "general_operand" "w,r,w,Dn,UxUi,r,Dm,w,Ul"))]
"TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT"
{
if (which_alternative == 3 || which_alternative == 6)
{
int width, is_valid;
static char templ[40];
is_valid = simd_immediate_valid_for_move (operands[1], mode,
&operands[1], &width);
gcc_assert (is_valid != 0);
if (width == 0)
return "vmov.f32\t%q0, %1 @ ";
else
sprintf (templ, "vmov.i%d\t%%q0, %%x1 @ ", width);
return templ;
}
if (which_alternative == 4 || which_alternative == 7)
{
if (mode == V2DFmode || mode == V2DImode || mode == TImode)
{
if (which_alternative == 7)
output_asm_insn ("vstrw.32\t%q1, %E0", operands);
else
output_asm_insn ("vldrw.u32\t%q0, %E1",operands);
}
else
{
if (which_alternative == 7)
output_asm_insn ("vstr.\t%q1, %E0", operands);
else
output_asm_insn ("vldr.\t%q0, %E1", operands);
}
return "";
}
switch (which_alternative)
{
case 0:
return "vmov\t%q0, %q1";
case 1:
return "vmov\t%e0, %Q1, %R1 @ \;vmov\t%f0, %J1, %K1";
case 2:
return "vmov\t%Q0, %R0, %e1 @ \;vmov\t%J0, %K0, %f1";
case 5:
return output_move_quad (operands);
case 8:
return output_move_neon (operands);
default:
gcc_unreachable ();
return "";
}
}
[(set_attr "type" "mve_move,mve_move,mve_move,mve_move,mve_load,multiple,mve_move,mve_store,mve_load")
(set_attr "length" "4,8,8,4,8,8,4,4,4")
(set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*,*,*")
(set_attr "neg_pool_range" "*,*,*,*,996,*,*,*,*")])
(define_insn "*mve_vdup"
[(set (match_operand:MVE_vecs 0 "s_register_operand" "=w")
(vec_duplicate:MVE_vecs
(match_operand: 1 "s_register_operand" "r")))]
"TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT"
"vdup.\t%q0, %1"
[(set_attr "length" "4")
(set_attr "type" "mve_move")])
;;
;; [vst4q])
;;
(define_insn "mve_vst4q"
[(set (match_operand:XI 0 "mve_struct_operand" "=Ug")
(unspec:XI [(match_operand:XI 1 "s_register_operand" "w")
(unspec:MVE_VLD_ST [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
VST4Q))
]
"TARGET_HAVE_MVE"
{
rtx ops[6];
int regno = REGNO (operands[1]);
ops[0] = gen_rtx_REG (TImode, regno);
ops[1] = gen_rtx_REG (TImode, regno+4);
ops[2] = gen_rtx_REG (TImode, regno+8);
ops[3] = gen_rtx_REG (TImode, regno+12);
rtx reg = operands[0];
while (reg && !REG_P (reg))
reg = XEXP (reg, 0);
gcc_assert (REG_P (reg));
ops[4] = reg;
ops[5] = operands[0];
/* Here in first three instructions data is stored to ops[4]'s location but
in the fourth instruction data is stored to operands[0], this is to
support the writeback. */
output_asm_insn ("vst40.\t{%q0, %q1, %q2, %q3}, [%4]\n\t"
"vst41.\t{%q0, %q1, %q2, %q3}, [%4]\n\t"
"vst42.\t{%q0, %q1, %q2, %q3}, [%4]\n\t"
"vst43.\t{%q0, %q1, %q2, %q3}, %5", ops);
return "";
}
[(set_attr "length" "16")])
;;
;; [vrndq_m_f])
;;
(define_insn "mve_vrndq_m_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0")
(match_operand:MVE_0 2 "s_register_operand" "w")
(match_operand: 3 "vpr_register_operand" "Up")]
VRNDQ_M_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vpst\;vrintzt.f%# %q0, %q2"
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
;; [vrndxq_f])
;;
(define_insn "mve_vrndxq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDXQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrintx.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrndq_f])
;;
(define_insn "mve_vrndq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrintz.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrndpq_f])
;;
(define_insn "mve_vrndpq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDPQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrintp.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrndnq_f])
;;
(define_insn "mve_vrndnq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDNQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrintn.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrndmq_f])
;;
(define_insn "mve_vrndmq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDMQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrintm.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrndaq_f])
;;
(define_insn "mve_vrndaq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VRNDAQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrinta.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrev64q_f])
;;
(define_insn "mve_vrev64q_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=&w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
VREV64Q_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrev64.%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vnegq_f])
;;
(define_insn "mve_vnegq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(neg:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vneg.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vdupq_n_f])
;;
(define_insn "mve_vdupq_n_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand: 1 "s_register_operand" "r")]
VDUPQ_N_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vdup.%# %q0, %1"
[(set_attr "type" "mve_move")
])
;;
;; [vabsq_f])
;;
(define_insn "mve_vabsq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(abs:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vabs.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrev32q_f])
;;
(define_insn "mve_vrev32q_fv8hf"
[
(set (match_operand:V8HF 0 "s_register_operand" "=w")
(unspec:V8HF [(match_operand:V8HF 1 "s_register_operand" "w")]
VREV32Q_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vrev32.16 %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvttq_f32_f16])
;;
(define_insn "mve_vcvttq_f32_f16v4sf"
[
(set (match_operand:V4SF 0 "s_register_operand" "=w")
(unspec:V4SF [(match_operand:V8HF 1 "s_register_operand" "w")]
VCVTTQ_F32_F16))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvtt.f32.f16 %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtbq_f32_f16])
;;
(define_insn "mve_vcvtbq_f32_f16v4sf"
[
(set (match_operand:V4SF 0 "s_register_operand" "=w")
(unspec:V4SF [(match_operand:V8HF 1 "s_register_operand" "w")]
VCVTBQ_F32_F16))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvtb.f32.f16 %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtq_to_f_s, vcvtq_to_f_u])
;;
(define_insn "mve_vcvtq_to_f_"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand: 1 "s_register_operand" "w")]
VCVTQ_TO_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvt.f%#.%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrev64q_u, vrev64q_s])
;;
(define_insn "mve_vrev64q_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=&w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
VREV64Q))
]
"TARGET_HAVE_MVE"
"vrev64.%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtq_from_f_s, vcvtq_from_f_u])
;;
(define_insn "mve_vcvtq_from_f_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")]
VCVTQ_FROM_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvt.%#.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;; [vqnegq_s])
;;
(define_insn "mve_vqnegq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
VQNEGQ_S))
]
"TARGET_HAVE_MVE"
"vqneg.s%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vqabsq_s])
;;
(define_insn "mve_vqabsq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
VQABSQ_S))
]
"TARGET_HAVE_MVE"
"vqabs.s%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vnegq_s])
;;
(define_insn "mve_vnegq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(neg:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vneg.s%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vmvnq_u, vmvnq_s])
;;
(define_insn "mve_vmvnq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(not:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vmvn\t%q0, %q1"
[(set_attr "type" "mve_move")
])
(define_expand "mve_vmvnq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand")
(not:MVE_2 (match_operand:MVE_2 1 "s_register_operand")))
]
"TARGET_HAVE_MVE"
)
;;
;; [vdupq_n_u, vdupq_n_s])
;;
(define_insn "mve_vdupq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand: 1 "s_register_operand" "r")]
VDUPQ_N))
]
"TARGET_HAVE_MVE"
"vdup.%# %q0, %1"
[(set_attr "type" "mve_move")
])
;;
;; [vclzq_u, vclzq_s])
;;
(define_insn "@mve_vclzq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(clz:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vclz.i%# %q0, %q1"
[(set_attr "type" "mve_move")
])
(define_expand "mve_vclzq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand")
(clz:MVE_2 (match_operand:MVE_2 1 "s_register_operand")))
]
"TARGET_HAVE_MVE"
)
;;
;; [vclsq_s])
;;
(define_insn "mve_vclsq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
VCLSQ_S))
]
"TARGET_HAVE_MVE"
"vcls.s%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vaddvq_s, vaddvq_u])
;;
(define_insn "@mve_vaddvq_"
[
(set (match_operand:SI 0 "s_register_operand" "=Te")
(unspec:SI [(match_operand:MVE_2 1 "s_register_operand" "w")]
VADDVQ))
]
"TARGET_HAVE_MVE"
"vaddv.%#\t%0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vabsq_s])
;;
(define_insn "mve_vabsq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(abs:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vabs.s%#\t%q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vrev32q_u, vrev32q_s])
;;
(define_insn "mve_vrev32q_"
[
(set (match_operand:MVE_3 0 "s_register_operand" "=w")
(unspec:MVE_3 [(match_operand:MVE_3 1 "s_register_operand" "w")]
VREV32Q))
]
"TARGET_HAVE_MVE"
"vrev32.%#\t%q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vmovltq_u, vmovltq_s])
;;
(define_insn "mve_vmovltq_"
[
(set (match_operand: 0 "s_register_operand" "=w")
(unspec: [(match_operand:MVE_3 1 "s_register_operand" "w")]
VMOVLTQ))
]
"TARGET_HAVE_MVE"
"vmovlt.%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vmovlbq_s, vmovlbq_u])
;;
(define_insn "mve_vmovlbq_"
[
(set (match_operand: 0 "s_register_operand" "=w")
(unspec: [(match_operand:MVE_3 1 "s_register_operand" "w")]
VMOVLBQ))
]
"TARGET_HAVE_MVE"
"vmovlb.%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtpq_s, vcvtpq_u])
;;
(define_insn "mve_vcvtpq_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")]
VCVTPQ))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvtp.%#.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtnq_s, vcvtnq_u])
;;
(define_insn "mve_vcvtnq_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")]
VCVTNQ))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvtn.%#.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtmq_s, vcvtmq_u])
;;
(define_insn "mve_vcvtmq_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")]
VCVTMQ))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvtm.%#.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtaq_u, vcvtaq_s])
;;
(define_insn "mve_vcvtaq_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")]
VCVTAQ))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvta.%#.f%# %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vmvnq_n_u, vmvnq_n_s])
;;
(define_insn "mve_vmvnq_n_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "immediate_operand" "i")]
VMVNQ_N))
]
"TARGET_HAVE_MVE"
"vmvn.i%# %q0, %1"
[(set_attr "type" "mve_move")
])
;;
;; [vrev16q_u, vrev16q_s])
;;
(define_insn "mve_vrev16q_v16qi"
[
(set (match_operand:V16QI 0 "s_register_operand" "=w")
(unspec:V16QI [(match_operand:V16QI 1 "s_register_operand" "w")]
VREV16Q))
]
"TARGET_HAVE_MVE"
"vrev16.8 %q0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vaddlvq_s vaddlvq_u])
;;
(define_insn "mve_vaddlvq_v4si"
[
(set (match_operand:DI 0 "s_register_operand" "=r")
(unspec:DI [(match_operand:V4SI 1 "s_register_operand" "w")]
VADDLVQ))
]
"TARGET_HAVE_MVE"
"vaddlv.32 %Q0, %R0, %q1"
[(set_attr "type" "mve_move")
])
;;
;; [vctp8q vctp16q vctp32q vctp64q])
;;
(define_insn "mve_vctpqhi"
[
(set (match_operand:HI 0 "vpr_register_operand" "=Up")
(unspec:HI [(match_operand:SI 1 "s_register_operand" "r")]
VCTPQ))
]
"TARGET_HAVE_MVE"
"vctp. %1"
[(set_attr "type" "mve_move")
])
;;
;; [vpnot])
;;
(define_insn "mve_vpnothi"
[
(set (match_operand:HI 0 "vpr_register_operand" "=Up")
(unspec:HI [(match_operand:HI 1 "vpr_register_operand" "0")]
VPNOT))
]
"TARGET_HAVE_MVE"
"vpnot"
[(set_attr "type" "mve_move")
])
;;
;; [vsubq_n_f])
;;
(define_insn "mve_vsubq_n_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
(match_operand: 2 "s_register_operand" "r")]
VSUBQ_N_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vsub.f %q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vbrsrq_n_f])
;;
(define_insn "mve_vbrsrq_n_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
(match_operand:SI 2 "s_register_operand" "r")]
VBRSRQ_N_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vbrsr. %q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vcvtq_n_to_f_s, vcvtq_n_to_f_u])
;;
(define_insn "mve_vcvtq_n_to_f_"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand: 1 "s_register_operand" "w")
(match_operand:SI 2 "" "")]
VCVTQ_N_TO_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvt.f.\t%q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;; [vcreateq_f])
;;
(define_insn "mve_vcreateq_f"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
(unspec:MVE_0 [(match_operand:DI 1 "s_register_operand" "r")
(match_operand:DI 2 "s_register_operand" "r")]
VCREATEQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vmov %q0[2], %q0[0], %Q2, %Q1\;vmov %q0[3], %q0[1], %R2, %R1"
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
;; [vcreateq_u, vcreateq_s])
;;
(define_insn "mve_vcreateq_"
[
(set (match_operand:MVE_1 0 "s_register_operand" "=w")
(unspec:MVE_1 [(match_operand:DI 1 "s_register_operand" "r")
(match_operand:DI 2 "s_register_operand" "r")]
VCREATEQ))
]
"TARGET_HAVE_MVE"
"vmov %q0[2], %q0[0], %Q2, %Q1\;vmov %q0[3], %q0[1], %R2, %R1"
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
;; [vshrq_n_s, vshrq_n_u])
;;
;; Version that takes an immediate as operand 2.
(define_insn "mve_vshrq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:SI 2 "" "")]
VSHRQ_N))
]
"TARGET_HAVE_MVE"
"vshr.\t%q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;; Versions that take constant vectors as operand 2 (with all elements
;; equal).
(define_insn "mve_vshrq_n_s_imm"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(ashiftrt:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "imm_for_neon_rshift_operand" "i")))
]
"TARGET_HAVE_MVE"
{
return neon_output_shift_immediate ("vshr", 's', &operands[2],
mode,
VALID_NEON_QREG_MODE (mode),
true);
}
[(set_attr "type" "mve_move")
])
(define_insn "mve_vshrq_n_u_imm"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(lshiftrt:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "imm_for_neon_rshift_operand" "i")))
]
"TARGET_HAVE_MVE"
{
return neon_output_shift_immediate ("vshr", 'u', &operands[2],
mode,
VALID_NEON_QREG_MODE (mode),
true);
}
[(set_attr "type" "mve_move")
])
;;
;; [vcvtq_n_from_f_s, vcvtq_n_from_f_u])
;;
(define_insn "mve_vcvtq_n_from_f_"
[
(set (match_operand:MVE_5 0 "s_register_operand" "=w")
(unspec:MVE_5 [(match_operand: 1 "s_register_operand" "w")
(match_operand:SI 2 "" "")]
VCVTQ_N_FROM_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vcvt..f\t%q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vaddlvq_p_s])
;;
(define_insn "mve_vaddlvq_p_v4si"
[
(set (match_operand:DI 0 "s_register_operand" "=r")
(unspec:DI [(match_operand:V4SI 1 "s_register_operand" "w")
(match_operand:V4BI 2 "vpr_register_operand" "Up")]
VADDLVQ_P))
]
"TARGET_HAVE_MVE"
"vpst\;vaddlvt.32 %Q0, %R0, %q1"
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
;; [vcmpneq_, vcmpcsq_, vcmpeqq_, vcmpgeq_, vcmpgtq_, vcmphiq_, vcmpleq_, vcmpltq_])
;;
(define_insn "@mve_vcmpq_"
[
(set (match_operand: 0 "vpr_register_operand" "=Up")
(MVE_COMPARISONS: (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vcmp.%# , %q1, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vcmpcsq_n_, vcmpeqq_n_, vcmpgeq_n_, vcmpgtq_n_, vcmphiq_n_, vcmpleq_n_, vcmpltq_n_, vcmpneq_n_])
;;
(define_insn "mve_vcmpq_n_"
[
(set (match_operand: 0 "vpr_register_operand" "=Up")
(MVE_COMPARISONS:
(match_operand:MVE_2 1 "s_register_operand" "w")
(vec_duplicate:MVE_2 (match_operand: 2 "s_register_operand" "r"))))
]
"TARGET_HAVE_MVE"
"vcmp.%# , %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vshlq_s, vshlq_u])
;; See vec-common.md
;;
;; [vabdq_s, vabdq_u])
;;
(define_insn "mve_vabdq_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VABDQ))
]
"TARGET_HAVE_MVE"
"vabd.%# %q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vaddq_n_s, vaddq_n_u])
;;
(define_insn "mve_vaddq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand: 2 "s_register_operand" "r")]
VADDQ_N))
]
"TARGET_HAVE_MVE"
"vadd.i%# %q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vaddvaq_s, vaddvaq_u])
;;
(define_insn "mve_vaddvaq_"
[
(set (match_operand:SI 0 "s_register_operand" "=Te")
(unspec:SI [(match_operand:SI 1 "s_register_operand" "0")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VADDVAQ))
]
"TARGET_HAVE_MVE"
"vaddva.%# %0, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vaddvq_p_u, vaddvq_p_s])
;;
(define_insn "mve_vaddvq_p_"
[
(set (match_operand:SI 0 "s_register_operand" "=Te")
(unspec:SI [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand: 2 "vpr_register_operand" "Up")]
VADDVQ_P))
]
"TARGET_HAVE_MVE"
"vpst\;vaddvt.%# %0, %q1"
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
;; [vandq_u, vandq_s])
;;
;; signed and unsigned versions are the same: define the unsigned
;; insn, and use an expander for the signed one as we still reference
;; both names from arm_mve.h.
;; We use the same code as in neon.md (TODO: avoid this duplication).
(define_insn "mve_vandq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w,w")
(and:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w,0")
(match_operand:MVE_2 2 "neon_inv_logic_op2" "w,DL")))
]
"TARGET_HAVE_MVE"
"@
vand\t%q0, %q1, %q2
* return neon_output_logic_immediate (\"vand\", &operands[2], mode, 1, VALID_NEON_QREG_MODE (mode));"
[(set_attr "type" "mve_move")
])
(define_expand "mve_vandq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand")
(and:MVE_2 (match_operand:MVE_2 1 "s_register_operand")
(match_operand:MVE_2 2 "neon_inv_logic_op2")))
]
"TARGET_HAVE_MVE"
)
;;
;; [vbicq_s, vbicq_u])
;;
(define_insn "mve_vbicq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(and:MVE_2 (not:MVE_2 (match_operand:MVE_2 2 "s_register_operand" "w"))
(match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vbic\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
(define_expand "mve_vbicq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand")
(and:MVE_2 (not:MVE_2 (match_operand:MVE_2 2 "s_register_operand"))
(match_operand:MVE_2 1 "s_register_operand")))
]
"TARGET_HAVE_MVE"
)
;;
;; [vbrsrq_n_u, vbrsrq_n_s])
;;
(define_insn "mve_vbrsrq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:SI 2 "s_register_operand" "r")]
VBRSRQ_N))
]
"TARGET_HAVE_MVE"
"vbrsr.%# %q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vcaddq, vcaddq_rot90, vcadd_rot180, vcadd_rot270])
;;
(define_insn "mve_vcaddq"
[
(set (match_operand:MVE_2 0 "s_register_operand" "")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VCADD))
]
"TARGET_HAVE_MVE"
"vcadd.i%# %q0, %q1, %q2, #"
[(set_attr "type" "mve_move")
])
;; Auto vectorizer pattern for int vcadd
(define_expand "cadd3"
[(set (match_operand:MVE_2 0 "register_operand")
(unspec:MVE_2 [(match_operand:MVE_2 1 "register_operand")
(match_operand:MVE_2 2 "register_operand")]
VCADD))]
"TARGET_HAVE_MVE && !BYTES_BIG_ENDIAN"
)
;;
;; [veorq_u, veorq_s])
;;
(define_insn "mve_veorq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(xor:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"veor\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
(define_expand "mve_veorq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand")
(xor:MVE_2 (match_operand:MVE_2 1 "s_register_operand")
(match_operand:MVE_2 2 "s_register_operand")))
]
"TARGET_HAVE_MVE"
)
;;
;; [vhaddq_n_u, vhaddq_n_s])
;;
(define_insn "mve_vhaddq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand: 2 "s_register_operand" "r")]
VHADDQ_N))
]
"TARGET_HAVE_MVE"
"vhadd.%#\t%q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vhaddq_s, vhaddq_u])
;;
(define_insn "@mve_vhaddq_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VHADDQ))
]
"TARGET_HAVE_MVE"
"vhadd.%#\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vhcaddq_rot270_s])
;;
(define_insn "mve_vhcaddq_rot270_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VHCADDQ_ROT270_S))
]
"TARGET_HAVE_MVE"
"vhcadd.s%#\t%q0, %q1, %q2, #270"
[(set_attr "type" "mve_move")
])
;;
;; [vhcaddq_rot90_s])
;;
(define_insn "mve_vhcaddq_rot90_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VHCADDQ_ROT90_S))
]
"TARGET_HAVE_MVE"
"vhcadd.s%#\t%q0, %q1, %q2, #90"
[(set_attr "type" "mve_move")
])
;;
;; [vhsubq_n_u, vhsubq_n_s])
;;
(define_insn "mve_vhsubq_n_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand: 2 "s_register_operand" "r")]
VHSUBQ_N))
]
"TARGET_HAVE_MVE"
"vhsub.%#\t%q0, %q1, %2"
[(set_attr "type" "mve_move")
])
;;
;; [vhsubq_s, vhsubq_u])
;;
(define_insn "mve_vhsubq_"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VHSUBQ))
]
"TARGET_HAVE_MVE"
"vhsub.%#\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vmaxaq_s])
;;
(define_insn "mve_vmaxaq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "0")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VMAXAQ_S))
]
"TARGET_HAVE_MVE"
"vmaxa.s%# %q0, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vmaxavq_s])
;;
(define_insn "mve_vmaxavq_s"
[
(set (match_operand: 0 "s_register_operand" "=r")
(unspec: [(match_operand: 1 "s_register_operand" "0")
(match_operand:MVE_2 2 "s_register_operand" "w")]
VMAXAVQ_S))
]
"TARGET_HAVE_MVE"
"vmaxav.s%#\t%0, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vmaxq_u, vmaxq_s])
;;
(define_insn "mve_vmaxq_s"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(smax:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vmax.%#\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
(define_insn "mve_vmaxq_u"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
(umax:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vmax.%#\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
;;
;; [vmaxvq_u, vmaxvq_s])
;;
(define_insn "mve_vmaxvq_