;; AltiVec patterns.
;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
;; 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_VCMPBFP
UNSPEC_VMSUMU
UNSPEC_VMSUMUDM
UNSPEC_VMSUMM
UNSPEC_VMSUMSHM
UNSPEC_VMSUMUHS
UNSPEC_VMSUMSHS
UNSPEC_VMHADDSHS
UNSPEC_VMHRADDSHS
UNSPEC_VADDCUW
UNSPEC_VAVGU
UNSPEC_VAVGS
UNSPEC_VMULEUB
UNSPEC_VMULESB
UNSPEC_VMULEUH
UNSPEC_VMULESH
UNSPEC_VMULEUW
UNSPEC_VMULESW
UNSPEC_VMULEUD
UNSPEC_VMULESD
UNSPEC_VMULOUB
UNSPEC_VMULOSB
UNSPEC_VMULOUH
UNSPEC_VMULOSH
UNSPEC_VMULOUW
UNSPEC_VMULOSW
UNSPEC_VMULOUD
UNSPEC_VMULOSD
UNSPEC_VPKPX
UNSPEC_VPACK_SIGN_SIGN_SAT
UNSPEC_VPACK_SIGN_UNS_SAT
UNSPEC_VPACK_UNS_UNS_SAT
UNSPEC_VPACK_UNS_UNS_MOD
UNSPEC_VPACK_UNS_UNS_MOD_DIRECT
UNSPEC_VREVEV
UNSPEC_VSLV4SI
UNSPEC_VSLO
UNSPEC_VSR
UNSPEC_VSRO
UNSPEC_VSUBCUW
UNSPEC_VSUM4UBS
UNSPEC_VSUM4S
UNSPEC_VSUM2SWS
UNSPEC_VSUMSWS
UNSPEC_VPERM
UNSPEC_VPERMR
UNSPEC_VPERM_UNS
UNSPEC_VRFIN
UNSPEC_VCFUX
UNSPEC_VCFSX
UNSPEC_VCTUXS
UNSPEC_VCTSXS
UNSPEC_VLOGEFP
UNSPEC_VEXPTEFP
UNSPEC_VSLDOI
UNSPEC_VUNPACK_HI_SIGN
UNSPEC_VUNPACK_LO_SIGN
UNSPEC_VUNPACK_HI_SIGN_DIRECT
UNSPEC_VUNPACK_LO_SIGN_DIRECT
UNSPEC_VUPKHPX
UNSPEC_VUPKLPX
UNSPEC_CONVERT_4F32_8I16
UNSPEC_CONVERT_4F32_8F16
UNSPEC_DST
UNSPEC_DSTT
UNSPEC_DSTST
UNSPEC_DSTSTT
UNSPEC_LVSL
UNSPEC_LVSR
UNSPEC_LVE
UNSPEC_STVX
UNSPEC_STVXL
UNSPEC_STVE
UNSPEC_SET_VSCR
UNSPEC_GET_VRSAVE
UNSPEC_LVX
UNSPEC_REDUC_PLUS
UNSPEC_VECSH
UNSPEC_EXTEVEN_V4SI
UNSPEC_EXTEVEN_V8HI
UNSPEC_EXTEVEN_V16QI
UNSPEC_EXTEVEN_V4SF
UNSPEC_EXTODD_V4SI
UNSPEC_EXTODD_V8HI
UNSPEC_EXTODD_V16QI
UNSPEC_EXTODD_V4SF
UNSPEC_INTERHI_V4SI
UNSPEC_INTERHI_V8HI
UNSPEC_INTERHI_V16QI
UNSPEC_INTERLO_V4SI
UNSPEC_INTERLO_V8HI
UNSPEC_INTERLO_V16QI
UNSPEC_LVLX
UNSPEC_LVLXL
UNSPEC_LVRX
UNSPEC_LVRXL
UNSPEC_STVLX
UNSPEC_STVLXL
UNSPEC_STVRX
UNSPEC_STVRXL
UNSPEC_VSLV
UNSPEC_VSRV
UNSPEC_VMULWHUB
UNSPEC_VMULWLUB
UNSPEC_VMULWHSB
UNSPEC_VMULWLSB
UNSPEC_VMULWHUH
UNSPEC_VMULWLUH
UNSPEC_VMULWHSH
UNSPEC_VMULWLSH
UNSPEC_VUPKHU
UNSPEC_VUPKLU
UNSPEC_VPERMSI
UNSPEC_VPERMHI
UNSPEC_INTERHI
UNSPEC_INTERLO
UNSPEC_VUPKHS_V4SF
UNSPEC_VUPKLS_V4SF
UNSPEC_VUPKHU_V4SF
UNSPEC_VUPKLU_V4SF
UNSPEC_VGBBD
UNSPEC_VSPLT_DIRECT
UNSPEC_VMRGEW_DIRECT
UNSPEC_VMRGOW_DIRECT
UNSPEC_VSUMSWS_DIRECT
UNSPEC_VADDCUQ
UNSPEC_VADDEUQM
UNSPEC_VADDECUQ
UNSPEC_VSUBCUQ
UNSPEC_VSUBEUQM
UNSPEC_VSUBECUQ
UNSPEC_VBPERMQ
UNSPEC_VBPERMD
UNSPEC_BCDADD
UNSPEC_BCDSUB
UNSPEC_BCD_OVERFLOW
UNSPEC_BCDSHIFT
UNSPEC_VRLMI
UNSPEC_VRLNM
UNSPEC_VCFUGED
UNSPEC_VCLZDM
UNSPEC_VCTZDM
UNSPEC_VGNB
UNSPEC_VPDEPD
UNSPEC_VPEXTD
UNSPEC_VCLRLB
UNSPEC_VCLRRB
UNSPEC_VSTRIR
UNSPEC_VSTRIL
UNSPEC_SLDB
UNSPEC_SRDB
UNSPEC_VECTOR_SHIFT
])
(define_c_enum "unspecv"
[UNSPECV_SET_VRSAVE
UNSPECV_MTVSCR
UNSPECV_MFVSCR
UNSPECV_DSSALL
UNSPECV_DSS
])
;; Short vec int modes
(define_mode_iterator VIshort [V8HI V16QI])
;; Vec float modes
(define_mode_iterator VF [V4SF])
;; Vec modes, pity mode iterators are not composable
(define_mode_iterator V [V4SI V8HI V16QI V4SF])
;; Vec modes for move/logical/permute ops, include vector types for move not
;; otherwise handled by altivec (v2df, v2di, ti)
(define_mode_iterator VM [V4SI
V8HI
V16QI
V4SF
V2DF
V2DI
V1TI
TI
(KF "FLOAT128_VECTOR_P (KFmode)")
(TF "FLOAT128_VECTOR_P (TFmode)")])
;; Like VM, except don't do TImode
(define_mode_iterator VM2 [V4SI
V8HI
V16QI
V4SF
V2DF
V2DI
V1TI
(KF "FLOAT128_VECTOR_P (KFmode)")
(TF "FLOAT128_VECTOR_P (TFmode)")])
;; Map the Vector convert single precision to double precision for integer
;; versus floating point
(define_mode_attr VS_sxwsp [(V4SI "sxw") (V4SF "sp")])
;; Specific iterator for parity which does not have a byte/half-word form, but
;; does have a quad word form
(define_mode_iterator VParity [V4SI
V2DI
V1TI
TI])
(define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
(define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
(define_mode_attr VI_unit [(V16QI "VECTOR_UNIT_ALTIVEC_P (V16QImode)")
(V8HI "VECTOR_UNIT_ALTIVEC_P (V8HImode)")
(V4SI "VECTOR_UNIT_ALTIVEC_P (V4SImode)")
(V2DI "VECTOR_UNIT_P8_VECTOR_P (V2DImode)")])
;; Vector pack/unpack
(define_mode_iterator VP [V2DI V4SI V8HI])
(define_mode_attr VP_small [(V2DI "V4SI") (V4SI "V8HI") (V8HI "V16QI")])
(define_mode_attr VP_small_lc [(V2DI "v4si") (V4SI "v8hi") (V8HI "v16qi")])
(define_mode_attr VU_char [(V2DI "w") (V4SI "h") (V8HI "b")])
;; Vector negate
(define_mode_iterator VNEG [V4SI V2DI])
;; Vector move instructions.
(define_insn "*altivec_mov"
[(set (match_operand:VM2 0 "nonimmediate_operand" "=Z,v,v,?Y,?*r,?*r,v,v,?*r")
(match_operand:VM2 1 "input_operand" "v,Z,v,*r,Y,*r,j,W,W"))]
"VECTOR_MEM_ALTIVEC_P (mode)
&& (register_operand (operands[0], mode)
|| register_operand (operands[1], mode))"
"@
stvx %1,%y0
lvx %0,%y1
vor %0,%1,%1
#
#
#
vxor %0,%0,%0
* return output_vec_const_move (operands);
#"
[(set_attr "type" "vecstore,vecload,veclogical,store,load,*,veclogical,*,*")
(set_attr "length" "*,*,*,20,20,20,*,8,32")])
;; Unlike other altivec moves, allow the GPRs, since a normal use of TImode
;; is for unions. However for plain data movement, slightly favor the vector
;; loads
(define_insn "*altivec_movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "=Z,v,v,?Y,?r,?r,v,v")
(match_operand:TI 1 "input_operand" "v,Z,v,r,Y,r,j,W"))]
"VECTOR_MEM_ALTIVEC_P (TImode)
&& (register_operand (operands[0], TImode)
|| register_operand (operands[1], TImode))"
"@
stvx %1,%y0
lvx %0,%y1
vor %0,%1,%1
#
#
#
vxor %0,%0,%0
* return output_vec_const_move (operands);"
[(set_attr "type" "vecstore,vecload,veclogical,store,load,*,veclogical,*")])
;; Load up a vector with the most significant bit set by loading up -1 and
;; doing a shift left
(define_split
[(set (match_operand:VM 0 "altivec_register_operand")
(match_operand:VM 1 "easy_vector_constant_msb"))]
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode) && reload_completed"
[(const_int 0)]
{
rtx dest = operands[0];
machine_mode mode;
rtvec v;
int i, num_elements;
switch (easy_altivec_constant (operands[1], mode))
{
case 1:
mode = V16QImode;
break;
case 2:
mode = V8HImode;
break;
case 4:
mode = V4SImode;
break;
default:
gcc_unreachable ();
}
if (mode != mode)
dest = gen_lowpart (mode, dest);
num_elements = GET_MODE_NUNITS (mode);
v = rtvec_alloc (num_elements);
for (i = 0; i < num_elements; i++)
RTVEC_ELT (v, i) = constm1_rtx;
rs6000_expand_vector_init (dest, gen_rtx_PARALLEL (mode, v));
emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, dest, dest)));
DONE;
})
(define_split
[(set (match_operand:VM 0 "altivec_register_operand")
(match_operand:VM 1 "easy_vector_constant_add_self"))]
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode) && reload_completed"
[(set (match_dup 0) (match_dup 3))
(set (match_dup 0) (match_dup 4))]
{
rtx dup = gen_easy_altivec_constant (operands[1]);
rtx const_vec;
machine_mode op_mode = mode;
/* Divide the operand of the resulting VEC_DUPLICATE, and use
simplify_rtx to make a CONST_VECTOR. */
XEXP (dup, 0) = simplify_const_binary_operation (ASHIFTRT, QImode,
XEXP (dup, 0), const1_rtx);
const_vec = simplify_rtx (dup);
if (op_mode == V4SFmode)
{
op_mode = V4SImode;
operands[0] = gen_lowpart (op_mode, operands[0]);
}
if (GET_MODE (const_vec) == op_mode)
operands[3] = const_vec;
else
operands[3] = gen_lowpart (op_mode, const_vec);
operands[4] = gen_rtx_PLUS (op_mode, operands[0], operands[0]);
})
(define_split
[(set (match_operand:VM 0 "altivec_register_operand")
(match_operand:VM 1 "easy_vector_constant_vsldoi"))]
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode) && can_create_pseudo_p ()"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))
(set (match_dup 0)
(unspec:VM [(match_dup 2)
(match_dup 4)
(match_dup 6)]
UNSPEC_VSLDOI))]
{
rtx op1 = operands[1];
int elt = (BYTES_BIG_ENDIAN) ? 0 : GET_MODE_NUNITS (mode) - 1;
HOST_WIDE_INT val = const_vector_elt_as_int (op1, elt);
rtx rtx_val = GEN_INT (val);
int shift = vspltis_shifted (op1);
gcc_assert (shift != 0);
operands[2] = gen_reg_rtx (mode);
operands[3] = gen_const_vec_duplicate (mode, rtx_val);
operands[4] = gen_reg_rtx (mode);
if (shift < 0)
{
operands[5] = CONSTM1_RTX (mode);
operands[6] = GEN_INT (-shift);
}
else
{
operands[5] = CONST0_RTX (mode);
operands[6] = GEN_INT (shift);
}
})
(define_insn_and_split "sldoi_to_mov"
[(set (match_operand:VM 0 "altivec_register_operand")
(unspec:VM [(match_operand:VM 1 "const_vector_each_byte_same")
(match_dup 1)
(match_operand:QI 2 "u5bit_cint_operand")]
UNSPEC_VSLDOI))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && can_create_pseudo_p ()"
"#"
"&& 1"
[(set (match_dup 0) (match_dup 1))]
"{
if (!easy_vector_constant (operands[1], mode))
{
rtx dest = gen_reg_rtx (mode);
emit_move_insn (dest, operands[1]);
operands[1] = dest;
}
}")
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(reg:SI VRSAVE_REGNO)] UNSPEC_GET_VRSAVE))]
"TARGET_ALTIVEC"
{
if (TARGET_MACHO)
return "mfspr %0,256";
else
return "mfvrsave %0";
}
[(set_attr "type" "*")])
(define_insn "*set_vrsave_internal"
[(match_parallel 0 "vrsave_operation"
[(set (reg:SI VRSAVE_REGNO)
(unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
(reg:SI VRSAVE_REGNO)] UNSPECV_SET_VRSAVE))])]
"TARGET_ALTIVEC"
{
if (TARGET_MACHO)
return "mtspr 256,%1";
else
return "mtvrsave %1";
}
[(set_attr "type" "*")])
(define_insn "*save_world"
[(match_parallel 0 "save_world_operation"
[(clobber (reg:SI LR_REGNO))
(use (match_operand:SI 1 "call_operand" "s"))])]
"TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
"bl %z1"
[(set_attr "type" "branch")])
(define_insn "*restore_world"
[(match_parallel 0 "restore_world_operation"
[(return)
(use (match_operand:SI 1 "call_operand" "s"))
(clobber (match_operand:SI 2 "gpc_reg_operand" "=r"))])]
"TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
"b %z1")
;; The save_vregs and restore_vregs patterns don't use memory_operand
;; because (plus (reg) (const_int)) is not a valid vector address.
;; This way is more compact than describing exactly what happens in
;; the out-of-line functions, ie. loading the constant into r11/r12
;; then using indexed addressing, and requires less editing of rtl
;; to describe the operation to dwarf2out_frame_debug_expr.
(define_insn "*save_vregs__r11"
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P LR_REGNO))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
(clobber (reg:P 11))
(use (reg:P 0))
(set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
(match_operand:P 3 "short_cint_operand" "I")))
(match_operand:V4SI 4 "altivec_register_operand" "v"))])]
"TARGET_ALTIVEC"
"bl %1"
[(set_attr "type" "branch")])
(define_insn "*save_vregs__r12"
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P LR_REGNO))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
(clobber (reg:P 12))
(use (reg:P 0))
(set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
(match_operand:P 3 "short_cint_operand" "I")))
(match_operand:V4SI 4 "altivec_register_operand" "v"))])]
"TARGET_ALTIVEC"
"bl %1"
[(set_attr "type" "branch")])
(define_insn "*restore_vregs__r11"
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P LR_REGNO))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
(clobber (reg:P 11))
(use (reg:P 0))
(set (match_operand:V4SI 2 "altivec_register_operand" "=v")
(mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
(match_operand:P 4 "short_cint_operand" "I"))))])]
"TARGET_ALTIVEC"
"bl %1"
[(set_attr "type" "branch")])
(define_insn "*restore_vregs__r12"
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P LR_REGNO))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
(clobber (reg:P 12))
(use (reg:P 0))
(set (match_operand:V4SI 2 "altivec_register_operand" "=v")
(mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
(match_operand:P 4 "short_cint_operand" "I"))))])]
"TARGET_ALTIVEC"
"bl %1"
[(set_attr "type" "branch")])
;; Simple binary operations.
;; add
(define_insn "add3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(plus:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vaddum %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_addv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vaddfp %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vaddcuw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VADDCUW))]
"VECTOR_UNIT_ALTIVEC_P (V4SImode)"
"vaddcuw %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vaddus"
[(set (match_operand:VI 0 "register_operand" "=v")
(us_plus:VI (match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
""
"vaddus %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vaddss"
[(set (match_operand:VI 0 "register_operand" "=v")
(ss_plus:VI (match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"VECTOR_UNIT_ALTIVEC_P (mode)"
"vaddss %0,%1,%2"
[(set_attr "type" "vecsimple")])
;; sub
(define_insn "sub3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(minus:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vsubum %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_subv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vsubfp %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vsubcuw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUBCUW))]
"VECTOR_UNIT_ALTIVEC_P (V4SImode)"
"vsubcuw %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubus"
[(set (match_operand:VI 0 "register_operand" "=v")
(us_minus:VI (match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"VECTOR_UNIT_ALTIVEC_P (mode)"
"vsubus %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubss"
[(set (match_operand:VI 0 "register_operand" "=v")
(ss_minus:VI (match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"VECTOR_UNIT_ALTIVEC_P (mode)"
"vsubss %0,%1,%2"
[(set_attr "type" "vecsimple")])
;;
(define_insn "uavg3_ceil"
[(set (match_operand:VI 0 "register_operand" "=v")
(unspec:VI [(match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")]
UNSPEC_VAVGU))]
"TARGET_ALTIVEC"
"vavgu %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "avg3_ceil"
[(set (match_operand:VI 0 "register_operand" "=v")
(unspec:VI [(match_operand:VI 1 "register_operand" "v")
(match_operand:VI 2 "register_operand" "v")]
UNSPEC_VAVGS))]
"VECTOR_UNIT_ALTIVEC_P (mode)"
"vavgs %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vcmpbfp"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")]
UNSPEC_VCMPBFP))]
"VECTOR_UNIT_ALTIVEC_P (V4SImode)"
"vcmpbfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_eqv1ti"
[(set (match_operand:V1TI 0 "altivec_register_operand" "=v")
(eq:V1TI (match_operand:V1TI 1 "altivec_register_operand" "v")
(match_operand:V1TI 2 "altivec_register_operand" "v")))]
"TARGET_POWER10"
"vcmpequq %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "altivec_eq"
[(set (match_operand:VI2 0 "altivec_register_operand" "=v")
(eq:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
(match_operand:VI2 2 "altivec_register_operand" "v")))]
""
"vcmpequ %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_gt"
[(set (match_operand:VI2 0 "altivec_register_operand" "=v")
(gt:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
(match_operand:VI2 2 "altivec_register_operand" "v")))]
""
"vcmpgts %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_gtv1ti"
[(set (match_operand:V1TI 0 "altivec_register_operand" "=v")
(gt:V1TI (match_operand:V1TI 1 "altivec_register_operand" "v")
(match_operand:V1TI 2 "altivec_register_operand" "v")))]
"TARGET_POWER10"
"vcmpgtsq %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_gtu"
[(set (match_operand:VI2 0 "altivec_register_operand" "=v")
(gtu:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
(match_operand:VI2 2 "altivec_register_operand" "v")))]
""
"vcmpgtu %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_gtuv1ti"
[(set (match_operand:V1TI 0 "altivec_register_operand" "=v")
(gtu:V1TI (match_operand:V1TI 1 "altivec_register_operand" "v")
(match_operand:V1TI 2 "altivec_register_operand" "v")))]
"TARGET_POWER10"
"vcmpgtuq %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_eqv4sf"
[(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
(eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
(match_operand:V4SF 2 "altivec_register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpeqfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "*altivec_gtv4sf"
[(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
(gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
(match_operand:V4SF 2 "altivec_register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpgtfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "*altivec_gev4sf"
[(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
(ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
(match_operand:V4SF 2 "altivec_register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpgefp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_vsel"
[(set (match_operand:VM 0 "register_operand" "=wa,v")
(ior:VM
(and:VM
(not:VM (match_operand:VM 3 "register_operand" "wa,v"))
(match_operand:VM 1 "register_operand" "wa,v"))
(and:VM
(match_dup 3)
(match_operand:VM 2 "register_operand" "wa,v"))))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)"
"@
xxsel %x0,%x1,%x2,%x3
vsel %0,%1,%2,%3"
[(set_attr "type" "vecmove")
(set_attr "isa" "")])
(define_insn "altivec_vsel2"
[(set (match_operand:VM 0 "register_operand" "=wa,v")
(ior:VM
(and:VM
(not:VM (match_operand:VM 3 "register_operand" "wa,v"))
(match_operand:VM 1 "register_operand" "wa,v"))
(and:VM
(match_operand:VM 2 "register_operand" "wa,v")
(match_dup 3))))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)"
"@
xxsel %x0,%x1,%x2,%x3
vsel %0,%1,%2,%3"
[(set_attr "type" "vecmove")
(set_attr "isa" "")])
(define_insn "altivec_vsel3"
[(set (match_operand:VM 0 "register_operand" "=wa,v")
(ior:VM
(and:VM
(match_operand:VM 3 "register_operand" "wa,v")
(match_operand:VM 1 "register_operand" "wa,v"))
(and:VM
(not:VM (match_dup 3))
(match_operand:VM 2 "register_operand" "wa,v"))))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)"
"@
xxsel %x0,%x2,%x1,%x3
vsel %0,%2,%1,%3"
[(set_attr "type" "vecmove")
(set_attr "isa" "")])
(define_insn "altivec_vsel4"
[(set (match_operand:VM 0 "register_operand" "=wa,v")
(ior:VM
(and:VM
(match_operand:VM 1 "register_operand" "wa,v")
(match_operand:VM 3 "register_operand" "wa,v"))
(and:VM
(not:VM (match_dup 3))
(match_operand:VM 2 "register_operand" "wa,v"))))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)"
"@
xxsel %x0,%x2,%x1,%x3
vsel %0,%2,%1,%3"
[(set_attr "type" "vecmove")
(set_attr "isa" "")])
;; Fused multiply add.
(define_insn "*altivec_fmav4sf4"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")
(match_operand:V4SF 3 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vmaddfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
(define_expand "altivec_mulv4sf3"
[(set (match_operand:V4SF 0 "register_operand")
(fma:V4SF (match_operand:V4SF 1 "register_operand")
(match_operand:V4SF 2 "register_operand")
(match_dup 3)))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
{
rtx neg0;
/* Generate [-0.0, -0.0, -0.0, -0.0]. */
neg0 = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
operands[3] = gen_lowpart (V4SFmode, neg0);
})
;; 32-bit integer multiplication
;; A_high = Operand_0 & 0xFFFF0000 >> 16
;; A_low = Operand_0 & 0xFFFF
;; B_high = Operand_1 & 0xFFFF0000 >> 16
;; B_low = Operand_1 & 0xFFFF
;; result = A_low * B_low + (A_high * B_low + B_high * A_low) << 16
;; (define_insn "mulv4si3"
;; [(set (match_operand:V4SI 0 "register_operand" "=v")
;; (mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
;; (match_operand:V4SI 2 "register_operand" "v")))]
(define_insn "mulv4si3_p8"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")))]
"TARGET_P8_VECTOR"
"vmuluwm %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_expand "mulv4si3"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
rtx zero;
rtx swap;
rtx small_swap;
rtx sixteen;
rtx one;
rtx two;
rtx low_product;
rtx high_product;
if (TARGET_P8_VECTOR)
{
emit_insn (gen_mulv4si3_p8 (operands[0], operands[1], operands[2]));
DONE;
}
zero = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
sixteen = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vspltisw (sixteen, gen_rtx_CONST_INT (V4SImode, -16)));
swap = gen_reg_rtx (V4SImode);
emit_insn (gen_vrotlv4si3 (swap, operands[2], sixteen));
one = gen_reg_rtx (V8HImode);
convert_move (one, operands[1], 0);
two = gen_reg_rtx (V8HImode);
convert_move (two, operands[2], 0);
small_swap = gen_reg_rtx (V8HImode);
convert_move (small_swap, swap, 0);
low_product = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vmulouh (low_product, one, two));
high_product = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
emit_insn (gen_vashlv4si3 (high_product, high_product, sixteen));
emit_insn (gen_addv4si3 (operands[0], high_product, low_product));
DONE;
})
(define_expand "mulv8hi3"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
rtx zero = gen_reg_rtx (V8HImode);
emit_insn (gen_altivec_vspltish (zero, const0_rtx));
emit_insn (gen_fmav8hi4 (operands[0], operands[1], operands[2], zero));
DONE;
})
;; Map UNSPEC_SLDB to "l" and UNSPEC_SRDB to "r".
(define_int_attr SLDB_lr [(UNSPEC_SLDB "l")
(UNSPEC_SRDB "r")])
(define_int_iterator VSHIFT_DBL_LR [UNSPEC_SLDB UNSPEC_SRDB])
(define_insn "vsdb_"
[(set (match_operand:VEC_IC 0 "register_operand" "=v")
(unspec:VEC_IC [(match_operand:VEC_IC 1 "register_operand" "v")
(match_operand:VEC_IC 2 "register_operand" "v")
(match_operand:QI 3 "const_0_to_12_operand" "n")]
VSHIFT_DBL_LR))]
"TARGET_POWER10"
"vsdbi %0,%1,%2,%3"
[(set_attr "type" "vecsimple")])
(define_expand "vstrir_"
[(set (match_operand:VIshort 0 "altivec_register_operand")
(unspec:VIshort [(match_operand:VIshort 1 "altivec_register_operand")]
UNSPEC_VSTRIR))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_vstrir_direct_ (operands[0], operands[1]));
else
emit_insn (gen_vstril_direct_ (operands[0], operands[1]));
DONE;
})
(define_insn "vstrir_direct_"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
UNSPEC_VSTRIR))]
"TARGET_POWER10"
"vstrir %0,%1"
[(set_attr "type" "vecsimple")])
;; This expands into same code as vstrir followed by condition logic
;; so that a single vstribr. or vstrihr. or vstribl. or vstrihl. instruction
;; can, for example, satisfy the needs of a vec_strir () function paired
;; with a vec_strir_p () function if both take the same incoming arguments.
(define_expand "vstrir_p_"
[(match_operand:SI 0 "gpc_reg_operand")
(match_operand:VIshort 1 "altivec_register_operand")]
"TARGET_POWER10"
{
rtx scratch = gen_reg_rtx (mode);
if (BYTES_BIG_ENDIAN)
emit_insn (gen_vstrir_p_direct_ (scratch, operands[1]));
else
emit_insn (gen_vstril_p_direct_ (scratch, operands[1]));
emit_insn (gen_cr6_test_for_zero (operands[0]));
DONE;
})
(define_insn "vstrir_p_direct_"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
UNSPEC_VSTRIR))
(set (reg:CC CR6_REGNO)
(unspec:CC [(match_dup 1)]
UNSPEC_VSTRIR))]
"TARGET_POWER10"
"vstrir. %0,%1"
[(set_attr "type" "vecsimple")])
(define_expand "vstril_"
[(set (match_operand:VIshort 0 "altivec_register_operand")
(unspec:VIshort [(match_operand:VIshort 1 "altivec_register_operand")]
UNSPEC_VSTRIR))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_vstril_direct_ (operands[0], operands[1]));
else
emit_insn (gen_vstrir_direct_ (operands[0], operands[1]));
DONE;
})
(define_insn "vstril_direct_"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
UNSPEC_VSTRIL))]
"TARGET_POWER10"
"vstril %0,%1"
[(set_attr "type" "vecsimple")])
;; This expands into same code as vstril_ followed by condition logic
;; so that a single vstribr. or vstrihr. or vstribl. or vstrihl. instruction
;; can, for example, satisfy the needs of a vec_stril () function paired
;; with a vec_stril_p () function if both take the same incoming arguments.
(define_expand "vstril_p_"
[(match_operand:SI 0 "gpc_reg_operand")
(match_operand:VIshort 1 "altivec_register_operand")]
"TARGET_POWER10"
{
rtx scratch = gen_reg_rtx (mode);
if (BYTES_BIG_ENDIAN)
emit_insn (gen_vstril_p_direct_ (scratch, operands[1]));
else
emit_insn (gen_vstrir_p_direct_ (scratch, operands[1]));
emit_insn (gen_cr6_test_for_zero (operands[0]));
DONE;
})
(define_insn "vstril_p_direct_"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
UNSPEC_VSTRIL))
(set (reg:CC CR6_REGNO)
(unspec:CC [(match_dup 1)]
UNSPEC_VSTRIR))]
"TARGET_POWER10"
"vstril. %0,%1"
[(set_attr "type" "vecsimple")])
;; Fused multiply subtract
(define_insn "*altivec_vnmsubfp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(neg:V4SF
(fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")
(neg:V4SF
(match_operand:V4SF 3 "register_operand" "v")))))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vnmsubfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vmsumum"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
(match_operand:VIshort 2 "register_operand" "v")
(match_operand:V4SI 3 "register_operand" "v")]
UNSPEC_VMSUMU))]
"TARGET_ALTIVEC"
"vmsumum %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsumudm"
[(set (match_operand:V1TI 0 "register_operand" "=v")
(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
(match_operand:V2DI 2 "register_operand" "v")
(match_operand:V1TI 3 "register_operand" "v")]
UNSPEC_VMSUMUDM))]
"TARGET_P8_VECTOR"
"vmsumudm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsummm"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
(match_operand:VIshort 2 "register_operand" "v")
(match_operand:V4SI 3 "register_operand" "v")]
UNSPEC_VMSUMM))]
"TARGET_ALTIVEC"
"vmsummm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsumshm"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V4SI 3 "register_operand" "v")]
UNSPEC_VMSUMSHM))]
"TARGET_ALTIVEC"
"vmsumshm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsumuhs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V4SI 3 "register_operand" "v")]
UNSPEC_VMSUMUHS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmsumuhs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsumshs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V4SI 3 "register_operand" "v")]
UNSPEC_VMSUMSHS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmsumshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
;; max
(define_insn "umax3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(umax:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vmaxu %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "smax3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(smax:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vmaxs %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_smaxv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vmaxfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "umin3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(umin:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vminu %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "smin3"
[(set (match_operand:VI2 0 "register_operand" "=v")
(smin:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vmins %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_sminv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vminfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_vmhaddshs"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V8HI 3 "register_operand" "v")]
UNSPEC_VMHADDSHS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmhaddshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmhraddshs"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V8HI 3 "register_operand" "v")]
UNSPEC_VMHRADDSHS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmhraddshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "fmav8hi4"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(plus:V8HI (mult:V8HI (match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v"))
(match_operand:V8HI 3 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vmladduhm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_expand "altivec_vmrghb"
[(use (match_operand:V16QI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (
gen_altivec_vmrghb_direct_be (operands[0], operands[1], operands[2]));
else
emit_insn (
gen_altivec_vmrglb_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
(define_insn "altivec_vmrghb_direct_be"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_select:V16QI
(vec_concat:V32QI
(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v"))
(parallel [(const_int 0) (const_int 16)
(const_int 1) (const_int 17)
(const_int 2) (const_int 18)
(const_int 3) (const_int 19)
(const_int 4) (const_int 20)
(const_int 5) (const_int 21)
(const_int 6) (const_int 22)
(const_int 7) (const_int 23)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"vmrghb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrghb_direct_le"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_select:V16QI
(vec_concat:V32QI
(match_operand:V16QI 2 "register_operand" "v")
(match_operand:V16QI 1 "register_operand" "v"))
(parallel [(const_int 8) (const_int 24)
(const_int 9) (const_int 25)
(const_int 10) (const_int 26)
(const_int 11) (const_int 27)
(const_int 12) (const_int 28)
(const_int 13) (const_int 29)
(const_int 14) (const_int 30)
(const_int 15) (const_int 31)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrghb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vmrghh"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (
gen_altivec_vmrghh_direct_be (operands[0], operands[1], operands[2]));
else
emit_insn (
gen_altivec_vmrglh_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
(define_insn "altivec_vmrghh_direct_be"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v"))
(parallel [(const_int 0) (const_int 8)
(const_int 1) (const_int 9)
(const_int 2) (const_int 10)
(const_int 3) (const_int 11)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrghh_direct_le"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V8HI 1 "register_operand" "v"))
(parallel [(const_int 4) (const_int 12)
(const_int 5) (const_int 13)
(const_int 6) (const_int 14)
(const_int 7) (const_int 15)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vmrghw"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmrghw_direct_v4si_be (operands[0],
operands[1],
operands[2]));
else
emit_insn (gen_altivec_vmrglw_direct_v4si_le (operands[0],
operands[2],
operands[1]));
DONE;
})
(define_insn "altivec_vmrghw_direct__be"
[(set (match_operand:VSX_W 0 "register_operand" "=wa,v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 1 "register_operand" "wa,v")
(match_operand:VSX_W 2 "register_operand" "wa,v"))
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"@
xxmrghw %x0,%x1,%x2
vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrghw_direct__le"
[(set (match_operand:VSX_W 0 "register_operand" "=wa,v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 2 "register_operand" "wa,v")
(match_operand:VSX_W 1 "register_operand" "wa,v"))
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"@
xxmrghw %x0,%x1,%x2
vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vmrghsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_select:V4SF
(vec_concat:V8SF
(match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
{
if (BYTES_BIG_ENDIAN)
return "vmrghw %0,%1,%2";
else
return "vmrglw %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_expand "altivec_vmrglb"
[(use (match_operand:V16QI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (
gen_altivec_vmrglb_direct_be (operands[0], operands[1], operands[2]));
else
emit_insn (
gen_altivec_vmrghb_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
(define_insn "altivec_vmrglb_direct_be"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_select:V16QI
(vec_concat:V32QI
(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v"))
(parallel [(const_int 8) (const_int 24)
(const_int 9) (const_int 25)
(const_int 10) (const_int 26)
(const_int 11) (const_int 27)
(const_int 12) (const_int 28)
(const_int 13) (const_int 29)
(const_int 14) (const_int 30)
(const_int 15) (const_int 31)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"vmrglb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglb_direct_le"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_select:V16QI
(vec_concat:V32QI
(match_operand:V16QI 2 "register_operand" "v")
(match_operand:V16QI 1 "register_operand" "v"))
(parallel [(const_int 0) (const_int 16)
(const_int 1) (const_int 17)
(const_int 2) (const_int 18)
(const_int 3) (const_int 19)
(const_int 4) (const_int 20)
(const_int 5) (const_int 21)
(const_int 6) (const_int 22)
(const_int 7) (const_int 23)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrglb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vmrglh"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (
gen_altivec_vmrglh_direct_be (operands[0], operands[1], operands[2]));
else
emit_insn (
gen_altivec_vmrghh_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
(define_insn "altivec_vmrglh_direct_be"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v"))
(parallel [(const_int 4) (const_int 12)
(const_int 5) (const_int 13)
(const_int 6) (const_int 14)
(const_int 7) (const_int 15)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglh_direct_le"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 2 "register_operand" "v")
(match_operand:V8HI 1 "register_operand" "v"))
(parallel [(const_int 0) (const_int 8)
(const_int 1) (const_int 9)
(const_int 2) (const_int 10)
(const_int 3) (const_int 11)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vmrglw"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmrglw_direct_v4si_be (operands[0],
operands[1],
operands[2]));
else
emit_insn (gen_altivec_vmrghw_direct_v4si_le (operands[0],
operands[2],
operands[1]));
DONE;
})
(define_insn "altivec_vmrglw_direct__be"
[(set (match_operand:VSX_W 0 "register_operand" "=wa,v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 1 "register_operand" "wa,v")
(match_operand:VSX_W 2 "register_operand" "wa,v"))
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
"@
xxmrglw %x0,%x1,%x2
vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglw_direct__le"
[(set (match_operand:VSX_W 0 "register_operand" "=wa,v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 2 "register_operand" "wa,v")
(match_operand:VSX_W 1 "register_operand" "wa,v"))
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"@
xxmrglw %x0,%x1,%x2
vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vmrglsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_select:V4SF
(vec_concat:V8SF
(match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
{
if (BYTES_BIG_ENDIAN)
return "vmrglw %0,%1,%2";
else
return "vmrghw %0,%2,%1";
}
[(set_attr "type" "vecperm")])
;; Power8 vector merge two V2DF/V2DI even words to V2DF
(define_expand "p8_vmrgew_"
[(use (match_operand:VSX_D 0 "vsx_register_operand"))
(use (match_operand:VSX_D 1 "vsx_register_operand"))
(use (match_operand:VSX_D 2 "vsx_register_operand"))]
"VECTOR_MEM_VSX_P (mode)"
{
rtvec v;
rtx x;
v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
x = gen_rtx_VEC_CONCAT (mode, operands[1], operands[2]);
x = gen_rtx_VEC_SELECT (mode, x, gen_rtx_PARALLEL (VOIDmode, v));
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
;; Power8 vector merge two V4SF/V4SI even words to V4SF
(define_insn "p8_vmrgew_"
[(set (match_operand:VSX_W 0 "register_operand" "=v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 1 "register_operand" "v")
(match_operand:VSX_W 2 "register_operand" "v"))
(parallel [(const_int 0) (const_int 4)
(const_int 2) (const_int 6)])))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
return "vmrgew %0,%1,%2";
else
return "vmrgow %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "p8_vmrgow_"
[(set (match_operand:VSX_W 0 "register_operand" "=v")
(vec_select:VSX_W
(vec_concat:
(match_operand:VSX_W 1 "register_operand" "v")
(match_operand:VSX_W 2 "register_operand" "v"))
(parallel [(const_int 1) (const_int 5)
(const_int 3) (const_int 7)])))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
return "vmrgow %0,%1,%2";
else
return "vmrgew %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_expand "p8_vmrgow_"
[(use (match_operand:VSX_D 0 "vsx_register_operand"))
(use (match_operand:VSX_D 1 "vsx_register_operand"))
(use (match_operand:VSX_D 2 "vsx_register_operand"))]
"VECTOR_MEM_VSX_P (mode)"
{
rtvec v;
rtx x;
v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
x = gen_rtx_VEC_CONCAT (mode, operands[1], operands[2]);
x = gen_rtx_VEC_SELECT (mode, x, gen_rtx_PARALLEL (VOIDmode, v));
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
(define_insn "p8_vmrgew__direct"
[(set (match_operand:VSX_W 0 "register_operand" "=v")
(unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v")
(match_operand:VSX_W 2 "register_operand" "v")]
UNSPEC_VMRGEW_DIRECT))]
"TARGET_P8_VECTOR"
"vmrgew %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "p8_vmrgow__direct"
[(set (match_operand:VSX_W 0 "register_operand" "=v")
(unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v")
(match_operand:VSX_W 2 "register_operand" "v")]
UNSPEC_VMRGOW_DIRECT))]
"TARGET_P8_VECTOR"
"vmrgow %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "vec_widen_umult_even_v16qi"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_even_v16qi"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_even_v8hi"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_even_v8hi"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_even_v4si"
[(use (match_operand:V2DI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_even_v2di"
[(use (match_operand:V1TI 0 "register_operand"))
(use (match_operand:V2DI 1 "register_operand"))
(use (match_operand:V2DI 2 "register_operand"))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuleud (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuloud (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_even_v4si"
[(use (match_operand:V2DI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulesw (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulosw (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_even_v2di"
[(use (match_operand:V1TI 0 "register_operand"))
(use (match_operand:V2DI 1 "register_operand"))
(use (match_operand:V2DI 2 "register_operand"))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulesd (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulosd (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_odd_v16qi"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_odd_v16qi"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:V16QI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_odd_v8hi"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_odd_v8hi"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_odd_v4si"
[(use (match_operand:V2DI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_umult_odd_v2di"
[(use (match_operand:V1TI 0 "register_operand"))
(use (match_operand:V2DI 1 "register_operand"))
(use (match_operand:V2DI 2 "register_operand"))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmuloud (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmuleud (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_odd_v4si"
[(use (match_operand:V2DI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_P8_VECTOR"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulosw (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulesw (operands[0], operands[1], operands[2]));
DONE;
})
(define_expand "vec_widen_smult_odd_v2di"
[(use (match_operand:V1TI 0 "register_operand"))
(use (match_operand:V2DI 1 "register_operand"))
(use (match_operand:V2DI 2 "register_operand"))]
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vmulosd (operands[0], operands[1], operands[2]));
else
emit_insn (gen_altivec_vmulesd (operands[0], operands[1], operands[2]));
DONE;
})
(define_insn "altivec_vmuleub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VMULEUB))]
"TARGET_ALTIVEC"
"vmuleub %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmuloub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VMULOUB))]
"TARGET_ALTIVEC"
"vmuloub %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulesb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VMULESB))]
"TARGET_ALTIVEC"
"vmulesb %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulosb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VMULOSB))]
"TARGET_ALTIVEC"
"vmulosb %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmuleuh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
UNSPEC_VMULEUH))]
"TARGET_ALTIVEC"
"vmuleuh %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulouh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
UNSPEC_VMULOUH))]
"TARGET_ALTIVEC"
"vmulouh %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulesh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
UNSPEC_VMULESH))]
"TARGET_ALTIVEC"
"vmulesh %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulosh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
UNSPEC_VMULOSH))]
"TARGET_ALTIVEC"
"vmulosh %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmuleuw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
(unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VMULEUW))]
"TARGET_P8_VECTOR"
"vmuleuw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmuleud"
[(set (match_operand:V1TI 0 "register_operand" "=v")
(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
(match_operand:V2DI 2 "register_operand" "v")]
UNSPEC_VMULEUD))]
"TARGET_POWER10"
"vmuleud %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulouw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
(unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VMULOUW))]
"TARGET_P8_VECTOR"
"vmulouw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmuloud"
[(set (match_operand:V1TI 0 "register_operand" "=v")
(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
(match_operand:V2DI 2 "register_operand" "v")]
UNSPEC_VMULOUD))]
"TARGET_POWER10"
"vmuloud %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulesw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
(unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VMULESW))]
"TARGET_P8_VECTOR"
"vmulesw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulesd"
[(set (match_operand:V1TI 0 "register_operand" "=v")
(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
(match_operand:V2DI 2 "register_operand" "v")]
UNSPEC_VMULESD))]
"TARGET_POWER10"
"vmulesd %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulosw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
(unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VMULOSW))]
"TARGET_P8_VECTOR"
"vmulosw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulosd"
[(set (match_operand:V1TI 0 "register_operand" "=v")
(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
(match_operand:V2DI 2 "register_operand" "v")]
UNSPEC_VMULOSD))]
"TARGET_POWER10"
"vmulosd %0,%1,%2"
[(set_attr "type" "veccomplex")])
;; Vector pack/unpack
(define_insn "altivec_vpkpx"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VPKPX))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
return "vpkpx %0,%1,%2";
else
return "vpkpx %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpksss"
[(set (match_operand: 0 "register_operand" "=v")
(unspec: [(match_operand:VP 1 "register_operand" "v")
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_SIGN_SIGN_SAT))]
""
{
if (BYTES_BIG_ENDIAN)
return "vpksss %0,%1,%2";
else
return "vpksss %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpksus"
[(set (match_operand: 0 "register_operand" "=v")
(unspec: [(match_operand:VP 1 "register_operand" "v")
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_SIGN_UNS_SAT))]
""
{
if (BYTES_BIG_ENDIAN)
return "vpksus %0,%1,%2";
else
return "vpksus %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpkuus"
[(set (match_operand: 0 "register_operand" "=v")
(unspec: [(match_operand:VP 1 "register_operand" "v")
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_UNS_UNS_SAT))]
""
{
if (BYTES_BIG_ENDIAN)
return "vpkuus %0,%1,%2";
else
return "vpkuus %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpkuum"
[(set (match_operand: 0 "register_operand" "=v")
(unspec: [(match_operand:VP 1 "register_operand" "v")
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_UNS_UNS_MOD))]
""
{
if (BYTES_BIG_ENDIAN)
return "vpkuum %0,%1,%2";
else
return "vpkuum %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpkuum_direct"
[(set (match_operand: 0 "register_operand" "=v")
(unspec: [(match_operand:VP 1 "register_operand" "v")
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_UNS_UNS_MOD_DIRECT))]
""
{
if (BYTES_BIG_ENDIAN)
return "vpkuum %0,%1,%2";
else
return "vpkuum %0,%2,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vrl"
[(set (match_operand:VI2 0 "register_operand" "=v")
(rotate:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vrl %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vrlq"
[(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
(rotate:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v")
(match_operand:V1TI 2 "vsx_register_operand" "v")))]
"TARGET_POWER10"
;; rotate amount in needs to be in bits[57:63] of operand2.
"vrlq %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vrlmi"
[(set (match_operand:VIlong 0 "register_operand" "=v")
(unspec:VIlong [(match_operand:VIlong 1 "register_operand" "v")
(match_operand:VIlong 2 "register_operand" "0")
(match_operand:VIlong 3 "register_operand" "v")]
UNSPEC_VRLMI))]
"TARGET_P9_VECTOR"
"vrlmi %0,%1,%3"
[(set_attr "type" "veclogical")])
(define_expand "altivec_vrlqmi"
[(set (match_operand:V1TI 0 "vsx_register_operand")
(unspec:V1TI [(match_operand:V1TI 1 "vsx_register_operand")
(match_operand:V1TI 2 "vsx_register_operand")
(match_operand:V1TI 3 "vsx_register_operand")]
UNSPEC_VRLMI))]
"TARGET_POWER10"
{
/* Mask bit begin, end fields need to be in bits [41:55] of 128-bit operand2.
Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */
rtx tmp = gen_reg_rtx (V1TImode);
emit_insn (gen_xxswapd_v1ti (tmp, operands[3]));
emit_insn (gen_altivec_vrlqmi_inst (operands[0], operands[1], operands[2],
tmp));
DONE;
})
(define_insn "altivec_vrlqmi_inst"
[(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
(unspec:V1TI [(match_operand:V1TI 1 "vsx_register_operand" "v")
(match_operand:V1TI 2 "vsx_register_operand" "0")
(match_operand:V1TI 3 "vsx_register_operand" "v")]
UNSPEC_VRLMI))]
"TARGET_POWER10"
"vrlqmi %0,%1,%3"
[(set_attr "type" "veclogical")])
(define_insn "altivec_vrlnm"
[(set (match_operand:VIlong 0 "register_operand" "=v")
(unspec:VIlong [(match_operand:VIlong 1 "register_operand" "v")
(match_operand:VIlong 2 "register_operand" "v")]
UNSPEC_VRLNM))]
"TARGET_P9_VECTOR"
"vrlnm %0,%1,%2"
[(set_attr "type" "veclogical")])
(define_expand "altivec_vrlqnm"
[(set (match_operand:V1TI 0 "vsx_register_operand")
(unspec:V1TI [(match_operand:V1TI 1 "vsx_register_operand")
(match_operand:V1TI 2 "vsx_register_operand")]
UNSPEC_VRLNM))]
"TARGET_POWER10"
{
/* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */
rtx tmp = gen_reg_rtx (V1TImode);
emit_insn (gen_xxswapd_v1ti (tmp, operands[2]));
emit_insn (gen_altivec_vrlqnm_inst (operands[0], operands[1], tmp));
DONE;
})
(define_insn "altivec_vrlqnm_inst"
[(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
(unspec:V1TI [(match_operand:V1TI 1 "vsx_register_operand" "v")
(match_operand:V1TI 2 "vsx_register_operand" "v")]
UNSPEC_VRLNM))]
"TARGET_POWER10"
;; rotate and mask bits need to be in upper 64-bits of operand2.
"vrlqnm %0,%1,%2"
[(set_attr "type" "veclogical")])
(define_insn "altivec_vsl"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSLV4SI))]
"TARGET_ALTIVEC"
"vsl %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vslo"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSLO))]
"TARGET_ALTIVEC"
"vslo %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "vslv"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VSLV))]
"TARGET_P9_VECTOR"
"vslv %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "vsrv"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
UNSPEC_VSRV))]
"TARGET_P9_VECTOR"
"vsrv %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_vsl"
[(set (match_operand:VI2 0 "register_operand" "=v")
(ashift:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vsl %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vslq_"
[(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v")
(ashift:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand" "v")
(match_operand:VEC_TI 2 "vsx_register_operand" "v")))]
"TARGET_POWER10"
/* Shift amount in needs to be in bits[57:63] of 128-bit operand. */
"vslq %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_vsr"
[(set (match_operand:VI2 0 "register_operand" "=v")
(lshiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vsr %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsrq_"
[(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v")
(lshiftrt:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand" "v")
(match_operand:VEC_TI 2 "vsx_register_operand" "v")))]
"TARGET_POWER10"
/* Shift amount in needs to be in bits[57:63] of 128-bit operand. */
"vsrq %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "*altivec_vsra"
[(set (match_operand:VI2 0 "register_operand" "=v")
(ashiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v")))]
""
"vsra %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsraq"
[(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
(ashiftrt:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v")
(match_operand:V1TI 2 "vsx_register_operand" "v")))]
"TARGET_POWER10"
/* Shift amount in needs to be in bits[57:63] of 128-bit operand. */
"vsraq %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsr"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSR))]
"TARGET_ALTIVEC"
"vsr %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vsro"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSRO))]
"TARGET_ALTIVEC"
"vsro %0,%1,%2"
[(set_attr "type" "vecperm")])
;; Optimize V2DI shifts by constants. This relies on the shift instructions
;; only looking at the bits needed to do the shift. This means we can use
;; VSPLTISW or XXSPLTIB to load up the constant, and not worry about the bits
;; that the vector shift instructions will not use.
(define_mode_iterator VSHIFT_MODE [(V4SI "TARGET_P9_VECTOR")
(V2DI "TARGET_P8_VECTOR")])
(define_code_iterator vshift_code [ashift ashiftrt lshiftrt])
(define_code_attr vshift_attr [(ashift "ashift")
(ashiftrt "ashiftrt")
(lshiftrt "lshiftrt")])
(define_insn_and_split "*altivec___const"
[(set (match_operand:VSHIFT_MODE 0 "register_operand" "=v")
(vshift_code:VSHIFT_MODE
(match_operand:VSHIFT_MODE 1 "register_operand" "v")
(match_operand:VSHIFT_MODE 2 "vector_shift_constant" "")))
(clobber (match_scratch:VSHIFT_MODE 3 "=&v"))]
"((mode == V2DImode && TARGET_P8_VECTOR)
|| (mode == V4SImode && TARGET_P9_VECTOR))"
"#"
"&& 1"
[(set (match_dup 3)
(unspec:VSHIFT_MODE [(match_dup 4)] UNSPEC_VECTOR_SHIFT))
(set (match_dup 0)
(vshift_code:VSHIFT_MODE (match_dup 1)
(match_dup 3)))]
{
if (GET_CODE (operands[3]) == SCRATCH)
operands[3] = gen_reg_rtx (mode);
operands[4] = GET_CODE (operands[2]) == CONST_VECTOR
? CONST_VECTOR_ELT (operands[2], 0)
: XEXP (operands[2], 0);
})
(define_insn "*altivec__shift_const"
[(set (match_operand:VSHIFT_MODE 0 "register_operand" "=v")
(unspec:VSHIFT_MODE [(match_operand 1 "const_int_operand" "n")]
UNSPEC_VECTOR_SHIFT))]
"TARGET_P8_VECTOR"
{
if (UINTVAL (operands[1]) <= 15)
return "vspltisw %0,%1";
else if (TARGET_P9_VECTOR)
return "xxspltib %x0,%1";
else
gcc_unreachable ();
})
(define_insn "altivec_vsum4ubs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUM4UBS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsum4ubs %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vsum4ss"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUM4S))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsum4ss %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_expand "altivec_vsum2sws"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vsum2sws_direct (operands[0], operands[1],
operands[2]));
else
{
rtx tmp1 = gen_reg_rtx (V4SImode);
rtx tmp2 = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vsldoi_v4si (tmp1, operands[2],
operands[2], GEN_INT (12)));
emit_insn (gen_altivec_vsum2sws_direct (tmp2, operands[1], tmp1));
emit_insn (gen_altivec_vsldoi_v4si (operands[0], tmp2, tmp2,
GEN_INT (4)));
}
DONE;
})
; FIXME: This can probably be expressed without an UNSPEC.
(define_insn "altivec_vsum2sws_direct"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUM2SWS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsum2sws %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_expand "altivec_vsumsws"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:V4SI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_vsumsws_direct (operands[0], operands[1],
operands[2]));
else
{
rtx tmp1 = gen_reg_rtx (V4SImode);
rtx tmp2 = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vspltw_direct (tmp1, operands[2], const0_rtx));
emit_insn (gen_altivec_vsumsws_direct (tmp2, operands[1], tmp1));
emit_insn (gen_altivec_vsldoi_v4si (operands[0], tmp2, tmp2,
GEN_INT (12)));
}
DONE;
})
; FIXME: This can probably be expressed without an UNSPEC.
(define_insn "altivec_vsumsws_direct"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUMSWS_DIRECT))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsumsws %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_expand "altivec_vspltb"
[(use (match_operand:V16QI 0 "register_operand"))
(use (match_operand:V16QI 1 "register_operand"))
(use (match_operand:QI 2 "const_0_to_15_operand"))]
"TARGET_ALTIVEC"
{
rtvec v = gen_rtvec (1, operands[2]);
rtx x;
x = gen_rtx_VEC_SELECT (QImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
x = gen_rtx_VEC_DUPLICATE (V16QImode, x);
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
(define_insn "*altivec_vspltb_internal"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_duplicate:V16QI
(vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "const_0_to_15_operand" "")]))))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN)
operands[2] = GEN_INT (15 - INTVAL (operands[2]));
return "vspltb %0,%1,%2";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltb_direct"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:QI 2 "const_0_to_15_operand" "i")]
UNSPEC_VSPLT_DIRECT))]
"TARGET_ALTIVEC"
"vspltb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vsplth"
[(use (match_operand:V8HI 0 "register_operand"))
(use (match_operand:V8HI 1 "register_operand"))
(use (match_operand:QI 2 "const_0_to_7_operand"))]
"TARGET_ALTIVEC"
{
rtvec v = gen_rtvec (1, operands[2]);
rtx x;
x = gen_rtx_VEC_SELECT (HImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
x = gen_rtx_VEC_DUPLICATE (V8HImode, x);
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
(define_insn "*altivec_vsplth_internal"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_duplicate:V8HI
(vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "const_0_to_7_operand" "")]))))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN)
operands[2] = GEN_INT (7 - INTVAL (operands[2]));
return "vsplth %0,%1,%2";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vsplth_direct"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:QI 2 "const_0_to_7_operand" "i")]
UNSPEC_VSPLT_DIRECT))]
"TARGET_ALTIVEC"
"vsplth %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vspltw"
[(use (match_operand:V4SI 0 "register_operand"))
(use (match_operand:V4SI 1 "register_operand"))
(use (match_operand:QI 2 "const_0_to_3_operand"))]
"TARGET_ALTIVEC"
{
rtvec v = gen_rtvec (1, operands[2]);
rtx x;
x = gen_rtx_VEC_SELECT (SImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
x = gen_rtx_VEC_DUPLICATE (V4SImode, x);
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
(define_insn "*altivec_vspltw_internal"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(vec_duplicate:V4SI
(vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN)
operands[2] = GEN_INT (3 - INTVAL (operands[2]));
return "vspltw %0,%1,%2";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltw_direct"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:QI 2 "const_0_to_3_operand" "i")]
UNSPEC_VSPLT_DIRECT))]
"TARGET_ALTIVEC"
"vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_expand "altivec_vspltsf"
[(use (match_operand:V4SF 0 "register_operand"))
(use (match_operand:V4SF 1 "register_operand"))
(use (match_operand:QI 2 "const_0_to_3_operand"))]
"TARGET_ALTIVEC"
{
rtvec v = gen_rtvec (1, operands[2]);
rtx x;
x = gen_rtx_VEC_SELECT (SFmode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
x = gen_rtx_VEC_DUPLICATE (V4SFmode, x);
emit_insn (gen_rtx_SET (operands[0], x));
DONE;
})
(define_insn "*altivec_vspltsf_internal"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_duplicate:V4SF
(vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
{
if (!BYTES_BIG_ENDIAN)
operands[2] = GEN_INT (3 - INTVAL (operands[2]));
return "vspltw %0,%1,%2";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltis"
[(set (match_operand:VI 0 "register_operand" "=v")
(vec_duplicate:VI
(match_operand:QI 1 "s5bit_cint_operand" "i")))]
"TARGET_ALTIVEC"
"vspltis %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vrfiz"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
(define_expand "altivec_vperm_"
[(set (match_operand:VM 0 "register_operand")
(unspec:VM [(match_operand:VM 1 "register_operand")
(match_operand:VM 2 "register_operand")
(match_operand:V16QI 3 "register_operand")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN)
{
altivec_expand_vec_perm_le (operands);
DONE;
}
})
;; Slightly prefer vperm, since the target does not overlap the source
(define_insn "altivec_vperm__direct"
[(set (match_operand:VM 0 "register_operand" "=?wa,v")
(unspec:VM [(match_operand:VM 1 "register_operand" "wa,v")
(match_operand:VM 2 "register_operand" "0,v")
(match_operand:V16QI 3 "register_operand" "wa,v")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"@
xxperm %x0,%x1,%x3
vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")
(set_attr "isa" "p9v,*")])
(define_insn "altivec_vperm_v8hiv16qi"
[(set (match_operand:V16QI 0 "register_operand" "=?wa,v")
(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "wa,v")
(match_operand:V8HI 2 "register_operand" "0,v")
(match_operand:V16QI 3 "register_operand" "wa,v")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"@
xxperm %x0,%x1,%x3
vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")
(set_attr "isa" "p9v,*")])
(define_expand "altivec_vperm__uns"
[(set (match_operand:VM 0 "register_operand")
(unspec:VM [(match_operand:VM 1 "register_operand")
(match_operand:VM 2 "register_operand")
(match_operand:V16QI 3 "register_operand")]
UNSPEC_VPERM_UNS))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN)
{
altivec_expand_vec_perm_le (operands);
DONE;
}
})
(define_insn "*altivec_vperm__uns_internal"
[(set (match_operand:VM 0 "register_operand" "=?wa,v")
(unspec:VM [(match_operand:VM 1 "register_operand" "wa,v")
(match_operand:VM 2 "register_operand" "0,v")
(match_operand:V16QI 3 "register_operand" "wa,v")]
UNSPEC_VPERM_UNS))]
"TARGET_ALTIVEC"
"@
xxperm %x0,%x1,%x3
vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")
(set_attr "isa" "p9v,*")])
(define_expand "vec_permv16qi"
[(set (match_operand:V16QI 0 "register_operand")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand")
(match_operand:V16QI 2 "register_operand")
(match_operand:V16QI 3 "register_operand")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
{
if (!BYTES_BIG_ENDIAN) {
altivec_expand_vec_perm_le (operands);
DONE;
}
})
(define_insn "*altivec_vpermr__internal"
[(set (match_operand:VM 0 "register_operand" "=?wa,v")
(unspec:VM [(match_operand:VM 1 "register_operand" "wa,v")
(match_operand:VM 2 "register_operand" "0,v")
(match_operand:V16QI 3 "register_operand" "wa,v")]
UNSPEC_VPERMR))]
"TARGET_P9_VECTOR"
"@
xxpermr %x0,%x1,%x3
vpermr %0,%1,%2,%3"
[(set_attr "type" "vecperm")
(set_attr "isa" "p9v,*")])
(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_FRIP))]
"TARGET_ALTIVEC"
"vrfip %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrfin"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_VRFIN))]
"TARGET_ALTIVEC"
"vrfin %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "*altivec_vrfim" ; floor
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_FRIM))]
"TARGET_ALTIVEC"
"vrfim %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vcfux"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:QI 2 "immediate_operand" "i")]
UNSPEC_VCFUX))]
"TARGET_ALTIVEC"
"vcfux %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vcfsx"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:QI 2 "immediate_operand" "i")]
UNSPEC_VCFSX))]
"TARGET_ALTIVEC"
"vcfsx %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vctuxs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
(match_operand:QI 2 "immediate_operand" "i")]
UNSPEC_VCTUXS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vctuxs %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vctsxs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
(match_operand:QI 2 "immediate_operand" "i")]
UNSPEC_VCTSXS))
(set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vctsxs %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vlogefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_VLOGEFP))]
"TARGET_ALTIVEC"
"vlogefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vexptefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_VEXPTEFP))]
"TARGET_ALTIVEC"
"vexptefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "*altivec_vrsqrtefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_RSQRT))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vrsqrtefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
UNSPEC_FRES))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vrefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_expand "altivec_copysign_v4sf3"
[(use (match_operand:V4SF 0 "register_operand"))
(use (match_operand:V4SF 1 "register_operand"))
(use (match_operand:V4SF 2 "register_operand"))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
{
rtx mask = gen_reg_rtx (V4SImode);
rtx mask_val = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
rtvec v = gen_rtvec (4, mask_val, mask_val, mask_val, mask_val);
emit_insn (gen_vec_initv4sisi (mask, gen_rtx_PARALLEL (V4SImode, v)));
emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2],
gen_lowpart (V4SFmode, mask)));
DONE;
})
(define_insn "altivec_vsldoi_"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
(match_operand:VM 2 "register_operand" "v")
(match_operand:QI 3 "immediate_operand" "i")]
UNSPEC_VSLDOI))]
"TARGET_ALTIVEC"
"vsldoi %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhs"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand: 1 "register_operand" "v")]
UNSPEC_VUNPACK_HI_SIGN))]
""
{
if (BYTES_BIG_ENDIAN)
return "vupkhs %0,%1";
else
return "vupkls %0,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhs_direct"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand: 1 "register_operand" "v")]
UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
""
"vupkhs %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkls"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand: 1 "register_operand" "v")]
UNSPEC_VUNPACK_LO_SIGN))]
""
{
if (BYTES_BIG_ENDIAN)
return "vupkls %0,%1";
else
return "vupkhs %0,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vupkls_direct"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand: 1 "register_operand" "v")]
UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
""
"vupkls %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKHPX))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
return "vupkhpx %0,%1";
else
return "vupklpx %0,%1";
}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupklpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKLPX))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
return "vupklpx %0,%1";
else
return "vupkhpx %0,%1";
}
[(set_attr "type" "vecperm")])
/* The cbranch_optab doesn't allow FAIL, so old cpus which are
inefficient on unaligned vsx are disabled as the cost is high
for unaligned load/store. */
(define_expand "cbranchv16qi4"
[(use (match_operator 0 "equality_operator"
[(match_operand:V16QI 1 "reg_or_mem_operand")
(match_operand:V16QI 2 "reg_or_mem_operand")]))
(use (match_operand 3))]
"VECTOR_MEM_VSX_P (V16QImode)
&& TARGET_EFFICIENT_UNALIGNED_VSX"
{
/* Use direct move for P8 LE to skip doubleword swap, as the byte
order doesn't matter for equality compare. If any operands are
altivec indexed or indirect operands, the load can be implemented
directly by altivec aligned load instruction and swap is no
need. */
if (!TARGET_P9_VECTOR
&& !BYTES_BIG_ENDIAN
&& MEM_P (operands[1])
&& !altivec_indexed_or_indirect_operand (operands[1], V16QImode)
&& MEM_P (operands[2])
&& !altivec_indexed_or_indirect_operand (operands[2], V16QImode))
{
rtx reg_op1 = gen_reg_rtx (V16QImode);
rtx reg_op2 = gen_reg_rtx (V16QImode);
rs6000_emit_le_vsx_permute (reg_op1, operands[1], V16QImode);
rs6000_emit_le_vsx_permute (reg_op2, operands[2], V16QImode);
operands[1] = reg_op1;
operands[2] = reg_op2;
}
else
{
operands[1] = force_reg (V16QImode, operands[1]);
operands[2] = force_reg (V16QImode, operands[2]);
}
rtx_code code = GET_CODE (operands[0]);
operands[0] = gen_rtx_fmt_ee (code, V16QImode, operands[1], operands[2]);
rs6000_emit_cbranch (V16QImode, operands);
DONE;
})
;; Compare vectors producing a vector result and a predicate, setting CR6 to
;; indicate a combined status
(define_insn "altivec_vcmpequ_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(eq:CC (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:VI2 0 "register_operand" "=v")
(eq:VI2 (match_dup 1)
(match_dup 2)))]
""
"vcmpequ. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "altivec_vcmpequt_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand" "v")
(match_operand:V1TI 2 "altivec_register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V1TI 0 "altivec_register_operand" "=v")
(eq:V1TI (match_dup 1)
(match_dup 2)))]
"TARGET_POWER10"
"vcmpequq. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
;; Expand for builtin vcmpne{b,h,w}
(define_expand "altivec_vcmpne_"
[(set (match_operand:VSX_EXTRACT_I 3 "altivec_register_operand" "=v")
(eq:VSX_EXTRACT_I (match_operand:VSX_EXTRACT_I 1 "altivec_register_operand" "v")
(match_operand:VSX_EXTRACT_I 2 "altivec_register_operand" "v")))
(set (match_operand:VSX_EXTRACT_I 0 "altivec_register_operand" "=v")
(not:VSX_EXTRACT_I (match_dup 3)))]
"TARGET_ALTIVEC"
{
operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
})
(define_insn "*altivec_vcmpgts_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gt:CC (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:VI2 0 "register_operand" "=v")
(gt:VI2 (match_dup 1)
(match_dup 2)))]
""
"vcmpgts. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_vcmpgtst_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gt:CC (match_operand:V1TI 1 "register_operand" "v")
(match_operand:V1TI 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V1TI 0 "register_operand" "=v")
(gt:V1TI (match_dup 1)
(match_dup 2)))]
"TARGET_POWER10"
"vcmpgtsq. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_vcmpgtu_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gtu:CC (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:VI2 0 "register_operand" "=v")
(gtu:VI2 (match_dup 1)
(match_dup 2)))]
""
"vcmpgtu. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_vcmpgtut_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gtu:CC (match_operand:V1TI 1 "register_operand" "v")
(match_operand:V1TI 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V1TI 0 "register_operand" "=v")
(gtu:V1TI (match_dup 1)
(match_dup 2)))]
"TARGET_POWER10"
"vcmpgtuq. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
(define_insn "*altivec_vcmpeqfp_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(eq:CC (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V4SF 0 "register_operand" "=v")
(eq:V4SF (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpeqfp. %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "*altivec_vcmpgtfp_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gt:CC (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V4SF 0 "register_operand" "=v")
(gt:V4SF (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpgtfp. %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "*altivec_vcmpgefp_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(ge:CC (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))]
UNSPEC_PREDICATE))
(set (match_operand:V4SF 0 "register_operand" "=v")
(ge:V4SF (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpgefp. %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_vcmpbfp_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")]
UNSPEC_VCMPBFP))
(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_dup 1)
(match_dup 2)]
UNSPEC_VCMPBFP))]
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
"vcmpbfp. %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_mtvscr"
[(set (reg:SI VSCR_REGNO)
(unspec_volatile:SI
[(match_operand:V4SI 0 "register_operand" "v")] UNSPECV_MTVSCR))]
"TARGET_ALTIVEC"
"mtvscr %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_mfvscr"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec_volatile:V8HI [(reg:SI VSCR_REGNO)] UNSPECV_MFVSCR))]
"TARGET_ALTIVEC"
"mfvscr %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dssall"
[(unspec_volatile [(const_int 0)] UNSPECV_DSSALL)]
"TARGET_ALTIVEC"
"dssall"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dss"
[(unspec_volatile [(match_operand:QI 0 "immediate_operand" "i")]
UNSPECV_DSS)]
"TARGET_ALTIVEC"
"dss %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dst"
[(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DST)]
"TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
"dst %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dstt"
[(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTT)]
"TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
"dstt %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dstst"
[(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTST)]
"TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
"dstst %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dststt"
[(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTSTT)]
"TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
"dststt %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_expand "altivec_lvsl"
[(use (match_operand:V16QI 0 "register_operand"))
(use (match_operand:V16QI 1 "memory_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_lvsl_direct (operands[0], operands[1]));
else
{
rtx mask, constv, vperm;
mask = gen_reg_rtx (V16QImode);
emit_insn (gen_altivec_lvsl_direct (mask, operands[1]));
constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
constv = force_reg (V16QImode, constv);
vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
UNSPEC_VPERM);
emit_insn (gen_rtx_SET (operands[0], vperm));
}
DONE;
})
(define_insn "altivec_lvsl_reg_"
[(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
(unspec:V16QI
[(match_operand:GPR 1 "gpc_reg_operand" "b")]
UNSPEC_LVSL_REG))]
"TARGET_ALTIVEC"
"lvsl %0,0,%1"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvsl_direct"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
UNSPEC_LVSL))]
"TARGET_ALTIVEC"
"lvsl %0,%y1"
[(set_attr "type" "vecload")])
(define_expand "altivec_lvsr"
[(use (match_operand:V16QI 0 "altivec_register_operand"))
(use (match_operand:V16QI 1 "memory_operand"))]
"TARGET_ALTIVEC"
{
if (BYTES_BIG_ENDIAN)
emit_insn (gen_altivec_lvsr_direct (operands[0], operands[1]));
else
{
rtx mask, constv, vperm;
mask = gen_reg_rtx (V16QImode);
emit_insn (gen_altivec_lvsr_direct (mask, operands[1]));
constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
constv = force_reg (V16QImode, constv);
vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
UNSPEC_VPERM);
emit_insn (gen_rtx_SET (operands[0], vperm));
}
DONE;
})
(define_insn "altivec_lvsr_reg_"
[(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
(unspec:V16QI
[(match_operand:GPR 1 "gpc_reg_operand" "b")]
UNSPEC_LVSR_REG))]
"TARGET_ALTIVEC"
"lvsr %0,0,%1"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvsr_direct"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
UNSPEC_LVSR))]
"TARGET_ALTIVEC"
"lvsr %0,%y1"
[(set_attr "type" "vecload")])
(define_expand "build_vector_mask_for_load"
[(set (match_operand:V16QI 0 "register_operand")
(unspec:V16QI [(match_operand 1 "memory_operand")] UNSPEC_LVSR))]
"TARGET_ALTIVEC"
{
rtx addr;
rtx temp;
gcc_assert (MEM_P (operands[1]));
addr = XEXP (operands[1], 0);
temp = gen_reg_rtx (GET_MODE (addr));
emit_insn (gen_rtx_SET (temp, gen_rtx_NEG (GET_MODE (addr), addr)));
emit_insn (gen_altivec_lvsr (operands[0],
replace_equiv_address (operands[1], temp)));
DONE;
})
;; Parallel some of the LVE* and STV*'s with unspecs because some have
;; identical rtl but different instructions-- and gcc gets confused.
(define_insn "altivec_lvex"
[(parallel
[(set (match_operand:VI 0 "register_operand" "=v")
(match_operand:VI 1 "memory_operand" "Z"))
(unspec [(const_int 0)] UNSPEC_LVE)])]
"TARGET_ALTIVEC"
"lvex %0,%y1"
[(set_attr "type" "vecload")])
(define_insn "*altivec_lvesfx"
[(parallel
[(set (match_operand:V4SF 0 "register_operand" "=v")
(match_operand:V4SF 1 "memory_operand" "Z"))
(unspec [(const_int 0)] UNSPEC_LVE)])]
"TARGET_ALTIVEC"
"lvewx %0,%y1"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvxl_"
[(parallel
[(set (match_operand:VM2 0 "register_operand" "=v")
(match_operand:VM2 1 "memory_operand" "Z"))
(unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
"TARGET_ALTIVEC"
"lvxl %0,%y1"
[(set_attr "type" "vecload")])
; This version of lvx is used only in cases where we need to force an lvx
; over any other load, and we don't care about losing CSE opportunities.
; Its primary use is for prologue register saves.
(define_insn "altivec_lvx__internal"
[(parallel
[(set (match_operand:VM2 0 "register_operand" "=v")
(match_operand:VM2 1 "memory_operand" "Z"))
(unspec [(const_int 0)] UNSPEC_LVX)])]
"TARGET_ALTIVEC"
"lvx %0,%y1"
[(set_attr "type" "vecload")])
; The following patterns embody what lvx should usually look like.
(define_expand "altivec_lvx_"
[(set (match_operand:VM2 0 "register_operand")
(match_operand:VM2 1 "altivec_indexed_or_indirect_operand"))]
"TARGET_ALTIVEC"
{
rtx addr = XEXP (operand1, 0);
if (rs6000_sum_of_two_registers_p (addr))
{
rtx op1 = XEXP (addr, 0);
rtx op2 = XEXP (addr, 1);
if (TARGET_64BIT)
emit_insn (gen_altivec_lvx__2op_di (operand0, op1, op2));
else
emit_insn (gen_altivec_lvx__2op_si (operand0, op1, op2));
}
else
{
if (TARGET_64BIT)
emit_insn (gen_altivec_lvx__1op_di (operand0, addr));
else
emit_insn (gen_altivec_lvx__1op_si (operand0, addr));
}
DONE;
})
; The next two patterns embody what lvx should usually look like.
(define_insn "altivec_lvx__2op_"
[(set (match_operand:VM2 0 "register_operand" "=v")
(mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
(match_operand:P 2 "register_operand" "r"))
(const_int -16))))]
"TARGET_ALTIVEC"
"lvx %0,%1,%2"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvx__1op_"
[(set (match_operand:VM2 0 "register_operand" "=v")
(mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
(const_int -16))))]
"TARGET_ALTIVEC"
"lvx %0,0,%1"
[(set_attr "type" "vecload")])
; This version of stvx is used only in cases where we need to force an stvx
; over any other store, and we don't care about losing CSE opportunities.
; Its primary use is for epilogue register restores.
(define_insn "altivec_stvx__internal"
[(parallel
[(set (match_operand:VM2 0 "memory_operand" "=Z")
(match_operand:VM2 1 "register_operand" "v"))
(unspec [(const_int 0)] UNSPEC_STVX)])]
"TARGET_ALTIVEC"
"stvx %1,%y0"
[(set_attr "type" "vecstore")])
; The following patterns embody what stvx should usually look like.
(define_expand "altivec_stvx_"
[(set (match_operand:VM2 1 "altivec_indexed_or_indirect_operand")
(match_operand:VM2 0 "register_operand"))]
"TARGET_ALTIVEC"
{
rtx addr = XEXP (operand1, 0);
if (rs6000_sum_of_two_registers_p (addr))
{
rtx op1 = XEXP (addr, 0);
rtx op2 = XEXP (addr, 1);
if (TARGET_64BIT)
emit_insn (gen_altivec_stvx__2op_di (operand0, op1, op2));
else
emit_insn (gen_altivec_stvx__2op_si (operand0, op1, op2));
}
else
{
if (TARGET_64BIT)
emit_insn (gen_altivec_stvx__1op_di (operand0, addr));
else
emit_insn (gen_altivec_stvx__1op_si (operand0, addr));
}
DONE;
})
; The next two patterns embody what stvx should usually look like.
(define_insn "altivec_stvx__2op_"
[(set (mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
(match_operand:P 2 "register_operand" "r"))
(const_int -16)))
(match_operand:VM2 0 "register_operand" "v"))]
"TARGET_ALTIVEC"
"stvx %0,%1,%2"
[(set_attr "type" "vecstore")])
(define_insn "altivec_stvx__1op_"
[(set (mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
(const_int -16)))
(match_operand:VM2 0 "register_operand" "v"))]
"TARGET_ALTIVEC"
"stvx %0,0,%1"
[(set_attr "type" "vecstore")])
(define_insn "altivec_stvxl_"
[(parallel
[(set (match_operand:VM2 0 "memory_operand" "=Z")
(match_operand:VM2 1 "register_operand" "v"))
(unspec [(const_int 0)] UNSPEC_STVXL)])]
"TARGET_ALTIVEC"
"stvxl %1,%y0"
[(set_attr "type" "vecstore")])
(define_insn "altivec_stvex"
[(set (match_operand: 0 "memory_operand" "=Z")
(unspec: [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
"TARGET_ALTIVEC"
"stve