1;;- Instruction patterns for the System z vector facility
2;;  Copyright (C) 2015-2021 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; All vector modes supported in a vector register
22(define_mode_iterator V
23  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
24   V2SF V4SF V1DF V2DF])
25(define_mode_iterator VT
26  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
27   V2SF V4SF V1DF V2DF V1TF V1TI TI])
28
29; All modes directly supported by the hardware having full vector reg size
30; V_HW2 is for having two iterators expanding independently e.g. vcond.
31; It's similar to V_HW, but not fully identical: V1TI is not included, because
32; there are no 128-bit compares.
33(define_mode_iterator V_HW  [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF
34			     (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")
35			     (TF "TARGET_VXE")])
36(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE")
37			     (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
38
39(define_mode_iterator VT_HW_HSDT [V8HI V4SI V4SF V2DI V2DF V1TI V1TF TI TF])
40(define_mode_iterator V_HW_HSD [V8HI V4SI (V4SF "TARGET_VXE") V2DI V2DF])
41
42; Including TI for instructions that support it (va, vn, ...)
43(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
44
45; All full size integer vector modes supported in a vector register + TImode
46(define_mode_iterator VIT_HW    [V16QI V8HI V4SI V2DI V1TI TI])
47(define_mode_iterator VI_HW     [V16QI V8HI V4SI V2DI])
48(define_mode_iterator VI_HW_QHS [V16QI V8HI V4SI])
49(define_mode_iterator VI_HW_HSD [V8HI  V4SI V2DI])
50(define_mode_iterator VI_HW_HS  [V8HI  V4SI])
51(define_mode_iterator VI_HW_QH  [V16QI V8HI])
52
53; Directly supported vector modes with a certain number of elements
54(define_mode_iterator V_HW_2   [V2DI V2DF])
55(define_mode_iterator V_HW_4   [V4SI V4SF])
56
57; All integer vector modes supported in a vector register + TImode
58(define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI])
59(define_mode_iterator VI  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI])
60(define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI])
61
62(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
63			   V1DF V2DF
64			   (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
65
66; FP vector modes directly supported by the HW.  This does not include
67; vector modes using only part of a vector register and should be used
68; for instructions which might trigger IEEE exceptions.
69(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")
70			     (TF "TARGET_VXE")])
71
72(define_mode_iterator V_8   [V1QI])
73(define_mode_iterator V_16  [V2QI  V1HI])
74(define_mode_iterator V_32  [V4QI  V2HI V1SI V1SF])
75(define_mode_iterator V_64  [V8QI  V4HI V2SI V2SF V1DI V1DF])
76(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF
77			     (TF "TARGET_VXE")])
78(define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
79
80; 32 bit int<->fp vector conversion instructions are available since VXE2 (z15).
81(define_mode_iterator VX_VEC_CONV_BFP [V2DF (V4SF "TARGET_VXE2")])
82(define_mode_iterator VX_VEC_CONV_INT [V2DI (V4SI "TARGET_VXE2")])
83
84; Empty string for all but TImode.  This is used to hide the TImode
85; expander name in case it is defined already.  See addti3 for an
86; example.
87(define_mode_attr ti* [(V1QI "")  (V2QI "") (V4QI "") (V8QI "") (V16QI "")
88		       (V1HI "")  (V2HI "") (V4HI "") (V8HI "")
89		       (V1SI "")  (V2SI "") (V4SI "")
90		       (V1DI "")  (V2DI "")
91		       (V1TI "")  (TI "*")
92		       (V1SF "")  (V2SF "") (V4SF "")
93		       (V1DF "")  (V2DF "")
94		       (V1TF "")  (TF "")])
95
96;; Facilitate dispatching TFmode expanders on z14+.
97(define_mode_attr tf_vr [(TF "_vr") (V4SF "") (V2DF "") (V1TF "") (V1SF "")
98			 (V2SF "") (V1DF "") (V16QI "") (V8HI "") (V4SI "")
99			 (V2DI "") (V1TI "")])
100
101; The element type of the vector.
102(define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
103			  (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
104			  (V1SI "SI") (V2SI "SI") (V4SI "SI")
105			  (V1DI "DI") (V2DI "DI")
106			  (V1TI "TI") (TI "TI")
107			  (V1SF "SF") (V2SF "SF") (V4SF "SF")
108			  (V1DF "DF") (V2DF "DF")
109			  (V1TF "TF") (TF "TF")])
110
111; Like above, but in lower case.
112(define_mode_attr non_vec_l[(V1QI "qi") (V2QI "qi") (V4QI "qi") (V8QI "qi")
113			    (V16QI "qi")
114			    (V1HI "hi") (V2HI "hi") (V4HI "hi") (V8HI "hi")
115			    (V1SI "si") (V2SI "si") (V4SI "si")
116			    (V1DI "di") (V2DI "di")
117			    (V1TI "ti") (TI "ti")
118			    (V1SF "sf") (V2SF "sf") (V4SF "sf")
119			    (V1DF "df") (V2DF "df")
120			    (V1TF "tf") (TF "tf")])
121
122; The instruction suffix for integer instructions and instructions
123; which do not care about whether it is floating point or integer.
124(define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b")
125			(V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h")
126			(V1SI "f") (V2SI "f") (V4SI "f")
127			(V1DI "g") (V2DI "g")
128			(V1TI "q") (TI "q")
129			(V1SF "f") (V2SF "f") (V4SF "f")
130			(V1DF "g") (V2DF "g")
131			(V1TF "q")])
132
133; This is for vmalhw. It gets an 'w' attached to avoid confusion with
134; multiply and add logical high vmalh.
135(define_mode_attr w [(V1QI "")  (V2QI "")  (V4QI "")  (V8QI "") (V16QI "")
136		     (V1HI "w") (V2HI "w") (V4HI "w") (V8HI "w")
137		     (V1SI "")  (V2SI "")  (V4SI "")
138		     (V1DI "")  (V2DI "")])
139
140; Resulting mode of a vector comparison.  For floating point modes an
141; integer vector mode with the same element size is picked.
142(define_mode_attr TOINTVEC [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
143			    (V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI")
144			    (V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI")
145			    (V1DI "V1DI") (V2DI "V2DI")
146			    (V1TI "V1TI")
147			    (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
148			    (V1DF "V1DI") (V2DF "V2DI")
149			    (V1TF "V1TI") (TF "V1TI")])
150
151(define_mode_attr tointvec [(V1QI "v1qi") (V2QI "v2qi") (V4QI "v4qi") (V8QI "v8qi") (V16QI "v16qi")
152			    (V1HI "v1hi") (V2HI "v2hi") (V4HI "v4hi") (V8HI "v8hi")
153			    (V1SI "v1si") (V2SI "v2si") (V4SI "v4si")
154			    (V1DI "v1di") (V2DI "v2di")
155			    (V1TI "v1ti")
156			    (V1SF "v1si") (V2SF "v2si") (V4SF "v4si")
157			    (V1DF "v1di") (V2DF "v2di")
158			    (V1TF "v1ti") (TF   "v1ti")])
159
160(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
161		      (DF "w") (V1DF "w") (V2DF "v")
162		      (TF "w") (V1TF "w")])
163
164(define_mode_attr sdx [(SF "s") (V1SF "s") (V2SF "s") (V4SF "s")
165		       (DF "d") (V1DF "d") (V2DF "d")
166		       (TF "x") (V1TF "x")])
167
168; Vector with widened element size but half the number of elements.
169(define_mode_attr vec_double [(V1QI "V1HI") (V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI")
170			      (V1HI "V1SI") (V2HI "V1SI") (V4HI "V2SI") (V8HI "V4SI")
171			      (V1SI "V1DI") (V2SI "V1DI") (V4SI "V2DI")
172			      (V1DI "V1TI") (V2DI "V1TI")
173			      (V1SF "V1DF") (V2SF "V1DF") (V4SF "V2DF")])
174
175; Vector with shrinked element size but twice the number of elements.
176(define_mode_attr vec_half [(V1HI "V2QI") (V2HI "V4QI") (V4HI "V8QI") (V8HI "V16QI")
177			    (V1SI "V2HI") (V2SI "V4HI") (V4SI "V8HI")
178			    (V1DI "V2SI") (V2DI "V4SI")
179			    (V1TI "V2DI")
180			    (V1DF "V2SF") (V2DF "V4SF")
181			    (V1TF "V1DF")])
182
183; Vector with twice the number of elements but same element size.
184(define_mode_attr vec_2x_nelts [(V1QI "V2QI") (V2QI "V4QI") (V4QI "V8QI") (V8QI "V16QI") (V16QI "V32QI")
185				(V1HI "V2HI") (V2HI "V4HI") (V4HI "V8HI") (V8HI "V16HI")
186				(V1SI "V2SI") (V2SI "V4SI") (V4SI "V8SI")
187				(V1DI "V2DI") (V2DI "V4DI")
188				(V1SF "V2SF") (V2SF "V4SF") (V4SF "V8SF")
189				(V1DF "V2DF") (V2DF "V4DF")])
190
191; Vector with widened element size and the same number of elements.
192(define_mode_attr vec_2x_wide [(V1QI "V1HI") (V2QI "V2HI") (V4QI "V4HI") (V8QI "V8HI") (V16QI "V16HI")
193			       (V1HI "V1SI") (V2HI "V2SI") (V4HI "V4SI") (V8HI "V8SI")
194			       (V1SI "V1DI") (V2SI "V2DI") (V4SI "V4DI")
195			       (V1DI "V1TI") (V2DI "V2TI")
196			       (V1SF "V1DF") (V2SF "V2DF") (V4SF "V4DF")
197			       (V1DF "V1TF") (V2DF "V2TF")])
198
199; Vector with half the element size AND half the number of elements.
200(define_mode_attr vec_halfhalf
201  [(V2HI "V2QI") (V4HI "V4QI") (V8HI "V8QI")
202   (V2SI "V2HI") (V4SI "V4HI")
203   (V2DI "V2SI")
204   (V2DF "V2SF")])
205
206(define_mode_attr vec_halfnumelts
207  [(V4SF "V2SF") (V4SI "V2SI")])
208
209
210
211; Comparison operators on int and fp compares which are directly
212; supported by the HW.
213(define_code_iterator VICMP_HW_OP [eq gt gtu])
214; For int insn_cmp_op can be used in the insn name as well as in the asm output.
215(define_code_attr insn_cmp_op [(eq "eq") (gt "h") (gtu "hl") (ge "he")])
216
217; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4)
218(define_constants
219  [(VSTRING_FLAG_IN         8)   ; invert result
220   (VSTRING_FLAG_RT         4)   ; result type
221   (VSTRING_FLAG_ZS         2)   ; zero search
222   (VSTRING_FLAG_CS         1)]) ; condition code set
223
224(include "vx-builtins.md")
225
226; Full HW vector size moves
227
228; We don't use lm/stm for 128 bit moves since these are slower than
229; splitting it into separate moves.
230
231; FIXME: More constants are possible by enabling jxx, jyy constraints
232; for TImode (use double-int for the calculations)
233
234; vgmb, vgmh, vgmf, vgmg, vrepib, vrepih, vrepif, vrepig
235(define_insn "mov<mode><tf_vr>"
236  [(set (match_operand:V_128 0 "nonimmediate_operand" "=v,v,R,  v,  v,  v,  v,  v,v,*d,*d,?o")
237	(match_operand:V_128 1 "general_operand"      " v,R,v,j00,jm1,jyy,jxx,jKK,d, v,dT,*d"))]
238  ""
239  "@
240   vlr\t%v0,%v1
241   vl\t%v0,%1%A1
242   vst\t%v1,%0%A0
243   vzero\t%v0
244   vone\t%v0
245   vgbm\t%v0,%t1
246   vgm<bhfgq>\t%v0,%s1,%e1
247   vrepi<bhfgq>\t%v0,%h1
248   vlvgp\t%v0,%1,%N1
249   #
250   #
251   #"
252  [(set_attr "cpu_facility" "vx,vx,vx,vx,vx,vx,vx,vx,vx,vx,*,*")
253   (set_attr "op_type"      "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*,*,*")])
254
255(define_expand "movtf"
256  [(match_operand:TF 0 "nonimmediate_operand" "")
257   (match_operand:TF 1 "general_operand"      "")]
258  ""
259  { EXPAND_MOVTF(movtf); })
260
261; VR -> GPR, no instruction so split it into 64 element sets.
262(define_split
263  [(set (match_operand:V_128 0 "register_operand" "")
264	(match_operand:V_128 1 "register_operand" ""))]
265  "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])"
266  [(set (match_dup 2)
267	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
268		    (const_int 0)] UNSPEC_VEC_EXTRACT))
269   (set (match_dup 3)
270	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
271		    (const_int 1)] UNSPEC_VEC_EXTRACT))]
272{
273  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
274  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
275})
276
277; Split the 128 bit GPR move into two word mode moves
278; s390_split_ok_p decides which part needs to be moved first.
279
280(define_split
281  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
282        (match_operand:V_128 1 "general_operand" ""))]
283  "reload_completed
284   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 0)"
285  [(set (match_dup 2) (match_dup 4))
286   (set (match_dup 3) (match_dup 5))]
287{
288  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
289  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
290  operands[4] = operand_subword (operands[1], 0, 0, <MODE>mode);
291  operands[5] = operand_subword (operands[1], 1, 0, <MODE>mode);
292})
293
294(define_split
295  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
296        (match_operand:V_128 1 "general_operand" ""))]
297  "reload_completed
298   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 1)"
299  [(set (match_dup 2) (match_dup 4))
300   (set (match_dup 3) (match_dup 5))]
301{
302  operands[2] = operand_subword (operands[0], 1, 0, <MODE>mode);
303  operands[3] = operand_subword (operands[0], 0, 0, <MODE>mode);
304  operands[4] = operand_subword (operands[1], 1, 0, <MODE>mode);
305  operands[5] = operand_subword (operands[1], 0, 0, <MODE>mode);
306})
307
308; This is the vector equivalent to the TImode splitter in s390.md.  It
309; is required if both target GPRs occur in the source address operand.
310
311; For non-s_operands at least one of the target GPRs does not conflict
312; with the address operand and one of the splitters above will take
313; over.
314(define_split
315  [(set (match_operand:V_128 0 "register_operand" "")
316        (match_operand:V_128 1 "memory_operand" ""))]
317  "TARGET_ZARCH && reload_completed
318   && !VECTOR_REG_P (operands[0])
319   && !s_operand (operands[1], VOIDmode)"
320  [(set (match_dup 0) (match_dup 1))]
321{
322  rtx addr = operand_subword (operands[0], 1, 0, <MODE>mode);
323  addr = gen_lowpart (Pmode, addr);
324  s390_load_address (addr, XEXP (operands[1], 0));
325  operands[1] = replace_equiv_address (operands[1], addr);
326})
327
328; Moves for smaller vector modes.
329
330; In these patterns only the vlr, vone, and vzero instructions write
331; VR bytes outside the mode.  This should be ok since we disallow
332; formerly bigger modes being accessed with smaller modes via
333; subreg. Note: The vone, vzero instructions could easily be replaced
334; with vlei which would only access the bytes belonging to the mode.
335; However, this would probably be slower.
336
337(define_insn "mov<mode>"
338  [(set (match_operand:V_8 0 "nonimmediate_operand" "=v,v,d,v,R,  v,  v,  v,  v,d,  Q,  S,  Q,  S,  d,  d,d,R,T")
339        (match_operand:V_8 1 "general_operand"      " v,d,v,R,v,j00,jm1,jyy,jxx,d,j00,j00,jm1,jm1,j00,jm1,T,d,d"))]
340  "TARGET_VX"
341  "@
342   vlr\t%v0,%v1
343   vlvgb\t%v0,%1,0
344   vlgvb\t%0,%v1,0
345   vleb\t%v0,%1,0
346   vsteb\t%v1,%0,0
347   vzero\t%v0
348   vone\t%v0
349   vgbm\t%v0,%t1
350   vgm\t%v0,%s1,%e1
351   lr\t%0,%1
352   mvi\t%0,0
353   mviy\t%0,0
354   mvi\t%0,-1
355   mviy\t%0,-1
356   lhi\t%0,0
357   lhi\t%0,-1
358   llc\t%0,%1
359   stc\t%1,%0
360   stcy\t%1,%0"
361  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RXY,RX,RXY")])
362
363(define_insn "mov<mode>"
364  [(set (match_operand:V_16 0 "nonimmediate_operand" "=v,v,d,v,R,  v,  v,  v,  v,d,  Q,  Q,  d,  d,d,d,d,R,T,b")
365        (match_operand:V_16 1 "general_operand"      " v,d,v,R,v,j00,jm1,jyy,jxx,d,j00,jm1,j00,jm1,R,T,b,d,d,d"))]
366  ""
367  "@
368   vlr\t%v0,%v1
369   vlvgh\t%v0,%1,0
370   vlgvh\t%0,%v1,0
371   vleh\t%v0,%1,0
372   vsteh\t%v1,%0,0
373   vzero\t%v0
374   vone\t%v0
375   vgbm\t%v0,%t1
376   vgm\t%v0,%s1,%e1
377   lr\t%0,%1
378   mvhhi\t%0,0
379   mvhhi\t%0,-1
380   lhi\t%0,0
381   lhi\t%0,-1
382   lh\t%0,%1
383   lhy\t%0,%1
384   lhrl\t%0,%1
385   sth\t%1,%0
386   sthy\t%1,%0
387   sthrl\t%1,%0"
388  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SIL,SIL,RI,RI,RX,RXY,RIL,RX,RXY,RIL")])
389
390(define_insn "mov<mode>"
391  [(set (match_operand:V_32 0 "nonimmediate_operand" "=f,f,f,R,T,v,v,d,v,R,  f,  v,  v,  v,  v,  Q,  Q,  d,  d,d,d,d,d,R,T,b")
392	(match_operand:V_32 1 "general_operand"      " f,R,T,f,f,v,d,v,R,v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,b,d,R,T,d,d,d"))]
393  "TARGET_VX"
394  "@
395   ldr\t%v0,%v1
396   lde\t%0,%1
397   ley\t%0,%1
398   ste\t%1,%0
399   stey\t%1,%0
400   vlr\t%v0,%v1
401   vlvgf\t%v0,%1,0
402   vlgvf\t%0,%v1,0
403   vlef\t%v0,%1,0
404   vstef\t%1,%0,0
405   lzer\t%v0
406   vzero\t%v0
407   vone\t%v0
408   vgbm\t%v0,%t1
409   vgm\t%v0,%s1,%e1
410   mvhi\t%0,0
411   mvhi\t%0,-1
412   lhi\t%0,0
413   lhi\t%0,-1
414   lrl\t%0,%1
415   lr\t%0,%1
416   l\t%0,%1
417   ly\t%0,%1
418   st\t%1,%0
419   sty\t%1,%0
420   strl\t%1,%0"
421  [(set_attr "op_type" "RR,RXE,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,SIL,SIL,RI,RI,
422                        RIL,RR,RX,RXY,RX,RXY,RIL")])
423
424(define_insn "mov<mode>"
425  [(set (match_operand:V_64 0 "nonimmediate_operand"
426         "=f,f,f,R,T,v,v,d,v,R,  f,  v,  v,  v,  v,  Q,  Q,  d,  d,f,d,d,d,d,T,b")
427        (match_operand:V_64 1 "general_operand"
428         " f,R,T,f,f,v,d,v,R,v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,d,f,b,d,T,d,d"))]
429  "TARGET_ZARCH"
430  "@
431   ldr\t%0,%1
432   ld\t%0,%1
433   ldy\t%0,%1
434   std\t%1,%0
435   stdy\t%1,%0
436   vlr\t%v0,%v1
437   vlvgg\t%v0,%1,0
438   vlgvg\t%0,%v1,0
439   vleg\t%v0,%1,0
440   vsteg\t%v1,%0,0
441   lzdr\t%0
442   vzero\t%v0
443   vone\t%v0
444   vgbm\t%v0,%t1
445   vgm\t%v0,%s1,%e1
446   mvghi\t%0,0
447   mvghi\t%0,-1
448   lghi\t%0,0
449   lghi\t%0,-1
450   ldgr\t%0,%1
451   lgdr\t%0,%1
452   lgrl\t%0,%1
453   lgr\t%0,%1
454   lg\t%0,%1
455   stg\t%1,%0
456   stgrl\t%1,%0"
457  [(set_attr "op_type" "RRE,RX,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,
458                        SIL,SIL,RI,RI,RRE,RRE,RIL,RR,RXY,RXY,RIL")])
459
460
461; vec_load_lanes?
462
463; vec_store_lanes?
464
465; vec_set is supposed to *modify* an existing vector so operand 0 is
466; duplicated as input operand.
467(define_expand "vec_set<mode>"
468  [(set (match_operand:V                    0 "register_operand"  "")
469	(unspec:V [(match_operand:<non_vec> 1 "general_operand"   "")
470		   (match_operand:SI        2 "nonmemory_operand" "")
471		   (match_dup 0)]
472		   UNSPEC_VEC_SET))]
473  "TARGET_VX")
474
475; FIXME: Support also vector mode operands for 1
476; FIXME: A target memory operand seems to be useful otherwise we end
477; up with vl vlvgg vst.  Shouldn't the middle-end be able to handle
478; that itself?
479; vlvgb, vlvgh, vlvgf, vlvgg, vleb, vleh, vlef, vleg, vleib, vleih, vleif, vleig
480(define_insn "*vec_set<mode>"
481  [(set (match_operand:V                    0 "register_operand"  "=v,v,v")
482	(unspec:V [(match_operand:<non_vec> 1 "general_operand"    "d,R,K")
483		   (match_operand:SI        2 "nonmemory_operand" "an,I,I")
484		   (match_operand:V         3 "register_operand"   "0,0,0")]
485		  UNSPEC_VEC_SET))]
486  "TARGET_VX
487   && (!CONST_INT_P (operands[2])
488       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
489  "@
490   vlvg<bhfgq>\t%v0,%1,%Y2
491   vle<bhfgq>\t%v0,%1,%2
492   vlei<bhfgq>\t%v0,%1,%2"
493  [(set_attr "op_type" "VRS,VRX,VRI")])
494
495; vlvgb, vlvgh, vlvgf, vlvgg
496(define_insn "*vec_set<mode>_plus"
497  [(set (match_operand:V                      0 "register_operand" "=v")
498	(unspec:V [(match_operand:<non_vec>   1 "general_operand"   "d")
499		   (plus:SI (match_operand:SI 2 "register_operand"  "a")
500			    (match_operand:SI 4 "const_int_operand" "n"))
501		   (match_operand:V           3 "register_operand"  "0")]
502		  UNSPEC_VEC_SET))]
503  "TARGET_VX"
504  "vlvg<bhfgq>\t%v0,%1,%Y4(%2)"
505  [(set_attr "op_type" "VRS")])
506
507
508; FIXME: Support also vector mode operands for 0
509; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
510; This is used via RTL standard name as well as for expanding the builtin
511(define_expand "vec_extract<mode><non_vec_l>"
512  [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
513	(unspec:<non_vec> [(match_operand:V  1 "register_operand" "")
514			   (match_operand:SI 2 "nonmemory_operand" "")]
515			  UNSPEC_VEC_EXTRACT))]
516  "TARGET_VX")
517
518; vlgvb, vlgvh, vlgvf, vlgvg, vsteb, vsteh, vstef, vsteg
519(define_insn "*vec_extract<mode>"
520  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"          "=d,R")
521	(unspec:<non_vec> [(match_operand:V  1 "register_operand"   "v,v")
522			   (match_operand:SI 2 "nonmemory_operand" "an,I")]
523			  UNSPEC_VEC_EXTRACT))]
524  "TARGET_VX
525   && (!CONST_INT_P (operands[2])
526       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
527  "@
528   vlgv<bhfgq>\t%0,%v1,%Y2
529   vste<bhfgq>\t%v1,%0,%2"
530  [(set_attr "op_type" "VRS,VRX")])
531
532; vlgvb, vlgvh, vlgvf, vlgvg
533(define_insn "*vec_extract<mode>_plus"
534  [(set (match_operand:<non_vec>                      0 "nonimmediate_operand" "=d")
535	(unspec:<non_vec> [(match_operand:V           1 "register_operand"      "v")
536			   (plus:SI (match_operand:SI 2 "nonmemory_operand"     "a")
537				    (match_operand:SI 3 "const_int_operand"     "n"))]
538			   UNSPEC_VEC_EXTRACT))]
539  "TARGET_VX"
540  "vlgv<bhfgq>\t%0,%v1,%Y3(%2)"
541  [(set_attr "op_type" "VRS")])
542
543(define_expand "vec_init<mode><non_vec_l>"
544  [(match_operand:V_128 0 "register_operand" "")
545   (match_operand:V_128 1 "nonmemory_operand" "")]
546  "TARGET_VX"
547{
548  s390_expand_vec_init (operands[0], operands[1]);
549  DONE;
550})
551
552(define_insn "*vec_vllezlf<mode>"
553  [(set (match_operand:V_HW_4              0 "register_operand" "=v")
554	(vec_concat:V_HW_4
555	 (vec_concat:<vec_halfnumelts>
556	  (match_operand:<non_vec> 1 "memory_operand"    "R")
557	  (const_int 0))
558	 (vec_concat:<vec_halfnumelts>
559	  (const_int 0)
560	  (const_int 0))))]
561  "TARGET_VXE"
562  "vllezlf\t%v0,%1"
563  [(set_attr "op_type" "VRX")])
564
565; Replicate from vector element
566; vrepb, vreph, vrepf, vrepg
567(define_insn "*vec_splat<mode>"
568  [(set (match_operand:V_128_NOSINGLE   0 "register_operand" "=v")
569	(vec_duplicate:V_128_NOSINGLE
570	 (vec_select:<non_vec>
571	  (match_operand:V_128_NOSINGLE 1 "register_operand"  "v")
572	  (parallel
573	   [(match_operand:QI 2 "const_mask_operand" "C")]))))]
574  "TARGET_VX && UINTVAL (operands[2]) < GET_MODE_NUNITS (<MODE>mode)"
575  "vrep<bhfgq>\t%v0,%v1,%2"
576  [(set_attr "op_type" "VRI")])
577
578; vlrepb, vlreph, vlrepf, vlrepg, vrepib, vrepih, vrepif, vrepig, vrepb, vreph, vrepf, vrepg
579(define_insn "*vec_splats<mode>"
580  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "=v,v,v,v")
581	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "general_operand"  " R,K,v,d")))]
582  "TARGET_VX"
583  "@
584   vlrep<bhfgq>\t%v0,%1
585   vrepi<bhfgq>\t%v0,%h1
586   vrep<bhfgq>\t%v0,%v1,0
587   #"
588  [(set_attr "op_type" "VRX,VRI,VRI,*")])
589
590; vlbrreph, vlbrrepf, vlbrrepg
591(define_insn "*vec_splats_bswap_vec<mode>"
592  [(set (match_operand:V_HW_HSD                           0 "register_operand"        "=v")
593	(bswap:V_HW_HSD
594	 (vec_duplicate:V_HW_HSD (match_operand:<non_vec> 1 "memory_operand"           "R"))))
595   (use (match_operand:V16QI                              2 "permute_pattern_operand"  "X"))]
596  "TARGET_VXE2"
597  "vlbrrep<bhfgq>\t%v0,%1"
598  [(set_attr "op_type" "VRX")])
599
600; Why do we need both? Shouldn't there be a canonical form?
601; vlbrreph, vlbrrepf, vlbrrepg
602(define_insn "*vec_splats_bswap_elem<mode>"
603  [(set (match_operand:V_HW_HSD                    0 "register_operand" "=v")
604	(vec_duplicate:V_HW_HSD
605	 (bswap:<non_vec> (match_operand:<non_vec> 1 "memory_operand"    "R"))))]
606  "TARGET_VXE2"
607  "vlbrrep<bhfgq>\t%v0,%1"
608  [(set_attr "op_type" "VRX")])
609
610; A TFmode operand resides in FPR register pairs while V1TF is in a
611; single vector register.
612(define_insn "*vec_tf_to_v1tf_fpr"
613  [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
614	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "f,R,f,G,d")))]
615  "TARGET_VX && !TARGET_VXE"
616  "@
617   vmrhg\t%v0,%1,%N1
618   vl\t%v0,%1%A1
619   vst\t%v1,%0%A0
620   vzero\t%v0
621   vlvgp\t%v0,%1,%N1"
622  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
623
624; Both TFmode and V1TFmode operands reside in vector registers.
625(define_insn "*vec_tf_to_v1tf_vr"
626  [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
627	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "v,R,v,G,d")))]
628  "TARGET_VXE"
629  "@
630   vlr\t%v0,%1
631   vl\t%v0,%1%A1
632   vst\t%v1,%0%A0
633   vzero\t%v0
634   vlvgp\t%v0,%1,%N1"
635  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
636
637(define_insn_and_split "fprx2_to_tf"
638  [(set (match_operand:TF               0 "nonimmediate_operand" "=v,AR")
639	(subreg:TF (match_operand:FPRX2 1 "general_operand"       "f,f") 0))]
640  "TARGET_VXE"
641  "@
642   vmrhg\t%v0,%1,%N1
643   #"
644  "!(MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))"
645  [(set (match_dup 2) (match_dup 3))
646   (set (match_dup 4) (match_dup 5))]
647{
648  operands[2] = simplify_gen_subreg (DFmode, operands[0], TFmode, 0);
649  operands[3] = simplify_gen_subreg (DFmode, operands[1], FPRX2mode, 0);
650  operands[4] = simplify_gen_subreg (DFmode, operands[0], TFmode, 8);
651  operands[5] = simplify_gen_subreg (DFmode, operands[1], FPRX2mode, 8);
652}
653  [(set_attr "op_type" "VRR,*")])
654
655(define_insn "*vec_ti_to_v1ti"
656  [(set (match_operand:V1TI                   0 "nonimmediate_operand" "=v,v,R,  v,  v,v")
657	(vec_duplicate:V1TI (match_operand:TI 1 "general_operand"       "v,R,v,j00,jm1,d")))]
658  "TARGET_VX"
659  "@
660   vlr\t%v0,%v1
661   vl\t%v0,%1%A1
662   vst\t%v1,%0%A0
663   vzero\t%v0
664   vone\t%v0
665   vlvgp\t%v0,%1,%N1"
666  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRR")])
667
668; vec_splats is supposed to replicate op1 into all elements of op0
669; This splitter first sets the rightmost element of op0 to op1 and
670; then does a vec_splat to replicate that element into all other
671; elements.
672(define_split
673  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "")
674	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "register_operand" "")))]
675  "TARGET_VX && GENERAL_REG_P (operands[1])"
676  [(set (match_dup 0)
677	(unspec:V_128_NOSINGLE [(match_dup 1) (match_dup 2) (match_dup 0)] UNSPEC_VEC_SET))
678   (set (match_dup 0)
679	(vec_duplicate:V_128_NOSINGLE
680	 (vec_select:<non_vec>
681	  (match_dup 0) (parallel [(match_dup 2)]))))]
682{
683  operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
684})
685
686(define_predicate "vcond_comparison_operator"
687  (match_operand 0 "comparison_operator")
688{
689  if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
690      && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
691    return true;
692  switch (GET_CODE (op))
693    {
694    case LE:
695    case LT:
696    case GE:
697    case GT:
698    case LTGT:
699      /* Signaling vector comparisons are supported only on z14+.  */
700      return TARGET_VXE || TARGET_NONSIGNALING_VECTOR_COMPARE_OK;
701    default:
702      return true;
703    }
704})
705
706(define_expand "vcond<V_HW:mode><V_HW2:mode>"
707  [(set (match_operand:V_HW 0 "register_operand" "")
708	(if_then_else:V_HW
709	 (match_operator 3 "vcond_comparison_operator"
710			 [(match_operand:V_HW2 4 "register_operand" "")
711			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
712	 (match_operand:V_HW 1 "nonmemory_operand" "")
713	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
714  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
715{
716  s390_expand_vcond (operands[0], operands[1], operands[2],
717		     GET_CODE (operands[3]), operands[4], operands[5]);
718  DONE;
719})
720
721(define_expand "vcondu<V_HW:mode><V_HW2:mode>"
722  [(set (match_operand:V_HW 0 "register_operand" "")
723	(if_then_else:V_HW
724	 (match_operator 3 "comparison_operator"
725			 [(match_operand:V_HW2 4 "register_operand" "")
726			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
727	 (match_operand:V_HW 1 "nonmemory_operand" "")
728	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
729  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
730{
731  s390_expand_vcond (operands[0], operands[1], operands[2],
732		     GET_CODE (operands[3]), operands[4], operands[5]);
733  DONE;
734})
735
736(define_expand "vcond_mask_<mode><tointvec>"
737  [(set (match_operand:V 0 "register_operand" "")
738	(if_then_else:V
739	 (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
740	     (match_dup 4))
741	 (match_operand:V 2 "register_operand" "")
742	 (match_operand:V 1 "register_operand" "")))]
743  "TARGET_VX"
744  "operands[4] = CONST0_RTX (<TOINTVEC>mode);")
745
746
747; We only have HW support for byte vectors.  The middle-end is
748; supposed to lower the mode if required.
749(define_insn "vec_permv16qi"
750  [(set (match_operand:V16QI 0 "register_operand"               "=v")
751	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
752		       (match_operand:V16QI 2 "register_operand" "v")
753		       (match_operand:V16QI 3 "register_operand" "v")]
754		      UNSPEC_VEC_PERM))]
755  "TARGET_VX"
756  "vperm\t%v0,%v1,%v2,%v3"
757  [(set_attr "op_type" "VRR")])
758
759(define_insn "*vec_perm<mode>"
760  [(set (match_operand:VT_HW                                            0 "register_operand" "=v")
761	(subreg:VT_HW (unspec:V16QI [(subreg:V16QI (match_operand:VT_HW 1 "register_operand"  "v") 0)
762				     (subreg:V16QI (match_operand:VT_HW 2 "register_operand"  "v") 0)
763				     (match_operand:V16QI               3 "register_operand"  "v")]
764				    UNSPEC_VEC_PERM) 0))]
765  "TARGET_VX"
766  "vperm\t%v0,%v1,%v2,%v3"
767  [(set_attr "op_type" "VRR")])
768
769
770; First DW of op1 and second DW of op2
771(define_insn "@vpdi1<mode>"
772  [(set (match_operand:V_HW_2   0 "register_operand" "=v")
773	(vec_select:V_HW_2
774	 (vec_concat:<vec_2x_nelts>
775	  (match_operand:V_HW_2 1 "register_operand"  "v")
776	  (match_operand:V_HW_2 2 "register_operand"  "v"))
777	 (parallel [(const_int 0) (const_int 3)])))]
778  "TARGET_VX"
779  "vpdi\t%v0,%v1,%v2,1"
780  [(set_attr "op_type" "VRR")])
781
782; Second DW of op1 and first of op2
783(define_insn "@vpdi4<mode>"
784  [(set (match_operand:V_HW_2   0 "register_operand" "=v")
785	(vec_select:V_HW_2
786	 (vec_concat:<vec_2x_nelts>
787	  (match_operand:V_HW_2 1 "register_operand"  "v")
788	  (match_operand:V_HW_2 2 "register_operand"  "v"))
789	 (parallel [(const_int 1) (const_int 2)])))]
790  "TARGET_VX"
791  "vpdi\t%v0,%v1,%v2,4"
792  [(set_attr "op_type" "VRR")])
793
794
795(define_insn "*vmrhb"
796  [(set (match_operand:V16QI                     0 "register_operand" "=v")
797        (vec_select:V16QI
798	  (vec_concat:V32QI (match_operand:V16QI 1 "register_operand"  "v")
799			    (match_operand:V16QI 2 "register_operand"  "v"))
800	  (parallel [(const_int 0) (const_int 16)
801		     (const_int 1) (const_int 17)
802		     (const_int 2) (const_int 18)
803		     (const_int 3) (const_int 19)
804		     (const_int 4) (const_int 20)
805		     (const_int 5) (const_int 21)
806		     (const_int 6) (const_int 22)
807		     (const_int 7) (const_int 23)])))]
808  "TARGET_VX"
809  "vmrhb\t%0,%1,%2";
810  [(set_attr "op_type" "VRR")])
811
812(define_insn "*vmrlb"
813  [(set (match_operand:V16QI                     0 "register_operand" "=v")
814        (vec_select:V16QI
815	  (vec_concat:V32QI (match_operand:V16QI 1 "register_operand"  "v")
816			    (match_operand:V16QI 2 "register_operand"  "v"))
817	  (parallel [(const_int  8) (const_int 24)
818		     (const_int  9) (const_int 25)
819		     (const_int 10) (const_int 26)
820		     (const_int 11) (const_int 27)
821		     (const_int 12) (const_int 28)
822		     (const_int 13) (const_int 29)
823		     (const_int 14) (const_int 30)
824		     (const_int 15) (const_int 31)])))]
825  "TARGET_VX"
826  "vmrlb\t%0,%1,%2";
827  [(set_attr "op_type" "VRR")])
828
829(define_insn "*vmrhh"
830  [(set (match_operand:V8HI                     0 "register_operand" "=v")
831        (vec_select:V8HI
832	  (vec_concat:V16HI (match_operand:V8HI 1 "register_operand"  "v")
833			    (match_operand:V8HI 2 "register_operand"  "v"))
834	  (parallel [(const_int 0) (const_int 8)
835		     (const_int 1) (const_int 9)
836		     (const_int 2) (const_int 10)
837		     (const_int 3) (const_int 11)])))]
838  "TARGET_VX"
839  "vmrhh\t%0,%1,%2";
840  [(set_attr "op_type" "VRR")])
841
842(define_insn "*vmrlh"
843  [(set (match_operand:V8HI                     0 "register_operand" "=v")
844        (vec_select:V8HI
845	  (vec_concat:V16HI (match_operand:V8HI 1 "register_operand"  "v")
846			    (match_operand:V8HI 2 "register_operand"  "v"))
847	  (parallel [(const_int 4) (const_int 12)
848		     (const_int 5) (const_int 13)
849		     (const_int 6) (const_int 14)
850		     (const_int 7) (const_int 15)])))]
851  "TARGET_VX"
852  "vmrlh\t%0,%1,%2";
853  [(set_attr "op_type" "VRR")])
854
855(define_insn "*vmrhf"
856  [(set (match_operand:V_HW_4                              0 "register_operand" "=v")
857        (vec_select:V_HW_4
858	  (vec_concat:<vec_2x_nelts> (match_operand:V_HW_4 1 "register_operand"  "v")
859				     (match_operand:V_HW_4 2 "register_operand"  "v"))
860	  (parallel [(const_int 0) (const_int 4)
861		     (const_int 1) (const_int 5)])))]
862  "TARGET_VX"
863  "vmrhf\t%0,%1,%2";
864  [(set_attr "op_type" "VRR")])
865
866(define_insn "*vmrlf"
867  [(set (match_operand:V_HW_4                              0 "register_operand" "=v")
868        (vec_select:V_HW_4
869	  (vec_concat:<vec_2x_nelts> (match_operand:V_HW_4 1 "register_operand"  "v")
870				     (match_operand:V_HW_4 2 "register_operand"  "v"))
871	  (parallel [(const_int 2) (const_int 6)
872		     (const_int 3) (const_int 7)])))]
873  "TARGET_VX"
874  "vmrlf\t%0,%1,%2";
875  [(set_attr "op_type" "VRR")])
876
877(define_insn "*vmrhg"
878  [(set (match_operand:V_HW_2                              0 "register_operand" "=v")
879        (vec_select:V_HW_2
880	  (vec_concat:<vec_2x_nelts> (match_operand:V_HW_2 1 "register_operand"  "v")
881				     (match_operand:V_HW_2 2 "register_operand"  "v"))
882	  (parallel [(const_int 0) (const_int 2)])))]
883  "TARGET_VX"
884  "vmrhg\t%0,%1,%2";
885  [(set_attr "op_type" "VRR")])
886
887(define_insn "*vmrlg"
888  [(set (match_operand:V_HW_2                              0 "register_operand" "=v")
889        (vec_select:V_HW_2
890	  (vec_concat:<vec_2x_nelts> (match_operand:V_HW_2 1 "register_operand"  "v")
891				     (match_operand:V_HW_2 2 "register_operand"  "v"))
892	  (parallel [(const_int 1) (const_int 3)])))]
893  "TARGET_VX"
894  "vmrlg\t%0,%1,%2";
895  [(set_attr "op_type" "VRR")])
896
897
898(define_insn "*tf_to_fprx2_0"
899  [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 0)
900	(subreg:DF (match_operand:TF    1 "general_operand"       "v") 0))]
901  "TARGET_VXE"
902  ; M4 == 1 corresponds to %v0[0] = %v1[0]; %v0[1] = %v0[1];
903  "vpdi\t%v0,%v1,%v0,1"
904  [(set_attr "op_type" "VRR")])
905
906(define_insn "*tf_to_fprx2_1"
907  [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 8)
908	(subreg:DF (match_operand:TF    1 "general_operand"       "v") 8))]
909  "TARGET_VXE"
910  ; M4 == 5 corresponds to %V0[0] = %v1[1]; %V0[1] = %V0[1];
911  "vpdi\t%V0,%v1,%V0,5"
912  [(set_attr "op_type" "VRR")])
913
914(define_insn_and_split "tf_to_fprx2"
915  [(set (match_operand:FPRX2            0 "nonimmediate_operand" "=f,f")
916	(subreg:FPRX2 (match_operand:TF 1 "general_operand"       "v,AR") 0))]
917  "TARGET_VXE"
918  "#"
919  "!(MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))"
920  [(set (match_dup 2) (match_dup 3))
921   (set (match_dup 4) (match_dup 5))]
922{
923  operands[2] = simplify_gen_subreg (DFmode, operands[0], FPRX2mode, 0);
924  operands[3] = simplify_gen_subreg (DFmode, operands[1], TFmode, 0);
925  operands[4] = simplify_gen_subreg (DFmode, operands[0], FPRX2mode, 8);
926  operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, 8);
927})
928
929
930;;
931;; Vector integer arithmetic instructions
932;;
933
934; vab, vah, vaf, vag, vaq
935
936; We use nonimmediate_operand instead of register_operand since it is
937; better to have the reloads into VRs instead of splitting the
938; operation into two DImode ADDs.
939(define_insn "<ti*>add<mode>3"
940  [(set (match_operand:VIT           0 "nonimmediate_operand" "=v")
941	(plus:VIT (match_operand:VIT 1 "nonimmediate_operand"  "v")
942		  (match_operand:VIT 2 "general_operand"       "v")))]
943  "TARGET_VX"
944  "va<bhfgq>\t%v0,%v1,%v2"
945  [(set_attr "op_type" "VRR")])
946
947; vsb, vsh, vsf, vsg, vsq
948(define_insn "<ti*>sub<mode>3"
949  [(set (match_operand:VIT            0 "nonimmediate_operand" "=v")
950	(minus:VIT (match_operand:VIT 1 "nonimmediate_operand"  "v")
951		   (match_operand:VIT 2 "general_operand"       "v")))]
952  "TARGET_VX"
953  "vs<bhfgq>\t%v0,%v1,%v2"
954  [(set_attr "op_type" "VRR")])
955
956; vmlb, vmlhw, vmlf
957(define_insn "mul<mode>3"
958  [(set (match_operand:VI_QHS              0 "register_operand" "=v")
959	(mult:VI_QHS (match_operand:VI_QHS 1 "register_operand"  "v")
960		     (match_operand:VI_QHS 2 "register_operand"  "v")))]
961  "TARGET_VX"
962  "vml<bhfgq><w>\t%v0,%v1,%v2"
963  [(set_attr "op_type" "VRR")])
964
965; vlcb, vlch, vlcf, vlcg
966(define_insn "neg<mode>2"
967  [(set (match_operand:VI         0 "register_operand" "=v")
968	(neg:VI (match_operand:VI 1 "register_operand"  "v")))]
969  "TARGET_VX"
970  "vlc<bhfgq>\t%v0,%v1"
971  [(set_attr "op_type" "VRR")])
972
973; vlpb, vlph, vlpf, vlpg
974(define_insn "abs<mode>2"
975  [(set (match_operand:VI         0 "register_operand" "=v")
976	(abs:VI (match_operand:VI 1 "register_operand"  "v")))]
977  "TARGET_VX"
978  "vlp<bhfgq>\t%v0,%v1"
979  [(set_attr "op_type" "VRR")])
980
981
982; Vector sum across
983
984; Sum across DImode parts of the 1st operand and add the rightmost
985; element of 2nd operand
986; vsumgh, vsumgf
987(define_insn "*vec_sum2<mode>"
988  [(set (match_operand:V2DI 0 "register_operand" "=v")
989	(unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "v")
990		      (match_operand:VI_HW_HS 2 "register_operand" "v")]
991		     UNSPEC_VEC_VSUMG))]
992  "TARGET_VX"
993  "vsumg<bhfgq>\t%v0,%v1,%v2"
994  [(set_attr "op_type" "VRR")])
995
996; vsumb, vsumh
997(define_insn "*vec_sum4<mode>"
998  [(set (match_operand:V4SI 0 "register_operand" "=v")
999	(unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "v")
1000		      (match_operand:VI_HW_QH 2 "register_operand" "v")]
1001		     UNSPEC_VEC_VSUM))]
1002  "TARGET_VX"
1003  "vsum<bhfgq>\t%v0,%v1,%v2"
1004  [(set_attr "op_type" "VRR")])
1005
1006;;
1007;; Vector bit instructions (int + fp)
1008;;
1009
1010; Vector and
1011
1012(define_insn "and<mode>3"
1013  [(set (match_operand:VT         0 "register_operand" "=v")
1014	(and:VT (match_operand:VT 1 "register_operand"  "v")
1015		(match_operand:VT 2 "register_operand"  "v")))]
1016  "TARGET_VX"
1017  "vn\t%v0,%v1,%v2"
1018  [(set_attr "op_type" "VRR")])
1019
1020; Vector not and
1021
1022(define_insn "notand<mode>3"
1023  [(set (match_operand:VT                 0 "register_operand" "=v")
1024	(ior:VT (not:VT (match_operand:VT 1 "register_operand"  "v"))
1025		(not:VT	(match_operand:VT 2 "register_operand"  "v"))))]
1026  "TARGET_VXE"
1027  "vnn\t%v0,%v1,%v2"
1028  [(set_attr "op_type" "VRR")])
1029
1030; Vector or
1031
1032(define_insn "ior<mode>3"
1033  [(set (match_operand:VT         0 "register_operand" "=v")
1034	(ior:VT (match_operand:VT 1 "register_operand"  "v")
1035		(match_operand:VT 2 "register_operand"  "v")))]
1036  "TARGET_VX"
1037  "vo\t%v0,%v1,%v2"
1038  [(set_attr "op_type" "VRR")])
1039
1040; Vector or with complement
1041
1042(define_insn "ior_not<mode>3"
1043  [(set (match_operand:VT                 0 "register_operand" "=v")
1044	(ior:VT (not:VT (match_operand:VT 2 "register_operand"  "v"))
1045		(match_operand:VT         1 "register_operand"  "v")))]
1046  "TARGET_VXE"
1047  "voc\t%v0,%v1,%v2"
1048  [(set_attr "op_type" "VRR")])
1049
1050; Vector xor
1051
1052(define_insn "xor<mode>3"
1053  [(set (match_operand:VT         0 "register_operand" "=v")
1054	(xor:VT (match_operand:VT 1 "register_operand"  "v")
1055		(match_operand:VT 2 "register_operand"  "v")))]
1056  "TARGET_VX"
1057  "vx\t%v0,%v1,%v2"
1058  [(set_attr "op_type" "VRR")])
1059
1060; Vector not xor
1061
1062(define_insn "notxor<mode>3"
1063  [(set (match_operand:VT                 0 "register_operand" "=v")
1064	(not:VT (xor:VT (match_operand:VT 1 "register_operand"  "v")
1065			(match_operand:VT 2 "register_operand"  "v"))))]
1066  "TARGET_VXE"
1067  "vnx\t%v0,%v1,%v2"
1068  [(set_attr "op_type" "VRR")])
1069
1070; Bitwise inversion of a vector
1071(define_insn "one_cmpl<mode>2"
1072  [(set (match_operand:VT         0 "register_operand" "=v")
1073	(not:VT (match_operand:VT 1 "register_operand"  "v")))]
1074  "TARGET_VX"
1075  "vnot\t%v0,%v1"
1076  [(set_attr "op_type" "VRR")])
1077
1078; Vector population count
1079
1080(define_expand "popcount<mode>2"
1081  [(set (match_operand:VI_HW                0 "register_operand" "=v")
1082	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
1083		      UNSPEC_POPCNT))]
1084  "TARGET_VX"
1085{
1086  if (TARGET_VXE)
1087    emit_insn (gen_popcount<mode>2_vxe (operands[0], operands[1]));
1088  else
1089    emit_insn (gen_popcount<mode>2_vx (operands[0], operands[1]));
1090  DONE;
1091})
1092
1093; vpopctb, vpopcth, vpopctf, vpopctg
1094(define_insn "popcount<mode>2_vxe"
1095  [(set (match_operand:VI_HW                0 "register_operand" "=v")
1096	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
1097		      UNSPEC_POPCNT))]
1098  "TARGET_VXE"
1099  "vpopct<bhfgq>\t%v0,%v1"
1100  [(set_attr "op_type" "VRR")])
1101
1102(define_insn "popcountv16qi2_vx"
1103  [(set (match_operand:V16QI                0 "register_operand" "=v")
1104	(unspec:V16QI [(match_operand:V16QI 1 "register_operand"  "v")]
1105		      UNSPEC_POPCNT))]
1106  "TARGET_VX && !TARGET_VXE"
1107  "vpopct\t%v0,%v1,0"
1108  [(set_attr "op_type" "VRR")])
1109
1110; vpopct only counts bits in byte elements.  Bigger element sizes need
1111; to be emulated.  Word and doubleword elements can use the sum across
1112; instructions.  For halfword sized elements we do a shift of a copy
1113; of the result, add it to the result and extend it to halfword
1114; element size (unpack).
1115
1116(define_expand "popcountv8hi2_vx"
1117  [(set (match_dup 2)
1118	(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")]
1119		      UNSPEC_POPCNT))
1120   ; Make a copy of the result
1121   (set (match_dup 3) (match_dup 2))
1122   ; Generate the shift count operand in a VR (8->byte 7)
1123   (set (match_dup 4) (match_dup 5))
1124   (set (match_dup 4) (unspec:V16QI [(const_int 8)
1125				     (const_int 7)
1126				     (match_dup 4)] UNSPEC_VEC_SET))
1127   ; Vector shift right logical by one byte
1128   (set (match_dup 3)
1129	(unspec:V16QI [(match_dup 3) (match_dup 4)] UNSPEC_VEC_SRLB))
1130   ; Add the shifted and the original result
1131   (set (match_dup 2)
1132	(plus:V16QI (match_dup 2) (match_dup 3)))
1133   ; Generate mask for the odd numbered byte elements
1134   (set (match_dup 3)
1135	(const_vector:V16QI [(const_int 0) (const_int 255)
1136			     (const_int 0) (const_int 255)
1137			     (const_int 0) (const_int 255)
1138			     (const_int 0) (const_int 255)
1139			     (const_int 0) (const_int 255)
1140			     (const_int 0) (const_int 255)
1141			     (const_int 0) (const_int 255)
1142			     (const_int 0) (const_int 255)]))
1143   ; Zero out the even indexed bytes
1144   (set (match_operand:V8HI 0 "register_operand" "=v")
1145	(and:V8HI (subreg:V8HI (match_dup 2) 0)
1146		  (subreg:V8HI (match_dup 3) 0)))
1147]
1148  "TARGET_VX && !TARGET_VXE"
1149{
1150  operands[1] = simplify_gen_subreg (V16QImode, operands[1],
1151				     V8HImode, 0);
1152  operands[2] = gen_reg_rtx (V16QImode);
1153  operands[3] = gen_reg_rtx (V16QImode);
1154  operands[4] = gen_reg_rtx (V16QImode);
1155  operands[5] = CONST0_RTX (V16QImode);
1156})
1157
1158(define_expand "popcountv4si2_vx"
1159  [(set (match_dup 2)
1160	(unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")]
1161		      UNSPEC_POPCNT))
1162   (set (match_operand:V4SI 0 "register_operand" "=v")
1163	(unspec:V4SI [(match_dup 2) (match_dup 3)]
1164		     UNSPEC_VEC_VSUM))]
1165  "TARGET_VX && !TARGET_VXE"
1166{
1167  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V4SImode, 0);
1168  operands[2] = gen_reg_rtx (V16QImode);
1169  operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
1170})
1171
1172(define_expand "popcountv2di2_vx"
1173  [(set (match_dup 2)
1174	(unspec:V16QI [(match_operand:V2DI 1 "register_operand" "v")]
1175		      UNSPEC_POPCNT))
1176   (set (match_dup 3)
1177	(unspec:V4SI [(match_dup 2) (match_dup 4)]
1178		     UNSPEC_VEC_VSUM))
1179   (set (match_operand:V2DI 0 "register_operand" "=v")
1180	(unspec:V2DI [(match_dup 3) (match_dup 5)]
1181		     UNSPEC_VEC_VSUMG))]
1182  "TARGET_VX && !TARGET_VXE"
1183{
1184  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V2DImode, 0);
1185  operands[2] = gen_reg_rtx (V16QImode);
1186  operands[3] = gen_reg_rtx (V4SImode);
1187  operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
1188  operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode));
1189})
1190
1191; Count leading zeros
1192; vclzb, vclzh, vclzf, vclzg
1193(define_insn "clz<mode>2"
1194  [(set (match_operand:V        0 "register_operand" "=v")
1195	(clz:V (match_operand:V 1 "register_operand"  "v")))]
1196  "TARGET_VX"
1197  "vclz<bhfgq>\t%v0,%v1"
1198  [(set_attr "op_type" "VRR")])
1199
1200; Count trailing zeros
1201; vctzb, vctzh, vctzf, vctzg
1202(define_insn "ctz<mode>2"
1203  [(set (match_operand:V        0 "register_operand" "=v")
1204	(ctz:V (match_operand:V 1 "register_operand"  "v")))]
1205  "TARGET_VX"
1206  "vctz<bhfgq>\t%v0,%v1"
1207  [(set_attr "op_type" "VRR")])
1208
1209
1210
1211; Each vector element rotated by the corresponding vector element
1212; verllvb, verllvh, verllvf, verllvg
1213(define_insn "vrotl<mode>3"
1214  [(set (match_operand:VI            0 "register_operand" "=v")
1215	(rotate:VI (match_operand:VI 1 "register_operand"  "v")
1216		   (match_operand:VI 2 "register_operand"  "v")))]
1217  "TARGET_VX"
1218  "verllv<bhfgq>\t%v0,%v1,%v2"
1219  [(set_attr "op_type" "VRR")])
1220
1221
1222; Vector rotate and shift by scalar instructions
1223
1224(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
1225(define_code_attr vec_shifts_name [(ashift "ashl")    (ashiftrt "ashr")
1226				   (lshiftrt "lshr")  (rotate "rotl")])
1227(define_code_attr vec_shifts_mnem [(ashift "vesl")    (ashiftrt "vesra")
1228				   (lshiftrt "vesrl") (rotate "verll")])
1229
1230; Each vector element rotated by a scalar
1231(define_expand "<vec_shifts_name><mode>3"
1232  [(set (match_operand:VI 0 "register_operand" "")
1233	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
1234		       (match_operand:QI 2 "shift_count_operand" "")))]
1235  "TARGET_VX")
1236
1237; verllb, verllh, verllf, verllg
1238; veslb,  veslh,  veslf,  veslg
1239; vesrab, vesrah, vesraf, vesrag
1240; vesrlb, vesrlh, vesrlf, vesrlg
1241(define_insn "*<vec_shifts_name><mode>3"
1242  [(set (match_operand:VI                0 "register_operand"  "=v")
1243	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand"   "v")
1244		       (match_operand:QI 2 "shift_count_operand_vec" "jsc")))]
1245  "TARGET_VX
1246  && s390_valid_shift_count (operands[2],
1247    GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) - 1)
1248  "
1249  "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
1250  [(set_attr "op_type" "VRS")])
1251
1252
1253; Shift each element by corresponding vector element
1254
1255; veslvb, veslvh, veslvf, veslvg
1256(define_insn "vashl<mode>3"
1257  [(set (match_operand:VI            0 "register_operand" "=v")
1258	(ashift:VI (match_operand:VI 1 "register_operand"  "v")
1259		   (match_operand:VI 2 "register_operand"  "v")))]
1260  "TARGET_VX"
1261  "veslv<bhfgq>\t%v0,%v1,%v2"
1262  [(set_attr "op_type" "VRR")])
1263
1264; vesravb, vesravh, vesravf, vesravg
1265(define_insn "vashr<mode>3"
1266  [(set (match_operand:VI              0 "register_operand" "=v")
1267	(ashiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1268		     (match_operand:VI 2 "register_operand"  "v")))]
1269  "TARGET_VX"
1270  "vesrav<bhfgq>\t%v0,%v1,%v2"
1271  [(set_attr "op_type" "VRR")])
1272
1273; vesrlvb, vesrlvh, vesrlvf, vesrlvg
1274(define_insn "vlshr<mode>3"
1275  [(set (match_operand:VI              0 "register_operand" "=v")
1276	(lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1277		     (match_operand:VI 2 "register_operand"  "v")))]
1278  "TARGET_VX"
1279  "vesrlv<bhfgq>\t%v0,%v1,%v2"
1280  [(set_attr "op_type" "VRR")])
1281
1282; Vector shift right logical by byte
1283
1284; Pattern used by e.g. popcount
1285(define_insn "*vec_srb<mode>"
1286  [(set (match_operand:V_128                0 "register_operand" "=v")
1287	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1288		       (match_operand:V16QI 2 "register_operand"  "v")]
1289		   UNSPEC_VEC_SRLB))]
1290  "TARGET_VX"
1291  "vsrlb\t%v0,%v1,%v2"
1292  [(set_attr "op_type" "VRR")])
1293
1294
1295; Vector shift left by byte
1296
1297(define_insn "*vec_slb<mode>"
1298  [(set (match_operand:V_128                0 "register_operand" "=v")
1299	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1300		    (match_operand:V16QI    2 "register_operand"  "v")]
1301		   UNSPEC_VEC_SLB))]
1302  "TARGET_VX"
1303  "vslb\t%v0,%v1,%v2"
1304  [(set_attr "op_type" "VRR")])
1305
1306; vec_shr is defined as shift towards element 0
1307; this means it is a left shift on BE targets!
1308(define_expand "vec_shr_<mode>"
1309  [(set (match_dup 3)
1310	(unspec:V16QI [(match_operand:SI 2 "const_shift_by_byte_operand" "")
1311		   (const_int 7)
1312		   (match_dup 3)]
1313		   UNSPEC_VEC_SET))
1314   (set (match_operand:V_128 0 "register_operand" "")
1315	(unspec:V_128 [(match_operand:V_128 1 "register_operand" "")
1316		    (match_dup 3)]
1317		   UNSPEC_VEC_SLB))]
1318  "TARGET_VX"
1319 {
1320   operands[3] = gen_reg_rtx(V16QImode);
1321 })
1322
1323; vmnb, vmnh, vmnf, vmng
1324(define_insn "smin<mode>3"
1325  [(set (match_operand:VI          0 "register_operand" "=v")
1326	(smin:VI (match_operand:VI 1 "register_operand"  "v")
1327		 (match_operand:VI 2 "register_operand"  "v")))]
1328  "TARGET_VX"
1329  "vmn<bhfgq>\t%v0,%v1,%v2"
1330  [(set_attr "op_type" "VRR")])
1331
1332; vmxb, vmxh, vmxf, vmxg
1333(define_insn "smax<mode>3"
1334  [(set (match_operand:VI          0 "register_operand" "=v")
1335	(smax:VI (match_operand:VI 1 "register_operand"  "v")
1336		 (match_operand:VI 2 "register_operand"  "v")))]
1337  "TARGET_VX"
1338  "vmx<bhfgq>\t%v0,%v1,%v2"
1339  [(set_attr "op_type" "VRR")])
1340
1341; vmnlb, vmnlh, vmnlf, vmnlg
1342(define_insn "umin<mode>3"
1343  [(set (match_operand:VI          0 "register_operand" "=v")
1344	(umin:VI (match_operand:VI 1 "register_operand"  "v")
1345		 (match_operand:VI 2 "register_operand"  "v")))]
1346  "TARGET_VX"
1347  "vmnl<bhfgq>\t%v0,%v1,%v2"
1348  [(set_attr "op_type" "VRR")])
1349
1350; vmxlb, vmxlh, vmxlf, vmxlg
1351(define_insn "umax<mode>3"
1352  [(set (match_operand:VI          0 "register_operand" "=v")
1353	(umax:VI (match_operand:VI 1 "register_operand"  "v")
1354		 (match_operand:VI 2 "register_operand"  "v")))]
1355  "TARGET_VX"
1356  "vmxl<bhfgq>\t%v0,%v1,%v2"
1357  [(set_attr "op_type" "VRR")])
1358
1359; vmeb, vmeh, vmef
1360(define_insn "vec_widen_smult_even_<mode>"
1361  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1362	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1363			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1364			     UNSPEC_VEC_SMULT_EVEN))]
1365  "TARGET_VX"
1366  "vme<bhfgq>\t%v0,%v1,%v2"
1367  [(set_attr "op_type" "VRR")])
1368
1369; vmleb, vmleh, vmlef
1370(define_insn "vec_widen_umult_even_<mode>"
1371  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1372	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1373			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1374			     UNSPEC_VEC_UMULT_EVEN))]
1375  "TARGET_VX"
1376  "vmle<bhfgq>\t%v0,%v1,%v2"
1377  [(set_attr "op_type" "VRR")])
1378
1379; vmob, vmoh, vmof
1380(define_insn "vec_widen_smult_odd_<mode>"
1381  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1382	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1383			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1384			     UNSPEC_VEC_SMULT_ODD))]
1385  "TARGET_VX"
1386  "vmo<bhfgq>\t%v0,%v1,%v2"
1387  [(set_attr "op_type" "VRR")])
1388
1389; vmlob, vmloh, vmlof
1390(define_insn "vec_widen_umult_odd_<mode>"
1391  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1392	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1393			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1394			     UNSPEC_VEC_UMULT_ODD))]
1395  "TARGET_VX"
1396  "vmlo<bhfgq>\t%v0,%v1,%v2"
1397  [(set_attr "op_type" "VRR")])
1398
1399
1400; Widening hi/lo multiplications
1401
1402; The S/390 instructions vml and vmh return the low or high parts of
1403; the double sized result elements in the corresponding elements of
1404; the target register.  That's NOT what the vec_widen_umult_lo/hi
1405; patterns are expected to do.
1406
1407; We emulate the widening lo/hi multiplies with the even/odd versions
1408; followed by a vector merge
1409
1410
1411(define_expand "vec_widen_umult_lo_<mode>"
1412  [(set (match_dup 3)
1413	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1414			      (match_operand:VI_QHS 2 "register_operand" "")]
1415			     UNSPEC_VEC_UMULT_EVEN))
1416   (set (match_dup 4)
1417	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1418			     UNSPEC_VEC_UMULT_ODD))
1419   (set (match_operand:<vec_double>                 0 "register_operand" "")
1420        (vec_select:<vec_double>
1421	 (vec_concat:<vec_2x_wide> (match_dup 3) (match_dup 4))
1422	 (match_dup 5)))]
1423  "TARGET_VX"
1424 {
1425   operands[3] = gen_reg_rtx (<vec_double>mode);
1426   operands[4] = gen_reg_rtx (<vec_double>mode);
1427   operands[5] = s390_expand_merge_perm_const (<vec_double>mode, false);
1428 })
1429
1430(define_expand "vec_widen_umult_hi_<mode>"
1431  [(set (match_dup 3)
1432	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1433			      (match_operand:VI_QHS 2 "register_operand" "")]
1434			     UNSPEC_VEC_UMULT_EVEN))
1435   (set (match_dup 4)
1436	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1437			     UNSPEC_VEC_UMULT_ODD))
1438   (set (match_operand:<vec_double>                 0 "register_operand" "")
1439        (vec_select:<vec_double>
1440	 (vec_concat:<vec_2x_wide> (match_dup 3) (match_dup 4))
1441	 (match_dup 5)))]
1442  "TARGET_VX"
1443 {
1444   operands[3] = gen_reg_rtx (<vec_double>mode);
1445   operands[4] = gen_reg_rtx (<vec_double>mode);
1446   operands[5] = s390_expand_merge_perm_const (<vec_double>mode, true);
1447 })
1448
1449(define_expand "vec_widen_smult_lo_<mode>"
1450  [(set (match_dup 3)
1451	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1452			      (match_operand:VI_QHS 2 "register_operand" "")]
1453			     UNSPEC_VEC_SMULT_EVEN))
1454   (set (match_dup 4)
1455	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1456			     UNSPEC_VEC_SMULT_ODD))
1457   (set (match_operand:<vec_double>                 0 "register_operand" "")
1458        (vec_select:<vec_double>
1459	 (vec_concat:<vec_2x_wide> (match_dup 3) (match_dup 4))
1460	 (match_dup 5)))]
1461  "TARGET_VX"
1462 {
1463   operands[3] = gen_reg_rtx (<vec_double>mode);
1464   operands[4] = gen_reg_rtx (<vec_double>mode);
1465   operands[5] = s390_expand_merge_perm_const (<vec_double>mode, false);
1466 })
1467
1468(define_expand "vec_widen_smult_hi_<mode>"
1469  [(set (match_dup 3)
1470	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1471			      (match_operand:VI_QHS 2 "register_operand" "")]
1472			     UNSPEC_VEC_SMULT_EVEN))
1473   (set (match_dup 4)
1474	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1475			     UNSPEC_VEC_SMULT_ODD))
1476   (set (match_operand:<vec_double>                 0 "register_operand" "")
1477        (vec_select:<vec_double>
1478	 (vec_concat:<vec_2x_wide> (match_dup 3) (match_dup 4))
1479	 (match_dup 5)))]
1480  "TARGET_VX"
1481 {
1482   operands[3] = gen_reg_rtx (<vec_double>mode);
1483   operands[4] = gen_reg_rtx (<vec_double>mode);
1484   operands[5] = s390_expand_merge_perm_const (<vec_double>mode, true);
1485 })
1486
1487; vec_widen_ushiftl_hi
1488; vec_widen_ushiftl_lo
1489; vec_widen_sshiftl_hi
1490; vec_widen_sshiftl_lo
1491
1492;;
1493;; Vector floating point arithmetic instructions
1494;;
1495
1496; vfasb, vfadb, wfasb, wfadb, wfaxb
1497(define_insn "add<mode>3<tf_vr>"
1498  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1499	(plus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1500		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1501  "TARGET_VX"
1502  "<vw>fa<sdx>b\t%v0,%v1,%v2"
1503  [(set_attr "op_type" "VRR")])
1504
1505(define_expand "addtf3"
1506  [(match_operand:TF 0 "register_operand"     "")
1507   (match_operand:TF 1 "nonimmediate_operand" "")
1508   (match_operand:TF 2 "general_operand"      "")]
1509  "HAVE_TF (addtf3)"
1510  { EXPAND_TF (addtf3, 3); })
1511
1512; vfssb, vfsdb, wfssb, wfsdb, wfsxb
1513(define_insn "sub<mode>3<tf_vr>"
1514  [(set (match_operand:VF_HW              0 "register_operand" "=v")
1515	(minus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1516		     (match_operand:VF_HW 2 "register_operand"  "v")))]
1517  "TARGET_VX"
1518  "<vw>fs<sdx>b\t%v0,%v1,%v2"
1519  [(set_attr "op_type" "VRR")])
1520
1521(define_expand "subtf3"
1522  [(match_operand:TF 0 "register_operand" "")
1523   (match_operand:TF 1 "register_operand" "")
1524   (match_operand:TF 2 "general_operand"  "")]
1525  "HAVE_TF (subtf3)"
1526  { EXPAND_TF (subtf3, 3); })
1527
1528; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
1529(define_insn "mul<mode>3<tf_vr>"
1530  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1531	(mult:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1532		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1533  "TARGET_VX"
1534  "<vw>fm<sdx>b\t%v0,%v1,%v2"
1535  [(set_attr "op_type" "VRR")])
1536
1537(define_expand "multf3"
1538  [(match_operand:TF 0 "register_operand"     "")
1539   (match_operand:TF 1 "nonimmediate_operand" "")
1540   (match_operand:TF 2 "general_operand"      "")]
1541  "HAVE_TF (multf3)"
1542  { EXPAND_TF (multf3, 3); })
1543
1544; vfdsb, vfddb, wfdsb, wfddb, wfdxb
1545(define_insn "div<mode>3<tf_vr>"
1546  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1547	(div:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1548		   (match_operand:VF_HW 2 "register_operand"  "v")))]
1549  "TARGET_VX"
1550  "<vw>fd<sdx>b\t%v0,%v1,%v2"
1551  [(set_attr "op_type" "VRR")])
1552
1553(define_expand "divtf3"
1554  [(match_operand:TF 0 "register_operand" "")
1555   (match_operand:TF 1 "register_operand" "")
1556   (match_operand:TF 2 "general_operand"  "")]
1557  "HAVE_TF (divtf3)"
1558  { EXPAND_TF (divtf3, 3); })
1559
1560; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
1561(define_insn "sqrt<mode>2<tf_vr>"
1562  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1563	(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")))]
1564  "TARGET_VX"
1565  "<vw>fsq<sdx>b\t%v0,%v1"
1566  [(set_attr "op_type" "VRR")])
1567
1568(define_expand "sqrttf2"
1569  [(match_operand:TF 0 "register_operand" "")
1570   (match_operand:TF 1 "general_operand"  "")]
1571  "HAVE_TF (sqrttf2)"
1572  { EXPAND_TF (sqrttf2, 2); })
1573
1574; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
1575(define_insn "fma<mode>4"
1576  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1577	(fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1578		   (match_operand:VF_HW 2 "register_operand"  "v")
1579		   (match_operand:VF_HW 3 "register_operand"  "v")))]
1580  "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
1581  "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
1582  [(set_attr "op_type" "VRR")])
1583
1584; vfmssb, vfmsdb, wfmssb, wfmsdb, wfmsxb
1585(define_insn "fms<mode>4"
1586  [(set (match_operand:VF_HW                     0 "register_operand" "=v")
1587	(fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
1588		   (match_operand:VF_HW          2 "register_operand"  "v")
1589		 (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v"))))]
1590  "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
1591  "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
1592  [(set_attr "op_type" "VRR")])
1593
1594; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb
1595(define_insn "neg_fma<mode>4"
1596  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1597	(neg:VF_HW
1598	 (fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1599		    (match_operand:VF_HW 2 "register_operand"  "v")
1600		    (match_operand:VF_HW 3 "register_operand"  "v"))))]
1601  "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
1602  "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
1603  [(set_attr "op_type" "VRR")])
1604
1605; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb
1606(define_insn "neg_fms<mode>4"
1607  [(set (match_operand:VF_HW                      0 "register_operand" "=v")
1608	(neg:VF_HW
1609	 (fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
1610		    (match_operand:VF_HW          2 "register_operand"  "v")
1611		  (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v")))))]
1612  "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
1613  "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
1614  [(set_attr "op_type" "VRR")])
1615
1616; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
1617(define_insn "neg<mode>2<tf_vr>"
1618  [(set (match_operand:VFT          0 "register_operand" "=v")
1619	(neg:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1620  "TARGET_VX"
1621  "<vw>flc<sdx>b\t%v0,%v1"
1622  [(set_attr "op_type" "VRR")])
1623
1624(define_expand "negtf2"
1625  [(match_operand:TF 0 "register_operand" "")
1626   (match_operand:TF 1 "register_operand" "")]
1627  "HAVE_TF (negtf2)"
1628  { EXPAND_TF (negtf2, 2); })
1629
1630; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
1631(define_insn "abs<mode>2<tf_vr>"
1632  [(set (match_operand:VFT          0 "register_operand" "=v")
1633	(abs:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1634  "TARGET_VX"
1635  "<vw>flp<sdx>b\t%v0,%v1"
1636  [(set_attr "op_type" "VRR")])
1637
1638(define_expand "abstf2"
1639  [(match_operand:TF 0 "register_operand" "")
1640   (match_operand:TF 1 "register_operand" "")]
1641  "HAVE_TF (abstf2)"
1642  { EXPAND_TF (abstf2, 2); })
1643
1644; vflnsb, vflndb, wflnsb, wflndb, wflnxb
1645(define_insn "negabs<mode>2"
1646  [(set (match_operand:VFT                   0 "register_operand" "=v")
1647	(neg:VFT (abs:VFT (match_operand:VFT 1 "register_operand"  "v"))))]
1648  "TARGET_VX"
1649  "<vw>fln<sdx>b\t%v0,%v1"
1650  [(set_attr "op_type" "VRR")])
1651
1652(define_expand "smax<mode>3"
1653  [(set (match_operand:VF_HW             0 "register_operand")
1654	(smax:VF_HW (match_operand:VF_HW 1 "register_operand")
1655		    (match_operand:VF_HW 2 "register_operand")))]
1656  "TARGET_VX")
1657
1658; vfmaxsb, vfmaxdb, wfmaxsb, wfmaxdb, wfmaxxb
1659(define_insn "*smax<mode>3_vxe"
1660  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1661	(smax:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1662		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1663  "TARGET_VXE"
1664  "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
1665  [(set_attr "op_type" "VRR")])
1666
1667; Emulate with compare + select
1668(define_insn_and_split "*smaxv2df3_vx"
1669  [(set (match_operand:V2DF            0 "register_operand" "=v")
1670	(smax:V2DF (match_operand:V2DF 1 "register_operand"  "v")
1671		   (match_operand:V2DF 2 "register_operand"  "v")))]
1672  "TARGET_VX && !TARGET_VXE"
1673  "#"
1674  "&& 1"
1675  [(set (match_dup 3)
1676	(not:V2DI
1677	 (unge:V2DI (match_dup 2) (match_dup 1))))
1678   (set (match_dup 0)
1679	(if_then_else:V2DF
1680	 (eq (match_dup 3) (match_dup 4))
1681	 (match_dup 2)
1682	 (match_dup 1)))]
1683{
1684  operands[3] = gen_reg_rtx (V2DImode);
1685  operands[4] = CONST0_RTX (V2DImode);
1686})
1687
1688(define_expand "smin<mode>3"
1689  [(set (match_operand:VF_HW             0 "register_operand")
1690	(smin:VF_HW (match_operand:VF_HW 1 "register_operand")
1691		    (match_operand:VF_HW 2 "register_operand")))]
1692  "TARGET_VX")
1693
1694; vfminsb, vfmindb, wfminsb, wfmindb, wfminxb
1695(define_insn "*smin<mode>3_vxe"
1696  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1697	(smin:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1698		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1699  "TARGET_VXE"
1700  "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
1701  [(set_attr "op_type" "VRR")])
1702
1703; Emulate with compare + select
1704(define_insn_and_split "*sminv2df3_vx"
1705  [(set (match_operand:V2DF            0 "register_operand" "=v")
1706	(smin:V2DF (match_operand:V2DF 1 "register_operand"  "v")
1707		   (match_operand:V2DF 2 "register_operand"  "v")))]
1708  "TARGET_VX && !TARGET_VXE"
1709  "#"
1710  "&& 1"
1711  [(set (match_dup 3)
1712	(not:V2DI
1713	 (unge:V2DI (match_dup 2) (match_dup 1))))
1714   (set (match_dup 0)
1715	(if_then_else:V2DF
1716	 (eq (match_dup 3) (match_dup 4))
1717	 (match_dup 1)
1718	 (match_dup 2)))]
1719{
1720  operands[3] = gen_reg_rtx (V2DImode);
1721  operands[4] = CONST0_RTX (V2DImode);
1722})
1723
1724; Vector copysign, implement using vector select
1725(define_expand "copysign<mode>3"
1726  [(set (match_operand:VFT            0 "register_operand" "")
1727	(ior:VFT
1728	 (and:VFT (match_operand:VFT  2 "register_operand" "")
1729		  (match_dup 3))
1730	 (and:VFT (not:VFT (match_dup 3))
1731		  (match_operand:VFT  1 "register_operand" ""))))]
1732  "TARGET_VX"
1733{
1734  rtx mask = s390_build_signbit_mask (<MODE>mode);
1735  operands[3] = force_reg (<MODE>mode, mask);
1736})
1737
1738;;
1739;; Compares
1740;;
1741
1742(define_expand "vec_cmp<mode><tointvec>"
1743  [(set (match_operand:<TOINTVEC>  0 "register_operand" "")
1744	(match_operator:<TOINTVEC> 1 "vcond_comparison_operator"
1745	  [(match_operand:V_HW     2 "register_operand" "")
1746	   (match_operand:V_HW     3 "nonmemory_operand" "")]))]
1747  "TARGET_VX"
1748{
1749  s390_expand_vec_compare (operands[0], GET_CODE(operands[1]), operands[2], operands[3]);
1750  DONE;
1751})
1752
1753(define_expand "vec_cmpu<VI_HW:mode><VI_HW:mode>"
1754  [(set (match_operand:VI_HW    0 "register_operand" "")
1755	(match_operator:VI_HW   1 ""
1756	  [(match_operand:VI_HW 2 "register_operand" "")
1757	   (match_operand:VI_HW 3 "register_operand" "")]))]
1758  "TARGET_VX"
1759{
1760  s390_expand_vec_compare (operands[0], GET_CODE(operands[1]), operands[2], operands[3]);
1761  DONE;
1762})
1763
1764(define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode><VI:mode>_nocc"
1765  [(set (match_operand:VI                 2 "register_operand" "=v")
1766	(VICMP_HW_OP:VI (match_operand:VI 0 "register_operand"  "v")
1767			(match_operand:VI 1 "register_operand"  "v")))]
1768  "TARGET_VX"
1769  "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1"
1770  [(set_attr "op_type" "VRR")])
1771
1772
1773;;
1774;; Floating point compares
1775;;
1776
1777; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
1778(define_insn "*vec_cmpeq<mode>_quiet_nocc"
1779  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1780	(eq:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1781		       (match_operand:VFT 2 "register_operand" "v")))]
1782  "TARGET_VX"
1783  "<vw>fce<sdx>b\t%v0,%v1,%v2"
1784  [(set_attr "op_type" "VRR")])
1785
1786; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
1787(define_insn "vec_cmpgt<mode>_quiet_nocc"
1788  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1789	(not:<TOINTVEC>
1790	 (unge:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
1791			  (match_operand:VFT 1 "register_operand" "v"))))]
1792  "TARGET_VX"
1793  "<vw>fch<sdx>b\t%v0,%v1,%v2"
1794  [(set_attr "op_type" "VRR")])
1795
1796(define_expand "vec_cmplt<mode>_quiet_nocc"
1797  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1798	(not:<TOINTVEC>
1799	 (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1800			  (match_operand:VFT 2 "register_operand" "v"))))]
1801  "TARGET_VX")
1802
1803; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
1804(define_insn "vec_cmpge<mode>_quiet_nocc"
1805  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1806	(not:<TOINTVEC>
1807	 (unlt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1808			  (match_operand:VFT 2 "register_operand" "v"))))]
1809  "TARGET_VX"
1810  "<vw>fche<sdx>b\t%v0,%v1,%v2"
1811  [(set_attr "op_type" "VRR")])
1812
1813(define_expand "vec_cmple<mode>_quiet_nocc"
1814  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1815	(not:<TOINTVEC>
1816	 (unlt:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
1817			  (match_operand:VFT 1 "register_operand" "v"))))]
1818  "TARGET_VX")
1819
1820; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
1821(define_insn "*vec_cmpeq<mode>_signaling_nocc"
1822  [(set (match_operand:<TOINTVEC>          0 "register_operand" "=v")
1823	(and:<TOINTVEC>
1824	 (ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1825			(match_operand:VFT 2 "register_operand" "v"))
1826	 (ge:<TOINTVEC> (match_dup         2)
1827			(match_dup         1))))]
1828  "TARGET_VXE"
1829  "<vw>fke<sdx>b\t%v0,%v1,%v2"
1830  [(set_attr "op_type" "VRR")])
1831
1832; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
1833(define_insn "*vec_cmpgt<mode>_signaling_nocc"
1834  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1835	(gt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1836		       (match_operand:VFT 2 "register_operand" "v")))]
1837  "TARGET_VXE"
1838  "<vw>fkh<sdx>b\t%v0,%v1,%v2"
1839  [(set_attr "op_type" "VRR")])
1840
1841(define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
1842  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1843	(gt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1844		       (match_operand:VFT 2 "register_operand" "v")))]
1845  "TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
1846  "<vw>fch<sdx>b\t%v0,%v1,%v2"
1847  [(set_attr "op_type" "VRR")])
1848
1849; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
1850(define_insn "*vec_cmpge<mode>_signaling_nocc"
1851  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1852	(ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1853		       (match_operand:VFT 2 "register_operand" "v")))]
1854  "TARGET_VXE"
1855  "<vw>fkhe<sdx>b\t%v0,%v1,%v2"
1856  [(set_attr "op_type" "VRR")])
1857
1858(define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
1859  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1860	(ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1861		       (match_operand:VFT 2 "register_operand" "v")))]
1862  "TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
1863  "<vw>fche<sdx>b\t%v0,%v1,%v2"
1864  [(set_attr "op_type" "VRR")])
1865
1866; Expanders for not directly supported comparisons
1867; Signaling comparisons must be expressed via signaling rtxes only,
1868; and quiet comparisons must be expressed via quiet rtxes only.
1869
1870; UNGT a u> b -> !!(b u< a)
1871(define_expand "vec_cmpungt<mode>"
1872  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1873	(not:<TOINTVEC>
1874	 (unlt:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
1875			  (match_operand:VFT 1 "register_operand" "v"))))
1876   (set (match_dup                           0)
1877	(not:<TOINTVEC> (match_dup           0)))]
1878  "TARGET_VX")
1879
1880; UNGE a u>= b -> !!(a u>= b)
1881(define_expand "vec_cmpunge<mode>"
1882  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1883	(not:<TOINTVEC>
1884	 (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1885			  (match_operand:VFT 2 "register_operand" "v"))))
1886   (set (match_dup                           0)
1887	(not:<TOINTVEC> (match_dup           0)))]
1888  "TARGET_VX")
1889
1890; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
1891(define_expand "vec_cmpuneq<mode>"
1892  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1893	(not:<TOINTVEC>
1894	 (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand"  "v")
1895		          (match_operand:VFT 2 "register_operand"  "v"))))
1896   (set (match_dup                           3)
1897	(not:<TOINTVEC>
1898	 (unge:<TOINTVEC> (match_dup         2)
1899	                  (match_dup         1))))
1900   (set (match_dup                           0)
1901	(ior:<TOINTVEC> (match_dup           0)
1902			(match_dup           3)))
1903   (set (match_dup                           0)
1904	(not:<TOINTVEC> (match_dup           0)))]
1905  "TARGET_VX"
1906{
1907  operands[3] = gen_reg_rtx (<TOINTVEC>mode);
1908})
1909
1910; LTGT a <> b -> a > b | b > a
1911(define_expand "vec_cmpltgt<mode>"
1912  [(set (match_operand:<TOINTVEC>         0 "register_operand" "=v")
1913	(gt:<TOINTVEC> (match_operand:VFT 1 "register_operand"  "v")
1914		    (match_operand:VFT 2 "register_operand"  "v")))
1915   (set (match_dup 3) (gt:<TOINTVEC> (match_dup 2) (match_dup 1)))
1916   (set (match_dup 0) (ior:<TOINTVEC> (match_dup 0) (match_dup 3)))]
1917  "TARGET_VXE"
1918{
1919  operands[3] = gen_reg_rtx (<TOINTVEC>mode);
1920})
1921
1922; ORDERED (a, b): !(a u< b) | !(a u>= b)
1923(define_expand "vec_cmpordered<mode>"
1924  [(set (match_operand:<TOINTVEC>            0 "register_operand" "=v")
1925	(not:<TOINTVEC>
1926	 (unlt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
1927		          (match_operand:VFT 2 "register_operand" "v"))))
1928   (set (match_dup                           3)
1929	(not:<TOINTVEC>
1930	 (unge:<TOINTVEC> (match_dup         1)
1931			  (match_dup         2))))
1932   (set (match_dup                           0)
1933	(ior:<TOINTVEC> (match_dup           0)
1934			(match_dup           3)))]
1935  "TARGET_VX"
1936{
1937  operands[3] = gen_reg_rtx (<TOINTVEC>mode);
1938})
1939
1940; UNORDERED (a, b): !ORDERED (a, b)
1941(define_expand "vec_cmpunordered<mode>"
1942  [(match_operand:<TOINTVEC> 0 "register_operand" "=v")
1943   (match_operand:VFT        1 "register_operand" "v")
1944   (match_operand:VFT        2 "register_operand" "v")]
1945  "TARGET_VX"
1946{
1947  emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
1948  emit_insn (gen_rtx_SET (operands[0],
1949	     gen_rtx_NOT (<TOINTVEC>mode, operands[0])));
1950  DONE;
1951})
1952
1953(define_code_iterator VEC_CMP_EXPAND
1954  [ungt unge uneq ltgt ordered unordered])
1955
1956(define_expand "vec_cmp<code>"
1957  [(match_operand 0 "register_operand" "")
1958   (VEC_CMP_EXPAND (match_operand 1 "register_operand" "")
1959                   (match_operand 2 "register_operand" ""))]
1960  "TARGET_VX"
1961{
1962  if (GET_MODE (operands[1]) == V4SFmode)
1963    emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
1964  else if (GET_MODE (operands[1]) == V2DFmode)
1965    emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
1966  else
1967    gcc_unreachable ();
1968
1969  DONE;
1970})
1971
1972(define_insn "*vec_load_pair<mode>"
1973  [(set (match_operand:V_HW_2                       0 "register_operand" "=v,v")
1974	(vec_concat:V_HW_2 (match_operand:<non_vec> 1 "register_operand"  "d,v")
1975			   (match_operand:<non_vec> 2 "register_operand"  "d,v")))]
1976  "TARGET_VX"
1977  "@
1978   vlvgp\t%v0,%1,%2
1979   vmrhg\t%v0,%v1,%v2"
1980  [(set_attr "op_type" "VRR,VRR")])
1981
1982(define_insn "vllv16qi"
1983  [(set (match_operand:V16QI              0 "register_operand" "=v")
1984	(unspec:V16QI [(match_operand:SI  1 "register_operand"  "d")
1985		       (match_operand:BLK 2 "memory_operand"    "Q")]
1986		      UNSPEC_VEC_LOAD_LEN))]
1987  "TARGET_VX"
1988  "vll\t%v0,%1,%2"
1989  [(set_attr "op_type" "VRS")])
1990
1991; vfeebs, vfeehs, vfeefs
1992; vfeezbs, vfeezhs, vfeezfs
1993(define_insn "@vec_vfees<mode>"
1994  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1995	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1996			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
1997			   (match_operand:QI 3 "const_mask_operand" "C")]
1998			  UNSPEC_VEC_VFEE))
1999   (set (reg:CCRAW CC_REGNUM)
2000	(unspec:CCRAW [(match_dup 1)
2001		       (match_dup 2)
2002		       (match_dup 3)]
2003		      UNSPEC_VEC_VFEECC))]
2004  "TARGET_VX"
2005{
2006  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
2007
2008  gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
2009  flags &= ~VSTRING_FLAG_CS;
2010
2011  if (flags == VSTRING_FLAG_ZS)
2012    return "vfeez<bhfgq>s\t%v0,%v1,%v2";
2013  return "vfee<bhfgq>s\t%v0,%v1,%v2";
2014}
2015  [(set_attr "op_type" "VRR")])
2016
2017; vfenebs, vfenehs, vfenefs
2018; vfenezbs, vfenezhs, vfenezfs
2019(define_insn "vec_vfenes<mode>"
2020  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
2021	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
2022			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
2023			   (match_operand:QI 3 "const_mask_operand" "C")]
2024			  UNSPEC_VEC_VFENE))
2025   (set (reg:CCRAW CC_REGNUM)
2026	(unspec:CCRAW [(match_dup 1)
2027		       (match_dup 2)
2028		       (match_dup 3)]
2029		      UNSPEC_VEC_VFENECC))]
2030  "TARGET_VX"
2031{
2032  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
2033
2034  gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
2035  flags &= ~VSTRING_FLAG_CS;
2036
2037  if (flags == VSTRING_FLAG_ZS)
2038    return "vfenez<bhfgq>s\t%v0,%v1,%v2";
2039  return "vfene<bhfgq>s\t%v0,%v1,%v2";
2040}
2041  [(set_attr "op_type" "VRR")])
2042
2043
2044; Vector select
2045
2046; The following splitters simplify vec_sel for constant 0 or -1
2047; selection sources.  This is required to generate efficient code for
2048; vcond.
2049
2050; a = b == c;
2051(define_split
2052  [(set (match_operand:V 0 "register_operand" "")
2053	(if_then_else:V
2054	 (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
2055	     (match_operand:V 4 "const0_operand" ""))
2056	 (match_operand:V 1 "const0_operand" "")
2057	 (match_operand:V 2 "all_ones_operand" "")))]
2058  "TARGET_VX"
2059  [(set (match_dup 0) (match_dup 3))]
2060{
2061  PUT_MODE (operands[3], <V:MODE>mode);
2062})
2063
2064; a = ~(b == c)
2065(define_split
2066  [(set (match_operand:V 0 "register_operand" "")
2067	(if_then_else:V
2068	 (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
2069	     (match_operand:V 4 "const0_operand" ""))
2070	 (match_operand:V 1 "all_ones_operand" "")
2071	 (match_operand:V 2 "const0_operand" "")))]
2072  "TARGET_VX"
2073  [(set (match_dup 0) (not:V (match_dup 3)))]
2074{
2075  PUT_MODE (operands[3], <V:MODE>mode);
2076})
2077
2078; a = b != c
2079(define_split
2080  [(set (match_operand:V 0 "register_operand" "")
2081	(if_then_else:V
2082	 (ne (match_operand:<TOINTVEC> 3 "register_operand" "")
2083	     (match_operand:V 4 "const0_operand" ""))
2084	 (match_operand:V 1 "all_ones_operand" "")
2085	 (match_operand:V 2 "const0_operand" "")))]
2086  "TARGET_VX"
2087  [(set (match_dup 0) (match_dup 3))]
2088{
2089  PUT_MODE (operands[3], <V:MODE>mode);
2090})
2091
2092; a = ~(b != c)
2093(define_split
2094  [(set (match_operand:V 0 "register_operand" "")
2095	(if_then_else:V
2096	 (ne (match_operand:<TOINTVEC> 3 "register_operand" "")
2097	     (match_operand:V 4 "const0_operand" ""))
2098	 (match_operand:V 1 "const0_operand" "")
2099	 (match_operand:V 2 "all_ones_operand" "")))]
2100  "TARGET_VX"
2101  [(set (match_dup 0) (not:V (match_dup 3)))]
2102{
2103  PUT_MODE (operands[3], <V:MODE>mode);
2104})
2105
2106; op0 = op3 == 0 ? op1 : op2
2107(define_insn "*vec_sel0<mode>"
2108  [(set (match_operand:V 0 "register_operand" "=v")
2109	(if_then_else:V
2110	 (eq (match_operand:<TOINTVEC> 3 "register_operand" "v")
2111	     (match_operand:<TOINTVEC> 4 "const0_operand" ""))
2112	 (match_operand:V 1 "register_operand" "v")
2113	 (match_operand:V 2 "register_operand" "v")))]
2114  "TARGET_VX"
2115  "vsel\t%v0,%2,%1,%3"
2116  [(set_attr "op_type" "VRR")])
2117
2118; op0 = !op3 == 0 ? op1 : op2
2119(define_insn "*vec_sel0<mode>"
2120  [(set (match_operand:V 0 "register_operand" "=v")
2121	(if_then_else:V
2122	 (eq (not:<TOINTVEC> (match_operand:<TOINTVEC> 3 "register_operand" "v"))
2123	     (match_operand:<TOINTVEC> 4 "const0_operand" ""))
2124	 (match_operand:V 1 "register_operand" "v")
2125	 (match_operand:V 2 "register_operand" "v")))]
2126  "TARGET_VX"
2127  "vsel\t%v0,%1,%2,%3"
2128  [(set_attr "op_type" "VRR")])
2129
2130; op0 = op3 == -1 ? op1 : op2
2131(define_insn "*vec_sel1<mode>"
2132  [(set (match_operand:V 0 "register_operand" "=v")
2133	(if_then_else:V
2134	 (eq (match_operand:<TOINTVEC> 3 "register_operand" "v")
2135	     (match_operand:<TOINTVEC> 4 "all_ones_operand" ""))
2136	 (match_operand:V 1 "register_operand" "v")
2137	 (match_operand:V 2 "register_operand" "v")))]
2138  "TARGET_VX"
2139  "vsel\t%v0,%1,%2,%3"
2140  [(set_attr "op_type" "VRR")])
2141
2142; op0 = !op3 == -1 ? op1 : op2
2143(define_insn "*vec_sel1<mode>"
2144  [(set (match_operand:V 0 "register_operand" "=v")
2145	(if_then_else:V
2146	 (eq (not:<TOINTVEC> (match_operand:<TOINTVEC> 3 "register_operand" "v"))
2147	     (match_operand:<TOINTVEC> 4 "all_ones_operand" ""))
2148	 (match_operand:V 1 "register_operand" "v")
2149	 (match_operand:V 2 "register_operand" "v")))]
2150  "TARGET_VX"
2151  "vsel\t%v0,%2,%1,%3"
2152  [(set_attr "op_type" "VRR")])
2153
2154; vec_pack_trunc
2155
2156; vpkh, vpkf, vpkg
2157(define_insn "vec_pack_trunc_<mode>"
2158  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
2159	(vec_concat:<vec_half>
2160	 (truncate:<vec_halfhalf>
2161	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
2162	 (truncate:<vec_halfhalf>
2163	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
2164  "TARGET_VX"
2165  "vpk<bhfgq>\t%0,%1,%2"
2166  [(set_attr "op_type" "VRR")])
2167
2168; vpksh, vpksf, vpksg
2169(define_insn "vec_pack_ssat_<mode>"
2170  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
2171	(vec_concat:<vec_half>
2172	 (ss_truncate:<vec_halfhalf>
2173	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
2174	 (ss_truncate:<vec_halfhalf>
2175	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
2176  "TARGET_VX"
2177  "vpks<bhfgq>\t%0,%1,%2"
2178  [(set_attr "op_type" "VRR")])
2179
2180; vpklsh, vpklsf, vpklsg
2181(define_insn "vec_pack_usat_<mode>"
2182  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
2183	(vec_concat:<vec_half>
2184	 (us_truncate:<vec_halfhalf>
2185	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
2186	 (us_truncate:<vec_halfhalf>
2187	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
2188  "TARGET_VX"
2189  "vpkls<bhfgq>\t%0,%1,%2"
2190  [(set_attr "op_type" "VRR")])
2191
2192;; vector unpack v16qi
2193
2194; signed
2195
2196(define_insn "vec_unpacks_hi_v16qi"
2197  [(set (match_operand:V8HI 0 "register_operand" "=v")
2198	(sign_extend:V8HI
2199	 (vec_select:V8QI
2200	  (match_operand:V16QI 1 "register_operand" "v")
2201	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
2202		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
2203  "TARGET_VX"
2204  "vuphb\t%0,%1"
2205  [(set_attr "op_type" "VRR")])
2206
2207(define_insn "vec_unpacks_lo_v16qi"
2208  [(set (match_operand:V8HI 0 "register_operand" "=v")
2209	(sign_extend:V8HI
2210	 (vec_select:V8QI
2211	  (match_operand:V16QI 1 "register_operand" "v")
2212	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
2213		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
2214  "TARGET_VX"
2215  "vuplb\t%0,%1"
2216  [(set_attr "op_type" "VRR")])
2217
2218; unsigned
2219
2220(define_insn "vec_unpacku_hi_v16qi"
2221  [(set (match_operand:V8HI 0 "register_operand" "=v")
2222	(zero_extend:V8HI
2223	 (vec_select:V8QI
2224	  (match_operand:V16QI 1 "register_operand" "v")
2225	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
2226		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
2227  "TARGET_VX"
2228  "vuplhb\t%0,%1"
2229  [(set_attr "op_type" "VRR")])
2230
2231(define_insn "vec_unpacku_lo_v16qi"
2232  [(set (match_operand:V8HI 0 "register_operand" "=v")
2233	(zero_extend:V8HI
2234	 (vec_select:V8QI
2235	  (match_operand:V16QI 1 "register_operand" "v")
2236	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
2237		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
2238  "TARGET_VX"
2239  "vupllb\t%0,%1"
2240  [(set_attr "op_type" "VRR")])
2241
2242;; vector unpack v8hi
2243
2244; signed
2245
2246(define_insn "vec_unpacks_hi_v8hi"
2247  [(set (match_operand:V4SI 0 "register_operand" "=v")
2248	(sign_extend:V4SI
2249	 (vec_select:V4HI
2250	  (match_operand:V8HI 1 "register_operand" "v")
2251	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
2252  "TARGET_VX"
2253  "vuphh\t%0,%1"
2254  [(set_attr "op_type" "VRR")])
2255
2256(define_insn "vec_unpacks_lo_v8hi"
2257  [(set (match_operand:V4SI 0 "register_operand" "=v")
2258	(sign_extend:V4SI
2259	 (vec_select:V4HI
2260	  (match_operand:V8HI 1 "register_operand" "v")
2261	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
2262  "TARGET_VX"
2263  "vuplhw\t%0,%1"
2264  [(set_attr "op_type" "VRR")])
2265
2266; unsigned
2267
2268(define_insn "vec_unpacku_hi_v8hi"
2269  [(set (match_operand:V4SI 0 "register_operand" "=v")
2270	(zero_extend:V4SI
2271	 (vec_select:V4HI
2272	  (match_operand:V8HI 1 "register_operand" "v")
2273	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
2274  "TARGET_VX"
2275  "vuplhh\t%0,%1"
2276  [(set_attr "op_type" "VRR")])
2277
2278(define_insn "vec_unpacku_lo_v8hi"
2279  [(set (match_operand:V4SI 0 "register_operand" "=v")
2280	(zero_extend:V4SI
2281	 (vec_select:V4HI
2282	  (match_operand:V8HI 1 "register_operand" "v")
2283	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
2284  "TARGET_VX"
2285  "vupllh\t%0,%1"
2286  [(set_attr "op_type" "VRR")])
2287
2288;; vector unpack v4si
2289
2290; signed
2291
2292(define_insn "vec_unpacks_hi_v4si"
2293  [(set (match_operand:V2DI 0 "register_operand" "=v")
2294	(sign_extend:V2DI
2295	 (vec_select:V2SI
2296	  (match_operand:V4SI 1 "register_operand" "v")
2297	  (parallel [(const_int 0)(const_int 1)]))))]
2298  "TARGET_VX"
2299  "vuphf\t%0,%1"
2300  [(set_attr "op_type" "VRR")])
2301
2302(define_insn "vec_unpacks_lo_v4si"
2303  [(set (match_operand:V2DI 0 "register_operand" "=v")
2304	(sign_extend:V2DI
2305	 (vec_select:V2SI
2306	  (match_operand:V4SI 1 "register_operand" "v")
2307	  (parallel [(const_int 2)(const_int 3)]))))]
2308  "TARGET_VX"
2309  "vuplf\t%0,%1"
2310  [(set_attr "op_type" "VRR")])
2311
2312; unsigned
2313
2314(define_insn "vec_unpacku_hi_v4si"
2315  [(set (match_operand:V2DI 0 "register_operand" "=v")
2316	(zero_extend:V2DI
2317	 (vec_select:V2SI
2318	  (match_operand:V4SI 1 "register_operand" "v")
2319	  (parallel [(const_int 0)(const_int 1)]))))]
2320  "TARGET_VX"
2321  "vuplhf\t%0,%1"
2322  [(set_attr "op_type" "VRR")])
2323
2324(define_insn "vec_unpacku_lo_v4si"
2325  [(set (match_operand:V2DI 0 "register_operand" "=v")
2326	(zero_extend:V2DI
2327	 (vec_select:V2SI
2328	  (match_operand:V4SI 1 "register_operand" "v")
2329	  (parallel [(const_int 2)(const_int 3)]))))]
2330  "TARGET_VX"
2331  "vupllf\t%0,%1"
2332  [(set_attr "op_type" "VRR")])
2333
2334;; vector load lengthened
2335
2336; vflls float -> double
2337(define_insn "*vec_extendv4sf"
2338  [(set (match_operand:V2DF 0 "register_operand" "=v")
2339	(float_extend:V2DF
2340	 (vec_select:V2SF
2341	  (match_operand:V4SF 1 "register_operand" "v")
2342	  (parallel [(const_int 0) (const_int 2)]))))]
2343  "TARGET_VX"
2344  "vldeb\t%v0,%v1"
2345  [(set_attr "op_type" "VRR")])
2346
2347(define_expand "vec_unpacks_lo_v4sf"
2348  [(set (match_dup 2)
2349        (vec_select:V4SF
2350	 (vec_concat:V8SF (match_operand:V4SF 1 "register_operand" "") (match_dup 1))
2351	 (match_dup 3)))
2352   (set (match_operand:V2DF                   0 "register_operand" "")
2353	(float_extend:V2DF
2354	 (vec_select:V2SF
2355	  (match_dup 2)
2356	  (parallel [(const_int 0) (const_int 2)]))))]
2357  "TARGET_VX"
2358{
2359  operands[2] = gen_reg_rtx(V4SFmode);
2360  operands[3] = s390_expand_merge_perm_const (V4SFmode, false);
2361})
2362
2363(define_expand "vec_unpacks_hi_v4sf"
2364  [(set (match_dup 2)
2365        (vec_select:V4SF
2366	 (vec_concat:V8SF (match_operand:V4SF 1 "register_operand" "") (match_dup 1))
2367	 (match_dup 3)))
2368   (set (match_operand:V2DF                   0 "register_operand" "")
2369	(float_extend:V2DF
2370	 (vec_select:V2SF
2371	  (match_dup 2)
2372	  (parallel [(const_int 0) (const_int 2)]))))]
2373  "TARGET_VX"
2374{
2375  operands[2] = gen_reg_rtx(V4SFmode);
2376  operands[3] = s390_expand_merge_perm_const (V4SFmode, true);
2377})
2378
2379
2380; double -> long double
2381(define_insn "*vec_extendv2df"
2382  [(set (match_operand:V1TF 0 "register_operand" "=v")
2383	(float_extend:V1TF
2384	 (vec_select:V1DF
2385	  (match_operand:V2DF 1 "register_operand" "v")
2386	  (parallel [(const_int 0)]))))]
2387  "TARGET_VXE"
2388  "wflld\t%v0,%v1"
2389  [(set_attr "op_type" "VRR")])
2390
2391(define_expand "vec_unpacks_lo_v2df"
2392  [(set (match_dup 2)
2393        (vec_select:V2DF
2394	 (vec_concat:V4DF (match_operand:V2DF 1 "register_operand" "") (match_dup 1))
2395	 (match_dup 3)))
2396   (set (match_operand:V1TF                   0 "register_operand" "")
2397	(float_extend:V1TF
2398	 (vec_select:V1DF
2399	  (match_dup 2)
2400	  (parallel [(const_int 0)]))))]
2401  "TARGET_VXE"
2402{
2403  operands[2] = gen_reg_rtx (V2DFmode);
2404  operands[3] = s390_expand_merge_perm_const (V2DFmode, false);
2405})
2406
2407(define_expand "vec_unpacks_hi_v2df"
2408  [(set (match_dup 2)
2409        (vec_select:V2DF
2410	 (vec_concat:V4DF (match_operand:V2DF 1 "register_operand" "") (match_dup 1))
2411	 (match_dup 3)))
2412   (set (match_operand:V1TF                   0 "register_operand" "")
2413	(float_extend:V1TF
2414	 (vec_select:V1DF
2415	  (match_dup 2)
2416	  (parallel [(const_int 0)]))))]
2417  "TARGET_VXE"
2418{
2419  operands[2] = gen_reg_rtx (V2DFmode);
2420  operands[3] = s390_expand_merge_perm_const (V2DFmode, true);
2421})
2422
2423
2424; 2 x v2df -> 1 x v4sf
2425(define_expand "vec_pack_trunc_v2df"
2426  [(set (match_dup 3)
2427	(unspec:V4SF [(match_operand:V2DF 1 "register_operand" "")
2428		      (const_int VEC_INEXACT)
2429		      (const_int VEC_RND_CURRENT)]
2430		     UNSPEC_VEC_VFLR))
2431   (set (match_dup 4)
2432	(unspec:V4SF [(match_operand:V2DF 2 "register_operand" "")
2433		      (const_int VEC_INEXACT)
2434		      (const_int VEC_RND_CURRENT)]
2435		     UNSPEC_VEC_VFLR))
2436   (set (match_dup 6)
2437	(unspec:V16QI [(subreg:V16QI (match_dup 3) 0)
2438		       (subreg:V16QI (match_dup 4) 0)
2439		       (match_dup 5)]
2440		      UNSPEC_VEC_PERM))
2441   (set (match_operand:V4SF 0 "register_operand" "")
2442	(subreg:V4SF (match_dup 6) 0))]
2443  "TARGET_VX"
2444{
2445  rtx constv, perm[16];
2446  int i;
2447
2448  for (i = 0; i < 4; ++i)
2449    {
2450      perm[i] = GEN_INT (i);
2451      perm[i + 4] = GEN_INT (i + 8);
2452      perm[i + 8] = GEN_INT (i + 16);
2453      perm[i + 12] = GEN_INT (i + 24);
2454    }
2455  constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
2456
2457  operands[3] = gen_reg_rtx (V4SFmode);
2458  operands[4] = gen_reg_rtx (V4SFmode);
2459  operands[5] = force_reg (V16QImode, constv);
2460  operands[6] = gen_reg_rtx (V16QImode);
2461})
2462
2463;
2464; BFP <-> integer conversions
2465;
2466
2467; signed integer to floating point
2468
2469; op2: inexact exception not suppressed (IEEE 754 2008)
2470; op3: according to current rounding mode
2471; vcdgb, vcefb
2472(define_insn "float<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2473  [(set (match_operand:VX_VEC_CONV_BFP                        0 "register_operand" "=v")
2474	(float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2475  "TARGET_VX
2476   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2477  "vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2478  [(set_attr "op_type" "VRR")])
2479
2480; There is no instruction for loading a signed integer into an extended BFP
2481; operand in a VR, therefore we need to load it into a FPR pair first.
2482(define_expand "float<mode>tf2_vr"
2483  [(set (match_dup 2)
2484	(float:FPRX2 (match_operand:DSI 1 "register_operand" "")))
2485   (set (match_operand:TF               0 "register_operand" "")
2486	(subreg:TF (match_dup 2) 0))]
2487  "TARGET_VXE"
2488{
2489  operands[2] = gen_reg_rtx (FPRX2mode);
2490})
2491
2492(define_expand "float<mode>tf2"
2493  [(match_operand:TF  0 "register_operand" "")
2494   (match_operand:DSI 1 "register_operand" "")]
2495  "HAVE_TF (float<mode>tf2)"
2496  { EXPAND_TF (float<mode>tf2, 2); })
2497
2498; unsigned integer to floating point
2499
2500; op2: inexact exception not suppressed (IEEE 754 2008)
2501; op3: according to current rounding mode
2502; vcdlgb, vcelfb
2503(define_insn "floatuns<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2504  [(set (match_operand:VX_VEC_CONV_BFP                                 0 "register_operand" "=v")
2505	(unsigned_float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2506  "TARGET_VX
2507   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2508  "vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2509  [(set_attr "op_type" "VRR")])
2510
2511; There is no instruction for loading an unsigned integer into an extended BFP
2512; operand in a VR, therefore load it into a FPR pair first.
2513(define_expand "floatuns<mode>tf2_vr"
2514  [(set (match_dup 2)
2515	(unsigned_float:FPRX2 (match_operand:GPR 1 "register_operand" "")))
2516   (set (match_operand:TF                        0 "register_operand" "")
2517	(subreg:TF (match_dup 2) 0))]
2518  "TARGET_VXE"
2519{
2520  operands[2] = gen_reg_rtx (FPRX2mode);
2521})
2522
2523(define_expand "floatuns<mode>tf2"
2524  [(match_operand:TF  0 "register_operand" "")
2525   (match_operand:GPR 1 "register_operand" "")]
2526  "HAVE_TF (floatuns<mode>tf2)"
2527  { EXPAND_TF (floatuns<mode>tf2, 2); })
2528
2529; floating point to signed integer
2530
2531; op2: inexact exception not suppressed (IEEE 754 2008)
2532; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2533; vcgdb, vcfeb
2534(define_insn "fix_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2535  [(set (match_operand:VX_VEC_CONV_INT                      0 "register_operand" "=v")
2536	(fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2537  "TARGET_VX
2538   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2539  "vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2540  [(set_attr "op_type" "VRR")])
2541
2542; There is no instruction for rounding an extended BFP operand in a VR into
2543; a signed integer, therefore copy it into a FPR pair first.
2544(define_expand "fix_trunctf<mode>2_vr"
2545  [(set (subreg:DF (match_dup 2) 0)
2546	(subreg:DF (match_operand:TF 1 "register_operand" "") 0))
2547   (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
2548   (parallel [(set (match_operand:GPR 0 "register_operand" "")
2549		   (fix:GPR (match_dup 2)))
2550	      (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
2551	      (clobber (reg:CC CC_REGNUM))])]
2552  "TARGET_VXE"
2553{
2554  operands[2] = gen_reg_rtx (FPRX2mode);
2555})
2556
2557(define_expand "fix_trunctf<mode>2"
2558  [(match_operand:GPR 0 "register_operand" "")
2559   (match_operand:TF  1 "register_operand" "")]
2560  "HAVE_TF (fix_trunctf<mode>2)"
2561  { EXPAND_TF (fix_trunctf<mode>2, 2); })
2562
2563; floating point to unsigned integer
2564
2565; op2: inexact exception not suppressed (IEEE 754 2008)
2566; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2567; vclgdb, vclfeb
2568(define_insn "fixuns_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2569  [(set (match_operand:VX_VEC_CONV_INT                               0 "register_operand" "=v")
2570	(unsigned_fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2571  "TARGET_VX
2572   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2573  "vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2574  [(set_attr "op_type" "VRR")])
2575
2576; There is no instruction for rounding an extended BFP operand in a VR into
2577; an unsigned integer, therefore copy it into a FPR pair first.
2578(define_expand "fixuns_trunctf<mode>2_vr"
2579  [(set (subreg:DF (match_dup 2) 0)
2580	(subreg:DF (match_operand:TF 1 "register_operand" "") 0))
2581   (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
2582   (parallel [(set (match_operand:GPR 0 "register_operand" "")
2583		   (unsigned_fix:GPR (match_dup 2)))
2584	      (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
2585	      (clobber (reg:CC CC_REGNUM))])]
2586  "TARGET_VXE"
2587{
2588  operands[2] = gen_reg_rtx (FPRX2mode);
2589})
2590
2591(define_expand "fixuns_trunctf<mode>2"
2592  [(match_operand:GPR 0 "register_operand" "")
2593   (match_operand:TF  1 "register_operand" "")]
2594  "HAVE_TF (fixuns_trunctf<mode>2)"
2595  { EXPAND_TF (fixuns_trunctf<mode>2, 2); })
2596
2597; load fp integer
2598
2599; vfisb, wfisb, vfidb, wfidb, wfixb; suppress inexact exceptions
2600(define_insn "<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>"
2601  [(set (match_operand:VF_HW                0 "register_operand" "=v")
2602	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"  "v")]
2603		      FPINT))]
2604  "TARGET_VX"
2605  "<vw>fi<VF_HW:sdx>b\t%v0,%v1,4,<FPINT:fpint_roundingmode>"
2606  [(set_attr "op_type" "VRR")])
2607
2608(define_expand "<FPINT:fpint_name>tf2"
2609  [(match_operand:TF 0 "register_operand" "")
2610   (match_operand:TF 1 "register_operand" "")
2611   ; recognize FPINT as an iterator
2612   (unspec:TF [(match_dup 1)] FPINT)]
2613  "HAVE_TF (<FPINT:fpint_name>tf2)"
2614  { EXPAND_TF (<FPINT:fpint_name>tf2, 2); })
2615
2616; vfisb, wfisb, vfidb, wfidb, wfixb; raise inexact exceptions
2617(define_insn "rint<mode>2<tf_vr>"
2618  [(set (match_operand:VF_HW                0 "register_operand" "=v")
2619	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"  "v")]
2620		      UNSPEC_FPINT_RINT))]
2621  "TARGET_VX"
2622  "<vw>fi<sdx>b\t%v0,%v1,0,0"
2623  [(set_attr "op_type" "VRR")])
2624
2625(define_expand "rinttf2"
2626  [(match_operand:TF 0 "register_operand" "")
2627   (match_operand:TF 1 "register_operand" "")]
2628  "HAVE_TF (rinttf2)"
2629  { EXPAND_TF (rinttf2, 2); })
2630
2631; load rounded
2632
2633; wflrx
2634(define_insn "*trunctfdf2_vr"
2635  [(set (match_operand:DF                    0 "register_operand" "=f")
2636	(float_truncate:DF (match_operand:TF 1 "register_operand"  "v")))
2637   (unspec:DF [(match_operand                2 "const_int_operand" "")]
2638	       UNSPEC_ROUND)]
2639  "TARGET_VXE"
2640  "wflrx\t%v0,%v1,0,%2"
2641  [(set_attr "op_type" "VRR")])
2642
2643(define_expand "trunctfdf2_vr"
2644  [(parallel [
2645     (set (match_operand:DF                    0 "register_operand" "")
2646	  (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
2647     (unspec:DF [(const_int BFP_RND_CURRENT)] UNSPEC_ROUND)])]
2648  "TARGET_VXE")
2649
2650(define_expand "trunctfdf2"
2651  [(match_operand:DF 0 "register_operand" "")
2652   (match_operand:TF 1 "register_operand" "")]
2653  "HAVE_TF (trunctfdf2)"
2654  { EXPAND_TF (trunctfdf2, 2); })
2655
2656; wflrx + (ledbr|wledb)
2657(define_expand "trunctfsf2_vr"
2658  [(parallel [
2659     (set (match_dup 2)
2660	  (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
2661     (unspec:DF [(const_int BFP_RND_PREP_FOR_SHORT_PREC)] UNSPEC_ROUND)])
2662   (set (match_operand:SF                    0 "register_operand" "")
2663	(float_truncate:SF (match_dup 2)))]
2664  "TARGET_VXE"
2665{
2666  operands[2] = gen_reg_rtx(DFmode);
2667})
2668
2669(define_expand "trunctfsf2"
2670  [(match_operand:SF 0 "register_operand" "")
2671   (match_operand:TF 1 "register_operand" "")]
2672  "HAVE_TF (trunctfsf2)"
2673  { EXPAND_TF (trunctfsf2, 2); })
2674
2675(define_expand "trunctf<DFP_ALL:mode>2_vr"
2676  [(match_operand:DFP_ALL 0 "nonimmediate_operand" "")
2677   (match_operand:TF 1 "nonimmediate_operand" "")]
2678  "TARGET_HARD_DFP
2679   && GET_MODE_SIZE (TFmode) > GET_MODE_SIZE (<DFP_ALL:MODE>mode)
2680   && TARGET_VXE"
2681{
2682  rtx fprx2 = gen_reg_rtx (FPRX2mode);
2683  emit_insn (gen_tf_to_fprx2 (fprx2, operands[1]));
2684  emit_insn (gen_truncfprx2<DFP_ALL:mode>2 (operands[0], fprx2));
2685  DONE;
2686})
2687
2688(define_expand "trunctf<DFP_ALL:mode>2"
2689  [(match_operand:DFP_ALL 0 "nonimmediate_operand" "")
2690   (match_operand:TF 1 "nonimmediate_operand" "")]
2691  "HAVE_TF (trunctf<DFP_ALL:mode>2)"
2692  { EXPAND_TF (trunctf<DFP_ALL:mode>2, 2); })
2693
2694(define_expand "trunctdtf2_vr"
2695  [(match_operand:TF 0 "nonimmediate_operand" "")
2696   (match_operand:TD 1 "nonimmediate_operand" "")]
2697  "TARGET_HARD_DFP && TARGET_VXE"
2698{
2699  rtx fprx2 = gen_reg_rtx (FPRX2mode);
2700  emit_insn (gen_trunctdfprx22 (fprx2, operands[1]));
2701  emit_insn (gen_fprx2_to_tf (operands[0], fprx2));
2702  DONE;
2703})
2704
2705(define_expand "trunctdtf2"
2706  [(match_operand:TF 0 "nonimmediate_operand" "")
2707   (match_operand:TD 1 "nonimmediate_operand" "")]
2708  "HAVE_TF (trunctdtf2)"
2709  { EXPAND_TF (trunctdtf2, 2); })
2710
2711; load lengthened
2712
2713(define_insn "extenddftf2_vr"
2714  [(set (match_operand:TF                  0 "register_operand" "=v")
2715	(float_extend:TF (match_operand:DF 1 "register_operand"  "f")))]
2716  "TARGET_VXE"
2717  "wflld\t%v0,%v1"
2718  [(set_attr "op_type" "VRR")])
2719
2720(define_expand "extenddftf2"
2721  [(match_operand:TF 0 "register_operand" "")
2722   (match_operand:DF 1 "nonimmediate_operand" "")]
2723  "HAVE_TF (extenddftf2)"
2724  { EXPAND_TF (extenddftf2, 2); })
2725
2726(define_expand "extendsftf2_vr"
2727  [(set (match_dup 2)
2728	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
2729   (set (match_operand:TF                  0 "register_operand"     "")
2730	(float_extend:TF (match_dup 2)))]
2731  "TARGET_VXE"
2732{
2733  operands[2] = gen_reg_rtx(DFmode);
2734})
2735
2736(define_expand "extendsftf2"
2737  [(match_operand:TF 0 "register_operand" "")
2738   (match_operand:SF 1 "nonimmediate_operand" "")]
2739  "HAVE_TF (extendsftf2)"
2740  { EXPAND_TF (extendsftf2, 2); })
2741
2742(define_expand "extend<DFP_ALL:mode>tf2_vr"
2743  [(match_operand:TF 0 "nonimmediate_operand" "")
2744   (match_operand:DFP_ALL 1 "nonimmediate_operand" "")]
2745  "TARGET_HARD_DFP
2746   && GET_MODE_SIZE (<DFP_ALL:MODE>mode) < GET_MODE_SIZE (TFmode)
2747   && TARGET_VXE"
2748{
2749  rtx fprx2 = gen_reg_rtx (FPRX2mode);
2750  emit_insn (gen_extend<DFP_ALL:mode>fprx22 (fprx2, operands[1]));
2751  emit_insn (gen_fprx2_to_tf (operands[0], fprx2));
2752  DONE;
2753})
2754
2755(define_expand "extend<DFP_ALL:mode>tf2"
2756  [(match_operand:TF 0 "nonimmediate_operand" "")
2757   (match_operand:DFP_ALL 1 "nonimmediate_operand" "")]
2758  "HAVE_TF (extend<DFP_ALL:mode>tf2)"
2759  { EXPAND_TF (extend<DFP_ALL:mode>tf2, 2); })
2760
2761(define_expand "extendtftd2_vr"
2762  [(match_operand:TD 0 "nonimmediate_operand" "")
2763   (match_operand:TF 1 "nonimmediate_operand" "")]
2764  "TARGET_HARD_DFP && TARGET_VXE"
2765{
2766  rtx fprx2 = gen_reg_rtx (FPRX2mode);
2767  emit_insn (gen_tf_to_fprx2 (fprx2, operands[1]));
2768  emit_insn (gen_extendfprx2td2 (operands[0], fprx2));
2769  DONE;
2770})
2771
2772(define_expand "extendtftd2"
2773  [(match_operand:TD 0 "nonimmediate_operand" "")
2774   (match_operand:TF 1 "nonimmediate_operand" "")]
2775  "HAVE_TF (extendtftd2)"
2776  { EXPAND_TF (extendtftd2, 2); })
2777
2778; test data class
2779
2780(define_expand "signbittf2_vr"
2781  [(parallel
2782    [(set (reg:CCRAW CC_REGNUM)
2783	  (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
2784			 (match_dup        2)]
2785			UNSPEC_VEC_VFTCICC))
2786     (clobber (scratch:V1TI))])
2787   (set (match_operand:SI                  0 "register_operand" "")
2788	(const_int 0))
2789   (set (match_dup                         0)
2790	(if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
2791			 (const_int 1)
2792			 (match_dup        0)))]
2793  "TARGET_VXE"
2794{
2795  operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
2796})
2797
2798(define_expand "signbittf2"
2799  [(match_operand:SI 0 "register_operand" "")
2800   (match_operand:TF 1 "register_operand" "")]
2801  "HAVE_TF (signbittf2)"
2802  { EXPAND_TF (signbittf2, 2); })
2803
2804(define_expand "isinftf2_vr"
2805  [(parallel
2806    [(set (reg:CCRAW CC_REGNUM)
2807	  (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
2808			 (match_dup        2)]
2809			UNSPEC_VEC_VFTCICC))
2810     (clobber (scratch:V1TI))])
2811   (set (match_operand:SI                  0 "register_operand" "")
2812	(const_int 0))
2813   (set (match_dup                         0)
2814	(if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
2815			 (const_int 1)
2816			 (match_dup        0)))]
2817  "TARGET_VXE"
2818{
2819  operands[2] = GEN_INT (S390_TDC_INFINITY);
2820})
2821
2822(define_expand "isinftf2"
2823  [(match_operand:SI 0 "register_operand" "")
2824   (match_operand:TF 1 "register_operand" "")]
2825  "HAVE_TF (isinftf2)"
2826  { EXPAND_TF (isinftf2, 2); })
2827
2828;
2829; Vector byte swap patterns
2830;
2831
2832; FIXME: The bswap rtl standard name currently does not appear to be
2833; used for vector modes.
2834(define_expand "bswap<mode>"
2835  [(parallel
2836    [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand" "")
2837	  (bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand" "")))
2838     (use (match_dup 2))])]
2839  "TARGET_VX"
2840{
2841  static char p[4][16] =
2842    { { 1,  0,  3,  2,  5,  4,  7, 6, 9,  8,  11, 10, 13, 12, 15, 14 },   /* H */
2843      { 3,  2,  1,  0,  7,  6,  5, 4, 11, 10, 9,  8,  15, 14, 13, 12 },   /* S */
2844      { 7,  6,  5,  4,  3,  2,  1, 0, 15, 14, 13, 12, 11, 10, 9,  8  },   /* D */
2845      { 15, 14, 13, 12, 11, 10, 9, 8, 7,  6,  5,  4,  3,  2,  1,  0  } }; /* T */
2846  char *perm;
2847  rtx perm_rtx[16];
2848
2849  switch (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)))
2850    {
2851    case 2: perm = p[0]; break;
2852    case 4: perm = p[1]; break;
2853    case 8: perm = p[2]; break;
2854    case 16: perm = p[3]; break;
2855    default: gcc_unreachable ();
2856    }
2857  for (int i = 0; i < 16; i++)
2858    perm_rtx[i] = GEN_INT (perm[i]);
2859
2860  operands[2] = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm_rtx));
2861
2862  /* Without vxe2 we do not have byte swap instructions dealing
2863     directly with memory operands.  So instead of waiting until
2864     reload to fix that up switch over to vector permute right
2865     now.  */
2866  if (!TARGET_VXE2)
2867    {
2868      rtx in = force_reg (V16QImode, simplify_gen_subreg (V16QImode, operands[1], <MODE>mode, 0));
2869      rtx permute = force_reg (V16QImode, force_const_mem (V16QImode, operands[2]));
2870      rtx out = gen_reg_rtx (V16QImode);
2871
2872      emit_insn (gen_vec_permv16qi (out, in, in, permute));
2873      emit_move_insn (operands[0], simplify_gen_subreg (<MODE>mode, out, V16QImode, 0));
2874      DONE;
2875    }
2876})
2877
2878; Switching late to the reg-reg variant requires the vector permute
2879; pattern to be pushed into literal pool and allocating a vector
2880; register to load it into.  We rely on both being provided by LRA
2881; when fixing up the v constraint for operand 2.
2882
2883; permute_pattern_operand: general_operand would reject the permute
2884; pattern constants since these are not accepted by
2885; s390_legimitate_constant_p
2886
2887; ^R: Prevent these alternatives from being chosen if it would require
2888; pushing the operand into memory first
2889
2890; vlbrh, vlbrf, vlbrg, vlbrq, vstbrh, vstbrf, vstbrg, vstbrq
2891(define_insn_and_split "*bswap<mode>"
2892  [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand"    "=v, v,^R")
2893	(bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand"     "v,^R, v")))
2894   (use (match_operand:V16QI                        2 "permute_pattern_operand"  "v, X, X"))]
2895  "TARGET_VXE2"
2896  "@
2897   #
2898   vlbr<bhfgq>\t%v0,%v1
2899   vstbr<bhfgq>\t%v1,%v0"
2900  "&& reload_completed
2901   && !memory_operand (operands[0], <MODE>mode)
2902   && !memory_operand (operands[1], <MODE>mode)"
2903  [(set (match_dup 0)
2904	(subreg:VT_HW_HSDT
2905	 (unspec:V16QI [(subreg:V16QI (match_dup 1) 0)
2906			(subreg:V16QI (match_dup 1) 0)
2907			(match_dup 2)]
2908		       UNSPEC_VEC_PERM) 0))]
2909  ""
2910  [(set_attr "op_type"      "*,VRX,VRX")])
2911
2912; reduc_smin
2913; reduc_smax
2914; reduc_umin
2915; reduc_umax
2916
2917; vec_pack_sfix_trunc: convert + pack ?
2918; vec_pack_ufix_trunc
2919; vec_unpacks_float_hi
2920; vec_unpacks_float_lo
2921; vec_unpacku_float_hi
2922; vec_unpacku_float_lo
2923