1;; AltiVec patterns.
2;; Copyright (C) 2002-2020 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" "*,*,*,20,20,20,*,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,?wa")
2033	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
2034		    (match_operand:VM 2 "register_operand" "v,0")
2035		    (match_operand:V16QI 3 "register_operand" "v,wa")]
2036		   UNSPEC_VPERM))]
2037  "TARGET_ALTIVEC"
2038  "@
2039   vperm %0,%1,%2,%3
2040   xxperm %x0,%x1,%x3"
2041  [(set_attr "type" "vecperm")
2042   (set_attr "isa" "*,p9v")])
2043
2044(define_insn "altivec_vperm_v8hiv16qi"
2045  [(set (match_operand:V16QI 0 "register_operand" "=v,?wa")
2046	(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v,wa")
2047   	               (match_operand:V8HI 2 "register_operand" "v,0")
2048		       (match_operand:V16QI 3 "register_operand" "v,wa")]
2049		   UNSPEC_VPERM))]
2050  "TARGET_ALTIVEC"
2051  "@
2052   vperm %0,%1,%2,%3
2053   xxperm %x0,%x1,%x3"
2054  [(set_attr "type" "vecperm")
2055   (set_attr "isa" "*,p9v")])
2056
2057(define_expand "altivec_vperm_<mode>_uns"
2058  [(set (match_operand:VM 0 "register_operand")
2059	(unspec:VM [(match_operand:VM 1 "register_operand")
2060		    (match_operand:VM 2 "register_operand")
2061		    (match_operand:V16QI 3 "register_operand")]
2062		   UNSPEC_VPERM_UNS))]
2063  "TARGET_ALTIVEC"
2064{
2065  if (!BYTES_BIG_ENDIAN)
2066    {
2067      altivec_expand_vec_perm_le (operands);
2068      DONE;
2069    }
2070})
2071
2072(define_insn "*altivec_vperm_<mode>_uns_internal"
2073  [(set (match_operand:VM 0 "register_operand" "=v,?wa")
2074	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
2075		    (match_operand:VM 2 "register_operand" "v,0")
2076		    (match_operand:V16QI 3 "register_operand" "v,wa")]
2077		   UNSPEC_VPERM_UNS))]
2078  "TARGET_ALTIVEC"
2079  "@
2080   vperm %0,%1,%2,%3
2081   xxperm %x0,%x1,%x3"
2082  [(set_attr "type" "vecperm")
2083   (set_attr "isa" "*,p9v")])
2084
2085(define_expand "vec_permv16qi"
2086  [(set (match_operand:V16QI 0 "register_operand")
2087	(unspec:V16QI [(match_operand:V16QI 1 "register_operand")
2088		       (match_operand:V16QI 2 "register_operand")
2089		       (match_operand:V16QI 3 "register_operand")]
2090		      UNSPEC_VPERM))]
2091  "TARGET_ALTIVEC"
2092{
2093  if (!BYTES_BIG_ENDIAN) {
2094    altivec_expand_vec_perm_le (operands);
2095    DONE;
2096  }
2097})
2098
2099(define_insn "*altivec_vpermr_<mode>_internal"
2100  [(set (match_operand:VM 0 "register_operand" "=v,?wa")
2101	(unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
2102		    (match_operand:VM 2 "register_operand" "v,0")
2103		    (match_operand:V16QI 3 "register_operand" "v,wa")]
2104		   UNSPEC_VPERMR))]
2105  "TARGET_P9_VECTOR"
2106  "@
2107   vpermr %0,%1,%2,%3
2108   xxpermr %x0,%x1,%x3"
2109  [(set_attr "type" "vecperm")
2110   (set_attr "isa" "*,p9v")])
2111
2112(define_insn "altivec_vrfip"		; ceil
2113  [(set (match_operand:V4SF 0 "register_operand" "=v")
2114        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2115		     UNSPEC_FRIP))]
2116  "TARGET_ALTIVEC"
2117  "vrfip %0,%1"
2118  [(set_attr "type" "vecfloat")])
2119
2120(define_insn "altivec_vrfin"
2121  [(set (match_operand:V4SF 0 "register_operand" "=v")
2122        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2123		     UNSPEC_VRFIN))]
2124  "TARGET_ALTIVEC"
2125  "vrfin %0,%1"
2126  [(set_attr "type" "vecfloat")])
2127
2128(define_insn "*altivec_vrfim"		; floor
2129  [(set (match_operand:V4SF 0 "register_operand" "=v")
2130        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2131		     UNSPEC_FRIM))]
2132  "TARGET_ALTIVEC"
2133  "vrfim %0,%1"
2134  [(set_attr "type" "vecfloat")])
2135
2136(define_insn "altivec_vcfux"
2137  [(set (match_operand:V4SF 0 "register_operand" "=v")
2138        (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
2139	              (match_operand:QI 2 "immediate_operand" "i")]
2140		     UNSPEC_VCFUX))]
2141  "TARGET_ALTIVEC"
2142  "vcfux %0,%1,%2"
2143  [(set_attr "type" "vecfloat")])
2144
2145(define_insn "altivec_vcfsx"
2146  [(set (match_operand:V4SF 0 "register_operand" "=v")
2147        (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
2148	              (match_operand:QI 2 "immediate_operand" "i")]
2149		     UNSPEC_VCFSX))]
2150  "TARGET_ALTIVEC"
2151  "vcfsx %0,%1,%2"
2152  [(set_attr "type" "vecfloat")])
2153
2154(define_insn "altivec_vctuxs"
2155  [(set (match_operand:V4SI 0 "register_operand" "=v")
2156        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2157                      (match_operand:QI 2 "immediate_operand" "i")]
2158		     UNSPEC_VCTUXS))
2159   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2160  "TARGET_ALTIVEC"
2161  "vctuxs %0,%1,%2"
2162  [(set_attr "type" "vecfloat")])
2163
2164(define_insn "altivec_vctsxs"
2165  [(set (match_operand:V4SI 0 "register_operand" "=v")
2166        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2167                      (match_operand:QI 2 "immediate_operand" "i")]
2168		     UNSPEC_VCTSXS))
2169   (set (reg:SI VSCR_REGNO) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2170  "TARGET_ALTIVEC"
2171  "vctsxs %0,%1,%2"
2172  [(set_attr "type" "vecfloat")])
2173
2174(define_insn "altivec_vlogefp"
2175  [(set (match_operand:V4SF 0 "register_operand" "=v")
2176        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2177		     UNSPEC_VLOGEFP))]
2178  "TARGET_ALTIVEC"
2179  "vlogefp %0,%1"
2180  [(set_attr "type" "vecfloat")])
2181
2182(define_insn "altivec_vexptefp"
2183  [(set (match_operand:V4SF 0 "register_operand" "=v")
2184        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2185		     UNSPEC_VEXPTEFP))]
2186  "TARGET_ALTIVEC"
2187  "vexptefp %0,%1"
2188  [(set_attr "type" "vecfloat")])
2189
2190(define_insn "*altivec_vrsqrtefp"
2191  [(set (match_operand:V4SF 0 "register_operand" "=v")
2192        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2193		     UNSPEC_RSQRT))]
2194  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2195  "vrsqrtefp %0,%1"
2196  [(set_attr "type" "vecfloat")])
2197
2198(define_insn "altivec_vrefp"
2199  [(set (match_operand:V4SF 0 "register_operand" "=v")
2200        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2201		     UNSPEC_FRES))]
2202  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2203  "vrefp %0,%1"
2204  [(set_attr "type" "vecfloat")])
2205
2206(define_expand "altivec_copysign_v4sf3"
2207  [(use (match_operand:V4SF 0 "register_operand"))
2208   (use (match_operand:V4SF 1 "register_operand"))
2209   (use (match_operand:V4SF 2 "register_operand"))]
2210  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2211{
2212  rtx mask = gen_reg_rtx (V4SImode);
2213  rtx mask_val = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
2214  rtvec v = gen_rtvec (4, mask_val, mask_val, mask_val, mask_val);
2215
2216  emit_insn (gen_vec_initv4sisi (mask, gen_rtx_PARALLEL (V4SImode, v)));
2217  emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2],
2218				     gen_lowpart (V4SFmode, mask)));
2219  DONE;
2220})
2221
2222(define_insn "altivec_vsldoi_<mode>"
2223  [(set (match_operand:VM 0 "register_operand" "=v")
2224        (unspec:VM [(match_operand:VM 1 "register_operand" "v")
2225		    (match_operand:VM 2 "register_operand" "v")
2226		    (match_operand:QI 3 "immediate_operand" "i")]
2227		  UNSPEC_VSLDOI))]
2228  "TARGET_ALTIVEC"
2229  "vsldoi %0,%1,%2,%3"
2230  [(set_attr "type" "vecperm")])
2231
2232(define_insn "altivec_vupkhs<VU_char>"
2233  [(set (match_operand:VP 0 "register_operand" "=v")
2234	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2235		     UNSPEC_VUNPACK_HI_SIGN))]
2236  "<VI_unit>"
2237{
2238  if (BYTES_BIG_ENDIAN)
2239    return "vupkhs<VU_char> %0,%1";
2240  else
2241    return "vupkls<VU_char> %0,%1";
2242}
2243  [(set_attr "type" "vecperm")])
2244
2245(define_insn "*altivec_vupkhs<VU_char>_direct"
2246  [(set (match_operand:VP 0 "register_operand" "=v")
2247	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2248		     UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
2249  "<VI_unit>"
2250  "vupkhs<VU_char> %0,%1"
2251  [(set_attr "type" "vecperm")])
2252
2253(define_insn "altivec_vupkls<VU_char>"
2254  [(set (match_operand:VP 0 "register_operand" "=v")
2255	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2256		     UNSPEC_VUNPACK_LO_SIGN))]
2257  "<VI_unit>"
2258{
2259  if (BYTES_BIG_ENDIAN)
2260    return "vupkls<VU_char> %0,%1";
2261  else
2262    return "vupkhs<VU_char> %0,%1";
2263}
2264  [(set_attr "type" "vecperm")])
2265
2266(define_insn "*altivec_vupkls<VU_char>_direct"
2267  [(set (match_operand:VP 0 "register_operand" "=v")
2268	(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2269		     UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
2270  "<VI_unit>"
2271  "vupkls<VU_char> %0,%1"
2272  [(set_attr "type" "vecperm")])
2273
2274(define_insn "altivec_vupkhpx"
2275  [(set (match_operand:V4SI 0 "register_operand" "=v")
2276	(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2277		     UNSPEC_VUPKHPX))]
2278  "TARGET_ALTIVEC"
2279{
2280  if (BYTES_BIG_ENDIAN)
2281    return "vupkhpx %0,%1";
2282  else
2283    return "vupklpx %0,%1";
2284}
2285  [(set_attr "type" "vecperm")])
2286
2287(define_insn "altivec_vupklpx"
2288  [(set (match_operand:V4SI 0 "register_operand" "=v")
2289	(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2290		     UNSPEC_VUPKLPX))]
2291  "TARGET_ALTIVEC"
2292{
2293  if (BYTES_BIG_ENDIAN)
2294    return "vupklpx %0,%1";
2295  else
2296    return "vupkhpx %0,%1";
2297}
2298  [(set_attr "type" "vecperm")])
2299
2300;; Compare vectors producing a vector result and a predicate, setting CR6 to
2301;; indicate a combined status
2302(define_insn "altivec_vcmpequ<VI_char>_p"
2303  [(set (reg:CC CR6_REGNO)
2304	(unspec:CC [(eq:CC (match_operand:VI2 1 "register_operand" "v")
2305			   (match_operand:VI2 2 "register_operand" "v"))]
2306		   UNSPEC_PREDICATE))
2307   (set (match_operand:VI2 0 "register_operand" "=v")
2308	(eq:VI2 (match_dup 1)
2309		(match_dup 2)))]
2310  "<VI_unit>"
2311  "vcmpequ<VI_char>. %0,%1,%2"
2312  [(set_attr "type" "veccmpfx")])
2313
2314(define_insn "*altivec_vcmpgts<VI_char>_p"
2315  [(set (reg:CC CR6_REGNO)
2316	(unspec:CC [(gt:CC (match_operand:VI2 1 "register_operand" "v")
2317			   (match_operand:VI2 2 "register_operand" "v"))]
2318		   UNSPEC_PREDICATE))
2319   (set (match_operand:VI2 0 "register_operand" "=v")
2320	(gt:VI2 (match_dup 1)
2321		(match_dup 2)))]
2322  "<VI_unit>"
2323  "vcmpgts<VI_char>. %0,%1,%2"
2324  [(set_attr "type" "veccmpfx")])
2325
2326(define_insn "*altivec_vcmpgtu<VI_char>_p"
2327  [(set (reg:CC CR6_REGNO)
2328	(unspec:CC [(gtu:CC (match_operand:VI2 1 "register_operand" "v")
2329			    (match_operand:VI2 2 "register_operand" "v"))]
2330		   UNSPEC_PREDICATE))
2331   (set (match_operand:VI2 0 "register_operand" "=v")
2332	(gtu:VI2 (match_dup 1)
2333		 (match_dup 2)))]
2334  "<VI_unit>"
2335  "vcmpgtu<VI_char>. %0,%1,%2"
2336  [(set_attr "type" "veccmpfx")])
2337
2338(define_insn "*altivec_vcmpeqfp_p"
2339  [(set (reg:CC CR6_REGNO)
2340	(unspec:CC [(eq:CC (match_operand:V4SF 1 "register_operand" "v")
2341			   (match_operand:V4SF 2 "register_operand" "v"))]
2342		   UNSPEC_PREDICATE))
2343   (set (match_operand:V4SF 0 "register_operand" "=v")
2344	(eq:V4SF (match_dup 1)
2345		 (match_dup 2)))]
2346  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2347  "vcmpeqfp. %0,%1,%2"
2348  [(set_attr "type" "veccmp")])
2349
2350(define_insn "*altivec_vcmpgtfp_p"
2351  [(set (reg:CC CR6_REGNO)
2352	(unspec:CC [(gt:CC (match_operand:V4SF 1 "register_operand" "v")
2353			   (match_operand:V4SF 2 "register_operand" "v"))]
2354		   UNSPEC_PREDICATE))
2355   (set (match_operand:V4SF 0 "register_operand" "=v")
2356	(gt:V4SF (match_dup 1)
2357		 (match_dup 2)))]
2358  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2359  "vcmpgtfp. %0,%1,%2"
2360  [(set_attr "type" "veccmp")])
2361
2362(define_insn "*altivec_vcmpgefp_p"
2363  [(set (reg:CC CR6_REGNO)
2364	(unspec:CC [(ge:CC (match_operand:V4SF 1 "register_operand" "v")
2365			   (match_operand:V4SF 2 "register_operand" "v"))]
2366		   UNSPEC_PREDICATE))
2367   (set (match_operand:V4SF 0 "register_operand" "=v")
2368	(ge:V4SF (match_dup 1)
2369		 (match_dup 2)))]
2370  "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2371  "vcmpgefp. %0,%1,%2"
2372  [(set_attr "type" "veccmp")])
2373
2374(define_insn "altivec_vcmpbfp_p"
2375  [(set (reg:CC CR6_REGNO)
2376	(unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
2377		    (match_operand:V4SF 2 "register_operand" "v")]
2378		   UNSPEC_VCMPBFP))
2379   (set (match_operand:V4SF 0 "register_operand" "=v")
2380        (unspec:V4SF [(match_dup 1)
2381                      (match_dup 2)] 
2382                      UNSPEC_VCMPBFP))]
2383  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
2384  "vcmpbfp. %0,%1,%2"
2385  [(set_attr "type" "veccmp")])
2386
2387(define_insn "altivec_mtvscr"
2388  [(set (reg:SI VSCR_REGNO)
2389	(unspec_volatile:SI
2390	 [(match_operand:V4SI 0 "register_operand" "v")] UNSPECV_MTVSCR))]
2391  "TARGET_ALTIVEC"
2392  "mtvscr %0"
2393  [(set_attr "type" "vecsimple")])
2394
2395(define_insn "altivec_mfvscr"
2396  [(set (match_operand:V8HI 0 "register_operand" "=v")
2397	(unspec_volatile:V8HI [(reg:SI VSCR_REGNO)] UNSPECV_MFVSCR))]
2398  "TARGET_ALTIVEC"
2399  "mfvscr %0"
2400  [(set_attr "type" "vecsimple")])
2401
2402(define_insn "altivec_dssall"
2403  [(unspec_volatile [(const_int 0)] UNSPECV_DSSALL)]
2404  "TARGET_ALTIVEC"
2405  "dssall"
2406  [(set_attr "type" "vecsimple")])
2407
2408(define_insn "altivec_dss"
2409  [(unspec_volatile [(match_operand:QI 0 "immediate_operand" "i")]
2410		    UNSPECV_DSS)]
2411  "TARGET_ALTIVEC"
2412  "dss %0"
2413  [(set_attr "type" "vecsimple")])
2414
2415(define_insn "altivec_dst"
2416  [(unspec [(match_operand 0 "register_operand" "b")
2417	    (match_operand:SI 1 "register_operand" "r")
2418	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DST)]
2419  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2420  "dst %0,%1,%2"
2421  [(set_attr "type" "vecsimple")])
2422
2423(define_insn "altivec_dstt"
2424  [(unspec [(match_operand 0 "register_operand" "b")
2425	    (match_operand:SI 1 "register_operand" "r")
2426	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTT)]
2427  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2428  "dstt %0,%1,%2"
2429  [(set_attr "type" "vecsimple")])
2430
2431(define_insn "altivec_dstst"
2432  [(unspec [(match_operand 0 "register_operand" "b")
2433	    (match_operand:SI 1 "register_operand" "r")
2434	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTST)]
2435  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2436  "dstst %0,%1,%2"
2437  [(set_attr "type" "vecsimple")])
2438
2439(define_insn "altivec_dststt"
2440  [(unspec [(match_operand 0 "register_operand" "b")
2441	    (match_operand:SI 1 "register_operand" "r")
2442	    (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTSTT)]
2443  "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2444  "dststt %0,%1,%2"
2445  [(set_attr "type" "vecsimple")])
2446
2447(define_expand "altivec_lvsl"
2448  [(use (match_operand:V16QI 0 "register_operand"))
2449   (use (match_operand:V16QI 1 "memory_operand"))]
2450  "TARGET_ALTIVEC"
2451{
2452  if (BYTES_BIG_ENDIAN)
2453    emit_insn (gen_altivec_lvsl_direct (operands[0], operands[1]));
2454  else
2455    {
2456      rtx mask, constv, vperm;
2457      mask = gen_reg_rtx (V16QImode);
2458      emit_insn (gen_altivec_lvsl_direct (mask, operands[1]));
2459      constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
2460      constv = force_reg (V16QImode, constv);
2461      vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2462                              UNSPEC_VPERM);
2463      emit_insn (gen_rtx_SET (operands[0], vperm));
2464    }
2465  DONE;
2466})
2467
2468(define_insn "altivec_lvsl_reg"
2469  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
2470	(unspec:V16QI
2471	[(match_operand:DI 1 "gpc_reg_operand" "b")]
2472	UNSPEC_LVSL_REG))]
2473  "TARGET_ALTIVEC"
2474  "lvsl %0,0,%1"
2475  [(set_attr "type" "vecload")])
2476
2477(define_insn "altivec_lvsl_direct"
2478  [(set (match_operand:V16QI 0 "register_operand" "=v")
2479	(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2480		      UNSPEC_LVSL))]
2481  "TARGET_ALTIVEC"
2482  "lvsl %0,%y1"
2483  [(set_attr "type" "vecload")])
2484
2485(define_expand "altivec_lvsr"
2486  [(use (match_operand:V16QI 0 "altivec_register_operand"))
2487   (use (match_operand:V16QI 1 "memory_operand"))]
2488  "TARGET_ALTIVEC"
2489{
2490  if (BYTES_BIG_ENDIAN)
2491    emit_insn (gen_altivec_lvsr_direct (operands[0], operands[1]));
2492  else
2493    {
2494      rtx mask, constv, vperm;
2495      mask = gen_reg_rtx (V16QImode);
2496      emit_insn (gen_altivec_lvsr_direct (mask, operands[1]));
2497      constv = gen_const_vec_series (V16QImode, const0_rtx, const1_rtx);
2498      constv = force_reg (V16QImode, constv);
2499      vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2500                              UNSPEC_VPERM);
2501      emit_insn (gen_rtx_SET (operands[0], vperm));
2502    }
2503  DONE;
2504})
2505
2506(define_insn "altivec_lvsr_reg"
2507  [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
2508       (unspec:V16QI
2509       [(match_operand:DI 1 "gpc_reg_operand" "b")]
2510       UNSPEC_LVSR_REG))]
2511  "TARGET_ALTIVEC"
2512  "lvsr %0,0,%1"
2513  [(set_attr "type" "vecload")])
2514
2515(define_insn "altivec_lvsr_direct"
2516  [(set (match_operand:V16QI 0 "register_operand" "=v")
2517	(unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2518		      UNSPEC_LVSR))]
2519  "TARGET_ALTIVEC"
2520  "lvsr %0,%y1"
2521  [(set_attr "type" "vecload")])
2522
2523(define_expand "build_vector_mask_for_load"
2524  [(set (match_operand:V16QI 0 "register_operand")
2525	(unspec:V16QI [(match_operand 1 "memory_operand")] UNSPEC_LVSR))]
2526  "TARGET_ALTIVEC"
2527{
2528  rtx addr;
2529  rtx temp;
2530
2531  gcc_assert (MEM_P (operands[1]));
2532
2533  addr = XEXP (operands[1], 0);
2534  temp = gen_reg_rtx (GET_MODE (addr));
2535  emit_insn (gen_rtx_SET (temp, gen_rtx_NEG (GET_MODE (addr), addr)));
2536  emit_insn (gen_altivec_lvsr (operands[0], 
2537			       replace_equiv_address (operands[1], temp)));
2538  DONE;
2539})
2540
2541;; Parallel some of the LVE* and STV*'s with unspecs because some have
2542;; identical rtl but different instructions-- and gcc gets confused.
2543
2544(define_insn "altivec_lve<VI_char>x"
2545  [(parallel
2546    [(set (match_operand:VI 0 "register_operand" "=v")
2547	  (match_operand:VI 1 "memory_operand" "Z"))
2548     (unspec [(const_int 0)] UNSPEC_LVE)])]
2549  "TARGET_ALTIVEC"
2550  "lve<VI_char>x %0,%y1"
2551  [(set_attr "type" "vecload")])
2552
2553(define_insn "*altivec_lvesfx"
2554  [(parallel
2555    [(set (match_operand:V4SF 0 "register_operand" "=v")
2556	  (match_operand:V4SF 1 "memory_operand" "Z"))
2557     (unspec [(const_int 0)] UNSPEC_LVE)])]
2558  "TARGET_ALTIVEC"
2559  "lvewx %0,%y1"
2560  [(set_attr "type" "vecload")])
2561
2562(define_insn "altivec_lvxl_<mode>"
2563  [(parallel
2564    [(set (match_operand:VM2 0 "register_operand" "=v")
2565	  (match_operand:VM2 1 "memory_operand" "Z"))
2566     (unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
2567  "TARGET_ALTIVEC"
2568  "lvxl %0,%y1"
2569  [(set_attr "type" "vecload")])
2570
2571; This version of lvx is used only in cases where we need to force an lvx
2572; over any other load, and we don't care about losing CSE opportunities.
2573; Its primary use is for prologue register saves.
2574(define_insn "altivec_lvx_<mode>_internal"
2575  [(parallel
2576    [(set (match_operand:VM2 0 "register_operand" "=v")
2577	  (match_operand:VM2 1 "memory_operand" "Z"))
2578     (unspec [(const_int 0)] UNSPEC_LVX)])]
2579  "TARGET_ALTIVEC"
2580  "lvx %0,%y1"
2581  [(set_attr "type" "vecload")])
2582
2583; The following patterns embody what lvx should usually look like.
2584(define_expand "altivec_lvx_<VM2:mode>"
2585  [(set (match_operand:VM2 0 "register_operand")
2586	(match_operand:VM2 1 "altivec_indexed_or_indirect_operand"))]
2587  "TARGET_ALTIVEC"
2588{
2589  rtx addr = XEXP (operand1, 0);
2590  if (rs6000_sum_of_two_registers_p (addr))
2591    {
2592      rtx op1 = XEXP (addr, 0);
2593      rtx op2 = XEXP (addr, 1);
2594      if (TARGET_64BIT)
2595	emit_insn (gen_altivec_lvx_<VM2:mode>_2op_di (operand0, op1, op2));
2596      else
2597	emit_insn (gen_altivec_lvx_<VM2:mode>_2op_si (operand0, op1, op2));
2598    }
2599  else
2600    {
2601      if (TARGET_64BIT)
2602	emit_insn (gen_altivec_lvx_<VM2:mode>_1op_di (operand0, addr));
2603      else
2604	emit_insn (gen_altivec_lvx_<VM2:mode>_1op_si (operand0, addr));
2605    }
2606  DONE;
2607})
2608
2609; The next two patterns embody what lvx should usually look like.
2610(define_insn "altivec_lvx_<VM2:mode>_2op_<P:mptrsize>"
2611  [(set (match_operand:VM2 0 "register_operand" "=v")
2612	(mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
2613				(match_operand:P 2 "register_operand" "r"))
2614			(const_int -16))))]
2615  "TARGET_ALTIVEC"
2616  "lvx %0,%1,%2"
2617  [(set_attr "type" "vecload")])
2618
2619(define_insn "altivec_lvx_<VM2:mode>_1op_<P:mptrsize>"
2620  [(set (match_operand:VM2 0 "register_operand" "=v")
2621	(mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
2622			(const_int -16))))]
2623  "TARGET_ALTIVEC"
2624  "lvx %0,0,%1"
2625  [(set_attr "type" "vecload")])
2626
2627; This version of stvx is used only in cases where we need to force an stvx
2628; over any other store, and we don't care about losing CSE opportunities.
2629; Its primary use is for epilogue register restores.
2630(define_insn "altivec_stvx_<mode>_internal"
2631  [(parallel
2632    [(set (match_operand:VM2 0 "memory_operand" "=Z")
2633	  (match_operand:VM2 1 "register_operand" "v"))
2634     (unspec [(const_int 0)] UNSPEC_STVX)])]
2635  "TARGET_ALTIVEC"
2636  "stvx %1,%y0"
2637  [(set_attr "type" "vecstore")])
2638
2639; The following patterns embody what stvx should usually look like.
2640(define_expand "altivec_stvx_<VM2:mode>"
2641  [(set (match_operand:VM2 1 "altivec_indexed_or_indirect_operand")
2642	(match_operand:VM2 0 "register_operand"))]
2643  "TARGET_ALTIVEC"
2644{
2645  rtx addr = XEXP (operand1, 0);
2646  if (rs6000_sum_of_two_registers_p (addr))
2647    {
2648      rtx op1 = XEXP (addr, 0);
2649      rtx op2 = XEXP (addr, 1);
2650      if (TARGET_64BIT)
2651	emit_insn (gen_altivec_stvx_<VM2:mode>_2op_di (operand0, op1, op2));
2652      else
2653	emit_insn (gen_altivec_stvx_<VM2:mode>_2op_si (operand0, op1, op2));
2654    }
2655  else
2656    {
2657      if (TARGET_64BIT)
2658	emit_insn (gen_altivec_stvx_<VM2:mode>_1op_di (operand0, addr));
2659      else
2660	emit_insn (gen_altivec_stvx_<VM2:mode>_1op_si (operand0, addr));
2661    }
2662  DONE;
2663})
2664
2665; The next two patterns embody what stvx should usually look like.
2666(define_insn "altivec_stvx_<VM2:mode>_2op_<P:mptrsize>"
2667  [(set (mem:VM2 (and:P (plus:P (match_operand:P 1 "register_operand" "b")
2668				(match_operand:P 2 "register_operand" "r"))
2669			(const_int -16)))
2670	(match_operand:VM2 0 "register_operand" "v"))]
2671  "TARGET_ALTIVEC"
2672  "stvx %0,%1,%2"
2673  [(set_attr "type" "vecstore")])
2674
2675(define_insn "altivec_stvx_<VM2:mode>_1op_<P:mptrsize>"
2676  [(set (mem:VM2 (and:P (match_operand:P 1 "register_operand" "r")
2677			(const_int -16)))
2678	(match_operand:VM2 0 "register_operand" "v"))]
2679  "TARGET_ALTIVEC"
2680  "stvx %0,0,%1"
2681  [(set_attr "type" "vecstore")])
2682
2683(define_insn "altivec_stvxl_<mode>"
2684  [(parallel
2685    [(set (match_operand:VM2 0 "memory_operand" "=Z")
2686	  (match_operand:VM2 1 "register_operand" "v"))
2687     (unspec [(const_int 0)] UNSPEC_STVXL)])]
2688  "TARGET_ALTIVEC"
2689  "stvxl %1,%y0"
2690  [(set_attr "type" "vecstore")])
2691
2692(define_insn "altivec_stve<VI_char>x"
2693  [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
2694	(unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
2695  "TARGET_ALTIVEC"
2696  "stve<VI_char>x %1,%y0"
2697  [(set_attr "type" "vecstore")])
2698
2699(define_insn "*altivec_stvesfx"
2700  [(set (match_operand:SF 0 "memory_operand" "=Z")
2701	(unspec:SF [(match_operand:V4SF 1 "register_operand" "v")] UNSPEC_STVE))]
2702  "TARGET_ALTIVEC"
2703  "stvewx %1,%y0"
2704  [(set_attr "type" "vecstore")])
2705
2706;; Generate doublee
2707;; signed int/float to double convert words 0 and 2
2708(define_expand "doublee<mode>2"
2709  [(set (match_operand:V2DF 0 "register_operand" "=v")
2710	(match_operand:VSX_W 1 "register_operand" "v"))]
2711  "TARGET_VSX"
2712{
2713  machine_mode op_mode = GET_MODE (operands[1]);
2714
2715  if (BYTES_BIG_ENDIAN)
2716    {
2717      /* Big endian word numbering for words in operand is 0 1 2 3.
2718	 Input words 0 and 2 are where they need to be.  */
2719      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], operands[1]));
2720    }
2721  else
2722    {
2723      /* Little endian word numbering for operand is 3 2 1 0.
2724	 take (operand[1] operand[1]) and shift left one word
2725	 3 2 1 0    3 2 1 0  =>  2 1 0 3
2726	 Input words 2 and 0 are now where they need to be for the
2727	 conversion.  */
2728      rtx rtx_tmp;
2729      rtx rtx_val = GEN_INT (1);
2730
2731      rtx_tmp = gen_reg_rtx (op_mode);
2732      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2733					 operands[1], rtx_val));
2734      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2735    }
2736  DONE;
2737}
2738  [(set_attr "type" "veccomplex")])
2739
2740;; Generate unsdoublee
2741;; unsigned int to double convert words 0 and 2
2742(define_expand "unsdoubleev4si2"
2743  [(set (match_operand:V2DF 0 "register_operand" "=v")
2744	(match_operand:V4SI 1 "register_operand" "v"))]
2745  "TARGET_VSX"
2746{
2747  if (BYTES_BIG_ENDIAN)
2748    {
2749      /* Big endian word numbering for words in operand is 0 1 2 3.
2750	 Input words 0 and 2 are where they need to be.  */
2751      emit_insn (gen_vsx_xvcvuxwdp (operands[0], operands[1]));
2752    }
2753  else
2754    {
2755      /* Little endian word numbering for operand is 3 2 1 0.
2756	 take (operand[1] operand[1]) and shift left one word
2757	 3 2 1 0    3 2 1 0  =>   2 1 0 3
2758	 Input words 2 and 0 are now where they need to be for the
2759	 conversion.  */
2760      rtx rtx_tmp;
2761      rtx rtx_val = GEN_INT (1);
2762
2763      rtx_tmp = gen_reg_rtx (V4SImode);
2764      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2765				       operands[1], rtx_val));
2766      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2767    }
2768  DONE;
2769}
2770  [(set_attr "type" "veccomplex")])
2771
2772;; Generate doubleov
2773;; signed int/float to double convert words 1 and 3
2774(define_expand "doubleo<mode>2"
2775  [(set (match_operand:V2DF 0 "register_operand" "=v")
2776	(match_operand:VSX_W 1 "register_operand" "v"))]
2777  "TARGET_VSX"
2778{
2779  machine_mode op_mode = GET_MODE (operands[1]);
2780
2781  if (BYTES_BIG_ENDIAN)
2782    {
2783      /* Big endian word numbering for words in operand is 0 1 2 3.
2784	 take (operand[1] operand[1]) and shift left one word
2785	 0 1 2 3    0 1 2 3  =>  1 2 3 0
2786	 Input words 1 and 3 are now where they need to be for the
2787	 conversion.  */
2788      rtx rtx_tmp;
2789      rtx rtx_val = GEN_INT (1);
2790
2791      rtx_tmp = gen_reg_rtx (op_mode);
2792      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2793					 operands[1], rtx_val));
2794      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2795    }
2796  else
2797    {
2798      /* Little endian word numbering for operand is 3 2 1 0.
2799	 Input words 3 and 1 are where they need to be.  */
2800      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], operands[1]));
2801    }
2802  DONE;
2803}
2804  [(set_attr "type" "veccomplex")])
2805
2806;; Generate unsdoubleov
2807;; unsigned int to double convert words 1 and 3
2808(define_expand "unsdoubleov4si2"
2809  [(set (match_operand:V2DF 0 "register_operand" "=v")
2810	(match_operand:V4SI 1 "register_operand" "v"))]
2811  "TARGET_VSX"
2812{
2813  if (BYTES_BIG_ENDIAN)
2814    {
2815      /* Big endian word numbering for words in operand is 0 1 2 3.
2816	 take (operand[1] operand[1]) and shift left one word
2817	 0 1 2 3    0 1 2 3  =>  1 2 3 0
2818	 Input words 1 and 3 are now where they need to be for the
2819	 conversion.  */
2820      rtx rtx_tmp;
2821      rtx rtx_val = GEN_INT (1);
2822
2823      rtx_tmp = gen_reg_rtx (V4SImode);
2824      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2825				       operands[1], rtx_val));
2826      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2827    }
2828  else
2829    {
2830      /* Want to convert the words 1 and 3.
2831	 Little endian word numbering for operand is 3 2 1 0.
2832	 Input words 3 and 1 are where they need to be.  */
2833      emit_insn (gen_vsx_xvcvuxwdp (operands[0], operands[1]));
2834    }
2835  DONE;
2836}
2837  [(set_attr "type" "veccomplex")])
2838
2839;; Generate doublehv
2840;; signed int/float to double convert words 0 and 1
2841(define_expand "doubleh<mode>2"
2842  [(set (match_operand:V2DF 0 "register_operand" "=v")
2843	(match_operand:VSX_W 1 "register_operand" "v"))]
2844  "TARGET_VSX"
2845{
2846  rtx rtx_tmp;
2847  rtx rtx_val;
2848
2849  machine_mode op_mode = GET_MODE (operands[1]);
2850  rtx_tmp = gen_reg_rtx (op_mode);
2851
2852  if (BYTES_BIG_ENDIAN)
2853    {
2854      /* Big endian word numbering for words in operand is 0 1 2 3.
2855	 Shift operand left one word, rtx_tmp word order is now 1 2 3 0.
2856	 take (rts_tmp operand[1]) and shift left three words
2857	 1 2 3 0  0 1 2 3 => 0 0 1 2
2858	 Input words 0 and 1 are now where they need to be for the
2859	 conversion.  */
2860      rtx_val = GEN_INT (1);
2861      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2862					 operands[1], rtx_val));
2863
2864      rtx_val = GEN_INT (3);
2865      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, rtx_tmp,
2866					 operands[1], rtx_val));
2867      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2868    }
2869  else
2870    {
2871      /* Little endian word numbering for operand is 3 2 1 0.
2872	 Shift operand left three words, rtx_tmp word order is now 0 3 2 1.
2873	 take (operand[1] rts_tmp) and shift left two words
2874	 3 2 1 0  0 3 2 1   =>  1 0 0 3
2875	 Input words 0 and 1 are now where they need to be for the
2876	 conversion.  */
2877      rtx_val = GEN_INT (3);
2878      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2879					 operands[1], rtx_val));
2880
2881      rtx_val = GEN_INT (2);
2882      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2883					 rtx_tmp, rtx_val));
2884      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2885    }
2886  DONE;
2887}
2888  [(set_attr "type" "veccomplex")])
2889
2890;; Generate unsdoublehv
2891;; unsigned int to double convert words 0 and 1
2892(define_expand "unsdoublehv4si2"
2893  [(set (match_operand:V2DF 0 "register_operand" "=v")
2894	(match_operand:V4SI 1 "register_operand" "v"))]
2895  "TARGET_VSX"
2896{
2897  rtx rtx_tmp = gen_reg_rtx (V4SImode);
2898  rtx rtx_val = GEN_INT (12);
2899
2900  if (BYTES_BIG_ENDIAN)
2901    {
2902      /* Big endian word numbering for words in operand is 0 1 2 3.
2903	 Shift operand left one word, rtx_tmp word order is now 1 2 3 0.
2904	 take (rts_tmp operand[1]) and shift left three words
2905	 1 2 3 0  0 1 2 3 => 0 0 1 2
2906	 Input words 0 and 1 are now where they need to be for the
2907	 conversion.  */
2908      rtx_val = GEN_INT (1);
2909      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2910				       operands[1], rtx_val));
2911
2912      rtx_val = GEN_INT (3);
2913      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, rtx_tmp,
2914				       operands[1], rtx_val));
2915      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2916    }
2917  else
2918    {
2919      /* Little endian word numbering for operand is 3 2 1 0.
2920	 Shift operand left three words, rtx_tmp word order is now 0 3 2 1.
2921	 take (operand[1] rts_tmp) and shift left two words
2922	 3 2 1 0   0 3 2 1  =>   1 0 0 3
2923	 Input words 1 and 0 are now where they need to be for the
2924	 conversion.  */
2925      rtx_val = GEN_INT (3);
2926
2927      rtx_tmp = gen_reg_rtx (V4SImode);
2928      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2929				       operands[1], rtx_val));
2930
2931      rtx_val = GEN_INT (2);
2932      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
2933				       rtx_tmp, rtx_val));
2934      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
2935    }
2936  DONE;
2937}
2938  [(set_attr "type" "veccomplex")])
2939
2940;; Generate doublelv
2941;; signed int/float to double convert words 2 and 3
2942(define_expand "doublel<mode>2"
2943  [(set (match_operand:V2DF 0 "register_operand" "=v")
2944	(match_operand:VSX_W 1 "register_operand" "v"))]
2945  "TARGET_VSX"
2946{
2947  rtx rtx_tmp;
2948  rtx rtx_val = GEN_INT (3);
2949
2950  machine_mode op_mode = GET_MODE (operands[1]);
2951  rtx_tmp = gen_reg_rtx (op_mode);
2952
2953  if (BYTES_BIG_ENDIAN)
2954    {
2955      /* Big endian word numbering for operand is 0 1 2 3.
2956	 Shift operand left three words, rtx_tmp word order is now 3 0 1 2.
2957	 take (operand[1] rtx_tmp) and shift left two words
2958	 0 1 2 3   3 0 1 2  =>  2 3 3 0
2959	 now use convert instruction to convert word 2 and 3 in the
2960	 input vector.  */
2961      rtx_val = GEN_INT (3);
2962      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2963					 operands[1], rtx_val));
2964
2965      rtx_val = GEN_INT (2);
2966      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2967					 rtx_tmp, rtx_val));
2968      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2969    }
2970  else
2971    {
2972      /* Little endian word numbering for operand is 3 2 1 0.
2973	 Shift operand left one word, rtx_tmp word order is now  2 1 0 3.
2974	 take (rtx_tmp operand[1]) and shift left three words
2975	 2 1 0 3  3 2 1 0  =>  3 3 2 1
2976	 now use convert instruction to convert word 3 and 2 in the
2977	 input vector.  */
2978      rtx_val = GEN_INT (1);
2979      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, operands[1],
2980					 operands[1], rtx_val));
2981
2982      rtx_val = GEN_INT (3);
2983      emit_insn (gen_vsx_xxsldwi_<mode> (rtx_tmp, rtx_tmp,
2984					 operands[1], rtx_val));
2985      emit_insn (gen_vsx_xvcv<VS_sxwsp>dp (operands[0], rtx_tmp));
2986    }
2987  DONE;
2988}
2989  [(set_attr "type" "veccomplex")])
2990
2991;; Generate unsdoublelv
2992;; unsigned int to double convert convert 2 and 3
2993(define_expand "unsdoublelv4si2"
2994  [(set (match_operand:V2DF 0 "register_operand" "=v")
2995	(match_operand:V4SI 1 "register_operand" "v"))]
2996  "TARGET_VSX"
2997{
2998  rtx rtx_tmp = gen_reg_rtx (V4SImode);
2999  rtx rtx_val = GEN_INT (12);
3000
3001  if (BYTES_BIG_ENDIAN)
3002    {
3003      /* Big endian word numbering for operand is 0 1 2 3.
3004	 Shift operand left three words, rtx_tmp word order is now 3 0 1 2.
3005	 take (operand[1] rtx_tmp) and shift left two words
3006	 0 1 2 3   3 0 1 2  =>  2 3 3 0
3007	 now use convert instruction to convert word 2 and 3 in the
3008	 input vector.  */
3009      rtx_val = GEN_INT (3);
3010      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
3011				       operands[1], rtx_val));
3012
3013      rtx_val = GEN_INT (2);
3014      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, operands[1],
3015				       rtx_tmp, rtx_val));
3016      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
3017    }
3018  else
3019    {
3020      /* Little endian word numbering for operand is 3 2 1 0.
3021	 Shift operand left one word, rtx_tmp word order is now 2 1 0 3.
3022	 take (rtx_tmp operand[1]) and shift left three words
3023	 2 1 0 3  3 2 1 0  =>   3 3 2 1
3024	 now use convert instruction to convert word 3 and 2 in the
3025	 input vector.  */
3026      rtx_val = GEN_INT (1);
3027      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp,
3028      operands[1], operands[1], rtx_val));
3029
3030      rtx_val = GEN_INT (3);
3031      emit_insn (gen_vsx_xxsldwi_v4si (rtx_tmp, rtx_tmp,
3032				       operands[1], rtx_val));
3033      emit_insn (gen_vsx_xvcvuxwdp (operands[0], rtx_tmp));
3034    }
3035  DONE;
3036}
3037  [(set_attr "type" "veccomplex")])
3038
3039;; Generate two vector F32 converted to packed vector I16 vector
3040(define_expand "convert_4f32_8i16"
3041  [(set (match_operand:V8HI 0 "register_operand" "=v")
3042	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "v")
3043		      (match_operand:V4SF 2 "register_operand" "v")]
3044		     UNSPEC_CONVERT_4F32_8I16))]
3045  "TARGET_P9_VECTOR"
3046{
3047  rtx rtx_tmp_hi = gen_reg_rtx (V4SImode);
3048  rtx rtx_tmp_lo = gen_reg_rtx (V4SImode);
3049
3050  emit_insn (gen_altivec_vctuxs (rtx_tmp_hi, operands[1], const0_rtx));
3051  emit_insn (gen_altivec_vctuxs (rtx_tmp_lo, operands[2], const0_rtx));
3052  emit_insn (gen_altivec_vpkswss (operands[0], rtx_tmp_hi, rtx_tmp_lo));
3053  DONE;
3054})
3055
3056;; Convert two vector F32 to packed vector F16.
3057;; This builtin packs 32-bit floating-point values into a packed
3058;; 16-bit floating point values (stored in 16bit integer type).
3059;; (vector unsigned short r = vec_pack_to_short_fp32 (a, b);
3060;; The expected codegen for this builtin is
3061;;    xvcvsphp t, a
3062;;    xvcvsphp u, b
3063;;    if (little endian)
3064;;      vpkuwum r, t, u
3065;;    else
3066;;      vpkuwum r, u, t
3067
3068(define_expand "convert_4f32_8f16"
3069  [(set (match_operand:V8HI 0 "register_operand" "=v")
3070	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "v")
3071		      (match_operand:V4SF 2 "register_operand" "v")]
3072		     UNSPEC_CONVERT_4F32_8F16))]
3073  "TARGET_P9_VECTOR"
3074{
3075  rtx rtx_tmp_hi = gen_reg_rtx (V4SImode);
3076  rtx rtx_tmp_lo = gen_reg_rtx (V4SImode);
3077
3078  emit_insn (gen_vsx_xvcvsphp (rtx_tmp_hi, operands[1]));
3079  emit_insn (gen_vsx_xvcvsphp (rtx_tmp_lo, operands[2]));
3080  if (!BYTES_BIG_ENDIAN)
3081    emit_insn (gen_altivec_vpkuwum (operands[0], rtx_tmp_hi, rtx_tmp_lo));
3082  else
3083    emit_insn (gen_altivec_vpkuwum (operands[0], rtx_tmp_lo, rtx_tmp_hi));
3084  DONE;
3085})
3086
3087;; Generate
3088;;    xxlxor/vxor SCRATCH0,SCRATCH0,SCRATCH0
3089;;    vsubu?m SCRATCH2,SCRATCH1,%1
3090;;    vmaxs? %0,%1,SCRATCH2"
3091(define_expand "abs<mode>2"
3092  [(set (match_dup 2) (match_dup 3))
3093   (set (match_dup 4)
3094        (minus:VI2 (match_dup 2)
3095		   (match_operand:VI2 1 "register_operand" "v")))
3096   (set (match_operand:VI2 0 "register_operand" "=v")
3097        (smax:VI2 (match_dup 1) (match_dup 4)))]
3098  "<VI_unit>"
3099{
3100  operands[2] = gen_reg_rtx (<MODE>mode);
3101  operands[3] = CONST0_RTX (<MODE>mode);
3102  operands[4] = gen_reg_rtx (<MODE>mode);
3103})
3104
3105;; Generate
3106;;    vspltisw SCRATCH1,0
3107;;    vsubu?m SCRATCH2,SCRATCH1,%1
3108;;    vmins? %0,%1,SCRATCH2"
3109(define_expand "nabs<mode>2"
3110  [(set (match_dup 2) (match_dup 3))
3111   (set (match_dup 4)
3112        (minus:VI2 (match_dup 2)
3113		   (match_operand:VI2 1 "register_operand" "v")))
3114   (set (match_operand:VI2 0 "register_operand" "=v")
3115        (smin:VI2 (match_dup 1) (match_dup 4)))]
3116  "<VI_unit>"
3117{
3118  operands[2] = gen_reg_rtx (<MODE>mode);
3119  operands[3] = CONST0_RTX (<MODE>mode);
3120  operands[4] = gen_reg_rtx (<MODE>mode);
3121})
3122
3123;; Generate
3124;;    vspltisw SCRATCH1,-1
3125;;    vslw SCRATCH2,SCRATCH1,SCRATCH1
3126;;    vandc %0,%1,SCRATCH2
3127(define_expand "altivec_absv4sf2"
3128  [(set (match_dup 2)
3129	(vec_duplicate:V4SI (const_int -1)))
3130   (set (match_dup 3)
3131        (ashift:V4SI (match_dup 2) (match_dup 2)))
3132   (set (match_operand:V4SF 0 "register_operand" "=v")
3133        (and:V4SF (not:V4SF (subreg:V4SF (match_dup 3) 0))
3134                  (match_operand:V4SF 1 "register_operand" "v")))]
3135  "TARGET_ALTIVEC"
3136{
3137  operands[2] = gen_reg_rtx (V4SImode);
3138  operands[3] = gen_reg_rtx (V4SImode);
3139})
3140
3141;; Generate
3142;;    vspltis? SCRATCH0,0
3143;;    vsubs?s SCRATCH2,SCRATCH1,%1
3144;;    vmaxs? %0,%1,SCRATCH2"
3145(define_expand "altivec_abss_<mode>"
3146  [(set (match_dup 2) (vec_duplicate:VI (const_int 0)))
3147   (parallel [(set (match_dup 3)
3148		   (unspec:VI [(match_dup 2)
3149			       (match_operand:VI 1 "register_operand" "v")]
3150			      UNSPEC_VSUBS))
3151	      (set (reg:SI VSCR_REGNO)
3152		   (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))])
3153   (set (match_operand:VI 0 "register_operand" "=v")
3154        (smax:VI (match_dup 1) (match_dup 3)))]
3155  "TARGET_ALTIVEC"
3156{
3157  operands[2] = gen_reg_rtx (GET_MODE (operands[0]));
3158  operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
3159})
3160
3161(define_expand "reduc_plus_scal_<mode>"
3162  [(set (match_operand:<VI_scalar> 0 "register_operand" "=v")
3163        (unspec:VIshort [(match_operand:VIshort 1 "register_operand" "v")]
3164			UNSPEC_REDUC_PLUS))]
3165  "TARGET_ALTIVEC"
3166{
3167  rtx vzero = gen_reg_rtx (V4SImode);
3168  rtx vtmp1 = gen_reg_rtx (V4SImode);
3169  rtx vtmp2 = gen_reg_rtx (<MODE>mode);
3170  rtx dest = gen_lowpart (V4SImode, vtmp2);
3171  int elt = BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (<MODE>mode) - 1 : 0;
3172
3173  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3174  emit_insn (gen_altivec_vsum4s<VI_char>s (vtmp1, operands[1], vzero));
3175  emit_insn (gen_altivec_vsumsws_direct (dest, vtmp1, vzero));
3176  rs6000_expand_vector_extract (operands[0], vtmp2, GEN_INT (elt));
3177  DONE;
3178})
3179
3180(define_insn "*p9_neg<mode>2"
3181  [(set (match_operand:VNEG 0 "altivec_register_operand" "=v")
3182	(neg:VNEG (match_operand:VNEG 1 "altivec_register_operand" "v")))]
3183  "TARGET_P9_VECTOR"
3184  "vneg<VI_char> %0,%1"
3185  [(set_attr "type" "vecsimple")])
3186
3187(define_expand "neg<mode>2"
3188  [(set (match_operand:VI2 0 "register_operand")
3189	(neg:VI2 (match_operand:VI2 1 "register_operand")))]
3190  "<VI_unit>"
3191{
3192  if (!TARGET_P9_VECTOR || (<MODE>mode != V4SImode && <MODE>mode != V2DImode))
3193    {
3194      rtx vzero;
3195
3196      vzero = gen_reg_rtx (GET_MODE (operands[0]));
3197      emit_move_insn (vzero, CONST0_RTX (<MODE>mode));
3198      emit_insn (gen_sub<mode>3 (operands[0], vzero, operands[1]));
3199      DONE;
3200    }
3201})
3202
3203(define_expand "udot_prod<mode>"
3204  [(set (match_operand:V4SI 0 "register_operand" "=v")
3205        (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
3206                   (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")  
3207                                 (match_operand:VIshort 2 "register_operand" "v")] 
3208                                UNSPEC_VMSUMU)))]
3209  "TARGET_ALTIVEC"
3210{
3211  emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], operands[2], operands[3]));
3212  DONE;
3213})
3214
3215(define_expand "sdot_prodv8hi"
3216  [(set (match_operand:V4SI 0 "register_operand" "=v")
3217        (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
3218                   (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3219                                 (match_operand:V8HI 2 "register_operand" "v")]
3220                                UNSPEC_VMSUMSHM)))]
3221  "TARGET_ALTIVEC"
3222{
3223  emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], operands[2], operands[3]));
3224  DONE;
3225})
3226
3227(define_expand "widen_usum<mode>3"
3228  [(set (match_operand:V4SI 0 "register_operand" "=v")
3229        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3230                   (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")]
3231                                UNSPEC_VMSUMU)))]
3232  "TARGET_ALTIVEC"
3233{
3234  rtx vones = gen_reg_rtx (GET_MODE (operands[1]));
3235
3236  emit_insn (gen_altivec_vspltis<VI_char> (vones, const1_rtx));
3237  emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], vones, operands[2]));
3238  DONE;
3239})
3240
3241(define_expand "widen_ssumv16qi3"
3242  [(set (match_operand:V4SI 0 "register_operand" "=v")
3243        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3244                   (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")]
3245                                UNSPEC_VMSUMM)))]
3246  "TARGET_ALTIVEC"
3247{
3248  rtx vones = gen_reg_rtx (V16QImode);
3249
3250  emit_insn (gen_altivec_vspltisb (vones, const1_rtx));
3251  emit_insn (gen_altivec_vmsummbm (operands[0], operands[1], vones, operands[2]));
3252  DONE;
3253})
3254
3255(define_expand "widen_ssumv8hi3"
3256  [(set (match_operand:V4SI 0 "register_operand" "=v")
3257        (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
3258                   (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3259                                UNSPEC_VMSUMSHM)))]
3260  "TARGET_ALTIVEC"
3261{
3262  rtx vones = gen_reg_rtx (V8HImode);
3263
3264  emit_insn (gen_altivec_vspltish (vones, const1_rtx));
3265  emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], vones, operands[2]));
3266  DONE;
3267})
3268
3269(define_expand "vec_unpacks_hi_<VP_small_lc>"
3270  [(set (match_operand:VP 0 "register_operand" "=v")
3271        (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
3272		   UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
3273  "<VI_unit>"
3274  "")
3275
3276(define_expand "vec_unpacks_lo_<VP_small_lc>"
3277  [(set (match_operand:VP 0 "register_operand" "=v")
3278        (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
3279		   UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
3280  "<VI_unit>"
3281  "")
3282
3283(define_insn "vperm_v8hiv4si"
3284  [(set (match_operand:V4SI 0 "register_operand" "=v,?wa")
3285        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v,wa")
3286		      (match_operand:V4SI 2 "register_operand" "v,0")
3287		      (match_operand:V16QI 3 "register_operand" "v,wa")]
3288                  UNSPEC_VPERMSI))]
3289  "TARGET_ALTIVEC"
3290  "@
3291   vperm %0,%1,%2,%3
3292   xxperm %x0,%x1,%x3"
3293  [(set_attr "type" "vecperm")
3294   (set_attr "isa" "*,p9v")])
3295
3296(define_insn "vperm_v16qiv8hi"
3297  [(set (match_operand:V8HI 0 "register_operand" "=v,?wa")
3298        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v,wa")
3299		      (match_operand:V8HI 2 "register_operand" "v,0")
3300		      (match_operand:V16QI 3 "register_operand" "v,wa")]
3301                  UNSPEC_VPERMHI))]
3302  "TARGET_ALTIVEC"
3303  "@
3304   vperm %0,%1,%2,%3
3305   xxperm %x0,%x1,%x3"
3306  [(set_attr "type" "vecperm")
3307   (set_attr "isa" "*,p9v")])
3308
3309
3310(define_expand "vec_unpacku_hi_v16qi"
3311  [(set (match_operand:V8HI 0 "register_operand" "=v")
3312        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
3313                     UNSPEC_VUPKHUB))]
3314  "TARGET_ALTIVEC"      
3315{  
3316  rtx vzero = gen_reg_rtx (V8HImode);
3317  rtx mask = gen_reg_rtx (V16QImode);
3318  rtvec v = rtvec_alloc (16);
3319  bool be = BYTES_BIG_ENDIAN;
3320   
3321  emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
3322   
3323  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
3324  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  0 : 16);
3325  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 :  6);
3326  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
3327  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
3328  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ?  2 : 16);
3329  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 :  4);
3330  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
3331  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
3332  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ?  4 : 16);
3333  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 :  2);
3334  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
3335  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
3336  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ?  6 : 16);
3337  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  0);
3338  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
3339
3340  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3341  emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
3342  DONE;
3343})
3344
3345(define_expand "vec_unpacku_hi_v8hi"
3346  [(set (match_operand:V4SI 0 "register_operand" "=v")
3347        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3348                     UNSPEC_VUPKHUH))]
3349  "TARGET_ALTIVEC"
3350{
3351  rtx vzero = gen_reg_rtx (V4SImode);
3352  rtx mask = gen_reg_rtx (V16QImode);
3353  rtvec v = rtvec_alloc (16);
3354  bool be = BYTES_BIG_ENDIAN;
3355
3356  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3357 
3358  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
3359  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 :  6);
3360  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  0 : 17);
3361  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
3362  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
3363  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 :  4);
3364  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ?  2 : 17);
3365  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
3366  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
3367  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 :  2);
3368  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ?  4 : 17);
3369  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
3370  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
3371  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  0);
3372  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ?  6 : 17);
3373  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
3374
3375  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3376  emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
3377  DONE;
3378})
3379
3380(define_expand "vec_unpacku_lo_v16qi"
3381  [(set (match_operand:V8HI 0 "register_operand" "=v")
3382        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
3383                     UNSPEC_VUPKLUB))]
3384  "TARGET_ALTIVEC"
3385{
3386  rtx vzero = gen_reg_rtx (V8HImode);
3387  rtx mask = gen_reg_rtx (V16QImode);
3388  rtvec v = rtvec_alloc (16);
3389  bool be = BYTES_BIG_ENDIAN;
3390
3391  emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
3392
3393  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
3394  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  8 : 16);
3395  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14);
3396  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
3397  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
3398  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16);
3399  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12);
3400  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
3401  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
3402  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16);
3403  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10);
3404  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
3405  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
3406  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16);
3407  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  8);
3408  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
3409
3410  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3411  emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
3412  DONE;
3413})
3414
3415(define_expand "vec_unpacku_lo_v8hi"
3416  [(set (match_operand:V4SI 0 "register_operand" "=v")
3417        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
3418                     UNSPEC_VUPKLUH))]
3419  "TARGET_ALTIVEC"
3420{
3421  rtx vzero = gen_reg_rtx (V4SImode);
3422  rtx mask = gen_reg_rtx (V16QImode);
3423  rtvec v = rtvec_alloc (16);
3424  bool be = BYTES_BIG_ENDIAN;
3425
3426  emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
3427 
3428  RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
3429  RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14);
3430  RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  8 : 17);
3431  RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
3432  RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
3433  RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12);
3434  RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17);
3435  RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
3436  RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
3437  RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10);
3438  RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17);
3439  RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
3440  RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
3441  RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  8);
3442  RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17);
3443  RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
3444
3445  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3446  emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
3447  DONE;
3448})
3449
3450(define_expand "vec_widen_umult_hi_v16qi"
3451  [(set (match_operand:V8HI 0 "register_operand" "=v")
3452        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3453                      (match_operand:V16QI 2 "register_operand" "v")]
3454                     UNSPEC_VMULWHUB))]
3455  "TARGET_ALTIVEC"
3456{
3457  rtx ve = gen_reg_rtx (V8HImode);
3458  rtx vo = gen_reg_rtx (V8HImode);
3459  
3460  if (BYTES_BIG_ENDIAN)
3461    {
3462      emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
3463      emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
3464      emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
3465    }
3466  else
3467    {
3468      emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
3469      emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
3470      emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
3471    }
3472  DONE;
3473})
3474
3475(define_expand "vec_widen_umult_lo_v16qi"
3476  [(set (match_operand:V8HI 0 "register_operand" "=v")
3477        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3478                      (match_operand:V16QI 2 "register_operand" "v")]
3479                     UNSPEC_VMULWLUB))]
3480  "TARGET_ALTIVEC"
3481{
3482  rtx ve = gen_reg_rtx (V8HImode);
3483  rtx vo = gen_reg_rtx (V8HImode);
3484  
3485  if (BYTES_BIG_ENDIAN)
3486    {
3487      emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
3488      emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
3489      emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
3490    }
3491  else
3492    {
3493      emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
3494      emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
3495      emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
3496    }
3497  DONE;
3498})
3499
3500(define_expand "vec_widen_smult_hi_v16qi"
3501  [(set (match_operand:V8HI 0 "register_operand" "=v")
3502        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3503                      (match_operand:V16QI 2 "register_operand" "v")]
3504                     UNSPEC_VMULWHSB))]
3505  "TARGET_ALTIVEC"
3506{
3507  rtx ve = gen_reg_rtx (V8HImode);
3508  rtx vo = gen_reg_rtx (V8HImode);
3509  
3510  if (BYTES_BIG_ENDIAN)
3511    {
3512      emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
3513      emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
3514      emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
3515    }
3516  else
3517    {
3518      emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
3519      emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
3520      emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
3521    }
3522  DONE;
3523})
3524
3525(define_expand "vec_widen_smult_lo_v16qi"
3526  [(set (match_operand:V8HI 0 "register_operand" "=v")
3527        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
3528                      (match_operand:V16QI 2 "register_operand" "v")]
3529                     UNSPEC_VMULWLSB))]
3530  "TARGET_ALTIVEC"
3531{
3532  rtx ve = gen_reg_rtx (V8HImode);
3533  rtx vo = gen_reg_rtx (V8HImode);
3534  
3535  if (BYTES_BIG_ENDIAN)
3536    {
3537      emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
3538      emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
3539      emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
3540    }
3541  else
3542    {
3543      emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
3544      emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
3545      emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
3546    }
3547  DONE;
3548})
3549
3550(define_expand "vec_widen_umult_hi_v8hi"
3551  [(set (match_operand:V4SI 0 "register_operand" "=v")
3552        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3553                      (match_operand:V8HI 2 "register_operand" "v")]
3554                     UNSPEC_VMULWHUH))]
3555  "TARGET_ALTIVEC"
3556{ 
3557  rtx ve = gen_reg_rtx (V4SImode);
3558  rtx vo = gen_reg_rtx (V4SImode);
3559  
3560  if (BYTES_BIG_ENDIAN)
3561    {
3562      emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3563      emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3564      emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3565    }
3566  else
3567    {
3568      emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3569      emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3570      emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3571    }
3572  DONE;
3573})
3574
3575(define_expand "vec_widen_umult_lo_v8hi"
3576  [(set (match_operand:V4SI 0 "register_operand" "=v")
3577        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3578                      (match_operand:V8HI 2 "register_operand" "v")]
3579                     UNSPEC_VMULWLUH))]
3580  "TARGET_ALTIVEC"
3581{ 
3582  rtx ve = gen_reg_rtx (V4SImode);
3583  rtx vo = gen_reg_rtx (V4SImode);
3584  
3585  if (BYTES_BIG_ENDIAN)
3586    {
3587      emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3588      emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3589      emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3590    }
3591  else
3592    {
3593      emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3594      emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3595      emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3596    }
3597  DONE;
3598})
3599
3600(define_expand "vec_widen_smult_hi_v8hi"
3601  [(set (match_operand:V4SI 0 "register_operand" "=v")
3602        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3603                      (match_operand:V8HI 2 "register_operand" "v")]
3604                     UNSPEC_VMULWHSH))]
3605  "TARGET_ALTIVEC"
3606{ 
3607  rtx ve = gen_reg_rtx (V4SImode);
3608  rtx vo = gen_reg_rtx (V4SImode);
3609  
3610  if (BYTES_BIG_ENDIAN)
3611    {
3612      emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3613      emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3614      emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3615    }
3616  else
3617    {
3618      emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3619      emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3620      emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3621    }
3622  DONE;
3623})
3624
3625(define_expand "vec_widen_smult_lo_v8hi"
3626  [(set (match_operand:V4SI 0 "register_operand" "=v")
3627        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3628                      (match_operand:V8HI 2 "register_operand" "v")]
3629                     UNSPEC_VMULWLSH))]
3630  "TARGET_ALTIVEC"
3631{ 
3632  rtx ve = gen_reg_rtx (V4SImode);
3633  rtx vo = gen_reg_rtx (V4SImode);
3634  
3635  if (BYTES_BIG_ENDIAN)
3636    {
3637      emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3638      emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3639      emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3640    }
3641  else
3642    {
3643      emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3644      emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3645      emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3646    }
3647  DONE;
3648})
3649
3650(define_expand "vec_pack_trunc_<mode>"
3651  [(set (match_operand:<VP_small> 0 "register_operand" "=v")
3652        (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
3653			    (match_operand:VP 2 "register_operand" "v")]
3654                      UNSPEC_VPACK_UNS_UNS_MOD))]
3655  "<VI_unit>"
3656  "")
3657
3658(define_expand "mulv16qi3"
3659  [(set (match_operand:V16QI 0 "register_operand" "=v")
3660        (mult:V16QI (match_operand:V16QI 1 "register_operand" "v")
3661                    (match_operand:V16QI 2 "register_operand" "v")))]
3662  "TARGET_ALTIVEC"
3663{
3664  rtx even = gen_reg_rtx (V8HImode);
3665  rtx odd = gen_reg_rtx (V8HImode);
3666  rtx mask = gen_reg_rtx (V16QImode);
3667  rtvec v = rtvec_alloc (16);
3668  int i;
3669
3670  for (i = 0; i < 8; ++i) {
3671    RTVEC_ELT (v, 2 * i)
3672     = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 1 : 31 - 2 * i);
3673    RTVEC_ELT (v, 2 * i + 1)
3674     = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 17 : 15 - 2 * i);
3675  }
3676
3677  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3678  emit_insn (gen_altivec_vmulesb (even, operands[1], operands[2]));
3679  emit_insn (gen_altivec_vmulosb (odd, operands[1], operands[2]));
3680  emit_insn (gen_altivec_vperm_v8hiv16qi (operands[0], even, odd, mask));
3681  DONE;
3682})
3683
3684(define_expand "altivec_vpermxor"
3685  [(use (match_operand:V16QI 0 "register_operand"))
3686   (use (match_operand:V16QI 1 "register_operand"))
3687   (use (match_operand:V16QI 2 "register_operand"))
3688   (use (match_operand:V16QI 3 "register_operand"))]
3689  "TARGET_P8_VECTOR"
3690{
3691  if (!BYTES_BIG_ENDIAN)
3692    {
3693      /* vpermxor indexes the bytes using Big Endian numbering.  If LE,
3694	 change indexing in operand[3] to BE index.  */
3695      rtx be_index = gen_reg_rtx (V16QImode);
3696
3697      emit_insn (gen_one_cmplv16qi2 (be_index, operands[3]));
3698      emit_insn (gen_crypto_vpermxor_v16qi (operands[0], operands[1],
3699					    operands[2], be_index));
3700    }
3701  else
3702    emit_insn (gen_crypto_vpermxor_v16qi (operands[0], operands[1],
3703					  operands[2], operands[3]));
3704  DONE;
3705})
3706
3707(define_expand "altivec_negv4sf2"
3708  [(use (match_operand:V4SF 0 "register_operand"))
3709   (use (match_operand:V4SF 1 "register_operand"))]
3710  "TARGET_ALTIVEC"
3711{
3712  rtx neg0;
3713
3714  /* Generate [-0.0, -0.0, -0.0, -0.0].  */
3715  neg0 = gen_reg_rtx (V4SImode);
3716  emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
3717  emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
3718
3719  /* XOR */
3720  emit_insn (gen_xorv4sf3 (operands[0],
3721			   gen_lowpart (V4SFmode, neg0), operands[1])); 
3722    
3723  DONE;
3724})
3725
3726;; Vector reverse elements
3727(define_expand "altivec_vreve<mode>2"
3728  [(set (match_operand:VEC_A 0 "register_operand" "=v")
3729	(unspec:VEC_A [(match_operand:VEC_A 1 "register_operand" "v")]
3730		      UNSPEC_VREVEV))]
3731  "TARGET_ALTIVEC"
3732{
3733  int i, j, size, num_elements;
3734  rtvec v = rtvec_alloc (16);
3735  rtx mask = gen_reg_rtx (V16QImode);
3736
3737  size = GET_MODE_UNIT_SIZE (<MODE>mode);
3738  num_elements = GET_MODE_NUNITS (<MODE>mode);
3739
3740  for (j = 0; j < num_elements; j++)
3741    for (i = 0; i < size; i++)
3742      RTVEC_ELT (v, i + j * size)
3743	= GEN_INT (i + (num_elements - 1 - j) * size);
3744
3745  emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
3746  emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
3747	     operands[1], mask));
3748  DONE;
3749})
3750
3751;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL,
3752;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell.
3753(define_insn "altivec_lvlx"
3754  [(set (match_operand:V16QI 0 "register_operand" "=v")
3755        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3756		      UNSPEC_LVLX))]
3757  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3758  "lvlx %0,%y1"
3759  [(set_attr "type" "vecload")])
3760
3761(define_insn "altivec_lvlxl"
3762  [(set (match_operand:V16QI 0 "register_operand" "=v")
3763        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3764		      UNSPEC_LVLXL))]
3765  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3766  "lvlxl %0,%y1"
3767  [(set_attr "type" "vecload")])
3768
3769(define_insn "altivec_lvrx"
3770  [(set (match_operand:V16QI 0 "register_operand" "=v")
3771        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3772		      UNSPEC_LVRX))]
3773  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3774  "lvrx %0,%y1"
3775  [(set_attr "type" "vecload")])
3776
3777(define_insn "altivec_lvrxl"
3778  [(set (match_operand:V16QI 0 "register_operand" "=v")
3779        (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3780		      UNSPEC_LVRXL))]
3781  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3782  "lvrxl %0,%y1"
3783  [(set_attr "type" "vecload")])
3784
3785(define_insn "altivec_stvlx"
3786  [(parallel
3787    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3788	  (match_operand:V16QI 1 "register_operand" "v"))
3789     (unspec [(const_int 0)] UNSPEC_STVLX)])]
3790  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3791  "stvlx %1,%y0"
3792  [(set_attr "type" "vecstore")])
3793
3794(define_insn "altivec_stvlxl"
3795  [(parallel
3796    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3797	  (match_operand:V16QI 1 "register_operand" "v"))
3798     (unspec [(const_int 0)] UNSPEC_STVLXL)])]
3799  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3800  "stvlxl %1,%y0"
3801  [(set_attr "type" "vecstore")])
3802
3803(define_insn "altivec_stvrx"
3804  [(parallel
3805    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3806	  (match_operand:V16QI 1 "register_operand" "v"))
3807     (unspec [(const_int 0)] UNSPEC_STVRX)])]
3808  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3809  "stvrx %1,%y0"
3810  [(set_attr "type" "vecstore")])
3811
3812(define_insn "altivec_stvrxl"
3813  [(parallel
3814    [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3815	  (match_operand:V16QI 1 "register_operand" "v"))
3816     (unspec [(const_int 0)] UNSPEC_STVRXL)])]
3817  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3818  "stvrxl %1,%y0"
3819  [(set_attr "type" "vecstore")])
3820
3821(define_expand "vec_unpacks_float_hi_v8hi"
3822 [(set (match_operand:V4SF 0 "register_operand")
3823        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3824                     UNSPEC_VUPKHS_V4SF))]
3825  "TARGET_ALTIVEC"
3826{
3827  rtx tmp = gen_reg_rtx (V4SImode);
3828
3829  emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
3830  emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3831  DONE;
3832})
3833
3834(define_expand "vec_unpacks_float_lo_v8hi"
3835 [(set (match_operand:V4SF 0 "register_operand")
3836        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3837                     UNSPEC_VUPKLS_V4SF))]
3838  "TARGET_ALTIVEC"
3839{
3840  rtx tmp = gen_reg_rtx (V4SImode);
3841
3842  emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
3843  emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3844  DONE;
3845})
3846
3847(define_expand "vec_unpacku_float_hi_v8hi"
3848 [(set (match_operand:V4SF 0 "register_operand")
3849        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3850                     UNSPEC_VUPKHU_V4SF))]
3851  "TARGET_ALTIVEC"
3852{
3853  rtx tmp = gen_reg_rtx (V4SImode);
3854
3855  emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
3856  emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3857  DONE;
3858})
3859
3860(define_expand "vec_unpacku_float_lo_v8hi"
3861 [(set (match_operand:V4SF 0 "register_operand")
3862        (unspec:V4SF [(match_operand:V8HI 1 "register_operand")]
3863                     UNSPEC_VUPKLU_V4SF))]
3864  "TARGET_ALTIVEC"
3865{
3866  rtx tmp = gen_reg_rtx (V4SImode);
3867
3868  emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
3869  emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3870  DONE;
3871})
3872
3873
3874;; Power8/power9 vector instructions encoded as Altivec instructions
3875
3876;; Vector count leading zeros
3877(define_insn "*p8v_clz<mode>2"
3878  [(set (match_operand:VI2 0 "register_operand" "=v")
3879	(clz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3880  "TARGET_P8_VECTOR"
3881  "vclz<wd> %0,%1"
3882  [(set_attr "type" "vecsimple")])
3883
3884;; Vector absolute difference unsigned
3885(define_expand "vadu<mode>3"
3886  [(set (match_operand:VI 0 "register_operand")
3887        (unspec:VI [(match_operand:VI 1 "register_operand")
3888		    (match_operand:VI 2 "register_operand")]
3889         UNSPEC_VADU))]
3890  "TARGET_P9_VECTOR")
3891
3892;; Vector absolute difference unsigned
3893(define_insn "p9_vadu<mode>3"
3894  [(set (match_operand:VI 0 "register_operand" "=v")
3895        (unspec:VI [(match_operand:VI 1 "register_operand" "v")
3896		    (match_operand:VI 2 "register_operand" "v")]
3897         UNSPEC_VADU))]
3898  "TARGET_P9_VECTOR"
3899  "vabsdu<wd> %0,%1,%2"
3900  [(set_attr "type" "vecsimple")])
3901
3902;; Vector count trailing zeros
3903(define_insn "*p9v_ctz<mode>2"
3904  [(set (match_operand:VI2 0 "register_operand" "=v")
3905	(ctz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3906  "TARGET_P9_VECTOR"
3907  "vctz<wd> %0,%1"
3908  [(set_attr "type" "vecsimple")])
3909
3910;; Vector population count
3911(define_insn "*p8v_popcount<mode>2"
3912  [(set (match_operand:VI2 0 "register_operand" "=v")
3913        (popcount:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3914  "TARGET_P8_VECTOR"
3915  "vpopcnt<wd> %0,%1"
3916  [(set_attr "type" "vecsimple")])
3917
3918;; Vector parity
3919(define_insn "rs6000_vprtyb<mode>2"
3920  [(set (match_operand:VEC_IP 0 "register_operand" "=v")
3921        (unspec:VEC_IP
3922          [(match_operand:VEC_IP 1 "register_operand" "v")]
3923          UNSPEC_PARITY))]
3924  "TARGET_P9_VECTOR"
3925  "vprtyb<wd> %0,%1"
3926  [(set_attr "type" "vecsimple")])
3927
3928;; Vector Gather Bits by Bytes by Doubleword
3929(define_insn "p8v_vgbbd"
3930  [(set (match_operand:V16QI 0 "register_operand" "=v")
3931	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
3932		      UNSPEC_VGBBD))]
3933  "TARGET_P8_VECTOR"
3934  "vgbbd %0,%1"
3935  [(set_attr "type" "vecsimple")])
3936
3937
3938;; 128-bit binary integer arithmetic
3939;; We have a special container type (V1TImode) to allow operations using the
3940;; ISA 2.07 128-bit binary support to target the VMX/altivec registers without
3941;; having to worry about the register allocator deciding GPRs are better.
3942
3943(define_insn "altivec_vadduqm"
3944  [(set (match_operand:V1TI 0 "register_operand" "=v")
3945	(plus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3946		   (match_operand:V1TI 2 "register_operand" "v")))]
3947  "TARGET_VADDUQM"
3948  "vadduqm %0,%1,%2"
3949  [(set_attr "type" "vecsimple")])
3950
3951(define_insn "altivec_vaddcuq"
3952  [(set (match_operand:V1TI 0 "register_operand" "=v")
3953	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3954		      (match_operand:V1TI 2 "register_operand" "v")]
3955		     UNSPEC_VADDCUQ))]
3956  "TARGET_VADDUQM"
3957  "vaddcuq %0,%1,%2"
3958  [(set_attr "type" "vecsimple")])
3959
3960(define_insn "altivec_vsubuqm"
3961  [(set (match_operand:V1TI 0 "register_operand" "=v")
3962	(minus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3963		    (match_operand:V1TI 2 "register_operand" "v")))]
3964  "TARGET_VADDUQM"
3965  "vsubuqm %0,%1,%2"
3966  [(set_attr "type" "vecsimple")])
3967
3968(define_insn "altivec_vsubcuq"
3969  [(set (match_operand:V1TI 0 "register_operand" "=v")
3970	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3971		      (match_operand:V1TI 2 "register_operand" "v")]
3972		     UNSPEC_VSUBCUQ))]
3973  "TARGET_VADDUQM"
3974  "vsubcuq %0,%1,%2"
3975  [(set_attr "type" "vecsimple")])
3976
3977(define_insn "altivec_vaddeuqm"
3978  [(set (match_operand:V1TI 0 "register_operand" "=v")
3979	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3980		      (match_operand:V1TI 2 "register_operand" "v")
3981		      (match_operand:V1TI 3 "register_operand" "v")]
3982		     UNSPEC_VADDEUQM))]
3983  "TARGET_VADDUQM"
3984  "vaddeuqm %0,%1,%2,%3"
3985  [(set_attr "type" "vecsimple")])
3986
3987(define_insn "altivec_vaddecuq"
3988  [(set (match_operand:V1TI 0 "register_operand" "=v")
3989	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3990		      (match_operand:V1TI 2 "register_operand" "v")
3991		      (match_operand:V1TI 3 "register_operand" "v")]
3992		     UNSPEC_VADDECUQ))]
3993  "TARGET_VADDUQM"
3994  "vaddecuq %0,%1,%2,%3"
3995  [(set_attr "type" "vecsimple")])
3996
3997(define_insn "altivec_vsubeuqm"
3998  [(set (match_operand:V1TI 0 "register_operand" "=v")
3999	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
4000		      (match_operand:V1TI 2 "register_operand" "v")
4001		      (match_operand:V1TI 3 "register_operand" "v")]
4002		   UNSPEC_VSUBEUQM))]
4003  "TARGET_VADDUQM"
4004  "vsubeuqm %0,%1,%2,%3"
4005  [(set_attr "type" "vecsimple")])
4006
4007(define_insn "altivec_vsubecuq"
4008  [(set (match_operand:V1TI 0 "register_operand" "=v")
4009	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
4010		      (match_operand:V1TI 2 "register_operand" "v")
4011		      (match_operand:V1TI 3 "register_operand" "v")]
4012		     UNSPEC_VSUBECUQ))]
4013  "TARGET_VADDUQM"
4014  "vsubecuq %0,%1,%2,%3"
4015  [(set_attr "type" "vecsimple")])
4016
4017;; We use V2DI as the output type to simplify converting the permute
4018;; bits into an integer
4019(define_insn "altivec_vbpermq"
4020  [(set (match_operand:V2DI 0 "register_operand" "=v")
4021	(unspec:V2DI [(match_operand:V16QI 1 "register_operand" "v")
4022		      (match_operand:V16QI 2 "register_operand" "v")]
4023		     UNSPEC_VBPERMQ))]
4024  "TARGET_P8_VECTOR"
4025  "vbpermq %0,%1,%2"
4026  [(set_attr "type" "vecperm")])
4027
4028; One of the vector API interfaces requires returning vector unsigned char.
4029(define_insn "altivec_vbpermq2"
4030  [(set (match_operand:V16QI 0 "register_operand" "=v")
4031	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
4032		       (match_operand:V16QI 2 "register_operand" "v")]
4033		      UNSPEC_VBPERMQ))]
4034  "TARGET_P8_VECTOR"
4035  "vbpermq %0,%1,%2"
4036  [(set_attr "type" "vecperm")])
4037
4038(define_insn "altivec_vbpermd"
4039  [(set (match_operand:V2DI 0 "register_operand" "=v")
4040	(unspec:V2DI [(match_operand:V2DI 1 "register_operand" "v")
4041		      (match_operand:V16QI 2 "register_operand" "v")]
4042		     UNSPEC_VBPERMD))]
4043  "TARGET_P9_VECTOR"
4044  "vbpermd %0,%1,%2"
4045  [(set_attr "type" "vecsimple")])
4046
4047;; Support for SAD (sum of absolute differences).
4048
4049;; Due to saturating semantics, we can't combine the sum-across
4050;; with the vector accumulate in vsum4ubs.  A vadduwm is needed.
4051(define_expand "usadv16qi"
4052  [(use (match_operand:V4SI 0 "register_operand"))
4053   (use (match_operand:V16QI 1 "register_operand"))
4054   (use (match_operand:V16QI 2 "register_operand"))
4055   (use (match_operand:V4SI 3 "register_operand"))]
4056  "TARGET_P9_VECTOR"
4057{
4058  rtx absd = gen_reg_rtx (V16QImode);
4059  rtx zero = gen_reg_rtx (V4SImode);
4060  rtx psum = gen_reg_rtx (V4SImode);
4061
4062  emit_insn (gen_p9_vaduv16qi3 (absd, operands[1], operands[2]));
4063  emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
4064  emit_insn (gen_altivec_vsum4ubs (psum, absd, zero));
4065  emit_insn (gen_addv4si3 (operands[0], psum, operands[3]));
4066  DONE;
4067})
4068
4069;; Since vsum4shs is saturating and further performs signed
4070;; arithmetic, we can't combine the sum-across with the vector
4071;; accumulate in vsum4shs.  A vadduwm is needed.
4072(define_expand "usadv8hi"
4073  [(use (match_operand:V4SI 0 "register_operand"))
4074   (use (match_operand:V8HI 1 "register_operand"))
4075   (use (match_operand:V8HI 2 "register_operand"))
4076   (use (match_operand:V4SI 3 "register_operand"))]
4077  "TARGET_P9_VECTOR"
4078{
4079  rtx absd = gen_reg_rtx (V8HImode);
4080  rtx zero = gen_reg_rtx (V4SImode);
4081  rtx psum = gen_reg_rtx (V4SImode);
4082
4083  emit_insn (gen_p9_vaduv8hi3 (absd, operands[1], operands[2]));
4084  emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
4085  emit_insn (gen_altivec_vsum4shs (psum, absd, zero));
4086  emit_insn (gen_addv4si3 (operands[0], psum, operands[3]));
4087  DONE;
4088})
4089
4090;; Decimal Integer operations
4091(define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB])
4092
4093(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
4094			      (UNSPEC_BCDSUB "sub")])
4095
4096(define_code_iterator BCD_TEST [eq lt gt unordered])
4097
4098(define_insn "bcd<bcd_add_sub>"
4099  [(set (match_operand:V1TI 0 "gpc_reg_operand" "=v")
4100	(unspec:V1TI [(match_operand:V1TI 1 "gpc_reg_operand" "v")
4101		      (match_operand:V1TI 2 "gpc_reg_operand" "v")
4102		      (match_operand:QI 3 "const_0_to_1_operand" "n")]
4103		     UNSPEC_BCD_ADD_SUB))
4104   (clobber (reg:CCFP CR6_REGNO))]
4105  "TARGET_P8_VECTOR"
4106  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4107  [(set_attr "type" "vecsimple")])
4108
4109;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
4110;; can use the unordered test for BCD nans and add/subtracts that overflow.  An
4111;; UNORDERED test on an integer type (like V1TImode) is not defined.  The type
4112;; probably should be one that can go in the VMX (Altivec) registers, so we
4113;; can't use DDmode or DFmode.
4114(define_insn "*bcd<bcd_add_sub>_test"
4115  [(set (reg:CCFP CR6_REGNO)
4116	(compare:CCFP
4117	 (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
4118		       (match_operand:V1TI 2 "register_operand" "v")
4119		       (match_operand:QI 3 "const_0_to_1_operand" "i")]
4120		      UNSPEC_BCD_ADD_SUB)
4121	 (match_operand:V2DF 4 "zero_constant" "j")))
4122   (clobber (match_scratch:V1TI 0 "=v"))]
4123  "TARGET_P8_VECTOR"
4124  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4125  [(set_attr "type" "vecsimple")])
4126
4127(define_insn "*bcd<bcd_add_sub>_test2"
4128  [(set (match_operand:V1TI 0 "register_operand" "=v")
4129	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
4130		      (match_operand:V1TI 2 "register_operand" "v")
4131		      (match_operand:QI 3 "const_0_to_1_operand" "i")]
4132		     UNSPEC_BCD_ADD_SUB))
4133   (set (reg:CCFP CR6_REGNO)
4134	(compare:CCFP
4135	 (unspec:V2DF [(match_dup 1)
4136		       (match_dup 2)
4137		       (match_dup 3)]
4138		      UNSPEC_BCD_ADD_SUB)
4139	 (match_operand:V2DF 4 "zero_constant" "j")))]
4140  "TARGET_P8_VECTOR"
4141  "bcd<bcd_add_sub>. %0,%1,%2,%3"
4142  [(set_attr "type" "vecsimple")])
4143
4144(define_expand "bcd<bcd_add_sub>_<code>"
4145  [(parallel [(set (reg:CCFP CR6_REGNO)
4146		   (compare:CCFP
4147		    (unspec:V2DF [(match_operand:V1TI 1 "register_operand")
4148				  (match_operand:V1TI 2 "register_operand")
4149				  (match_operand:QI 3 "const_0_to_1_operand")]
4150				 UNSPEC_BCD_ADD_SUB)
4151		    (match_dup 4)))
4152	      (clobber (match_scratch:V1TI 5))])
4153   (set (match_operand:SI 0 "register_operand")
4154	(BCD_TEST:SI (reg:CCFP CR6_REGNO)
4155		     (const_int 0)))]
4156  "TARGET_P8_VECTOR"
4157{
4158  operands[4] = CONST0_RTX (V2DFmode);
4159})
4160
4161;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
4162;; the bcdadd/bcdsub that tests the value.  The combiner won't work since
4163;; CR6 is a hard coded register.  Unfortunately, all of the Altivec predicate
4164;; support is hard coded to use the fixed register CR6 instead of creating
4165;; a register class for CR6.
4166
4167(define_peephole2
4168  [(parallel [(set (match_operand:V1TI 0 "register_operand")
4169		   (unspec:V1TI [(match_operand:V1TI 1 "register_operand")
4170				 (match_operand:V1TI 2 "register_operand")
4171				 (match_operand:QI 3 "const_0_to_1_operand")]
4172				UNSPEC_BCD_ADD_SUB))
4173	      (clobber (reg:CCFP CR6_REGNO))])
4174   (parallel [(set (reg:CCFP CR6_REGNO)
4175		   (compare:CCFP
4176		    (unspec:V2DF [(match_dup 1)
4177				  (match_dup 2)
4178				  (match_dup 3)]
4179				 UNSPEC_BCD_ADD_SUB)
4180		    (match_operand:V2DF 4 "zero_constant")))
4181	      (clobber (match_operand:V1TI 5 "register_operand"))])]
4182  "TARGET_P8_VECTOR"
4183  [(parallel [(set (match_dup 0)
4184		   (unspec:V1TI [(match_dup 1)
4185				 (match_dup 2)
4186				 (match_dup 3)]
4187				UNSPEC_BCD_ADD_SUB))
4188	      (set (reg:CCFP CR6_REGNO)
4189		   (compare:CCFP
4190		    (unspec:V2DF [(match_dup 1)
4191				  (match_dup 2)
4192				  (match_dup 3)]
4193				 UNSPEC_BCD_ADD_SUB)
4194		    (match_dup 4)))])])
4195