Sync with upstream 4.9 branch
[official-gcc.git] / embedded-4_9-branch / gcc / config / rs6000 / altivec.md
blob682bdae4eabea23a72d26898a0b6ad7aa893cfdc
1 ;; AltiVec patterns.
2 ;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
3 ;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
5 ;; This file is part of GCC.
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.
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.
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/>.
21 (define_c_enum "unspec"
22   [UNSPEC_VCMPBFP
23    UNSPEC_VMSUMU
24    UNSPEC_VMSUMM
25    UNSPEC_VMSUMSHM
26    UNSPEC_VMSUMUHS
27    UNSPEC_VMSUMSHS
28    UNSPEC_VMHADDSHS
29    UNSPEC_VMHRADDSHS
30    UNSPEC_VMLADDUHM
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_VMULOUB
41    UNSPEC_VMULOSB
42    UNSPEC_VMULOUH
43    UNSPEC_VMULOSH
44    UNSPEC_VPKPX
45    UNSPEC_VPACK_SIGN_SIGN_SAT
46    UNSPEC_VPACK_SIGN_UNS_SAT
47    UNSPEC_VPACK_UNS_UNS_SAT
48    UNSPEC_VPACK_UNS_UNS_MOD
49    UNSPEC_VPACK_UNS_UNS_MOD_DIRECT
50    UNSPEC_VSLV4SI
51    UNSPEC_VSLO
52    UNSPEC_VSR
53    UNSPEC_VSRO
54    UNSPEC_VSUBCUW
55    UNSPEC_VSUBU
56    UNSPEC_VSUBS
57    UNSPEC_VSUM4UBS
58    UNSPEC_VSUM4S
59    UNSPEC_VSUM2SWS
60    UNSPEC_VSUMSWS
61    UNSPEC_VPERM
62    UNSPEC_VPERM_UNS
63    UNSPEC_VRFIN
64    UNSPEC_VCFUX
65    UNSPEC_VCFSX
66    UNSPEC_VCTUXS
67    UNSPEC_VCTSXS
68    UNSPEC_VLOGEFP
69    UNSPEC_VEXPTEFP
70    UNSPEC_VLSDOI
71    UNSPEC_VUNPACK_HI_SIGN
72    UNSPEC_VUNPACK_LO_SIGN
73    UNSPEC_VUNPACK_HI_SIGN_DIRECT
74    UNSPEC_VUNPACK_LO_SIGN_DIRECT
75    UNSPEC_VUPKHPX
76    UNSPEC_VUPKLPX
77    UNSPEC_DST
78    UNSPEC_DSTT
79    UNSPEC_DSTST
80    UNSPEC_DSTSTT
81    UNSPEC_LVSL
82    UNSPEC_LVSR
83    UNSPEC_LVE
84    UNSPEC_STVX
85    UNSPEC_STVXL
86    UNSPEC_STVE
87    UNSPEC_SET_VSCR
88    UNSPEC_GET_VRSAVE
89    UNSPEC_LVX
90    UNSPEC_REDUC_PLUS
91    UNSPEC_VECSH
92    UNSPEC_EXTEVEN_V4SI
93    UNSPEC_EXTEVEN_V8HI
94    UNSPEC_EXTEVEN_V16QI
95    UNSPEC_EXTEVEN_V4SF
96    UNSPEC_EXTODD_V4SI
97    UNSPEC_EXTODD_V8HI
98    UNSPEC_EXTODD_V16QI
99    UNSPEC_EXTODD_V4SF
100    UNSPEC_INTERHI_V4SI
101    UNSPEC_INTERHI_V8HI
102    UNSPEC_INTERHI_V16QI
103    UNSPEC_INTERLO_V4SI
104    UNSPEC_INTERLO_V8HI
105    UNSPEC_INTERLO_V16QI
106    UNSPEC_LVLX
107    UNSPEC_LVLXL
108    UNSPEC_LVRX
109    UNSPEC_LVRXL
110    UNSPEC_STVLX
111    UNSPEC_STVLXL
112    UNSPEC_STVRX
113    UNSPEC_STVRXL
114    UNSPEC_VMULWHUB
115    UNSPEC_VMULWLUB
116    UNSPEC_VMULWHSB
117    UNSPEC_VMULWLSB
118    UNSPEC_VMULWHUH
119    UNSPEC_VMULWLUH
120    UNSPEC_VMULWHSH
121    UNSPEC_VMULWLSH
122    UNSPEC_VUPKHUB
123    UNSPEC_VUPKHUH
124    UNSPEC_VUPKLUB
125    UNSPEC_VUPKLUH
126    UNSPEC_VPERMSI
127    UNSPEC_VPERMHI
128    UNSPEC_INTERHI
129    UNSPEC_INTERLO
130    UNSPEC_VUPKHS_V4SF
131    UNSPEC_VUPKLS_V4SF
132    UNSPEC_VUPKHU_V4SF
133    UNSPEC_VUPKLU_V4SF
134    UNSPEC_VGBBD
135    UNSPEC_VMRGH_DIRECT
136    UNSPEC_VMRGL_DIRECT
137    UNSPEC_VSPLT_DIRECT
138    UNSPEC_VSUMSWS_DIRECT
139    UNSPEC_VADDCUQ
140    UNSPEC_VADDEUQM
141    UNSPEC_VADDECUQ
142    UNSPEC_VSUBCUQ
143    UNSPEC_VSUBEUQM
144    UNSPEC_VSUBECUQ
145    UNSPEC_VBPERMQ
146    UNSPEC_BCDADD
147    UNSPEC_BCDSUB
148    UNSPEC_BCD_OVERFLOW
151 (define_c_enum "unspecv"
152   [UNSPECV_SET_VRSAVE
153    UNSPECV_MTVSCR
154    UNSPECV_MFVSCR
155    UNSPECV_DSSALL
156    UNSPECV_DSS
157   ])
159 ;; Vec int modes
160 (define_mode_iterator VI [V4SI V8HI V16QI])
161 ;; Like VI, but add ISA 2.07 integer vector ops
162 (define_mode_iterator VI2 [V4SI V8HI V16QI V2DI])
163 ;; Short vec in modes
164 (define_mode_iterator VIshort [V8HI V16QI])
165 ;; Vec float modes
166 (define_mode_iterator VF [V4SF])
167 ;; Vec modes, pity mode iterators are not composable
168 (define_mode_iterator V [V4SI V8HI V16QI V4SF])
169 ;; Vec modes for move/logical/permute ops, include vector types for move not
170 ;; otherwise handled by altivec (v2df, v2di, ti)
171 (define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI V1TI TI])
173 ;; Like VM, except don't do TImode
174 (define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI V1TI])
176 (define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
177 (define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
178 (define_mode_attr VI_unit [(V16QI "VECTOR_UNIT_ALTIVEC_P (V16QImode)")
179                            (V8HI "VECTOR_UNIT_ALTIVEC_P (V8HImode)")
180                            (V4SI "VECTOR_UNIT_ALTIVEC_P (V4SImode)")
181                            (V2DI "VECTOR_UNIT_P8_VECTOR_P (V2DImode)")
182                            (V1TI "VECTOR_UNIT_ALTIVEC_P (V1TImode)")])
184 ;; Vector pack/unpack
185 (define_mode_iterator VP [V2DI V4SI V8HI])
186 (define_mode_attr VP_small [(V2DI "V4SI") (V4SI "V8HI") (V8HI "V16QI")])
187 (define_mode_attr VP_small_lc [(V2DI "v4si") (V4SI "v8hi") (V8HI "v16qi")])
188 (define_mode_attr VU_char [(V2DI "w") (V4SI "h") (V8HI "b")])
190 ;; Vector move instructions.
191 (define_insn "*altivec_mov<mode>"
192   [(set (match_operand:VM2 0 "nonimmediate_operand" "=Z,v,v,*Y,*r,*r,v,v")
193         (match_operand:VM2 1 "input_operand" "v,Z,v,r,Y,r,j,W"))]
194   "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
195    && (register_operand (operands[0], <MODE>mode) 
196        || register_operand (operands[1], <MODE>mode))"
198   switch (which_alternative)
199     {
200     case 0: return "stvx %1,%y0";
201     case 1: return "lvx %0,%y1";
202     case 2: return "vor %0,%1,%1";
203     case 3: return "#";
204     case 4: return "#";
205     case 5: return "#";
206     case 6: return "vxor %0,%0,%0";
207     case 7: return output_vec_const_move (operands);
208     default: gcc_unreachable ();
209     }
211   [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
213 ;; Unlike other altivec moves, allow the GPRs, since a normal use of TImode
214 ;; is for unions.  However for plain data movement, slightly favor the vector
215 ;; loads
216 (define_insn "*altivec_movti"
217   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,v,v,?Y,?r,?r,v,v")
218         (match_operand:TI 1 "input_operand" "v,Z,v,r,Y,r,j,W"))]
219   "VECTOR_MEM_ALTIVEC_P (TImode)
220    && (register_operand (operands[0], TImode) 
221        || register_operand (operands[1], TImode))"
223   switch (which_alternative)
224     {
225     case 0: return "stvx %1,%y0";
226     case 1: return "lvx %0,%y1";
227     case 2: return "vor %0,%1,%1";
228     case 3: return "#";
229     case 4: return "#";
230     case 5: return "#";
231     case 6: return "vxor %0,%0,%0";
232     case 7: return output_vec_const_move (operands);
233     default: gcc_unreachable ();
234     }
236   [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
238 ;; Load up a vector with the most significant bit set by loading up -1 and
239 ;; doing a shift left
240 (define_split
241   [(set (match_operand:VM 0 "altivec_register_operand" "")
242         (match_operand:VM 1 "easy_vector_constant_msb" ""))]
243   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && reload_completed"
244   [(const_int 0)]
246   rtx dest = operands[0];
247   enum machine_mode mode = GET_MODE (operands[0]);
248   rtvec v;
249   int i, num_elements;
251   if (mode == V4SFmode)
252     {
253       mode = V4SImode;
254       dest = gen_lowpart (V4SImode, dest);
255     }
257   num_elements = GET_MODE_NUNITS (mode);
258   v = rtvec_alloc (num_elements);
259   for (i = 0; i < num_elements; i++)
260     RTVEC_ELT (v, i) = constm1_rtx;
262   emit_insn (gen_vec_initv4si (dest, gen_rtx_PARALLEL (mode, v)));
263   emit_insn (gen_rtx_SET (VOIDmode, dest, gen_rtx_ASHIFT (mode, dest, dest)));
264   DONE;
267 (define_split
268   [(set (match_operand:VM 0 "altivec_register_operand" "")
269         (match_operand:VM 1 "easy_vector_constant_add_self" ""))]
270   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && reload_completed"
271   [(set (match_dup 0) (match_dup 3))
272    (set (match_dup 0) (match_dup 4))]
274   rtx dup = gen_easy_altivec_constant (operands[1]);
275   rtx const_vec;
276   enum machine_mode op_mode = <MODE>mode;
278   /* Divide the operand of the resulting VEC_DUPLICATE, and use
279      simplify_rtx to make a CONST_VECTOR.  */
280   XEXP (dup, 0) = simplify_const_binary_operation (ASHIFTRT, QImode,
281                                                    XEXP (dup, 0), const1_rtx);
282   const_vec = simplify_rtx (dup);
284   if (op_mode == V4SFmode)
285     {
286       op_mode = V4SImode;
287       operands[0] = gen_lowpart (op_mode, operands[0]);
288     }
289   if (GET_MODE (const_vec) == op_mode)
290     operands[3] = const_vec;
291   else
292     operands[3] = gen_lowpart (op_mode, const_vec);
293   operands[4] = gen_rtx_PLUS (op_mode, operands[0], operands[0]);
296 (define_insn "get_vrsave_internal"
297   [(set (match_operand:SI 0 "register_operand" "=r")
298         (unspec:SI [(reg:SI 109)] UNSPEC_GET_VRSAVE))]
299   "TARGET_ALTIVEC"
301   if (TARGET_MACHO)
302      return "mfspr %0,256";
303   else
304      return "mfvrsave %0";
306   [(set_attr "type" "*")])
308 (define_insn "*set_vrsave_internal"
309   [(match_parallel 0 "vrsave_operation"
310      [(set (reg:SI 109)
311            (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
312                                 (reg:SI 109)] UNSPECV_SET_VRSAVE))])]
313   "TARGET_ALTIVEC"
315   if (TARGET_MACHO)
316     return "mtspr 256,%1";
317   else
318     return "mtvrsave %1";
320   [(set_attr "type" "*")])
322 (define_insn "*save_world"
323  [(match_parallel 0 "save_world_operation"
324                   [(clobber (reg:SI 65))
325                    (use (match_operand:SI 1 "call_operand" "s"))])]
326  "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"         
327  "bl %z1"
328   [(set_attr "type" "branch")
329    (set_attr "length" "4")])
331 (define_insn "*restore_world"
332  [(match_parallel 0 "restore_world_operation"
333                   [(return)
334                    (use (reg:SI 65))
335                    (use (match_operand:SI 1 "call_operand" "s"))
336                    (clobber (match_operand:SI 2 "gpc_reg_operand" "=r"))])]
337  "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
338  "b %z1")
340 ;; The save_vregs and restore_vregs patterns don't use memory_operand
341 ;; because (plus (reg) (const_int)) is not a valid vector address.
342 ;; This way is more compact than describing exactly what happens in
343 ;; the out-of-line functions, ie. loading the constant into r11/r12
344 ;; then using indexed addressing, and requires less editing of rtl
345 ;; to describe the operation to dwarf2out_frame_debug_expr.
346 (define_insn "*save_vregs_<mode>_r11"
347   [(match_parallel 0 "any_parallel_operand"
348      [(clobber (reg:P 65))
349       (use (match_operand:P 1 "symbol_ref_operand" "s"))
350       (clobber (reg:P 11))
351       (use (reg:P 0))
352       (set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
353                              (match_operand:P 3 "short_cint_operand" "I")))
354            (match_operand:V4SI 4 "gpc_reg_operand" "v"))])]
355   ""
356   "bl %1"
357   [(set_attr "type" "branch")
358    (set_attr "length" "4")])
360 (define_insn "*save_vregs_<mode>_r12"
361   [(match_parallel 0 "any_parallel_operand"
362      [(clobber (reg:P 65))
363       (use (match_operand:P 1 "symbol_ref_operand" "s"))
364       (clobber (reg:P 12))
365       (use (reg:P 0))
366       (set (mem:V4SI (plus:P (match_operand:P 2 "gpc_reg_operand" "b")
367                              (match_operand:P 3 "short_cint_operand" "I")))
368            (match_operand:V4SI 4 "gpc_reg_operand" "v"))])]
369   ""
370   "bl %1"
371   [(set_attr "type" "branch")
372    (set_attr "length" "4")])
374 (define_insn "*restore_vregs_<mode>_r11"
375   [(match_parallel 0 "any_parallel_operand"
376      [(clobber (reg:P 65))
377       (use (match_operand:P 1 "symbol_ref_operand" "s"))
378       (clobber (reg:P 11))
379       (use (reg:P 0))
380       (set (match_operand:V4SI 2 "gpc_reg_operand" "=v")
381            (mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
382                              (match_operand:P 4 "short_cint_operand" "I"))))])]
383   ""
384   "bl %1"
385   [(set_attr "type" "branch")
386    (set_attr "length" "4")])
388 (define_insn "*restore_vregs_<mode>_r12"
389   [(match_parallel 0 "any_parallel_operand"
390      [(clobber (reg:P 65))
391       (use (match_operand:P 1 "symbol_ref_operand" "s"))
392       (clobber (reg:P 12))
393       (use (reg:P 0))
394       (set (match_operand:V4SI 2 "gpc_reg_operand" "=v")
395            (mem:V4SI (plus:P (match_operand:P 3 "gpc_reg_operand" "b")
396                              (match_operand:P 4 "short_cint_operand" "I"))))])]
397   ""
398   "bl %1"
399   [(set_attr "type" "branch")
400    (set_attr "length" "4")])
402 ;; Simple binary operations.
404 ;; add
405 (define_insn "add<mode>3"
406   [(set (match_operand:VI2 0 "register_operand" "=v")
407         (plus:VI2 (match_operand:VI2 1 "register_operand" "v")
408                   (match_operand:VI2 2 "register_operand" "v")))]
409   "<VI_unit>"
410   "vaddu<VI_char>m %0,%1,%2"
411   [(set_attr "type" "vecsimple")])
413 (define_insn "*altivec_addv4sf3"
414   [(set (match_operand:V4SF 0 "register_operand" "=v")
415         (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
416                    (match_operand:V4SF 2 "register_operand" "v")))]
417   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
418   "vaddfp %0,%1,%2"
419   [(set_attr "type" "vecfloat")])
421 (define_insn "altivec_vaddcuw"
422   [(set (match_operand:V4SI 0 "register_operand" "=v")
423         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
424                       (match_operand:V4SI 2 "register_operand" "v")]
425                      UNSPEC_VADDCUW))]
426   "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
427   "vaddcuw %0,%1,%2"
428   [(set_attr "type" "vecsimple")])
430 (define_insn "altivec_vaddu<VI_char>s"
431   [(set (match_operand:VI 0 "register_operand" "=v")
432         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
433                     (match_operand:VI 2 "register_operand" "v")]
434                    UNSPEC_VADDU))
435    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
436   "<VI_unit>"
437   "vaddu<VI_char>s %0,%1,%2"
438   [(set_attr "type" "vecsimple")])
440 (define_insn "altivec_vadds<VI_char>s"
441   [(set (match_operand:VI 0 "register_operand" "=v")
442         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
443                     (match_operand:VI 2 "register_operand" "v")]
444                    UNSPEC_VADDS))
445    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
446   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
447   "vadds<VI_char>s %0,%1,%2"
448   [(set_attr "type" "vecsimple")])
450 ;; sub
451 (define_insn "sub<mode>3"
452   [(set (match_operand:VI2 0 "register_operand" "=v")
453         (minus:VI2 (match_operand:VI2 1 "register_operand" "v")
454                    (match_operand:VI2 2 "register_operand" "v")))]
455   "<VI_unit>"
456   "vsubu<VI_char>m %0,%1,%2"
457   [(set_attr "type" "vecsimple")])
459 (define_insn "*altivec_subv4sf3"
460   [(set (match_operand:V4SF 0 "register_operand" "=v")
461         (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
462                     (match_operand:V4SF 2 "register_operand" "v")))]
463   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
464   "vsubfp %0,%1,%2"
465   [(set_attr "type" "vecfloat")])
467 (define_insn "altivec_vsubcuw"
468   [(set (match_operand:V4SI 0 "register_operand" "=v")
469         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
470                       (match_operand:V4SI 2 "register_operand" "v")]
471                      UNSPEC_VSUBCUW))]
472   "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
473   "vsubcuw %0,%1,%2"
474   [(set_attr "type" "vecsimple")])
476 (define_insn "altivec_vsubu<VI_char>s"
477   [(set (match_operand:VI 0 "register_operand" "=v")
478         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
479                     (match_operand:VI 2 "register_operand" "v")]
480                    UNSPEC_VSUBU))
481    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
482   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
483   "vsubu<VI_char>s %0,%1,%2"
484   [(set_attr "type" "vecsimple")])
486 (define_insn "altivec_vsubs<VI_char>s"
487   [(set (match_operand:VI 0 "register_operand" "=v")
488         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
489                     (match_operand:VI 2 "register_operand" "v")]
490                    UNSPEC_VSUBS))
491    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
492   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
493   "vsubs<VI_char>s %0,%1,%2"
494   [(set_attr "type" "vecsimple")])
497 (define_insn "altivec_vavgu<VI_char>"
498   [(set (match_operand:VI 0 "register_operand" "=v")
499         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
500                     (match_operand:VI 2 "register_operand" "v")]
501                    UNSPEC_VAVGU))]
502   "TARGET_ALTIVEC"
503   "vavgu<VI_char> %0,%1,%2"
504   [(set_attr "type" "vecsimple")])
506 (define_insn "altivec_vavgs<VI_char>"
507   [(set (match_operand:VI 0 "register_operand" "=v")
508         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
509                     (match_operand:VI 2 "register_operand" "v")]
510                    UNSPEC_VAVGS))]
511   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
512   "vavgs<VI_char> %0,%1,%2"
513   [(set_attr "type" "vecsimple")])
515 (define_insn "altivec_vcmpbfp"
516   [(set (match_operand:V4SI 0 "register_operand" "=v")
517         (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
518                       (match_operand:V4SF 2 "register_operand" "v")] 
519                       UNSPEC_VCMPBFP))]
520   "VECTOR_UNIT_ALTIVEC_P (V4SImode)"
521   "vcmpbfp %0,%1,%2"
522   [(set_attr "type" "veccmp")])
524 (define_insn "*altivec_eq<mode>"
525   [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
526         (eq:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
527                 (match_operand:VI2 2 "altivec_register_operand" "v")))]
528   "<VI_unit>"
529   "vcmpequ<VI_char> %0,%1,%2"
530   [(set_attr "type" "veccmp")])
532 (define_insn "*altivec_gt<mode>"
533   [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
534         (gt:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
535                 (match_operand:VI2 2 "altivec_register_operand" "v")))]
536   "<VI_unit>"
537   "vcmpgts<VI_char> %0,%1,%2"
538   [(set_attr "type" "veccmp")])
540 (define_insn "*altivec_gtu<mode>"
541   [(set (match_operand:VI2 0 "altivec_register_operand" "=v")
542         (gtu:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
543                  (match_operand:VI2 2 "altivec_register_operand" "v")))]
544   "<VI_unit>"
545   "vcmpgtu<VI_char> %0,%1,%2"
546   [(set_attr "type" "veccmp")])
548 (define_insn "*altivec_eqv4sf"
549   [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
550         (eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
551                  (match_operand:V4SF 2 "altivec_register_operand" "v")))]
552   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
553   "vcmpeqfp %0,%1,%2"
554   [(set_attr "type" "veccmp")])
556 (define_insn "*altivec_gtv4sf"
557   [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
558         (gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
559                  (match_operand:V4SF 2 "altivec_register_operand" "v")))]
560   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
561   "vcmpgtfp %0,%1,%2"
562   [(set_attr "type" "veccmp")])
564 (define_insn "*altivec_gev4sf"
565   [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
566         (ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
567                  (match_operand:V4SF 2 "altivec_register_operand" "v")))]
568   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
569   "vcmpgefp %0,%1,%2"
570   [(set_attr "type" "veccmp")])
572 (define_insn "*altivec_vsel<mode>"
573   [(set (match_operand:VM 0 "altivec_register_operand" "=v")
574         (if_then_else:VM
575          (ne:CC (match_operand:VM 1 "altivec_register_operand" "v")
576                 (match_operand:VM 4 "zero_constant" ""))
577          (match_operand:VM 2 "altivec_register_operand" "v")
578          (match_operand:VM 3 "altivec_register_operand" "v")))]
579   "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
580   "vsel %0,%3,%2,%1"
581   [(set_attr "type" "vecperm")])
583 (define_insn "*altivec_vsel<mode>_uns"
584   [(set (match_operand:VM 0 "altivec_register_operand" "=v")
585         (if_then_else:VM
586          (ne:CCUNS (match_operand:VM 1 "altivec_register_operand" "v")
587                    (match_operand:VM 4 "zero_constant" ""))
588          (match_operand:VM 2 "altivec_register_operand" "v")
589          (match_operand:VM 3 "altivec_register_operand" "v")))]
590   "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
591   "vsel %0,%3,%2,%1"
592   [(set_attr "type" "vecperm")])
594 ;; Fused multiply add.
596 (define_insn "*altivec_fmav4sf4"
597   [(set (match_operand:V4SF 0 "register_operand" "=v")
598         (fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
599                   (match_operand:V4SF 2 "register_operand" "v")
600                   (match_operand:V4SF 3 "register_operand" "v")))]
601   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
602   "vmaddfp %0,%1,%2,%3"
603   [(set_attr "type" "vecfloat")])
605 ;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
607 (define_expand "altivec_mulv4sf3"
608   [(set (match_operand:V4SF 0 "register_operand" "")
609         (fma:V4SF (match_operand:V4SF 1 "register_operand" "")
610                   (match_operand:V4SF 2 "register_operand" "")
611                   (match_dup 3)))]
612   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
614   rtx neg0;
616   /* Generate [-0.0, -0.0, -0.0, -0.0].  */
617   neg0 = gen_reg_rtx (V4SImode);
618   emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
619   emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
621   operands[3] = gen_lowpart (V4SFmode, neg0);
624 ;; 32-bit integer multiplication
625 ;; A_high = Operand_0 & 0xFFFF0000 >> 16
626 ;; A_low = Operand_0 & 0xFFFF
627 ;; B_high = Operand_1 & 0xFFFF0000 >> 16
628 ;; B_low = Operand_1 & 0xFFFF
629 ;; result = A_low * B_low + (A_high * B_low + B_high * A_low) << 16
631 ;; (define_insn "mulv4si3"
632 ;;   [(set (match_operand:V4SI 0 "register_operand" "=v")
633 ;;         (mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
634 ;;                    (match_operand:V4SI 2 "register_operand" "v")))]
635 (define_expand "mulv4si3"
636   [(use (match_operand:V4SI 0 "register_operand" ""))
637    (use (match_operand:V4SI 1 "register_operand" ""))
638    (use (match_operand:V4SI 2 "register_operand" ""))]
639    "TARGET_ALTIVEC"
640    "
642    rtx zero;
643    rtx swap;
644    rtx small_swap;
645    rtx sixteen;
646    rtx one;
647    rtx two;
648    rtx low_product;
649    rtx high_product;
650        
651    zero = gen_reg_rtx (V4SImode);
652    emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
654    sixteen = gen_reg_rtx (V4SImode);   
655    emit_insn (gen_altivec_vspltisw (sixteen,  gen_rtx_CONST_INT (V4SImode, -16)));
657    swap = gen_reg_rtx (V4SImode);
658    emit_insn (gen_vrotlv4si3 (swap, operands[2], sixteen));
660    one = gen_reg_rtx (V8HImode);
661    convert_move (one, operands[1], 0);
663    two = gen_reg_rtx (V8HImode);
664    convert_move (two, operands[2], 0);
666    small_swap = gen_reg_rtx (V8HImode);
667    convert_move (small_swap, swap, 0);
669    low_product = gen_reg_rtx (V4SImode);
670    emit_insn (gen_altivec_vmulouh (low_product, one, two));
672    high_product = gen_reg_rtx (V4SImode);
673    emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
675    emit_insn (gen_vashlv4si3 (high_product, high_product, sixteen));
677    emit_insn (gen_addv4si3 (operands[0], high_product, low_product));
678    
679    DONE;
680  }")
682 (define_expand "mulv8hi3"
683   [(use (match_operand:V8HI 0 "register_operand" ""))
684    (use (match_operand:V8HI 1 "register_operand" ""))
685    (use (match_operand:V8HI 2 "register_operand" ""))]
686    "TARGET_ALTIVEC"
687    "
689    rtx odd = gen_reg_rtx (V4SImode);
690    rtx even = gen_reg_rtx (V4SImode);
691    rtx high = gen_reg_rtx (V4SImode);
692    rtx low = gen_reg_rtx (V4SImode);
694    if (BYTES_BIG_ENDIAN)
695      {
696        emit_insn (gen_altivec_vmulesh (even, operands[1], operands[2]));
697        emit_insn (gen_altivec_vmulosh (odd, operands[1], operands[2]));
698        emit_insn (gen_altivec_vmrghw_direct (high, even, odd));
699        emit_insn (gen_altivec_vmrglw_direct (low, even, odd));
700        emit_insn (gen_altivec_vpkuwum_direct (operands[0], high, low));
701      }
702    else
703      {
704        emit_insn (gen_altivec_vmulosh (even, operands[1], operands[2]));
705        emit_insn (gen_altivec_vmulesh (odd, operands[1], operands[2]));
706        emit_insn (gen_altivec_vmrghw_direct (high, odd, even));
707        emit_insn (gen_altivec_vmrglw_direct (low, odd, even));
708        emit_insn (gen_altivec_vpkuwum_direct (operands[0], low, high));
709      } 
711    DONE;
714 ;; Fused multiply subtract 
715 (define_insn "*altivec_vnmsubfp"
716   [(set (match_operand:V4SF 0 "register_operand" "=v")
717         (neg:V4SF
718          (fma:V4SF (match_operand:V4SF 1 "register_operand" "v")
719                    (match_operand:V4SF 2 "register_operand" "v")
720                    (neg:V4SF
721                     (match_operand:V4SF 3 "register_operand" "v")))))]
722   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
723   "vnmsubfp %0,%1,%2,%3"
724   [(set_attr "type" "vecfloat")])
726 (define_insn "altivec_vmsumu<VI_char>m"
727   [(set (match_operand:V4SI 0 "register_operand" "=v")
728         (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
729                       (match_operand:VIshort 2 "register_operand" "v")
730                       (match_operand:V4SI 3 "register_operand" "v")]
731                      UNSPEC_VMSUMU))]
732   "TARGET_ALTIVEC"
733   "vmsumu<VI_char>m %0,%1,%2,%3"
734   [(set_attr "type" "veccomplex")])
736 (define_insn "altivec_vmsumm<VI_char>m"
737   [(set (match_operand:V4SI 0 "register_operand" "=v")
738         (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
739                       (match_operand:VIshort 2 "register_operand" "v")
740                       (match_operand:V4SI 3 "register_operand" "v")]
741                      UNSPEC_VMSUMM))]
742   "TARGET_ALTIVEC"
743   "vmsumm<VI_char>m %0,%1,%2,%3"
744   [(set_attr "type" "veccomplex")])
746 (define_insn "altivec_vmsumshm"
747   [(set (match_operand:V4SI 0 "register_operand" "=v")
748         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
749                       (match_operand:V8HI 2 "register_operand" "v")
750                       (match_operand:V4SI 3 "register_operand" "v")]
751                      UNSPEC_VMSUMSHM))]
752   "TARGET_ALTIVEC"
753   "vmsumshm %0,%1,%2,%3"
754   [(set_attr "type" "veccomplex")])
756 (define_insn "altivec_vmsumuhs"
757   [(set (match_operand:V4SI 0 "register_operand" "=v")
758         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
759                       (match_operand:V8HI 2 "register_operand" "v")
760                       (match_operand:V4SI 3 "register_operand" "v")]
761                      UNSPEC_VMSUMUHS))
762    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
763   "TARGET_ALTIVEC"
764   "vmsumuhs %0,%1,%2,%3"
765   [(set_attr "type" "veccomplex")])
767 (define_insn "altivec_vmsumshs"
768   [(set (match_operand:V4SI 0 "register_operand" "=v")
769         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
770                       (match_operand:V8HI 2 "register_operand" "v")
771                       (match_operand:V4SI 3 "register_operand" "v")]
772                      UNSPEC_VMSUMSHS))
773    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
774   "TARGET_ALTIVEC"
775   "vmsumshs %0,%1,%2,%3"
776   [(set_attr "type" "veccomplex")])
778 ;; max
780 (define_insn "umax<mode>3"
781   [(set (match_operand:VI2 0 "register_operand" "=v")
782         (umax:VI2 (match_operand:VI2 1 "register_operand" "v")
783                   (match_operand:VI2 2 "register_operand" "v")))]
784   "<VI_unit>"
785   "vmaxu<VI_char> %0,%1,%2"
786   [(set_attr "type" "vecsimple")])
788 (define_insn "smax<mode>3"
789   [(set (match_operand:VI2 0 "register_operand" "=v")
790         (smax:VI2 (match_operand:VI2 1 "register_operand" "v")
791                   (match_operand:VI2 2 "register_operand" "v")))]
792   "<VI_unit>"
793   "vmaxs<VI_char> %0,%1,%2"
794   [(set_attr "type" "vecsimple")])
796 (define_insn "*altivec_smaxv4sf3"
797   [(set (match_operand:V4SF 0 "register_operand" "=v")
798         (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
799                    (match_operand:V4SF 2 "register_operand" "v")))]
800   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
801   "vmaxfp %0,%1,%2"
802   [(set_attr "type" "veccmp")])
804 (define_insn "umin<mode>3"
805   [(set (match_operand:VI2 0 "register_operand" "=v")
806         (umin:VI2 (match_operand:VI2 1 "register_operand" "v")
807                   (match_operand:VI2 2 "register_operand" "v")))]
808   "<VI_unit>"
809   "vminu<VI_char> %0,%1,%2"
810   [(set_attr "type" "vecsimple")])
812 (define_insn "smin<mode>3"
813   [(set (match_operand:VI2 0 "register_operand" "=v")
814         (smin:VI2 (match_operand:VI2 1 "register_operand" "v")
815                   (match_operand:VI2 2 "register_operand" "v")))]
816   "<VI_unit>"
817   "vmins<VI_char> %0,%1,%2"
818   [(set_attr "type" "vecsimple")])
820 (define_insn "*altivec_sminv4sf3"
821   [(set (match_operand:V4SF 0 "register_operand" "=v")
822         (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
823                    (match_operand:V4SF 2 "register_operand" "v")))]
824   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
825   "vminfp %0,%1,%2"
826   [(set_attr "type" "veccmp")])
828 (define_insn "altivec_vmhaddshs"
829   [(set (match_operand:V8HI 0 "register_operand" "=v")
830         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
831                       (match_operand:V8HI 2 "register_operand" "v")
832                       (match_operand:V8HI 3 "register_operand" "v")]
833                      UNSPEC_VMHADDSHS))
834    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
835   "TARGET_ALTIVEC"
836   "vmhaddshs %0,%1,%2,%3"
837   [(set_attr "type" "veccomplex")])
839 (define_insn "altivec_vmhraddshs"
840   [(set (match_operand:V8HI 0 "register_operand" "=v")
841         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
842                       (match_operand:V8HI 2 "register_operand" "v")
843                       (match_operand:V8HI 3 "register_operand" "v")]
844                      UNSPEC_VMHRADDSHS))
845    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
846   "TARGET_ALTIVEC"
847   "vmhraddshs %0,%1,%2,%3"
848   [(set_attr "type" "veccomplex")])
850 (define_insn "altivec_vmladduhm"
851   [(set (match_operand:V8HI 0 "register_operand" "=v")
852         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
853                       (match_operand:V8HI 2 "register_operand" "v")
854                       (match_operand:V8HI 3 "register_operand" "v")]
855                      UNSPEC_VMLADDUHM))]
856   "TARGET_ALTIVEC"
857   "vmladduhm %0,%1,%2,%3"
858   [(set_attr "type" "veccomplex")])
860 (define_expand "altivec_vmrghb"
861   [(use (match_operand:V16QI 0 "register_operand" ""))
862    (use (match_operand:V16QI 1 "register_operand" ""))
863    (use (match_operand:V16QI 2 "register_operand" ""))]
864   "TARGET_ALTIVEC"
866   rtvec v;
867   rtx x;
869   /* Special handling for LE with -maltivec=be.  */
870   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
871     {
872       v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25),
873                      GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27),
874                      GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29),
875                      GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31));
876       x = gen_rtx_VEC_CONCAT (V32QImode, operands[2], operands[1]);
877     }
878   else
879     {
880       v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17),
881                      GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19),
882                      GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21),
883                      GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23));
884       x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
885     }
887   x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
888   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
889   DONE;
892 (define_insn "*altivec_vmrghb_internal"
893   [(set (match_operand:V16QI 0 "register_operand" "=v")
894         (vec_select:V16QI
895           (vec_concat:V32QI
896             (match_operand:V16QI 1 "register_operand" "v")
897             (match_operand:V16QI 2 "register_operand" "v"))
898           (parallel [(const_int 0) (const_int 16)
899                      (const_int 1) (const_int 17)
900                      (const_int 2) (const_int 18)
901                      (const_int 3) (const_int 19)
902                      (const_int 4) (const_int 20)
903                      (const_int 5) (const_int 21)
904                      (const_int 6) (const_int 22)
905                      (const_int 7) (const_int 23)])))]
906   "TARGET_ALTIVEC"
908   if (BYTES_BIG_ENDIAN)
909     return "vmrghb %0,%1,%2";
910   else
911     return "vmrglb %0,%2,%1";
913   [(set_attr "type" "vecperm")])
915 (define_insn "altivec_vmrghb_direct"
916   [(set (match_operand:V16QI 0 "register_operand" "=v")
917         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
918                        (match_operand:V16QI 2 "register_operand" "v")]
919                       UNSPEC_VMRGH_DIRECT))]
920   "TARGET_ALTIVEC"
921   "vmrghb %0,%1,%2"
922   [(set_attr "type" "vecperm")])
924 (define_expand "altivec_vmrghh"
925   [(use (match_operand:V8HI 0 "register_operand" ""))
926    (use (match_operand:V8HI 1 "register_operand" ""))
927    (use (match_operand:V8HI 2 "register_operand" ""))]
928   "TARGET_ALTIVEC"
930   rtvec v;
931   rtx x;
933   /* Special handling for LE with -maltivec=be.  */
934   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
935     {
936       v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13),
937                      GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15));
938       x = gen_rtx_VEC_CONCAT (V16HImode, operands[2], operands[1]);
939     }
940   else
941     {
942       v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9),
943                      GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11));
944       x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
945     }
947   x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
948   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
949   DONE;
952 (define_insn "*altivec_vmrghh_internal"
953   [(set (match_operand:V8HI 0 "register_operand" "=v")
954         (vec_select:V8HI
955           (vec_concat:V16HI
956             (match_operand:V8HI 1 "register_operand" "v")
957             (match_operand:V8HI 2 "register_operand" "v"))
958           (parallel [(const_int 0) (const_int 8)
959                      (const_int 1) (const_int 9)
960                      (const_int 2) (const_int 10)
961                      (const_int 3) (const_int 11)])))]
962   "TARGET_ALTIVEC"
964   if (BYTES_BIG_ENDIAN)
965     return "vmrghh %0,%1,%2";
966   else
967     return "vmrglh %0,%2,%1";
969   [(set_attr "type" "vecperm")])
971 (define_insn "altivec_vmrghh_direct"
972   [(set (match_operand:V8HI 0 "register_operand" "=v")
973         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
974                       (match_operand:V8HI 2 "register_operand" "v")]
975                      UNSPEC_VMRGH_DIRECT))]
976   "TARGET_ALTIVEC"
977   "vmrghh %0,%1,%2"
978   [(set_attr "type" "vecperm")])
980 (define_expand "altivec_vmrghw"
981   [(use (match_operand:V4SI 0 "register_operand" ""))
982    (use (match_operand:V4SI 1 "register_operand" ""))
983    (use (match_operand:V4SI 2 "register_operand" ""))]
984   "VECTOR_MEM_ALTIVEC_P (V4SImode)"
986   rtvec v;
987   rtx x;
989   /* Special handling for LE with -maltivec=be.  */
990   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
991     {
992       v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7));
993       x = gen_rtx_VEC_CONCAT (V8SImode, operands[2], operands[1]);
994     }
995   else
996     {
997       v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5));
998       x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
999     }
1001   x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1002   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1003   DONE;
1006 (define_insn "*altivec_vmrghw_internal"
1007   [(set (match_operand:V4SI 0 "register_operand" "=v")
1008         (vec_select:V4SI
1009           (vec_concat:V8SI
1010             (match_operand:V4SI 1 "register_operand" "v")
1011             (match_operand:V4SI 2 "register_operand" "v"))
1012           (parallel [(const_int 0) (const_int 4)
1013                      (const_int 1) (const_int 5)])))]
1014   "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1016   if (BYTES_BIG_ENDIAN)
1017     return "vmrghw %0,%1,%2";
1018   else
1019     return "vmrglw %0,%2,%1";
1021   [(set_attr "type" "vecperm")])
1023 (define_insn "altivec_vmrghw_direct"
1024   [(set (match_operand:V4SI 0 "register_operand" "=v")
1025         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1026                       (match_operand:V4SI 2 "register_operand" "v")]
1027                      UNSPEC_VMRGH_DIRECT))]
1028   "TARGET_ALTIVEC"
1029   "vmrghw %0,%1,%2"
1030   [(set_attr "type" "vecperm")])
1032 (define_insn "*altivec_vmrghsf"
1033   [(set (match_operand:V4SF 0 "register_operand" "=v")
1034         (vec_select:V4SF
1035           (vec_concat:V8SF
1036             (match_operand:V4SF 1 "register_operand" "v")
1037             (match_operand:V4SF 2 "register_operand" "v"))
1038           (parallel [(const_int 0) (const_int 4)
1039                      (const_int 1) (const_int 5)])))]
1040   "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
1042   if (BYTES_BIG_ENDIAN)
1043     return "vmrghw %0,%1,%2";
1044   else
1045     return "vmrglw %0,%2,%1";
1047   [(set_attr "type" "vecperm")])
1049 (define_expand "altivec_vmrglb"
1050   [(use (match_operand:V16QI 0 "register_operand" ""))
1051    (use (match_operand:V16QI 1 "register_operand" ""))
1052    (use (match_operand:V16QI 2 "register_operand" ""))]
1053   "TARGET_ALTIVEC"
1055   rtvec v;
1056   rtx x;
1058   /* Special handling for LE with -maltivec=be.  */
1059   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1060     {
1061       v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17),
1062                      GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19),
1063                      GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21),
1064                      GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23));
1065       x = gen_rtx_VEC_CONCAT (V32QImode, operands[2], operands[1]);
1066     }
1067   else
1068     {
1069       v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25),
1070                      GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27),
1071                      GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29),
1072                      GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31));
1073       x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
1074     }
1076   x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1077   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1078   DONE;
1081 (define_insn "*altivec_vmrglb_internal"
1082   [(set (match_operand:V16QI 0 "register_operand" "=v")
1083         (vec_select:V16QI
1084           (vec_concat:V32QI
1085             (match_operand:V16QI 1 "register_operand" "v")
1086             (match_operand:V16QI 2 "register_operand" "v"))
1087           (parallel [(const_int  8) (const_int 24)
1088                      (const_int  9) (const_int 25)
1089                      (const_int 10) (const_int 26)
1090                      (const_int 11) (const_int 27)
1091                      (const_int 12) (const_int 28)
1092                      (const_int 13) (const_int 29)
1093                      (const_int 14) (const_int 30)
1094                      (const_int 15) (const_int 31)])))]
1095   "TARGET_ALTIVEC"
1097   if (BYTES_BIG_ENDIAN)
1098     return "vmrglb %0,%1,%2";
1099   else
1100     return "vmrghb %0,%2,%1";
1102   [(set_attr "type" "vecperm")])
1104 (define_insn "altivec_vmrglb_direct"
1105   [(set (match_operand:V16QI 0 "register_operand" "=v")
1106         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1107                        (match_operand:V16QI 2 "register_operand" "v")]
1108                       UNSPEC_VMRGL_DIRECT))]
1109   "TARGET_ALTIVEC"
1110   "vmrglb %0,%1,%2"
1111   [(set_attr "type" "vecperm")])
1113 (define_expand "altivec_vmrglh"
1114   [(use (match_operand:V8HI 0 "register_operand" ""))
1115    (use (match_operand:V8HI 1 "register_operand" ""))
1116    (use (match_operand:V8HI 2 "register_operand" ""))]
1117   "TARGET_ALTIVEC"
1119   rtvec v;
1120   rtx x;
1122   /* Special handling for LE with -maltivec=be.  */
1123   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1124     {
1125       v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9),
1126                      GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11));
1127       x = gen_rtx_VEC_CONCAT (V16HImode, operands[2], operands[1]);
1128     }
1129   else
1130     {
1131       v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13),
1132                      GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15));
1133       x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
1134     }
1136   x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1137   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1138   DONE;
1141 (define_insn "*altivec_vmrglh_internal"
1142   [(set (match_operand:V8HI 0 "register_operand" "=v")
1143         (vec_select:V8HI
1144           (vec_concat:V16HI
1145             (match_operand:V8HI 1 "register_operand" "v")
1146             (match_operand:V8HI 2 "register_operand" "v"))
1147           (parallel [(const_int 4) (const_int 12)
1148                      (const_int 5) (const_int 13)
1149                      (const_int 6) (const_int 14)
1150                      (const_int 7) (const_int 15)])))]
1151   "TARGET_ALTIVEC"
1153   if (BYTES_BIG_ENDIAN)
1154     return "vmrglh %0,%1,%2";
1155   else
1156     return "vmrghh %0,%2,%1";
1158   [(set_attr "type" "vecperm")])
1160 (define_insn "altivec_vmrglh_direct"
1161   [(set (match_operand:V8HI 0 "register_operand" "=v")
1162         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
1163                       (match_operand:V8HI 2 "register_operand" "v")]
1164                      UNSPEC_VMRGL_DIRECT))]
1165   "TARGET_ALTIVEC"
1166   "vmrglh %0,%1,%2"
1167   [(set_attr "type" "vecperm")])
1169 (define_expand "altivec_vmrglw"
1170   [(use (match_operand:V4SI 0 "register_operand" ""))
1171    (use (match_operand:V4SI 1 "register_operand" ""))
1172    (use (match_operand:V4SI 2 "register_operand" ""))]
1173   "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1175   rtvec v;
1176   rtx x;
1178   /* Special handling for LE with -maltivec=be.  */
1179   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1180     {
1181       v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5));
1182       x = gen_rtx_VEC_CONCAT (V8SImode, operands[2], operands[1]);
1183     }
1184   else
1185     {
1186       v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7));
1187       x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
1188     }
1190   x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
1191   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1192   DONE;
1195 (define_insn "*altivec_vmrglw_internal"
1196   [(set (match_operand:V4SI 0 "register_operand" "=v")
1197         (vec_select:V4SI
1198           (vec_concat:V8SI
1199             (match_operand:V4SI 1 "register_operand" "v")
1200             (match_operand:V4SI 2 "register_operand" "v"))
1201           (parallel [(const_int 2) (const_int 6)
1202                      (const_int 3) (const_int 7)])))]
1203   "VECTOR_MEM_ALTIVEC_P (V4SImode)"
1205   if (BYTES_BIG_ENDIAN)
1206     return "vmrglw %0,%1,%2";
1207   else
1208     return "vmrghw %0,%2,%1";
1210   [(set_attr "type" "vecperm")])
1212 (define_insn "altivec_vmrglw_direct"
1213   [(set (match_operand:V4SI 0 "register_operand" "=v")
1214         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1215                       (match_operand:V4SI 2 "register_operand" "v")]
1216                      UNSPEC_VMRGL_DIRECT))]
1217   "TARGET_ALTIVEC"
1218   "vmrglw %0,%1,%2"
1219   [(set_attr "type" "vecperm")])
1221 (define_insn "*altivec_vmrglsf"
1222   [(set (match_operand:V4SF 0 "register_operand" "=v")
1223         (vec_select:V4SF
1224          (vec_concat:V8SF
1225            (match_operand:V4SF 1 "register_operand" "v")
1226            (match_operand:V4SF 2 "register_operand" "v"))
1227          (parallel [(const_int 2) (const_int 6)
1228                     (const_int 3) (const_int 7)])))]
1229   "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
1231   if (BYTES_BIG_ENDIAN)
1232     return "vmrglw %0,%1,%2";
1233   else
1234     return "vmrghw %0,%2,%1";
1236   [(set_attr "type" "vecperm")])
1238 ;; Power8 vector merge even/odd
1239 (define_insn "p8_vmrgew"
1240   [(set (match_operand:V4SI 0 "register_operand" "=v")
1241         (vec_select:V4SI
1242           (vec_concat:V8SI
1243             (match_operand:V4SI 1 "register_operand" "v")
1244             (match_operand:V4SI 2 "register_operand" "v"))
1245           (parallel [(const_int 0) (const_int 4)
1246                      (const_int 2) (const_int 6)])))]
1247   "TARGET_P8_VECTOR"
1249   if (BYTES_BIG_ENDIAN)
1250     return "vmrgew %0,%1,%2";
1251   else
1252     return "vmrgow %0,%2,%1";
1254   [(set_attr "type" "vecperm")])
1256 (define_insn "p8_vmrgow"
1257   [(set (match_operand:V4SI 0 "register_operand" "=v")
1258         (vec_select:V4SI
1259           (vec_concat:V8SI
1260             (match_operand:V4SI 1 "register_operand" "v")
1261             (match_operand:V4SI 2 "register_operand" "v"))
1262           (parallel [(const_int 1) (const_int 5)
1263                      (const_int 3) (const_int 7)])))]
1264   "TARGET_P8_VECTOR"
1266   if (BYTES_BIG_ENDIAN)
1267     return "vmrgow %0,%1,%2";
1268   else
1269     return "vmrgew %0,%2,%1";
1271   [(set_attr "type" "vecperm")])
1273 (define_expand "vec_widen_umult_even_v16qi"
1274   [(use (match_operand:V8HI 0 "register_operand" ""))
1275    (use (match_operand:V16QI 1 "register_operand" ""))
1276    (use (match_operand:V16QI 2 "register_operand" ""))]
1277   "TARGET_ALTIVEC"
1279   if (VECTOR_ELT_ORDER_BIG)
1280     emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
1281   else
1282     emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
1283   DONE;
1286 (define_expand "vec_widen_smult_even_v16qi"
1287   [(use (match_operand:V8HI 0 "register_operand" ""))
1288    (use (match_operand:V16QI 1 "register_operand" ""))
1289    (use (match_operand:V16QI 2 "register_operand" ""))]
1290   "TARGET_ALTIVEC"
1292   if (VECTOR_ELT_ORDER_BIG)
1293     emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
1294   else
1295     emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
1296   DONE;
1299 (define_expand "vec_widen_umult_even_v8hi"
1300   [(use (match_operand:V4SI 0 "register_operand" ""))
1301    (use (match_operand:V8HI 1 "register_operand" ""))
1302    (use (match_operand:V8HI 2 "register_operand" ""))]
1303   "TARGET_ALTIVEC"
1305   if (VECTOR_ELT_ORDER_BIG)
1306     emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
1307   else
1308     emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
1309   DONE;
1312 (define_expand "vec_widen_smult_even_v8hi"
1313   [(use (match_operand:V4SI 0 "register_operand" ""))
1314    (use (match_operand:V8HI 1 "register_operand" ""))
1315    (use (match_operand:V8HI 2 "register_operand" ""))]
1316   "TARGET_ALTIVEC"
1318   if (VECTOR_ELT_ORDER_BIG)
1319     emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
1320   else
1321     emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
1322   DONE;
1325 (define_expand "vec_widen_umult_odd_v16qi"
1326   [(use (match_operand:V8HI 0 "register_operand" ""))
1327    (use (match_operand:V16QI 1 "register_operand" ""))
1328    (use (match_operand:V16QI 2 "register_operand" ""))]
1329   "TARGET_ALTIVEC"
1331   if (VECTOR_ELT_ORDER_BIG)
1332     emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
1333   else
1334     emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
1335   DONE;
1338 (define_expand "vec_widen_smult_odd_v16qi"
1339   [(use (match_operand:V8HI 0 "register_operand" ""))
1340    (use (match_operand:V16QI 1 "register_operand" ""))
1341    (use (match_operand:V16QI 2 "register_operand" ""))]
1342   "TARGET_ALTIVEC"
1344   if (VECTOR_ELT_ORDER_BIG)
1345     emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
1346   else
1347     emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
1348   DONE;
1351 (define_expand "vec_widen_umult_odd_v8hi"
1352   [(use (match_operand:V4SI 0 "register_operand" ""))
1353    (use (match_operand:V8HI 1 "register_operand" ""))
1354    (use (match_operand:V8HI 2 "register_operand" ""))]
1355   "TARGET_ALTIVEC"
1357   if (VECTOR_ELT_ORDER_BIG)
1358     emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
1359   else
1360     emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
1361   DONE;
1364 (define_expand "vec_widen_smult_odd_v8hi"
1365   [(use (match_operand:V4SI 0 "register_operand" ""))
1366    (use (match_operand:V8HI 1 "register_operand" ""))
1367    (use (match_operand:V8HI 2 "register_operand" ""))]
1368   "TARGET_ALTIVEC"
1370   if (VECTOR_ELT_ORDER_BIG)
1371     emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
1372   else
1373     emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
1374   DONE;
1377 (define_insn "altivec_vmuleub"
1378   [(set (match_operand:V8HI 0 "register_operand" "=v")
1379         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1380                       (match_operand:V16QI 2 "register_operand" "v")]
1381                      UNSPEC_VMULEUB))]
1382   "TARGET_ALTIVEC"
1383   "vmuleub %0,%1,%2"
1384   [(set_attr "type" "veccomplex")])
1386 (define_insn "altivec_vmuloub"
1387   [(set (match_operand:V8HI 0 "register_operand" "=v")
1388         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1389                       (match_operand:V16QI 2 "register_operand" "v")]
1390                      UNSPEC_VMULOUB))]
1391   "TARGET_ALTIVEC"
1392   "vmuloub %0,%1,%2"
1393   [(set_attr "type" "veccomplex")])
1395 (define_insn "altivec_vmulesb"
1396   [(set (match_operand:V8HI 0 "register_operand" "=v")
1397         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1398                       (match_operand:V16QI 2 "register_operand" "v")]
1399                      UNSPEC_VMULESB))]
1400   "TARGET_ALTIVEC"
1401   "vmulesb %0,%1,%2"
1402   [(set_attr "type" "veccomplex")])
1404 (define_insn "altivec_vmulosb"
1405   [(set (match_operand:V8HI 0 "register_operand" "=v")
1406         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
1407                       (match_operand:V16QI 2 "register_operand" "v")]
1408                      UNSPEC_VMULOSB))]
1409   "TARGET_ALTIVEC"
1410   "vmulosb %0,%1,%2"
1411   [(set_attr "type" "veccomplex")])
1413 (define_insn "altivec_vmuleuh"
1414   [(set (match_operand:V4SI 0 "register_operand" "=v")
1415         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1416                       (match_operand:V8HI 2 "register_operand" "v")]
1417                      UNSPEC_VMULEUH))]
1418   "TARGET_ALTIVEC"
1419   "vmuleuh %0,%1,%2"
1420   [(set_attr "type" "veccomplex")])
1422 (define_insn "altivec_vmulouh"
1423   [(set (match_operand:V4SI 0 "register_operand" "=v")
1424         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1425                       (match_operand:V8HI 2 "register_operand" "v")]
1426                      UNSPEC_VMULOUH))]
1427   "TARGET_ALTIVEC"
1428   "vmulouh %0,%1,%2"
1429   [(set_attr "type" "veccomplex")])
1431 (define_insn "altivec_vmulesh"
1432   [(set (match_operand:V4SI 0 "register_operand" "=v")
1433         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1434                       (match_operand:V8HI 2 "register_operand" "v")]
1435                      UNSPEC_VMULESH))]
1436   "TARGET_ALTIVEC"
1437   "vmulesh %0,%1,%2"
1438   [(set_attr "type" "veccomplex")])
1440 (define_insn "altivec_vmulosh"
1441   [(set (match_operand:V4SI 0 "register_operand" "=v")
1442         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
1443                       (match_operand:V8HI 2 "register_operand" "v")]
1444                      UNSPEC_VMULOSH))]
1445   "TARGET_ALTIVEC"
1446   "vmulosh %0,%1,%2"
1447   [(set_attr "type" "veccomplex")])
1450 ;; Vector pack/unpack
1451 (define_insn "altivec_vpkpx"
1452   [(set (match_operand:V8HI 0 "register_operand" "=v")
1453         (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
1454                       (match_operand:V4SI 2 "register_operand" "v")]
1455                      UNSPEC_VPKPX))]
1456   "TARGET_ALTIVEC"
1457   "*
1458   {
1459     if (VECTOR_ELT_ORDER_BIG)
1460       return \"vpkpx %0,%1,%2\";
1461     else
1462       return \"vpkpx %0,%2,%1\";
1463   }"
1464   [(set_attr "type" "vecperm")])
1466 (define_insn "altivec_vpks<VI_char>ss"
1467   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1468         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1469                             (match_operand:VP 2 "register_operand" "v")]
1470                            UNSPEC_VPACK_SIGN_SIGN_SAT))]
1471   "<VI_unit>"
1472   "*
1473   {
1474     if (VECTOR_ELT_ORDER_BIG)
1475       return \"vpks<VI_char>ss %0,%1,%2\";
1476     else
1477       return \"vpks<VI_char>ss %0,%2,%1\";
1478   }"
1479   [(set_attr "type" "vecperm")])
1481 (define_insn "altivec_vpks<VI_char>us"
1482   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1483         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1484                             (match_operand:VP 2 "register_operand" "v")]
1485                            UNSPEC_VPACK_SIGN_UNS_SAT))]
1486   "<VI_unit>"
1487   "*
1488   {
1489     if (VECTOR_ELT_ORDER_BIG)
1490       return \"vpks<VI_char>us %0,%1,%2\";
1491     else
1492       return \"vpks<VI_char>us %0,%2,%1\";
1493   }"
1494   [(set_attr "type" "vecperm")])
1496 (define_insn "altivec_vpku<VI_char>us"
1497   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1498         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1499                             (match_operand:VP 2 "register_operand" "v")]
1500                            UNSPEC_VPACK_UNS_UNS_SAT))]
1501   "<VI_unit>"
1502   "*
1503   {
1504     if (VECTOR_ELT_ORDER_BIG)
1505       return \"vpku<VI_char>us %0,%1,%2\";
1506     else
1507       return \"vpku<VI_char>us %0,%2,%1\";
1508   }"
1509   [(set_attr "type" "vecperm")])
1511 (define_insn "altivec_vpku<VI_char>um"
1512   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1513         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1514                             (match_operand:VP 2 "register_operand" "v")]
1515                            UNSPEC_VPACK_UNS_UNS_MOD))]
1516   "<VI_unit>"
1517   "*
1518   {
1519     if (VECTOR_ELT_ORDER_BIG)
1520       return \"vpku<VI_char>um %0,%1,%2\";
1521     else
1522       return \"vpku<VI_char>um %0,%2,%1\";
1523   }"
1524   [(set_attr "type" "vecperm")])
1526 (define_insn "altivec_vpku<VI_char>um_direct"
1527   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
1528         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
1529                             (match_operand:VP 2 "register_operand" "v")]
1530                            UNSPEC_VPACK_UNS_UNS_MOD_DIRECT))]
1531   "<VI_unit>"
1532   "*
1533   {
1534     if (BYTES_BIG_ENDIAN)
1535       return \"vpku<VI_char>um %0,%1,%2\";
1536     else
1537       return \"vpku<VI_char>um %0,%2,%1\";
1538   }"
1539   [(set_attr "type" "vecperm")])
1541 (define_insn "*altivec_vrl<VI_char>"
1542   [(set (match_operand:VI2 0 "register_operand" "=v")
1543         (rotate:VI2 (match_operand:VI2 1 "register_operand" "v")
1544                     (match_operand:VI2 2 "register_operand" "v")))]
1545   "<VI_unit>"
1546   "vrl<VI_char> %0,%1,%2"
1547   [(set_attr "type" "vecsimple")])
1549 (define_insn "altivec_vsl"
1550   [(set (match_operand:V4SI 0 "register_operand" "=v")
1551         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1552                       (match_operand:V4SI 2 "register_operand" "v")]
1553                      UNSPEC_VSLV4SI))]
1554   "TARGET_ALTIVEC"
1555   "vsl %0,%1,%2"
1556   [(set_attr "type" "vecperm")])
1558 (define_insn "altivec_vslo"
1559   [(set (match_operand:V4SI 0 "register_operand" "=v")
1560         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1561                       (match_operand:V4SI 2 "register_operand" "v")]
1562                      UNSPEC_VSLO))]
1563   "TARGET_ALTIVEC"
1564   "vslo %0,%1,%2"
1565   [(set_attr "type" "vecperm")])
1567 (define_insn "*altivec_vsl<VI_char>"
1568   [(set (match_operand:VI2 0 "register_operand" "=v")
1569         (ashift:VI2 (match_operand:VI2 1 "register_operand" "v")
1570                     (match_operand:VI2 2 "register_operand" "v")))]
1571   "<VI_unit>"
1572   "vsl<VI_char> %0,%1,%2"
1573   [(set_attr "type" "vecsimple")])
1575 (define_insn "*altivec_vsr<VI_char>"
1576   [(set (match_operand:VI2 0 "register_operand" "=v")
1577         (lshiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
1578                       (match_operand:VI2 2 "register_operand" "v")))]
1579   "<VI_unit>"
1580   "vsr<VI_char> %0,%1,%2"
1581   [(set_attr "type" "vecsimple")])
1583 (define_insn "*altivec_vsra<VI_char>"
1584   [(set (match_operand:VI2 0 "register_operand" "=v")
1585         (ashiftrt:VI2 (match_operand:VI2 1 "register_operand" "v")
1586                       (match_operand:VI2 2 "register_operand" "v")))]
1587   "<VI_unit>"
1588   "vsra<VI_char> %0,%1,%2"
1589   [(set_attr "type" "vecsimple")])
1591 (define_insn "altivec_vsr"
1592   [(set (match_operand:V4SI 0 "register_operand" "=v")
1593         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1594                       (match_operand:V4SI 2 "register_operand" "v")]
1595                      UNSPEC_VSR))]
1596   "TARGET_ALTIVEC"
1597   "vsr %0,%1,%2"
1598   [(set_attr "type" "vecperm")])
1600 (define_insn "altivec_vsro"
1601   [(set (match_operand:V4SI 0 "register_operand" "=v")
1602         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1603                       (match_operand:V4SI 2 "register_operand" "v")]
1604                      UNSPEC_VSRO))]
1605   "TARGET_ALTIVEC"
1606   "vsro %0,%1,%2"
1607   [(set_attr "type" "vecperm")])
1609 (define_insn "altivec_vsum4ubs"
1610   [(set (match_operand:V4SI 0 "register_operand" "=v")
1611         (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
1612                       (match_operand:V4SI 2 "register_operand" "v")]
1613                      UNSPEC_VSUM4UBS))
1614    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1615   "TARGET_ALTIVEC"
1616   "vsum4ubs %0,%1,%2"
1617   [(set_attr "type" "veccomplex")])
1619 (define_insn "altivec_vsum4s<VI_char>s"
1620   [(set (match_operand:V4SI 0 "register_operand" "=v")
1621         (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
1622                       (match_operand:V4SI 2 "register_operand" "v")]
1623                      UNSPEC_VSUM4S))
1624    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1625   "TARGET_ALTIVEC"
1626   "vsum4s<VI_char>s %0,%1,%2"
1627   [(set_attr "type" "veccomplex")])
1629 ;; FIXME: For the following two patterns, the scratch should only be
1630 ;; allocated for !VECTOR_ELT_ORDER_BIG, and the instructions should
1631 ;; be emitted separately.
1632 (define_insn "altivec_vsum2sws"
1633   [(set (match_operand:V4SI 0 "register_operand" "=v")
1634         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1635                       (match_operand:V4SI 2 "register_operand" "v")]
1636                      UNSPEC_VSUM2SWS))
1637    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))
1638    (clobber (match_scratch:V4SI 3 "=v"))]
1639   "TARGET_ALTIVEC"
1641   if (VECTOR_ELT_ORDER_BIG)
1642     return "vsum2sws %0,%1,%2";
1643   else
1644     return "vsldoi %3,%2,%2,12\n\tvsum2sws %3,%1,%3\n\tvsldoi %0,%3,%3,4";
1646   [(set_attr "type" "veccomplex")
1647    (set (attr "length")
1648      (if_then_else
1649        (match_test "VECTOR_ELT_ORDER_BIG")
1650        (const_string "4")
1651        (const_string "12")))])
1653 (define_insn "altivec_vsumsws"
1654   [(set (match_operand:V4SI 0 "register_operand" "=v")
1655         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1656                       (match_operand:V4SI 2 "register_operand" "v")]
1657                      UNSPEC_VSUMSWS))
1658    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))
1659    (clobber (match_scratch:V4SI 3 "=v"))]
1660   "TARGET_ALTIVEC"
1662   if (VECTOR_ELT_ORDER_BIG)
1663     return "vsumsws %0,%1,%2";
1664   else
1665     return "vspltw %3,%2,0\n\tvsumsws %3,%1,%3\n\tvsldoi %0,%3,%3,12";
1667   [(set_attr "type" "veccomplex")
1668    (set (attr "length")
1669      (if_then_else
1670        (match_test "(VECTOR_ELT_ORDER_BIG)")
1671        (const_string "4")
1672        (const_string "12")))])
1674 (define_insn "altivec_vsumsws_direct"
1675   [(set (match_operand:V4SI 0 "register_operand" "=v")
1676         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1677                       (match_operand:V4SI 2 "register_operand" "v")]
1678                      UNSPEC_VSUMSWS_DIRECT))
1679    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
1680   "TARGET_ALTIVEC"
1681   "vsumsws %0,%1,%2"
1682   [(set_attr "type" "veccomplex")])
1684 (define_expand "altivec_vspltb"
1685   [(use (match_operand:V16QI 0 "register_operand" ""))
1686    (use (match_operand:V16QI 1 "register_operand" ""))
1687    (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
1688   "TARGET_ALTIVEC"
1690   rtvec v;
1691   rtx x;
1693   /* Special handling for LE with -maltivec=be.  We have to reflect
1694      the actual selected index for the splat in the RTL.  */
1695   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1696     operands[2] = GEN_INT (15 - INTVAL (operands[2]));
1698   v = gen_rtvec (1, operands[2]);
1699   x = gen_rtx_VEC_SELECT (QImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1700   x = gen_rtx_VEC_DUPLICATE (V16QImode, x);
1701   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1702   DONE;
1705 (define_insn "*altivec_vspltb_internal"
1706   [(set (match_operand:V16QI 0 "register_operand" "=v")
1707         (vec_duplicate:V16QI
1708          (vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
1709                         (parallel
1710                          [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
1711   "TARGET_ALTIVEC"
1713   /* For true LE, this adjusts the selected index.  For LE with 
1714      -maltivec=be, this reverses what was done in the define_expand
1715      because the instruction already has big-endian bias.  */
1716   if (!BYTES_BIG_ENDIAN)
1717     operands[2] = GEN_INT (15 - INTVAL (operands[2]));
1719   return "vspltb %0,%1,%2";
1721   [(set_attr "type" "vecperm")])
1723 (define_insn "altivec_vspltb_direct"
1724   [(set (match_operand:V16QI 0 "register_operand" "=v")
1725         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
1726                        (match_operand:QI 2 "u5bit_cint_operand" "i")]
1727                       UNSPEC_VSPLT_DIRECT))]
1728   "TARGET_ALTIVEC"
1729   "vspltb %0,%1,%2"
1730   [(set_attr "type" "vecperm")])
1732 (define_expand "altivec_vsplth"
1733   [(use (match_operand:V8HI 0 "register_operand" ""))
1734    (use (match_operand:V8HI 1 "register_operand" ""))
1735    (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
1736   "TARGET_ALTIVEC"
1738   rtvec v;
1739   rtx x;
1741   /* Special handling for LE with -maltivec=be.  We have to reflect
1742      the actual selected index for the splat in the RTL.  */
1743   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1744     operands[2] = GEN_INT (7 - INTVAL (operands[2]));
1746   v = gen_rtvec (1, operands[2]);
1747   x = gen_rtx_VEC_SELECT (HImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1748   x = gen_rtx_VEC_DUPLICATE (V8HImode, x);
1749   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1750   DONE;
1753 (define_insn "*altivec_vsplth_internal"
1754   [(set (match_operand:V8HI 0 "register_operand" "=v")
1755         (vec_duplicate:V8HI
1756          (vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
1757                         (parallel
1758                          [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
1759   "TARGET_ALTIVEC"
1761   /* For true LE, this adjusts the selected index.  For LE with 
1762      -maltivec=be, this reverses what was done in the define_expand
1763      because the instruction already has big-endian bias.  */
1764   if (!BYTES_BIG_ENDIAN)
1765     operands[2] = GEN_INT (7 - INTVAL (operands[2]));
1767   return "vsplth %0,%1,%2";
1769   [(set_attr "type" "vecperm")])
1771 (define_insn "altivec_vsplth_direct"
1772   [(set (match_operand:V8HI 0 "register_operand" "=v")
1773         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
1774                       (match_operand:QI 2 "u5bit_cint_operand" "i")]
1775                      UNSPEC_VSPLT_DIRECT))]
1776   "TARGET_ALTIVEC"
1777   "vsplth %0,%1,%2"
1778   [(set_attr "type" "vecperm")])
1780 (define_expand "altivec_vspltw"
1781   [(use (match_operand:V4SI 0 "register_operand" ""))
1782    (use (match_operand:V4SI 1 "register_operand" ""))
1783    (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
1784   "TARGET_ALTIVEC"
1786   rtvec v;
1787   rtx x;
1789   /* Special handling for LE with -maltivec=be.  We have to reflect
1790      the actual selected index for the splat in the RTL.  */
1791   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1792     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1794   v = gen_rtvec (1, operands[2]);
1795   x = gen_rtx_VEC_SELECT (SImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1796   x = gen_rtx_VEC_DUPLICATE (V4SImode, x);
1797   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1798   DONE;
1801 (define_insn "*altivec_vspltw_internal"
1802   [(set (match_operand:V4SI 0 "register_operand" "=v")
1803         (vec_duplicate:V4SI
1804          (vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
1805                         (parallel
1806                          [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
1807   "TARGET_ALTIVEC"
1809   /* For true LE, this adjusts the selected index.  For LE with 
1810      -maltivec=be, this reverses what was done in the define_expand
1811      because the instruction already has big-endian bias.  */
1812   if (!BYTES_BIG_ENDIAN)
1813     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1815   return "vspltw %0,%1,%2";
1817   [(set_attr "type" "vecperm")])
1819 (define_insn "altivec_vspltw_direct"
1820   [(set (match_operand:V4SI 0 "register_operand" "=v")
1821         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
1822                       (match_operand:QI 2 "u5bit_cint_operand" "i")]
1823                      UNSPEC_VSPLT_DIRECT))]
1824   "TARGET_ALTIVEC"
1825   "vspltw %0,%1,%2"
1826   [(set_attr "type" "vecperm")])
1828 (define_expand "altivec_vspltsf"
1829   [(use (match_operand:V4SF 0 "register_operand" ""))
1830    (use (match_operand:V4SF 1 "register_operand" ""))
1831    (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
1832   "TARGET_ALTIVEC"
1834   rtvec v;
1835   rtx x;
1837   /* Special handling for LE with -maltivec=be.  We have to reflect
1838      the actual selected index for the splat in the RTL.  */
1839   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
1840     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1842   v = gen_rtvec (1, operands[2]);
1843   x = gen_rtx_VEC_SELECT (SFmode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
1844   x = gen_rtx_VEC_DUPLICATE (V4SFmode, x);
1845   emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
1846   DONE;
1849 (define_insn "*altivec_vspltsf_internal"
1850   [(set (match_operand:V4SF 0 "register_operand" "=v")
1851         (vec_duplicate:V4SF
1852          (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
1853                         (parallel
1854                          [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
1855   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
1857   /* For true LE, this adjusts the selected index.  For LE with 
1858      -maltivec=be, this reverses what was done in the define_expand
1859      because the instruction already has big-endian bias.  */
1860   if (!BYTES_BIG_ENDIAN)
1861     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
1863   return "vspltw %0,%1,%2";
1865   [(set_attr "type" "vecperm")])
1867 (define_insn "altivec_vspltis<VI_char>"
1868   [(set (match_operand:VI 0 "register_operand" "=v")
1869         (vec_duplicate:VI
1870          (match_operand:QI 1 "s5bit_cint_operand" "i")))]
1871   "TARGET_ALTIVEC"
1872   "vspltis<VI_char> %0,%1"
1873   [(set_attr "type" "vecperm")])
1875 (define_insn "*altivec_vrfiz"
1876   [(set (match_operand:V4SF 0 "register_operand" "=v")
1877         (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
1878   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
1879   "vrfiz %0,%1"
1880   [(set_attr "type" "vecfloat")])
1882 (define_expand "altivec_vperm_<mode>"
1883   [(set (match_operand:VM 0 "register_operand" "=v")
1884         (unspec:VM [(match_operand:VM 1 "register_operand" "v")
1885                     (match_operand:VM 2 "register_operand" "v")
1886                     (match_operand:V16QI 3 "register_operand" "v")]
1887                    UNSPEC_VPERM))]
1888   "TARGET_ALTIVEC"
1890   if (!VECTOR_ELT_ORDER_BIG)
1891     {
1892       altivec_expand_vec_perm_le (operands);
1893       DONE;
1894     }
1897 (define_insn "*altivec_vperm_<mode>_internal"
1898   [(set (match_operand:VM 0 "register_operand" "=v")
1899         (unspec:VM [(match_operand:VM 1 "register_operand" "v")
1900                     (match_operand:VM 2 "register_operand" "v")
1901                     (match_operand:V16QI 3 "register_operand" "v")]
1902                    UNSPEC_VPERM))]
1903   "TARGET_ALTIVEC"
1904   "vperm %0,%1,%2,%3"
1905   [(set_attr "type" "vecperm")])
1907 (define_expand "altivec_vperm_<mode>_uns"
1908   [(set (match_operand:VM 0 "register_operand" "=v")
1909         (unspec:VM [(match_operand:VM 1 "register_operand" "v")
1910                     (match_operand:VM 2 "register_operand" "v")
1911                     (match_operand:V16QI 3 "register_operand" "v")]
1912                    UNSPEC_VPERM_UNS))]
1913   "TARGET_ALTIVEC"
1915   if (!VECTOR_ELT_ORDER_BIG)
1916     {
1917       altivec_expand_vec_perm_le (operands);
1918       DONE;
1919     }
1922 (define_insn "*altivec_vperm_<mode>_uns_internal"
1923   [(set (match_operand:VM 0 "register_operand" "=v")
1924         (unspec:VM [(match_operand:VM 1 "register_operand" "v")
1925                     (match_operand:VM 2 "register_operand" "v")
1926                     (match_operand:V16QI 3 "register_operand" "v")]
1927                    UNSPEC_VPERM_UNS))]
1928   "TARGET_ALTIVEC"
1929   "vperm %0,%1,%2,%3"
1930   [(set_attr "type" "vecperm")])
1932 (define_expand "vec_permv16qi"
1933   [(set (match_operand:V16QI 0 "register_operand" "")
1934         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "")
1935                        (match_operand:V16QI 2 "register_operand" "")
1936                        (match_operand:V16QI 3 "register_operand" "")]
1937                       UNSPEC_VPERM))]
1938   "TARGET_ALTIVEC"
1940   if (!BYTES_BIG_ENDIAN) {
1941     altivec_expand_vec_perm_le (operands);
1942     DONE;
1943   }
1946 (define_expand "vec_perm_constv16qi"
1947   [(match_operand:V16QI 0 "register_operand" "")
1948    (match_operand:V16QI 1 "register_operand" "")
1949    (match_operand:V16QI 2 "register_operand" "")
1950    (match_operand:V16QI 3 "" "")]
1951   "TARGET_ALTIVEC"
1953   if (altivec_expand_vec_perm_const (operands))
1954     DONE;
1955   else
1956     FAIL;
1959 (define_insn "altivec_vrfip"            ; ceil
1960   [(set (match_operand:V4SF 0 "register_operand" "=v")
1961         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
1962                      UNSPEC_FRIP))]
1963   "TARGET_ALTIVEC"
1964   "vrfip %0,%1"
1965   [(set_attr "type" "vecfloat")])
1967 (define_insn "altivec_vrfin"
1968   [(set (match_operand:V4SF 0 "register_operand" "=v")
1969         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
1970                      UNSPEC_VRFIN))]
1971   "TARGET_ALTIVEC"
1972   "vrfin %0,%1"
1973   [(set_attr "type" "vecfloat")])
1975 (define_insn "*altivec_vrfim"           ; floor
1976   [(set (match_operand:V4SF 0 "register_operand" "=v")
1977         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
1978                      UNSPEC_FRIM))]
1979   "TARGET_ALTIVEC"
1980   "vrfim %0,%1"
1981   [(set_attr "type" "vecfloat")])
1983 (define_insn "altivec_vcfux"
1984   [(set (match_operand:V4SF 0 "register_operand" "=v")
1985         (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
1986                       (match_operand:QI 2 "immediate_operand" "i")]
1987                      UNSPEC_VCFUX))]
1988   "TARGET_ALTIVEC"
1989   "vcfux %0,%1,%2"
1990   [(set_attr "type" "vecfloat")])
1992 (define_insn "altivec_vcfsx"
1993   [(set (match_operand:V4SF 0 "register_operand" "=v")
1994         (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
1995                       (match_operand:QI 2 "immediate_operand" "i")]
1996                      UNSPEC_VCFSX))]
1997   "TARGET_ALTIVEC"
1998   "vcfsx %0,%1,%2"
1999   [(set_attr "type" "vecfloat")])
2001 (define_insn "altivec_vctuxs"
2002   [(set (match_operand:V4SI 0 "register_operand" "=v")
2003         (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2004                       (match_operand:QI 2 "immediate_operand" "i")]
2005                      UNSPEC_VCTUXS))
2006    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2007   "TARGET_ALTIVEC"
2008   "vctuxs %0,%1,%2"
2009   [(set_attr "type" "vecfloat")])
2011 (define_insn "altivec_vctsxs"
2012   [(set (match_operand:V4SI 0 "register_operand" "=v")
2013         (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
2014                       (match_operand:QI 2 "immediate_operand" "i")]
2015                      UNSPEC_VCTSXS))
2016    (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
2017   "TARGET_ALTIVEC"
2018   "vctsxs %0,%1,%2"
2019   [(set_attr "type" "vecfloat")])
2021 (define_insn "altivec_vlogefp"
2022   [(set (match_operand:V4SF 0 "register_operand" "=v")
2023         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2024                      UNSPEC_VLOGEFP))]
2025   "TARGET_ALTIVEC"
2026   "vlogefp %0,%1"
2027   [(set_attr "type" "vecfloat")])
2029 (define_insn "altivec_vexptefp"
2030   [(set (match_operand:V4SF 0 "register_operand" "=v")
2031         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2032                      UNSPEC_VEXPTEFP))]
2033   "TARGET_ALTIVEC"
2034   "vexptefp %0,%1"
2035   [(set_attr "type" "vecfloat")])
2037 (define_insn "*altivec_vrsqrtefp"
2038   [(set (match_operand:V4SF 0 "register_operand" "=v")
2039         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2040                      UNSPEC_RSQRT))]
2041   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2042   "vrsqrtefp %0,%1"
2043   [(set_attr "type" "vecfloat")])
2045 (define_insn "altivec_vrefp"
2046   [(set (match_operand:V4SF 0 "register_operand" "=v")
2047         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
2048                      UNSPEC_FRES))]
2049   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2050   "vrefp %0,%1"
2051   [(set_attr "type" "vecfloat")])
2053 (define_expand "altivec_copysign_v4sf3"
2054   [(use (match_operand:V4SF 0 "register_operand" ""))
2055    (use (match_operand:V4SF 1 "register_operand" ""))
2056    (use (match_operand:V4SF 2 "register_operand" ""))]
2057   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2058   "
2060   rtx mask = gen_reg_rtx (V4SImode);
2061   rtvec v = rtvec_alloc (4);
2062   unsigned HOST_WIDE_INT mask_val = ((unsigned HOST_WIDE_INT)1) << 31;
2064   RTVEC_ELT (v, 0) = GEN_INT (mask_val);
2065   RTVEC_ELT (v, 1) = GEN_INT (mask_val);
2066   RTVEC_ELT (v, 2) = GEN_INT (mask_val);
2067   RTVEC_ELT (v, 3) = GEN_INT (mask_val);
2069   emit_insn (gen_vec_initv4si (mask, gen_rtx_PARALLEL (V4SImode, v)));
2070   emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2],
2071                                      gen_lowpart (V4SFmode, mask)));
2072   DONE;
2075 (define_insn "altivec_vsldoi_<mode>"
2076   [(set (match_operand:VM 0 "register_operand" "=v")
2077         (unspec:VM [(match_operand:VM 1 "register_operand" "v")
2078                     (match_operand:VM 2 "register_operand" "v")
2079                     (match_operand:QI 3 "immediate_operand" "i")]
2080                   UNSPEC_VLSDOI))]
2081   "TARGET_ALTIVEC"
2082   "vsldoi %0,%1,%2,%3"
2083   [(set_attr "type" "vecperm")])
2085 (define_insn "altivec_vupkhs<VU_char>"
2086   [(set (match_operand:VP 0 "register_operand" "=v")
2087         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2088                      UNSPEC_VUNPACK_HI_SIGN))]
2089   "<VI_unit>"
2091   if (VECTOR_ELT_ORDER_BIG)
2092     return "vupkhs<VU_char> %0,%1";
2093   else
2094     return "vupkls<VU_char> %0,%1";
2096   [(set_attr "type" "vecperm")])
2098 (define_insn "*altivec_vupkhs<VU_char>_direct"
2099   [(set (match_operand:VP 0 "register_operand" "=v")
2100         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2101                      UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
2102   "<VI_unit>"
2103   "vupkhs<VU_char> %0,%1"
2104   [(set_attr "type" "vecperm")])
2106 (define_insn "altivec_vupkls<VU_char>"
2107   [(set (match_operand:VP 0 "register_operand" "=v")
2108         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2109                      UNSPEC_VUNPACK_LO_SIGN))]
2110   "<VI_unit>"
2112   if (VECTOR_ELT_ORDER_BIG)
2113     return "vupkls<VU_char> %0,%1";
2114   else
2115     return "vupkhs<VU_char> %0,%1";
2117   [(set_attr "type" "vecperm")])
2119 (define_insn "*altivec_vupkls<VU_char>_direct"
2120   [(set (match_operand:VP 0 "register_operand" "=v")
2121         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2122                      UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
2123   "<VI_unit>"
2124   "vupkls<VU_char> %0,%1"
2125   [(set_attr "type" "vecperm")])
2127 (define_insn "altivec_vupkhpx"
2128   [(set (match_operand:V4SI 0 "register_operand" "=v")
2129         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2130                      UNSPEC_VUPKHPX))]
2131   "TARGET_ALTIVEC"
2133   if (VECTOR_ELT_ORDER_BIG)
2134     return "vupkhpx %0,%1";
2135   else
2136     return "vupklpx %0,%1";
2138   [(set_attr "type" "vecperm")])
2140 (define_insn "altivec_vupklpx"
2141   [(set (match_operand:V4SI 0 "register_operand" "=v")
2142         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2143                      UNSPEC_VUPKLPX))]
2144   "TARGET_ALTIVEC"
2146   if (VECTOR_ELT_ORDER_BIG)
2147     return "vupklpx %0,%1";
2148   else
2149     return "vupkhpx %0,%1";
2151   [(set_attr "type" "vecperm")])
2153 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
2154 ;; indicate a combined status
2155 (define_insn "*altivec_vcmpequ<VI_char>_p"
2156   [(set (reg:CC 74)
2157         (unspec:CC [(eq:CC (match_operand:VI2 1 "register_operand" "v")
2158                            (match_operand:VI2 2 "register_operand" "v"))]
2159                    UNSPEC_PREDICATE))
2160    (set (match_operand:VI2 0 "register_operand" "=v")
2161         (eq:VI2 (match_dup 1)
2162                 (match_dup 2)))]
2163   "<VI_unit>"
2164   "vcmpequ<VI_char>. %0,%1,%2"
2165   [(set_attr "type" "veccmp")])
2167 (define_insn "*altivec_vcmpgts<VI_char>_p"
2168   [(set (reg:CC 74)
2169         (unspec:CC [(gt:CC (match_operand:VI2 1 "register_operand" "v")
2170                            (match_operand:VI2 2 "register_operand" "v"))]
2171                    UNSPEC_PREDICATE))
2172    (set (match_operand:VI2 0 "register_operand" "=v")
2173         (gt:VI2 (match_dup 1)
2174                 (match_dup 2)))]
2175   "<VI_unit>"
2176   "vcmpgts<VI_char>. %0,%1,%2"
2177   [(set_attr "type" "veccmp")])
2179 (define_insn "*altivec_vcmpgtu<VI_char>_p"
2180   [(set (reg:CC 74)
2181         (unspec:CC [(gtu:CC (match_operand:VI2 1 "register_operand" "v")
2182                             (match_operand:VI2 2 "register_operand" "v"))]
2183                    UNSPEC_PREDICATE))
2184    (set (match_operand:VI2 0 "register_operand" "=v")
2185         (gtu:VI2 (match_dup 1)
2186                  (match_dup 2)))]
2187   "<VI_unit>"
2188   "vcmpgtu<VI_char>. %0,%1,%2"
2189   [(set_attr "type" "veccmp")])
2191 (define_insn "*altivec_vcmpeqfp_p"
2192   [(set (reg:CC 74)
2193         (unspec:CC [(eq:CC (match_operand:V4SF 1 "register_operand" "v")
2194                            (match_operand:V4SF 2 "register_operand" "v"))]
2195                    UNSPEC_PREDICATE))
2196    (set (match_operand:V4SF 0 "register_operand" "=v")
2197         (eq:V4SF (match_dup 1)
2198                  (match_dup 2)))]
2199   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2200   "vcmpeqfp. %0,%1,%2"
2201   [(set_attr "type" "veccmp")])
2203 (define_insn "*altivec_vcmpgtfp_p"
2204   [(set (reg:CC 74)
2205         (unspec:CC [(gt:CC (match_operand:V4SF 1 "register_operand" "v")
2206                            (match_operand:V4SF 2 "register_operand" "v"))]
2207                    UNSPEC_PREDICATE))
2208    (set (match_operand:V4SF 0 "register_operand" "=v")
2209         (gt:V4SF (match_dup 1)
2210                  (match_dup 2)))]
2211   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2212   "vcmpgtfp. %0,%1,%2"
2213   [(set_attr "type" "veccmp")])
2215 (define_insn "*altivec_vcmpgefp_p"
2216   [(set (reg:CC 74)
2217         (unspec:CC [(ge:CC (match_operand:V4SF 1 "register_operand" "v")
2218                            (match_operand:V4SF 2 "register_operand" "v"))]
2219                    UNSPEC_PREDICATE))
2220    (set (match_operand:V4SF 0 "register_operand" "=v")
2221         (ge:V4SF (match_dup 1)
2222                  (match_dup 2)))]
2223   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
2224   "vcmpgefp. %0,%1,%2"
2225   [(set_attr "type" "veccmp")])
2227 (define_insn "altivec_vcmpbfp_p"
2228   [(set (reg:CC 74)
2229         (unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
2230                     (match_operand:V4SF 2 "register_operand" "v")]
2231                    UNSPEC_VCMPBFP))
2232    (set (match_operand:V4SF 0 "register_operand" "=v")
2233         (unspec:V4SF [(match_dup 1)
2234                       (match_dup 2)] 
2235                       UNSPEC_VCMPBFP))]
2236   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
2237   "vcmpbfp. %0,%1,%2"
2238   [(set_attr "type" "veccmp")])
2240 (define_insn "altivec_mtvscr"
2241   [(set (reg:SI 110)
2242         (unspec_volatile:SI
2243          [(match_operand:V4SI 0 "register_operand" "v")] UNSPECV_MTVSCR))]
2244   "TARGET_ALTIVEC"
2245   "mtvscr %0"
2246   [(set_attr "type" "vecsimple")])
2248 (define_insn "altivec_mfvscr"
2249   [(set (match_operand:V8HI 0 "register_operand" "=v")
2250         (unspec_volatile:V8HI [(reg:SI 110)] UNSPECV_MFVSCR))]
2251   "TARGET_ALTIVEC"
2252   "mfvscr %0"
2253   [(set_attr "type" "vecsimple")])
2255 (define_insn "altivec_dssall"
2256   [(unspec_volatile [(const_int 0)] UNSPECV_DSSALL)]
2257   "TARGET_ALTIVEC"
2258   "dssall"
2259   [(set_attr "type" "vecsimple")])
2261 (define_insn "altivec_dss"
2262   [(unspec_volatile [(match_operand:QI 0 "immediate_operand" "i")]
2263                     UNSPECV_DSS)]
2264   "TARGET_ALTIVEC"
2265   "dss %0"
2266   [(set_attr "type" "vecsimple")])
2268 (define_insn "altivec_dst"
2269   [(unspec [(match_operand 0 "register_operand" "b")
2270             (match_operand:SI 1 "register_operand" "r")
2271             (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DST)]
2272   "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2273   "dst %0,%1,%2"
2274   [(set_attr "type" "vecsimple")])
2276 (define_insn "altivec_dstt"
2277   [(unspec [(match_operand 0 "register_operand" "b")
2278             (match_operand:SI 1 "register_operand" "r")
2279             (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTT)]
2280   "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2281   "dstt %0,%1,%2"
2282   [(set_attr "type" "vecsimple")])
2284 (define_insn "altivec_dstst"
2285   [(unspec [(match_operand 0 "register_operand" "b")
2286             (match_operand:SI 1 "register_operand" "r")
2287             (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTST)]
2288   "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2289   "dstst %0,%1,%2"
2290   [(set_attr "type" "vecsimple")])
2292 (define_insn "altivec_dststt"
2293   [(unspec [(match_operand 0 "register_operand" "b")
2294             (match_operand:SI 1 "register_operand" "r")
2295             (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTSTT)]
2296   "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
2297   "dststt %0,%1,%2"
2298   [(set_attr "type" "vecsimple")])
2300 (define_expand "altivec_lvsl"
2301   [(use (match_operand:V16QI 0 "register_operand" ""))
2302    (use (match_operand:V16QI 1 "memory_operand" ""))]
2303   "TARGET_ALTIVEC"
2305   if (VECTOR_ELT_ORDER_BIG)
2306     emit_insn (gen_altivec_lvsl_direct (operands[0], operands[1]));
2307   else
2308     {
2309       int i;
2310       rtx mask, perm[16], constv, vperm;
2311       mask = gen_reg_rtx (V16QImode);
2312       emit_insn (gen_altivec_lvsl_direct (mask, operands[1]));
2313       for (i = 0; i < 16; ++i)
2314         perm[i] = GEN_INT (i);
2315       constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
2316       constv = force_reg (V16QImode, constv);
2317       vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2318                               UNSPEC_VPERM);
2319       emit_insn (gen_rtx_SET (VOIDmode, operands[0], vperm));
2320     }
2321   DONE;
2324 (define_insn "altivec_lvsl_direct"
2325   [(set (match_operand:V16QI 0 "register_operand" "=v")
2326         (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2327                       UNSPEC_LVSL))]
2328   "TARGET_ALTIVEC"
2329   "lvsl %0,%y1"
2330   [(set_attr "type" "vecload")])
2332 (define_expand "altivec_lvsr"
2333   [(use (match_operand:V16QI 0 "register_operand" ""))
2334    (use (match_operand:V16QI 1 "memory_operand" ""))]
2335   "TARGET_ALTIVEC"
2337   if (VECTOR_ELT_ORDER_BIG)
2338     emit_insn (gen_altivec_lvsr_direct (operands[0], operands[1]));
2339   else
2340     {
2341       int i;
2342       rtx mask, perm[16], constv, vperm;
2343       mask = gen_reg_rtx (V16QImode);
2344       emit_insn (gen_altivec_lvsr_direct (mask, operands[1]));
2345       for (i = 0; i < 16; ++i)
2346         perm[i] = GEN_INT (i);
2347       constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
2348       constv = force_reg (V16QImode, constv);
2349       vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv),
2350                               UNSPEC_VPERM);
2351       emit_insn (gen_rtx_SET (VOIDmode, operands[0], vperm));
2352     }
2353   DONE;
2356 (define_insn "altivec_lvsr_direct"
2357   [(set (match_operand:V16QI 0 "register_operand" "=v")
2358         (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")]
2359                       UNSPEC_LVSR))]
2360   "TARGET_ALTIVEC"
2361   "lvsr %0,%y1"
2362   [(set_attr "type" "vecload")])
2364 (define_expand "build_vector_mask_for_load"
2365   [(set (match_operand:V16QI 0 "register_operand" "")
2366         (unspec:V16QI [(match_operand 1 "memory_operand" "")] UNSPEC_LVSR))]
2367   "TARGET_ALTIVEC"
2368   "
2370   rtx addr;
2371   rtx temp;
2373   gcc_assert (GET_CODE (operands[1]) == MEM);
2375   addr = XEXP (operands[1], 0);
2376   temp = gen_reg_rtx (GET_MODE (addr));
2377   emit_insn (gen_rtx_SET (VOIDmode, temp, 
2378                           gen_rtx_NEG (GET_MODE (addr), addr)));
2379   emit_insn (gen_altivec_lvsr (operands[0], 
2380                                replace_equiv_address (operands[1], temp)));
2381   DONE;
2384 ;; Parallel some of the LVE* and STV*'s with unspecs because some have
2385 ;; identical rtl but different instructions-- and gcc gets confused.
2387 (define_expand "altivec_lve<VI_char>x"
2388   [(parallel
2389     [(set (match_operand:VI 0 "register_operand" "=v")
2390           (match_operand:VI 1 "memory_operand" "Z"))
2391      (unspec [(const_int 0)] UNSPEC_LVE)])]
2392   "TARGET_ALTIVEC"
2394   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2395     {
2396       altivec_expand_lvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_LVE);
2397       DONE;
2398     }
2401 (define_insn "*altivec_lve<VI_char>x_internal"
2402   [(parallel
2403     [(set (match_operand:VI 0 "register_operand" "=v")
2404           (match_operand:VI 1 "memory_operand" "Z"))
2405      (unspec [(const_int 0)] UNSPEC_LVE)])]
2406   "TARGET_ALTIVEC"
2407   "lve<VI_char>x %0,%y1"
2408   [(set_attr "type" "vecload")])
2410 (define_insn "*altivec_lvesfx"
2411   [(parallel
2412     [(set (match_operand:V4SF 0 "register_operand" "=v")
2413           (match_operand:V4SF 1 "memory_operand" "Z"))
2414      (unspec [(const_int 0)] UNSPEC_LVE)])]
2415   "TARGET_ALTIVEC"
2416   "lvewx %0,%y1"
2417   [(set_attr "type" "vecload")])
2419 (define_expand "altivec_lvxl_<mode>"
2420   [(parallel
2421     [(set (match_operand:VM2 0 "register_operand" "=v")
2422           (match_operand:VM2 1 "memory_operand" "Z"))
2423      (unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
2424   "TARGET_ALTIVEC"
2426   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2427     {
2428       altivec_expand_lvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_SET_VSCR);
2429       DONE;
2430     }
2433 (define_insn "*altivec_lvxl_<mode>_internal"
2434   [(parallel
2435     [(set (match_operand:VM2 0 "register_operand" "=v")
2436           (match_operand:VM2 1 "memory_operand" "Z"))
2437      (unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
2438   "TARGET_ALTIVEC"
2439   "lvx %0,%y1"
2440   [(set_attr "type" "vecload")])
2442 (define_expand "altivec_lvx_<mode>"
2443   [(parallel
2444     [(set (match_operand:VM2 0 "register_operand" "=v")
2445           (match_operand:VM2 1 "memory_operand" "Z"))
2446      (unspec [(const_int 0)] UNSPEC_LVX)])]
2447   "TARGET_ALTIVEC"
2449   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2450     {
2451       altivec_expand_lvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_LVX);
2452       DONE;
2453     }
2456 (define_insn "*altivec_lvx_<mode>_internal"
2457   [(parallel
2458     [(set (match_operand:VM2 0 "register_operand" "=v")
2459           (match_operand:VM2 1 "memory_operand" "Z"))
2460      (unspec [(const_int 0)] UNSPEC_LVX)])]
2461   "TARGET_ALTIVEC"
2462   "lvx %0,%y1"
2463   [(set_attr "type" "vecload")])
2465 (define_expand "altivec_stvx_<mode>"
2466   [(parallel
2467     [(set (match_operand:VM2 0 "memory_operand" "=Z")
2468           (match_operand:VM2 1 "register_operand" "v"))
2469      (unspec [(const_int 0)] UNSPEC_STVX)])]
2470   "TARGET_ALTIVEC"
2472   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2473     {
2474       altivec_expand_stvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_STVX);
2475       DONE;
2476     }
2479 (define_insn "*altivec_stvx_<mode>_internal"
2480   [(parallel
2481     [(set (match_operand:VM2 0 "memory_operand" "=Z")
2482           (match_operand:VM2 1 "register_operand" "v"))
2483      (unspec [(const_int 0)] UNSPEC_STVX)])]
2484   "TARGET_ALTIVEC"
2485   "stvx %1,%y0"
2486   [(set_attr "type" "vecstore")])
2488 (define_expand "altivec_stvxl_<mode>"
2489   [(parallel
2490     [(set (match_operand:VM2 0 "memory_operand" "=Z")
2491           (match_operand:VM2 1 "register_operand" "v"))
2492      (unspec [(const_int 0)] UNSPEC_STVXL)])]
2493   "TARGET_ALTIVEC"
2495   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2496     {
2497       altivec_expand_stvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_STVXL);
2498       DONE;
2499     }
2502 (define_insn "*altivec_stvxl_<mode>_internal"
2503   [(parallel
2504     [(set (match_operand:VM2 0 "memory_operand" "=Z")
2505           (match_operand:VM2 1 "register_operand" "v"))
2506      (unspec [(const_int 0)] UNSPEC_STVXL)])]
2507   "TARGET_ALTIVEC"
2508   "stvxl %1,%y0"
2509   [(set_attr "type" "vecstore")])
2511 (define_expand "altivec_stve<VI_char>x"
2512   [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
2513         (unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
2514   "TARGET_ALTIVEC"
2516   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2517     {
2518       altivec_expand_stvex_be (operands[0], operands[1], <MODE>mode, UNSPEC_STVE);
2519       DONE;
2520     }
2523 (define_insn "*altivec_stve<VI_char>x_internal"
2524   [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
2525         (unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
2526   "TARGET_ALTIVEC"
2527   "stve<VI_char>x %1,%y0"
2528   [(set_attr "type" "vecstore")])
2530 (define_insn "*altivec_stvesfx"
2531   [(set (match_operand:SF 0 "memory_operand" "=Z")
2532         (unspec:SF [(match_operand:V4SF 1 "register_operand" "v")] UNSPEC_STVE))]
2533   "TARGET_ALTIVEC"
2534   "stvewx %1,%y0"
2535   [(set_attr "type" "vecstore")])
2537 ;; Generate
2538 ;;    xxlxor/vxor SCRATCH0,SCRATCH0,SCRATCH0
2539 ;;    vsubu?m SCRATCH2,SCRATCH1,%1
2540 ;;    vmaxs? %0,%1,SCRATCH2"
2541 (define_expand "abs<mode>2"
2542   [(set (match_dup 2) (match_dup 3))
2543    (set (match_dup 4)
2544         (minus:VI2 (match_dup 2)
2545                    (match_operand:VI2 1 "register_operand" "v")))
2546    (set (match_operand:VI2 0 "register_operand" "=v")
2547         (smax:VI2 (match_dup 1) (match_dup 4)))]
2548   "<VI_unit>"
2550   int i, n_elt = GET_MODE_NUNITS (<MODE>mode);
2551   rtvec v = rtvec_alloc (n_elt);
2553   /* Create an all 0 constant.  */
2554   for (i = 0; i < n_elt; ++i)
2555     RTVEC_ELT (v, i) = const0_rtx;
2557   operands[2] = gen_reg_rtx (<MODE>mode);
2558   operands[3] = gen_rtx_CONST_VECTOR (<MODE>mode, v);
2559   operands[4] = gen_reg_rtx (<MODE>mode);
2562 ;; Generate
2563 ;;    vspltisw SCRATCH1,-1
2564 ;;    vslw SCRATCH2,SCRATCH1,SCRATCH1
2565 ;;    vandc %0,%1,SCRATCH2
2566 (define_expand "altivec_absv4sf2"
2567   [(set (match_dup 2)
2568         (vec_duplicate:V4SI (const_int -1)))
2569    (set (match_dup 3)
2570         (ashift:V4SI (match_dup 2) (match_dup 2)))
2571    (set (match_operand:V4SF 0 "register_operand" "=v")
2572         (and:V4SF (not:V4SF (subreg:V4SF (match_dup 3) 0))
2573                   (match_operand:V4SF 1 "register_operand" "v")))]
2574   "TARGET_ALTIVEC"
2576   operands[2] = gen_reg_rtx (V4SImode);
2577   operands[3] = gen_reg_rtx (V4SImode);
2580 ;; Generate
2581 ;;    vspltis? SCRATCH0,0
2582 ;;    vsubs?s SCRATCH2,SCRATCH1,%1
2583 ;;    vmaxs? %0,%1,SCRATCH2"
2584 (define_expand "altivec_abss_<mode>"
2585   [(set (match_dup 2) (vec_duplicate:VI (const_int 0)))
2586    (parallel [(set (match_dup 3)
2587                    (unspec:VI [(match_dup 2)
2588                                (match_operand:VI 1 "register_operand" "v")]
2589                               UNSPEC_VSUBS))
2590               (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))])
2591    (set (match_operand:VI 0 "register_operand" "=v")
2592         (smax:VI (match_dup 1) (match_dup 3)))]
2593   "TARGET_ALTIVEC"
2595   operands[2] = gen_reg_rtx (GET_MODE (operands[0]));
2596   operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
2599 (define_expand "reduc_splus_<mode>"
2600   [(set (match_operand:VIshort 0 "register_operand" "=v")
2601         (unspec:VIshort [(match_operand:VIshort 1 "register_operand" "v")]
2602                         UNSPEC_REDUC_PLUS))]
2603   "TARGET_ALTIVEC"
2605   rtx vzero = gen_reg_rtx (V4SImode);
2606   rtx vtmp1 = gen_reg_rtx (V4SImode);
2607   rtx dest = gen_lowpart (V4SImode, operands[0]);
2609   emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
2610   emit_insn (gen_altivec_vsum4s<VI_char>s (vtmp1, operands[1], vzero));
2611   emit_insn (gen_altivec_vsumsws_direct (dest, vtmp1, vzero));
2612   DONE;
2615 (define_expand "reduc_uplus_v16qi"
2616   [(set (match_operand:V16QI 0 "register_operand" "=v")
2617         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
2618                       UNSPEC_REDUC_PLUS))]
2619   "TARGET_ALTIVEC"
2621   rtx vzero = gen_reg_rtx (V4SImode);
2622   rtx vtmp1 = gen_reg_rtx (V4SImode);
2623   rtx dest = gen_lowpart (V4SImode, operands[0]);
2625   emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
2626   emit_insn (gen_altivec_vsum4ubs (vtmp1, operands[1], vzero));
2627   emit_insn (gen_altivec_vsumsws_direct (dest, vtmp1, vzero));
2628   DONE;
2631 (define_expand "neg<mode>2"
2632   [(use (match_operand:VI 0 "register_operand" ""))
2633    (use (match_operand:VI 1 "register_operand" ""))]
2634   "TARGET_ALTIVEC"
2635   "
2637   rtx vzero;
2639   vzero = gen_reg_rtx (GET_MODE (operands[0]));
2640   emit_insn (gen_altivec_vspltis<VI_char> (vzero, const0_rtx));
2641   emit_insn (gen_sub<mode>3 (operands[0], vzero, operands[1])); 
2642   
2643   DONE;
2646 (define_expand "udot_prod<mode>"
2647   [(set (match_operand:V4SI 0 "register_operand" "=v")
2648         (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
2649                    (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")  
2650                                  (match_operand:VIshort 2 "register_operand" "v")] 
2651                                 UNSPEC_VMSUMU)))]
2652   "TARGET_ALTIVEC"
2653   "
2654 {  
2655   emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], operands[2], operands[3]));
2656   DONE;
2658    
2659 (define_expand "sdot_prodv8hi"
2660   [(set (match_operand:V4SI 0 "register_operand" "=v")
2661         (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
2662                    (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
2663                                  (match_operand:V8HI 2 "register_operand" "v")]
2664                                 UNSPEC_VMSUMSHM)))]
2665   "TARGET_ALTIVEC"
2666   "
2668   emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], operands[2], operands[3]));
2669   DONE;
2672 (define_expand "widen_usum<mode>3"
2673   [(set (match_operand:V4SI 0 "register_operand" "=v")
2674         (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
2675                    (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")]
2676                                 UNSPEC_VMSUMU)))]
2677   "TARGET_ALTIVEC"
2678   "
2680   rtx vones = gen_reg_rtx (GET_MODE (operands[1]));
2682   emit_insn (gen_altivec_vspltis<VI_char> (vones, const1_rtx));
2683   emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], vones, operands[2]));
2684   DONE;
2687 (define_expand "widen_ssumv16qi3"
2688   [(set (match_operand:V4SI 0 "register_operand" "=v")
2689         (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
2690                    (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")]
2691                                 UNSPEC_VMSUMM)))]
2692   "TARGET_ALTIVEC"
2693   "
2695   rtx vones = gen_reg_rtx (V16QImode);
2697   emit_insn (gen_altivec_vspltisb (vones, const1_rtx));
2698   emit_insn (gen_altivec_vmsummbm (operands[0], operands[1], vones, operands[2]));
2699   DONE;
2702 (define_expand "widen_ssumv8hi3"
2703   [(set (match_operand:V4SI 0 "register_operand" "=v")
2704         (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
2705                    (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2706                                 UNSPEC_VMSUMSHM)))]
2707   "TARGET_ALTIVEC"
2708   "
2710   rtx vones = gen_reg_rtx (V8HImode);
2712   emit_insn (gen_altivec_vspltish (vones, const1_rtx));
2713   emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], vones, operands[2]));
2714   DONE;
2717 (define_expand "vec_unpacks_hi_<VP_small_lc>"
2718   [(set (match_operand:VP 0 "register_operand" "=v")
2719         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2720                    UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
2721   "<VI_unit>"
2722   "")
2724 (define_expand "vec_unpacks_lo_<VP_small_lc>"
2725   [(set (match_operand:VP 0 "register_operand" "=v")
2726         (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
2727                    UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
2728   "<VI_unit>"
2729   "")
2731 (define_insn "vperm_v8hiv4si"
2732   [(set (match_operand:V4SI 0 "register_operand" "=v")
2733         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
2734                    (match_operand:V4SI 2 "register_operand" "v")
2735                    (match_operand:V16QI 3 "register_operand" "v")]
2736                   UNSPEC_VPERMSI))]
2737   "TARGET_ALTIVEC"
2738   "vperm %0,%1,%2,%3"
2739   [(set_attr "type" "vecperm")])
2741 (define_insn "vperm_v16qiv8hi"
2742   [(set (match_operand:V8HI 0 "register_operand" "=v")
2743         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
2744                    (match_operand:V8HI 2 "register_operand" "v")
2745                    (match_operand:V16QI 3 "register_operand" "v")]
2746                   UNSPEC_VPERMHI))]
2747   "TARGET_ALTIVEC"
2748   "vperm %0,%1,%2,%3"
2749   [(set_attr "type" "vecperm")])
2752 (define_expand "vec_unpacku_hi_v16qi"
2753   [(set (match_operand:V8HI 0 "register_operand" "=v")
2754         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
2755                      UNSPEC_VUPKHUB))]
2756   "TARGET_ALTIVEC"      
2757   "
2758 {  
2759   rtx vzero = gen_reg_rtx (V8HImode);
2760   rtx mask = gen_reg_rtx (V16QImode);
2761   rtvec v = rtvec_alloc (16);
2762   bool be = BYTES_BIG_ENDIAN;
2763    
2764   emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
2765    
2766   RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
2767   RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  0 : 16);
2768   RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 :  6);
2769   RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
2770   RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
2771   RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ?  2 : 16);
2772   RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 :  4);
2773   RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
2774   RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
2775   RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ?  4 : 16);
2776   RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 :  2);
2777   RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
2778   RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
2779   RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ?  6 : 16);
2780   RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  0);
2781   RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
2783   emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
2784   emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
2785   DONE;
2788 (define_expand "vec_unpacku_hi_v8hi"
2789   [(set (match_operand:V4SI 0 "register_operand" "=v")
2790         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2791                      UNSPEC_VUPKHUH))]
2792   "TARGET_ALTIVEC"
2793   "
2795   rtx vzero = gen_reg_rtx (V4SImode);
2796   rtx mask = gen_reg_rtx (V16QImode);
2797   rtvec v = rtvec_alloc (16);
2798   bool be = BYTES_BIG_ENDIAN;
2800   emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
2802   RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 :  7);
2803   RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 :  6);
2804   RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  0 : 17);
2805   RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  1 : 16);
2806   RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 :  5);
2807   RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 :  4);
2808   RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ?  2 : 17);
2809   RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ?  3 : 16);
2810   RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 :  3);
2811   RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 :  2);
2812   RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ?  4 : 17);
2813   RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ?  5 : 16);
2814   RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  1);
2815   RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  0);
2816   RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ?  6 : 17);
2817   RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ?  7 : 16);
2819   emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
2820   emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
2821   DONE;
2824 (define_expand "vec_unpacku_lo_v16qi"
2825   [(set (match_operand:V8HI 0 "register_operand" "=v")
2826         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
2827                      UNSPEC_VUPKLUB))]
2828   "TARGET_ALTIVEC"
2829   "
2831   rtx vzero = gen_reg_rtx (V8HImode);
2832   rtx mask = gen_reg_rtx (V16QImode);
2833   rtvec v = rtvec_alloc (16);
2834   bool be = BYTES_BIG_ENDIAN;
2836   emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
2838   RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
2839   RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ?  8 : 16);
2840   RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14);
2841   RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
2842   RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
2843   RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16);
2844   RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12);
2845   RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
2846   RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
2847   RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16);
2848   RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10);
2849   RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
2850   RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
2851   RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16);
2852   RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 :  8);
2853   RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
2855   emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
2856   emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
2857   DONE;
2860 (define_expand "vec_unpacku_lo_v8hi"
2861   [(set (match_operand:V4SI 0 "register_operand" "=v")
2862         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
2863                      UNSPEC_VUPKLUH))]
2864   "TARGET_ALTIVEC"
2865   "
2867   rtx vzero = gen_reg_rtx (V4SImode);
2868   rtx mask = gen_reg_rtx (V16QImode);
2869   rtvec v = rtvec_alloc (16);
2870   bool be = BYTES_BIG_ENDIAN;
2872   emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
2874   RTVEC_ELT (v,  0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
2875   RTVEC_ELT (v,  1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14);
2876   RTVEC_ELT (v,  2) = gen_rtx_CONST_INT (QImode, be ?  8 : 17);
2877   RTVEC_ELT (v,  3) = gen_rtx_CONST_INT (QImode, be ?  9 : 16);
2878   RTVEC_ELT (v,  4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
2879   RTVEC_ELT (v,  5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12);
2880   RTVEC_ELT (v,  6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17);
2881   RTVEC_ELT (v,  7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
2882   RTVEC_ELT (v,  8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
2883   RTVEC_ELT (v,  9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10);
2884   RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17);
2885   RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
2886   RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 :  9);
2887   RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 :  8);
2888   RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17);
2889   RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
2891   emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
2892   emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
2893   DONE;
2896 (define_expand "vec_widen_umult_hi_v16qi"
2897   [(set (match_operand:V8HI 0 "register_operand" "=v")
2898         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
2899                       (match_operand:V16QI 2 "register_operand" "v")]
2900                      UNSPEC_VMULWHUB))]
2901   "TARGET_ALTIVEC"
2902   "
2904   rtx ve = gen_reg_rtx (V8HImode);
2905   rtx vo = gen_reg_rtx (V8HImode);
2906   
2907   if (BYTES_BIG_ENDIAN)
2908     {
2909       emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
2910       emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
2911       emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
2912     }
2913   else
2914     {
2915       emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
2916       emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
2917       emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
2918     }
2919   DONE;
2922 (define_expand "vec_widen_umult_lo_v16qi"
2923   [(set (match_operand:V8HI 0 "register_operand" "=v")
2924         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
2925                       (match_operand:V16QI 2 "register_operand" "v")]
2926                      UNSPEC_VMULWLUB))]
2927   "TARGET_ALTIVEC"
2928   "
2930   rtx ve = gen_reg_rtx (V8HImode);
2931   rtx vo = gen_reg_rtx (V8HImode);
2932   
2933   if (BYTES_BIG_ENDIAN)
2934     {
2935       emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
2936       emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
2937       emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
2938     }
2939   else
2940     {
2941       emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
2942       emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
2943       emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
2944     }
2945   DONE;
2948 (define_expand "vec_widen_smult_hi_v16qi"
2949   [(set (match_operand:V8HI 0 "register_operand" "=v")
2950         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
2951                       (match_operand:V16QI 2 "register_operand" "v")]
2952                      UNSPEC_VMULWHSB))]
2953   "TARGET_ALTIVEC"
2954   "
2956   rtx ve = gen_reg_rtx (V8HImode);
2957   rtx vo = gen_reg_rtx (V8HImode);
2958   
2959   if (BYTES_BIG_ENDIAN)
2960     {
2961       emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
2962       emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
2963       emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
2964     }
2965   else
2966     {
2967       emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
2968       emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
2969       emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
2970     }
2971   DONE;
2974 (define_expand "vec_widen_smult_lo_v16qi"
2975   [(set (match_operand:V8HI 0 "register_operand" "=v")
2976         (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
2977                       (match_operand:V16QI 2 "register_operand" "v")]
2978                      UNSPEC_VMULWLSB))]
2979   "TARGET_ALTIVEC"
2980   "
2982   rtx ve = gen_reg_rtx (V8HImode);
2983   rtx vo = gen_reg_rtx (V8HImode);
2984   
2985   if (BYTES_BIG_ENDIAN)
2986     {
2987       emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
2988       emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
2989       emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
2990     }
2991   else
2992     {
2993       emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
2994       emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
2995       emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
2996     }
2997   DONE;
3000 (define_expand "vec_widen_umult_hi_v8hi"
3001   [(set (match_operand:V4SI 0 "register_operand" "=v")
3002         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3003                       (match_operand:V8HI 2 "register_operand" "v")]
3004                      UNSPEC_VMULWHUH))]
3005   "TARGET_ALTIVEC"
3006   "
3008   rtx ve = gen_reg_rtx (V4SImode);
3009   rtx vo = gen_reg_rtx (V4SImode);
3010   
3011   if (BYTES_BIG_ENDIAN)
3012     {
3013       emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3014       emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3015       emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3016     }
3017   else
3018     {
3019       emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3020       emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3021       emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3022     }
3023   DONE;
3026 (define_expand "vec_widen_umult_lo_v8hi"
3027   [(set (match_operand:V4SI 0 "register_operand" "=v")
3028         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3029                       (match_operand:V8HI 2 "register_operand" "v")]
3030                      UNSPEC_VMULWLUH))]
3031   "TARGET_ALTIVEC"
3032   "
3034   rtx ve = gen_reg_rtx (V4SImode);
3035   rtx vo = gen_reg_rtx (V4SImode);
3036   
3037   if (BYTES_BIG_ENDIAN)
3038     {
3039       emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
3040       emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
3041       emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3042     }
3043   else
3044     {
3045       emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
3046       emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
3047       emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3048     }
3049   DONE;
3052 (define_expand "vec_widen_smult_hi_v8hi"
3053   [(set (match_operand:V4SI 0 "register_operand" "=v")
3054         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3055                       (match_operand:V8HI 2 "register_operand" "v")]
3056                      UNSPEC_VMULWHSH))]
3057   "TARGET_ALTIVEC"
3058   "
3060   rtx ve = gen_reg_rtx (V4SImode);
3061   rtx vo = gen_reg_rtx (V4SImode);
3062   
3063   if (BYTES_BIG_ENDIAN)
3064     {
3065       emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3066       emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3067       emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
3068     }
3069   else
3070     {
3071       emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3072       emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3073       emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
3074     }
3075   DONE;
3078 (define_expand "vec_widen_smult_lo_v8hi"
3079   [(set (match_operand:V4SI 0 "register_operand" "=v")
3080         (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
3081                       (match_operand:V8HI 2 "register_operand" "v")]
3082                      UNSPEC_VMULWLSH))]
3083   "TARGET_ALTIVEC"
3084   "
3086   rtx ve = gen_reg_rtx (V4SImode);
3087   rtx vo = gen_reg_rtx (V4SImode);
3088   
3089   if (BYTES_BIG_ENDIAN)
3090     {
3091       emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
3092       emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
3093       emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
3094     }
3095   else
3096     {
3097       emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
3098       emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
3099       emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
3100     }
3101   DONE;
3104 (define_expand "vec_pack_trunc_<mode>"
3105   [(set (match_operand:<VP_small> 0 "register_operand" "=v")
3106         (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
3107                             (match_operand:VP 2 "register_operand" "v")]
3108                       UNSPEC_VPACK_UNS_UNS_MOD))]
3109   "<VI_unit>"
3110   "")
3112 (define_expand "altivec_negv4sf2"
3113   [(use (match_operand:V4SF 0 "register_operand" ""))
3114    (use (match_operand:V4SF 1 "register_operand" ""))]
3115   "TARGET_ALTIVEC"
3116   "
3118   rtx neg0;
3120   /* Generate [-0.0, -0.0, -0.0, -0.0].  */
3121   neg0 = gen_reg_rtx (V4SImode);
3122   emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
3123   emit_insn (gen_vashlv4si3 (neg0, neg0, neg0));
3125   /* XOR */
3126   emit_insn (gen_xorv4sf3 (operands[0],
3127                            gen_lowpart (V4SFmode, neg0), operands[1])); 
3128     
3129   DONE;
3132 ;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL,
3133 ;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell.
3134 (define_insn "altivec_lvlx"
3135   [(set (match_operand:V16QI 0 "register_operand" "=v")
3136         (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3137                       UNSPEC_LVLX))]
3138   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3139   "lvlx %0,%y1"
3140   [(set_attr "type" "vecload")])
3142 (define_insn "altivec_lvlxl"
3143   [(set (match_operand:V16QI 0 "register_operand" "=v")
3144         (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3145                       UNSPEC_LVLXL))]
3146   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3147   "lvlxl %0,%y1"
3148   [(set_attr "type" "vecload")])
3150 (define_insn "altivec_lvrx"
3151   [(set (match_operand:V16QI 0 "register_operand" "=v")
3152         (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3153                       UNSPEC_LVRX))]
3154   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3155   "lvrx %0,%y1"
3156   [(set_attr "type" "vecload")])
3158 (define_insn "altivec_lvrxl"
3159   [(set (match_operand:V16QI 0 "register_operand" "=v")
3160         (unspec:V16QI [(match_operand:BLK 1 "memory_operand" "Z")]
3161                       UNSPEC_LVRXL))]
3162   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3163   "lvrxl %0,%y1"
3164   [(set_attr "type" "vecload")])
3166 (define_insn "altivec_stvlx"
3167   [(parallel
3168     [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3169           (match_operand:V16QI 1 "register_operand" "v"))
3170      (unspec [(const_int 0)] UNSPEC_STVLX)])]
3171   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3172   "stvlx %1,%y0"
3173   [(set_attr "type" "vecstore")])
3175 (define_insn "altivec_stvlxl"
3176   [(parallel
3177     [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3178           (match_operand:V16QI 1 "register_operand" "v"))
3179      (unspec [(const_int 0)] UNSPEC_STVLXL)])]
3180   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3181   "stvlxl %1,%y0"
3182   [(set_attr "type" "vecstore")])
3184 (define_insn "altivec_stvrx"
3185   [(parallel
3186     [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3187           (match_operand:V16QI 1 "register_operand" "v"))
3188      (unspec [(const_int 0)] UNSPEC_STVRX)])]
3189   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3190   "stvrx %1,%y0"
3191   [(set_attr "type" "vecstore")])
3193 (define_insn "altivec_stvrxl"
3194   [(parallel
3195     [(set (match_operand:V16QI 0 "memory_operand" "=Z")
3196           (match_operand:V16QI 1 "register_operand" "v"))
3197      (unspec [(const_int 0)] UNSPEC_STVRXL)])]
3198   "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
3199   "stvrxl %1,%y0"
3200   [(set_attr "type" "vecstore")])
3202 (define_expand "vec_unpacks_float_hi_v8hi"
3203  [(set (match_operand:V4SF 0 "register_operand" "")
3204         (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "")]
3205                      UNSPEC_VUPKHS_V4SF))]
3206   "TARGET_ALTIVEC"
3207   "
3209   rtx tmp = gen_reg_rtx (V4SImode);
3211   emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
3212   emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3213   DONE;
3216 (define_expand "vec_unpacks_float_lo_v8hi"
3217  [(set (match_operand:V4SF 0 "register_operand" "")
3218         (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "")]
3219                      UNSPEC_VUPKLS_V4SF))]
3220   "TARGET_ALTIVEC"
3221   "
3223   rtx tmp = gen_reg_rtx (V4SImode);
3225   emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
3226   emit_insn (gen_altivec_vcfsx (operands[0], tmp, const0_rtx));
3227   DONE;
3230 (define_expand "vec_unpacku_float_hi_v8hi"
3231  [(set (match_operand:V4SF 0 "register_operand" "")
3232         (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "")]
3233                      UNSPEC_VUPKHU_V4SF))]
3234   "TARGET_ALTIVEC"
3235   "
3237   rtx tmp = gen_reg_rtx (V4SImode);
3239   emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
3240   emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3241   DONE;
3244 (define_expand "vec_unpacku_float_lo_v8hi"
3245  [(set (match_operand:V4SF 0 "register_operand" "")
3246         (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "")]
3247                      UNSPEC_VUPKLU_V4SF))]
3248   "TARGET_ALTIVEC"
3249   "
3251   rtx tmp = gen_reg_rtx (V4SImode);
3253   emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
3254   emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
3255   DONE;
3259 ;; Power8 vector instructions encoded as Altivec instructions
3261 ;; Vector count leading zeros
3262 (define_insn "*p8v_clz<mode>2"
3263   [(set (match_operand:VI2 0 "register_operand" "=v")
3264         (clz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3265   "TARGET_P8_VECTOR"
3266   "vclz<wd> %0,%1"
3267   [(set_attr "length" "4")
3268    (set_attr "type" "vecsimple")])
3270 ;; Vector population count
3271 (define_insn "*p8v_popcount<mode>2"
3272   [(set (match_operand:VI2 0 "register_operand" "=v")
3273         (popcount:VI2 (match_operand:VI2 1 "register_operand" "v")))]
3274   "TARGET_P8_VECTOR"
3275   "vpopcnt<wd> %0,%1"
3276   [(set_attr "length" "4")
3277    (set_attr "type" "vecsimple")])
3279 ;; Vector Gather Bits by Bytes by Doubleword
3280 (define_insn "p8v_vgbbd"
3281   [(set (match_operand:V16QI 0 "register_operand" "=v")
3282         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
3283                       UNSPEC_VGBBD))]
3284   "TARGET_P8_VECTOR"
3285   "vgbbd %0,%1"
3286   [(set_attr "length" "4")
3287    (set_attr "type" "vecsimple")])
3290 ;; 128-bit binary integer arithmetic
3291 ;; We have a special container type (V1TImode) to allow operations using the
3292 ;; ISA 2.07 128-bit binary support to target the VMX/altivec registers without
3293 ;; having to worry about the register allocator deciding GPRs are better.
3295 (define_insn "altivec_vadduqm"
3296   [(set (match_operand:V1TI 0 "register_operand" "=v")
3297         (plus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3298                    (match_operand:V1TI 2 "register_operand" "v")))]
3299   "TARGET_VADDUQM"
3300   "vadduqm %0,%1,%2"
3301   [(set_attr "length" "4")
3302    (set_attr "type" "vecsimple")])
3304 (define_insn "altivec_vaddcuq"
3305   [(set (match_operand:V1TI 0 "register_operand" "=v")
3306         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3307                       (match_operand:V1TI 2 "register_operand" "v")]
3308                      UNSPEC_VADDCUQ))]
3309   "TARGET_VADDUQM"
3310   "vaddcuq %0,%1,%2"
3311   [(set_attr "length" "4")
3312    (set_attr "type" "vecsimple")])
3314 (define_insn "altivec_vsubuqm"
3315   [(set (match_operand:V1TI 0 "register_operand" "=v")
3316         (minus:V1TI (match_operand:V1TI 1 "register_operand" "v")
3317                     (match_operand:V1TI 2 "register_operand" "v")))]
3318   "TARGET_VADDUQM"
3319   "vsubuqm %0,%1,%2"
3320   [(set_attr "length" "4")
3321    (set_attr "type" "vecsimple")])
3323 (define_insn "altivec_vsubcuq"
3324   [(set (match_operand:V1TI 0 "register_operand" "=v")
3325         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3326                       (match_operand:V1TI 2 "register_operand" "v")]
3327                      UNSPEC_VSUBCUQ))]
3328   "TARGET_VADDUQM"
3329   "vsubcuq %0,%1,%2"
3330   [(set_attr "length" "4")
3331    (set_attr "type" "vecsimple")])
3333 (define_insn "altivec_vaddeuqm"
3334   [(set (match_operand:V1TI 0 "register_operand" "=v")
3335         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3336                       (match_operand:V1TI 2 "register_operand" "v")
3337                       (match_operand:V1TI 3 "register_operand" "v")]
3338                      UNSPEC_VADDEUQM))]
3339   "TARGET_VADDUQM"
3340   "vaddeuqm %0,%1,%2,%3"
3341   [(set_attr "length" "4")
3342    (set_attr "type" "vecsimple")])
3344 (define_insn "altivec_vaddecuq"
3345   [(set (match_operand:V1TI 0 "register_operand" "=v")
3346         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3347                       (match_operand:V1TI 2 "register_operand" "v")
3348                       (match_operand:V1TI 3 "register_operand" "v")]
3349                      UNSPEC_VADDECUQ))]
3350   "TARGET_VADDUQM"
3351   "vaddecuq %0,%1,%2,%3"
3352   [(set_attr "length" "4")
3353    (set_attr "type" "vecsimple")])
3355 (define_insn "altivec_vsubeuqm"
3356   [(set (match_operand:V1TI 0 "register_operand" "=v")
3357         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3358                       (match_operand:V1TI 2 "register_operand" "v")
3359                       (match_operand:V1TI 3 "register_operand" "v")]
3360                    UNSPEC_VSUBEUQM))]
3361   "TARGET_VADDUQM"
3362   "vsubeuqm %0,%1,%2,%3"
3363   [(set_attr "length" "4")
3364    (set_attr "type" "vecsimple")])
3366 (define_insn "altivec_vsubecuq"
3367   [(set (match_operand:V1TI 0 "register_operand" "=v")
3368         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3369                       (match_operand:V1TI 2 "register_operand" "v")
3370                       (match_operand:V1TI 3 "register_operand" "v")]
3371                      UNSPEC_VSUBECUQ))]
3372   "TARGET_VADDUQM"
3373   "vsubecuq %0,%1,%2,%3"
3374   [(set_attr "length" "4")
3375    (set_attr "type" "vecsimple")])
3377 ;; We use V2DI as the output type to simplify converting the permute
3378 ;; bits into an integer
3379 (define_insn "altivec_vbpermq"
3380   [(set (match_operand:V2DI 0 "register_operand" "=v")
3381         (unspec:V2DI [(match_operand:V16QI 1 "register_operand" "v")
3382                       (match_operand:V16QI 2 "register_operand" "v")]
3383                      UNSPEC_VBPERMQ))]
3384   "TARGET_P8_VECTOR"
3385   "vbpermq %0,%1,%2"
3386   [(set_attr "length" "4")
3387    (set_attr "type" "vecsimple")])
3389 ;; Decimal Integer operations
3390 (define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB])
3392 (define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
3393                               (UNSPEC_BCDSUB "sub")])
3395 (define_code_iterator BCD_TEST [eq lt gt unordered])
3397 (define_insn "bcd<bcd_add_sub>"
3398   [(set (match_operand:V1TI 0 "register_operand" "")
3399         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
3400                       (match_operand:V1TI 2 "register_operand" "")
3401                       (match_operand:QI 3 "const_0_to_1_operand" "")]
3402                      UNSPEC_BCD_ADD_SUB))
3403    (clobber (reg:CCFP 74))]
3404   "TARGET_P8_VECTOR"
3405   "bcd<bcd_add_sub>. %0,%1,%2,%3"
3406   [(set_attr "length" "4")
3407    (set_attr "type" "vecsimple")])
3409 ;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
3410 ;; can use the unordered test for BCD nans and add/subtracts that overflow.  An
3411 ;; UNORDERED test on an integer type (like V1TImode) is not defined.  The type
3412 ;; probably should be one that can go in the VMX (Altivec) registers, so we
3413 ;; can't use DDmode or DFmode.
3414 (define_insn "*bcd<bcd_add_sub>_test"
3415   [(set (reg:CCFP 74)
3416         (compare:CCFP
3417          (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
3418                        (match_operand:V1TI 2 "register_operand" "v")
3419                        (match_operand:QI 3 "const_0_to_1_operand" "i")]
3420                       UNSPEC_BCD_ADD_SUB)
3421          (match_operand:V2DF 4 "zero_constant" "j")))
3422    (clobber (match_scratch:V1TI 0 "=v"))]
3423   "TARGET_P8_VECTOR"
3424   "bcd<bcd_add_sub>. %0,%1,%2,%3"
3425   [(set_attr "length" "4")
3426    (set_attr "type" "vecsimple")])
3428 (define_insn "*bcd<bcd_add_sub>_test2"
3429   [(set (match_operand:V1TI 0 "register_operand" "=v")
3430         (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
3431                       (match_operand:V1TI 2 "register_operand" "v")
3432                       (match_operand:QI 3 "const_0_to_1_operand" "i")]
3433                      UNSPEC_BCD_ADD_SUB))
3434    (set (reg:CCFP 74)
3435         (compare:CCFP
3436          (unspec:V2DF [(match_dup 1)
3437                        (match_dup 2)
3438                        (match_dup 3)]
3439                       UNSPEC_BCD_ADD_SUB)
3440          (match_operand:V2DF 4 "zero_constant" "j")))]
3441   "TARGET_P8_VECTOR"
3442   "bcd<bcd_add_sub>. %0,%1,%2,%3"
3443   [(set_attr "length" "4")
3444    (set_attr "type" "vecsimple")])
3446 (define_expand "bcd<bcd_add_sub>_<code>"
3447   [(parallel [(set (reg:CCFP 74)
3448                    (compare:CCFP
3449                     (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "")
3450                                   (match_operand:V1TI 2 "register_operand" "")
3451                                   (match_operand:QI 3 "const_0_to_1_operand" "")]
3452                                  UNSPEC_BCD_ADD_SUB)
3453                     (match_dup 4)))
3454               (clobber (match_scratch:V1TI 5 ""))])
3455    (set (match_operand:SI 0 "register_operand" "")
3456         (BCD_TEST:SI (reg:CCFP 74)
3457                      (const_int 0)))]
3458   "TARGET_P8_VECTOR"
3460   operands[4] = CONST0_RTX (V2DFmode);
3463 ;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
3464 ;; the bcdadd/bcdsub that tests the value.  The combiner won't work since
3465 ;; CR6 is a hard coded register.  Unfortunately, all of the Altivec predicate
3466 ;; support is hard coded to use the fixed register CR6 instead of creating
3467 ;; a register class for CR6.
3469 (define_peephole2
3470   [(parallel [(set (match_operand:V1TI 0 "register_operand" "")
3471                    (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
3472                                  (match_operand:V1TI 2 "register_operand" "")
3473                                  (match_operand:QI 3 "const_0_to_1_operand" "")]
3474                                 UNSPEC_BCD_ADD_SUB))
3475               (clobber (reg:CCFP 74))])
3476    (parallel [(set (reg:CCFP 74)
3477                    (compare:CCFP
3478                     (unspec:V2DF [(match_dup 1)
3479                                   (match_dup 2)
3480                                   (match_dup 3)]
3481                                  UNSPEC_BCD_ADD_SUB)
3482                     (match_operand:V2DF 4 "zero_constant" "")))
3483               (clobber (match_operand:V1TI 5 "register_operand" ""))])]
3484   "TARGET_P8_VECTOR"
3485   [(parallel [(set (match_dup 0)
3486                    (unspec:V1TI [(match_dup 1)
3487                                  (match_dup 2)
3488                                  (match_dup 3)]
3489                                 UNSPEC_BCD_ADD_SUB))
3490               (set (reg:CCFP 74)
3491                    (compare:CCFP
3492                     (unspec:V2DF [(match_dup 1)
3493                                   (match_dup 2)
3494                                   (match_dup 3)]
3495                                  UNSPEC_BCD_ADD_SUB)
3496                     (match_dup 4)))])])