1;; AltiVec patterns.
2;; Copyright (C) 2002-2019 Free Software Foundation, Inc.
3;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify it
8;; under the terms of the GNU General Public License as published
9;; by the Free Software Foundation; either version 3, or (at your
10;; option) any later version.
11
12;; GCC is distributed in the hope that it will be useful, but WITHOUT
13;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15;; License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21(define_c_enum "unspec"
22  [UNSPEC_VCMPBFP
23   UNSPEC_VMSUMU
24   UNSPEC_VMSUMUDM
25   UNSPEC_VMSUMM
26   UNSPEC_VMSUMSHM
27   UNSPEC_VMSUMUHS
28   UNSPEC_VMSUMSHS
29   UNSPEC_VMHADDSHS
30   UNSPEC_VMHRADDSHS
31   UNSPEC_VADDCUW
32   UNSPEC_VADDU
33   UNSPEC_VADDS
34   UNSPEC_VAVGU
35   UNSPEC_VAVGS
36   UNSPEC_VMULEUB
37   UNSPEC_VMULESB
38   UNSPEC_VMULEUH
39   UNSPEC_VMULESH
40   UNSPEC_VMULEUW
41   UNSPEC_VMULESW
42   UNSPEC_VMULOUB
43   UNSPEC_VMULOSB
44   UNSPEC_VMULOUH
45   UNSPEC_VMULOSH
46   UNSPEC_VMULOUW
47   UNSPEC_VMULOSW
48   UNSPEC_VPKPX
49   UNSPEC_VPACK_SIGN_SIGN_SAT
50   UNSPEC_VPACK_SIGN_UNS_SAT
51   UNSPEC_VPACK_UNS_UNS_SAT
52   UNSPEC_VPACK_UNS_UNS_MOD
53   UNSPEC_VPACK_UNS_UNS_MOD_DIRECT
54   UNSPEC_VREVEV
55   UNSPEC_VSLV4SI
56   UNSPEC_VSLO
57   UNSPEC_VSR
58   UNSPEC_VSRO
59   UNSPEC_VSUBCUW
60   UNSPEC_VSUBU
61   UNSPEC_VSUBS
62   UNSPEC_VSUM4UBS
63   UNSPEC_VSUM4S
64   UNSPEC_VSUM2SWS
65   UNSPEC_VSUMSWS
66   UNSPEC_VPERM
67   UNSPEC_VPERMR
68   UNSPEC_VPERM_UNS
69   UNSPEC_VRFIN
70   UNSPEC_VCFUX
71   UNSPEC_VCFSX
72   UNSPEC_VCTUXS
73   UNSPEC_VCTSXS
74   UNSPEC_VLOGEFP
75   UNSPEC_VEXPTEFP
76   UNSPEC_VSLDOI
77   UNSPEC_VUNPACK_HI_SIGN
78   UNSPEC_VUNPACK_LO_SIGN
79   UNSPEC_VUNPACK_HI_SIGN_DIRECT
80   UNSPEC_VUNPACK_LO_SIGN_DIRECT
81   UNSPEC_VUPKHPX
82   UNSPEC_VUPKLPX
83   UNSPEC_CONVERT_4F32_8I16
84   UNSPEC_CONVERT_4F32_8F16
85   UNSPEC_DST
86   UNSPEC_DSTT
87   UNSPEC_DSTST
88   UNSPEC_DSTSTT
89   UNSPEC_LVSL
90   UNSPEC_LVSR
91   UNSPEC_LVE
92   UNSPEC_STVX
93   UNSPEC_STVXL
94   UNSPEC_STVE
95   UNSPEC_SET_VSCR
96   UNSPEC_GET_VRSAVE
97   UNSPEC_LVX
98   UNSPEC_REDUC_PLUS
99   UNSPEC_VECSH
100   UNSPEC_EXTEVEN_V4SI
101   UNSPEC_EXTEVEN_V8HI
102   UNSPEC_EXTEVEN_V16QI
103   UNSPEC_EXTEVEN_V4SF
104   UNSPEC_EXTODD_V4SI
105   UNSPEC_EXTODD_V8HI
106   UNSPEC_EXTODD_V16QI
107   UNSPEC_EXTODD_V4SF
108   UNSPEC_INTERHI_V4SI
109   UNSPEC_INTERHI_V8HI
110   UNSPEC_INTERHI_V16QI
111   UNSPEC_INTERLO_V4SI
112   UNSPEC_INTERLO_V8HI
113   UNSPEC_INTERLO_V16QI
114   UNSPEC_LVLX
115   UNSPEC_LVLXL
116   UNSPEC_LVRX
117   UNSPEC_LVRXL
118   UNSPEC_STVLX
119   UNSPEC_STVLXL
120   UNSPEC_STVRX
121   UNSPEC_STVRXL
122   UNSPEC_VADU
123   UNSPEC_VSLV
124   UNSPEC_VSRV
125   UNSPEC_VMULWHUB
126   UNSPEC_VMULWLUB
127   UNSPEC_VMULWHSB
128   UNSPEC_VMULWLSB
129   UNSPEC_VMULWHUH
130   UNSPEC_VMULWLUH
131   UNSPEC_VMULWHSH
132   UNSPEC_VMULWLSH
133   UNSPEC_VUPKHUB
134   UNSPEC_VUPKHUH
135   UNSPEC_VUPKLUB
136   UNSPEC_VUPKLUH
137   UNSPEC_VPERMSI
138   UNSPEC_VPERMHI
139   UNSPEC_INTERHI
140   UNSPEC_INTERLO
141   UNSPEC_VUPKHS_V4SF
142   UNSPEC_VUPKLS_V4SF
143   UNSPEC_VUPKHU_V4SF
144   UNSPEC_VUPKLU_V4SF
145   UNSPEC_VGBBD
146   UNSPEC_VMRGH_DIRECT
147   UNSPEC_VMRGL_DIRECT
148   UNSPEC_VSPLT_DIRECT
149   UNSPEC_VMRGEW_DIRECT
150   UNSPEC_VMRGOW_DIRECT
151   UNSPEC_VSUMSWS_DIRECT
152   UNSPEC_VADDCUQ
153   UNSPEC_VADDEUQM
154   UNSPEC_VADDECUQ
155   UNSPEC_VSUBCUQ
156   UNSPEC_VSUBEUQM
157   UNSPEC_VSUBECUQ
158   UNSPEC_VBPERMQ
159   UNSPEC_VBPERMD
160   UNSPEC_BCDADD
161   UNSPEC_BCDSUB
162   UNSPEC_BCD_OVERFLOW
163   UNSPEC_VRLMI
164   UNSPEC_VRLNM
165])
166
167(define_c_enum "unspecv"
168  [UNSPECV_SET_VRSAVE
169   UNSPECV_MTVSCR
170   UNSPECV_MFVSCR
171   UNSPECV_DSSALL
172   UNSPECV_DSS
173  ])
174
175;; Like VI, defined in vector.md, but add ISA 2.07 integer vector ops
176(define_mode_iterator VI2 [V4SI V8HI V16QI V2DI])
177;; Short vec int modes
178(define_mode_iterator VIshort [V8HI V16QI])
179;; Longer vec int modes for rotate/mask ops
180(define_mode_iterator VIlong [V2DI V4SI])
181;; Vec float modes
182(define_mode_iterator VF [V4SF])
183;; Vec modes, pity mode iterators are not composable
184(define_mode_iterator V [V4SI V8HI V16QI V4SF])
185;; Vec modes for move/logical/permute ops, include vector types for move not
186;; otherwise handled by altivec (v2df, v2di, ti)
187(define_mode_iterator VM [V4SI
188			  V8HI
189			  V16QI
190			  V4SF
191			  V2DF
192			  V2DI
193			  V1TI
194			  TI
195			  (KF "FLOAT128_VECTOR_P (KFmode)")
196			  (TF "FLOAT128_VECTOR_P (TFmode)")])
197
198;; Like VM, except don't do TImode
199(define_mode_iterator VM2 [V4SI
200			   V8HI
201			   V16QI
202			   V4SF
203			   V2DF
204			   V2DI
205			   V1TI
206			   (KF "FLOAT128_VECTOR_P (KFmode)")
207			   (TF "FLOAT128_VECTOR_P (TFmode)")])
208
209;; Map the Vector convert single precision to double precision for integer
210;; versus floating point
211(define_mode_attr VS_sxwsp [(V4SI "sxw") (V4SF "sp")])
212
213;; Specific iterator for parity which does not have a byte/half-word form, but
214;; does have a quad word form
215(define_mode_iterator VParity [V4SI
216			       V2DI
217			       V1TI
218			       TI])
219
220(define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
221(define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
222(define_mode_attr VI_unit [(V16QI "VECTOR_UNIT_ALTIVEC_P (V16QImode)")
223			   (V8HI "VECTOR_UNIT_ALTIVEC_P (V8HImode)")
224			   (V4SI "VECTOR_UNIT_ALTIVEC_P (V4SImode)")
225			   (V2DI "VECTOR_UNIT_P8_VECTOR_P (V2DImode)")
226			   (V1TI "VECTOR_UNIT_ALTIVEC_P (V1TImode)")])
227
228;; Vector pack/unpack
229(define_mode_iterator VP [V2DI V4SI V8HI])
230(define_mode_attr VP_small [(V2DI "V4SI") (V4SI "V8HI") (V8HI "V16QI")])
231(define_mode_attr VP_small_lc [(V2DI "v4si") (V4SI "v8hi") (V8HI "v16qi")])
232(define_mode_attr VU_char [(V2DI "w") (V4SI "h") (V8HI "b")])
233
234;; Vector negate
235(define_mode_iterator VNEG [V4SI V2DI])
236
237;; Vector move instructions.
238(define_insn "*altivec_mov<mode>"
239  [(set (match_operand:VM2 0 "nonimmediate_operand" "=Z,v,v,?Y,?*r,?*r,v,v,?*r")
240	(match_operand:VM2 1 "input_operand" "v,Z,v,*r,Y,*r,j,W,W"))]
241  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
242   && (register_operand (operands[0], <MODE>mode)
243       || register_operand (operands[1], <MODE>mode))"
244  "@
245   stvx %1,%y0
246   lvx %0,%y1
247   vor %0,%1,%1
248   #
249   #
250   #
251   vxor %0,%0,%0
252   * return output_vec_const_move (operands);
253   #"
254  [(set_attr "type" "vecstore,vecload,veclogical,store,load,*,veclogical,*,*")
255   (set_attr "length" "4,4,4,20,20,20,4,8,32")])
256
257;; Unlike other altivec moves, allow the GPRs, since a normal use of TImode
258;; is for unions.  However for plain data movement, slightly favor the vector
259;; loads
260(define_insn "*altivec_movti"
261  [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,v,v,?Y,?r,?r,v,v")
262	(match_operand:TI 1 "input_operand" "v,Z,v,r,Y,r,j,W"))]
263  "VECTOR_MEM_ALTIVEC_P (TImode)
264   && (register_operand (operands[0], TImode)
265       || register_operand (operands[1], TImode))"
266  "@
267   stvx %1,%y0
268   lvx %0,%y1
269   vor %0,%1,%1
270   #
271   #
272   #
273   vxor %0,%0,%0
274   * return output_vec_const_move (operands);"
275  [(set_attr "type" "vecstore,vecload,veclogical,store,load,*,veclogical,*")])
276
277;; Load up a vector with the most significant bit set by loading up -1 and
278;; doing a shift left
279(define_split
280  [(set (match_operand:VM 0 "altivec_register_operand")
281	(match_operand:VM 1 "easy_vector_constant_msb"))]
282  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && reload_completed"
283  [(const_int 0)]
284{
285  rtx dest = operands[0];
286  machine_mode mode = GET_MODE (operands[0]);
287  rtvec v;
288  int i, num_elements;
289
290  if (mode == V4SFmode)
291    {
292      mode = V4SImode;
293      dest = gen_lowpart (V4SImode, dest);
294    }
295
296  num_elements = GET_MODE_NUNITS (mode);
297  v = rtvec_alloc (num_elements);
298  for (i = 0; i < num_elements; i++)
299    RTVEC_ELT (v, i) = constm1_rtx;
300
301  emit_insn (gen_vec_initv4sisi (dest, gen_rtx_PARALLEL (mode, v)));
302  emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, dest, dest)));
303  DONE;
304})
305
306(define_split
307  [(set (match_operand:VM 0 "altivec_register_operand")
308	(match_operand:VM 1 "easy_vector_constant_add_self"))]
309  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && reload_completed"
310  [(set (match_dup 0) (match_dup 3))
311   (set (match_dup 0) (match_dup 4))]
312{
313  rtx dup = gen_easy_altivec_constant (operands[1]);
314  rtx const_vec;
315  machine_mode op_mode = <MODE>mode;
316
317  /* Divide the operand of the resulting VEC_DUPLICATE, and use
318     simplify_rtx to make a CONST_VECTOR.  */
319  XEXP (dup, 0) = simplify_const_binary_operation (ASHIFTRT, QImode,
320						   XEXP (dup, 0), const1_rtx);
321  const_vec = simplify_rtx (dup);
322
323  if (op_mode == V4SFmode)
324    {
325      op_mode = V4SImode;
326      operands[0] = gen_lowpart (op_mode, operands[0]);
327    }
328  if (GET_MODE (const_vec) == op_mode)
329    operands[3] = const_vec;
330  else
331    operands[3] = gen_lowpart (op_mode, const_vec);
332  operands[4] = gen_rtx_PLUS (op_mode, operands[0], operands[0]);
333})
334
335(define_split
336  [(set (match_operand:VM 0 "altivec_register_operand")
337	(match_operand:VM 1 "easy_vector_constant_vsldoi"))]
338  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()"
339  [(set (match_dup 2) (match_dup 3))
340   (set (match_dup 4) (match_dup 5))
341   (set (match_dup 0)
342        (unspec:VM [(match_dup 2)
343		    (match_dup 4)
344		    (match_dup 6)]
345		   UNSPEC_VSLDOI))]
346{
347  rtx op1 = operands[1];
348  int elt = (BYTES_BIG_ENDIAN) ? 0 : GET_MODE_NUNITS (<MODE>mode) - 1;
349  HOST_WIDE_INT val = const_vector_elt_as_int (op1, elt);
350  rtx rtx_val = GEN_INT (val);
351  int shift = vspltis_shifted (op1);
352
353  gcc_assert (shift != 0);
354  operands[2] = gen_reg_rtx (<MODE>mode);
355  operands[3] = gen_const_vec_duplicate (<MODE>mode, rtx_val);
356  operands[4] = gen_reg_rtx (<MODE>mode);
357
358  if (shift < 0)
359    {
360      operands[5] = CONSTM1_RTX (<MODE>mode);
361      operands[6] = GEN_INT (-shift);
362    }
363  else
364    {
365      operands[5] = CONST0_RTX (<MODE>mode);
366      operands[6] = GEN_INT (shift);
367    }
368})
369
370(define_insn "get_vrsave_internal"
371  [(set (match_operand:SI 0 "register_operand" "=r")
372	(unspec:SI [(reg:SI VRSAVE_REGNO)] UNSPEC_GET_VRSAVE))]
373  "TARGET_ALTIVEC"
374{
375  if (TARGET_MACHO)
376     return "mfspr %0,256";
377  else
378     return "mfvrsave %0";
379}
380  [(set_attr "type" "*")])
381
382(define_insn "*set_vrsave_internal"
383  [(match_parallel 0 "vrsave_operation"
384     [(set (reg:SI VRSAVE_REGNO)
385	   (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
386				(reg:SI VRSAVE_REGNO)] UNSPECV_SET_VRSAVE))])]
387  "TARGET_ALTIVEC"
388{
389  if (TARGET_MACHO)
390    return "mtspr 256,%1";
391  else
392    return "mtvrsave %1";
393}
394  [(set_attr "type" "*")])
395
396(define_insn "*save_world"
397 [(match_parallel 0 "save_world_operation"
398                  [(clobber (reg:SI LR_REGNO))
399                   (use (match_operand:SI 1 "call_operand" "s"))])]
400 "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
401 "bl %z1"
402  [(set_attr "type" "branch")])
403
404(define_insn "*restore_world"
405 [(match_parallel 0 "restore_world_operation"
406                  [(return)
407                   (use (match_operand:SI 1 "call_operand" "s"))
408                   (clobber (match_operand:SI 2 "gpc_reg_operand" "=r"))])]
409 "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
410 "b %z1")
411
412;; The save_vregs and restore_vregs patterns don't use memory_operand
413;; because (plus (reg) (const_int)) is not a valid vector address.
414;; This way is more compact than describing exactly what happens in
415;; the out-of-line functions, ie. loading the constant into r11/r12
416;; then using indexed addressing, and requires less editing of rtl
417;; to describe the operation to dwarf2out_frame_debug_expr.
418(define_insn "*save_vregs_<mode>_r11"
419  [(match_parallel 0 "any_parallel_operand"
420     [(clobber (reg:P LR_REGNO))
421      (use (match_operand:P 1 "symbol_ref_operand" "s"))
422      (clobber (reg:P 11))
423      (use (reg:P 0))
424      (set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
425			     (match_operand:P 3 "short_cint_operand" "I")))
426	   (match_operand:V4SI 4 "altivec_register_operand" "v"))])]
427  "TARGET_ALTIVEC"
428  "bl %1"
429  [(set_attr "type" "branch")])
430
431(define_insn "*save_vregs_<mode>_r12"
432  [(match_parallel 0 "any_parallel_operand"
433     [(clobber (reg:P LR_REGNO))
434      (use (match_operand:P 1 "symbol_ref_operand" "s"))
435      (clobber (reg:P 12))
436      (use (reg:P 0))
437      (set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
438			     (match_operand:P 3 "short_cint_operand" "I")))
439	   (match_operand:V4SI 4 "altivec_register_operand" "v"))])]
440  "TARGET_ALTIVEC"
441  "bl %1"
442  [(set_attr "type" "branch")])
443
444(define_insn "*restore_vregs_<mode>_r11"
445  [(match_parallel 0 "any_parallel_operand"
446     [(clobber (reg:P LR_REGNO))
447      (use (match_operand:P 1 "symbol_ref_operand" "s"))
448      (clobber (reg:P 11))
449      (use (reg:P 0))
450      (set (match_operand:V4SI 2 "altivec_register_operand" "=v")
451	   (mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
452			     (match_operand:P 4 "short_cint_operand" "I"))))])]
453  "TARGET_ALTIVEC"
454  "bl %1"
455  [(set_attr "type" "branch")])
456
457(define_insn "*restore_vregs_<mode>_r12"
458  [(match_parallel 0 "any_parallel_operand"
459     [(clobber (reg:P LR_REGNO))
460      (use (match_operand:P 1 "symbol_ref_operand" "s"))
461      (clobber (reg:P 12))
462      (use (reg:P 0))
463      (set (match_operand:V4SI 2 "altivec_register_operand" "=v")
464	   (mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
465			     (match_operand:P 4 "short_cint_operand" "I"))))])]
466  "TARGET_ALTIVEC"
467  "bl %1"
468  [(set_attr "type" "branch")])
469
470;; Simple binary operations.
471
472;; add
473(define_insn "add<mode>3"
474  [(set (match_operand:VI2 0 "register_operand" "=v")
475        (plus:VI2 (match_operand:VI2 1 "register_operand" "v")
476		  (match_operand:VI2 2 "register_operand" "v")))]
477  "<VI_unit>"
478  "vaddu<VI_char>m %0,%1,%2"
479  [(set_attr "type" "vecsimple")])
480
481(define_insn "*altivec_addv4sf3"
482  [(set (match_operand:V4SF 0 "register_operand" "=v")
483        (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
484		   (match_operand:V4SF 2 "register_operand" "v")))]
485  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
486  "vaddfp %0,%1,%2"
487  [(set_attr "type" "vecfloat")])
488
489(define_insn "altivec_vaddcuw"
490  [(set (match_operand:V4SI 0 "register_operand" "=v")
491        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
492                      (match_operand:V4SI 2 "register_operand" "v")]
493		     UNSPEC_VADDCUW))]
494  "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
495  "vaddcuw %0,%1,%2"
496  [(set_attr "type" "vecsimple")])
497
498(define_insn "altivec_vaddu<VI_char>s"
499  [(set (match_operand:VI 0 "register_operand" "=v")
500        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
501		    (match_operand:VI 2 "register_operand" "v")]
502		   UNSPEC_VADDU))
503   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
504  "<VI_unit>"
505  "vaddu<VI_char>s %0,%1,%2"
506  [(set_attr "type" "vecsimple")])
507
508(define_insn "altivec_vadds<VI_char>s"
509  [(set (match_operand:VI 0 "register_operand" "=v")
510        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
511                    (match_operand:VI 2 "register_operand" "v")]
512		   UNSPEC_VADDS))
513   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
514  "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
515  "vadds<VI_char>s %0,%1,%2"
516  [(set_attr "type" "vecsimple")])
517
518;; sub
519(define_insn "sub<mode>3"
520  [(set (match_operand:VI2 0 "register_operand" "=v")
521        (minus:VI2 (match_operand:VI2 1 "register_operand" "v")
522		   (match_operand:VI2 2 "register_operand" "v")))]
523  "<VI_unit>"
524  "vsubu<VI_char>m %0,%1,%2"
525  [(set_attr "type" "vecsimple")])
526
527(define_insn "*altivec_subv4sf3"
528  [(set (match_operand:V4SF 0 "register_operand" "=v")
529        (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
530                    (match_operand:V4SF 2 "register_operand" "v")))]
531  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
532  "vsubfp %0,%1,%2"
533  [(set_attr "type" "vecfloat")])
534
535(define_insn "altivec_vsubcuw"
536  [(set (match_operand:V4SI 0 "register_operand" "=v")
537        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
538                      (match_operand:V4SI 2 "register_operand" "v")]
539		     UNSPEC_VSUBCUW))]
540  "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
541  "vsubcuw %0,%1,%2"
542  [(set_attr "type" "vecsimple")])
543
544(define_insn "altivec_vsubu<VI_char>s"
545  [(set (match_operand:VI 0 "register_operand" "=v")
546        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
547                    (match_operand:VI 2 "register_operand" "v")]
548		   UNSPEC_VSUBU))
549   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
550  "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
551  "vsubu<VI_char>s %0,%1,%2"
552  [(set_attr "type" "vecsimple")])
553
554(define_insn "altivec_vsubs<VI_char>s"
555  [(set (match_operand:VI 0 "register_operand" "=v")
556        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
557                    (match_operand:VI 2 "register_operand" "v")]
558		   UNSPEC_VSUBS))
559   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
560  "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
561  "vsubs<VI_char>s %0,%1,%2"
562  [(set_attr "type" "vecsimple")])
563
564;;
565(define_insn "uavg<mode>3_ceil"
566  [(set (match_operand:VI 0 "register_operand" "=v")
567        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
568                    (match_operand:VI 2 "register_operand" "v")]
569		   UNSPEC_VAVGU))]
570  "TARGET_ALTIVEC"
571  "vavgu<VI_char> %0,%1,%2"
572  [(set_attr "type" "vecsimple")])
573
574(define_insn "avg<mode>3_ceil"
575  [(set (match_operand:VI 0 "register_operand" "=v")
576        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
577                    (match_operand:VI 2 "register_operand" "v")]
578		   UNSPEC_VAVGS))]
579  "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
580  "vavgs<VI_char> %0,%1,%2"
581  [(set_attr "type" "vecsimple")])
582
583(define_insn "altivec_vcmpbfp"
584  [(set (match_operand:V4SI 0 "register_operand" "=v")
585        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
586                      (match_operand:V4SF 2 "register_operand" "v")]
587                      UNSPEC_VCMPBFP))]
588  "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
589  "vcmpbfp %0,%1,%2"
590  [(set_attr "type" "veccmp")])
591
592(define_insn "altivec_eq<mode>"
593  [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
594	(eq:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
595		(match_operand:VI2 2 "altivec_register_operand" "v")))]
596  "<VI_unit>"
597  "vcmpequ<VI_char> %0,%1,%2"
598  [(set_attr "type" "veccmpfx")])
599
600(define_insn "*altivec_gt<mode>"
601  [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
602	(gt:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
603		(match_operand:VI2 2 "altivec_register_operand" "v")))]
604  "<VI_unit>"
605  "vcmpgts<VI_char> %0,%1,%2"
606  [(set_attr "type" "veccmpfx")])
607
608(define_insn "*altivec_gtu<mode>"
609  [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
610	(gtu:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
611		 (match_operand:VI2 2 "altivec_register_operand" "v")))]
612  "<VI_unit>"
613  "vcmpgtu<VI_char> %0,%1,%2"
614  [(set_attr "type" "veccmpfx")])
615
616(define_insn "*altivec_eqv4sf"
617  [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
618	(eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
619		 (match_operand:V4SF 2 "altivec_register_operand" "v")))]
620  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
621  "vcmpeqfp %0,%1,%2"
622  [(set_attr "type" "veccmp")])
623
624(define_insn "*altivec_gtv4sf"
625  [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
626	(gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
627		 (match_operand:V4SF 2 "altivec_register_operand" "v")))]
628  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
629  "vcmpgtfp %0,%1,%2"
630  [(set_attr "type" "veccmp")])
631
632(define_insn "*altivec_gev4sf"
633  [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
634	(ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
635		 (match_operand:V4SF 2 "altivec_register_operand" "v")))]
636  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
637  "vcmpgefp %0,%1,%2"
638  [(set_attr "type" "veccmp")])
639
640(define_insn "*altivec_vsel<mode>"
641  [(set (match_operand:VM 0 "altivec_register_operand" "=v")
642	(if_then_else:VM
643	 (ne:CC (match_operand:VM 1 "altivec_register_operand" "v")
644		(match_operand:VM 4 "zero_constant" ""))
645	 (match_operand:VM 2 "altivec_register_operand" "v")
646	 (match_operand:VM 3 "altivec_register_operand" "v")))]
647  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
648  "vsel %0,%3,%2,%1"
649  [(set_attr "type" "vecmove")])
650
651(define_insn "*altivec_vsel<mode>_uns"
652  [(set (match_operand:VM 0 "altivec_register_operand" "=v")
653	(if_then_else:VM
654	 (ne:CCUNS (match_operand:VM 1 "altivec_register_operand" "v")
655		   (match_operand:VM 4 "zero_constant" ""))
656	 (match_operand:VM 2 "altivec_register_operand" "v")
657	 (match_operand:VM 3 "altivec_register_operand" "v")))]
658  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
659  "vsel %0,%3,%2,%1"
660  [(set_attr "type" "vecmove")])
661
662;; Fused multiply add.
663
664(define_insn "*altivec_fmav4sf4"
665  [(set (match_operand:V4SF 0 "register_operand" "=v")
666	(fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
667		  (match_operand:V4SF 2 "register_operand" "v")
668		  (match_operand:V4SF 3 "register_operand" "v")))]
669  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
670  "vmaddfp %0,%1,%2,%3"
671  [(set_attr "type" "vecfloat")])
672
673;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
674
675(define_expand "altivec_mulv4sf3"
676  [(set (match_operand:V4SF 0 "register_operand")
677	(fma:V4SF (match_operand:V4SF 1 "register_operand")
678		  (match_operand:V4SF 2 "register_operand")
679		  (match_dup 3)))]
680  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
681{
682  rtx neg0;
683
684  /* Generate [-0.0, -0.0, -0.0, -0.0].  */
685  neg0 = gen_reg_rtx (V4SImode);
686  emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
687  emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
688
689  operands[3] = gen_lowpart (V4SFmode, neg0);
690})
691
692;; 32-bit integer multiplication
693;; A_high = Operand_0 & 0xFFFF0000 >> 16
694;; A_low = Operand_0 & 0xFFFF
695;; B_high = Operand_1 & 0xFFFF0000 >> 16
696;; B_low = Operand_1 & 0xFFFF
697;; result = A_low * B_low + (A_high * B_low + B_high * A_low) << 16
698
699;; (define_insn "mulv4si3"
700;;   [(set (match_operand:V4SI 0 "register_operand" "=v")
701;;         (mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
702;;                    (match_operand:V4SI 2 "register_operand" "v")))]
703(define_insn "mulv4si3_p8"
704  [(set (match_operand:V4SI 0 "register_operand" "=v")
705        (mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
706                   (match_operand:V4SI 2 "register_operand" "v")))]
707  "TARGET_P8_VECTOR"
708  "vmuluwm %0,%1,%2"
709  [(set_attr "type" "veccomplex")])
710
711(define_expand "mulv4si3"
712  [(use (match_operand:V4SI 0 "register_operand"))
713   (use (match_operand:V4SI 1 "register_operand"))
714   (use (match_operand:V4SI 2 "register_operand"))]
715   "TARGET_ALTIVEC"
716{
717  rtx zero;
718  rtx swap;
719  rtx small_swap;
720  rtx sixteen;
721  rtx one;
722  rtx two;
723  rtx low_product;
724  rtx high_product;
725
726  if (TARGET_P8_VECTOR)
727    {
728      emit_insn (gen_mulv4si3_p8 (operands[0], operands[1], operands[2]));
729      DONE;
730    }
731
732  zero = gen_reg_rtx (V4SImode);
733  emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
734
735  sixteen = gen_reg_rtx (V4SImode);
736  emit_insn (gen_altivec_vspltisw (sixteen,  gen_rtx_CONST_INT (V4SImode, -16)));
737
738  swap = gen_reg_rtx (V4SImode);
739  emit_insn (gen_vrotlv4si3 (swap, operands[2], sixteen));
740
741  one = gen_reg_rtx (V8HImode);
742  convert_move (one, operands[1], 0);
743
744  two = gen_reg_rtx (V8HImode);
745  convert_move (two, operands[2], 0);
746
747  small_swap = gen_reg_rtx (V8HImode);
748  convert_move (small_swap, swap, 0);
749
750  low_product = gen_reg_rtx (V4SImode);
751  emit_insn (gen_altivec_vmulouh (low_product, one, two));
752
753  high_product = gen_reg_rtx (V4SImode);
754  emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
755
756  emit_insn (gen_vashlv4si3 (high_product, high_product, sixteen));
757
758  emit_insn (gen_addv4si3 (operands[0], high_product, low_product));
759
760  DONE;
761})
762
763(define_expand "mulv8hi3"
764  [(use (match_operand:V8HI 0 "register_operand"))
765   (use (match_operand:V8HI 1 "register_operand"))
766   (use (match_operand:V8HI 2 "register_operand"))]
767   "TARGET_ALTIVEC"
768{
769  rtx zero = gen_reg_rtx (V8HImode);
770
771  emit_insn (gen_altivec_vspltish (zero, const0_rtx));
772  emit_insn (gen_fmav8hi4 (operands[0], operands[1], operands[2], zero));
773
774  DONE;
775})
776
777
778;; Fused multiply subtract
779(define_insn "*altivec_vnmsubfp"
780  [(set (match_operand:V4SF 0 "register_operand" "=v")
781	(neg:V4SF
782	 (fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
783		   (match_operand:V4SF 2 "register_operand" "v")
784		   (neg:V4SF
785		    (match_operand:V4SF 3 "register_operand" "v")))))]
786  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
787  "vnmsubfp %0,%1,%2,%3"
788  [(set_attr "type" "vecfloat")])
789
790(define_insn "altivec_vmsumu<VI_char>m"
791  [(set (match_operand:V4SI 0 "register_operand" "=v")
792        (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
793		      (match_operand:VIshort 2 "register_operand" "v")
794                      (match_operand:V4SI 3 "register_operand" "v")]
795		     UNSPEC_VMSUMU))]
796  "TARGET_ALTIVEC"
797  "vmsumu<VI_char>m %0,%1,%2,%3"
798  [(set_attr "type" "veccomplex")])
799
800(define_insn "altivec_vmsumudm"
801  [(set (match_operand:V1TI 0 "register_operand" "=v")
802	(unspec:V1TI [(match_operand:V2DI 1 "register_operand" "v")
803		      (match_operand:V2DI 2 "register_operand" "v")
804		      (match_operand:V1TI 3 "register_operand" "v")]
805		     UNSPEC_VMSUMUDM))]
806  "TARGET_P8_VECTOR"
807  "vmsumudm %0,%1,%2,%3"
808  [(set_attr "type" "veccomplex")])
809
810(define_insn "altivec_vmsumm<VI_char>m"
811  [(set (match_operand:V4SI 0 "register_operand" "=v")
812        (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
813		      (match_operand:VIshort 2 "register_operand" "v")
814                      (match_operand:V4SI 3 "register_operand" "v")]
815		     UNSPEC_VMSUMM))]
816  "TARGET_ALTIVEC"
817  "vmsumm<VI_char>m %0,%1,%2,%3"
818  [(set_attr "type" "veccomplex")])
819
820(define_insn "altivec_vmsumshm"
821  [(set (match_operand:V4SI 0 "register_operand" "=v")
822        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
823		      (match_operand:V8HI 2 "register_operand" "v")
824                      (match_operand:V4SI 3 "register_operand" "v")]
825		     UNSPEC_VMSUMSHM))]
826  "TARGET_ALTIVEC"
827  "vmsumshm %0,%1,%2,%3"
828  [(set_attr "type" "veccomplex")])
829
830(define_insn "altivec_vmsumuhs"
831  [(set (match_operand:V4SI 0 "register_operand" "=v")
832        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
833		      (match_operand:V8HI 2 "register_operand" "v")
834                      (match_operand:V4SI 3 "register_operand" "v")]
835		     UNSPEC_VMSUMUHS))
836   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
837  "TARGET_ALTIVEC"
838  "vmsumuhs %0,%1,%2,%3"
839  [(set_attr "type" "veccomplex")])
840
841(define_insn "altivec_vmsumshs"
842  [(set (match_operand:V4SI 0 "register_operand" "=v")
843        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
844		      (match_operand:V8HI 2 "register_operand" "v")
845                      (match_operand:V4SI 3 "register_operand" "v")]
846		     UNSPEC_VMSUMSHS))
847   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
848  "TARGET_ALTIVEC"
849  "vmsumshs %0,%1,%2,%3"
850  [(set_attr "type" "veccomplex")])
851
852;; max
853
854(define_insn "umax<mode>3"
855  [(set (match_operand:VI2 0 "register_operand" "=v")
856        (umax:VI2 (match_operand:VI2 1 "register_operand" "v")
857		  (match_operand:VI2 2 "register_operand" "v")))]
858  "<VI_unit>"
859  "vmaxu<VI_char> %0,%1,%2"
860  [(set_attr "type" "vecsimple")])
861
862(define_insn "smax<mode>3"
863  [(set (match_operand:VI2 0 "register_operand" "=v")
864        (smax:VI2 (match_operand:VI2 1 "register_operand" "v")
865		  (match_operand:VI2 2 "register_operand" "v")))]
866  "<VI_unit>"
867  "vmaxs<VI_char> %0,%1,%2"
868  [(set_attr "type" "vecsimple")])
869
870(define_insn "*altivec_smaxv4sf3"
871  [(set (match_operand:V4SF 0 "register_operand" "=v")
872        (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
873                   (match_operand:V4SF 2 "register_operand" "v")))]
874  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
875  "vmaxfp %0,%1,%2"
876  [(set_attr "type" "veccmp")])
877
878(define_insn "umin<mode>3"
879  [(set (match_operand:VI2 0 "register_operand" "=v")
880        (umin:VI2 (match_operand:VI2 1 "register_operand" "v")
881		  (match_operand:VI2 2 "register_operand" "v")))]
882  "<VI_unit>"
883  "vminu<VI_char> %0,%1,%2"
884  [(set_attr "type" "vecsimple")])
885
886(define_insn "smin<mode>3"
887  [(set (match_operand:VI2 0 "register_operand" "=v")
888        (smin:VI2 (match_operand:VI2 1 "register_operand" "v")
889		  (match_operand:VI2 2 "register_operand" "v")))]
890  "<VI_unit>"
891  "vmins<VI_char> %0,%1,%2"
892  [(set_attr "type" "vecsimple")])
893
894(define_insn "*altivec_sminv4sf3"
895  [(set (match_operand:V4SF 0 "register_operand" "=v")
896        (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
897                   (match_operand:V4SF 2 "register_operand" "v")))]
898  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
899  "vminfp %0,%1,%2"
900  [(set_attr "type" "veccmp")])
901
902(define_insn "altivec_vmhaddshs"
903  [(set (match_operand:V8HI 0 "register_operand" "=v")
904        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
905		      (match_operand:V8HI 2 "register_operand" "v")
906                      (match_operand:V8HI 3 "register_operand" "v")]
907		     UNSPEC_VMHADDSHS))
908   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
909  "TARGET_ALTIVEC"
910  "vmhaddshs %0,%1,%2,%3"
911  [(set_attr "type" "veccomplex")])
912
913(define_insn "altivec_vmhraddshs"
914  [(set (match_operand:V8HI 0 "register_operand" "=v")
915        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
916		      (match_operand:V8HI 2 "register_operand" "v")
917                      (match_operand:V8HI 3 "register_operand" "v")]
918		     UNSPEC_VMHRADDSHS))
919   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
920  "TARGET_ALTIVEC"
921  "vmhraddshs %0,%1,%2,%3"
922  [(set_attr "type" "veccomplex")])
923
924(define_insn "fmav8hi4"
925  [(set (match_operand:V8HI 0 "register_operand" "=v")
926        (plus:V8HI (mult:V8HI (match_operand:V8HI 1 "register_operand" "v")
927		   	      (match_operand:V8HI 2 "register_operand" "v"))
928		   (match_operand:V8HI 3 "register_operand" "v")))]
929  "TARGET_ALTIVEC"
930  "vmladduhm %0,%1,%2,%3"
931  [(set_attr "type" "veccomplex")])
932
933(define_expand "altivec_vmrghb"
934  [(use (match_operand:V16QI 0 "register_operand"))
935   (use (match_operand:V16QI 1 "register_operand"))
936   (use (match_operand:V16QI 2 "register_operand"))]
937  "TARGET_ALTIVEC"
938{
939  rtvec v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17),
940		       GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19),
941		       GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21),
942		       GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23));
943  rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
944  x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
945  emit_insn (gen_rtx_SET (operands[0], x));
946  DONE;
947})
948
949(define_insn "*altivec_vmrghb_internal"
950  [(set (match_operand:V16QI 0 "register_operand" "=v")
951        (vec_select:V16QI
952	  (vec_concat:V32QI
953	    (match_operand:V16QI 1 "register_operand" "v")
954	    (match_operand:V16QI 2 "register_operand" "v"))
955	  (parallel [(const_int 0) (const_int 16)
956		     (const_int 1) (const_int 17)
957		     (const_int 2) (const_int 18)
958		     (const_int 3) (const_int 19)
959		     (const_int 4) (const_int 20)
960		     (const_int 5) (const_int 21)
961		     (const_int 6) (const_int 22)
962		     (const_int 7) (const_int 23)])))]
963  "TARGET_ALTIVEC"
964{
965  if (BYTES_BIG_ENDIAN)
966    return "vmrghb %0,%1,%2";
967  else
968    return "vmrglb %0,%2,%1";
969}
970  [(set_attr "type" "vecperm")])
971
972(define_insn "altivec_vmrghb_direct"
973  [(set (match_operand:V16QI 0 "register_operand" "=v")
974	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
975		       (match_operand:V16QI 2 "register_operand" "v")]
976		      UNSPEC_VMRGH_DIRECT))]
977  "TARGET_ALTIVEC"
978  "vmrghb %0,%1,%2"
979  [(set_attr "type" "vecperm")])
980
981(define_expand "altivec_vmrghh"
982  [(use (match_operand:V8HI 0 "register_operand"))
983   (use (match_operand:V8HI 1 "register_operand"))
984   (use (match_operand:V8HI 2 "register_operand"))]
985  "TARGET_ALTIVEC"
986{
987  rtvec v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9),
988		       GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11));
989  rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
990
991  x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
992  emit_insn (gen_rtx_SET (operands[0], x));
993  DONE;
994})
995
996(define_insn "*altivec_vmrghh_internal"
997  [(set (match_operand:V8HI 0 "register_operand" "=v")
998        (vec_select:V8HI
999	  (vec_concat:V16HI
1000	    (match_operand:V8HI 1 "register_operand" "v")
1001	    (match_operand:V8HI 2 "register_operand" "v"))
1002	  (parallel [(const_int 0) (const_int 8)
1003		     (const_int 1) (const_int 9)
1004		     (const_int 2) (const_int 10)
1005		     (const_int 3) (const_int 11)])))]
1006  "TARGET_ALTIVEC"
1007{
1008  if (BYTES_BIG_ENDIAN)
1009    return "vmrghh %0,%1,%2";
1010  else
1011    return "vmrglh %0,%2,%1";
1012}
1013  [(set_attr "type" "vecperm")])
1014
1015(define_insn "altivec_vmrghh_direct"
1016  [(set (match_operand:V8HI 0 "register_operand" "=v")
1017        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
1018                      (match_operand:V8HI 2 "register_operand" "v")]
1019                     UNSPEC_VMRGH_DIRECT))]
1020  "TARGET_ALTIVEC"
1021  "vmrghh %0,%1,%2"
1022  [(set_attr "type" "vecperm")])
1023
1024(define_expand "altivec_vmrghw"
1025  [(use (match_operand:V4SI 0 "register_operand"))
1026   (use (match_operand:V4SI 1 "register_operand"))
1027   (use (match_operand:V4SI 2 "register_operand"))]
1028  "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1029{
1030  rtvec v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5));
1031  rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
1032  x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1033  emit_insn (gen_rtx_SET (operands[0], x));
1034  DONE;
1035})
1036
1037(define_insn "*altivec_vmrghw_internal"
1038  [(set (match_operand:V4SI 0 "register_operand" "=v")
1039        (vec_select:V4SI
1040	  (vec_concat:V8SI
1041	    (match_operand:V4SI 1 "register_operand" "v")
1042	    (match_operand:V4SI 2 "register_operand" "v"))
1043	  (parallel [(const_int 0) (const_int 4)
1044		     (const_int 1) (const_int 5)])))]
1045  "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1046{
1047  if (BYTES_BIG_ENDIAN)
1048    return "vmrghw %0,%1,%2";
1049  else
1050    return "vmrglw %0,%2,%1";
1051}
1052  [(set_attr "type" "vecperm")])
1053
1054(define_insn "altivec_vmrghw_direct"
1055  [(set (match_operand:V4SI 0 "register_operand" "=v,wa")
1056	(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v,wa")
1057		      (match_operand:V4SI 2 "register_operand" "v,wa")]
1058		     UNSPEC_VMRGH_DIRECT))]
1059  "TARGET_ALTIVEC"
1060  "@
1061   vmrghw %0,%1,%2
1062   xxmrghw %x0,%x1,%x2"
1063  [(set_attr "type" "vecperm")])
1064
1065(define_insn "*altivec_vmrghsf"
1066  [(set (match_operand:V4SF 0 "register_operand" "=v")
1067        (vec_select:V4SF
1068	  (vec_concat:V8SF
1069	    (match_operand:V4SF 1 "register_operand" "v")
1070	    (match_operand:V4SF 2 "register_operand" "v"))
1071	  (parallel [(const_int 0) (const_int 4)
1072		     (const_int 1) (const_int 5)])))]
1073  "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
1074{
1075  if (BYTES_BIG_ENDIAN)
1076    return "vmrghw %0,%1,%2";
1077  else
1078    return "vmrglw %0,%2,%1";
1079}
1080  [(set_attr "type" "vecperm")])
1081
1082(define_expand "altivec_vmrglb"
1083  [(use (match_operand:V16QI 0 "register_operand"))
1084   (use (match_operand:V16QI 1 "register_operand"))
1085   (use (match_operand:V16QI 2 "register_operand"))]
1086  "TARGET_ALTIVEC"
1087{
1088  rtvec v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25),
1089		       GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27),
1090		       GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29),
1091		       GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31));
1092  rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
1093  x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1094  emit_insn (gen_rtx_SET (operands[0], x));
1095  DONE;
1096})
1097
1098(define_insn "*altivec_vmrglb_internal"
1099  [(set (match_operand:V16QI 0 "register_operand" "=v")
1100        (vec_select:V16QI
1101	  (vec_concat:V32QI
1102	    (match_operand:V16QI 1 "register_operand" "v")
1103	    (match_operand:V16QI 2 "register_operand" "v"))
1104	  (parallel [(const_int  8) (const_int 24)
1105		     (const_int  9) (const_int 25)
1106		     (const_int 10) (const_int 26)
1107		     (const_int 11) (const_int 27)
1108		     (const_int 12) (const_int 28)
1109		     (const_int 13) (const_int 29)
1110		     (const_int 14) (const_int 30)
1111		     (const_int 15) (const_int 31)])))]
1112  "TARGET_ALTIVEC"
1113{
1114  if (BYTES_BIG_ENDIAN)
1115    return "vmrglb %0,%1,%2";
1116  else
1117    return "vmrghb %0,%2,%1";
1118}
1119  [(set_attr "type" "vecperm")])
1120
1121(define_insn "altivec_vmrglb_direct"
1122  [(set (match_operand:V16QI 0 "register_operand" "=v")
1123	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1124		       (match_operand:V16QI 2 "register_operand" "v")]
1125		      UNSPEC_VMRGL_DIRECT))]
1126  "TARGET_ALTIVEC"
1127  "vmrglb %0,%1,%2"
1128  [(set_attr "type" "vecperm")])
1129
1130(define_expand "altivec_vmrglh"
1131  [(use (match_operand:V8HI 0 "register_operand"))
1132   (use (match_operand:V8HI 1 "register_operand"))
1133   (use (match_operand:V8HI 2 "register_operand"))]
1134  "TARGET_ALTIVEC"
1135{
1136  rtvec v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13),
1137		       GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15));
1138  rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
1139  x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1140  emit_insn (gen_rtx_SET (operands[0], x));
1141  DONE;
1142})
1143
1144(define_insn "*altivec_vmrglh_internal"
1145  [(set (match_operand:V8HI 0 "register_operand" "=v")
1146        (vec_select:V8HI
1147	  (vec_concat:V16HI
1148	    (match_operand:V8HI 1 "register_operand" "v")
1149	    (match_operand:V8HI 2 "register_operand" "v"))
1150	  (parallel [(const_int 4) (const_int 12)
1151		     (const_int 5) (const_int 13)
1152		     (const_int 6) (const_int 14)
1153		     (const_int 7) (const_int 15)])))]
1154  "TARGET_ALTIVEC"
1155{
1156  if (BYTES_BIG_ENDIAN)
1157    return "vmrglh %0,%1,%2";
1158  else
1159    return "vmrghh %0,%2,%1";
1160}
1161  [(set_attr "type" "vecperm")])
1162
1163(define_insn "altivec_vmrglh_direct"
1164  [(set (match_operand:V8HI 0 "register_operand" "=v")
1165        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
1166		      (match_operand:V8HI 2 "register_operand" "v")]
1167		     UNSPEC_VMRGL_DIRECT))]
1168  "TARGET_ALTIVEC"
1169  "vmrglh %0,%1,%2"
1170  [(set_attr "type" "vecperm")])
1171
1172(define_expand "altivec_vmrglw"
1173  [(use (match_operand:V4SI 0 "register_operand"))
1174   (use (match_operand:V4SI 1 "register_operand"))
1175   (use (match_operand:V4SI 2 "register_operand"))]
1176  "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1177{
1178  rtvec v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7));
1179  rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
1180  x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1181  emit_insn (gen_rtx_SET (operands[0], x));
1182  DONE;
1183})
1184
1185(define_insn "*altivec_vmrglw_internal"
1186  [(set (match_operand:V4SI 0 "register_operand" "=v")
1187        (vec_select:V4SI
1188	  (vec_concat:V8SI
1189	    (match_operand:V4SI 1 "register_operand" "v")
1190	    (match_operand:V4SI 2 "register_operand" "v"))
1191	  (parallel [(const_int 2) (const_int 6)
1192		     (const_int 3) (const_int 7)])))]
1193  "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1194{
1195  if (BYTES_BIG_ENDIAN)
1196    return "vmrglw %0,%1,%2";
1197  else
1198    return "vmrghw %0,%2,%1";
1199}
1200  [(set_attr "type" "vecperm")])
1201
1202(define_insn "altivec_vmrglw_direct"
1203  [(set (match_operand:V4SI 0 "register_operand" "=v,wa")
1204	(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v,wa")
1205		      (match_operand:V4SI 2 "register_operand" "v,wa")]
1206		     UNSPEC_VMRGL_DIRECT))]
1207  "TARGET_ALTIVEC"
1208  "@
1209   vmrglw %0,%1,%2
1210   xxmrglw %x0,%x1,%x2"
1211  [(set_attr "type" "vecperm")])
1212
1213(define_insn "*altivec_vmrglsf"
1214  [(set (match_operand:V4SF 0 "register_operand" "=v")
1215        (vec_select:V4SF
1216	 (vec_concat:V8SF
1217	   (match_operand:V4SF 1 "register_operand" "v")
1218	   (match_operand:V4SF 2 "register_operand" "v"))
1219	 (parallel [(const_int 2) (const_int 6)
1220		    (const_int 3) (const_int 7)])))]
1221  "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
1222{
1223  if (BYTES_BIG_ENDIAN)
1224    return "vmrglw %0,%1,%2";
1225  else
1226    return "vmrghw %0,%2,%1";
1227}
1228  [(set_attr "type" "vecperm")])
1229
1230;; Power8 vector merge two V2DF/V2DI even words to V2DF
1231(define_expand "p8_vmrgew_<mode>"
1232  [(use (match_operand:VSX_D 0 "vsx_register_operand"))
1233   (use (match_operand:VSX_D 1 "vsx_register_operand"))
1234   (use (match_operand:VSX_D 2 "vsx_register_operand"))]
1235  "VECTOR_MEM_VSX_P (<MODE>mode)"
1236{
1237  rtvec v;
1238  rtx x;
1239
1240  v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
1241  x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
1242
1243  x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
1244  emit_insn (gen_rtx_SET (operands[0], x));
1245  DONE;
1246})
1247
1248;; Power8 vector merge two V4SF/V4SI even words to V4SF
1249(define_insn "p8_vmrgew_<mode>"
1250  [(set (match_operand:VSX_W 0 "register_operand" "=v")
1251	(vec_select:VSX_W
1252	  (vec_concat:<VS_double>
1253	    (match_operand:VSX_W 1 "register_operand" "v")
1254	    (match_operand:VSX_W 2 "register_operand" "v"))
1255	  (parallel [(const_int 0) (const_int 4)
1256		     (const_int 2) (const_int 6)])))]
1257  "TARGET_P8_VECTOR"
1258{
1259  if (BYTES_BIG_ENDIAN)
1260    return "vmrgew %0,%1,%2";
1261  else
1262    return "vmrgow %0,%2,%1";
1263}
1264  [(set_attr "type" "vecperm")])
1265
1266(define_insn "p8_vmrgow_<mode>"
1267  [(set (match_operand:VSX_W 0 "register_operand" "=v")
1268	(vec_select:VSX_W
1269	  (vec_concat:<VS_double>
1270	    (match_operand:VSX_W 1 "register_operand" "v")
1271	    (match_operand:VSX_W 2 "register_operand" "v"))
1272	  (parallel [(const_int 1) (const_int 5)
1273		     (const_int 3) (const_int 7)])))]
1274  "TARGET_P8_VECTOR"
1275{
1276  if (BYTES_BIG_ENDIAN)
1277    return "vmrgow %0,%1,%2";
1278  else
1279    return "vmrgew %0,%2,%1";
1280}
1281  [(set_attr "type" "vecperm")])
1282
1283(define_expand "p8_vmrgow_<mode>"
1284  [(use (match_operand:VSX_D 0 "vsx_register_operand"))
1285   (use (match_operand:VSX_D 1 "vsx_register_operand"))
1286   (use (match_operand:VSX_D 2 "vsx_register_operand"))]
1287  "VECTOR_MEM_VSX_P (<MODE>mode)"
1288{
1289  rtvec v;
1290  rtx x;
1291
1292  v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
1293  x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
1294
1295  x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
1296  emit_insn (gen_rtx_SET (operands[0], x));
1297  DONE;
1298})
1299
1300(define_insn "p8_vmrgew_<mode>_direct"
1301  [(set (match_operand:VSX_W 0 "register_operand" "=v")
1302	(unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v")
1303		       (match_operand:VSX_W 2 "register_operand" "v")]
1304		     UNSPEC_VMRGEW_DIRECT))]
1305  "TARGET_P8_VECTOR"
1306  "vmrgew %0,%1,%2"
1307  [(set_attr "type" "vecperm")])
1308
1309(define_insn "p8_vmrgow_<mode>_direct"
1310  [(set (match_operand:VSX_W 0 "register_operand" "=v")
1311	(unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v")
1312		       (match_operand:VSX_W 2 "register_operand" "v")]
1313		     UNSPEC_VMRGOW_DIRECT))]
1314  "TARGET_P8_VECTOR"
1315  "vmrgow %0,%1,%2"
1316  [(set_attr "type" "vecperm")])
1317
1318(define_expand "vec_widen_umult_even_v16qi"
1319  [(use (match_operand:V8HI 0 "register_operand"))
1320   (use (match_operand:V16QI 1 "register_operand"))
1321   (use (match_operand:V16QI 2 "register_operand"))]
1322  "TARGET_ALTIVEC"
1323{
1324  if (BYTES_BIG_ENDIAN)
1325    emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
1326  else
1327    emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
1328  DONE;
1329})
1330
1331(define_expand "vec_widen_smult_even_v16qi"
1332  [(use (match_operand:V8HI 0 "register_operand"))
1333   (use (match_operand:V16QI 1 "register_operand"))
1334   (use (match_operand:V16QI 2 "register_operand"))]
1335  "TARGET_ALTIVEC"
1336{
1337  if (BYTES_BIG_ENDIAN)
1338    emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
1339  else
1340    emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
1341  DONE;
1342})
1343
1344(define_expand "vec_widen_umult_even_v8hi"
1345  [(use (match_operand:V4SI 0 "register_operand"))
1346   (use (match_operand:V8HI 1 "register_operand"))
1347   (use (match_operand:V8HI 2 "register_operand"))]
1348  "TARGET_ALTIVEC"
1349{
1350  if (BYTES_BIG_ENDIAN)
1351    emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
1352  else
1353    emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
1354  DONE;
1355})
1356
1357(define_expand "vec_widen_smult_even_v8hi"
1358  [(use (match_operand:V4SI 0 "register_operand"))
1359   (use (match_operand:V8HI 1 "register_operand"))
1360   (use (match_operand:V8HI 2 "register_operand"))]
1361  "TARGET_ALTIVEC"
1362{
1363  if (BYTES_BIG_ENDIAN)
1364    emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
1365  else
1366    emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
1367  DONE;
1368})
1369
1370(define_expand "vec_widen_umult_even_v4si"
1371  [(use (match_operand:V2DI 0 "register_operand"))
1372   (use (match_operand:V4SI 1 "register_operand"))
1373   (use (match_operand:V4SI 2 "register_operand"))]
1374  "TARGET_P8_VECTOR"
1375{
1376 if (BYTES_BIG_ENDIAN)
1377    emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
1378  else
1379    emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
1380 DONE;
1381})
1382
1383(define_expand "vec_widen_smult_even_v4si"
1384  [(use (match_operand:V2DI 0 "register_operand"))
1385   (use (match_operand:V4SI 1 "register_operand"))
1386   (use (match_operand:V4SI 2 "register_operand"))]
1387  "TARGET_P8_VECTOR"
1388{
1389  if (BYTES_BIG_ENDIAN)
1390    emit_insn (gen_altivec_vmulesw (operands[0], operands[1], operands[2]));
1391 else
1392    emit_insn (gen_altivec_vmulosw (operands[0], operands[1], operands[2]));
1393  DONE;
1394})
1395
1396(define_expand "vec_widen_umult_odd_v16qi"
1397  [(use (match_operand:V8HI 0 "register_operand"))
1398   (use (match_operand:V16QI 1 "register_operand"))
1399   (use (match_operand:V16QI 2 "register_operand"))]
1400  "TARGET_ALTIVEC"
1401{
1402  if (BYTES_BIG_ENDIAN)
1403    emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
1404  else
1405    emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
1406  DONE;
1407})
1408
1409(define_expand "vec_widen_smult_odd_v16qi"
1410  [(use (match_operand:V8HI 0 "register_operand"))
1411   (use (match_operand:V16QI 1 "register_operand"))
1412   (use (match_operand:V16QI 2 "register_operand"))]
1413  "TARGET_ALTIVEC"
1414{
1415  if (BYTES_BIG_ENDIAN)
1416    emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
1417  else
1418    emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
1419  DONE;
1420})
1421
1422(define_expand "vec_widen_umult_odd_v8hi"
1423  [(use (match_operand:V4SI 0 "register_operand"))
1424   (use (match_operand:V8HI 1 "register_operand"))
1425   (use (match_operand:V8HI 2 "register_operand"))]
1426  "TARGET_ALTIVEC"
1427{
1428  if (BYTES_BIG_ENDIAN)
1429    emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
1430  else
1431    emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
1432  DONE;
1433})
1434
1435(define_expand "vec_widen_smult_odd_v8hi"
1436  [(use (match_operand:V4SI 0 "register_operand"))
1437   (use (match_operand:V8HI 1 "register_operand"))
1438   (use (match_operand:V8HI 2 "register_operand"))]
1439  "TARGET_ALTIVEC"
1440{
1441  if (BYTES_BIG_ENDIAN)
1442    emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
1443  else
1444    emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
1445  DONE;
1446})
1447
1448(define_expand "vec_widen_umult_odd_v4si"
1449  [(use (match_operand:V2DI 0 "register_operand"))
1450   (use (match_operand:V4SI 1 "register_operand"))
1451   (use (match_operand:V4SI 2 "register_operand"))]
1452  "TARGET_P8_VECTOR"
1453{
1454  if (BYTES_BIG_ENDIAN)
1455    emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
1456  else
1457    emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
1458  DONE;
1459})
1460
1461(define_expand "vec_widen_smult_odd_v4si"
1462  [(use (match_operand:V2DI 0 "register_operand"))
1463   (use (match_operand:V4SI 1 "register_operand"))
1464   (use (match_operand:V4SI 2 "register_operand"))]
1465  "TARGET_P8_VECTOR"
1466{
1467  if (BYTES_BIG_ENDIAN)
1468    emit_insn (gen_altivec_vmulosw (operands[0], operands[1], operands[2]));
1469  else
1470    emit_insn (gen_altivec_vmulesw (operands[0], operands[1], operands[2]));
1471  DONE;
1472})
1473
1474(define_insn "altivec_vmuleub"
1475  [(set (match_operand:V8HI 0 "register_operand" "=v")
1476        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1477                      (match_operand:V16QI 2 "register_operand" "v")]
1478		     UNSPEC_VMULEUB))]
1479  "TARGET_ALTIVEC"
1480  "vmuleub %0,%1,%2"
1481  [(set_attr "type" "veccomplex")])
1482
1483(define_insn "altivec_vmuloub"
1484  [(set (match_operand:V8HI 0 "register_operand" "=v")
1485        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1486                      (match_operand:V16QI 2 "register_operand" "v")]
1487		     UNSPEC_VMULOUB))]
1488  "TARGET_ALTIVEC"
1489  "vmuloub %0,%1,%2"
1490  [(set_attr "type" "veccomplex")])
1491
1492(define_insn "altivec_vmulesb"
1493  [(set (match_operand:V8HI 0 "register_operand" "=v")
1494        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1495                      (match_operand:V16QI 2 "register_operand" "v")]
1496		     UNSPEC_VMULESB))]
1497  "TARGET_ALTIVEC"
1498  "vmulesb %0,%1,%2"
1499  [(set_attr "type" "veccomplex")])
1500
1501(define_insn "altivec_vmulosb"
1502  [(set (match_operand:V8HI 0 "register_operand" "=v")
1503        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1504                      (match_operand:V16QI 2 "register_operand" "v")]
1505		     UNSPEC_VMULOSB))]
1506  "TARGET_ALTIVEC"
1507  "vmulosb %0,%1,%2"
1508  [(set_attr "type" "veccomplex")])
1509
1510(define_insn "altivec_vmuleuh"
1511  [(set (match_operand:V4SI 0 "register_operand" "=v")
1512        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1513                      (match_operand:V8HI 2 "register_operand" "v")]
1514		     UNSPEC_VMULEUH))]
1515  "TARGET_ALTIVEC"
1516  "vmuleuh %0,%1,%2"
1517  [(set_attr "type" "veccomplex")])
1518
1519(define_insn "altivec_vmulouh"
1520  [(set (match_operand:V4SI 0 "register_operand" "=v")
1521        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1522                      (match_operand:V8HI 2 "register_operand" "v")]
1523		     UNSPEC_VMULOUH))]
1524  "TARGET_ALTIVEC"
1525  "vmulouh %0,%1,%2"
1526  [(set_attr "type" "veccomplex")])
1527
1528(define_insn "altivec_vmulesh"
1529  [(set (match_operand:V4SI 0 "register_operand" "=v")
1530        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1531                      (match_operand:V8HI 2 "register_operand" "v")]
1532		     UNSPEC_VMULESH))]
1533  "TARGET_ALTIVEC"
1534  "vmulesh %0,%1,%2"
1535  [(set_attr "type" "veccomplex")])
1536
1537(define_insn "altivec_vmulosh"
1538  [(set (match_operand:V4SI 0 "register_operand" "=v")
1539        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1540                      (match_operand:V8HI 2 "register_operand" "v")]
1541		     UNSPEC_VMULOSH))]
1542  "TARGET_ALTIVEC"
1543  "vmulosh %0,%1,%2"
1544  [(set_attr "type" "veccomplex")])
1545
1546(define_insn "altivec_vmuleuw"
1547  [(set (match_operand:V2DI 0 "register_operand" "=v")
1548       (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
1549                     (match_operand:V4SI 2 "register_operand" "v")]
1550                    UNSPEC_VMULEUW))]
1551  "TARGET_P8_VECTOR"
1552  "vmuleuw %0,%1,%2"
1553  [(set_attr "type" "veccomplex")])
1554
1555(define_insn "altivec_vmulouw"
1556  [(set (match_operand:V2DI 0 "register_operand" "=v")
1557       (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
1558                     (match_operand:V4SI 2 "register_operand" "v")]
1559                    UNSPEC_VMULOUW))]
1560  "TARGET_P8_VECTOR"
1561  "vmulouw %0,%1,%2"
1562  [(set_attr "type" "veccomplex")])
1563
1564(define_insn "altivec_vmulesw"
1565  [(set (match_operand:V2DI 0 "register_operand" "=v")
1566       (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
1567                     (match_operand:V4SI 2 "register_operand" "v")]
1568                    UNSPEC_VMULESW))]
1569  "TARGET_P8_VECTOR"
1570  "vmulesw %0,%1,%2"
1571  [(set_attr "type" "veccomplex")])
1572
1573(define_insn "altivec_vmulosw"
1574  [(set (match_operand:V2DI 0 "register_operand" "=v")
1575       (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
1576                     (match_operand:V4SI 2 "register_operand" "v")]
1577                    UNSPEC_VMULOSW))]
1578  "TARGET_P8_VECTOR"
1579  "vmulosw %0,%1,%2"
1580  [(set_attr "type" "veccomplex")])
1581
1582;; Vector pack/unpack
1583(define_insn "altivec_vpkpx"
1584  [(set (match_operand:V8HI 0 "register_operand" "=v")
1585        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
1586                      (match_operand:V4SI 2 "register_operand" "v")]
1587		     UNSPEC_VPKPX))]
1588  "TARGET_ALTIVEC"
1589{
1590  if (BYTES_BIG_ENDIAN)
1591    return "vpkpx %0,%1,%2";
1592  else
1593    return "vpkpx %0,%2,%1";
1594}
1595  [(set_attr "type" "vecperm")])
1596
1597(define_insn "altivec_vpks<VI_char>ss"
1598  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1599	(unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1600			    (match_operand:VP 2 "register_operand" "v")]
1601			   UNSPEC_VPACK_SIGN_SIGN_SAT))]
1602  "<VI_unit>"
1603{
1604  if (BYTES_BIG_ENDIAN)
1605    return "vpks<VI_char>ss %0,%1,%2";
1606  else
1607    return "vpks<VI_char>ss %0,%2,%1";
1608}
1609  [(set_attr "type" "vecperm")])
1610
1611(define_insn "altivec_vpks<VI_char>us"
1612  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1613	(unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1614			    (match_operand:VP 2 "register_operand" "v")]
1615			   UNSPEC_VPACK_SIGN_UNS_SAT))]
1616  "<VI_unit>"
1617{
1618  if (BYTES_BIG_ENDIAN)
1619    return "vpks<VI_char>us %0,%1,%2";
1620  else
1621    return "vpks<VI_char>us %0,%2,%1";
1622}
1623  [(set_attr "type" "vecperm")])
1624
1625(define_insn "altivec_vpku<VI_char>us"
1626  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1627	(unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1628			    (match_operand:VP 2 "register_operand" "v")]
1629			   UNSPEC_VPACK_UNS_UNS_SAT))]
1630  "<VI_unit>"
1631{
1632  if (BYTES_BIG_ENDIAN)
1633    return "vpku<VI_char>us %0,%1,%2";
1634  else
1635    return "vpku<VI_char>us %0,%2,%1";
1636}
1637  [(set_attr "type" "vecperm")])
1638
1639(define_insn "altivec_vpku<VI_char>um"
1640  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1641	(unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1642			    (match_operand:VP 2 "register_operand" "v")]
1643			   UNSPEC_VPACK_UNS_UNS_MOD))]
1644  "<VI_unit>"
1645{
1646  if (BYTES_BIG_ENDIAN)
1647    return "vpku<VI_char>um %0,%1,%2";
1648  else
1649    return "vpku<VI_char>um %0,%2,%1";
1650}
1651  [(set_attr "type" "vecperm")])
1652
1653(define_insn "altivec_vpku<VI_char>um_direct"
1654  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1655	(unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1656			    (match_operand:VP 2 "register_operand" "v")]
1657			   UNSPEC_VPACK_UNS_UNS_MOD_DIRECT))]
1658  "<VI_unit>"
1659{
1660  if (BYTES_BIG_ENDIAN)
1661    return "vpku<VI_char>um %0,%1,%2";
1662  else
1663    return "vpku<VI_char>um %0,%2,%1";
1664}
1665  [(set_attr "type" "vecperm")])
1666
1667(define_insn "*altivec_vrl<VI_char>"
1668  [(set (match_operand:VI2 0 "register_operand" "=v")
1669        (rotate:VI2 (match_operand:VI2 1 "register_operand" "v")
1670		    (match_operand:VI2 2 "register_operand" "v")))]
1671  "<VI_unit>"
1672  "vrl<VI_char> %0,%1,%2"
1673  [(set_attr "type" "vecsimple")])
1674
1675(define_insn "altivec_vrl<VI_char>mi"
1676  [(set (match_operand:VIlong 0 "register_operand" "=v")
1677        (unspec:VIlong [(match_operand:VIlong 1 "register_operand" "0")
1678	                (match_operand:VIlong 2 "register_operand" "v")
1679		        (match_operand:VIlong 3 "register_operand" "v")]
1680		       UNSPEC_VRLMI))]
1681  "TARGET_P9_VECTOR"
1682  "vrl<VI_char>mi %0,%2,%3"
1683  [(set_attr "type" "veclogical")])
1684
1685(define_insn "altivec_vrl<VI_char>nm"
1686  [(set (match_operand:VIlong 0 "register_operand" "=v")
1687        (unspec:VIlong [(match_operand:VIlong 1 "register_operand" "v")
1688		        (match_operand:VIlong 2 "register_operand" "v")]
1689		       UNSPEC_VRLNM))]
1690  "TARGET_P9_VECTOR"
1691  "vrl<VI_char>nm %0,%1,%2"
1692  [(set_attr "type" "veclogical")])
1693
1694(define_insn "altivec_vsl"
1695  [(set (match_operand:V4SI 0 "register_operand" "=v")
1696        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1697                      (match_operand:V4SI 2 "register_operand" "v")]
1698		     UNSPEC_VSLV4SI))]
1699  "TARGET_ALTIVEC"
1700  "vsl %0,%1,%2"
1701  [(set_attr "type" "vecperm")])
1702
1703(define_insn "altivec_vslo"
1704  [(set (match_operand:V4SI 0 "register_operand" "=v")
1705        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1706                      (match_operand:V4SI 2 "register_operand" "v")]
1707		     UNSPEC_VSLO))]
1708  "TARGET_ALTIVEC"
1709  "vslo %0,%1,%2"
1710  [(set_attr "type" "vecperm")])
1711
1712(define_insn "vslv"
1713  [(set (match_operand:V16QI 0 "register_operand" "=v")
1714	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1715		       (match_operand:V16QI 2 "register_operand" "v")]
1716         UNSPEC_VSLV))]
1717  "TARGET_P9_VECTOR"
1718  "vslv %0,%1,%2"
1719  [(set_attr "type" "vecsimple")])
1720
1721(define_insn "vsrv"
1722  [(set (match_operand:V16QI 0 "register_operand" "=v")
1723	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1724		       (match_operand:V16QI 2 "register_operand" "v")]
1725         UNSPEC_VSRV))]
1726  "TARGET_P9_VECTOR"
1727  "vsrv %0,%1,%2"
1728  [(set_attr "type" "vecsimple")])
1729
1730(define_insn "*altivec_vsl<VI_char>"
1731  [(set (match_operand:VI2 0 "register_operand" "=v")
1732        (ashift:VI2 (match_operand:VI2 1 "register_operand" "v")
1733		    (match_operand:VI2 2 "register_operand" "v")))]
1734  "<VI_unit>"
1735  "vsl<VI_char> %0,%1,%2"
1736  [(set_attr "type" "vecsimple")])
1737
1738(define_insn "*altivec_vsr<VI_char>"
1739  [(set (match_operand:VI2 0 "register_operand" "=v")
1740        (lshiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
1741		      (match_operand:VI2 2 "register_operand" "v")))]
1742  "<VI_unit>"
1743  "vsr<VI_char> %0,%1,%2"
1744  [(set_attr "type" "vecsimple")])
1745
1746(define_insn "*altivec_vsra<VI_char>"
1747  [(set (match_operand:VI2 0 "register_operand" "=v")
1748        (ashiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
1749		      (match_operand:VI2 2 "register_operand" "v")))]
1750  "<VI_unit>"
1751  "vsra<VI_char> %0,%1,%2"
1752  [(set_attr "type" "vecsimple")])
1753
1754(define_insn "altivec_vsr"
1755  [(set (match_operand:V4SI 0 "register_operand" "=v")
1756        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1757                      (match_operand:V4SI 2 "register_operand" "v")]
1758		     UNSPEC_VSR))]
1759  "TARGET_ALTIVEC"
1760  "vsr %0,%1,%2"
1761  [(set_attr "type" "vecperm")])
1762
1763(define_insn "altivec_vsro"
1764  [(set (match_operand:V4SI 0 "register_operand" "=v")
1765        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1766                      (match_operand:V4SI 2 "register_operand" "v")]
1767		     UNSPEC_VSRO))]
1768  "TARGET_ALTIVEC"
1769  "vsro %0,%1,%2"
1770  [(set_attr "type" "vecperm")])
1771
1772(define_insn "altivec_vsum4ubs"
1773  [(set (match_operand:V4SI 0 "register_operand" "=v")
1774        (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
1775                      (match_operand:V4SI 2 "register_operand" "v")]
1776		     UNSPEC_VSUM4UBS))
1777   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1778  "TARGET_ALTIVEC"
1779  "vsum4ubs %0,%1,%2"
1780  [(set_attr "type" "veccomplex")])
1781
1782(define_insn "altivec_vsum4s<VI_char>s"
1783  [(set (match_operand:V4SI 0 "register_operand" "=v")
1784        (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
1785                      (match_operand:V4SI 2 "register_operand" "v")]
1786		     UNSPEC_VSUM4S))
1787   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1788  "TARGET_ALTIVEC"
1789  "vsum4s<VI_char>s %0,%1,%2"
1790  [(set_attr "type" "veccomplex")])
1791
1792(define_expand "altivec_vsum2sws"
1793  [(use (match_operand:V4SI 0 "register_operand"))
1794   (use (match_operand:V4SI 1 "register_operand"))
1795   (use (match_operand:V4SI 2 "register_operand"))]
1796  "TARGET_ALTIVEC"
1797{
1798  if (BYTES_BIG_ENDIAN)
1799    emit_insn (gen_altivec_vsum2sws_direct (operands[0], operands[1],
1800                                            operands[2]));
1801  else
1802    {
1803      rtx tmp1 = gen_reg_rtx (V4SImode);
1804      rtx tmp2 = gen_reg_rtx (V4SImode);
1805      emit_insn (gen_altivec_vsldoi_v4si (tmp1, operands[2],
1806                                          operands[2], GEN_INT (12)));
1807      emit_insn (gen_altivec_vsum2sws_direct (tmp2, operands[1], tmp1));
1808      emit_insn (gen_altivec_vsldoi_v4si (operands[0], tmp2, tmp2,
1809                                          GEN_INT (4)));
1810    }
1811  DONE;
1812})
1813
1814; FIXME: This can probably be expressed without an UNSPEC.
1815(define_insn "altivec_vsum2sws_direct"
1816  [(set (match_operand:V4SI 0 "register_operand" "=v")
1817        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1818	              (match_operand:V4SI 2 "register_operand" "v")]
1819		     UNSPEC_VSUM2SWS))
1820   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1821  "TARGET_ALTIVEC"
1822  "vsum2sws %0,%1,%2"
1823  [(set_attr "type" "veccomplex")])
1824
1825(define_expand "altivec_vsumsws"
1826  [(use (match_operand:V4SI 0 "register_operand"))
1827   (use (match_operand:V4SI 1 "register_operand"))
1828   (use (match_operand:V4SI 2 "register_operand"))]
1829  "TARGET_ALTIVEC"
1830{
1831  if (BYTES_BIG_ENDIAN)
1832    emit_insn (gen_altivec_vsumsws_direct (operands[0], operands[1],
1833                                           operands[2]));
1834  else
1835    {
1836      rtx tmp1 = gen_reg_rtx (V4SImode);
1837      rtx tmp2 = gen_reg_rtx (V4SImode);
1838      emit_insn (gen_altivec_vspltw_direct (tmp1, operands[2], const0_rtx));
1839      emit_insn (gen_altivec_vsumsws_direct (tmp2, operands[1], tmp1));
1840      emit_insn (gen_altivec_vsldoi_v4si (operands[0], tmp2, tmp2,
1841                                          GEN_INT (12)));
1842    }
1843  DONE;
1844})
1845
1846; FIXME: This can probably be expressed without an UNSPEC.
1847(define_insn "altivec_vsumsws_direct"
1848  [(set (match_operand:V4SI 0 "register_operand" "=v")
1849        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1850                      (match_operand:V4SI 2 "register_operand" "v")]
1851		     UNSPEC_VSUMSWS_DIRECT))
1852   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1853  "TARGET_ALTIVEC"
1854  "vsumsws %0,%1,%2"
1855  [(set_attr "type" "veccomplex")])
1856
1857(define_expand "altivec_vspltb"
1858  [(use (match_operand:V16QI 0 "register_operand"))
1859   (use (match_operand:V16QI 1 "register_operand"))
1860   (use (match_operand:QI 2 "const_0_to_15_operand"))]
1861  "TARGET_ALTIVEC"
1862{
1863  rtvec v = gen_rtvec (1, operands[2]);
1864  rtx x;
1865  x = gen_rtx_VEC_SELECT (QImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1866  x = gen_rtx_VEC_DUPLICATE (V16QImode, x);
1867  emit_insn (gen_rtx_SET (operands[0], x));
1868  DONE;
1869})
1870
1871(define_insn "*altivec_vspltb_internal"
1872  [(set (match_operand:V16QI 0 "register_operand" "=v")
1873        (vec_duplicate:V16QI
1874	 (vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
1875			(parallel
1876			 [(match_operand:QI 2 "const_0_to_15_operand" "")]))))]
1877  "TARGET_ALTIVEC"
1878{
1879  if (!BYTES_BIG_ENDIAN)
1880    operands[2] = GEN_INT (15 - INTVAL (operands[2]));
1881
1882  return "vspltb %0,%1,%2";
1883}
1884  [(set_attr "type" "vecperm")])
1885
1886(define_insn "altivec_vspltb_direct"
1887  [(set (match_operand:V16QI 0 "register_operand" "=v")
1888        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1889	               (match_operand:QI 2 "const_0_to_15_operand" "i")]
1890                      UNSPEC_VSPLT_DIRECT))]
1891  "TARGET_ALTIVEC"
1892  "vspltb %0,%1,%2"
1893  [(set_attr "type" "vecperm")])
1894
1895(define_expand "altivec_vsplth"
1896  [(use (match_operand:V8HI 0 "register_operand"))
1897   (use (match_operand:V8HI 1 "register_operand"))
1898   (use (match_operand:QI 2 "const_0_to_7_operand"))]
1899  "TARGET_ALTIVEC"
1900{
1901  rtvec v = gen_rtvec (1, operands[2]);
1902  rtx x;
1903  x = gen_rtx_VEC_SELECT (HImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1904  x = gen_rtx_VEC_DUPLICATE (V8HImode, x);
1905  emit_insn (gen_rtx_SET (operands[0], x));
1906  DONE;
1907})
1908
1909(define_insn "*altivec_vsplth_internal"
1910  [(set (match_operand:V8HI 0 "register_operand" "=v")
1911	(vec_duplicate:V8HI
1912	 (vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
1913			(parallel
1914			 [(match_operand:QI 2 "const_0_to_7_operand" "")]))))]
1915  "TARGET_ALTIVEC"
1916{
1917  if (!BYTES_BIG_ENDIAN)
1918    operands[2] = GEN_INT (7 - INTVAL (operands[2]));
1919
1920  return "vsplth %0,%1,%2";
1921}
1922  [(set_attr "type" "vecperm")])
1923
1924(define_insn "altivec_vsplth_direct"
1925  [(set (match_operand:V8HI 0 "register_operand" "=v")
1926        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
1927                      (match_operand:QI 2 "const_0_to_7_operand" "i")]
1928                     UNSPEC_VSPLT_DIRECT))]
1929  "TARGET_ALTIVEC"
1930  "vsplth %0,%1,%2"
1931  [(set_attr "type" "vecperm")])
1932
1933(define_expand "altivec_vspltw"
1934  [(use (match_operand:V4SI 0 "register_operand"))
1935   (use (match_operand:V4SI 1 "register_operand"))
1936   (use (match_operand:QI 2 "const_0_to_3_operand"))]
1937  "TARGET_ALTIVEC"
1938{
1939  rtvec v = gen_rtvec (1, operands[2]);
1940  rtx x;
1941  x = gen_rtx_VEC_SELECT (SImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1942  x = gen_rtx_VEC_DUPLICATE (V4SImode, x);
1943  emit_insn (gen_rtx_SET (operands[0], x));
1944  DONE;
1945})
1946
1947(define_insn "*altivec_vspltw_internal"
1948  [(set (match_operand:V4SI 0 "register_operand" "=v")
1949	(vec_duplicate:V4SI
1950	 (vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
1951			(parallel
1952			 [(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
1953  "TARGET_ALTIVEC"
1954{
1955  if (!BYTES_BIG_ENDIAN)
1956    operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1957
1958  return "vspltw %0,%1,%2";
1959}
1960  [(set_attr "type" "vecperm")])
1961
1962(define_insn "altivec_vspltw_direct"
1963  [(set (match_operand:V4SI 0 "register_operand" "=v")
1964        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1965                      (match_operand:QI 2 "const_0_to_3_operand" "i")]
1966                     UNSPEC_VSPLT_DIRECT))]
1967  "TARGET_ALTIVEC"
1968  "vspltw %0,%1,%2"
1969  [(set_attr "type" "vecperm")])
1970
1971(define_expand "altivec_vspltsf"
1972  [(use (match_operand:V4SF 0 "register_operand"))
1973   (use (match_operand:V4SF 1 "register_operand"))
1974   (use (match_operand:QI 2 "const_0_to_3_operand"))]
1975  "TARGET_ALTIVEC"
1976{
1977  rtvec v = gen_rtvec (1, operands[2]);
1978  rtx x;
1979  x = gen_rtx_VEC_SELECT (SFmode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1980  x = gen_rtx_VEC_DUPLICATE (V4SFmode, x);
1981  emit_insn (gen_rtx_SET (operands[0], x));
1982  DONE;
1983})
1984
1985(define_insn "*altivec_vspltsf_internal"
1986  [(set (match_operand:V4SF 0 "register_operand" "=v")
1987	(vec_duplicate:V4SF
1988	 (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
1989			(parallel
1990			 [(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
1991  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
1992{
1993  if (!BYTES_BIG_ENDIAN)
1994    operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1995
1996  return "vspltw %0,%1,%2";
1997}
1998  [(set_attr "type" "vecperm")])
1999
2000(define_insn "altivec_vspltis<VI_char>"
2001  [(set (match_operand:VI 0 "register_operand" "=v")
2002	(vec_duplicate:VI
2003	 (match_operand:QI 1 "s5bit_cint_operand" "i")))]
2004  "TARGET_ALTIVEC"
2005  "vspltis<VI_char> %0,%1"
2006  [(set_attr "type" "vecperm")])
2007
2008(define_insn "*altivec_vrfiz"
2009  [(set (match_operand:V4SF 0 "register_operand" "=v")
2010	(fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
2011  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2012  "vrfiz %0,%1"
2013  [(set_attr "type" "vecfloat")])
2014
2015(define_expand "altivec_vperm_<mode>"
2016  [(set (match_operand:VM 0 "register_operand")
2017	(unspec:VM [(match_operand:VM 1 "register_operand")
2018		    (match_operand:VM 2 "register_operand")
2019		    (match_operand:V16QI 3 "register_operand")]
2020		   UNSPEC_VPERM))]
2021  "TARGET_ALTIVEC"
2022{
2023  if (!BYTES_BIG_ENDIAN)
2024    {
2025      altivec_expand_vec_perm_le (operands);
2026      DONE;
2027    }
2028})
2029
2030;; Slightly prefer vperm, since the target does not overlap the source
2031(define_insn "altivec_vperm_<mode>_direct"
2032  [(set (match_operand:VM 0 "register_operand" "=v,?wo")
2033	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
2034		    (match_operand:VM 2 "register_operand" "v,0")
2035		    (match_operand:V16QI 3 "register_operand" "v,wo")]
2036		   UNSPEC_VPERM))]
2037  "TARGET_ALTIVEC"
2038  "@
2039   vperm %0,%1,%2,%3
2040   xxperm %x0,%x1,%x3"
2041  [(set_attr "type" "vecperm")])
2042
2043(define_insn "altivec_vperm_v8hiv16qi"
2044  [(set (match_operand:V16QI 0 "register_operand" "=v,?wo")
2045	(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v,wo")
2046   	               (match_operand:V8HI 2 "register_operand" "v,0")
2047		       (match_operand:V16QI 3 "register_operand" "v,wo")]
2048		   UNSPEC_VPERM))]
2049  "TARGET_ALTIVEC"
2050  "@
2051   vperm %0,%1,%2,%3
2052   xxperm %x0,%x1,%x3"
2053  [(set_attr "type" "vecperm")])
2054
2055(define_expand "altivec_vperm_<mode>_uns"
2056  [(set (match_operand:VM 0 "register_operand")
2057	(unspec:VM [(match_operand:VM 1 "register_operand")
2058		    (match_operand:VM 2 "register_operand")
2059		    (match_operand:V16QI 3 "register_operand")]
2060		   UNSPEC_VPERM_UNS))]
2061  "TARGET_ALTIVEC"
2062{
2063  if (!BYTES_BIG_ENDIAN)
2064    {
2065      altivec_expand_vec_perm_le (operands);
2066      DONE;
2067    }
2068})
2069
2070(define_insn "*altivec_vperm_<mode>_uns_internal"
2071  [(set (match_operand:VM 0 "register_operand" "=v,?wo")
2072	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
2073		    (match_operand:VM 2 "register_operand" "v,0")
2074		    (match_operand:V16QI 3 "register_operand" "v,wo")]
2075		   UNSPEC_VPERM_UNS))]
2076  "TARGET_ALTIVEC"
2077  "@
2078   vperm %0,%1,%2,%3
2079   xxperm %x0,%x1,%x3"
2080  [(set_attr "type" "vecperm")])
2081
2082(define_expand "vec_permv16qi"
2083  [(set (match_operand:V16QI 0 "register_operand")
2084	(unspec:V16QI [(match_operand:V16QI 1 "register_operand")
2085		       (match_operand:V16QI 2 "register_operand")
2086		       (match_operand:V16QI 3 "register_operand")]
2087		      UNSPEC_VPERM))]
2088  "TARGET_ALTIVEC"
2089{
2090  if (!BYTES_BIG_ENDIAN) {
2091    altivec_expand_vec_perm_le (operands);
2092    DONE;
2093  }
2094})
2095
2096(define_insn "*altivec_vpermr_<mode>_internal"
2097  [(set (match_operand:VM 0 "register_operand" "=v,?wo")
2098	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
2099		    (match_operand:VM 2 "register_operand" "v,0")
2100		    (match_operand:V16QI 3 "register_operand" "v,wo")]
2101		   UNSPEC_VPERMR))]
2102  "TARGET_P9_VECTOR"
2103  "@
2104   vpermr %0,%1,%2,%3
2105   xxpermr %x0,%x1,%x3"
2106  [(set_attr "type" "vecperm")])
2107
2108(define_insn "altivec_vrfip"		; ceil
2109  [(set (match_operand:V4SF 0 "register_operand" "=v")
2110        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2111		     UNSPEC_FRIP))]
2112  "TARGET_ALTIVEC"
2113  "vrfip %0,%1"
2114  [(set_attr "type" "vecfloat")])
2115
2116(define_insn "altivec_vrfin"
2117  [(set (match_operand:V4SF 0 "register_operand" "=v")
2118        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2119		     UNSPEC_VRFIN))]
2120  "TARGET_ALTIVEC"
2121  "vrfin %0,%1"
2122  [(set_attr "type" "vecfloat")])
2123
2124(define_insn "*altivec_vrfim"		; floor
2125  [(set (match_operand:V4SF 0 "register_operand" "=v")
2126        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2127		     UNSPEC_FRIM))]
2128  "TARGET_ALTIVEC"
2129  "vrfim %0,%1"
2130  [(set_attr "type" "vecfloat")])
2131
2132(define_insn "altivec_vcfux"
2133  [(set (match_operand:V4SF 0 "register_operand" "=v")
2134        (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
2135	              (match_operand:QI 2 "immediate_operand" "i")]
2136		     UNSPEC_VCFUX))]
2137  "TARGET_ALTIVEC"
2138  "vcfux %0,%1,%2"
2139  [(set_attr "type" "vecfloat")])
2140
2141(define_insn "altivec_vcfsx"
2142  [(set (match_operand:V4SF 0 "register_operand" "=v")
2143        (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
2144	              (match_operand:QI 2 "immediate_operand" "i")]
2145		     UNSPEC_VCFSX))]
2146  "TARGET_ALTIVEC"
2147  "vcfsx %0,%1,%2"
2148  [(set_attr "type" "vecfloat")])
2149
2150(define_insn "altivec_vctuxs"
2151  [(set (match_operand:V4SI 0 "register_operand" "=v")
2152        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2153                      (match_operand:QI 2 "immediate_operand" "i")]
2154		     UNSPEC_VCTUXS))
2155   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2156  "TARGET_ALTIVEC"
2157  "vctuxs %0,%1,%2"
2158  [(set_attr "type" "vecfloat")])
2159
2160(define_insn "altivec_vctsxs"
2161  [(set (match_operand:V4SI 0 "register_operand" "=v")
2162        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2163                      (match_operand:QI 2 "immediate_operand" "i")]
2164		     UNSPEC_VCTSXS))
2165   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2166  "TARGET_ALTIVEC"
2167  "vctsxs %0,%1,%2"
2168  [(set_attr "type" "vecfloat")])
2169
2170(define_insn "altivec_vlogefp"
2171  [(set (match_operand:V4SF 0 "register_operand" "=v")
2172        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2173		     UNSPEC_VLOGEFP))]
2174  "TARGET_ALTIVEC"
2175  "vlogefp %0,%1"
2176  [(set_attr "type" "vecfloat")])
2177
2178(define_insn "altivec_vexptefp"
2179  [(set (match_operand:V4SF 0 "register_operand" "=v")
2180        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2181		     UNSPEC_VEXPTEFP))]
2182  "TARGET_ALTIVEC"
2183  "vexptefp %0,%1"
2184  [(set_attr "type" "vecfloat")])
2185
2186(define_insn "*altivec_vrsqrtefp"
2187  [(set (match_operand:V4SF 0 "register_operand" "=v")
2188        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2189		     UNSPEC_RSQRT))]
2190  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2191  "vrsqrtefp %0,%1"
2192  [(set_attr "type" "vecfloat")])
2193
2194(define_insn "altivec_vrefp"
2195  [(set (match_operand:V4SF 0 "register_operand" "=v")
2196        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2197		     UNSPEC_FRES))]
2198  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2199  "vrefp %0,%1"
2200  [(set_attr "type" "vecfloat")])
2201
2202(define_expand "altivec_copysign_v4sf3"
2203  [(use (match_operand:V4SF 0 "register_operand"))
2204   (use (match_operand:V4SF 1 "register_operand"))
2205   (use (match_operand:V4SF 2 "register_operand"))]
2206  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2207{
2208  rtx mask = gen_reg_rtx (V4SImode);
2209  rtvec v = rtvec_alloc (4);
2210  unsigned HOST_WIDE_INT mask_val = ((unsigned HOST_WIDE_INT)1) << 31;
2211
2212  RTVEC_ELT (v, 0) = GEN_INT (mask_val);
2213  RTVEC_ELT (v, 1) = GEN_INT (mask_val);
2214  RTVEC_ELT (v, 2) = GEN_INT (mask_val);
2215  RTVEC_ELT (v, 3) = GEN_INT (mask_val);
2216
2217  emit_insn (gen_vec_initv4sisi (mask, gen_rtx_PARALLEL (V4SImode, v)));
2218  emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2],
2219				     gen_lowpart (V4SFmode, mask)));
2220  DONE;
2221})
2222
2223(define_insn "altivec_vsldoi_<mode>"
2224  [(set (match_operand:VM 0 "register_operand" "=v")
2225        (unspec:VM [(match_operand:VM 1 "register_operand" "v")
2226		    (match_operand:VM 2 "register_operand" "v")
2227		    (match_operand:QI 3 "immediate_operand" "i")]
2228		  UNSPEC_VSLDOI))]
2229  "TARGET_ALTIVEC"
2230  "vsldoi %0,%1,%2,%3"
2231  [(set_attr "type" "vecperm")])
2232
2233(define_insn "altivec_vupkhs<VU_char>"
2234  [(set (match_operand:VP 0 "register_operand" "=v")
2235	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2236		     UNSPEC_VUNPACK_HI_SIGN))]
2237  "<VI_unit>"
2238{
2239  if (BYTES_BIG_ENDIAN)
2240    return "vupkhs<VU_char> %0,%1";
2241  else
2242    return "vupkls<VU_char> %0,%1";
2243}
2244  [(set_attr "type" "vecperm")])
2245
2246(define_insn "*altivec_vupkhs<VU_char>_direct"
2247  [(set (match_operand:VP 0 "register_operand" "=v")
2248	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2249		     UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
2250  "<VI_unit>"
2251  "vupkhs<VU_char> %0,%1"
2252  [(set_attr "type" "vecperm")])
2253
2254(define_insn "altivec_vupkls<VU_char>"
2255  [(set (match_operand:VP 0 "register_operand" "=v")
2256	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2257		     UNSPEC_VUNPACK_LO_SIGN))]
2258  "<VI_unit>"
2259{
2260  if (BYTES_BIG_ENDIAN)
2261    return "vupkls<VU_char> %0,%1";
2262  else
2263    return "vupkhs<VU_char> %0,%1";
2264}
2265  [(set_attr "type" "vecperm")])
2266
2267(define_insn "*altivec_vupkls<VU_char>_direct"
2268  [(set (match_operand:VP 0 "register_operand" "=v")
2269	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2270		     UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
2271  "<VI_unit>"
2272  "vupkls<VU_char> %0,%1"
2273  [(set_attr "type" "vecperm")])
2274
2275(define_insn "altivec_vupkhpx"
2276  [(set (match_operand:V4SI 0 "register_operand" "=v")
2277	(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2278		     UNSPEC_VUPKHPX))]
2279  "TARGET_ALTIVEC"
2280{
2281  if (BYTES_BIG_ENDIAN)
2282    return "vupkhpx %0,%1";
2283  else
2284    return "vupklpx %0,%1";
2285}
2286  [(set_attr "type" "vecperm")])
2287
2288(define_insn "altivec_vupklpx"
2289  [(set (match_operand:V4SI 0 "register_operand" "=v")
2290	(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2291		     UNSPEC_VUPKLPX))]
2292  "TARGET_ALTIVEC"
2293{
2294  if (BYTES_BIG_ENDIAN)
2295    return "vupklpx %0,%1";
2296  else
2297    return "vupkhpx %0,%1";
2298}
2299  [(set_attr "type" "vecperm")])
2300
2301;; Compare vectors producing a vector result and a predicate, setting CR6 to
2302;; indicate a combined status
2303(define_insn "altivec_vcmpequ<VI_char>_p"
2304  [(set (reg:CC CR6_REGNO)
2305	(unspec:CC [(eq:CC (match_operand:VI2 1 "register_operand" "v")
2306			   (match_operand:VI2 2 "register_operand" "v"))]
2307		   UNSPEC_PREDICATE))
2308   (set (match_operand:VI2 0 "register_operand" "=v")
2309	(eq:VI2 (match_dup 1)
2310		(match_dup 2)))]
2311  "<VI_unit>"
2312  "vcmpequ<VI_char>. %0,%1,%2"
2313  [(set_attr "type" "veccmpfx")])
2314
2315(define_insn "*altivec_vcmpgts<VI_char>_p"
2316  [(set (reg:CC CR6_REGNO)
2317	(unspec:CC [(gt:CC (match_operand:VI2 1 "register_operand" "v")
2318			   (match_operand:VI2 2 "register_operand" "v"))]
2319		   UNSPEC_PREDICATE))
2320   (set (match_operand:VI2 0 "register_operand" "=v")
2321	(gt:VI2 (match_dup 1)
2322		(match_dup 2)))]
2323  "<VI_unit>"
2324  "vcmpgts<VI_char>. %0,%1,%2"
2325  [(set_attr "type" "veccmpfx")])
2326
2327(define_insn "*altivec_vcmpgtu<VI_char>_p"
2328  [(set (reg:CC CR6_REGNO)
2329	(unspec:CC [(gtu:CC (match_operand:VI2 1 "register_operand" "v")
2330			    (match_operand:VI2 2 "register_operand" "v"))]
2331		   UNSPEC_PREDICATE))
2332   (set (match_operand:VI2 0 "register_operand" "=v")
2333	(gtu:VI2 (match_dup 1)
2334		 (match_dup 2)))]
2335  "<VI_unit>"
2336  "vcmpgtu<VI_char>. %0,%1,%2"
2337  [(set_attr "type" "veccmpfx")])
2338
2339(define_insn "*altivec_vcmpeqfp_p"
2340  [(set (reg:CC CR6_REGNO)
2341	(unspec:CC [(eq:CC (match_operand:V4SF 1 "register_operand" "v")
2342			   (match_operand:V4SF 2 "register_operand" "v"))]
2343		   UNSPEC_PREDICATE))
2344   (set (match_operand:V4SF 0 "register_operand" "=v")
2345	(eq:V4SF (match_dup 1)
2346		 (match_dup 2)))]
2347  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2348  "vcmpeqfp. %0,%1,%2"
2349  [(set_attr "type" "veccmp")])
2350
2351(define_insn "*altivec_vcmpgtfp_p"
2352  [(set (reg:CC CR6_REGNO)
2353	(unspec:CC [(gt:CC (match_operand:V4SF 1 "register_operand" "v")
2354			   (match_operand:V4SF 2 "register_operand" "v"))]
2355		   UNSPEC_PREDICATE))
2356   (set (match_operand:V4SF 0 "register_operand" "=v")
2357	(gt:V4SF (match_dup 1)
2358		 (match_dup 2)))]
2359  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2360  "vcmpgtfp. %0,%1,%2"
2361  [(set_attr "type" "veccmp")])
2362
2363(define_insn "*altivec_vcmpgefp_p"
2364  [(set (reg:CC CR6_REGNO)
2365	(unspec:CC [(ge:CC (match_operand:V4SF 1 "register_operand" "v")
2366			   (match_operand:V4SF 2 "register_operand" "v"))]
2367		   UNSPEC_PREDICATE))
2368   (set (match_operand:V4SF 0 "register_operand" "=v")
2369	(ge:V4SF (match_dup 1)
2370		 (match_dup 2)))]
2371  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2372  "vcmpgefp. %0,%1,%2"
2373  [(set_attr "type" "veccmp")])
2374
2375(define_insn "altivec_vcmpbfp_p"
2376  [(set (reg:CC CR6_REGNO)
2377	(unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
2378		    (match_operand:V4SF 2 "register_operand" "v")]
2379		   UNSPEC_VCMPBFP))
2380   (set (match_operand:V4SF 0 "register_operand" "=v")
2381        (unspec:V4SF [(match_dup 1)
2382                      (match_dup 2)]
2383                      UNSPEC_VCMPBFP))]
2384  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
2385  "vcmpbfp. %0,%1,%2"
2386  [(set_attr "type" "veccmp")])
2387
2388(define_insn "altivec_mtvscr"
2389  [(set (reg:SI VSCR_REGNO)
2390	(unspec_volatile:SI
2391	 [(match_operand:V4SI 0 "register_operand" "v")] UNSPECV_MTVSCR))]
2392  "TARGET_ALTIVEC"
2393  "mtvscr %0"
2394  [(set_attr "type" "vecsimple")])
2395
2396(define_insn "altivec_mfvscr"
2397  [(set (match_operand:V8HI 0 "register_operand" "=v")
2398	(unspec_volatile:V8HI [(reg:SI VSCR_REGNO)] UNSPECV_MFVSCR))]
2399  "TARGET_ALTIVEC"
2400  "mfvscr %0"
2401  [(set_attr "type" "vecsimple")])
2402
2403(define_insn "altivec_dssall"
2404  [(unspec_volatile [(const_int 0)] UNSPECV_DSSALL)]
2405  "TARGET_ALTIVEC"
2406  "dssall"
2407  [(set_attr "type" "vecsimple")])
2408
2409(define_insn "altivec_dss"
2410  [(unspec_volatile [(match_operand:QI 0 "immediate_operand" "i")]
2411		    UNSPECV_DSS)]
2412  "TARGET_ALTIVEC"
2413  "dss %0"
2414  [(set_attr "type" "vecsimple")])
2415
2416(define_insn "altivec_dst"
2417  [(unspec [(match_operand 0 "register_operand" "b")
2418	    (match_operand:SI 1 "register_operand" "r")
2419	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DST)]
2420  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2421  "dst %0,%1,%2"
2422  [(set_attr "type" "vecsimple")])
2423
2424(define_insn "altivec_dstt"
2425  [(unspec [(match_operand 0 "register_operand" "b")
2426	    (match_operand:SI 1 "register_operand" "r")
2427	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTT)]
2428  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2429  "dstt %0,%1,%2"
2430  [(set_attr "type" "vecsimple")])
2431
2432(define_insn "altivec_dstst"
2433  [(unspec [(match_operand 0 "register_operand" "b")
2434	    (match_operand:SI 1 "register_operand" "r")
2435	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTST)]
2436  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2437  "dstst %0,%1,%2"
2438  [(set_attr "type" "vecsimple")])
2439
2440(define_insn "altivec_dststt"
2441  [(unspec [(match_operand 0 "register_operand" "b")
2442	    (match_operand:SI 1 "register_operand" "r")
2443	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTSTT)]
2444  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2445  "dststt %0,%1,%2"
2446  [(set_attr "type" "vecsimple")])
2447
2448(define_expand "altivec_lvsl"
2449  [(use (match_operand:V16QI 0 "register_operand"))
2450   (use (match_operand:V16QI 1 "memory_operand"))]
2451  "TARGET_ALTIVEC"
2452{
2453  if (BYTES_BIG_ENDIAN)
2454    emit_insn (gen_altivec_lvsl_direct (operands[0], operands[1]));
2455  else
2456    {
2457      rtx mask, constv, vperm;
2458      mask = gen_reg_rtx (V16QImode);
2459      emit_insn (gen_altivec_lvsl_direct (mask, operands[1]));
2460      constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
2461      constv = force_reg (V16QImode, constv);
2462      vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2463                              UNSPEC_VPERM);
2464      emit_insn (gen_rtx_SET (operands[0], vperm));
2465    }
2466  DONE;
2467})
2468
2469(define_insn "altivec_lvsl_reg"
2470  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
2471	(unspec:V16QI
2472	[(match_operand:DI 1 "gpc_reg_operand" "b")]
2473	UNSPEC_LVSL_REG))]
2474  "TARGET_ALTIVEC"
2475  "lvsl %0,0,%1"
2476  [(set_attr "type" "vecload")])
2477
2478(define_insn "altivec_lvsl_direct"
2479  [(set (match_operand:V16QI 0 "register_operand" "=v")
2480	(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2481		      UNSPEC_LVSL))]
2482  "TARGET_ALTIVEC"
2483  "lvsl %0,%y1"
2484  [(set_attr "type" "vecload")])
2485
2486(define_expand "altivec_lvsr"
2487  [(use (match_operand:V16QI 0 "altivec_register_operand"))
2488   (use (match_operand:V16QI 1 "memory_operand"))]
2489  "TARGET_ALTIVEC"
2490{
2491  if (BYTES_BIG_ENDIAN)
2492    emit_insn (gen_altivec_lvsr_direct (operands[0], operands[1]));
2493  else
2494    {
2495      rtx mask, constv, vperm;
2496      mask = gen_reg_rtx (V16QImode);
2497      emit_insn (gen_altivec_lvsr_direct (mask, operands[1]));
2498      constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
2499      constv = force_reg (V16QImode, constv);
2500      vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2501                              UNSPEC_VPERM);
2502      emit_insn (gen_rtx_SET (operands[0], vperm));
2503    }
2504  DONE;
2505})
2506
2507(define_insn "altivec_lvsr_reg"
2508  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
2509       (unspec:V16QI
2510       [(match_operand:DI 1 "gpc_reg_operand" "b")]
2511       UNSPEC_LVSR_REG))]
2512  "TARGET_ALTIVEC"
2513  "lvsr %0,0,%1"
2514  [(set_attr "type" "vecload")])
2515
2516(define_insn "altivec_lvsr_direct"
2517  [(set (match_operand:V16QI 0 "register_operand" "=v")
2518	(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2519		      UNSPEC_LVSR))]
2520  "TARGET_ALTIVEC"
2521  "lvsr %0,%y1"
2522  [(set_attr "type" "vecload")])
2523
2524(define_expand "build_vector_mask_for_load"
2525  [(set (match_operand:V16QI 0 "register_operand")
2526	(unspec:V16QI [(match_operand 1 "memory_operand")] UNSPEC_LVSR))]
2527  "TARGET_ALTIVEC"
2528{
2529  rtx addr;
2530  rtx temp;
2531
2532  gcc_assert (MEM_P (operands[1]));
2533
2534  addr = XEXP (operands[1], 0);
2535  temp = gen_reg_rtx (GET_MODE (addr));
2536  emit_insn (gen_rtx_SET (temp, gen_rtx_NEG (GET_MODE (addr), addr)));
2537  emit_insn (gen_altivec_lvsr (operands[0],
2538			       replace_equiv_address (operands[1], temp)));
2539  DONE;
2540})
2541
2542;; Parallel some of the LVE* and STV*'s with unspecs because some have
2543;; identical rtl but different instructions-- and gcc gets confused.
2544
2545(define_insn "altivec_lve<VI_char>x"
2546  [(parallel
2547    [(set (match_operand:VI 0 "register_operand" "=v")
2548	  (match_operand:VI 1 "memory_operand" "Z"))
2549     (unspec [(const_int 0)] UNSPEC_LVE)])]
2550  "TARGET_ALTIVEC"
2551  "lve<VI_char>x %0,%y1"
2552  [(set_attr "type" "vecload")])
2553
2554(define_insn "*altivec_lvesfx"
2555  [(parallel
2556    [(set (match_operand:V4SF 0 "register_operand" "=v")
2557	  (match_operand:V4SF 1 "memory_operand" "Z"))
2558     (unspec [(const_int 0)] UNSPEC_LVE)])]
2559  "TARGET_ALTIVEC"
2560  "lvewx %0,%y1"
2561  [(set_attr "type" "vecload")])
2562
2563(define_insn "altivec_lvxl_<mode>"
2564  [(parallel
2565    [(set (match_operand:VM2 0 "register_operand" "=v")
2566	  (match_operand:VM2 1 "memory_operand" "Z"))
2567     (unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
2568  "TARGET_ALTIVEC"
2569  "lvxl %0,%y1"
2570  [(set_attr "type" "vecload")])
2571
2572; This version of lvx is used only in cases where we need to force an lvx
2573; over any other load, and we don't care about losing CSE opportunities.
2574; Its primary use is for prologue register saves.
2575(define_insn "altivec_lvx_<mode>_internal"
2576  [(parallel
2577    [(set (match_operand:VM2 0 "register_operand" "=v")
2578	  (match_operand:VM2 1 "memory_operand" "Z"))
2579     (unspec [(const_int 0)] UNSPEC_LVX)])]
2580  "TARGET_ALTIVEC"
2581  "lvx %0,%y1"
2582  [(set_attr "type" "vecload")])
2583
2584; The following patterns embody what lvx should usually look like.
2585(define_expand "altivec_lvx_<VM2:mode>"
2586  [(set (match_operand:VM2 0 "register_operand")
2587	(match_operand:VM2 1 "altivec_indexed_or_indirect_operand"))]
2588  "TARGET_ALTIVEC"
2589{
2590  rtx addr = XEXP (operand1, 0);
2591  if (rs6000_sum_of_two_registers_p (addr))
2592    {
2593      rtx op1 = XEXP (addr, 0);
2594      rtx op2 = XEXP (addr, 1);
2595      if (TARGET_64BIT)
2596	emit_insn (gen_altivec_lvx_<VM2:mode>_2op_di (operand0, op1, op2));
2597      else
2598	emit_insn (gen_altivec_lvx_<VM2:mode>_2op_si (operand0, op1, op2));
2599    }
2600  else
2601    {
2602      if (TARGET_64BIT)
2603	emit_insn (gen_altivec_lvx_<VM2:mode>_1op_di (operand0, addr));
2604      else
2605	emit_insn (gen_altivec_lvx_<VM2:mode>_1op_si (operand0, addr));
2606    }
2607  DONE;
2608})
2609
2610; The next two patterns embody what lvx should usually look like.
2611(define_insn "altivec_lvx_<VM2:mode>_2op_<P:mptrsize>"
2612  [(set (match_operand:VM2 0 "register_operand" "=v")
2613	(mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
2614				(match_operand:P 2 "register_operand" "r"))
2615			(const_int -16))))]
2616  "TARGET_ALTIVEC"
2617  "lvx %0,%1,%2"
2618  [(set_attr "type" "vecload")])
2619
2620(define_insn "altivec_lvx_<VM2:mode>_1op_<P:mptrsize>"
2621  [(set (match_operand:VM2 0 "register_operand" "=v")
2622	(mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
2623			(const_int -16))))]
2624  "TARGET_ALTIVEC"
2625  "lvx %0,0,%1"
2626  [(set_attr "type" "vecload")])
2627
2628; This version of stvx is used only in cases where we need to force an stvx
2629; over any other store, and we don't care about losing CSE opportunities.
2630; Its primary use is for epilogue register restores.
2631(define_insn "altivec_stvx_<mode>_internal"
2632  [(parallel
2633    [(set (match_operand:VM2 0 "memory_operand" "=Z")
2634	  (match_operand:VM2 1 "register_operand" "v"))
2635     (unspec [(const_int 0)] UNSPEC_STVX)])]
2636  "TARGET_ALTIVEC"
2637  "stvx %1,%y0"
2638  [(set_attr "type" "vecstore")])
2639
2640; The following patterns embody what stvx should usually look like.
2641(define_expand "altivec_stvx_<VM2:mode>"
2642  [(set (match_operand:VM2 1 "altivec_indexed_or_indirect_operand")
2643	(match_operand:VM2 0 "register_operand"))]
2644  "TARGET_ALTIVEC"
2645{
2646  rtx addr = XEXP (operand1, 0);
2647  if (rs6000_sum_of_two_registers_p (addr))
2648    {
2649      rtx op1 = XEXP (addr, 0);
2650      rtx op2 = XEXP (addr, 1);
2651      if (TARGET_64BIT)
2652	emit_insn (gen_altivec_stvx_<VM2:mode>_2op_di (operand0, op1, op2));
2653      else
2654	emit_insn (gen_altivec_stvx_<VM2:mode>_2op_si (operand0, op1, op2));
2655    }
2656  else
2657    {
2658      if (TARGET_64BIT)
2659	emit_insn (gen_altivec_stvx_<VM2:mode>_1op_di (operand0, addr));
2660      else
2661	emit_insn (gen_altivec_stvx_<VM2:mode>_1op_si (operand0, addr));
2662    }
2663  DONE;
2664})
2665
2666; The next two patterns embody what stvx should usually look like.
2667(define_insn "altivec_stvx_<VM2:mode>_2op_<P:mptrsize>"
2668  [(set (mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
2669				(match_operand:P 2 "register_operand" "r"))
2670			(const_int -16)))
2671	(match_operand:VM2 0 "register_operand" "v"))]
2672  "TARGET_ALTIVEC"
2673  "stvx %0,%1,%2"
2674  [(set_attr "type" "vecstore")])
2675
2676(define_insn "altivec_stvx_<VM2:mode>_1op_<P:mptrsize>"
2677  [(set (mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
2678			(const_int -16)))
2679	(match_operand:VM2 0 "register_operand" "v"))]
2680  "TARGET_ALTIVEC"
2681  "stvx %0,0,%1"
2682  [(set_attr "type" "vecstore")])
2683
2684(define_insn "altivec_stvxl_<mode>"
2685  [(parallel
2686    [(set (match_operand:VM2 0 "memory_operand" "=Z")
2687	  (match_operand:VM2 1 "register_operand" "v"))
2688     (unspec [(const_int 0)] UNSPEC_STVXL)])]
2689  "TARGET_ALTIVEC"
2690  "stvxl %1,%y0"
2691  [(set_attr "type" "vecstore")])
2692
2693(define_insn "altivec_stve<VI_char>x"
2694  [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
2695	(unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
2696  "TARGET_ALTIVEC"
2697  "stve<VI_char>x %1,%y0"
2698  [(set_attr "type" "vecstore")])
2699
2700(define_insn "*altivec_stvesfx"
2701  [(set (match_operand:SF 0 "memory_operand" "=Z")
2702	(unspec:SF [(match_operand:V4SF 1 "register_operand" "v")] UNSPEC_STVE))]
2703  "TARGET_ALTIVEC"
2704  "stvewx %1,%y0"
2705  [(set_attr "type" "vecstore")])
2706
2707;; Generate doublee
2708;; signed int/float to double convert words 0 and 2
2709(define_expand "doublee<mode>2"
2710  [(set (match_operand:V2DF 0 "register_operand" "=v")
2711	(match_operand:VSX_W 1 "register_operand" "v"))]
2712  "TARGET_VSX"
2713{
2714  machine_mode op_mode = GET_MODE (operands[1]);
2715
2716  if (BYTES_BIG_ENDIAN)
2717    {
2718      /* Big endian word numbering for words in operand is 0 1 2 3.
2719	 Input words 0 and 2 are where they need to be.  */
2720      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], operands[1]));
2721    }
2722  else
2723    {
2724      /* Little endian word numbering for operand is 3 2 1 0.
2725	 take (operand[1] operand[1]) and shift left one word
2726	 3 2 1 0    3 2 1 0  =>  2 1 0 3
2727	 Input words 2 and 0 are now where they need to be for the
2728	 conversion.  */
2729      rtx rtx_tmp;
2730      rtx rtx_val = GEN_INT (1);
2731
2732      rtx_tmp = gen_reg_rtx (op_mode);
2733      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2734					 operands[1], rtx_val));
2735      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2736    }
2737  DONE;
2738}
2739  [(set_attr "type" "veccomplex")])
2740
2741;; Generate unsdoublee
2742;; unsigned int to double convert words 0 and 2
2743(define_expand "unsdoubleev4si2"
2744  [(set (match_operand:V2DF 0 "register_operand" "=v")
2745	(match_operand:V4SI 1 "register_operand" "v"))]
2746  "TARGET_VSX"
2747{
2748  if (BYTES_BIG_ENDIAN)
2749    {
2750      /* Big endian word numbering for words in operand is 0 1 2 3.
2751	 Input words 0 and 2 are where they need to be.  */
2752      emit_insn (gen_vsx_xvcvuxwdp (operands[0], operands[1]));
2753    }
2754  else
2755    {
2756      /* Little endian word numbering for operand is 3 2 1 0.
2757	 take (operand[1] operand[1]) and shift left one word
2758	 3 2 1 0    3 2 1 0  =>   2 1 0 3
2759	 Input words 2 and 0 are now where they need to be for the
2760	 conversion.  */
2761      rtx rtx_tmp;
2762      rtx rtx_val = GEN_INT (1);
2763
2764      rtx_tmp = gen_reg_rtx (V4SImode);
2765      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2766				       operands[1], rtx_val));
2767      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2768    }
2769  DONE;
2770}
2771  [(set_attr "type" "veccomplex")])
2772
2773;; Generate doubleov
2774;; signed int/float to double convert words 1 and 3
2775(define_expand "doubleo<mode>2"
2776  [(set (match_operand:V2DF 0 "register_operand" "=v")
2777	(match_operand:VSX_W 1 "register_operand" "v"))]
2778  "TARGET_VSX"
2779{
2780  machine_mode op_mode = GET_MODE (operands[1]);
2781
2782  if (BYTES_BIG_ENDIAN)
2783    {
2784      /* Big endian word numbering for words in operand is 0 1 2 3.
2785	 take (operand[1] operand[1]) and shift left one word
2786	 0 1 2 3    0 1 2 3  =>  1 2 3 0
2787	 Input words 1 and 3 are now where they need to be for the
2788	 conversion.  */
2789      rtx rtx_tmp;
2790      rtx rtx_val = GEN_INT (1);
2791
2792      rtx_tmp = gen_reg_rtx (op_mode);
2793      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2794					 operands[1], rtx_val));
2795      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2796    }
2797  else
2798    {
2799      /* Little endian word numbering for operand is 3 2 1 0.
2800	 Input words 3 and 1 are where they need to be.  */
2801      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], operands[1]));
2802    }
2803  DONE;
2804}
2805  [(set_attr "type" "veccomplex")])
2806
2807;; Generate unsdoubleov
2808;; unsigned int to double convert words 1 and 3
2809(define_expand "unsdoubleov4si2"
2810  [(set (match_operand:V2DF 0 "register_operand" "=v")
2811	(match_operand:V4SI 1 "register_operand" "v"))]
2812  "TARGET_VSX"
2813{
2814  if (BYTES_BIG_ENDIAN)
2815    {
2816      /* Big endian word numbering for words in operand is 0 1 2 3.
2817	 take (operand[1] operand[1]) and shift left one word
2818	 0 1 2 3    0 1 2 3  =>  1 2 3 0
2819	 Input words 1 and 3 are now where they need to be for the
2820	 conversion.  */
2821      rtx rtx_tmp;
2822      rtx rtx_val = GEN_INT (1);
2823
2824      rtx_tmp = gen_reg_rtx (V4SImode);
2825      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2826				       operands[1], rtx_val));
2827      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2828    }
2829  else
2830    {
2831      /* Want to convert the words 1 and 3.
2832	 Little endian word numbering for operand is 3 2 1 0.
2833	 Input words 3 and 1 are where they need to be.  */
2834      emit_insn (gen_vsx_xvcvuxwdp (operands[0], operands[1]));
2835    }
2836  DONE;
2837}
2838  [(set_attr "type" "veccomplex")])
2839
2840;; Generate doublehv
2841;; signed int/float to double convert words 0 and 1
2842(define_expand "doubleh<mode>2"
2843  [(set (match_operand:V2DF 0 "register_operand" "=v")
2844	(match_operand:VSX_W 1 "register_operand" "v"))]
2845  "TARGET_VSX"
2846{
2847  rtx rtx_tmp;
2848  rtx rtx_val;
2849
2850  machine_mode op_mode = GET_MODE (operands[1]);
2851  rtx_tmp = gen_reg_rtx (op_mode);
2852
2853  if (BYTES_BIG_ENDIAN)
2854    {
2855      /* Big endian word numbering for words in operand is 0 1 2 3.
2856	 Shift operand left one word, rtx_tmp word order is now 1 2 3 0.
2857	 take (rts_tmp operand[1]) and shift left three words
2858	 1 2 3 0  0 1 2 3 => 0 0 1 2
2859	 Input words 0 and 1 are now where they need to be for the
2860	 conversion.  */
2861      rtx_val = GEN_INT (1);
2862      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2863					 operands[1], rtx_val));
2864
2865      rtx_val = GEN_INT (3);
2866      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, rtx_tmp,
2867					 operands[1], rtx_val));
2868      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2869    }
2870  else
2871    {
2872      /* Little endian word numbering for operand is 3 2 1 0.
2873	 Shift operand left three words, rtx_tmp word order is now 0 3 2 1.
2874	 take (operand[1] rts_tmp) and shift left two words
2875	 3 2 1 0  0 3 2 1   =>  1 0 0 3
2876	 Input words 0 and 1 are now where they need to be for the
2877	 conversion.  */
2878      rtx_val = GEN_INT (3);
2879      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2880					 operands[1], rtx_val));
2881
2882      rtx_val = GEN_INT (2);
2883      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2884					 rtx_tmp, rtx_val));
2885      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2886    }
2887  DONE;
2888}
2889  [(set_attr "type" "veccomplex")])
2890
2891;; Generate unsdoublehv
2892;; unsigned int to double convert words 0 and 1
2893(define_expand "unsdoublehv4si2"
2894  [(set (match_operand:V2DF 0 "register_operand" "=v")
2895	(match_operand:V4SI 1 "register_operand" "v"))]
2896  "TARGET_VSX"
2897{
2898  rtx rtx_tmp = gen_reg_rtx (V4SImode);
2899  rtx rtx_val = GEN_INT (12);
2900
2901  if (BYTES_BIG_ENDIAN)
2902    {
2903      /* Big endian word numbering for words in operand is 0 1 2 3.
2904	 Shift operand left one word, rtx_tmp word order is now 1 2 3 0.
2905	 take (rts_tmp operand[1]) and shift left three words
2906	 1 2 3 0  0 1 2 3 => 0 0 1 2
2907	 Input words 0 and 1 are now where they need to be for the
2908	 conversion.  */
2909      rtx_val = GEN_INT (1);
2910      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2911				       operands[1], rtx_val));
2912
2913      rtx_val = GEN_INT (3);
2914      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, rtx_tmp,
2915				       operands[1], rtx_val));
2916      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2917    }
2918  else
2919    {
2920      /* Little endian word numbering for operand is 3 2 1 0.
2921	 Shift operand left three words, rtx_tmp word order is now 0 3 2 1.
2922	 take (operand[1] rts_tmp) and shift left two words
2923	 3 2 1 0   0 3 2 1  =>   1 0 0 3
2924	 Input words 1 and 0 are now where they need to be for the
2925	 conversion.  */
2926      rtx_val = GEN_INT (3);
2927
2928      rtx_tmp = gen_reg_rtx (V4SImode);
2929      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2930				       operands[1], rtx_val));
2931
2932      rtx_val = GEN_INT (2);
2933      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2934				       rtx_tmp, rtx_val));
2935      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2936    }
2937  DONE;
2938}
2939  [(set_attr "type" "veccomplex")])
2940
2941;; Generate doublelv
2942;; signed int/float to double convert words 2 and 3
2943(define_expand "doublel<mode>2"
2944  [(set (match_operand:V2DF 0 "register_operand" "=v")
2945	(match_operand:VSX_W 1 "register_operand" "v"))]
2946  "TARGET_VSX"
2947{
2948  rtx rtx_tmp;
2949  rtx rtx_val = GEN_INT (3);
2950
2951  machine_mode op_mode = GET_MODE (operands[1]);
2952  rtx_tmp = gen_reg_rtx (op_mode);
2953
2954  if (BYTES_BIG_ENDIAN)
2955    {
2956      /* Big endian word numbering for operand is 0 1 2 3.
2957	 Shift operand left three words, rtx_tmp word order is now 3 0 1 2.
2958	 take (operand[1] rtx_tmp) and shift left two words
2959	 0 1 2 3   3 0 1 2  =>  2 3 3 0
2960	 now use convert instruction to convert word 2 and 3 in the
2961	 input vector.  */
2962      rtx_val = GEN_INT (3);
2963      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2964					 operands[1], rtx_val));
2965
2966      rtx_val = GEN_INT (2);
2967      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2968					 rtx_tmp, rtx_val));
2969      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2970    }
2971  else
2972    {
2973      /* Little endian word numbering for operand is 3 2 1 0.
2974	 Shift operand left one word, rtx_tmp word order is now  2 1 0 3.
2975	 take (rtx_tmp operand[1]) and shift left three words
2976	 2 1 0 3  3 2 1 0  =>  3 3 2 1
2977	 now use convert instruction to convert word 3 and 2 in the
2978	 input vector.  */
2979      rtx_val = GEN_INT (1);
2980      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2981					 operands[1], rtx_val));
2982
2983      rtx_val = GEN_INT (3);
2984      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, rtx_tmp,
2985					 operands[1], rtx_val));
2986      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2987    }
2988  DONE;
2989}
2990  [(set_attr "type" "veccomplex")])
2991
2992;; Generate unsdoublelv
2993;; unsigned int to double convert convert 2 and 3
2994(define_expand "unsdoublelv4si2"
2995  [(set (match_operand:V2DF 0 "register_operand" "=v")
2996	(match_operand:V4SI 1 "register_operand" "v"))]
2997  "TARGET_VSX"
2998{
2999  rtx rtx_tmp = gen_reg_rtx (V4SImode);
3000  rtx rtx_val = GEN_INT (12);
3001
3002  if (BYTES_BIG_ENDIAN)
3003    {
3004      /* Big endian word numbering for operand is 0 1 2 3.
3005	 Shift operand left three words, rtx_tmp word order is now 3 0 1 2.
3006	 take (operand[1] rtx_tmp) and shift left two words
3007	 0 1 2 3   3 0 1 2  =>  2 3 3 0
3008	 now use convert instruction to convert word 2 and 3 in the
3009	 input vector.  */
3010      rtx_val = GEN_INT (3);
3011      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
3012				       operands[1], rtx_val));
3013
3014      rtx_val = GEN_INT (2);
3015      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
3016				       rtx_tmp, rtx_val));
3017      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
3018    }
3019  else
3020    {
3021      /* Little endian word numbering for operand is 3 2 1 0.
3022	 Shift operand left one word, rtx_tmp word order is now 2 1 0 3.
3023	 take (rtx_tmp operand[1]) and shift left three words
3024	 2 1 0 3  3 2 1 0  =>   3 3 2 1
3025	 now use convert instruction to convert word 3 and 2 in the
3026	 input vector.  */
3027      rtx_val = GEN_INT (1);
3028      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp,
3029      operands[1], operands[1], rtx_val));
3030
3031      rtx_val = GEN_INT (3);
3032      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, rtx_tmp,
3033				       operands[1], rtx_val));
3034      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
3035    }
3036  DONE;
3037}
3038  [(set_attr "type" "veccomplex")])
3039
3040;; Generate two vector F32 converted to packed vector I16 vector
3041(define_expand "convert_4f32_8i16"
3042  [(set (match_operand:V8HI 0 "register_operand" "=v")
3043	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "v")
3044		      (match_operand:V4SF 2 "register_operand" "v")]
3045		     UNSPEC_CONVERT_4F32_8I16))]
3046  "TARGET_P9_VECTOR"
3047{
3048  rtx rtx_tmp_hi = gen_reg_rtx (V4SImode);
3049  rtx rtx_tmp_lo = gen_reg_rtx (V4SImode);
3050
3051  emit_insn (gen_altivec_vctuxs (rtx_tmp_hi, operands[1], const0_rtx));
3052  emit_insn (gen_altivec_vctuxs (rtx_tmp_lo, operands[2], const0_rtx));
3053  emit_insn (gen_altivec_vpkswss (operands[0], rtx_tmp_hi, rtx_tmp_lo));
3054  DONE;
3055})
3056
3057;; Convert two vector F32 to packed vector F16.
3058;; This builtin packs 32-bit floating-point values into a packed
3059;; 16-bit floating point values (stored in 16bit integer type).
3060;; (vector unsigned short r = vec_pack_to_short_fp32 (a, b);
3061;; The expected codegen for this builtin is
3062;;    xvcvsphp t, a
3063;;    xvcvsphp u, b
3064;;    if (little endian)
3065;;      vpkuwum r, t, u
3066;;    else
3067;;      vpkuwum r, u, t
3068
3069(define_expand "convert_4f32_8f16"
3070  [(set (match_operand:V8HI 0 "register_operand" "=v")
3071	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "v")
3072		      (match_operand:V4SF 2 "register_operand" "v")]
3073		     UNSPEC_CONVERT_4F32_8F16))]
3074  "TARGET_P9_VECTOR"
3075{
3076  rtx rtx_tmp_hi = gen_reg_rtx (V4SImode);
3077  rtx rtx_tmp_lo = gen_reg_rtx (V4SImode);
3078
3079  emit_insn (gen_vsx_xvcvsphp (rtx_tmp_hi, operands[1]));
3080  emit_insn (gen_vsx_xvcvsphp (rtx_tmp_lo, operands[2]));
3081  if (!BYTES_BIG_ENDIAN)
3082    emit_insn (gen_altivec_vpkuwum (operands[0], rtx_tmp_hi, rtx_tmp_lo));
3083  else
3084    emit_insn (gen_altivec_vpkuwum (operands[0], rtx_tmp_lo, rtx_tmp_hi));
3085  DONE;
3086})
3087
3088;; Generate
3089;;    xxlxor/vxor SCRATCH0,SCRATCH0,SCRATCH0
3090;;    vsubu?m SCRATCH2,SCRATCH1,%1
3091;;    vmaxs? %0,%1,SCRATCH2"
3092(define_expand "abs<mode>2"
3093  [(set (match_dup 2) (match_dup 3))
3094   (set (match_dup 4)
3095        (minus:VI2 (match_dup 2)
3096		   (match_operand:VI2 1 "register_operand" "v")))
3097   (set (match_operand:VI2 0 "register_operand" "=v")
3098        (smax:VI2 (match_dup 1) (match_dup 4)))]
3099  "<VI_unit>"
3100{
3101  operands[2] = gen_reg_rtx (<MODE>mode);
3102  operands[3] = CONST0_RTX (<MODE>mode);
3103  operands[4] = gen_reg_rtx (<MODE>mode);
3104})
3105
3106;; Generate
3107;;    vspltisw SCRATCH1,0
3108;;    vsubu?m SCRATCH2,SCRATCH1,%1
3109;;    vmins? %0,%1,SCRATCH2"
3110(define_expand "nabs<mode>2"
3111  [(set (match_dup 2) (match_dup 3))
3112   (set (match_dup 4)
3113        (minus:VI2 (match_dup 2)
3114		   (match_operand:VI2 1 "register_operand" "v")))
3115   (set (match_operand:VI2 0 "register_operand" "=v")
3116        (smin:VI2 (match_dup 1) (match_dup 4)))]
3117  "<VI_unit>"
3118{
3119  operands[2] = gen_reg_rtx (<MODE>mode);
3120  operands[3] = CONST0_RTX (<MODE>mode);
3121  operands[4] = gen_reg_rtx (<MODE>mode);
3122})
3123
3124;; Generate
3125;;    vspltisw SCRATCH1,-1
3126;;    vslw SCRATCH2,SCRATCH1,SCRATCH1
3127;;    vandc %0,%1,SCRATCH2
3128(define_expand "altivec_absv4sf2"
3129  [(set (match_dup 2)
3130	(vec_duplicate:V4SI (const_int -1)))
3131   (set (match_dup 3)
3132        (ashift:V4SI (match_dup 2) (match_dup 2)))
3133   (set (match_operand:V4SF 0 "register_operand" "=v")
3134        (and:V4SF (not:V4SF (subreg:V4SF (match_dup 3) 0))
3135                  (match_operand:V4SF 1 "register_operand" "v")))]
3136  "TARGET_ALTIVEC"
3137{
3138  operands[2] = gen_reg_rtx (V4SImode);
3139  operands[3] = gen_reg_rtx (V4SImode);
3140})
3141
3142;; Generate
3143;;    vspltis? SCRATCH0,0
3144;;    vsubs?s SCRATCH2,SCRATCH1,%1
3145;;    vmaxs? %0,%1,SCRATCH2"
3146(define_expand "altivec_abss_<mode>"
3147  [(set (match_dup 2) (vec_duplicate:VI (const_int 0)))
3148   (parallel [(set (match_dup 3)
3149		   (unspec:VI [(match_dup 2)
3150			       (match_operand:VI 1 "register_operand" "v")]
3151			      UNSPEC_VSUBS))
3152	      (set (reg:SI VSCR_REGNO)
3153		   (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))])
3154   (set (match_operand:VI 0 "register_operand" "=v")
3155        (smax:VI (match_dup 1) (match_dup 3)))]
3156  "TARGET_ALTIVEC"
3157{
3158  operands[2] = gen_reg_rtx (GET_MODE (operands[0]));
3159  operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
3160})
3161
3162(define_expand "reduc_plus_scal_<mode>"
3163  [(set (match_operand:<VI_scalar> 0 "register_operand" "=v")
3164        (unspec:VIshort [(match_operand:VIshort 1 "register_operand" "v")]
3165			UNSPEC_REDUC_PLUS))]
3166  "TARGET_ALTIVEC"
3167{
3168  rtx vzero = gen_reg_rtx (V4SImode);
3169  rtx vtmp1 = gen_reg_rtx (V4SImode);
3170  rtx vtmp2 = gen_reg_rtx (<MODE>mode);
3171  rtx dest = gen_lowpart (V4SImode, vtmp2);
3172  int elt = BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (<MODE>mode) - 1 : 0;
3173
3174  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3175  emit_insn (gen_altivec_vsum4s<VI_char>s (vtmp1, operands[1], vzero));
3176  emit_insn (gen_altivec_vsumsws_direct (dest, vtmp1, vzero));
3177  rs6000_expand_vector_extract (operands[0], vtmp2, GEN_INT (elt));
3178  DONE;
3179})
3180
3181(define_insn "*p9_neg<mode>2"
3182  [(set (match_operand:VNEG 0 "altivec_register_operand" "=v")
3183	(neg:VNEG (match_operand:VNEG 1 "altivec_register_operand" "v")))]
3184  "TARGET_P9_VECTOR"
3185  "vneg<VI_char> %0,%1"
3186  [(set_attr "type" "vecsimple")])
3187
3188(define_expand "neg<mode>2"
3189  [(set (match_operand:VI2 0 "register_operand")
3190	(neg:VI2 (match_operand:VI2 1 "register_operand")))]
3191  "<VI_unit>"
3192{
3193  if (!TARGET_P9_VECTOR || (<MODE>mode != V4SImode && <MODE>mode != V2DImode))
3194    {
3195      rtx vzero;
3196
3197      vzero = gen_reg_rtx (GET_MODE (operands[0]));
3198      emit_move_insn (vzero, CONST0_RTX (<MODE>mode));
3199      emit_insn (gen_sub<mode>3 (operands[0], vzero, operands[1]));
3200      DONE;
3201    }
3202})
3203
3204(define_expand "udot_prod<mode>"
3205  [(set (match_operand:V4SI 0 "register_operand" "=v")
3206        (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
3207                   (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
3208                                 (match_operand:VIshort 2 "register_operand" "v")]
3209                                UNSPEC_VMSUMU)))]
3210  "TARGET_ALTIVEC"
3211{
3212  emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], operands[2], operands[3]));
3213  DONE;
3214})
3215
3216(define_expand "sdot_prodv8hi"
3217  [(set (match_operand:V4SI 0 "register_operand" "=v")
3218        (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
3219                   (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3220                                 (match_operand:V8HI 2 "register_operand" "v")]
3221                                UNSPEC_VMSUMSHM)))]
3222  "TARGET_ALTIVEC"
3223{
3224  emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], operands[2], operands[3]));
3225  DONE;
3226})
3227
3228(define_expand "widen_usum<mode>3"
3229  [(set (match_operand:V4SI 0 "register_operand" "=v")
3230        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3231                   (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")]
3232                                UNSPEC_VMSUMU)))]
3233  "TARGET_ALTIVEC"
3234{
3235  rtx vones = gen_reg_rtx (GET_MODE (operands[1]));
3236
3237  emit_insn (gen_altivec_vspltis<VI_char> (vones, const1_rtx));
3238  emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], vones, operands[2]));
3239  DONE;
3240})
3241
3242(define_expand "widen_ssumv16qi3"
3243  [(set (match_operand:V4SI 0 "register_operand" "=v")
3244        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3245                   (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")]
3246                                UNSPEC_VMSUMM)))]
3247  "TARGET_ALTIVEC"
3248{
3249  rtx vones = gen_reg_rtx (V16QImode);
3250
3251  emit_insn (gen_altivec_vspltisb (vones, const1_rtx));
3252  emit_insn (gen_altivec_vmsummbm (operands[0], operands[1], vones, operands[2]));
3253  DONE;
3254})
3255
3256(define_expand "widen_ssumv8hi3"
3257  [(set (match_operand:V4SI 0 "register_operand" "=v")
3258        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3259                   (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3260                                UNSPEC_VMSUMSHM)))]
3261  "TARGET_ALTIVEC"
3262{
3263  rtx vones = gen_reg_rtx (V8HImode);
3264
3265  emit_insn (gen_altivec_vspltish (vones, const1_rtx));
3266  emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], vones, operands[2]));
3267  DONE;
3268})
3269
3270(define_expand "vec_unpacks_hi_<VP_small_lc>"
3271  [(set (match_operand:VP 0 "register_operand" "=v")
3272        (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
3273		   UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
3274  "<VI_unit>"
3275  "")
3276
3277(define_expand "vec_unpacks_lo_<VP_small_lc>"
3278  [(set (match_operand:VP 0 "register_operand" "=v")
3279        (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
3280		   UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
3281  "<VI_unit>"
3282  "")
3283
3284(define_insn "vperm_v8hiv4si"
3285  [(set (match_operand:V4SI 0 "register_operand" "=v,?wo")
3286        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v,wo")
3287		      (match_operand:V4SI 2 "register_operand" "v,0")
3288		      (match_operand:V16QI 3 "register_operand" "v,wo")]
3289                  UNSPEC_VPERMSI))]
3290  "TARGET_ALTIVEC"
3291  "@
3292   vperm %0,%1,%2,%3
3293   xxperm %x0,%x1,%x3"
3294  [(set_attr "type" "vecperm")])
3295
3296(define_insn "vperm_v16qiv8hi"
3297  [(set (match_operand:V8HI 0 "register_operand" "=v,?wo")
3298        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v,wo")
3299		      (match_operand:V8HI 2 "register_operand" "v,0")
3300		      (match_operand:V16QI 3 "register_operand" "v,wo")]
3301                  UNSPEC_VPERMHI))]
3302  "TARGET_ALTIVEC"
3303  "@
3304   vperm %0,%1,%2,%3
3305   xxperm %x0,%x1,%x3"
3306  [(set_attr "type" "vecperm")])
3307
3308
3309(define_expand "vec_unpacku_hi_v16qi"
3310  [(set (match_operand:V8HI 0 "register_operand" "=v")
3311        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
3312                     UNSPEC_VUPKHUB))]
3313  "TARGET_ALTIVEC"
3314{
3315  rtx vzero = gen_reg_rtx (V8HImode);
3316  rtx mask = gen_reg_rtx (V16QImode);
3317  rtvec v = rtvec_alloc (16);
3318  bool be = BYTES_BIG_ENDIAN;
3319
3320  emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
3321
3322  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
3323  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  0 : 16);
3324  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 :  6);
3325  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
3326  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
3327  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ?  2 : 16);
3328  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 :  4);
3329  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
3330  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
3331  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ?  4 : 16);
3332  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 :  2);
3333  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
3334  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
3335  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ?  6 : 16);
3336  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  0);
3337  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
3338
3339  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3340  emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
3341  DONE;
3342})
3343
3344(define_expand "vec_unpacku_hi_v8hi"
3345  [(set (match_operand:V4SI 0 "register_operand" "=v")
3346        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3347                     UNSPEC_VUPKHUH))]
3348  "TARGET_ALTIVEC"
3349{
3350  rtx vzero = gen_reg_rtx (V4SImode);
3351  rtx mask = gen_reg_rtx (V16QImode);
3352  rtvec v = rtvec_alloc (16);
3353  bool be = BYTES_BIG_ENDIAN;
3354
3355  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3356
3357  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
3358  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 :  6);
3359  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  0 : 17);
3360  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
3361  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
3362  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 :  4);
3363  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ?  2 : 17);
3364  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
3365  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
3366  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 :  2);
3367  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ?  4 : 17);
3368  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
3369  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
3370  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  0);
3371  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ?  6 : 17);
3372  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
3373
3374  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3375  emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
3376  DONE;
3377})
3378
3379(define_expand "vec_unpacku_lo_v16qi"
3380  [(set (match_operand:V8HI 0 "register_operand" "=v")
3381        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
3382                     UNSPEC_VUPKLUB))]
3383  "TARGET_ALTIVEC"
3384{
3385  rtx vzero = gen_reg_rtx (V8HImode);
3386  rtx mask = gen_reg_rtx (V16QImode);
3387  rtvec v = rtvec_alloc (16);
3388  bool be = BYTES_BIG_ENDIAN;
3389
3390  emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
3391
3392  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
3393  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  8 : 16);
3394  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14);
3395  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
3396  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
3397  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16);
3398  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12);
3399  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
3400  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
3401  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16);
3402  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10);
3403  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
3404  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
3405  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16);
3406  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  8);
3407  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
3408
3409  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3410  emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
3411  DONE;
3412})
3413
3414(define_expand "vec_unpacku_lo_v8hi"
3415  [(set (match_operand:V4SI 0 "register_operand" "=v")
3416        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3417                     UNSPEC_VUPKLUH))]
3418  "TARGET_ALTIVEC"
3419{
3420  rtx vzero = gen_reg_rtx (V4SImode);
3421  rtx mask = gen_reg_rtx (V16QImode);
3422  rtvec v = rtvec_alloc (16);
3423  bool be = BYTES_BIG_ENDIAN;
3424
3425  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3426
3427  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
3428  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14);
3429  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  8 : 17);
3430  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
3431  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
3432  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12);
3433  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17);
3434  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
3435  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
3436  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10);
3437  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17);
3438  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
3439  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
3440  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  8);
3441  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17);
3442  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
3443
3444  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3445  emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
3446  DONE;
3447})
3448
3449(define_expand "vec_widen_umult_hi_v16qi"
3450  [(set (match_operand:V8HI 0 "register_operand" "=v")
3451        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3452                      (match_operand:V16QI 2 "register_operand" "v")]
3453                     UNSPEC_VMULWHUB))]
3454  "TARGET_ALTIVEC"
3455{
3456  rtx ve = gen_reg_rtx (V8HImode);
3457  rtx vo = gen_reg_rtx (V8HImode);
3458
3459  if (BYTES_BIG_ENDIAN)
3460    {
3461      emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
3462      emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
3463      emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
3464    }
3465  else
3466    {
3467      emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
3468      emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
3469      emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
3470    }
3471  DONE;
3472})
3473
3474(define_expand "vec_widen_umult_lo_v16qi"
3475  [(set (match_operand:V8HI 0 "register_operand" "=v")
3476        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3477                      (match_operand:V16QI 2 "register_operand" "v")]
3478                     UNSPEC_VMULWLUB))]
3479  "TARGET_ALTIVEC"
3480{
3481  rtx ve = gen_reg_rtx (V8HImode);
3482  rtx vo = gen_reg_rtx (V8HImode);
3483
3484  if (BYTES_BIG_ENDIAN)
3485    {
3486      emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
3487      emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
3488      emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
3489    }
3490  else
3491    {
3492      emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
3493      emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
3494      emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
3495    }
3496  DONE;
3497})
3498
3499(define_expand "vec_widen_smult_hi_v16qi"
3500  [(set (match_operand:V8HI 0 "register_operand" "=v")
3501        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3502                      (match_operand:V16QI 2 "register_operand" "v")]
3503                     UNSPEC_VMULWHSB))]
3504  "TARGET_ALTIVEC"
3505{
3506  rtx ve = gen_reg_rtx (V8HImode);
3507  rtx vo = gen_reg_rtx (V8HImode);
3508
3509  if (BYTES_BIG_ENDIAN)
3510    {
3511      emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
3512      emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
3513      emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
3514    }
3515  else
3516    {
3517      emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
3518      emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
3519      emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
3520    }
3521  DONE;
3522})
3523
3524(define_expand "vec_widen_smult_lo_v16qi"
3525  [(set (match_operand:V8HI 0 "register_operand" "=v")
3526        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3527                      (match_operand:V16QI 2 "register_operand" "v")]
3528                     UNSPEC_VMULWLSB))]
3529  "TARGET_ALTIVEC"
3530{
3531  rtx ve = gen_reg_rtx (V8HImode);
3532  rtx vo = gen_reg_rtx (V8HImode);
3533
3534  if (BYTES_BIG_ENDIAN)
3535    {
3536      emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
3537      emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
3538      emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
3539    }
3540  else
3541    {
3542      emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
3543      emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
3544      emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
3545    }
3546  DONE;
3547})
3548
3549(define_expand "vec_widen_umult_hi_v8hi"
3550  [(set (match_operand:V4SI 0 "register_operand" "=v")
3551        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3552                      (match_operand:V8HI 2 "register_operand" "v")]
3553                     UNSPEC_VMULWHUH))]
3554  "TARGET_ALTIVEC"
3555{
3556  rtx ve = gen_reg_rtx (V4SImode);
3557  rtx vo = gen_reg_rtx (V4SImode);
3558
3559  if (BYTES_BIG_ENDIAN)
3560    {
3561      emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3562      emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3563      emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3564    }
3565  else
3566    {
3567      emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3568      emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3569      emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3570    }
3571  DONE;
3572})
3573
3574(define_expand "vec_widen_umult_lo_v8hi"
3575  [(set (match_operand:V4SI 0 "register_operand" "=v")
3576        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3577                      (match_operand:V8HI 2 "register_operand" "v")]
3578                     UNSPEC_VMULWLUH))]
3579  "TARGET_ALTIVEC"
3580{
3581  rtx ve = gen_reg_rtx (V4SImode);
3582  rtx vo = gen_reg_rtx (V4SImode);
3583
3584  if (BYTES_BIG_ENDIAN)
3585    {
3586      emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3587      emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3588      emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3589    }
3590  else
3591    {
3592      emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3593      emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3594      emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3595    }
3596  DONE;
3597})
3598
3599(define_expand "vec_widen_smult_hi_v8hi"
3600  [(set (match_operand:V4SI 0 "register_operand" "=v")
3601        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3602                      (match_operand:V8HI 2 "register_operand" "v")]
3603                     UNSPEC_VMULWHSH))]
3604  "TARGET_ALTIVEC"
3605{
3606  rtx ve = gen_reg_rtx (V4SImode);
3607  rtx vo = gen_reg_rtx (V4SImode);
3608
3609  if (BYTES_BIG_ENDIAN)
3610    {
3611      emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3612      emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3613      emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3614    }
3615  else
3616    {
3617      emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3618      emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3619      emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3620    }
3621  DONE;
3622})
3623
3624(define_expand "vec_widen_smult_lo_v8hi"
3625  [(set (match_operand:V4SI 0 "register_operand" "=v")
3626        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3627                      (match_operand:V8HI 2 "register_operand" "v")]
3628                     UNSPEC_VMULWLSH))]
3629  "TARGET_ALTIVEC"
3630{
3631  rtx ve = gen_reg_rtx (V4SImode);
3632  rtx vo = gen_reg_rtx (V4SImode);
3633
3634  if (BYTES_BIG_ENDIAN)
3635    {
3636      emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3637      emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3638      emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3639    }
3640  else
3641    {
3642      emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3643      emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3644      emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3645    }
3646  DONE;
3647})
3648
3649(define_expand "vec_pack_trunc_<mode>"
3650  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
3651        (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
3652			    (match_operand:VP 2 "register_operand" "v")]
3653                      UNSPEC_VPACK_UNS_UNS_MOD))]
3654  "<VI_unit>"
3655  "")
3656
3657(define_expand "mulv16qi3"
3658  [(set (match_operand:V16QI 0 "register_operand" "=v")
3659        (mult:V16QI (match_operand:V16QI 1 "register_operand" "v")
3660                    (match_operand:V16QI 2 "register_operand" "v")))]
3661  "TARGET_ALTIVEC"
3662{
3663  rtx even = gen_reg_rtx (V8HImode);
3664  rtx odd = gen_reg_rtx (V8HImode);
3665  rtx mask = gen_reg_rtx (V16QImode);
3666  rtvec v = rtvec_alloc (16);
3667  int i;
3668
3669  for (i = 0; i < 8; ++i) {
3670    RTVEC_ELT (v, 2 * i)
3671     = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 1 : 31 - 2 * i);
3672    RTVEC_ELT (v, 2 * i + 1)
3673     = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 17 : 15 - 2 * i);
3674  }
3675
3676  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3677  emit_insn (gen_altivec_vmulesb (even, operands[1], operands[2]));
3678  emit_insn (gen_altivec_vmulosb (odd, operands[1], operands[2]));
3679  emit_insn (gen_altivec_vperm_v8hiv16qi (operands[0], even, odd, mask));
3680  DONE;
3681})
3682
3683(define_expand "altivec_vpermxor"
3684  [(use (match_operand:V16QI 0 "register_operand"))
3685   (use (match_operand:V16QI 1 "register_operand"))
3686   (use (match_operand:V16QI 2 "register_operand"))
3687   (use (match_operand:V16QI 3 "register_operand"))]
3688  "TARGET_P8_VECTOR"
3689{
3690  if (!BYTES_BIG_ENDIAN)
3691    {
3692      /* vpermxor indexes the bytes using Big Endian numbering.  If LE,
3693	 change indexing in operand[3] to BE index.  */
3694      rtx be_index = gen_reg_rtx (V16QImode);
3695
3696      emit_insn (gen_one_cmplv16qi2 (be_index, operands[3]));
3697      emit_insn (gen_crypto_vpermxor_v16qi (operands[0], operands[1],
3698					    operands[2], be_index));
3699    }
3700  else
3701    emit_insn (gen_crypto_vpermxor_v16qi (operands[0], operands[1],
3702					  operands[2], operands[3]));
3703  DONE;
3704})
3705
3706(define_expand "altivec_negv4sf2"
3707  [(use (match_operand:V4SF 0 "register_operand"))
3708   (use (match_operand:V4SF 1 "register_operand"))]
3709  "TARGET_ALTIVEC"
3710{
3711  rtx neg0;
3712
3713  /* Generate [-0.0, -0.0, -0.0, -0.0].  */
3714  neg0 = gen_reg_rtx (V4SImode);
3715  emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
3716  emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
3717
3718  /* XOR */
3719  emit_insn (gen_xorv4sf3 (operands[0],
3720			   gen_lowpart (V4SFmode, neg0), operands[1]));
3721
3722  DONE;
3723})
3724
3725;; Vector reverse elements
3726(define_expand "altivec_vreve<mode>2"
3727  [(set (match_operand:VEC_A 0 "register_operand" "=v")
3728	(unspec:VEC_A [(match_operand:VEC_A 1 "register_operand" "v")]
3729		      UNSPEC_VREVEV))]
3730  "TARGET_ALTIVEC"
3731{
3732  int i, j, size, num_elements;
3733  rtvec v = rtvec_alloc (16);
3734  rtx mask = gen_reg_rtx (V16QImode);
3735
3736  size = GET_MODE_UNIT_SIZE (<MODE>mode);
3737  num_elements = GET_MODE_NUNITS (<MODE>mode);
3738
3739  for (j = 0; j < num_elements; j++)
3740    for (i = 0; i < size; i++)
3741      RTVEC_ELT (v, i + j * size)
3742	= GEN_INT (i + (num_elements - 1 - j) * size);
3743
3744  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3745  emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
3746	     operands[1], mask));
3747  DONE;
3748})
3749
3750;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL,
3751;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell.
3752(define_insn "altivec_lvlx"
3753  [(set (match_operand:V16QI 0 "register_operand" "=v")
3754        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3755		      UNSPEC_LVLX))]
3756  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3757  "lvlx %0,%y1"
3758  [(set_attr "type" "vecload")])
3759
3760(define_insn "altivec_lvlxl"
3761  [(set (match_operand:V16QI 0 "register_operand" "=v")
3762        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3763		      UNSPEC_LVLXL))]
3764  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3765  "lvlxl %0,%y1"
3766  [(set_attr "type" "vecload")])
3767
3768(define_insn "altivec_lvrx"
3769  [(set (match_operand:V16QI 0 "register_operand" "=v")
3770        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3771		      UNSPEC_LVRX))]
3772  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3773  "lvrx %0,%y1"
3774  [(set_attr "type" "vecload")])
3775
3776(define_insn "altivec_lvrxl"
3777  [(set (match_operand:V16QI 0 "register_operand" "=v")
3778        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3779		      UNSPEC_LVRXL))]
3780  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3781  "lvrxl %0,%y1"
3782  [(set_attr "type" "vecload")])
3783
3784(define_insn "altivec_stvlx"
3785  [(parallel
3786    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3787	  (match_operand:V16QI 1 "register_operand" "v"))
3788     (unspec [(const_int 0)] UNSPEC_STVLX)])]
3789  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3790  "stvlx %1,%y0"
3791  [(set_attr "type" "vecstore")])
3792
3793(define_insn "altivec_stvlxl"
3794  [(parallel
3795    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3796	  (match_operand:V16QI 1 "register_operand" "v"))
3797     (unspec [(const_int 0)] UNSPEC_STVLXL)])]
3798  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3799  "stvlxl %1,%y0"
3800  [(set_attr "type" "vecstore")])
3801
3802(define_insn "altivec_stvrx"
3803  [(parallel
3804    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3805	  (match_operand:V16QI 1 "register_operand" "v"))
3806     (unspec [(const_int 0)] UNSPEC_STVRX)])]
3807  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3808  "stvrx %1,%y0"
3809  [(set_attr "type" "vecstore")])
3810
3811(define_insn "altivec_stvrxl"
3812  [(parallel
3813    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3814	  (match_operand:V16QI 1 "register_operand" "v"))
3815     (unspec [(const_int 0)] UNSPEC_STVRXL)])]
3816  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3817  "stvrxl %1,%y0"
3818  [(set_attr "type" "vecstore")])
3819
3820(define_expand "vec_unpacks_float_hi_v8hi"
3821 [(set (match_operand:V4SF 0 "register_operand")
3822        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3823                     UNSPEC_VUPKHS_V4SF))]
3824  "TARGET_ALTIVEC"
3825{
3826  rtx tmp = gen_reg_rtx (V4SImode);
3827
3828  emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
3829  emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3830  DONE;
3831})
3832
3833(define_expand "vec_unpacks_float_lo_v8hi"
3834 [(set (match_operand:V4SF 0 "register_operand")
3835        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3836                     UNSPEC_VUPKLS_V4SF))]
3837  "TARGET_ALTIVEC"
3838{
3839  rtx tmp = gen_reg_rtx (V4SImode);
3840
3841  emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
3842  emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3843  DONE;
3844})
3845
3846(define_expand "vec_unpacku_float_hi_v8hi"
3847 [(set (match_operand:V4SF 0 "register_operand")
3848        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3849                     UNSPEC_VUPKHU_V4SF))]
3850  "TARGET_ALTIVEC"
3851{
3852  rtx tmp = gen_reg_rtx (V4SImode);
3853
3854  emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
3855  emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3856  DONE;
3857})
3858
3859(define_expand "vec_unpacku_float_lo_v8hi"
3860 [(set (match_operand:V4SF 0 "register_operand")
3861        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3862                     UNSPEC_VUPKLU_V4SF))]
3863  "TARGET_ALTIVEC"
3864{
3865  rtx tmp = gen_reg_rtx (V4SImode);
3866
3867  emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
3868  emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3869  DONE;
3870})
3871
3872
3873;; Power8/power9 vector instructions encoded as Altivec instructions
3874
3875;; Vector count leading zeros
3876(define_insn "*p8v_clz<mode>2"
3877  [(set (match_operand:VI2 0 "register_operand" "=v")
3878	(clz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3879  "TARGET_P8_VECTOR"
3880  "vclz<wd> %0,%1"
3881  [(set_attr "type" "vecsimple")])
3882
3883;; Vector absolute difference unsigned
3884(define_expand "vadu<mode>3"
3885  [(set (match_operand:VI 0 "register_operand")
3886        (unspec:VI [(match_operand:VI 1 "register_operand")
3887		    (match_operand:VI 2 "register_operand")]
3888         UNSPEC_VADU))]
3889  "TARGET_P9_VECTOR")
3890
3891;; Vector absolute difference unsigned
3892(define_insn "p9_vadu<mode>3"
3893  [(set (match_operand:VI 0 "register_operand" "=v")
3894        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
3895		    (match_operand:VI 2 "register_operand" "v")]
3896         UNSPEC_VADU))]
3897  "TARGET_P9_VECTOR"
3898  "vabsdu<wd> %0,%1,%2"
3899  [(set_attr "type" "vecsimple")])
3900
3901;; Vector count trailing zeros
3902(define_insn "*p9v_ctz<mode>2"
3903  [(set (match_operand:VI2 0 "register_operand" "=v")
3904	(ctz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3905  "TARGET_P9_VECTOR"
3906  "vctz<wd> %0,%1"
3907  [(set_attr "type" "vecsimple")])
3908
3909;; Vector population count
3910(define_insn "*p8v_popcount<mode>2"
3911  [(set (match_operand:VI2 0 "register_operand" "=v")
3912        (popcount:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3913  "TARGET_P8_VECTOR"
3914  "vpopcnt<wd> %0,%1"
3915  [(set_attr "type" "vecsimple")])
3916
3917;; Vector parity
3918(define_insn "*p9v_parity<mode>2"
3919  [(set (match_operand:VParity 0 "register_operand" "=v")
3920        (parity:VParity (match_operand:VParity 1 "register_operand" "v")))]
3921  "TARGET_P9_VECTOR"
3922  "vprtyb<wd> %0,%1"
3923  [(set_attr "type" "vecsimple")])
3924
3925;; Vector Gather Bits by Bytes by Doubleword
3926(define_insn "p8v_vgbbd"
3927  [(set (match_operand:V16QI 0 "register_operand" "=v")
3928	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
3929		      UNSPEC_VGBBD))]
3930  "TARGET_P8_VECTOR"
3931  "vgbbd %0,%1"
3932  [(set_attr "type" "vecsimple")])
3933
3934
3935;; 128-bit binary integer arithmetic
3936;; We have a special container type (V1TImode) to allow operations using the
3937;; ISA 2.07 128-bit binary support to target the VMX/altivec registers without
3938;; having to worry about the register allocator deciding GPRs are better.
3939
3940(define_insn "altivec_vadduqm"
3941  [(set (match_operand:V1TI 0 "register_operand" "=v")
3942	(plus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3943		   (match_operand:V1TI 2 "register_operand" "v")))]
3944  "TARGET_VADDUQM"
3945  "vadduqm %0,%1,%2"
3946  [(set_attr "type" "vecsimple")])
3947
3948(define_insn "altivec_vaddcuq"
3949  [(set (match_operand:V1TI 0 "register_operand" "=v")
3950	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3951		      (match_operand:V1TI 2 "register_operand" "v")]
3952		     UNSPEC_VADDCUQ))]
3953  "TARGET_VADDUQM"
3954  "vaddcuq %0,%1,%2"
3955  [(set_attr "type" "vecsimple")])
3956
3957(define_insn "altivec_vsubuqm"
3958  [(set (match_operand:V1TI 0 "register_operand" "=v")
3959	(minus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3960		    (match_operand:V1TI 2 "register_operand" "v")))]
3961  "TARGET_VADDUQM"
3962  "vsubuqm %0,%1,%2"
3963  [(set_attr "type" "vecsimple")])
3964
3965(define_insn "altivec_vsubcuq"
3966  [(set (match_operand:V1TI 0 "register_operand" "=v")
3967	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3968		      (match_operand:V1TI 2 "register_operand" "v")]
3969		     UNSPEC_VSUBCUQ))]
3970  "TARGET_VADDUQM"
3971  "vsubcuq %0,%1,%2"
3972  [(set_attr "type" "vecsimple")])
3973
3974(define_insn "altivec_vaddeuqm"
3975  [(set (match_operand:V1TI 0 "register_operand" "=v")
3976	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3977		      (match_operand:V1TI 2 "register_operand" "v")
3978		      (match_operand:V1TI 3 "register_operand" "v")]
3979		     UNSPEC_VADDEUQM))]
3980  "TARGET_VADDUQM"
3981  "vaddeuqm %0,%1,%2,%3"
3982  [(set_attr "type" "vecsimple")])
3983
3984(define_insn "altivec_vaddecuq"
3985  [(set (match_operand:V1TI 0 "register_operand" "=v")
3986	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3987		      (match_operand:V1TI 2 "register_operand" "v")
3988		      (match_operand:V1TI 3 "register_operand" "v")]
3989		     UNSPEC_VADDECUQ))]
3990  "TARGET_VADDUQM"
3991  "vaddecuq %0,%1,%2,%3"
3992  [(set_attr "type" "vecsimple")])
3993
3994(define_insn "altivec_vsubeuqm"
3995  [(set (match_operand:V1TI 0 "register_operand" "=v")
3996	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3997		      (match_operand:V1TI 2 "register_operand" "v")
3998		      (match_operand:V1TI 3 "register_operand" "v")]
3999		   UNSPEC_VSUBEUQM))]
4000  "TARGET_VADDUQM"
4001  "vsubeuqm %0,%1,%2,%3"
4002  [(set_attr "type" "vecsimple")])
4003
4004(define_insn "altivec_vsubecuq"
4005  [(set (match_operand:V1TI 0 "register_operand" "=v")
4006	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
4007		      (match_operand:V1TI 2 "register_operand" "v")
4008		      (match_operand:V1TI 3 "register_operand" "v")]
4009		     UNSPEC_VSUBECUQ))]
4010  "TARGET_VADDUQM"
4011  "vsubecuq %0,%1,%2,%3"
4012  [(set_attr "type" "vecsimple")])
4013
4014;; We use V2DI as the output type to simplify converting the permute
4015;; bits into an integer
4016(define_insn "altivec_vbpermq"
4017  [(set (match_operand:V2DI 0 "register_operand" "=v")
4018	(unspec:V2DI [(match_operand:V16QI 1 "register_operand" "v")
4019		      (match_operand:V16QI 2 "register_operand" "v")]
4020		     UNSPEC_VBPERMQ))]
4021  "TARGET_P8_VECTOR"
4022  "vbpermq %0,%1,%2"
4023  [(set_attr "type" "vecperm")])
4024
4025; One of the vector API interfaces requires returning vector unsigned char.
4026(define_insn "altivec_vbpermq2"
4027  [(set (match_operand:V16QI 0 "register_operand" "=v")
4028	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
4029		       (match_operand:V16QI 2 "register_operand" "v")]
4030		      UNSPEC_VBPERMQ))]
4031  "TARGET_P8_VECTOR"
4032  "vbpermq %0,%1,%2"
4033  [(set_attr "type" "vecperm")])
4034
4035(define_insn "altivec_vbpermd"
4036  [(set (match_operand:V2DI 0 "register_operand" "=v")
4037	(unspec:V2DI [(match_operand:V2DI 1 "register_operand" "v")
4038		      (match_operand:V16QI 2 "register_operand" "v")]
4039		     UNSPEC_VBPERMD))]
4040  "TARGET_P9_VECTOR"
4041  "vbpermd %0,%1,%2"
4042  [(set_attr "type" "vecsimple")])
4043
4044;; Support for SAD (sum of absolute differences).
4045
4046;; Due to saturating semantics, we can't combine the sum-across
4047;; with the vector accumulate in vsum4ubs.  A vadduwm is needed.
4048(define_expand "usadv16qi"
4049  [(use (match_operand:V4SI 0 "register_operand"))
4050   (use (match_operand:V16QI 1 "register_operand"))
4051   (use (match_operand:V16QI 2 "register_operand"))
4052   (use (match_operand:V4SI 3 "register_operand"))]
4053  "TARGET_P9_VECTOR"
4054{
4055  rtx absd = gen_reg_rtx (V16QImode);
4056  rtx zero = gen_reg_rtx (V4SImode);
4057  rtx psum = gen_reg_rtx (V4SImode);
4058
4059  emit_insn (gen_p9_vaduv16qi3 (absd, operands[1], operands[2]));
4060  emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
4061  emit_insn (gen_altivec_vsum4ubs (psum, absd, zero));
4062  emit_insn (gen_addv4si3 (operands[0], psum, operands[3]));
4063  DONE;
4064})
4065
4066;; Since vsum4shs is saturating and further performs signed
4067;; arithmetic, we can't combine the sum-across with the vector
4068;; accumulate in vsum4shs.  A vadduwm is needed.
4069(define_expand "usadv8hi"
4070  [(use (match_operand:V4SI 0 "register_operand"))
4071   (use (match_operand:V8HI 1 "register_operand"))
4072   (use (match_operand:V8HI 2 "register_operand"))
4073   (use (match_operand:V4SI 3 "register_operand"))]
4074  "TARGET_P9_VECTOR"
4075{
4076  rtx absd = gen_reg_rtx (V8HImode);
4077  rtx zero = gen_reg_rtx (V4SImode);
4078  rtx psum = gen_reg_rtx (V4SImode);
4079
4080  emit_insn (gen_p9_vaduv8hi3 (absd, operands[1], operands[2]));
4081  emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
4082  emit_insn (gen_altivec_vsum4shs (psum, absd, zero));
4083  emit_insn (gen_addv4si3 (operands[0], psum, operands[3]));
4084  DONE;
4085})
4086
4087;; Decimal Integer operations
4088(define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB])
4089
4090(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
4091			      (UNSPEC_BCDSUB "sub")])
4092
4093(define_code_iterator BCD_TEST [eq lt gt unordered])
4094
4095(define_insn "bcd<bcd_add_sub>"
4096  [(set (match_operand:V1TI 0 "gpc_reg_operand" "=v")
4097	(unspec:V1TI [(match_operand:V1TI 1 "gpc_reg_operand" "v")
4098		      (match_operand:V1TI 2 "gpc_reg_operand" "v")
4099		      (match_operand:QI 3 "const_0_to_1_operand" "n")]
4100		     UNSPEC_BCD_ADD_SUB))
4101   (clobber (reg:CCFP CR6_REGNO))]
4102  "TARGET_P8_VECTOR"
4103  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4104  [(set_attr "type" "vecsimple")])
4105
4106;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
4107;; can use the unordered test for BCD nans and add/subtracts that overflow.  An
4108;; UNORDERED test on an integer type (like V1TImode) is not defined.  The type
4109;; probably should be one that can go in the VMX (Altivec) registers, so we
4110;; can't use DDmode or DFmode.
4111(define_insn "*bcd<bcd_add_sub>_test"
4112  [(set (reg:CCFP CR6_REGNO)
4113	(compare:CCFP
4114	 (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
4115		       (match_operand:V1TI 2 "register_operand" "v")
4116		       (match_operand:QI 3 "const_0_to_1_operand" "i")]
4117		      UNSPEC_BCD_ADD_SUB)
4118	 (match_operand:V2DF 4 "zero_constant" "j")))
4119   (clobber (match_scratch:V1TI 0 "=v"))]
4120  "TARGET_P8_VECTOR"
4121  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4122  [(set_attr "type" "vecsimple")])
4123
4124(define_insn "*bcd<bcd_add_sub>_test2"
4125  [(set (match_operand:V1TI 0 "register_operand" "=v")
4126	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
4127		      (match_operand:V1TI 2 "register_operand" "v")
4128		      (match_operand:QI 3 "const_0_to_1_operand" "i")]
4129		     UNSPEC_BCD_ADD_SUB))
4130   (set (reg:CCFP CR6_REGNO)
4131	(compare:CCFP
4132	 (unspec:V2DF [(match_dup 1)
4133		       (match_dup 2)
4134		       (match_dup 3)]
4135		      UNSPEC_BCD_ADD_SUB)
4136	 (match_operand:V2DF 4 "zero_constant" "j")))]
4137  "TARGET_P8_VECTOR"
4138  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4139  [(set_attr "type" "vecsimple")])
4140
4141(define_expand "bcd<bcd_add_sub>_<code>"
4142  [(parallel [(set (reg:CCFP CR6_REGNO)
4143		   (compare:CCFP
4144		    (unspec:V2DF [(match_operand:V1TI 1 "register_operand")
4145				  (match_operand:V1TI 2 "register_operand")
4146				  (match_operand:QI 3 "const_0_to_1_operand")]
4147				 UNSPEC_BCD_ADD_SUB)
4148		    (match_dup 4)))
4149	      (clobber (match_scratch:V1TI 5))])
4150   (set (match_operand:SI 0 "register_operand")
4151	(BCD_TEST:SI (reg:CCFP CR6_REGNO)
4152		     (const_int 0)))]
4153  "TARGET_P8_VECTOR"
4154{
4155  operands[4] = CONST0_RTX (V2DFmode);
4156})
4157
4158;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
4159;; the bcdadd/bcdsub that tests the value.  The combiner won't work since
4160;; CR6 is a hard coded register.  Unfortunately, all of the Altivec predicate
4161;; support is hard coded to use the fixed register CR6 instead of creating
4162;; a register class for CR6.
4163
4164(define_peephole2
4165  [(parallel [(set (match_operand:V1TI 0 "register_operand")
4166		   (unspec:V1TI [(match_operand:V1TI 1 "register_operand")
4167				 (match_operand:V1TI 2 "register_operand")
4168				 (match_operand:QI 3 "const_0_to_1_operand")]
4169				UNSPEC_BCD_ADD_SUB))
4170	      (clobber (reg:CCFP CR6_REGNO))])
4171   (parallel [(set (reg:CCFP CR6_REGNO)
4172		   (compare:CCFP
4173		    (unspec:V2DF [(match_dup 1)
4174				  (match_dup 2)
4175				  (match_dup 3)]
4176				 UNSPEC_BCD_ADD_SUB)
4177		    (match_operand:V2DF 4 "zero_constant")))
4178	      (clobber (match_operand:V1TI 5 "register_operand"))])]
4179  "TARGET_P8_VECTOR"
4180  [(parallel [(set (match_dup 0)
4181		   (unspec:V1TI [(match_dup 1)
4182				 (match_dup 2)
4183				 (match_dup 3)]
4184				UNSPEC_BCD_ADD_SUB))
4185	      (set (reg:CCFP CR6_REGNO)
4186		   (compare:CCFP
4187		    (unspec:V2DF [(match_dup 1)
4188				  (match_dup 2)
4189				  (match_dup 3)]
4190				 UNSPEC_BCD_ADD_SUB)
4191		    (match_dup 4)))])])
4192