1;;- Instruction patterns for the System z vector facility builtins.
2;;  Copyright (C) 2015-2020 Free Software Foundation, Inc.
3;;  Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify it under
8;; the terms of the GNU General Public License as published by the Free
9;; Software Foundation; either version 3, or (at your option) any later
10;; version.
11
12;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
14;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15;; for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21; The patterns in this file are enabled with -mzvector
22
23(define_mode_iterator V_HW_32_64 [V4SI V2DI V2DF (V4SF "TARGET_VXE")])
24(define_mode_iterator VI_HW_SD [V4SI V2DI])
25(define_mode_iterator V_HW_4 [V4SI V4SF])
26; Full size vector modes with more than one element which are directly supported in vector registers by the hardware.
27(define_mode_iterator VEC_HW  [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE")])
28(define_mode_iterator VECF_HW [(V4SF "TARGET_VXE") V2DF])
29
30; The element type of the vector with floating point modes translated
31; to int modes of the same size.
32(define_mode_attr non_vec_int[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
33			      (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
34			      (V1SI "SI") (V2SI "SI") (V4SI "SI")
35			      (V1DI "DI") (V2DI "DI")
36			      (V1SF "SI") (V2SF "SI") (V4SF "SI")
37			      (V1DF "DI") (V2DF "DI")])
38
39; Condition code modes generated by int comparisons
40(define_mode_iterator VICMP [CCVEQ CCVIH CCVIHU])
41
42; Comparisons supported by the vec_cmp* builtins
43(define_code_iterator intcmp [eq gt gtu ge geu lt ltu le leu])
44(define_code_iterator fpcmp  [eq gt ge lt le])
45
46; Comparisons supported by the vec_all/any* builtins
47(define_code_iterator intcmpcc [eq ne gt ge lt le gtu geu ltu leu])
48(define_code_iterator fpcmpcc  [eq ne gt ge unle unlt lt le])
49
50; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4)
51(define_constants
52  [(VSTRING_FLAG_IN         8)   ; invert result
53   (VSTRING_FLAG_RT         4)   ; result type
54   (VSTRING_FLAG_ZS         2)   ; zero search
55   (VSTRING_FLAG_CS         1)]) ; condition code set
56
57; Rounding modes as being used for e.g. VFI
58(define_constants
59  [(VEC_RND_CURRENT                0)
60   (VEC_RND_NEAREST_AWAY_FROM_ZERO 1)
61   (VEC_RND_SHORT_PREC             3)
62   (VEC_RND_NEAREST_TO_EVEN        4)
63   (VEC_RND_TO_ZERO                5)
64   (VEC_RND_TO_INF                 6)
65   (VEC_RND_TO_MINF                7)])
66
67; Inexact suppression facility flag as being used for e.g. VFI
68(define_constants
69  [(VEC_INEXACT                0)
70   (VEC_NOINEXACT              4)])
71
72
73; Vector gather element
74
75; vgef, vgeg
76(define_insn "vec_gather_element<mode>"
77  [(set (match_operand:V_HW_32_64                     0 "register_operand"  "=v")
78	(unspec:V_HW_32_64 [(match_operand:V_HW_32_64 1 "register_operand"   "0")
79			    (match_operand:<tointvec> 2 "register_operand"   "v")
80			    (match_operand:BLK        3 "memory_operand"     "R")
81			    (match_operand:QI         4 "const_mask_operand" "C")]
82			   UNSPEC_VEC_GATHER))]
83  "TARGET_VX && UINTVAL (operands[4]) < GET_MODE_NUNITS (<V_HW_32_64:MODE>mode)"
84  "vge<bhfgq>\t%0,%O3(%v2,%R3),%b4"
85  [(set_attr "op_type" "VRV")])
86
87(define_expand "vec_genmask<mode>"
88  [(match_operand:VI_HW 0 "register_operand" "=v")
89   (match_operand:QI    1 "const_int_operand" "C")
90   (match_operand:QI    2 "const_int_operand" "C")]
91  "TARGET_VX"
92{
93  int bitlen = GET_MODE_UNIT_BITSIZE (<VI_HW:MODE>mode);
94  /* To bit little endian style.  */
95  int end = bitlen - 1 - INTVAL (operands[1]);
96  int start = bitlen - 1 - INTVAL (operands[2]);
97  int i;
98  unsigned HOST_WIDE_INT mask;
99  bool swapped_p = false;
100
101  if (start > end)
102    {
103      i = start - 1; start = end + 1; end = i;
104      swapped_p = true;
105    }
106  if (end == 63)
107    mask = HOST_WIDE_INT_M1U;
108  else
109    mask = (HOST_WIDE_INT_1U << (end + 1)) - 1;
110
111  mask &= ~((HOST_WIDE_INT_1U << start) - 1);
112
113  if (swapped_p)
114    mask = ~mask;
115
116  rtx mask_rtx = gen_int_mode (mask, GET_MODE_INNER (<VI_HW:MODE>mode));
117
118  emit_insn (gen_rtx_SET (operands[0],
119			  gen_const_vec_duplicate (<VI_HW:MODE>mode,
120						   mask_rtx)));
121  DONE;
122})
123
124(define_expand "vec_genbytemaskv16qi"
125  [(match_operand:V16QI 0 "register_operand"  "")
126   (match_operand:HI    1 "const_int_operand" "")]
127  "TARGET_VX"
128{
129  int i;
130  unsigned mask = 0x8000;
131  rtx const_vec[16];
132  unsigned HOST_WIDE_INT byte_mask = UINTVAL (operands[1]);
133
134  for (i = 0; i < 16; i++)
135    {
136      if (mask & byte_mask)
137	const_vec[i] = constm1_rtx;
138      else
139	const_vec[i] = const0_rtx;
140      mask = mask >> 1;
141    }
142  emit_insn (gen_rtx_SET (operands[0],
143			  gen_rtx_CONST_VECTOR (V16QImode,
144						gen_rtvec_v (16, const_vec))));
145  DONE;
146})
147
148(define_expand "vec_splats<mode>"
149  [(set (match_operand:VEC_HW                          0 "register_operand" "")
150	(vec_duplicate:VEC_HW (match_operand:<non_vec> 1 "general_operand"  "")))]
151  "TARGET_VX")
152
153(define_expand "vec_insert<mode>"
154  [(set (match_operand:VEC_HW                    0 "register_operand" "")
155	(unspec:VEC_HW [(match_operand:<non_vec> 2 "register_operand" "")
156			(match_operand:SI        3 "nonmemory_operand" "")
157			(match_operand:VEC_HW    1 "register_operand" "")]
158		       UNSPEC_VEC_SET))]
159  "TARGET_VX"
160  "")
161
162; This is vec_set + modulo arithmetic on the element selector (op 2)
163(define_expand "vec_promote<mode>"
164  [(set (match_operand:VEC_HW                    0 "register_operand" "")
165	(unspec:VEC_HW [(match_operand:<non_vec> 1 "register_operand" "")
166			(match_operand:SI        2 "nonmemory_operand" "")
167			(match_dup 0)]
168		       UNSPEC_VEC_SET))]
169  "TARGET_VX"
170  "")
171
172; vec_extract is also an RTL standard name -> vector.md
173
174; vllezb, vllezh, vllezf, vllezg
175(define_insn "vec_insert_and_zero<mode>"
176  [(set (match_operand:VEC_HW                    0 "register_operand" "=v")
177	(unspec:VEC_HW [(match_operand:<non_vec> 1 "memory_operand"    "R")]
178		       UNSPEC_VEC_INSERT_AND_ZERO))]
179  "TARGET_VX"
180  "vllez<bhfgq>\t%v0,%1"
181  [(set_attr "op_type" "VRX")])
182
183; vec_revb (vec_insert_and_zero(x))             bswap-and-replicate-1.c
184; vllebrzh, vllebrzf, vllebrzg
185(define_insn "*vec_insert_and_zero_bswap<mode>"
186  [(set (match_operand:V_HW_HSD                    0 "register_operand"       "=v")
187	(bswap:V_HW_HSD (unspec:V_HW_HSD
188			 [(match_operand:<non_vec> 1 "memory_operand"          "R")]
189			 UNSPEC_VEC_INSERT_AND_ZERO)))
190   (use (match_operand:V16QI                       2 "permute_pattern_operand" "X"))]
191  "TARGET_VXE2"
192  "vllebrz<bhfgq>\t%v0,%1"
193  [(set_attr "op_type" "VRX")])
194
195
196(define_insn "vlbb"
197  [(set (match_operand:V16QI              0 "register_operand"   "=v")
198	(unspec:V16QI [(match_operand:BLK 1 "memory_operand"      "R")
199		       (match_operand:QI  2 "const_mask_operand"  "C")]
200		      UNSPEC_VEC_LOAD_BNDRY))]
201  "TARGET_VX && UINTVAL (operands[2]) < 7"
202  "vlbb\t%v0,%1,%2"
203  [(set_attr "op_type" "VRX")])
204
205; Vector load rightmost with length
206
207(define_expand "vlrlrv16qi"
208  [(set (match_operand:V16QI              0 "register_operand"  "")
209	(unspec:V16QI [(match_operand:BLK 2 "memory_operand"    "")
210		       (match_operand:SI  1 "nonmemory_operand" "")]
211		      UNSPEC_VEC_LOAD_LEN_R))]
212  "TARGET_VXE"
213{
214  /* vlrlr sets all length values beyond 15 to 15.  Emulate the same
215     behavior for immediate length operands.  vlrl would trigger a
216     SIGILL for too large immediate operands.  */
217  if (CONST_INT_P (operands[1])
218      && (UINTVAL (operands[1]) & 0xffffffff) > 15)
219    operands[1] = GEN_INT (15);
220})
221
222(define_insn "*vlrlrv16qi"
223  [(set (match_operand:V16QI              0 "register_operand"  "=v,  v,  v")
224	(unspec:V16QI [(match_operand:BLK 2 "memory_operand"     "Q,  R,  Q")
225		       (match_operand:SI  1 "nonmemory_operand"  "d,j>f,jb4")]
226		      UNSPEC_VEC_LOAD_LEN_R))]
227  "TARGET_VXE"
228  "@
229   vlrlr\t%v0,%1,%2
230   vl\t%v0,%2%A2
231   vlrl\t%v0,%2,%1"
232  [(set_attr "op_type" "VRS,VRX,VSI")])
233
234
235; FIXME: The following two patterns might using vec_merge. But what is
236; the canonical form: (vec_select (vec_merge op0 op1)) or (vec_merge
237; (vec_select op0) (vec_select op1)
238; vmrhb, vmrhh, vmrhf, vmrhg
239(define_insn "vec_mergeh<mode>"
240  [(set (match_operand:V_128_NOSINGLE                         0 "register_operand" "=v")
241	(unspec:V_128_NOSINGLE [(match_operand:V_128_NOSINGLE 1 "register_operand"  "v")
242			(match_operand:V_128_NOSINGLE         2 "register_operand"  "v")]
243		       UNSPEC_VEC_MERGEH))]
244  "TARGET_VX"
245  "vmrh<bhfgq>\t%v0,%1,%2"
246  [(set_attr "op_type" "VRR")])
247
248; vmrlb, vmrlh, vmrlf, vmrlg
249(define_insn "vec_mergel<mode>"
250  [(set (match_operand:V_128_NOSINGLE                         0 "register_operand" "=v")
251	(unspec:V_128_NOSINGLE [(match_operand:V_128_NOSINGLE 1 "register_operand"  "v")
252			(match_operand:V_128_NOSINGLE         2 "register_operand"  "v")]
253		     UNSPEC_VEC_MERGEL))]
254  "TARGET_VX"
255  "vmrl<bhfgq>\t%v0,%1,%2"
256  [(set_attr "op_type" "VRR")])
257
258
259; Vector pack
260
261; vpkh, vpkf, vpkg
262(define_insn "vec_pack<mode>"
263  [(set (match_operand:<vec_half>                    0 "register_operand" "=v")
264	(unspec:<vec_half> [(match_operand:VI_HW_HSD 1 "register_operand"  "v")
265			    (match_operand:VI_HW_HSD 2 "register_operand"  "v")]
266			   UNSPEC_VEC_PACK))]
267  "TARGET_VX"
268  "vpk<bhfgq>\t%v0,%v1,%v2"
269  [(set_attr "op_type" "VRR")])
270
271
272; Vector pack saturate
273
274; vpksh, vpksf, vpksg
275(define_insn "vec_packs<mode>"
276  [(set (match_operand:<vec_half>                    0 "register_operand" "=v")
277	(unspec:<vec_half> [(match_operand:VI_HW_HSD 1 "register_operand"  "v")
278			    (match_operand:VI_HW_HSD 2 "register_operand"  "v")]
279			   UNSPEC_VEC_PACK_SATURATE))]
280  "TARGET_VX"
281  "vpks<bhfgq>\t%v0,%v1,%v2"
282  [(set_attr "op_type" "VRR")])
283
284
285; This is vec_packs_cc + loading cc into a caller specified memory location.
286(define_expand "vec_packs_cc<mode>"
287  [(parallel
288    [(set (reg:CCRAW CC_REGNUM)
289	  (unspec:CCRAW [(match_operand:VI_HW_HSD 1 "register_operand" "")
290			 (match_operand:VI_HW_HSD 2 "register_operand" "")]
291			UNSPEC_VEC_PACK_SATURATE_GENCC))
292     (set (match_operand:<vec_half> 0 "register_operand" "")
293	  (unspec:<vec_half> [(match_dup 1) (match_dup 2)]
294			     UNSPEC_VEC_PACK_SATURATE_CC))])
295   (set (match_dup 4)
296	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))
297   (set (match_operand:SI 3 "memory_operand" "")
298	(match_dup 4))]
299  "TARGET_VX"
300{
301  operands[4] = gen_reg_rtx (SImode);
302})
303
304; vpksh, vpksf, vpksg
305(define_insn "*vec_packs_cc<mode>"
306  [(set (reg:CCRAW CC_REGNUM)
307	(unspec:CCRAW [(match_operand:VI_HW_HSD 1 "register_operand" "v")
308		       (match_operand:VI_HW_HSD 2 "register_operand" "v")]
309		      UNSPEC_VEC_PACK_SATURATE_GENCC))
310   (set (match_operand:<vec_half> 0 "register_operand" "=v")
311	(unspec:<vec_half> [(match_dup 1) (match_dup 2)]
312			   UNSPEC_VEC_PACK_SATURATE_CC))]
313  "TARGET_VX"
314  "vpks<bhfgq>s\t%v0,%v1,%v2"
315  [(set_attr "op_type" "VRR")])
316
317
318; Vector pack logical saturate
319
320; vpklsh, vpklsf, vpklsg
321(define_insn "vec_packsu<mode>"
322  [(set (match_operand:<vec_half>                    0 "register_operand" "=v")
323	(unspec:<vec_half> [(match_operand:VI_HW_HSD 1 "register_operand"  "v")
324			    (match_operand:VI_HW_HSD 2 "register_operand"  "v")]
325			   UNSPEC_VEC_PACK_UNSIGNED_SATURATE))]
326  "TARGET_VX"
327  "vpkls<bhfgq>\t%v0,%v1,%v2"
328  [(set_attr "op_type" "VRR")])
329
330; Emulate saturate unsigned pack on signed operands.
331; Zero out negative elements and continue with the unsigned saturating pack.
332(define_expand "vec_packsu_u<mode>"
333  [(set (match_operand:<vec_half>                    0 "register_operand" "=v")
334	(unspec:<vec_half> [(match_operand:VI_HW_HSD 1 "register_operand"  "v")
335			    (match_operand:VI_HW_HSD 2 "register_operand"  "v")]
336			   UNSPEC_VEC_PACK_UNSIGNED_SATURATE))]
337  "TARGET_VX"
338{
339   rtx null_vec = CONST0_RTX(<MODE>mode);
340   machine_mode half_mode;
341   switch (<MODE>mode)
342   {
343     case E_V8HImode: half_mode = V16QImode; break;
344     case E_V4SImode: half_mode = V8HImode; break;
345     case E_V2DImode: half_mode = V4SImode; break;
346     default: gcc_unreachable ();
347   }
348   s390_expand_vcond (operands[1], operands[1], null_vec,
349		      GE, operands[1], null_vec);
350   s390_expand_vcond (operands[2], operands[2], null_vec,
351		      GE, operands[2], null_vec);
352   emit_insn (gen_rtx_SET (operands[0],
353			   gen_rtx_UNSPEC (half_mode,
354					   gen_rtvec (2, operands[1], operands[2]),
355					   UNSPEC_VEC_PACK_UNSIGNED_SATURATE)));
356   DONE;
357})
358
359; This is vec_packsu_cc + loading cc into a caller specified memory location.
360; FIXME: The reg to target mem copy should be issued by reload?!
361(define_expand "vec_packsu_cc<mode>"
362  [(parallel
363    [(set (reg:CCRAW CC_REGNUM)
364	  (unspec:CCRAW [(match_operand:VI_HW_HSD 1 "register_operand" "")
365			 (match_operand:VI_HW_HSD 2 "register_operand" "")]
366			UNSPEC_VEC_PACK_UNSIGNED_SATURATE_GENCC))
367     (set (match_operand:<vec_half> 0 "register_operand" "")
368	  (unspec:<vec_half> [(match_dup 1) (match_dup 2)]
369			     UNSPEC_VEC_PACK_UNSIGNED_SATURATE_CC))])
370   (set (match_dup 4)
371	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))
372   (set (match_operand:SI 3 "memory_operand" "")
373	(match_dup 4))]
374  "TARGET_VX"
375{
376  operands[4] = gen_reg_rtx (SImode);
377})
378
379; vpklsh, vpklsf, vpklsg
380(define_insn "*vec_packsu_cc<mode>"
381  [(set (reg:CCRAW CC_REGNUM)
382	(unspec:CCRAW [(match_operand:VI_HW_HSD 1 "register_operand" "v")
383		       (match_operand:VI_HW_HSD 2 "register_operand" "v")]
384		      UNSPEC_VEC_PACK_UNSIGNED_SATURATE_GENCC))
385   (set (match_operand:<vec_half> 0 "register_operand" "=v")
386	(unspec:<vec_half> [(match_dup 1) (match_dup 2)]
387			   UNSPEC_VEC_PACK_UNSIGNED_SATURATE_CC))]
388  "TARGET_VX"
389  "vpkls<bhfgq>s\t%v0,%v1,%v2"
390  [(set_attr "op_type" "VRR")])
391
392
393; Vector permute
394
395; vec_perm is also RTL standard name, but we can only use it for V16QI
396
397(define_insn "vec_zperm<mode>"
398  [(set (match_operand:V_HW_HSD                   0 "register_operand" "=v")
399	(unspec:V_HW_HSD [(match_operand:V_HW_HSD 1 "register_operand"  "v")
400			  (match_operand:V_HW_HSD 2 "register_operand"  "v")
401			  (match_operand:V16QI    3 "register_operand"  "v")]
402			 UNSPEC_VEC_PERM))]
403  "TARGET_VX"
404  "vperm\t%v0,%v1,%v2,%v3"
405  [(set_attr "op_type" "VRR")])
406
407(define_expand "vec_permi<mode>"
408  [(set (match_operand:V_HW_64                  0 "register_operand"   "")
409	(unspec:V_HW_64 [(match_operand:V_HW_64 1 "register_operand"   "")
410			 (match_operand:V_HW_64 2 "register_operand"   "")
411			 (match_operand:QI      3 "const_mask_operand" "")]
412			UNSPEC_VEC_PERMI))]
413  "TARGET_VX"
414{
415  HOST_WIDE_INT val = INTVAL (operands[3]);
416  operands[3] = GEN_INT ((val & 1) | (val & 2) << 1);
417})
418
419(define_insn "*vec_permi<mode>"
420  [(set (match_operand:V_HW_64                  0 "register_operand"  "=v")
421	(unspec:V_HW_64 [(match_operand:V_HW_64 1 "register_operand"   "v")
422			 (match_operand:V_HW_64 2 "register_operand"   "v")
423			 (match_operand:QI      3 "const_mask_operand" "C")]
424			UNSPEC_VEC_PERMI))]
425  "TARGET_VX && (UINTVAL (operands[3]) & 10) == 0"
426  "vpdi\t%v0,%v1,%v2,%b3"
427  [(set_attr "op_type" "VRR")])
428
429
430; Vector replicate
431
432
433; Replicate from vector element
434(define_expand "vec_splat<mode>"
435  [(set (match_operand:V_HW                      0 "register_operand"  "")
436	(vec_duplicate:V_HW (vec_select:<non_vec>
437			     (match_operand:V_HW 1 "register_operand"  "")
438			     (parallel
439			      [(match_operand:QI 2 "const_mask_operand" "")]))))]
440  "TARGET_VX")
441
442; Vector scatter element
443
444; vscef, vsceg
445
446; A 64 bit target address generated from 32 bit elements
447(define_insn "vec_scatter_element<V_HW_4:mode>_DI"
448  [(set (mem:<non_vec>
449	 (plus:DI (zero_extend:DI
450		   (unspec:SI [(match_operand:V4SI 1 "register_operand"   "v")
451			       (match_operand:QI   3 "const_mask_operand" "C")]
452			      UNSPEC_VEC_EXTRACT))
453		  (match_operand:SI                2 "address_operand"   "ZQ")))
454	(unspec:<non_vec> [(match_operand:V_HW_4          0 "register_operand"   "v")
455			   (match_dup 3)] UNSPEC_VEC_EXTRACT))]
456  "TARGET_VX && TARGET_64BIT && UINTVAL (operands[3]) < 4"
457  "vscef\t%v0,%O2(%v1,%R2),%3"
458  [(set_attr "op_type" "VRV")])
459
460; A 31 bit target address is generated from 64 bit elements
461; vsceg
462(define_insn "vec_scatter_element<V_HW_64:mode>_SI"
463  [(set (mem:<non_vec>
464	 (plus:SI (subreg:SI
465		   (unspec:<non_vec_int> [(match_operand:V_HW_64 1 "register_operand"   "v")
466					  (match_operand:QI      3 "const_mask_operand" "C")]
467					 UNSPEC_VEC_EXTRACT) 4)
468		  (match_operand:SI                              2 "address_operand"   "ZQ")))
469	(unspec:<non_vec> [(match_operand:V_HW_64                0 "register_operand"   "v")
470			   (match_dup 3)] UNSPEC_VEC_EXTRACT))]
471  "TARGET_VX && !TARGET_64BIT && UINTVAL (operands[3]) < GET_MODE_NUNITS (<V_HW_64:MODE>mode)"
472  "vsce<V_HW_64:bhfgq>\t%v0,%O2(%v1,%R2),%3"
473  [(set_attr "op_type" "VRV")])
474
475; Element size and target address size is the same
476; vscef, vsceg
477(define_insn "vec_scatter_element<mode>_<non_vec_int>"
478  [(set (mem:<non_vec>
479	 (plus:<non_vec_int> (unspec:<non_vec_int>
480			      [(match_operand:<tointvec> 1 "register_operand"   "v")
481			       (match_operand:QI         3 "const_mask_operand" "C")]
482			      UNSPEC_VEC_EXTRACT)
483			     (match_operand:DI           2 "address_operand"   "ZQ")))
484	(unspec:<non_vec> [(match_operand:V_HW_32_64     0 "register_operand"   "v")
485			   (match_dup 3)] UNSPEC_VEC_EXTRACT))]
486  "TARGET_VX && UINTVAL (operands[3]) < GET_MODE_NUNITS (<V_HW_32_64:MODE>mode)"
487  "vsce<bhfgq>\t%v0,%O2(%v1,%R2),%3"
488  [(set_attr "op_type" "VRV")])
489
490; Depending on the address size we have to expand a different pattern.
491; This however cannot be represented in s390-builtins.def so we do the
492; multiplexing here in the expander.
493(define_expand "vec_scatter_element<V_HW_32_64:mode>"
494  [(match_operand:V_HW_32_64 0 "register_operand" "")
495   (match_operand:<tointvec> 1 "register_operand" "")
496   (match_operand 2 "address_operand" "")
497   (match_operand:QI 3 "const_mask_operand" "")]
498  "TARGET_VX"
499{
500  if (TARGET_64BIT)
501    {
502      PUT_MODE (operands[2], DImode);
503      emit_insn (
504	gen_vec_scatter_element<V_HW_32_64:mode>_DI (operands[0], operands[1],
505						     operands[2], operands[3]));
506    }
507  else
508    {
509      PUT_MODE (operands[2], SImode);
510      emit_insn (
511	gen_vec_scatter_element<V_HW_32_64:mode>_SI (operands[0], operands[1],
512						     operands[2], operands[3]));
513    }
514  DONE;
515})
516
517
518; Vector select
519
520; for all b in bits op0[b] = op3[b] == 0 ? op2[b] : op1[b]
521; implemented as: op0 = (op1 & op3) | (op2 & ~op3)
522
523; Used to expand the vec_sel builtin. Operands op1 and op2 already got
524; swapped in s390-c.c when we get here.
525
526(define_insn "vsel<mode>"
527  [(set (match_operand:V_HW                      0 "register_operand" "=v")
528	(ior:V_HW
529	 (and:V_HW (match_operand:V_HW           1 "register_operand"  "v")
530		   (match_operand:V_HW           3 "register_operand"  "v"))
531	 (and:V_HW (not:V_HW (match_dup 3))
532		   (match_operand:V_HW           2 "register_operand"  "v"))))]
533  "TARGET_VX"
534  "vsel\t%v0,%1,%2,%3"
535  [(set_attr "op_type" "VRR")])
536
537
538; Vector sign extend to doubleword
539
540; Sign extend of right most vector element to respective double-word
541; vsegb, vsegh, vsegf
542(define_insn "vec_extend<mode>"
543  [(set (match_operand:VI_HW_QHS                    0 "register_operand" "=v")
544	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "v")]
545			  UNSPEC_VEC_EXTEND))]
546  "TARGET_VX"
547  "vseg<bhfgq>\t%v0,%1"
548  [(set_attr "op_type" "VRR")])
549
550
551; Vector store with length
552
553; Store bytes in OP1 from OP0 with the highest indexed byte to be
554; stored from OP0 given by OP2
555(define_insn "vstl<mode>"
556  [(set (match_operand:BLK             2 "memory_operand"   "=Q")
557	(unspec:BLK [(match_operand:V  0 "register_operand"  "v")
558		     (match_operand:SI 1 "register_operand"  "d")]
559		    UNSPEC_VEC_STORE_LEN))]
560  "TARGET_VX"
561  "vstl\t%v0,%1,%2"
562  [(set_attr "op_type" "VRS")])
563
564; Vector store rightmost with length
565
566(define_expand "vstrlrv16qi"
567  [(set (match_operand:BLK                2 "memory_operand"    "")
568	(unspec:BLK [(match_operand:V16QI 0 "register_operand"  "")
569		     (match_operand:SI    1 "nonmemory_operand" "")]
570		    UNSPEC_VEC_STORE_LEN_R))]
571  "TARGET_VXE"
572{
573  /* vstrlr sets all length values beyond 15 to 15.  Emulate the same
574     behavior for immediate length operands.  vstrl would trigger a
575     SIGILL for too large immediate operands.  */
576  if (CONST_INT_P (operands[1])
577      && (UINTVAL (operands[1]) & 0xffffffff) > 15)
578    operands[1] = GEN_INT (15);
579})
580
581(define_insn "*vstrlrv16qi"
582  [(set (match_operand:BLK                2 "memory_operand"    "=Q,  R,  Q")
583	(unspec:BLK [(match_operand:V16QI 0 "register_operand"   "v,  v,  v")
584		     (match_operand:SI    1 "nonmemory_operand"  "d,j>f,jb4")]
585		    UNSPEC_VEC_STORE_LEN_R))]
586  "TARGET_VXE"
587  "@
588   vstrlr\t%v0,%1,%2
589   vst\t%v0,%2%A2
590   vstrl\t%v0,%2,%1"
591  [(set_attr "op_type" "VRS,VRX,VSI")])
592
593
594
595; vector bit permute
596
597(define_insn "vbpermv16qi"
598  [(set (match_operand:V2DI                0 "register_operand" "=v")
599	(unspec:V2DI [(match_operand:V16QI 1 "register_operand"  "v")
600		      (match_operand:V16QI 2 "register_operand"  "v")]
601		     UNSPEC_VEC_VBPERM))]
602  "TARGET_VXE"
603  "vbperm\t%v0,%v1,%v2"
604  [(set_attr "op_type" "VRR")])
605
606; Vector unpack high
607
608; vuphb, vuphh, vuphf
609(define_insn "vec_unpackh<mode>"
610  [(set (match_operand:<vec_double>                    0 "register_operand" "=v")
611	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"  "v")]
612			     UNSPEC_VEC_UNPACKH))]
613  "TARGET_VX"
614  "vuph<bhfgq>\t%v0,%v1"
615  [(set_attr "op_type" "VRR")])
616
617; vuplhb, vuplhh, vuplhf
618(define_insn "vec_unpackh_l<mode>"
619  [(set (match_operand:<vec_double>                    0 "register_operand" "=v")
620	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"  "v")]
621			     UNSPEC_VEC_UNPACKH_L))]
622  "TARGET_VX"
623  "vuplh<bhfgq>\t%v0,%v1"
624  [(set_attr "op_type" "VRR")])
625
626
627; Vector unpack low
628
629; vuplb, vuplhw, vuplf
630(define_insn "vec_unpackl<mode>"
631  [(set (match_operand:<vec_double>                    0 "register_operand" "=v")
632	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"  "v")]
633			     UNSPEC_VEC_UNPACKL))]
634  "TARGET_VX"
635  "vupl<bhfgq><w>\t%v0,%v1"
636  [(set_attr "op_type" "VRR")])
637
638; vupllb, vupllh, vupllf
639(define_insn "vec_unpackl_l<mode>"
640  [(set (match_operand:<vec_double>                    0 "register_operand" "=v")
641	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"  "v")]
642			     UNSPEC_VEC_UNPACKL_L))]
643  "TARGET_VX"
644  "vupll<bhfgq>\t%v0,%v1"
645  [(set_attr "op_type" "VRR")])
646
647
648; Vector add
649
650; Vector add compute carry
651
652; vaccb, vacch, vaccf, vaccg, vaccq
653(define_insn "vacc<bhfgq>_<mode>"
654  [(set (match_operand:VIT_HW                 0 "register_operand" "=v")
655	(unspec:VIT_HW [(match_operand:VIT_HW 1 "register_operand"  "v")
656			(match_operand:VIT_HW 2 "register_operand"  "v")]
657		       UNSPEC_VEC_ADDC))]
658  "TARGET_VX"
659  "vacc<bhfgq>\t%v0,%v1,%v2"
660  [(set_attr "op_type" "VRR")])
661
662; Vector add with carry
663
664(define_insn "vacq"
665  [(set (match_operand:TI             0 "register_operand" "=v")
666	(unspec:TI [(match_operand:TI 1 "register_operand"  "v")
667		    (match_operand:TI 2 "register_operand"  "v")
668		    (match_operand:TI 3 "register_operand"  "v")]
669		   UNSPEC_VEC_ADDE_U128))]
670  "TARGET_VX"
671  "vacq\t%v0,%v1,%v2,%v3"
672  [(set_attr "op_type" "VRR")])
673
674
675; Vector add with carry compute carry
676
677(define_insn "vacccq"
678  [(set (match_operand:TI             0 "register_operand" "=v")
679	(unspec:TI [(match_operand:TI 1 "register_operand"  "v")
680		    (match_operand:TI 2 "register_operand"  "v")
681		    (match_operand:TI 3 "register_operand"  "v")]
682		   UNSPEC_VEC_ADDEC_U128))]
683  "TARGET_VX"
684  "vacccq\t%v0,%v1,%v2,%v3"
685  [(set_attr "op_type" "VRR")])
686
687
688; Vector and
689
690; Vector and with complement
691
692; vnc
693(define_insn "vec_andc<mode>3"
694  [(set (match_operand:VT_HW                       0 "register_operand" "=v")
695	(and:VT_HW (not:VT_HW (match_operand:VT_HW 2 "register_operand"  "v"))
696		  (match_operand:VT_HW             1 "register_operand"  "v")))]
697  "TARGET_VX"
698  "vnc\t%v0,%v1,%v2"
699  [(set_attr "op_type" "VRR")])
700
701
702; Vector average
703
704; vavgb, vavgh, vavgf, vavgg
705(define_insn "vec_avg<mode>"
706  [(set (match_operand:VI_HW                0 "register_operand" "=v")
707	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")
708		       (match_operand:VI_HW 2 "register_operand"  "v")]
709		      UNSPEC_VEC_AVG))]
710  "TARGET_VX"
711  "vavg<bhfgq>\t%v0,%v1,%v2"
712  [(set_attr "op_type" "VRR")])
713
714; Vector average logical
715
716; vavglb, vavglh, vavglf, vavglg
717(define_insn "vec_avgu<mode>"
718  [(set (match_operand:VI_HW                0 "register_operand" "=v")
719	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")
720		       (match_operand:VI_HW 2 "register_operand"  "v")]
721		      UNSPEC_VEC_AVGU))]
722  "TARGET_VX"
723  "vavgl<bhfgq>\t%v0,%v1,%v2"
724  [(set_attr "op_type" "VRR")])
725
726
727; Vector checksum
728
729(define_insn "vec_checksum"
730  [(set (match_operand:V4SI               0 "register_operand" "=v")
731	(unspec:V4SI [(match_operand:V4SI 1 "register_operand"  "v")
732		      (match_operand:V4SI 2 "register_operand"  "v")]
733		     UNSPEC_VEC_CHECKSUM))]
734  "TARGET_VX"
735  "vcksm\t%v0,%v1,%v2"
736  [(set_attr "op_type" "VRR")])
737
738;;
739;; Vector compare
740;;
741
742; vec_all/any int compares
743
744(define_expand "vec_all_<intcmpcc:code><VI_HW:mode>"
745  [(match_operand:SI                0 "register_operand" "")
746   (intcmpcc (match_operand:VI_HW 1 "register_operand" "")
747	     (match_operand:VI_HW 2 "register_operand" ""))]
748  "TARGET_VX"
749{
750  s390_expand_vec_compare_cc (operands[0],
751			      <intcmpcc:CODE>,
752			      operands[1],
753			      operands[2],
754			      true);
755  DONE;
756})
757
758(define_expand "vec_any_<intcmpcc:code><VI_HW:mode>"
759  [(match_operand:SI                0 "register_operand" "")
760   (intcmpcc (match_operand:VI_HW 1 "register_operand" "")
761	     (match_operand:VI_HW 2 "register_operand" ""))]
762  "TARGET_VX"
763{
764  s390_expand_vec_compare_cc (operands[0],
765			      <intcmpcc:CODE>,
766			      operands[1],
767			      operands[2],
768			      false);
769  DONE;
770})
771
772; vec_all/any fp compares
773
774(define_expand "vec_all_<fpcmpcc:code><mode>"
775  [(match_operand:SI               0 "register_operand" "")
776   (fpcmpcc (match_operand:VECF_HW 1 "register_operand" "")
777	    (match_operand:VECF_HW 2 "register_operand" ""))]
778  "TARGET_VX"
779{
780  s390_expand_vec_compare_cc (operands[0],
781			      <fpcmpcc:CODE>,
782			      operands[1],
783			      operands[2],
784			      true);
785  DONE;
786})
787
788(define_expand "vec_any_<fpcmpcc:code><mode>"
789  [(match_operand:SI               0 "register_operand" "")
790   (fpcmpcc (match_operand:VECF_HW 1 "register_operand" "")
791	    (match_operand:VECF_HW 2 "register_operand" ""))]
792  "TARGET_VX"
793{
794  s390_expand_vec_compare_cc (operands[0],
795			      <fpcmpcc:CODE>,
796			      operands[1],
797			      operands[2],
798			      false);
799  DONE;
800})
801
802
803; Compare without generating CC
804
805(define_expand "vec_cmp<intcmp:code><VI_HW:mode>"
806  [(set (match_operand:VI_HW               0 "register_operand" "=v")
807	(intcmp:VI_HW (match_operand:VI_HW 1 "register_operand"  "v")
808		      (match_operand:VI_HW 2 "register_operand"  "v")))]
809  "TARGET_VX"
810{
811  s390_expand_vec_compare (operands[0], <intcmp:CODE>, operands[1], operands[2]);
812  DONE;
813})
814
815(define_expand "vec_cmp<fpcmp:code><mode>"
816  [(set (match_operand:<tointvec>              0 "register_operand" "=v")
817	(fpcmp:<tointvec> (match_operand:VF_HW 1 "register_operand"  "v")
818		       (match_operand:VF_HW 2 "register_operand"  "v")))]
819  "TARGET_VX"
820{
821  s390_expand_vec_compare (operands[0], <fpcmp:CODE>, operands[1], operands[2]);
822  DONE;
823})
824
825
826; Vector count leading zeros
827
828; vec_cntlz -> clz
829; vec_cnttz -> ctz
830
831; Vector xor
832
833; vec_xor -> xor
834
835; Vector Galois field multiply sum
836
837; vgfmb, vgfmh, vgfmf
838(define_insn "vec_gfmsum<mode>"
839  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
840	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
841			   (match_operand:VI_HW_QHS 2 "register_operand" "v")]
842			  UNSPEC_VEC_GFMSUM))]
843  "TARGET_VX"
844  "vgfm<bhfgq>\t%v0,%v1,%v2"
845  [(set_attr "op_type" "VRR")])
846
847(define_insn "vec_gfmsum_128"
848  [(set (match_operand:V16QI 0 "register_operand" "=v")
849	(unspec:V16QI [(match_operand:V2DI 1 "register_operand" "v")
850		       (match_operand:V2DI 2 "register_operand" "v")]
851		      UNSPEC_VEC_GFMSUM_128))]
852  "TARGET_VX"
853  "vgfmg\t%v0,%v1,%v2"
854  [(set_attr "op_type" "VRR")])
855
856; vgfmab, vgfmah, vgfmaf
857(define_insn "vec_gfmsum_accum<mode>"
858  [(set (match_operand:<vec_double> 0 "register_operand" "=v")
859	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand" "v")
860			      (match_operand:VI_HW_QHS 2 "register_operand" "v")
861			      (match_operand:<vec_double> 3 "register_operand" "v")]
862			     UNSPEC_VEC_GFMSUM_ACCUM))]
863  "TARGET_VX"
864  "vgfma<bhfgq>\t%v0,%v1,%v2,%v3"
865  [(set_attr "op_type" "VRR")])
866
867(define_insn "vec_gfmsum_accum_128"
868  [(set (match_operand:V16QI 0 "register_operand" "=v")
869	(unspec:V16QI [(match_operand:V2DI 1 "register_operand" "v")
870		       (match_operand:V2DI 2 "register_operand" "v")
871		       (match_operand:V16QI 3 "register_operand" "v")]
872		      UNSPEC_VEC_GFMSUM_ACCUM_128))]
873  "TARGET_VX"
874  "vgfmag\t%v0,%v1,%v2,%v3"
875  [(set_attr "op_type" "VRR")])
876
877
878; FIXME: vec_neg ?
879
880; Vector load positive: vec_abs -> abs
881; Vector maximum vec_max -> smax, logical vec_max -> umax
882; Vector maximum vec_min -> smin, logical vec_min -> umin
883
884
885; Vector multiply and add high
886
887; vec_mladd -> vec_vmal
888; vmalb, vmalh, vmalf, vmalg
889(define_insn "vec_vmal<mode>"
890  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
891	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
892			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
893			   (match_operand:VI_HW_QHS 3 "register_operand" "v")]
894			  UNSPEC_VEC_VMAL))]
895  "TARGET_VX"
896  "vmal<bhfgq><w>\t%v0,%v1,%v2,%v3"
897  [(set_attr "op_type" "VRR")])
898
899; vec_mhadd -> vec_vmah/vec_vmalh
900
901; vmahb; vmahh, vmahf, vmahg
902(define_insn "vec_vmah<mode>"
903  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
904	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
905			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
906			   (match_operand:VI_HW_QHS 3 "register_operand" "v")]
907			  UNSPEC_VEC_VMAH))]
908  "TARGET_VX"
909  "vmah<bhfgq>\t%v0,%v1,%v2,%v3"
910  [(set_attr "op_type" "VRR")])
911
912; vmalhb; vmalhh, vmalhf, vmalhg
913(define_insn "vec_vmalh<mode>"
914  [(set (match_operand:VI_HW_QHS 0 "register_operand"                   "=v")
915	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
916			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
917			   (match_operand:VI_HW_QHS 3 "register_operand" "v")]
918			  UNSPEC_VEC_VMALH))]
919  "TARGET_VX"
920  "vmalh<bhfgq>\t%v0,%v1,%v2,%v3"
921  [(set_attr "op_type" "VRR")])
922
923; vec_meadd -> vec_vmae/vec_vmale
924
925; vmaeb; vmaeh, vmaef, vmaeg
926(define_insn "vec_vmae<mode>"
927  [(set (match_operand:<vec_double> 0 "register_operand"                      "=v")
928	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"    "v")
929			      (match_operand:VI_HW_QHS 2 "register_operand"    "v")
930			      (match_operand:<vec_double> 3 "register_operand" "v")]
931			     UNSPEC_VEC_VMAE))]
932  "TARGET_VX"
933  "vmae<bhfgq>\t%v0,%v1,%v2,%v3"
934  [(set_attr "op_type" "VRR")])
935
936; vmaleb; vmaleh, vmalef, vmaleg
937(define_insn "vec_vmale<mode>"
938  [(set (match_operand:<vec_double> 0 "register_operand"                      "=v")
939	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"    "v")
940			      (match_operand:VI_HW_QHS 2 "register_operand"    "v")
941			      (match_operand:<vec_double> 3 "register_operand" "v")]
942			     UNSPEC_VEC_VMALE))]
943  "TARGET_VX"
944  "vmale<bhfgq>\t%v0,%v1,%v2,%v3"
945  [(set_attr "op_type" "VRR")])
946
947; vec_moadd -> vec_vmao/vec_vmalo
948
949; vmaob; vmaoh, vmaof, vmaog
950(define_insn "vec_vmao<mode>"
951  [(set (match_operand:<vec_double> 0 "register_operand"                      "=v")
952	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"    "v")
953			      (match_operand:VI_HW_QHS 2 "register_operand"    "v")
954			      (match_operand:<vec_double> 3 "register_operand" "v")]
955			     UNSPEC_VEC_VMAO))]
956  "TARGET_VX"
957  "vmao<bhfgq>\t%v0,%v1,%v2,%v3"
958  [(set_attr "op_type" "VRR")])
959
960; vmalob; vmaloh, vmalof, vmalog
961(define_insn "vec_vmalo<mode>"
962  [(set (match_operand:<vec_double> 0 "register_operand"                      "=v")
963	(unspec:<vec_double> [(match_operand:VI_HW_QHS 1 "register_operand"    "v")
964			      (match_operand:VI_HW_QHS 2 "register_operand"    "v")
965			      (match_operand:<vec_double> 3 "register_operand" "v")]
966			     UNSPEC_VEC_VMALO))]
967  "TARGET_VX"
968  "vmalo<bhfgq>\t%v0,%v1,%v2,%v3"
969  [(set_attr "op_type" "VRR")])
970
971
972; Vector multiply high
973
974; vec_mulh -> vec_smulh/vec_umulh
975
976; vmhb, vmhh, vmhf
977(define_insn "vec_smulh<mode>"
978  [(set (match_operand:VI_HW_QHS 0 "register_operand"                   "=v")
979	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
980			   (match_operand:VI_HW_QHS 2 "register_operand" "v")]
981			  UNSPEC_VEC_SMULT_HI))]
982  "TARGET_VX"
983  "vmh<bhfgq>\t%v0,%v1,%v2"
984  [(set_attr "op_type" "VRR")])
985
986; vmlhb, vmlhh, vmlhf
987(define_insn "vec_umulh<mode>"
988  [(set (match_operand:VI_HW_QHS 0 "register_operand"                   "=v")
989	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
990			   (match_operand:VI_HW_QHS 2 "register_operand" "v")]
991			  UNSPEC_VEC_UMULT_HI))]
992  "TARGET_VX"
993  "vmlh<bhfgq>\t%v0,%v1,%v2"
994  [(set_attr "op_type" "VRR")])
995
996
997; Vector multiply low
998
999; vec_mule -> vec_widen_umult_even/vec_widen_smult_even
1000; vec_mulo -> vec_widen_umult_odd/vec_widen_smult_odd
1001
1002
1003; Vector nor
1004
1005(define_insn "vec_nor<mode>3"
1006  [(set (match_operand:VT_HW 0 "register_operand"            "=v")
1007	(not:VT_HW
1008	 (ior:VT_HW (match_operand:VT_HW 1 "register_operand" "v")
1009		    (match_operand:VT_HW 2 "register_operand" "v"))))]
1010  "TARGET_VX"
1011  "vno\t%v0,%v1,%v2"
1012  [(set_attr "op_type" "VRR")])
1013
1014
1015; Vector or
1016
1017; Vector population count vec_popcnt -> popcount
1018; Vector element rotate left logical vec_rl -> vrotl, vec_rli -> rot
1019
1020; Vector element rotate and insert under mask
1021
1022; verimb, verimh, verimf, verimg
1023(define_insn "verim<mode>"
1024  [(set (match_operand:VI_HW                0 "register_operand" "=v")
1025	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "0")
1026		       (match_operand:VI_HW 2 "register_operand"  "v")
1027		       (match_operand:VI_HW 3 "register_operand"  "v")
1028		       (match_operand:QI    4 "const_int_operand" "C")]
1029		      UNSPEC_VEC_RL_MASK))]
1030  "TARGET_VX"
1031  "verim<bhfgq>\t%v0,%v2,%v3,%b4"
1032  [(set_attr "op_type" "VRI")])
1033
1034
1035; Vector shift left
1036
1037(define_insn "vec_sll<VI_HW:mode><VI_HW_QHS:mode>"
1038  [(set (match_operand:VI_HW                    0 "register_operand" "=v")
1039	(unspec:VI_HW [(match_operand:VI_HW     1 "register_operand"  "v")
1040		       (match_operand:VI_HW_QHS 2 "register_operand"  "v")]
1041		      UNSPEC_VEC_SLL))]
1042  "TARGET_VX"
1043  "vsl\t%v0,%v1,%v2"
1044  [(set_attr "op_type" "VRR")])
1045
1046
1047; Vector shift left by byte
1048
1049; Pattern definition in vector.md, see vec_vslb
1050(define_expand "vec_slb<mode>"
1051  [(set (match_operand:V_HW 0 "register_operand"                     "")
1052	(unspec:V_HW [(match_operand:V_HW 1 "register_operand"       "")
1053		      (match_operand:<tointvec> 2 "register_operand" "")]
1054		     UNSPEC_VEC_SLB))]
1055  "TARGET_VX"
1056{
1057  PUT_MODE (operands[2], V16QImode);
1058})
1059
1060; Vector shift left double by byte
1061
1062(define_insn "vec_sld<mode>"
1063  [(set (match_operand:V_HW 0 "register_operand"              "=v")
1064	(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v")
1065		      (match_operand:V_HW 2 "register_operand" "v")
1066		      (match_operand:QI 3 "const_int_operand"  "C")]
1067		     UNSPEC_VEC_SLDBYTE))]
1068  "TARGET_VX"
1069  "vsldb\t%v0,%v1,%v2,%b3"
1070  [(set_attr "op_type" "VRI")])
1071
1072(define_expand "vec_sldw<mode>"
1073  [(set (match_operand:V_HW 0 "register_operand"               "")
1074	(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "")
1075		      (match_operand:V_HW 2 "register_operand" "")
1076		      (match_operand:QI 3 "const_int_operand"  "")]
1077		     UNSPEC_VEC_SLDBYTE))]
1078  "TARGET_VX"
1079{
1080  operands[3] = GEN_INT (INTVAL (operands[3]) << 2);
1081})
1082
1083; Vector shift left double by bit
1084
1085(define_insn "vec_sldb<mode>"
1086  [(set (match_operand:V_HW 0 "register_operand"              "=v")
1087	(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v")
1088		      (match_operand:V_HW 2 "register_operand" "v")
1089		      (match_operand:QI 3 "const_int_operand"  "C")]
1090		     UNSPEC_VEC_SLDBIT))]
1091  "TARGET_VXE2"
1092  "vsld\t%v0,%v1,%v2,%b3"
1093  [(set_attr "op_type" "VRI")])
1094
1095; Vector shift right double by bit
1096
1097(define_insn "vec_srdb<mode>"
1098  [(set (match_operand:V_HW 0 "register_operand"              "=v")
1099	(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v")
1100		      (match_operand:V_HW 2 "register_operand" "v")
1101		      (match_operand:QI 3 "const_int_operand"  "C")]
1102		     UNSPEC_VEC_SRDBIT))]
1103  "TARGET_VXE2"
1104  "vsrd\t%v0,%v1,%v2,%b3"
1105  [(set_attr "op_type" "VRI")])
1106
1107; Vector shift right arithmetic
1108
1109(define_insn "vec_sral<VI_HW:mode><VI_HW_QHS:mode>"
1110  [(set (match_operand:VI_HW                    0 "register_operand" "=v")
1111	(unspec:VI_HW [(match_operand:VI_HW     1 "register_operand"  "v")
1112		       (match_operand:VI_HW_QHS 2 "register_operand"  "v")]
1113		      UNSPEC_VEC_SRAL))]
1114  "TARGET_VX"
1115  "vsra\t%v0,%v1,%v2"
1116  [(set_attr "op_type" "VRR")])
1117
1118
1119; Vector shift right arithmetic by byte
1120
1121(define_insn "vec_srab<mode>"
1122  [(set (match_operand:V_HW 0 "register_operand"                    "=v")
1123	(unspec:V_HW [(match_operand:V_HW 1 "register_operand"       "v")
1124		      (match_operand:<tointvec> 2 "register_operand" "v")]
1125		     UNSPEC_VEC_SRAB))]
1126  "TARGET_VX"
1127  "vsrab\t%v0,%v1,%v2"
1128  [(set_attr "op_type" "VRR")])
1129
1130
1131; Vector shift right logical
1132
1133(define_insn "vec_srl<VI_HW:mode><VI_HW_QHS:mode>"
1134  [(set (match_operand:VI_HW                    0 "register_operand" "=v")
1135	(unspec:VI_HW [(match_operand:VI_HW     1 "register_operand"  "v")
1136		       (match_operand:VI_HW_QHS 2 "register_operand"  "v")]
1137		      UNSPEC_VEC_SRL))]
1138  "TARGET_VX"
1139  "vsrl\t%v0,%v1,%v2"
1140  [(set_attr "op_type" "VRR")])
1141
1142
1143; Vector shift right logical by byte
1144
1145; Pattern definition in vector.md, see vec_vsrb
1146(define_expand "vec_srb<mode>"
1147  [(set (match_operand:V_HW 0 "register_operand"                     "")
1148	(unspec:V_HW [(match_operand:V_HW 1 "register_operand"       "")
1149		      (match_operand:<tointvec> 2 "register_operand" "")]
1150		     UNSPEC_VEC_SRLB))]
1151  "TARGET_VX"
1152{
1153  PUT_MODE (operands[2], V16QImode);
1154})
1155
1156; Vector subtract
1157
1158; Vector subtract compute borrow indication
1159
1160; vscbib, vscbih, vscbif, vscbig, vscbiq
1161(define_insn "vscbi<bhfgq>_<mode>"
1162  [(set (match_operand:VIT_HW 0 "register_operand"                "=v")
1163	(unspec:VIT_HW [(match_operand:VIT_HW 1 "register_operand" "v")
1164			(match_operand:VIT_HW 2 "register_operand" "v")]
1165		      UNSPEC_VEC_SUBC))]
1166  "TARGET_VX"
1167  "vscbi<bhfgq>\t%v0,%v1,%v2"
1168  [(set_attr "op_type" "VRR")])
1169
1170; Vector subtract with borrow indication
1171
1172(define_insn "vsbiq"
1173  [(set (match_operand:TI 0 "register_operand"               "=v")
1174	(unspec:TI [(match_operand:TI 1 "register_operand"    "v")
1175		       (match_operand:TI 2 "register_operand" "v")
1176		       (match_operand:TI 3 "register_operand" "v")]
1177		      UNSPEC_VEC_SUBE_U128))]
1178  "TARGET_VX"
1179  "vsbiq\t%v0,%v1,%v2,%v3"
1180  [(set_attr "op_type" "VRR")])
1181
1182
1183; Vector subtract with borrow compute and borrow indication
1184
1185(define_insn "vsbcbiq"
1186  [(set (match_operand:TI 0 "register_operand"               "=v")
1187	(unspec:TI [(match_operand:TI 1 "register_operand"    "v")
1188		       (match_operand:TI 2 "register_operand" "v")
1189		       (match_operand:TI 3 "register_operand" "v")]
1190		      UNSPEC_VEC_SUBEC_U128))]
1191  "TARGET_VX"
1192  "vsbcbiq\t%v0,%v1,%v2,%v3"
1193  [(set_attr "op_type" "VRR")])
1194
1195
1196; Vector sum across
1197
1198; Sum across DImode parts of the 1st operand and add the rightmost
1199; element of 2nd operand
1200; vsumgh, vsumgf
1201(define_expand "vec_sum2<mode>"
1202  [(set (match_operand:V2DI 0 "register_operand" "")
1203	(unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "")
1204		      (match_operand:VI_HW_HS 2 "register_operand" "")]
1205		     UNSPEC_VEC_VSUMG))]
1206  "TARGET_VX")
1207
1208; vsumqh, vsumqf
1209(define_insn "vec_sum_u128<mode>"
1210  [(set (match_operand:V2DI 0 "register_operand" "=v")
1211	(unspec:V2DI [(match_operand:VI_HW_SD 1 "register_operand" "v")
1212		      (match_operand:VI_HW_SD 2 "register_operand" "v")]
1213		     UNSPEC_VEC_VSUMQ))]
1214  "TARGET_VX"
1215  "vsumq<bhfgq>\t%v0,%v1,%v2"
1216  [(set_attr "op_type" "VRR")])
1217
1218; vsumb, vsumh
1219(define_expand "vec_sum4<mode>"
1220  [(set (match_operand:V4SI 0 "register_operand" "")
1221	(unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "")
1222		      (match_operand:VI_HW_QH 2 "register_operand" "")]
1223		     UNSPEC_VEC_VSUM))]
1224  "TARGET_VX")
1225
1226
1227; Vector test under mask
1228
1229(define_expand "vec_test_mask_int<mode>"
1230  [(set (reg:CCRAW CC_REGNUM)
1231	(unspec:CCRAW [(match_operand:V_HW 1 "register_operand" "")
1232		       (match_operand:<tointvec> 2 "register_operand" "")]
1233		      UNSPEC_VEC_TEST_MASK))
1234   (set (match_operand:SI 0 "register_operand" "")
1235	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1236  "TARGET_VX")
1237
1238(define_insn "*vec_test_mask<mode>"
1239  [(set (reg:CCRAW CC_REGNUM)
1240	(unspec:CCRAW [(match_operand:V_HW 0 "register_operand" "v")
1241		       (match_operand:<tointvec> 1 "register_operand" "v")]
1242		      UNSPEC_VEC_TEST_MASK))]
1243  "TARGET_VX"
1244  "vtm\t%v0,%v1"
1245  [(set_attr "op_type" "VRR")])
1246
1247
1248; Vector multiply sum logical
1249
1250(define_insn "vec_msumv2di"
1251  [(set (match_operand:V16QI 0 "register_operand" "=v")
1252	(unspec:V16QI [(match_operand:V2DI  1 "register_operand"   "v")
1253		       (match_operand:V2DI  2 "register_operand"   "v")
1254		       (match_operand:V16QI 3 "register_operand"   "v")
1255		       (match_operand:QI    4 "const_mask_operand" "C")]
1256		      UNSPEC_VEC_MSUM))]
1257  "TARGET_VXE"
1258  "vmslg\t%v0,%v1,%v2,%v3,%4"
1259  [(set_attr "op_type" "VRR")])
1260
1261(define_insn "vmslg"
1262  [(set (match_operand:TI 0 "register_operand" "=v")
1263	(unspec:TI [(match_operand:V2DI  1 "register_operand"   "v")
1264		    (match_operand:V2DI  2 "register_operand"   "v")
1265		    (match_operand:TI    3 "register_operand"   "v")
1266		    (match_operand:QI    4 "const_mask_operand" "C")]
1267		   UNSPEC_VEC_MSUM))]
1268  "TARGET_VXE"
1269  "vmslg\t%v0,%v1,%v2,%v3,%4"
1270  [(set_attr "op_type" "VRR")])
1271
1272
1273; Vector find any element equal
1274
1275; vfaeb, vfaeh, vfaef
1276; vfaezb, vfaezh, vfaezf
1277(define_insn "vfae<mode>"
1278  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1279	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1280			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
1281			   (match_operand:QI        3 "const_mask_operand" "C")]
1282			  UNSPEC_VEC_VFAE))]
1283  "TARGET_VX"
1284{
1285  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
1286
1287  if (flags & VSTRING_FLAG_ZS)
1288    {
1289      flags &= ~VSTRING_FLAG_ZS;
1290      operands[3] = GEN_INT (flags);
1291      return "vfaez<bhfgq>\t%v0,%v1,%v2,%b3";
1292    }
1293  return "vfae<bhfgq>\t%v0,%v1,%v2,%b3";
1294}
1295[(set_attr "op_type" "VRR")])
1296
1297; vfaebs, vfaehs, vfaefs
1298; vfaezbs, vfaezhs, vfaezfs
1299(define_insn "*vfaes<mode>"
1300  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1301	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"   "v")
1302			   (match_operand:VI_HW_QHS 2 "register_operand"   "v")
1303			   (match_operand:QI        3 "const_mask_operand" "C")]
1304			  UNSPEC_VEC_VFAE))
1305   (set (reg:CCRAW CC_REGNUM)
1306	(unspec:CCRAW [(match_dup 1)
1307		       (match_dup 2)
1308		       (match_dup 3)]
1309		      UNSPEC_VEC_VFAECC))]
1310  "TARGET_VX"
1311{
1312  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
1313
1314  if (flags & VSTRING_FLAG_ZS)
1315    {
1316      flags &= ~VSTRING_FLAG_ZS;
1317      operands[3] = GEN_INT (flags);
1318      return "vfaez<bhfgq>s\t%v0,%v1,%v2,%b3";
1319    }
1320  return "vfae<bhfgq>s\t%v0,%v1,%v2,%b3";
1321}
1322  [(set_attr "op_type" "VRR")])
1323
1324(define_expand "vfaez<mode>"
1325  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1326	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "")
1327			   (match_operand:VI_HW_QHS 2 "register_operand"  "")
1328			   (match_operand:QI        3 "const_mask_operand" "")]
1329			  UNSPEC_VEC_VFAE))]
1330  "TARGET_VX"
1331{
1332  operands[3] = GEN_INT (INTVAL (operands[3]) | VSTRING_FLAG_ZS);
1333})
1334
1335(define_expand "vfaes<mode>"
1336  [(parallel
1337    [(set (match_operand:VI_HW_QHS 0 "register_operand" "")
1338	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "")
1339			   (match_operand:VI_HW_QHS 2 "register_operand"  "")
1340			   (match_operand:QI        3 "const_mask_operand" "")]
1341			  UNSPEC_VEC_VFAE))
1342   (set (reg:CCRAW CC_REGNUM)
1343	(unspec:CCRAW [(match_dup 1)
1344		       (match_dup 2)
1345		       (match_dup 3)]
1346		      UNSPEC_VEC_VFAECC))])
1347   (set (match_operand:SI 4 "memory_operand" "")
1348	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1349  "TARGET_VX"
1350{
1351  operands[3] = GEN_INT (INTVAL (operands[3]) | VSTRING_FLAG_CS);
1352})
1353
1354(define_expand "vfaezs<mode>"
1355  [(parallel
1356    [(set (match_operand:VI_HW_QHS 0 "register_operand" "")
1357	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "")
1358			   (match_operand:VI_HW_QHS 2 "register_operand"  "")
1359			   (match_operand:SI        3 "const_mask_operand" "")]
1360			  UNSPEC_VEC_VFAE))
1361   (set (reg:CCRAW CC_REGNUM)
1362	(unspec:CCRAW [(match_dup 1)
1363		       (match_dup 2)
1364		       (match_dup 3)]
1365		      UNSPEC_VEC_VFAECC))])
1366   (set (match_operand:SI 4 "memory_operand" "")
1367	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1368  "TARGET_VX"
1369{
1370  operands[3] = GEN_INT (INTVAL (operands[3]) | VSTRING_FLAG_CS | VSTRING_FLAG_ZS);
1371})
1372
1373
1374; Vector find element equal
1375
1376; vfeebs, vfeehs, vfeefs
1377; vfeezbs, vfeezhs, vfeezfs
1378(define_insn "*vfees<mode>"
1379  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1380	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1381			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
1382			   (match_operand:QI 3 "const_mask_operand" "C")]
1383			  UNSPEC_VEC_VFEE))
1384   (set (reg:CCRAW CC_REGNUM)
1385	(unspec:CCRAW [(match_dup 1)
1386		       (match_dup 2)
1387		       (match_dup 3)]
1388		      UNSPEC_VEC_VFEECC))]
1389  "TARGET_VX"
1390{
1391  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
1392
1393  gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
1394  flags &= ~VSTRING_FLAG_CS;
1395
1396  if (flags == VSTRING_FLAG_ZS)
1397    return "vfeez<bhfgq>s\t%v0,%v1,%v2";
1398  return "vfee<bhfgq>s\t%v0,%v1,%v2,%b3";
1399}
1400  [(set_attr "op_type" "VRR")])
1401
1402; vfeeb, vfeeh, vfeef
1403(define_insn "vfee<mode>"
1404  [(set (match_operand:VI_HW_QHS                    0 "register_operand" "=v")
1405	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "v")
1406			   (match_operand:VI_HW_QHS 2 "register_operand"  "v")
1407			   (const_int 0)]
1408			  UNSPEC_VEC_VFEE))]
1409  "TARGET_VX"
1410  "vfee<bhfgq>\t%v0,%v1,%v2,0"
1411  [(set_attr "op_type" "VRR")])
1412
1413; vfeezb, vfeezh, vfeezf
1414(define_insn "vfeez<mode>"
1415  [(set (match_operand:VI_HW_QHS                    0 "register_operand" "=v")
1416	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "v")
1417			   (match_operand:VI_HW_QHS 2 "register_operand"  "v")
1418			   (const_int VSTRING_FLAG_ZS)]
1419			  UNSPEC_VEC_VFEE))]
1420  "TARGET_VX"
1421  "vfeez<bhfgq>s\t%v0,%v1,%v2,2"
1422  [(set_attr "op_type" "VRR")])
1423
1424(define_expand "vfees<mode>"
1425  [(parallel
1426    [(set (match_operand:VI_HW_QHS                    0 "register_operand" "")
1427	  (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1428			     (match_operand:VI_HW_QHS 2 "register_operand" "")
1429			     (const_int VSTRING_FLAG_CS)]
1430			    UNSPEC_VEC_VFEE))
1431   (set (reg:CCRAW CC_REGNUM)
1432	(unspec:CCRAW [(match_dup 1)
1433		       (match_dup 2)
1434		       (const_int VSTRING_FLAG_CS)]
1435		      UNSPEC_VEC_VFEECC))])
1436   (set (match_operand:SI 3 "memory_operand" "")
1437	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1438  "TARGET_VX")
1439
1440(define_expand "vfeezs<mode>"
1441  [(parallel
1442    [(set (match_operand:VI_HW_QHS                    0 "register_operand" "")
1443	  (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1444			     (match_operand:VI_HW_QHS 2 "register_operand" "")
1445			     (match_dup 4)]
1446			    UNSPEC_VEC_VFEE))
1447   (set (reg:CCRAW CC_REGNUM)
1448	(unspec:CCRAW [(match_dup 1)
1449		       (match_dup 2)
1450		       (match_dup 4)]
1451		      UNSPEC_VEC_VFEECC))])
1452   (set (match_operand:SI 3 "memory_operand" "")
1453	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1454  "TARGET_VX"
1455{
1456  operands[4] = GEN_INT (VSTRING_FLAG_ZS | VSTRING_FLAG_CS);
1457})
1458
1459; Vector find element not equal
1460
1461; vfeneb, vfeneh, vfenef
1462(define_insn "vfene<mode>"
1463  [(set (match_operand:VI_HW_QHS                    0 "register_operand" "=v")
1464	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "v")
1465			   (match_operand:VI_HW_QHS 2 "register_operand"  "v")
1466			   (const_int 0)]
1467			  UNSPEC_VEC_VFENE))]
1468  "TARGET_VX"
1469  "vfene<bhfgq>\t%v0,%v1,%v2,0"
1470  [(set_attr "op_type" "VRR")])
1471
1472; vec_vfenes can be found in vector.md since it is used for strlen
1473
1474; vfenezb, vfenezh, vfenezf
1475(define_insn "vfenez<mode>"
1476  [(set (match_operand:VI_HW_QHS                    0 "register_operand" "=v")
1477	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"  "v")
1478			   (match_operand:VI_HW_QHS 2 "register_operand"  "v")
1479			   (const_int VSTRING_FLAG_ZS)]
1480			  UNSPEC_VEC_VFENE))]
1481  "TARGET_VX"
1482  "vfenez<bhfgq>\t%v0,%v1,%v2"
1483  [(set_attr "op_type" "VRR")])
1484
1485(define_expand "vfenes<mode>"
1486  [(parallel
1487    [(set (match_operand:VI_HW_QHS                    0 "register_operand" "")
1488	  (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1489			     (match_operand:VI_HW_QHS 2 "register_operand" "")
1490			     (const_int VSTRING_FLAG_CS)]
1491			    UNSPEC_VEC_VFENE))
1492   (set (reg:CCRAW CC_REGNUM)
1493	(unspec:CCRAW [(match_dup 1)
1494		       (match_dup 2)
1495		       (const_int VSTRING_FLAG_CS)]
1496		      UNSPEC_VEC_VFENECC))])
1497   (set (match_operand:SI 3 "memory_operand" "")
1498	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1499  "TARGET_VX")
1500
1501(define_expand "vfenezs<mode>"
1502  [(parallel
1503    [(set (match_operand:VI_HW_QHS                    0 "register_operand" "")
1504	  (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1505			     (match_operand:VI_HW_QHS 2 "register_operand" "")
1506			     (match_dup 4)]
1507			    UNSPEC_VEC_VFENE))
1508     (set (reg:CCRAW CC_REGNUM)
1509	  (unspec:CCRAW [(match_dup 1)
1510			 (match_dup 2)
1511			 (match_dup 4)]
1512			UNSPEC_VEC_VFENECC))])
1513   (set (match_operand:SI 3 "memory_operand" "")
1514	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1515  "TARGET_VX"
1516{
1517  operands[4] = GEN_INT (VSTRING_FLAG_ZS | VSTRING_FLAG_CS);
1518})
1519
1520; Vector isolate string
1521
1522; vistrb, vistrh, vistrf
1523(define_insn "vistr<mode>"
1524  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1525	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")]
1526			  UNSPEC_VEC_VISTR))]
1527  "TARGET_VX"
1528  "vistr<bhfgq>\t%v0,%v1"
1529  [(set_attr "op_type" "VRR")])
1530
1531; vistrbs, vistrhs, vistrfs
1532(define_insn "*vistrs<mode>"
1533  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1534	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")]
1535			  UNSPEC_VEC_VISTR))
1536   (set (reg:CCRAW CC_REGNUM)
1537	(unspec:CCRAW [(match_dup 1)] UNSPEC_VEC_VISTRCC))]
1538  "TARGET_VX"
1539  "vistr<bhfgq>s\t%v0,%v1"
1540  [(set_attr "op_type" "VRR")])
1541
1542(define_expand "vistrs<mode>"
1543  [(parallel
1544    [(set (match_operand:VI_HW_QHS                    0 "register_operand" "")
1545	  (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")]
1546			    UNSPEC_VEC_VISTR))
1547     (set (reg:CCRAW CC_REGNUM)
1548	  (unspec:CCRAW [(match_dup 1)]
1549			UNSPEC_VEC_VISTRCC))])
1550   (set (match_operand:SI 2 "memory_operand" "")
1551	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1552  "TARGET_VX")
1553
1554
1555; Vector compare range
1556
1557; vstrcb, vstrch, vstrcf
1558; vstrczb, vstrczh, vstrczf
1559(define_insn "vstrc<mode>"
1560  [(set (match_operand:VI_HW_QHS                    0 "register_operand"  "=v")
1561	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"   "v")
1562			   (match_operand:VI_HW_QHS 2 "register_operand"   "v")
1563			   (match_operand:VI_HW_QHS 3 "register_operand"   "v")
1564			   (match_operand:QI        4 "const_mask_operand" "C")]
1565			  UNSPEC_VEC_VSTRC))]
1566  "TARGET_VX"
1567{
1568  unsigned HOST_WIDE_INT flags = UINTVAL (operands[4]);
1569
1570  if (flags & VSTRING_FLAG_ZS)
1571    {
1572      flags &= ~VSTRING_FLAG_ZS;
1573      operands[4] = GEN_INT (flags);
1574      return "vstrcz<bhfgq>\t%v0,%v1,%v2,%v3,%b4";
1575    }
1576  return "vstrc<bhfgq>\t%v0,%v1,%v2,%v3,%b4";
1577}
1578[(set_attr "op_type" "VRR")])
1579
1580; vstrcbs, vstrchs, vstrcfs
1581; vstrczbs, vstrczhs, vstrczfs
1582(define_insn "*vstrcs<mode>"
1583  [(set (match_operand:VI_HW_QHS                    0 "register_operand"  "=v")
1584	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"   "v")
1585			   (match_operand:VI_HW_QHS 2 "register_operand"   "v")
1586			   (match_operand:VI_HW_QHS 3 "register_operand"   "v")
1587			   (match_operand:QI        4 "const_mask_operand" "C")]
1588			  UNSPEC_VEC_VSTRC))
1589   (set (reg:CCRAW CC_REGNUM)
1590	(unspec:CCRAW [(match_dup 1)
1591		       (match_dup 2)
1592		       (match_dup 3)
1593		       (match_dup 4)]
1594		      UNSPEC_VEC_VSTRCCC))]
1595  "TARGET_VX"
1596{
1597  unsigned HOST_WIDE_INT flags = UINTVAL (operands[4]);
1598
1599  if (flags & VSTRING_FLAG_ZS)
1600    {
1601      flags &= ~VSTRING_FLAG_ZS;
1602      operands[4] = GEN_INT (flags);
1603      return "vstrcz<bhfgq>s\t%v0,%v1,%v2,%v3,%b4";
1604    }
1605  return "vstrc<bhfgq>s\t%v0,%v1,%v2,%v3,%b4";
1606}
1607  [(set_attr "op_type" "VRR")])
1608
1609(define_expand "vstrcz<mode>"
1610  [(set (match_operand:VI_HW_QHS 0 "register_operand" "")
1611	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand"   "")
1612			   (match_operand:VI_HW_QHS 2 "register_operand"   "")
1613			   (match_operand:VI_HW_QHS 3 "register_operand"   "")
1614			   (match_operand:QI        4 "const_mask_operand" "")]
1615			  UNSPEC_VEC_VSTRC))]
1616  "TARGET_VX"
1617{
1618  operands[4] = GEN_INT (INTVAL (operands[4]) | VSTRING_FLAG_ZS);
1619})
1620
1621(define_expand "vstrcs<mode>"
1622  [(parallel
1623    [(set (match_operand:VI_HW_QHS 0 "register_operand" "")
1624	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1625			   (match_operand:VI_HW_QHS 2 "register_operand" "")
1626			   (match_operand:VI_HW_QHS 3 "register_operand" "")
1627			   (match_operand:QI        4 "const_mask_operand" "")]
1628			  UNSPEC_VEC_VSTRC))
1629   (set (reg:CCRAW CC_REGNUM)
1630	(unspec:CCRAW [(match_dup 1)
1631		       (match_dup 2)
1632		       (match_dup 3)
1633		       (match_dup 4)]
1634		      UNSPEC_VEC_VSTRCCC))])
1635   (set (match_operand:SI 5 "memory_operand" "")
1636	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1637  "TARGET_VX"
1638{
1639  operands[4] = GEN_INT (INTVAL (operands[4]) | VSTRING_FLAG_CS);
1640})
1641
1642(define_expand "vstrczs<mode>"
1643  [(parallel
1644    [(set (match_operand:VI_HW_QHS 0 "register_operand" "")
1645	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "")
1646			   (match_operand:VI_HW_QHS 2 "register_operand" "")
1647			   (match_operand:VI_HW_QHS 3 "register_operand" "")
1648			   (match_operand:QI        4 "const_mask_operand" "")]
1649			  UNSPEC_VEC_VSTRC))
1650   (set (reg:CCRAW CC_REGNUM)
1651	(unspec:CCRAW [(match_dup 1)
1652		       (match_dup 2)
1653		       (match_dup 3)
1654		       (match_dup 4)]
1655		      UNSPEC_VEC_VSTRCCC))])
1656   (set (match_operand:SI 5 "memory_operand" "")
1657	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1658  "TARGET_VX"
1659{
1660  operands[4] = GEN_INT (INTVAL (operands[4]) | VSTRING_FLAG_CS | VSTRING_FLAG_ZS);
1661})
1662
1663; Vector string search
1664
1665(define_expand "vstrs<mode>"
1666  [(parallel
1667    [(set (match_operand:V16QI                    0 "register_operand" "")
1668	  (unspec:V16QI [(match_operand:VI_HW_QHS 1 "register_operand" "")
1669			 (match_operand:VI_HW_QHS 2 "register_operand" "")
1670			 (match_operand:V16QI     3 "register_operand" "")
1671			 (const_int 0)]
1672			UNSPEC_VEC_VSTRS))
1673     (set (reg:CCRAW CC_REGNUM)
1674	  (unspec:CCRAW [(match_dup 1)
1675			 (match_dup 2)
1676			 (match_dup 3)
1677			 (const_int 0)]
1678			UNSPEC_VEC_VSTRSCC))])
1679   (set (match_operand:SI 4 "memory_operand" "")
1680	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1681  "TARGET_VXE2")
1682
1683(define_expand "vstrsz<mode>"
1684  [(parallel
1685    [(set (match_operand:V16QI                    0 "register_operand" "")
1686	  (unspec:V16QI [(match_operand:VI_HW_QHS 1 "register_operand" "")
1687			 (match_operand:VI_HW_QHS 2 "register_operand" "")
1688			 (match_operand:V16QI     3 "register_operand" "")
1689			 (const_int VSTRING_FLAG_ZS)]
1690			UNSPEC_VEC_VSTRS))
1691     (set (reg:CCRAW CC_REGNUM)
1692	  (unspec:CCRAW [(match_dup 1)
1693			 (match_dup 2)
1694			 (match_dup 3)
1695			 (const_int VSTRING_FLAG_ZS)]
1696			UNSPEC_VEC_VSTRSCC))])
1697   (set (match_operand:SI 4 "memory_operand" "")
1698	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1699  "TARGET_VXE2")
1700
1701; vstrsb, vstrsh, vstrsf
1702; vstrszb, vstrszh, vstrszf
1703(define_insn "vec_vstrs<mode>"
1704  [(set (match_operand:V16QI                    0 "register_operand" "=v")
1705	(unspec:V16QI [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1706		       (match_operand:VI_HW_QHS 2 "register_operand" "v")
1707		       (match_operand:V16QI     3 "register_operand" "v")
1708		       (match_operand:QI        4 "const_mask_operand" "C")]
1709		      UNSPEC_VEC_VSTRS))
1710   (set (reg:CCRAW CC_REGNUM)
1711	(unspec:CCRAW [(match_dup 1)
1712		       (match_dup 2)
1713		       (match_dup 3)
1714		       (match_dup 4)]
1715		      UNSPEC_VEC_VSTRSCC))]
1716  "TARGET_VXE2"
1717{
1718  unsigned HOST_WIDE_INT flags = UINTVAL (operands[4]);
1719
1720  gcc_assert (!(flags & ~VSTRING_FLAG_ZS));
1721
1722  if (flags == VSTRING_FLAG_ZS)
1723    return "vstrsz<bhfgq>\t%v0,%v1,%v2,%v3";
1724  return "vstrs<bhfgq>\t%v0,%v1,%v2,%v3";
1725}
1726  [(set_attr "op_type" "VRR")])
1727
1728
1729; Vector convert int<->float
1730
1731(define_insn "vcdgb"
1732  [(set (match_operand:V2DF 0 "register_operand"                "=v")
1733	(unspec:V2DF [(match_operand:V2DI 1 "register_operand"   "v")
1734		      (match_operand:QI   2 "const_mask_operand" "C")  ; inexact suppression
1735		      (match_operand:QI   3 "const_mask_operand" "C")] ; rounding mode
1736		     UNSPEC_VEC_VCDGB))]
1737  "TARGET_VX && UINTVAL (operands[3]) != 2 && UINTVAL (operands[3]) <= 7"
1738  "vcdgb\t%v0,%v1,%b2,%b3"
1739  [(set_attr "op_type" "VRR")])
1740
1741
1742; The result needs to be multiplied with 2**-op2
1743(define_expand "vec_ctd_s64"
1744  [(set (match_operand:V2DF               0 "register_operand" "")
1745	(unspec:V2DF [(match_operand:V2DI 1 "register_operand" "")
1746		      (const_int VEC_NOINEXACT)
1747		      (const_int VEC_RND_CURRENT)]
1748		     UNSPEC_VEC_VCDGB))
1749   (use (match_operand:QI 2 "const_int_operand" ""))
1750   (set (match_dup 0) (mult:V2DF (match_dup 0) (match_dup 3)))]
1751  "TARGET_VX"
1752{
1753  REAL_VALUE_TYPE f;
1754  rtx c;
1755
1756  real_2expN (&f, -INTVAL (operands[2]), DFmode);
1757  c = const_double_from_real_value (f, DFmode);
1758
1759  operands[3] = gen_const_vec_duplicate (V2DFmode, c);
1760  operands[3] = force_reg (V2DFmode, operands[3]);
1761})
1762
1763(define_insn "vcdlgb"
1764  [(set (match_operand:V2DF 0 "register_operand"                 "=v")
1765	(unspec:V2DF [(match_operand:V2DI 1 "register_operand"    "v")
1766		      (match_operand:QI   2 "const_mask_operand"  "C")  ; inexact suppression
1767		      (match_operand:QI   3 "const_mask_operand"  "C")] ; rounding mode
1768		     UNSPEC_VEC_VCDLGB))]
1769  "TARGET_VX && UINTVAL (operands[3]) != 2 && UINTVAL (operands[3]) <= 7"
1770  "vcdlgb\t%v0,%v1,%b2,%b3"
1771  [(set_attr "op_type" "VRR")])
1772
1773; The result needs to be multiplied with 2**-op2
1774(define_expand "vec_ctd_u64"
1775  [(set (match_operand:V2DF               0 "register_operand" "")
1776	(unspec:V2DF [(match_operand:V2DI 1 "register_operand" "")
1777		      (const_int VEC_NOINEXACT)
1778		      (const_int VEC_RND_CURRENT)]
1779		     UNSPEC_VEC_VCDLGB))
1780   (use (match_operand:QI 2 "const_int_operand" ""))
1781   (set (match_dup 0) (mult:V2DF (match_dup 0) (match_dup 3)))]
1782  "TARGET_VX"
1783{
1784  REAL_VALUE_TYPE f;
1785  rtx c;
1786
1787  real_2expN (&f, -INTVAL (operands[2]), DFmode);
1788  c = const_double_from_real_value (f, DFmode);
1789
1790  operands[3] = gen_const_vec_duplicate (V2DFmode, c);
1791  operands[3] = force_reg (V2DFmode, operands[3]);
1792})
1793
1794(define_insn "vcgdb"
1795  [(set (match_operand:V2DI 0 "register_operand"                "=v")
1796	(unspec:V2DI [(match_operand:V2DF 1 "register_operand"   "v")
1797		      (match_operand:QI   2 "const_mask_operand" "C")
1798		      (match_operand:QI   3 "const_mask_operand" "C")]
1799		     UNSPEC_VEC_VCGDB))]
1800  "TARGET_VX && UINTVAL (operands[3]) != 2 && UINTVAL (operands[3]) <= 7"
1801  "vcgdb\t%v0,%v1,%b2,%b3"
1802  [(set_attr "op_type" "VRR")])
1803
1804; The input needs to be multiplied with 2**op2
1805(define_expand "vec_ctsl"
1806  [(use (match_operand:QI 2 "const_int_operand" ""))
1807   (set (match_dup 4) (mult:V2DF (match_operand:V2DF 1 "register_operand" "")
1808				 (match_dup 3)))
1809   (set (match_operand:V2DI 0 "register_operand" "")
1810	(unspec:V2DI [(match_dup 4)
1811		      (const_int VEC_NOINEXACT)
1812		      (const_int VEC_RND_CURRENT)]
1813		     UNSPEC_VEC_VCGDB))]
1814  "TARGET_VX"
1815{
1816  REAL_VALUE_TYPE f;
1817  rtx c;
1818
1819  real_2expN (&f, INTVAL (operands[2]), DFmode);
1820  c = const_double_from_real_value (f, DFmode);
1821
1822  operands[3] = gen_const_vec_duplicate (V2DFmode, c);
1823  operands[3] = force_reg (V2DFmode, operands[3]);
1824  operands[4] = gen_reg_rtx (V2DFmode);
1825})
1826
1827(define_insn "vclgdb"
1828  [(set (match_operand:V2DI 0 "register_operand"               "=v")
1829	(unspec:V2DI [(match_operand:V2DF 1 "register_operand"  "v")
1830		      (match_operand:QI   2 "const_mask_operand" "C")
1831		      (match_operand:QI   3 "const_mask_operand" "C")]
1832		     UNSPEC_VEC_VCLGDB))]
1833  "TARGET_VX && UINTVAL (operands[3]) != 2 && UINTVAL (operands[3]) <= 7"
1834  "vclgdb\t%v0,%v1,%b2,%b3"
1835  [(set_attr "op_type" "VRR")])
1836
1837; The input needs to be multiplied with 2**op2
1838(define_expand "vec_ctul"
1839  [(use (match_operand:QI 2 "const_int_operand" ""))
1840   (set (match_dup 4) (mult:V2DF (match_operand:V2DF 1 "register_operand" "")
1841				 (match_dup 3)))
1842   (set (match_operand:V2DI 0 "register_operand" "")
1843	(unspec:V2DI [(match_dup 4)
1844		      (const_int VEC_NOINEXACT)
1845		      (const_int VEC_RND_CURRENT)]
1846		     UNSPEC_VEC_VCLGDB))]
1847  "TARGET_VX"
1848{
1849  REAL_VALUE_TYPE f;
1850  rtx c;
1851
1852  real_2expN (&f, INTVAL (operands[2]), DFmode);
1853  c = const_double_from_real_value (f, DFmode);
1854
1855  operands[3] = gen_const_vec_duplicate (V2DFmode, c);
1856  operands[3] = force_reg (V2DFmode, operands[3]);
1857  operands[4] = gen_reg_rtx (V2DFmode);
1858})
1859
1860; Vector load fp integer - IEEE inexact exception is suppressed
1861; vfisb, vfidb, wfisb, wfidb, wfixb
1862(define_insn "vec_fpint<mode>"
1863  [(set (match_operand:VFT              0 "register_operand"  "=v")
1864	(unspec:VFT [(match_operand:VFT 1 "register_operand"   "v")
1865		     (match_operand:QI  2 "const_mask_operand" "C")  ; inexact suppression control
1866		     (match_operand:QI  3 "const_mask_operand" "C")] ; rounding mode
1867		     UNSPEC_VEC_VFI))]
1868  "TARGET_VX"
1869  "<vw>fi<sdx>b\t%v0,%v1,%b2,%b3"
1870  [(set_attr "op_type" "VRR")])
1871
1872
1873; Vector load lengthened - V4SF -> V2DF
1874
1875(define_insn "vflls"
1876  [(set (match_operand:V2DF 0 "register_operand"               "=v")
1877	(unspec:V2DF [(match_operand:V4SF 1 "register_operand"  "v")]
1878		     UNSPEC_VEC_VFLL))]
1879  "TARGET_VX"
1880  "vldeb\t%v0,%v1"
1881  [(set_attr "op_type" "VRR")])
1882
1883(define_expand "vec_ld2f"
1884  [; Initialize a vector to all zeroes.  FIXME: This should not be
1885   ; necessary since all elements of the vector will be set anyway.
1886   ; This is just to make it explicit to the data flow framework.
1887   (set (match_dup 2) (match_dup 3))
1888   (set (match_dup 2) (unspec:V4SF [(match_operand:SF 1 "memory_operand" "")
1889				    (const_int 0)
1890				    (match_dup 2)]
1891				    UNSPEC_VEC_SET))
1892   (set (match_dup 2) (unspec:V4SF [(match_dup 4)
1893				    (const_int 2)
1894				    (match_dup 2)]
1895				    UNSPEC_VEC_SET))
1896   (set (match_operand:V2DF 0 "register_operand" "")
1897	(unspec:V2DF [(match_dup 2)] UNSPEC_VEC_VFLL))]
1898  "TARGET_VX"
1899{
1900  operands[2] = gen_reg_rtx (V4SFmode);
1901  operands[3] = CONST0_RTX (V4SFmode);
1902  operands[4] = adjust_address (operands[1], SFmode, 4);
1903})
1904
1905
1906; Vector load rounded - V2DF -> V4SF
1907
1908(define_insn "vflrd"
1909  [(set (match_operand:V4SF 0 "register_operand"                "=v")
1910	(unspec:V4SF [(match_operand:V2DF 1 "register_operand"   "v")
1911		      (match_operand:QI   2 "const_mask_operand" "C")
1912		      (match_operand:QI   3 "const_mask_operand" "C")]
1913		     UNSPEC_VEC_VFLR))]
1914  "TARGET_VX"
1915  "vledb\t%v0,%v1,%b2,%b3"
1916  [(set_attr "op_type" "VRR")])
1917
1918(define_expand "vec_st2f"
1919  [(set (match_dup 2)
1920	(unspec:V4SF [(match_operand:V2DF 0 "register_operand" "")
1921		      (const_int VEC_INEXACT)
1922		      (const_int VEC_RND_CURRENT)]
1923		     UNSPEC_VEC_VFLR))
1924   (set (match_operand:SF 1 "memory_operand" "")
1925	(unspec:SF [(match_dup 2) (const_int 0)] UNSPEC_VEC_EXTRACT))
1926   (set (match_dup 3)
1927	(unspec:SF [(match_dup 2) (const_int 2)] UNSPEC_VEC_EXTRACT))]
1928  "TARGET_VX"
1929{
1930  operands[2] = gen_reg_rtx (V4SFmode);
1931  operands[3] = adjust_address (operands[1], SFmode, 4);
1932})
1933
1934
1935; Vector square root fp vec_sqrt -> sqrt rtx standard name
1936
1937;; Vector FP test data class immediate
1938
1939; vec_all_nan, vec_all_numeric, vec_any_nan, vec_any_numeric
1940; These ignore the vector result and only want CC stored to an int
1941; pointer.
1942
1943; vftcisb, vftcidb
1944(define_insn "*vftci<mode>_cconly"
1945  [(set (reg:CCRAW CC_REGNUM)
1946	(unspec:CCRAW [(match_operand:VECF_HW 1 "register_operand")
1947		       (match_operand:HI      2 "const_int_operand")]
1948		      UNSPEC_VEC_VFTCICC))
1949   (clobber (match_scratch:<tointvec> 0))]
1950  "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
1951  "vftci<sdx>b\t%v0,%v1,%x2"
1952  [(set_attr "op_type" "VRR")])
1953
1954(define_expand "vftci<mode>_intcconly"
1955  [(parallel
1956    [(set (reg:CCRAW CC_REGNUM)
1957	  (unspec:CCRAW [(match_operand:VECF_HW 0 "register_operand")
1958			 (match_operand:HI      1 "const_int_operand")]
1959			UNSPEC_VEC_VFTCICC))
1960     (clobber (scratch:<tointvec>))])
1961   (set (match_operand:SI 2 "register_operand" "")
1962	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1963  "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'J', \"J\")")
1964
1965; vec_fp_test_data_class wants the result vector and the CC stored to
1966; an int pointer.
1967
1968; vftcisb, vftcidb
1969(define_insn "*vftci<mode>"
1970  [(set (match_operand:VECF_HW                  0 "register_operand"  "=v")
1971	(unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand"   "v")
1972			 (match_operand:HI      2 "const_int_operand"  "J")]
1973			UNSPEC_VEC_VFTCI))
1974   (set (reg:CCRAW CC_REGNUM)
1975	(unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))]
1976  "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
1977  "vftci<sdx>b\t%v0,%v1,%x2"
1978  [(set_attr "op_type" "VRR")])
1979
1980(define_expand "vftci<mode>_intcc"
1981  [(parallel
1982    [(set (match_operand:VECF_HW                  0 "register_operand")
1983	  (unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand")
1984			   (match_operand:HI      2 "const_int_operand")]
1985			  UNSPEC_VEC_VFTCI))
1986     (set (reg:CCRAW CC_REGNUM)
1987	  (unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))])
1988   (set (match_operand:SI 3 "memory_operand" "")
1989	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
1990  "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")")
1991
1992;;
1993;; Integer compares
1994;;
1995
1996; All comparisons which produce a CC need fully populated (VI_HW)
1997; vector arguments.  Otherwise the any/all CCs would be just bogus.
1998
1999(define_insn "*vec_cmp<VICMP:insn_cmp><VI_HW:mode>_cconly"
2000  [(set (reg:VICMP CC_REGNUM)
2001	(compare:VICMP (match_operand:VI_HW 0 "register_operand" "v")
2002		       (match_operand:VI_HW 1 "register_operand" "v")))
2003   (clobber (match_scratch:VI_HW 2 "=v"))]
2004  "TARGET_VX"
2005  "vc<VICMP:insn_cmp><VI_HW:bhfgq>s\t%v2,%v0,%v1"
2006  [(set_attr "op_type" "VRR")])
2007
2008; FIXME: The following 2x3 definitions should be merged into 2 with
2009; VICMP like above but I could not find a way to set the comparison
2010; operator (eq) depending on the mode CCVEQ (mode_iterator). Or the
2011; other way around - setting the mode depending on the code
2012; (code_iterator).
2013(define_expand "vec_cmpeq<VI_HW:mode>_cc"
2014  [(parallel
2015    [(set (reg:CCVEQ CC_REGNUM)
2016	(compare:CCVEQ (match_operand:VI_HW 1 "register_operand" "v")
2017		       (match_operand:VI_HW 2 "register_operand" "v")))
2018     (set (match_operand:VI_HW 0 "register_operand" "=v")
2019	  (eq:VI_HW (match_dup 1) (match_dup 2)))])
2020   (set (match_operand:SI 3 "memory_operand" "")
2021	(unspec:SI [(reg:CCVEQ CC_REGNUM)] UNSPEC_CC_TO_INT))]
2022  "TARGET_VX")
2023
2024(define_expand "vec_cmph<VI_HW:mode>_cc"
2025  [(parallel
2026    [(set (reg:CCVIH CC_REGNUM)
2027	  (compare:CCVIH (match_operand:VI_HW 1 "register_operand" "v")
2028			 (match_operand:VI_HW 2 "register_operand" "v")))
2029     (set (match_operand:VI_HW 0 "register_operand" "=v")
2030	  (gt:VI_HW (match_dup 1) (match_dup 2)))])
2031   (set (match_operand:SI 3 "memory_operand" "")
2032	(unspec:SI [(reg:CCVIH CC_REGNUM)] UNSPEC_CC_TO_INT))]
2033  "TARGET_VX")
2034
2035(define_expand "vec_cmphl<VI_HW:mode>_cc"
2036  [(parallel
2037    [(set (reg:CCVIHU CC_REGNUM)
2038	  (compare:CCVIHU (match_operand:VI_HW 1 "register_operand" "v")
2039			  (match_operand:VI_HW 2 "register_operand" "v")))
2040     (set (match_operand:VI_HW 0 "register_operand" "=v")
2041	  (gtu:VI_HW (match_dup 1) (match_dup 2)))])
2042   (set (match_operand:SI 3 "memory_operand" "")
2043	(unspec:SI [(reg:CCVIHU CC_REGNUM)] UNSPEC_CC_TO_INT))]
2044  "TARGET_VX")
2045
2046
2047(define_insn "*vec_cmpeq<VI_HW:mode>_cc"
2048  [(set (reg:CCVEQ CC_REGNUM)
2049	(compare:CCVEQ (match_operand:VI_HW 0 "register_operand"  "v")
2050		       (match_operand:VI_HW 1 "register_operand"  "v")))
2051   (set (match_operand:VI_HW                2 "register_operand" "=v")
2052	(eq:VI_HW (match_dup 0) (match_dup 1)))]
2053  "TARGET_VX"
2054  "vceq<VI_HW:bhfgq>s\t%v2,%v0,%v1"
2055  [(set_attr "op_type" "VRR")])
2056
2057(define_insn "*vec_cmph<VI_HW:mode>_cc"
2058  [(set (reg:CCVIH CC_REGNUM)
2059	(compare:CCVIH (match_operand:VI_HW 0 "register_operand"  "v")
2060		       (match_operand:VI_HW 1 "register_operand"  "v")))
2061   (set (match_operand:VI_HW               2 "register_operand" "=v")
2062	(gt:VI_HW (match_dup 0) (match_dup 1)))]
2063  "TARGET_VX"
2064  "vch<VI_HW:bhfgq>s\t%v2,%v0,%v1"
2065  [(set_attr "op_type" "VRR")])
2066
2067(define_insn "*vec_cmphl<VI_HW:mode>_cc"
2068  [(set (reg:CCVIHU CC_REGNUM)
2069	(compare:CCVIHU (match_operand:VI_HW 0 "register_operand"  "v")
2070			(match_operand:VI_HW 1 "register_operand"  "v")))
2071   (set (match_operand:VI_HW                2 "register_operand" "=v")
2072	(gtu:VI_HW (match_dup 0) (match_dup 1)))]
2073  "TARGET_VX"
2074  "vchl<VI_HW:bhfgq>s\t%v2,%v0,%v1"
2075  [(set_attr "op_type" "VRR")])
2076
2077;;
2078;; Floating point compares
2079;;
2080
2081; vfcesbs, vfcedbs, wfcexbs, vfchsbs, vfchdbs, wfchxbs, vfchesbs, vfchedbs, wfchexbs
2082(define_insn "*vec_cmp<insn_cmp><VF_HW:mode>_cconly"
2083  [(set (reg:VFCMP CC_REGNUM)
2084	(compare:VFCMP (match_operand:VF_HW 0 "register_operand" "v")
2085		       (match_operand:VF_HW 1 "register_operand" "v")))
2086   (clobber (match_scratch:<tointvec> 2 "=v"))]
2087  "TARGET_VX"
2088  "<vw>fc<asm_fcmp><sdx>bs\t%v2,%v0,%v1"
2089  [(set_attr "op_type" "VRR")])
2090
2091; FIXME: Merge the following 2x3 patterns with VFCMP
2092(define_expand "vec_cmpeq<mode>_cc"
2093  [(parallel
2094    [(set (reg:CCVEQ CC_REGNUM)
2095	  (compare:CCVEQ (match_operand:VF_HW 1 "register_operand"  "v")
2096			 (match_operand:VF_HW 2 "register_operand"  "v")))
2097     (set (match_operand:<tointvec> 0 "register_operand" "=v")
2098	  (eq:<tointvec> (match_dup 1) (match_dup 2)))])
2099   (set (match_operand:SI 3 "memory_operand" "")
2100	(unspec:SI [(reg:CCVEQ CC_REGNUM)] UNSPEC_CC_TO_INT))]
2101  "TARGET_VX")
2102
2103(define_expand "vec_cmph<mode>_cc"
2104  [(parallel
2105    [(set (reg:CCVFH CC_REGNUM)
2106	  (compare:CCVFH (match_operand:VF_HW 1 "register_operand"  "v")
2107			 (match_operand:VF_HW 2 "register_operand"  "v")))
2108     (set (match_operand:<tointvec> 0 "register_operand" "=v")
2109	  (gt:<tointvec> (match_dup 1) (match_dup 2)))])
2110   (set (match_operand:SI 3 "memory_operand" "")
2111	(unspec:SI [(reg:CCVIH CC_REGNUM)] UNSPEC_CC_TO_INT))]
2112  "TARGET_VX")
2113
2114(define_expand "vec_cmphe<mode>_cc"
2115  [(parallel
2116    [(set (reg:CCVFHE CC_REGNUM)
2117	  (compare:CCVFHE (match_operand:VF_HW 1 "register_operand"  "v")
2118			  (match_operand:VF_HW 2 "register_operand"  "v")))
2119     (set (match_operand:<tointvec> 0 "register_operand" "=v")
2120	  (ge:<tointvec> (match_dup 1) (match_dup 2)))])
2121   (set (match_operand:SI 3 "memory_operand" "")
2122	(unspec:SI [(reg:CCVFHE CC_REGNUM)] UNSPEC_CC_TO_INT))]
2123  "TARGET_VX")
2124
2125; These 3 cannot be merged as the insn defintion above since it also
2126; requires to rewrite the RTL equality operator that the same time as
2127; the CC mode.
2128
2129; vfcesbs, vfcedbs, wfcexbs
2130(define_insn "*vec_cmpeq<mode>_cc"
2131  [(set (reg:CCVEQ CC_REGNUM)
2132	(compare:CCVEQ (match_operand:VF_HW 0 "register_operand"  "v")
2133		       (match_operand:VF_HW 1 "register_operand"  "v")))
2134   (set (match_operand:<tointvec>              2 "register_operand" "=v")
2135	(eq:<tointvec> (match_dup 0) (match_dup 1)))]
2136  "TARGET_VX"
2137  "<vw>fce<sdx>bs\t%v2,%v0,%v1"
2138  [(set_attr "op_type" "VRR")])
2139
2140; vfchsbs, vfchdbs, wfchxbs
2141(define_insn "*vec_cmph<mode>_cc"
2142  [(set (reg:CCVFH CC_REGNUM)
2143	(compare:CCVFH (match_operand:VF_HW 0 "register_operand"  "v")
2144		       (match_operand:VF_HW 1 "register_operand"  "v")))
2145   (set (match_operand:<tointvec>              2 "register_operand" "=v")
2146	(gt:<tointvec> (match_dup 0) (match_dup 1)))]
2147  "TARGET_VX"
2148  "<vw>fch<sdx>bs\t%v2,%v0,%v1"
2149  [(set_attr "op_type" "VRR")])
2150
2151; vfchesbs, vfchedbs, wfchexbs
2152(define_insn "*vec_cmphe<mode>_cc"
2153  [(set (reg:CCVFHE CC_REGNUM)
2154	(compare:CCVFHE (match_operand:VF_HW 0 "register_operand"  "v")
2155			(match_operand:VF_HW 1 "register_operand"  "v")))
2156   (set (match_operand:<tointvec>            2 "register_operand" "=v")
2157	(ge:<tointvec> (match_dup 0) (match_dup 1)))]
2158  "TARGET_VX"
2159  "<vw>fche<sdx>bs\t%v2,%v0,%v1"
2160  [(set_attr "op_type" "VRR")])
2161
2162
2163(define_insn "vfmin<mode>"
2164  [(set (match_operand:VF_HW                0 "register_operand"  "=v")
2165	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"   "v")
2166		       (match_operand:VF_HW 2 "register_operand"   "v")
2167		       (match_operand:QI    3 "const_mask_operand" "C")]
2168		      UNSPEC_VEC_VFMIN))]
2169  "TARGET_VXE"
2170  "<vw>fmin<sdx>b\t%v0,%v1,%v2,%b3"
2171  [(set_attr "op_type" "VRR")])
2172
2173(define_insn "vfmax<mode>"
2174  [(set (match_operand:VF_HW                0 "register_operand"  "=v")
2175	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"   "v")
2176		       (match_operand:VF_HW 2 "register_operand"   "v")
2177		       (match_operand:QI    3 "const_mask_operand" "C")]
2178		      UNSPEC_VEC_VFMAX))]
2179  "TARGET_VXE"
2180  "<vw>fmax<sdx>b\t%v0,%v1,%v2,%b3"
2181  [(set_attr "op_type" "VRR")])
2182
2183; The element reversal builtins introduced with z15 have been made
2184; available also for older CPUs down to z13.
2185(define_expand "eltswap<mode>"
2186  [(set (match_operand:VEC_HW                 0 "nonimmediate_operand" "")
2187	(unspec:VEC_HW [(match_operand:VEC_HW 1 "nonimmediate_operand" "")]
2188		       UNSPEC_VEC_ELTSWAP))]
2189  "TARGET_VX")
2190
2191; The byte element reversal is implemented as 128 bit byte swap.
2192; Alternatively this could be emitted as bswap:V1TI but the required
2193; subregs appear to confuse combine.
2194(define_insn "*eltswapv16qi"
2195  [(set (match_operand:V16QI                0 "nonimmediate_operand" "=v,v,R")
2196	(unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand"  "v,R,v")]
2197		      UNSPEC_VEC_ELTSWAP))]
2198  "TARGET_VXE2"
2199  "@
2200   #
2201   vlbrq\t%v0,%v1
2202   vstbrq\t%v1,%v0"
2203  [(set_attr "op_type" "*,VRX,VRX")])
2204
2205; vlerh, vlerf, vlerg, vsterh, vsterf, vsterg
2206(define_insn "*eltswap<mode>"
2207  [(set (match_operand:V_HW_HSD                   0 "nonimmediate_operand" "=v,v,R")
2208	(unspec:V_HW_HSD [(match_operand:V_HW_HSD 1 "nonimmediate_operand"  "v,R,v")]
2209			 UNSPEC_VEC_ELTSWAP))]
2210  "TARGET_VXE2"
2211  "@
2212   #
2213   vler<bhfgq>\t%v0,%v1
2214   vster<bhfgq>\t%v1,%v0"
2215  [(set_attr "op_type" "*,VRX,VRX")])
2216
2217; z15 has instructions for doing element reversal from mem to reg
2218; or the other way around.  For reg to reg or on pre z15 machines
2219; we have to emulate it with vector permute.
2220(define_insn_and_split "*eltswap<mode>_emu"
2221  [(set (match_operand:VEC_HW                 0 "nonimmediate_operand" "=vR")
2222	(unspec:VEC_HW [(match_operand:VEC_HW 1 "nonimmediate_operand" "vR")]
2223		       UNSPEC_VEC_ELTSWAP))]
2224  "TARGET_VX && can_create_pseudo_p ()"
2225  "#"
2226  "&& ((!memory_operand (operands[0], <MODE>mode)
2227        && !memory_operand (operands[1], <MODE>mode))
2228       || !TARGET_VXE2)"
2229  [(set (match_dup 3)
2230	(unspec:V16QI [(match_dup 4)
2231		       (match_dup 4)
2232		       (match_dup 2)]
2233		      UNSPEC_VEC_PERM))
2234   (set (match_dup 0) (subreg:VEC_HW (match_dup 3) 0))]
2235{
2236  static char p[4][16] =
2237    { { 15, 14, 13, 12, 11, 10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0 },   /* Q */
2238      { 14, 15, 12, 13, 10, 11, 8,  9,  6,  7,  4,  5,  2,  3,  0,  1 },   /* H */
2239      { 12, 13, 14, 15, 8,  9,  10, 11, 4,  5,  6,  7,  0,  1,  2,  3 },   /* S */
2240      { 8,  9,  10, 11, 12, 13, 14, 15, 0,  1,  2,  3,  4,  5,  6,  7 } }; /* D */
2241  char *perm;
2242  rtx perm_rtx[16], constv;
2243
2244  switch (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)))
2245    {
2246    case 1: perm = p[0]; break;
2247    case 2: perm = p[1]; break;
2248    case 4: perm = p[2]; break;
2249    case 8: perm = p[3]; break;
2250    default: gcc_unreachable ();
2251    }
2252
2253  for (int i = 0; i < 16; i++)
2254    perm_rtx[i] = GEN_INT (perm[i]);
2255
2256  operands[1] = force_reg (<MODE>mode, operands[1]);
2257  operands[2] = gen_reg_rtx (V16QImode);
2258  operands[3] = gen_reg_rtx (V16QImode);
2259  operands[4] = simplify_gen_subreg (V16QImode, operands[1], <MODE>mode, 0);
2260  constv = force_const_mem (V16QImode, gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm_rtx)));
2261  emit_move_insn (operands[2], constv);
2262})
2263
2264; vec_insert (__builtin_bswap32 (*a), b, 1)        set-element-bswap-2.c
2265; b[1] = __builtin_bswap32 (*a)                    set-element-bswap-3.c
2266; vlebrh, vlebrf, vlebrg
2267(define_insn "*vec_set_bswap_elem<mode>"
2268  [(set (match_operand:V_HW_HSD                                     0 "register_operand" "=v")
2269	(unspec:V_HW_HSD [(bswap:<non_vec> (match_operand:<non_vec> 1 "memory_operand"    "R"))
2270		                           (match_operand:SI        2 "const_int_operand" "C")
2271					   (match_operand:V_HW_HSD  3 "register_operand"  "0")]
2272		  UNSPEC_VEC_SET))]
2273  "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)"
2274  "vlebr<bhfgq>\t%v0,%1,%2"
2275  [(set_attr "op_type" "VRX")])
2276
2277; vec_revb (vec_insert (*a, vec_revb (b), 1))      set-element-bswap-1.c
2278; vlebrh, vlebrf, vlebrg
2279(define_insn "*vec_set_bswap_vec<mode>"
2280  [(set (match_operand:V_HW_HSD                                     0 "register_operand"       "=v")
2281	(bswap:V_HW_HSD
2282	 (unspec:V_HW_HSD [(match_operand:<non_vec>                 1 "memory_operand"          "R")
2283		           (match_operand:SI                        2 "const_int_operand"       "C")
2284			   (bswap:V_HW_HSD (match_operand:V_HW_HSD  3 "register_operand"        "0"))]
2285			  UNSPEC_VEC_SET)))
2286   (use (match_operand:V16QI                                        4 "permute_pattern_operand" "X"))]
2287  "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)"
2288  "vlebr<bhfgq>\t%v0,%1,%2"
2289  [(set_attr "op_type" "VRX")])
2290
2291; *a = vec_extract (vec_revb (b), 1);              get-element-bswap-3.c
2292; *a = vec_revb (b)[1];                            get-element-bswap-4.c
2293; vstebrh, vstebrf, vstebrg
2294(define_insn "*vec_extract_bswap_vec<mode>"
2295  [(set (match_operand:<non_vec>                                    0 "memory_operand"   "=R")
2296	(unspec:<non_vec> [(bswap:V_HW_HSD (match_operand:V_HW_HSD  1 "register_operand"  "v"))
2297			   (match_operand:SI                        2 "const_int_operand" "C")]
2298			   UNSPEC_VEC_EXTRACT))]
2299  "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)"
2300  "vstebr<bhfgq>\t%v1,%0,%2"
2301  [(set_attr "op_type" "VRX")])
2302
2303; *a = __builtin_bswap32 (vec_extract (b, 1));     get-element-bswap-1.c
2304; *a = __builtin_bswap32 (b[1]);                   get-element-bswap-2.c
2305; vstebrh, vstebrf, vstebrg
2306(define_insn "*vec_extract_bswap_elem<mode>"
2307  [(set (match_operand:<non_vec>                     0 "memory_operand"   "=R")
2308	(bswap:<non_vec>
2309	 (unspec:<non_vec> [(match_operand:V_HW_HSD  1 "register_operand"  "v")
2310			    (match_operand:SI        2 "const_int_operand" "C")]
2311			   UNSPEC_VEC_EXTRACT)))]
2312  "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)"
2313  "vstebr<bhfgq>\t%v1,%0,%2"
2314  [(set_attr "op_type" "VRX")])
2315