xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/s390/vector.md (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1;;- Instruction patterns for the System z vector facility
2;;  Copyright (C) 2015-2019 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 duplicate of V_HW for having two iterators expanding
31; independently e.g. vcond
32(define_mode_iterator V_HW  [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
33(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
34
35(define_mode_iterator V_HW_64 [V2DI V2DF])
36(define_mode_iterator VT_HW_HSDT [V8HI V4SI V4SF V2DI V2DF V1TI V1TF TI TF])
37(define_mode_iterator V_HW_HSD [V8HI V4SI (V4SF "TARGET_VXE") V2DI V2DF])
38
39; Including TI for instructions that support it (va, vn, ...)
40(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
41
42; All full size integer vector modes supported in a vector register + TImode
43(define_mode_iterator VIT_HW    [V16QI V8HI V4SI V2DI V1TI TI])
44(define_mode_iterator VI_HW     [V16QI V8HI V4SI V2DI])
45(define_mode_iterator VI_HW_QHS [V16QI V8HI V4SI])
46(define_mode_iterator VI_HW_HSD [V8HI  V4SI V2DI])
47(define_mode_iterator VI_HW_HS  [V8HI  V4SI])
48(define_mode_iterator VI_HW_QH  [V16QI V8HI])
49(define_mode_iterator VI_HW_4   [V4SI V4SF])
50
51; All integer vector modes supported in a vector register + TImode
52(define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI])
53(define_mode_iterator VI  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI])
54(define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI])
55
56(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
57			   V1DF V2DF
58			   (V1TF "TARGET_VXE")])
59
60; FP vector modes directly supported by the HW.  This does not include
61; vector modes using only part of a vector register and should be used
62; for instructions which might trigger IEEE exceptions.
63(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")])
64
65(define_mode_iterator V_8   [V1QI])
66(define_mode_iterator V_16  [V2QI  V1HI])
67(define_mode_iterator V_32  [V4QI  V2HI V1SI V1SF])
68(define_mode_iterator V_64  [V8QI  V4HI V2SI V2SF V1DI V1DF])
69(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF])
70
71(define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
72
73; 32 bit int<->fp vector conversion instructions are available since VXE2 (z15).
74(define_mode_iterator VX_VEC_CONV_BFP [V2DF (V4SF "TARGET_VXE2")])
75(define_mode_iterator VX_VEC_CONV_INT [V2DI (V4SI "TARGET_VXE2")])
76
77; Empty string for all but TImode.  This is used to hide the TImode
78; expander name in case it is defined already.  See addti3 for an
79; example.
80(define_mode_attr ti* [(V1QI "")  (V2QI "") (V4QI "") (V8QI "") (V16QI "")
81		       (V1HI "")  (V2HI "") (V4HI "") (V8HI "")
82		       (V1SI "")  (V2SI "") (V4SI "")
83		       (V1DI "")  (V2DI "")
84		       (V1TI "")  (TI "*")
85		       (V1SF "")  (V2SF "") (V4SF "")
86		       (V1DF "")  (V2DF "")
87		       (V1TF "")  (TF "")])
88
89; The element type of the vector.
90(define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
91			  (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
92			  (V1SI "SI") (V2SI "SI") (V4SI "SI")
93			  (V1DI "DI") (V2DI "DI")
94			  (V1TI "TI") (TI "TI")
95			  (V1SF "SF") (V2SF "SF") (V4SF "SF")
96			  (V1DF "DF") (V2DF "DF")
97			  (V1TF "TF") (TF "TF")])
98
99; Like above, but in lower case.
100(define_mode_attr non_vec_l[(V1QI "qi") (V2QI "qi") (V4QI "qi") (V8QI "qi")
101			    (V16QI "qi")
102			    (V1HI "hi") (V2HI "hi") (V4HI "hi") (V8HI "hi")
103			    (V1SI "si") (V2SI "si") (V4SI "si")
104			    (V1DI "di") (V2DI "di")
105			    (V1TI "ti") (TI "ti")
106			    (V1SF "sf") (V2SF "sf") (V4SF "sf")
107			    (V1DF "df") (V2DF "df")
108			    (V1TF "tf") (TF "tf")])
109
110; The instruction suffix for integer instructions and instructions
111; which do not care about whether it is floating point or integer.
112(define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b")
113			(V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h")
114			(V1SI "f") (V2SI "f") (V4SI "f")
115			(V1DI "g") (V2DI "g")
116			(V1TI "q") (TI "q")
117			(V1SF "f") (V2SF "f") (V4SF "f")
118			(V1DF "g") (V2DF "g")
119			(V1TF "q")])
120
121; This is for vmalhw. It gets an 'w' attached to avoid confusion with
122; multiply and add logical high vmalh.
123(define_mode_attr w [(V1QI "")  (V2QI "")  (V4QI "")  (V8QI "") (V16QI "")
124		     (V1HI "w") (V2HI "w") (V4HI "w") (V8HI "w")
125		     (V1SI "")  (V2SI "")  (V4SI "")
126		     (V1DI "")  (V2DI "")])
127
128; Resulting mode of a vector comparison.  For floating point modes an
129; integer vector mode with the same element size is picked.
130(define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
131			    (V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI")
132			    (V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI")
133			    (V1DI "V1DI") (V2DI "V2DI")
134			    (V1TI "V1TI")
135			    (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
136			    (V1DF "V1DI") (V2DF "V2DI")
137			    (V1TF "V1TI")])
138(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
139		      (DF "w") (V1DF "w") (V2DF "v")
140		      (TF "w") (V1TF "w")])
141
142(define_mode_attr sdx [(SF "s") (V1SF "s") (V2SF "s") (V4SF "s")
143		       (DF "d") (V1DF "d") (V2DF "d")
144		       (TF "x") (V1TF "x")])
145
146; Vector with doubled element size.
147(define_mode_attr vec_double [(V1QI "V1HI") (V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI")
148			      (V1HI "V1SI") (V2HI "V1SI") (V4HI "V2SI") (V8HI "V4SI")
149			      (V1SI "V1DI") (V2SI "V1DI") (V4SI "V2DI")
150			      (V1DI "V1TI") (V2DI "V1TI")
151			      (V1SF "V1DF") (V2SF "V1DF") (V4SF "V2DF")])
152
153; Vector with half the element size.
154(define_mode_attr vec_half [(V1HI "V2QI") (V2HI "V4QI") (V4HI "V8QI") (V8HI "V16QI")
155			    (V1SI "V2HI") (V2SI "V4HI") (V4SI "V8HI")
156			    (V1DI "V2SI") (V2DI "V4SI")
157			    (V1TI "V2DI")
158			    (V1DF "V2SF") (V2DF "V4SF")
159			    (V1TF "V1DF")])
160
161; Vector with half the element size AND half the number of elements.
162(define_mode_attr vec_halfhalf
163  [(V2HI "V2QI") (V4HI "V4QI") (V8HI "V8QI")
164   (V2SI "V2HI") (V4SI "V4HI")
165   (V2DI "V2SI")
166   (V2DF "V2SF")])
167
168(define_mode_attr vec_halfnumelts
169  [(V4SF "V2SF") (V4SI "V2SI")])
170
171; The comparisons not setting CC iterate over the rtx code.
172(define_code_iterator VFCMP_HW_OP [eq gt ge])
173(define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")])
174
175
176
177; Comparison operators on int and fp compares which are directly
178; supported by the HW.
179(define_code_iterator VICMP_HW_OP [eq gt gtu])
180; For int insn_cmp_op can be used in the insn name as well as in the asm output.
181(define_code_attr insn_cmp_op [(eq "eq") (gt "h") (gtu "hl") (ge "he")])
182
183; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4)
184(define_constants
185  [(VSTRING_FLAG_IN         8)   ; invert result
186   (VSTRING_FLAG_RT         4)   ; result type
187   (VSTRING_FLAG_ZS         2)   ; zero search
188   (VSTRING_FLAG_CS         1)]) ; condition code set
189
190(include "vx-builtins.md")
191
192; Full HW vector size moves
193
194; We don't use lm/stm for 128 bit moves since these are slower than
195; splitting it into separate moves.
196
197; FIXME: More constants are possible by enabling jxx, jyy constraints
198; for TImode (use double-int for the calculations)
199
200; vgmb, vgmh, vgmf, vgmg, vrepib, vrepih, vrepif, vrepig
201(define_insn "mov<mode>"
202  [(set (match_operand:V_128 0 "nonimmediate_operand" "=v,v,R,  v,  v,  v,  v,  v,v,*d,*d,?o")
203	(match_operand:V_128 1 "general_operand"      " v,R,v,j00,jm1,jyy,jxx,jKK,d, v,dT,*d"))]
204  ""
205  "@
206   vlr\t%v0,%v1
207   vl\t%v0,%1%A1
208   vst\t%v1,%0%A0
209   vzero\t%v0
210   vone\t%v0
211   vgbm\t%v0,%t1
212   vgm<bhfgq>\t%v0,%s1,%e1
213   vrepi<bhfgq>\t%v0,%h1
214   vlvgp\t%v0,%1,%N1
215   #
216   #
217   #"
218  [(set_attr "cpu_facility" "vx,vx,vx,vx,vx,vx,vx,vx,vx,vx,*,*")
219   (set_attr "op_type"      "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*,*,*")])
220
221; VR -> GPR, no instruction so split it into 64 element sets.
222(define_split
223  [(set (match_operand:V_128 0 "register_operand" "")
224	(match_operand:V_128 1 "register_operand" ""))]
225  "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])"
226  [(set (match_dup 2)
227	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
228		    (const_int 0)] UNSPEC_VEC_EXTRACT))
229   (set (match_dup 3)
230	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
231		    (const_int 1)] UNSPEC_VEC_EXTRACT))]
232{
233  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
234  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
235})
236
237; Split the 128 bit GPR move into two word mode moves
238; s390_split_ok_p decides which part needs to be moved first.
239
240(define_split
241  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
242        (match_operand:V_128 1 "general_operand" ""))]
243  "reload_completed
244   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 0)"
245  [(set (match_dup 2) (match_dup 4))
246   (set (match_dup 3) (match_dup 5))]
247{
248  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
249  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
250  operands[4] = operand_subword (operands[1], 0, 0, <MODE>mode);
251  operands[5] = operand_subword (operands[1], 1, 0, <MODE>mode);
252})
253
254(define_split
255  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
256        (match_operand:V_128 1 "general_operand" ""))]
257  "reload_completed
258   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 1)"
259  [(set (match_dup 2) (match_dup 4))
260   (set (match_dup 3) (match_dup 5))]
261{
262  operands[2] = operand_subword (operands[0], 1, 0, <MODE>mode);
263  operands[3] = operand_subword (operands[0], 0, 0, <MODE>mode);
264  operands[4] = operand_subword (operands[1], 1, 0, <MODE>mode);
265  operands[5] = operand_subword (operands[1], 0, 0, <MODE>mode);
266})
267
268; This is the vector equivalent to the TImode splitter in s390.md.  It
269; is required if both target GPRs occur in the source address operand.
270
271; For non-s_operands at least one of the target GPRs does not conflict
272; with the address operand and one of the splitters above will take
273; over.
274(define_split
275  [(set (match_operand:V_128 0 "register_operand" "")
276        (match_operand:V_128 1 "memory_operand" ""))]
277  "TARGET_ZARCH && reload_completed
278   && !VECTOR_REG_P (operands[0])
279   && !s_operand (operands[1], VOIDmode)"
280  [(set (match_dup 0) (match_dup 1))]
281{
282  rtx addr = operand_subword (operands[0], 1, 0, <MODE>mode);
283  addr = gen_lowpart (Pmode, addr);
284  s390_load_address (addr, XEXP (operands[1], 0));
285  operands[1] = replace_equiv_address (operands[1], addr);
286})
287
288; Moves for smaller vector modes.
289
290; In these patterns only the vlr, vone, and vzero instructions write
291; VR bytes outside the mode.  This should be ok since we disallow
292; formerly bigger modes being accessed with smaller modes via
293; subreg. Note: The vone, vzero instructions could easily be replaced
294; with vlei which would only access the bytes belonging to the mode.
295; However, this would probably be slower.
296
297(define_insn "mov<mode>"
298  [(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")
299        (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"))]
300  "TARGET_VX"
301  "@
302   vlr\t%v0,%v1
303   vlvgb\t%v0,%1,0
304   vlgvb\t%0,%v1,0
305   vleb\t%v0,%1,0
306   vsteb\t%v1,%0,0
307   vzero\t%v0
308   vone\t%v0
309   vgbm\t%v0,%t1
310   vgm\t%v0,%s1,%e1
311   lr\t%0,%1
312   mvi\t%0,0
313   mviy\t%0,0
314   mvi\t%0,-1
315   mviy\t%0,-1
316   lhi\t%0,0
317   lhi\t%0,-1
318   llc\t%0,%1
319   stc\t%1,%0
320   stcy\t%1,%0"
321  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RXY,RX,RXY")])
322
323(define_insn "mov<mode>"
324  [(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")
325        (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"))]
326  ""
327  "@
328   vlr\t%v0,%v1
329   vlvgh\t%v0,%1,0
330   vlgvh\t%0,%v1,0
331   vleh\t%v0,%1,0
332   vsteh\t%v1,%0,0
333   vzero\t%v0
334   vone\t%v0
335   vgbm\t%v0,%t1
336   vgm\t%v0,%s1,%e1
337   lr\t%0,%1
338   mvhhi\t%0,0
339   mvhhi\t%0,-1
340   lhi\t%0,0
341   lhi\t%0,-1
342   lh\t%0,%1
343   lhy\t%0,%1
344   lhrl\t%0,%1
345   sth\t%1,%0
346   sthy\t%1,%0
347   sthrl\t%1,%0"
348  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SIL,SIL,RI,RI,RX,RXY,RIL,RX,RXY,RIL")])
349
350(define_insn "mov<mode>"
351  [(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")
352	(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"))]
353  "TARGET_VX"
354  "@
355   ldr\t%v0,%v1
356   lde\t%0,%1
357   ley\t%0,%1
358   ste\t%1,%0
359   stey\t%1,%0
360   vlr\t%v0,%v1
361   vlvgf\t%v0,%1,0
362   vlgvf\t%0,%v1,0
363   vlef\t%v0,%1,0
364   vstef\t%1,%0,0
365   lzer\t%v0
366   vzero\t%v0
367   vone\t%v0
368   vgbm\t%v0,%t1
369   vgm\t%v0,%s1,%e1
370   mvhi\t%0,0
371   mvhi\t%0,-1
372   lhi\t%0,0
373   lhi\t%0,-1
374   lrl\t%0,%1
375   lr\t%0,%1
376   l\t%0,%1
377   ly\t%0,%1
378   st\t%1,%0
379   sty\t%1,%0
380   strl\t%1,%0"
381  [(set_attr "op_type" "RR,RXE,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,SIL,SIL,RI,RI,
382                        RIL,RR,RX,RXY,RX,RXY,RIL")])
383
384(define_insn "mov<mode>"
385  [(set (match_operand:V_64 0 "nonimmediate_operand"
386         "=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")
387        (match_operand:V_64 1 "general_operand"
388         " 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"))]
389  "TARGET_ZARCH"
390  "@
391   ldr\t%0,%1
392   ld\t%0,%1
393   ldy\t%0,%1
394   std\t%1,%0
395   stdy\t%1,%0
396   vlr\t%v0,%v1
397   vlvgg\t%v0,%1,0
398   vlgvg\t%0,%v1,0
399   vleg\t%v0,%1,0
400   vsteg\t%v1,%0,0
401   lzdr\t%0
402   vzero\t%v0
403   vone\t%v0
404   vgbm\t%v0,%t1
405   vgm\t%v0,%s1,%e1
406   mvghi\t%0,0
407   mvghi\t%0,-1
408   lghi\t%0,0
409   lghi\t%0,-1
410   ldgr\t%0,%1
411   lgdr\t%0,%1
412   lgrl\t%0,%1
413   lgr\t%0,%1
414   lg\t%0,%1
415   stg\t%1,%0
416   stgrl\t%1,%0"
417  [(set_attr "op_type" "RRE,RX,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,
418                        SIL,SIL,RI,RI,RRE,RRE,RIL,RR,RXY,RXY,RIL")])
419
420
421; vec_load_lanes?
422
423; vec_store_lanes?
424
425; vec_set is supposed to *modify* an existing vector so operand 0 is
426; duplicated as input operand.
427(define_expand "vec_set<mode>"
428  [(set (match_operand:V                    0 "register_operand"  "")
429	(unspec:V [(match_operand:<non_vec> 1 "general_operand"   "")
430		   (match_operand:SI        2 "nonmemory_operand" "")
431		   (match_dup 0)]
432		   UNSPEC_VEC_SET))]
433  "TARGET_VX")
434
435; FIXME: Support also vector mode operands for 1
436; FIXME: A target memory operand seems to be useful otherwise we end
437; up with vl vlvgg vst.  Shouldn't the middle-end be able to handle
438; that itself?
439; vlvgb, vlvgh, vlvgf, vlvgg, vleb, vleh, vlef, vleg, vleib, vleih, vleif, vleig
440(define_insn "*vec_set<mode>"
441  [(set (match_operand:V                    0 "register_operand"  "=v,v,v")
442	(unspec:V [(match_operand:<non_vec> 1 "general_operand"    "d,R,K")
443		   (match_operand:SI        2 "nonmemory_operand" "an,I,I")
444		   (match_operand:V         3 "register_operand"   "0,0,0")]
445		  UNSPEC_VEC_SET))]
446  "TARGET_VX
447   && (!CONST_INT_P (operands[2])
448       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
449  "@
450   vlvg<bhfgq>\t%v0,%1,%Y2
451   vle<bhfgq>\t%v0,%1,%2
452   vlei<bhfgq>\t%v0,%1,%2"
453  [(set_attr "op_type" "VRS,VRX,VRI")])
454
455; vlvgb, vlvgh, vlvgf, vlvgg
456(define_insn "*vec_set<mode>_plus"
457  [(set (match_operand:V                      0 "register_operand" "=v")
458	(unspec:V [(match_operand:<non_vec>   1 "general_operand"   "d")
459		   (plus:SI (match_operand:SI 2 "register_operand"  "a")
460			    (match_operand:SI 4 "const_int_operand" "n"))
461		   (match_operand:V           3 "register_operand"  "0")]
462		  UNSPEC_VEC_SET))]
463  "TARGET_VX"
464  "vlvg<bhfgq>\t%v0,%1,%Y4(%2)"
465  [(set_attr "op_type" "VRS")])
466
467
468; FIXME: Support also vector mode operands for 0
469; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
470; This is used via RTL standard name as well as for expanding the builtin
471(define_expand "vec_extract<mode><non_vec_l>"
472  [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
473	(unspec:<non_vec> [(match_operand:V  1 "register_operand" "")
474			   (match_operand:SI 2 "nonmemory_operand" "")]
475			  UNSPEC_VEC_EXTRACT))]
476  "TARGET_VX")
477
478; vlgvb, vlgvh, vlgvf, vlgvg, vsteb, vsteh, vstef, vsteg
479(define_insn "*vec_extract<mode>"
480  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"          "=d,R")
481	(unspec:<non_vec> [(match_operand:V  1 "register_operand"   "v,v")
482			   (match_operand:SI 2 "nonmemory_operand" "an,I")]
483			  UNSPEC_VEC_EXTRACT))]
484  "TARGET_VX
485   && (!CONST_INT_P (operands[2])
486       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
487  "@
488   vlgv<bhfgq>\t%0,%v1,%Y2
489   vste<bhfgq>\t%v1,%0,%2"
490  [(set_attr "op_type" "VRS,VRX")])
491
492; vlgvb, vlgvh, vlgvf, vlgvg
493(define_insn "*vec_extract<mode>_plus"
494  [(set (match_operand:<non_vec>                      0 "nonimmediate_operand" "=d")
495	(unspec:<non_vec> [(match_operand:V           1 "register_operand"      "v")
496			   (plus:SI (match_operand:SI 2 "nonmemory_operand"     "a")
497				    (match_operand:SI 3 "const_int_operand"     "n"))]
498			   UNSPEC_VEC_EXTRACT))]
499  "TARGET_VX"
500  "vlgv<bhfgq>\t%0,%v1,%Y3(%2)"
501  [(set_attr "op_type" "VRS")])
502
503(define_expand "vec_init<mode><non_vec_l>"
504  [(match_operand:V_128 0 "register_operand" "")
505   (match_operand:V_128 1 "nonmemory_operand" "")]
506  "TARGET_VX"
507{
508  s390_expand_vec_init (operands[0], operands[1]);
509  DONE;
510})
511
512(define_insn "*vec_vllezlf<mode>"
513  [(set (match_operand:VI_HW_4              0 "register_operand" "=v")
514	(vec_concat:VI_HW_4
515	 (vec_concat:<vec_halfnumelts>
516	  (match_operand:<non_vec> 1 "memory_operand"    "R")
517	  (const_int 0))
518	 (vec_concat:<vec_halfnumelts>
519	  (const_int 0)
520	  (const_int 0))))]
521  "TARGET_VXE"
522  "vllezlf\t%v0,%1"
523  [(set_attr "op_type" "VRX")])
524
525; Replicate from vector element
526; vrepb, vreph, vrepf, vrepg
527(define_insn "*vec_splat<mode>"
528  [(set (match_operand:V_128_NOSINGLE   0 "register_operand" "=v")
529	(vec_duplicate:V_128_NOSINGLE
530	 (vec_select:<non_vec>
531	  (match_operand:V_128_NOSINGLE 1 "register_operand"  "v")
532	  (parallel
533	   [(match_operand:QI 2 "const_mask_operand" "C")]))))]
534  "TARGET_VX && UINTVAL (operands[2]) < GET_MODE_NUNITS (<MODE>mode)"
535  "vrep<bhfgq>\t%v0,%v1,%2"
536  [(set_attr "op_type" "VRI")])
537
538; vlrepb, vlreph, vlrepf, vlrepg, vrepib, vrepih, vrepif, vrepig, vrepb, vreph, vrepf, vrepg
539(define_insn "*vec_splats<mode>"
540  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "=v,v,v,v")
541	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "general_operand"  " R,K,v,d")))]
542  "TARGET_VX"
543  "@
544   vlrep<bhfgq>\t%v0,%1
545   vrepi<bhfgq>\t%v0,%h1
546   vrep<bhfgq>\t%v0,%v1,0
547   #"
548  [(set_attr "op_type" "VRX,VRI,VRI,*")])
549
550; vlbrreph, vlbrrepf, vlbrrepg
551(define_insn "*vec_splats_bswap_vec<mode>"
552  [(set (match_operand:V_HW_HSD                           0 "register_operand"        "=v")
553	(bswap:V_HW_HSD
554	 (vec_duplicate:V_HW_HSD (match_operand:<non_vec> 1 "memory_operand"           "R"))))
555   (use (match_operand:V16QI                              2 "permute_pattern_operand"  "X"))]
556  "TARGET_VXE2"
557  "vlbrrep<bhfgq>\t%v0,%1"
558  [(set_attr "op_type" "VRX")])
559
560; Why do we need both? Shouldn't there be a canonical form?
561; vlbrreph, vlbrrepf, vlbrrepg
562(define_insn "*vec_splats_bswap_elem<mode>"
563  [(set (match_operand:V_HW_HSD                    0 "register_operand" "=v")
564	(vec_duplicate:V_HW_HSD
565	 (bswap:<non_vec> (match_operand:<non_vec> 1 "memory_operand"    "R"))))]
566  "TARGET_VXE2"
567  "vlbrrep<bhfgq>\t%v0,%1"
568  [(set_attr "op_type" "VRX")])
569
570; A TFmode operand resides in FPR register pairs while V1TF is in a
571; single vector register.
572(define_insn "*vec_tf_to_v1tf"
573  [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
574	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "v,R,v,G,d")))]
575  "TARGET_VX"
576  "@
577   vmrhg\t%v0,%1,%N1
578   vl\t%v0,%1%A1
579   vst\t%v1,%0%A0
580   vzero\t%v0
581   vlvgp\t%v0,%1,%N1"
582  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
583
584(define_insn "*vec_ti_to_v1ti"
585  [(set (match_operand:V1TI                   0 "nonimmediate_operand" "=v,v,R,  v,  v,v")
586	(vec_duplicate:V1TI (match_operand:TI 1 "general_operand"       "v,R,v,j00,jm1,d")))]
587  "TARGET_VX"
588  "@
589   vlr\t%v0,%v1
590   vl\t%v0,%1%A1
591   vst\t%v1,%0%A0
592   vzero\t%v0
593   vone\t%v0
594   vlvgp\t%v0,%1,%N1"
595  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRR")])
596
597; vec_splats is supposed to replicate op1 into all elements of op0
598; This splitter first sets the rightmost element of op0 to op1 and
599; then does a vec_splat to replicate that element into all other
600; elements.
601(define_split
602  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "")
603	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "register_operand" "")))]
604  "TARGET_VX && GENERAL_REG_P (operands[1])"
605  [(set (match_dup 0)
606	(unspec:V_128_NOSINGLE [(match_dup 1) (match_dup 2) (match_dup 0)] UNSPEC_VEC_SET))
607   (set (match_dup 0)
608	(vec_duplicate:V_128_NOSINGLE
609	 (vec_select:<non_vec>
610	  (match_dup 0) (parallel [(match_dup 2)]))))]
611{
612  operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
613})
614
615(define_expand "vcond<V_HW:mode><V_HW2:mode>"
616  [(set (match_operand:V_HW 0 "register_operand" "")
617	(if_then_else:V_HW
618	 (match_operator 3 "comparison_operator"
619			 [(match_operand:V_HW2 4 "register_operand" "")
620			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
621	 (match_operand:V_HW 1 "nonmemory_operand" "")
622	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
623  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
624{
625  s390_expand_vcond (operands[0], operands[1], operands[2],
626		     GET_CODE (operands[3]), operands[4], operands[5]);
627  DONE;
628})
629
630(define_expand "vcondu<V_HW:mode><V_HW2:mode>"
631  [(set (match_operand:V_HW 0 "register_operand" "")
632	(if_then_else:V_HW
633	 (match_operator 3 "comparison_operator"
634			 [(match_operand:V_HW2 4 "register_operand" "")
635			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
636	 (match_operand:V_HW 1 "nonmemory_operand" "")
637	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
638  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
639{
640  s390_expand_vcond (operands[0], operands[1], operands[2],
641		     GET_CODE (operands[3]), operands[4], operands[5]);
642  DONE;
643})
644
645; We only have HW support for byte vectors.  The middle-end is
646; supposed to lower the mode if required.
647(define_insn "vec_permv16qi"
648  [(set (match_operand:V16QI 0 "register_operand"               "=v")
649	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
650		       (match_operand:V16QI 2 "register_operand" "v")
651		       (match_operand:V16QI 3 "register_operand" "v")]
652		      UNSPEC_VEC_PERM))]
653  "TARGET_VX"
654  "vperm\t%v0,%v1,%v2,%v3"
655  [(set_attr "op_type" "VRR")])
656
657(define_insn "*vec_perm<mode>"
658  [(set (match_operand:VT_HW                                            0 "register_operand" "=v")
659	(subreg:VT_HW (unspec:V16QI [(subreg:V16QI (match_operand:VT_HW 1 "register_operand"  "v") 0)
660				     (subreg:V16QI (match_operand:VT_HW 2 "register_operand"  "v") 0)
661				     (match_operand:V16QI               3 "register_operand"  "v")]
662				    UNSPEC_VEC_PERM) 0))]
663  "TARGET_VX"
664  "vperm\t%v0,%v1,%v2,%v3"
665  [(set_attr "op_type" "VRR")])
666
667
668; vec_perm_const for V2DI using vpdi?
669
670;;
671;; Vector integer arithmetic instructions
672;;
673
674; vab, vah, vaf, vag, vaq
675
676; We use nonimmediate_operand instead of register_operand since it is
677; better to have the reloads into VRs instead of splitting the
678; operation into two DImode ADDs.
679(define_insn "<ti*>add<mode>3"
680  [(set (match_operand:VIT           0 "nonimmediate_operand" "=v")
681	(plus:VIT (match_operand:VIT 1 "nonimmediate_operand" "%v")
682		  (match_operand:VIT 2 "general_operand"       "v")))]
683  "TARGET_VX"
684  "va<bhfgq>\t%v0,%v1,%v2"
685  [(set_attr "op_type" "VRR")])
686
687; vsb, vsh, vsf, vsg, vsq
688(define_insn "<ti*>sub<mode>3"
689  [(set (match_operand:VIT            0 "nonimmediate_operand" "=v")
690	(minus:VIT (match_operand:VIT 1 "nonimmediate_operand"  "v")
691		   (match_operand:VIT 2 "general_operand"  "v")))]
692  "TARGET_VX"
693  "vs<bhfgq>\t%v0,%v1,%v2"
694  [(set_attr "op_type" "VRR")])
695
696; vmlb, vmlhw, vmlf
697(define_insn "mul<mode>3"
698  [(set (match_operand:VI_QHS              0 "register_operand" "=v")
699	(mult:VI_QHS (match_operand:VI_QHS 1 "register_operand" "%v")
700		     (match_operand:VI_QHS 2 "register_operand"  "v")))]
701  "TARGET_VX"
702  "vml<bhfgq><w>\t%v0,%v1,%v2"
703  [(set_attr "op_type" "VRR")])
704
705; vlcb, vlch, vlcf, vlcg
706(define_insn "neg<mode>2"
707  [(set (match_operand:VI         0 "register_operand" "=v")
708	(neg:VI (match_operand:VI 1 "register_operand"  "v")))]
709  "TARGET_VX"
710  "vlc<bhfgq>\t%v0,%v1"
711  [(set_attr "op_type" "VRR")])
712
713; vlpb, vlph, vlpf, vlpg
714(define_insn "abs<mode>2"
715  [(set (match_operand:VI         0 "register_operand" "=v")
716	(abs:VI (match_operand:VI 1 "register_operand"  "v")))]
717  "TARGET_VX"
718  "vlp<bhfgq>\t%v0,%v1"
719  [(set_attr "op_type" "VRR")])
720
721
722; Vector sum across
723
724; Sum across DImode parts of the 1st operand and add the rightmost
725; element of 2nd operand
726; vsumgh, vsumgf
727(define_insn "*vec_sum2<mode>"
728  [(set (match_operand:V2DI 0 "register_operand" "=v")
729	(unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "v")
730		      (match_operand:VI_HW_HS 2 "register_operand" "v")]
731		     UNSPEC_VEC_VSUMG))]
732  "TARGET_VX"
733  "vsumg<bhfgq>\t%v0,%v1,%v2"
734  [(set_attr "op_type" "VRR")])
735
736; vsumb, vsumh
737(define_insn "*vec_sum4<mode>"
738  [(set (match_operand:V4SI 0 "register_operand" "=v")
739	(unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "v")
740		      (match_operand:VI_HW_QH 2 "register_operand" "v")]
741		     UNSPEC_VEC_VSUM))]
742  "TARGET_VX"
743  "vsum<bhfgq>\t%v0,%v1,%v2"
744  [(set_attr "op_type" "VRR")])
745
746;;
747;; Vector bit instructions (int + fp)
748;;
749
750; Vector and
751
752(define_insn "and<mode>3"
753  [(set (match_operand:VT         0 "register_operand" "=v")
754	(and:VT (match_operand:VT 1 "register_operand" "%v")
755		(match_operand:VT 2 "register_operand"  "v")))]
756  "TARGET_VX"
757  "vn\t%v0,%v1,%v2"
758  [(set_attr "op_type" "VRR")])
759
760; Vector not and
761
762(define_insn "notand<mode>3"
763  [(set (match_operand:VT                 0 "register_operand" "=v")
764	(ior:VT (not:VT (match_operand:VT 1 "register_operand" "%v"))
765		(not:VT	(match_operand:VT 2 "register_operand"  "v"))))]
766  "TARGET_VXE"
767  "vnn\t%v0,%v1,%v2"
768  [(set_attr "op_type" "VRR")])
769
770; Vector or
771
772(define_insn "ior<mode>3"
773  [(set (match_operand:VT         0 "register_operand" "=v")
774	(ior:VT (match_operand:VT 1 "register_operand" "%v")
775		(match_operand:VT 2 "register_operand"  "v")))]
776  "TARGET_VX"
777  "vo\t%v0,%v1,%v2"
778  [(set_attr "op_type" "VRR")])
779
780; Vector or with complement
781
782(define_insn "ior_not<mode>3"
783  [(set (match_operand:VT                 0 "register_operand" "=v")
784	(ior:VT (not:VT (match_operand:VT 2 "register_operand"  "v"))
785		(match_operand:VT         1 "register_operand" "%v")))]
786  "TARGET_VXE"
787  "voc\t%v0,%v1,%v2"
788  [(set_attr "op_type" "VRR")])
789
790; Vector xor
791
792(define_insn "xor<mode>3"
793  [(set (match_operand:VT         0 "register_operand" "=v")
794	(xor:VT (match_operand:VT 1 "register_operand" "%v")
795		(match_operand:VT 2 "register_operand"  "v")))]
796  "TARGET_VX"
797  "vx\t%v0,%v1,%v2"
798  [(set_attr "op_type" "VRR")])
799
800; Vector not xor
801
802(define_insn "notxor<mode>3"
803  [(set (match_operand:VT                 0 "register_operand" "=v")
804	(not:VT (xor:VT (match_operand:VT 1 "register_operand" "%v")
805			(match_operand:VT 2 "register_operand"  "v"))))]
806  "TARGET_VXE"
807  "vnx\t%v0,%v1,%v2"
808  [(set_attr "op_type" "VRR")])
809
810; Bitwise inversion of a vector
811(define_insn "one_cmpl<mode>2"
812  [(set (match_operand:VT         0 "register_operand" "=v")
813	(not:VT (match_operand:VT 1 "register_operand"  "v")))]
814  "TARGET_VX"
815  "vnot\t%v0,%v1"
816  [(set_attr "op_type" "VRR")])
817
818; Vector population count
819
820(define_expand "popcount<mode>2"
821  [(set (match_operand:VI_HW                0 "register_operand" "=v")
822	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
823		      UNSPEC_POPCNT))]
824  "TARGET_VX"
825{
826  if (TARGET_VXE)
827    emit_insn (gen_popcount<mode>2_vxe (operands[0], operands[1]));
828  else
829    emit_insn (gen_popcount<mode>2_vx (operands[0], operands[1]));
830  DONE;
831})
832
833; vpopctb, vpopcth, vpopctf, vpopctg
834(define_insn "popcount<mode>2_vxe"
835  [(set (match_operand:VI_HW                0 "register_operand" "=v")
836	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
837		      UNSPEC_POPCNT))]
838  "TARGET_VXE"
839  "vpopct<bhfgq>\t%v0,%v1"
840  [(set_attr "op_type" "VRR")])
841
842(define_insn "popcountv16qi2_vx"
843  [(set (match_operand:V16QI                0 "register_operand" "=v")
844	(unspec:V16QI [(match_operand:V16QI 1 "register_operand"  "v")]
845		      UNSPEC_POPCNT))]
846  "TARGET_VX && !TARGET_VXE"
847  "vpopct\t%v0,%v1,0"
848  [(set_attr "op_type" "VRR")])
849
850; vpopct only counts bits in byte elements.  Bigger element sizes need
851; to be emulated.  Word and doubleword elements can use the sum across
852; instructions.  For halfword sized elements we do a shift of a copy
853; of the result, add it to the result and extend it to halfword
854; element size (unpack).
855
856(define_expand "popcountv8hi2_vx"
857  [(set (match_dup 2)
858	(unspec:V16QI [(subreg:V16QI (match_operand:V8HI 1 "register_operand" "v") 0)]
859		      UNSPEC_POPCNT))
860   ; Make a copy of the result
861   (set (match_dup 3) (match_dup 2))
862   ; Generate the shift count operand in a VR (8->byte 7)
863   (set (match_dup 4) (match_dup 5))
864   (set (match_dup 4) (unspec:V16QI [(const_int 8)
865				     (const_int 7)
866				     (match_dup 4)] UNSPEC_VEC_SET))
867   ; Vector shift right logical by one byte
868   (set (match_dup 3)
869	(unspec:V16QI [(match_dup 3) (match_dup 4)] UNSPEC_VEC_SRLB))
870   ; Add the shifted and the original result
871   (set (match_dup 2)
872	(plus:V16QI (match_dup 2) (match_dup 3)))
873   ; Generate mask for the odd numbered byte elements
874   (set (match_dup 3)
875	(const_vector:V16QI [(const_int 0) (const_int 255)
876			     (const_int 0) (const_int 255)
877			     (const_int 0) (const_int 255)
878			     (const_int 0) (const_int 255)
879			     (const_int 0) (const_int 255)
880			     (const_int 0) (const_int 255)
881			     (const_int 0) (const_int 255)
882			     (const_int 0) (const_int 255)]))
883   ; Zero out the even indexed bytes
884   (set (match_operand:V8HI 0 "register_operand" "=v")
885	(and:V8HI (subreg:V8HI (match_dup 2) 0)
886		  (subreg:V8HI (match_dup 3) 0)))
887]
888  "TARGET_VX && !TARGET_VXE"
889{
890  operands[2] = gen_reg_rtx (V16QImode);
891  operands[3] = gen_reg_rtx (V16QImode);
892  operands[4] = gen_reg_rtx (V16QImode);
893  operands[5] = CONST0_RTX (V16QImode);
894})
895
896(define_expand "popcountv4si2_vx"
897  [(set (match_dup 2)
898	(unspec:V16QI [(subreg:V16QI (match_operand:V4SI 1 "register_operand" "v") 0)]
899		      UNSPEC_POPCNT))
900   (set (match_operand:V4SI 0 "register_operand" "=v")
901	(unspec:V4SI [(match_dup 2) (match_dup 3)]
902		     UNSPEC_VEC_VSUM))]
903  "TARGET_VX && !TARGET_VXE"
904{
905  operands[2] = gen_reg_rtx (V16QImode);
906  operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
907})
908
909(define_expand "popcountv2di2_vx"
910  [(set (match_dup 2)
911	(unspec:V16QI [(subreg:V16QI (match_operand:V2DI 1 "register_operand" "v") 0)]
912		      UNSPEC_POPCNT))
913   (set (match_dup 3)
914	(unspec:V4SI [(match_dup 2) (match_dup 4)]
915		     UNSPEC_VEC_VSUM))
916   (set (match_operand:V2DI 0 "register_operand" "=v")
917	(unspec:V2DI [(match_dup 3) (match_dup 5)]
918		     UNSPEC_VEC_VSUMG))]
919  "TARGET_VX && !TARGET_VXE"
920{
921  operands[2] = gen_reg_rtx (V16QImode);
922  operands[3] = gen_reg_rtx (V4SImode);
923  operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
924  operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode));
925})
926
927; Count leading zeros
928; vclzb, vclzh, vclzf, vclzg
929(define_insn "clz<mode>2"
930  [(set (match_operand:V        0 "register_operand" "=v")
931	(clz:V (match_operand:V 1 "register_operand"  "v")))]
932  "TARGET_VX"
933  "vclz<bhfgq>\t%v0,%v1"
934  [(set_attr "op_type" "VRR")])
935
936; Count trailing zeros
937; vctzb, vctzh, vctzf, vctzg
938(define_insn "ctz<mode>2"
939  [(set (match_operand:V        0 "register_operand" "=v")
940	(ctz:V (match_operand:V 1 "register_operand"  "v")))]
941  "TARGET_VX"
942  "vctz<bhfgq>\t%v0,%v1"
943  [(set_attr "op_type" "VRR")])
944
945
946
947; Each vector element rotated by the corresponding vector element
948; verllvb, verllvh, verllvf, verllvg
949(define_insn "vrotl<mode>3"
950  [(set (match_operand:VI            0 "register_operand" "=v")
951	(rotate:VI (match_operand:VI 1 "register_operand"  "v")
952		   (match_operand:VI 2 "register_operand"  "v")))]
953  "TARGET_VX"
954  "verllv<bhfgq>\t%v0,%v1,%v2"
955  [(set_attr "op_type" "VRR")])
956
957
958; Vector rotate and shift by scalar instructions
959
960(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
961(define_code_attr vec_shifts_name [(ashift "ashl")    (ashiftrt "ashr")
962				   (lshiftrt "lshr")  (rotate "rotl")])
963(define_code_attr vec_shifts_mnem [(ashift "vesl")    (ashiftrt "vesra")
964				   (lshiftrt "vesrl") (rotate "verll")])
965
966; Each vector element rotated by a scalar
967(define_expand "<vec_shifts_name><mode>3"
968  [(set (match_operand:VI 0 "register_operand" "")
969	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
970		       (match_operand:SI 2 "nonmemory_operand" "")))]
971  "TARGET_VX")
972
973; verllb, verllh, verllf, verllg
974; veslb,  veslh,  veslf,  veslg
975; vesrab, vesrah, vesraf, vesrag
976; vesrlb, vesrlh, vesrlf, vesrlg
977(define_insn "*<vec_shifts_name><mode>3<addr_style_op>"
978  [(set (match_operand:VI                0 "register_operand"  "=v")
979	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand"   "v")
980		       (match_operand:SI 2 "nonmemory_operand" "an")))]
981  "TARGET_VX"
982  "<vec_shifts_mnem><bhfgq>\t%v0,%v1,<addr_style_op_ops>"
983  [(set_attr "op_type" "VRS")])
984
985; Shift each element by corresponding vector element
986
987; veslvb, veslvh, veslvf, veslvg
988(define_insn "vashl<mode>3"
989  [(set (match_operand:VI            0 "register_operand" "=v")
990	(ashift:VI (match_operand:VI 1 "register_operand"  "v")
991		   (match_operand:VI 2 "register_operand"  "v")))]
992  "TARGET_VX"
993  "veslv<bhfgq>\t%v0,%v1,%v2"
994  [(set_attr "op_type" "VRR")])
995
996; vesravb, vesravh, vesravf, vesravg
997(define_insn "vashr<mode>3"
998  [(set (match_operand:VI              0 "register_operand" "=v")
999	(ashiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1000		     (match_operand:VI 2 "register_operand"  "v")))]
1001  "TARGET_VX"
1002  "vesrav<bhfgq>\t%v0,%v1,%v2"
1003  [(set_attr "op_type" "VRR")])
1004
1005; vesrlvb, vesrlvh, vesrlvf, vesrlvg
1006(define_insn "vlshr<mode>3"
1007  [(set (match_operand:VI              0 "register_operand" "=v")
1008	(lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1009		     (match_operand:VI 2 "register_operand"  "v")))]
1010  "TARGET_VX"
1011  "vesrlv<bhfgq>\t%v0,%v1,%v2"
1012  [(set_attr "op_type" "VRR")])
1013
1014; Vector shift right logical by byte
1015
1016; Pattern used by e.g. popcount
1017(define_insn "*vec_srb<mode>"
1018  [(set (match_operand:V_128                0 "register_operand" "=v")
1019	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1020		       (match_operand:V16QI 2 "register_operand"  "v")]
1021		   UNSPEC_VEC_SRLB))]
1022  "TARGET_VX"
1023  "vsrlb\t%v0,%v1,%v2"
1024  [(set_attr "op_type" "VRR")])
1025
1026
1027; Vector shift left by byte
1028
1029(define_insn "*vec_slb<mode>"
1030  [(set (match_operand:V_128                0 "register_operand" "=v")
1031	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1032		    (match_operand:V16QI    2 "register_operand"  "v")]
1033		   UNSPEC_VEC_SLB))]
1034  "TARGET_VX"
1035  "vslb\t%v0,%v1,%v2"
1036  [(set_attr "op_type" "VRR")])
1037
1038; vec_shr is defined as shift towards element 0
1039; this means it is a left shift on BE targets!
1040(define_expand "vec_shr_<mode>"
1041  [(set (match_dup 3)
1042	(unspec:V16QI [(match_operand:SI 2 "const_shift_by_byte_operand" "")
1043		   (const_int 7)
1044		   (match_dup 3)]
1045		   UNSPEC_VEC_SET))
1046   (set (match_operand:V_128 0 "register_operand" "")
1047	(unspec:V_128 [(match_operand:V_128 1 "register_operand" "")
1048		    (match_dup 3)]
1049		   UNSPEC_VEC_SLB))]
1050  "TARGET_VX"
1051 {
1052   operands[3] = gen_reg_rtx(V16QImode);
1053 })
1054
1055; vmnb, vmnh, vmnf, vmng
1056(define_insn "smin<mode>3"
1057  [(set (match_operand:VI          0 "register_operand" "=v")
1058	(smin:VI (match_operand:VI 1 "register_operand" "%v")
1059		 (match_operand:VI 2 "register_operand"  "v")))]
1060  "TARGET_VX"
1061  "vmn<bhfgq>\t%v0,%v1,%v2"
1062  [(set_attr "op_type" "VRR")])
1063
1064; vmxb, vmxh, vmxf, vmxg
1065(define_insn "smax<mode>3"
1066  [(set (match_operand:VI          0 "register_operand" "=v")
1067	(smax:VI (match_operand:VI 1 "register_operand" "%v")
1068		 (match_operand:VI 2 "register_operand"  "v")))]
1069  "TARGET_VX"
1070  "vmx<bhfgq>\t%v0,%v1,%v2"
1071  [(set_attr "op_type" "VRR")])
1072
1073; vmnlb, vmnlh, vmnlf, vmnlg
1074(define_insn "umin<mode>3"
1075  [(set (match_operand:VI          0 "register_operand" "=v")
1076	(umin:VI (match_operand:VI 1 "register_operand" "%v")
1077		 (match_operand:VI 2 "register_operand"  "v")))]
1078  "TARGET_VX"
1079  "vmnl<bhfgq>\t%v0,%v1,%v2"
1080  [(set_attr "op_type" "VRR")])
1081
1082; vmxlb, vmxlh, vmxlf, vmxlg
1083(define_insn "umax<mode>3"
1084  [(set (match_operand:VI          0 "register_operand" "=v")
1085	(umax:VI (match_operand:VI 1 "register_operand" "%v")
1086		 (match_operand:VI 2 "register_operand"  "v")))]
1087  "TARGET_VX"
1088  "vmxl<bhfgq>\t%v0,%v1,%v2"
1089  [(set_attr "op_type" "VRR")])
1090
1091; vmeb, vmeh, vmef
1092(define_insn "vec_widen_smult_even_<mode>"
1093  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1094	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1095			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1096			     UNSPEC_VEC_SMULT_EVEN))]
1097  "TARGET_VX"
1098  "vme<bhfgq>\t%v0,%v1,%v2"
1099  [(set_attr "op_type" "VRR")])
1100
1101; vmleb, vmleh, vmlef
1102(define_insn "vec_widen_umult_even_<mode>"
1103  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1104	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1105			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1106			     UNSPEC_VEC_UMULT_EVEN))]
1107  "TARGET_VX"
1108  "vmle<bhfgq>\t%v0,%v1,%v2"
1109  [(set_attr "op_type" "VRR")])
1110
1111; vmob, vmoh, vmof
1112(define_insn "vec_widen_smult_odd_<mode>"
1113  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1114	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1115			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1116			     UNSPEC_VEC_SMULT_ODD))]
1117  "TARGET_VX"
1118  "vmo<bhfgq>\t%v0,%v1,%v2"
1119  [(set_attr "op_type" "VRR")])
1120
1121; vmlob, vmloh, vmlof
1122(define_insn "vec_widen_umult_odd_<mode>"
1123  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1124	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1125			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1126			     UNSPEC_VEC_UMULT_ODD))]
1127  "TARGET_VX"
1128  "vmlo<bhfgq>\t%v0,%v1,%v2"
1129  [(set_attr "op_type" "VRR")])
1130
1131
1132; Widening hi/lo multiplications
1133
1134; The S/390 instructions vml and vmh return the low or high parts of
1135; the double sized result elements in the corresponding elements of
1136; the target register.  That's NOT what the vec_widen_umult_lo/hi
1137; patterns are expected to do.
1138
1139; We emulate the widening lo/hi multiplies with the even/odd versions
1140; followed by a vector merge
1141
1142
1143(define_expand "vec_widen_umult_lo_<mode>"
1144  [(set (match_dup 3)
1145	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1146			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1147			     UNSPEC_VEC_UMULT_EVEN))
1148   (set (match_dup 4)
1149	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1150			     UNSPEC_VEC_UMULT_ODD))
1151   (set (match_operand:<vec_double>                 0 "register_operand" "=v")
1152	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1153			     UNSPEC_VEC_MERGEL))]
1154  "TARGET_VX"
1155 {
1156   operands[3] = gen_reg_rtx (<vec_double>mode);
1157   operands[4] = gen_reg_rtx (<vec_double>mode);
1158 })
1159
1160(define_expand "vec_widen_umult_hi_<mode>"
1161  [(set (match_dup 3)
1162	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1163			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1164			     UNSPEC_VEC_UMULT_EVEN))
1165   (set (match_dup 4)
1166	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1167			     UNSPEC_VEC_UMULT_ODD))
1168   (set (match_operand:<vec_double>                 0 "register_operand" "=v")
1169	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1170			     UNSPEC_VEC_MERGEH))]
1171  "TARGET_VX"
1172 {
1173   operands[3] = gen_reg_rtx (<vec_double>mode);
1174   operands[4] = gen_reg_rtx (<vec_double>mode);
1175 })
1176
1177(define_expand "vec_widen_smult_lo_<mode>"
1178  [(set (match_dup 3)
1179	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1180			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1181			     UNSPEC_VEC_SMULT_EVEN))
1182   (set (match_dup 4)
1183	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1184			     UNSPEC_VEC_SMULT_ODD))
1185   (set (match_operand:<vec_double>                 0 "register_operand" "=v")
1186	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1187			     UNSPEC_VEC_MERGEL))]
1188  "TARGET_VX"
1189 {
1190   operands[3] = gen_reg_rtx (<vec_double>mode);
1191   operands[4] = gen_reg_rtx (<vec_double>mode);
1192 })
1193
1194(define_expand "vec_widen_smult_hi_<mode>"
1195  [(set (match_dup 3)
1196	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
1197			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1198			     UNSPEC_VEC_SMULT_EVEN))
1199   (set (match_dup 4)
1200	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1201			     UNSPEC_VEC_SMULT_ODD))
1202   (set (match_operand:<vec_double>                 0 "register_operand" "=v")
1203	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1204			     UNSPEC_VEC_MERGEH))]
1205  "TARGET_VX"
1206 {
1207   operands[3] = gen_reg_rtx (<vec_double>mode);
1208   operands[4] = gen_reg_rtx (<vec_double>mode);
1209 })
1210
1211; vec_widen_ushiftl_hi
1212; vec_widen_ushiftl_lo
1213; vec_widen_sshiftl_hi
1214; vec_widen_sshiftl_lo
1215
1216;;
1217;; Vector floating point arithmetic instructions
1218;;
1219
1220; vfasb, vfadb, wfasb, wfadb, wfaxb
1221(define_insn "add<mode>3"
1222  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1223	(plus:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1224		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1225  "TARGET_VX"
1226  "<vw>fa<sdx>b\t%v0,%v1,%v2"
1227  [(set_attr "op_type" "VRR")])
1228
1229; vfssb, vfsdb, wfssb, wfsdb, wfsxb
1230(define_insn "sub<mode>3"
1231  [(set (match_operand:VF_HW              0 "register_operand" "=v")
1232	(minus:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1233		     (match_operand:VF_HW 2 "register_operand"  "v")))]
1234  "TARGET_VX"
1235  "<vw>fs<sdx>b\t%v0,%v1,%v2"
1236  [(set_attr "op_type" "VRR")])
1237
1238; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
1239(define_insn "mul<mode>3"
1240  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1241	(mult:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1242		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1243  "TARGET_VX"
1244  "<vw>fm<sdx>b\t%v0,%v1,%v2"
1245  [(set_attr "op_type" "VRR")])
1246
1247; vfdsb, vfddb, wfdsb, wfddb, wfdxb
1248(define_insn "div<mode>3"
1249  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1250	(div:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1251		   (match_operand:VF_HW 2 "register_operand"  "v")))]
1252  "TARGET_VX"
1253  "<vw>fd<sdx>b\t%v0,%v1,%v2"
1254  [(set_attr "op_type" "VRR")])
1255
1256; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
1257(define_insn "sqrt<mode>2"
1258  [(set (match_operand:VF_HW           0 "register_operand" "=v")
1259	(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")))]
1260  "TARGET_VX"
1261  "<vw>fsq<sdx>b\t%v0,%v1"
1262  [(set_attr "op_type" "VRR")])
1263
1264; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
1265(define_insn "fma<mode>4"
1266  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1267	(fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1268		   (match_operand:VF_HW 2 "register_operand"  "v")
1269		   (match_operand:VF_HW 3 "register_operand"  "v")))]
1270  "TARGET_VX"
1271  "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
1272  [(set_attr "op_type" "VRR")])
1273
1274; vfmssb, vfmsdb, wfmssb, wfmsdb, wfmsxb
1275(define_insn "fms<mode>4"
1276  [(set (match_operand:VF_HW                     0 "register_operand" "=v")
1277	(fma:VF_HW (match_operand:VF_HW          1 "register_operand" "%v")
1278		   (match_operand:VF_HW          2 "register_operand"  "v")
1279		 (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v"))))]
1280  "TARGET_VX"
1281  "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
1282  [(set_attr "op_type" "VRR")])
1283
1284; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb
1285(define_insn "neg_fma<mode>4"
1286  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1287	(neg:VF_HW
1288	 (fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1289		    (match_operand:VF_HW 2 "register_operand"  "v")
1290		    (match_operand:VF_HW 3 "register_operand"  "v"))))]
1291  "TARGET_VXE"
1292  "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
1293  [(set_attr "op_type" "VRR")])
1294
1295; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb
1296(define_insn "neg_fms<mode>4"
1297  [(set (match_operand:VF_HW                      0 "register_operand" "=v")
1298	(neg:VF_HW
1299	 (fma:VF_HW (match_operand:VF_HW          1 "register_operand" "%v")
1300		    (match_operand:VF_HW          2 "register_operand"  "v")
1301		  (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v")))))]
1302  "TARGET_VXE"
1303  "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
1304  [(set_attr "op_type" "VRR")])
1305
1306; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
1307(define_insn "neg<mode>2"
1308  [(set (match_operand:VFT          0 "register_operand" "=v")
1309	(neg:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1310  "TARGET_VX"
1311  "<vw>flc<sdx>b\t%v0,%v1"
1312  [(set_attr "op_type" "VRR")])
1313
1314; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
1315(define_insn "abs<mode>2"
1316  [(set (match_operand:VFT          0 "register_operand" "=v")
1317	(abs:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1318  "TARGET_VX"
1319  "<vw>flp<sdx>b\t%v0,%v1"
1320  [(set_attr "op_type" "VRR")])
1321
1322; vflnsb, vflndb, wflnsb, wflndb, wflnxb
1323(define_insn "negabs<mode>2"
1324  [(set (match_operand:VFT                   0 "register_operand" "=v")
1325	(neg:VFT (abs:VFT (match_operand:VFT 1 "register_operand"  "v"))))]
1326  "TARGET_VX"
1327  "<vw>fln<sdx>b\t%v0,%v1"
1328  [(set_attr "op_type" "VRR")])
1329
1330(define_expand "smax<mode>3"
1331  [(set (match_operand:VF_HW             0 "register_operand")
1332	(smax:VF_HW (match_operand:VF_HW 1 "register_operand")
1333		    (match_operand:VF_HW 2 "register_operand")))]
1334  "TARGET_VX")
1335
1336; vfmaxsb, vfmaxdb, wfmaxsb, wfmaxdb, wfmaxxb
1337(define_insn "*smax<mode>3_vxe"
1338  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1339	(smax:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1340		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1341  "TARGET_VXE"
1342  "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
1343  [(set_attr "op_type" "VRR")])
1344
1345; Emulate with compare + select
1346(define_insn_and_split "*smaxv2df3_vx"
1347  [(set (match_operand:V2DF            0 "register_operand" "=v")
1348	(smax:V2DF (match_operand:V2DF 1 "register_operand" "%v")
1349		   (match_operand:V2DF 2 "register_operand"  "v")))]
1350  "TARGET_VX && !TARGET_VXE"
1351  "#"
1352  "&& 1"
1353  [(set (match_dup 3)
1354	(gt:V2DI (match_dup 1) (match_dup 2)))
1355   (set (match_dup 0)
1356	(if_then_else:V2DF
1357	 (eq (match_dup 3) (match_dup 4))
1358	 (match_dup 2)
1359	 (match_dup 1)))]
1360{
1361  operands[3] = gen_reg_rtx (V2DImode);
1362  operands[4] = CONST0_RTX (V2DImode);
1363})
1364
1365(define_expand "smin<mode>3"
1366  [(set (match_operand:VF_HW             0 "register_operand")
1367	(smin:VF_HW (match_operand:VF_HW 1 "register_operand")
1368		    (match_operand:VF_HW 2 "register_operand")))]
1369  "TARGET_VX")
1370
1371; vfminsb, vfmindb, wfminsb, wfmindb, wfminxb
1372(define_insn "*smin<mode>3_vxe"
1373  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1374	(smin:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
1375		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1376  "TARGET_VXE"
1377  "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
1378  [(set_attr "op_type" "VRR")])
1379
1380; Emulate with compare + select
1381(define_insn_and_split "*sminv2df3_vx"
1382  [(set (match_operand:V2DF            0 "register_operand" "=v")
1383	(smin:V2DF (match_operand:V2DF 1 "register_operand" "%v")
1384		   (match_operand:V2DF 2 "register_operand"  "v")))]
1385  "TARGET_VX && !TARGET_VXE"
1386  "#"
1387  "&& 1"
1388  [(set (match_dup 3)
1389	(gt:V2DI (match_dup 1) (match_dup 2)))
1390   (set (match_dup 0)
1391	(if_then_else:V2DF
1392	 (eq (match_dup 3) (match_dup 4))
1393	 (match_dup 1)
1394	 (match_dup 2)))]
1395{
1396  operands[3] = gen_reg_rtx (V2DImode);
1397  operands[4] = CONST0_RTX (V2DImode);
1398})
1399
1400; Vector copysign, implement using vector select
1401(define_expand "copysign<mode>3"
1402  [(set (match_operand:VFT 0 "register_operand" "")
1403	(if_then_else:VFT
1404	 (eq (match_dup 3)
1405	     (match_dup 4))
1406	 (match_operand:VFT 1 "register_operand"  "")
1407	 (match_operand:VFT 2 "register_operand"  "")))]
1408  "TARGET_VX"
1409{
1410  int sz = GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
1411  int prec = GET_MODE_PRECISION (GET_MODE_INNER (<tointvec>mode));
1412  wide_int mask_val = wi::shwi (1l << (sz - 1), prec);
1413
1414  rtx mask = gen_reg_rtx (<tointvec>mode);
1415
1416  int nunits = GET_MODE_NUNITS (<tointvec>mode);
1417  rtvec v = rtvec_alloc (nunits);
1418  for (int i = 0; i < nunits; i++)
1419    RTVEC_ELT (v, i) = GEN_INT (mask_val.to_shwi ());
1420
1421  mask = gen_rtx_CONST_VECTOR (<tointvec>mode, v);
1422  operands[3] = force_reg (<tointvec>mode, mask);
1423  operands[4] = CONST0_RTX (<tointvec>mode);
1424})
1425
1426;;
1427;; Integer compares
1428;;
1429
1430(define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode>_nocc"
1431  [(set (match_operand:VI                 2 "register_operand" "=v")
1432	(VICMP_HW_OP:VI (match_operand:VI 0 "register_operand"  "v")
1433			(match_operand:VI 1 "register_operand"  "v")))]
1434  "TARGET_VX"
1435  "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1"
1436  [(set_attr "op_type" "VRR")])
1437
1438
1439;;
1440;; Floating point compares
1441;;
1442
1443; EQ, GT, GE
1444; vfcesb, vfcedb, wfcexb, vfchsb, vfchdb, wfchxb, vfchesb, vfchedb, wfchexb
1445(define_insn "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc"
1446  [(set (match_operand:<tointvec>                  0 "register_operand" "=v")
1447	(VFCMP_HW_OP:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1448			     (match_operand:VFT 2 "register_operand"  "v")))]
1449   "TARGET_VX"
1450   "<vw>fc<VFCMP_HW_OP:asm_fcmp_op><sdx>b\t%v0,%v1,%v2"
1451  [(set_attr "op_type" "VRR")])
1452
1453; Expanders for not directly supported comparisons
1454
1455; UNEQ a u== b -> !(a > b | b > a)
1456(define_expand "vec_cmpuneq<mode>"
1457  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1458	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1459		    (match_operand:VFT 2 "register_operand"  "v")))
1460   (set (match_dup 3)
1461	(gt:<tointvec> (match_dup 2) (match_dup 1)))
1462   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
1463   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
1464  "TARGET_VX"
1465{
1466  operands[3] = gen_reg_rtx (<tointvec>mode);
1467})
1468
1469(define_expand "vec_cmpuneq"
1470  [(match_operand 0 "register_operand" "")
1471   (match_operand 1 "register_operand" "")
1472   (match_operand 2 "register_operand" "")]
1473  "TARGET_VX"
1474{
1475  if (GET_MODE (operands[1]) == V4SFmode)
1476    emit_insn (gen_vec_cmpuneqv4sf (operands[0], operands[1], operands[2]));
1477  else if (GET_MODE (operands[1]) == V2DFmode)
1478    emit_insn (gen_vec_cmpuneqv2df (operands[0], operands[1], operands[2]));
1479  else
1480    gcc_unreachable ();
1481
1482  DONE;
1483})
1484
1485; LTGT a <> b -> a > b | b > a
1486(define_expand "vec_cmpltgt<mode>"
1487  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1488	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1489		    (match_operand:VFT 2 "register_operand"  "v")))
1490   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
1491   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
1492  "TARGET_VX"
1493{
1494  operands[3] = gen_reg_rtx (<tointvec>mode);
1495})
1496
1497(define_expand "vec_cmpltgt"
1498  [(match_operand 0 "register_operand" "")
1499   (match_operand 1 "register_operand" "")
1500   (match_operand 2 "register_operand" "")]
1501  "TARGET_VX"
1502{
1503  if (GET_MODE (operands[1]) == V4SFmode)
1504    emit_insn (gen_vec_cmpltgtv4sf (operands[0], operands[1], operands[2]));
1505  else if (GET_MODE (operands[1]) == V2DFmode)
1506    emit_insn (gen_vec_cmpltgtv2df (operands[0], operands[1], operands[2]));
1507  else
1508    gcc_unreachable ();
1509
1510  DONE;
1511})
1512
1513; ORDERED (a, b): a >= b | b > a
1514(define_expand "vec_ordered<mode>"
1515  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
1516	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1517		 (match_operand:VFT 2 "register_operand"  "v")))
1518   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
1519   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
1520  "TARGET_VX"
1521{
1522  operands[3] = gen_reg_rtx (<tointvec>mode);
1523})
1524
1525(define_expand "vec_ordered"
1526  [(match_operand 0 "register_operand" "")
1527   (match_operand 1 "register_operand" "")
1528   (match_operand 2 "register_operand" "")]
1529  "TARGET_VX"
1530{
1531  if (GET_MODE (operands[1]) == V4SFmode)
1532    emit_insn (gen_vec_orderedv4sf (operands[0], operands[1], operands[2]));
1533  else if (GET_MODE (operands[1]) == V2DFmode)
1534    emit_insn (gen_vec_orderedv2df (operands[0], operands[1], operands[2]));
1535  else
1536    gcc_unreachable ();
1537
1538  DONE;
1539})
1540
1541; UNORDERED (a, b): !ORDERED (a, b)
1542(define_expand "vec_unordered<mode>"
1543  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
1544	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1545		 (match_operand:VFT 2 "register_operand"  "v")))
1546   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
1547   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
1548   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
1549  "TARGET_VX"
1550{
1551  operands[3] = gen_reg_rtx (<tointvec>mode);
1552})
1553
1554(define_expand "vec_unordered"
1555  [(match_operand 0 "register_operand" "")
1556   (match_operand 1 "register_operand" "")
1557   (match_operand 2 "register_operand" "")]
1558  "TARGET_VX"
1559{
1560  if (GET_MODE (operands[1]) == V4SFmode)
1561    emit_insn (gen_vec_unorderedv4sf (operands[0], operands[1], operands[2]));
1562  else if (GET_MODE (operands[1]) == V2DFmode)
1563    emit_insn (gen_vec_unorderedv2df (operands[0], operands[1], operands[2]));
1564  else
1565    gcc_unreachable ();
1566
1567  DONE;
1568})
1569
1570(define_insn "*vec_load_pair<mode>"
1571  [(set (match_operand:V_HW_64                       0 "register_operand" "=v,v")
1572	(vec_concat:V_HW_64 (match_operand:<non_vec> 1 "register_operand"  "d,v")
1573			    (match_operand:<non_vec> 2 "register_operand"  "d,v")))]
1574  "TARGET_VX"
1575  "@
1576   vlvgp\t%v0,%1,%2
1577   vmrhg\t%v0,%v1,%v2"
1578  [(set_attr "op_type" "VRR,VRR")])
1579
1580(define_insn "vllv16qi"
1581  [(set (match_operand:V16QI              0 "register_operand" "=v")
1582	(unspec:V16QI [(match_operand:SI  1 "register_operand"  "d")
1583		       (match_operand:BLK 2 "memory_operand"    "Q")]
1584		      UNSPEC_VEC_LOAD_LEN))]
1585  "TARGET_VX"
1586  "vll\t%v0,%1,%2"
1587  [(set_attr "op_type" "VRS")])
1588
1589; vfenebs, vfenehs, vfenefs
1590; vfenezbs, vfenezhs, vfenezfs
1591(define_insn "vec_vfenes<mode>"
1592  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1593	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1594			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
1595			   (match_operand:QI 3 "const_mask_operand" "C")]
1596			  UNSPEC_VEC_VFENE))
1597   (set (reg:CCRAW CC_REGNUM)
1598	(unspec:CCRAW [(match_dup 1)
1599		       (match_dup 2)
1600		       (match_dup 3)]
1601		      UNSPEC_VEC_VFENECC))]
1602  "TARGET_VX"
1603{
1604  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
1605
1606  gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
1607  flags &= ~VSTRING_FLAG_CS;
1608
1609  if (flags == VSTRING_FLAG_ZS)
1610    return "vfenez<bhfgq>s\t%v0,%v1,%v2";
1611  return "vfene<bhfgq>s\t%v0,%v1,%v2";
1612}
1613  [(set_attr "op_type" "VRR")])
1614
1615
1616; Vector select
1617
1618; The following splitters simplify vec_sel for constant 0 or -1
1619; selection sources.  This is required to generate efficient code for
1620; vcond.
1621
1622; a = b == c;
1623(define_split
1624  [(set (match_operand:V 0 "register_operand" "")
1625	(if_then_else:V
1626	 (eq (match_operand:<tointvec> 3 "register_operand" "")
1627	     (match_operand:V 4 "const0_operand" ""))
1628	 (match_operand:V 1 "const0_operand" "")
1629	 (match_operand:V 2 "all_ones_operand" "")))]
1630  "TARGET_VX"
1631  [(set (match_dup 0) (match_dup 3))]
1632{
1633  PUT_MODE (operands[3], <V:MODE>mode);
1634})
1635
1636; a = ~(b == c)
1637(define_split
1638  [(set (match_operand:V 0 "register_operand" "")
1639	(if_then_else:V
1640	 (eq (match_operand:<tointvec> 3 "register_operand" "")
1641	     (match_operand:V 4 "const0_operand" ""))
1642	 (match_operand:V 1 "all_ones_operand" "")
1643	 (match_operand:V 2 "const0_operand" "")))]
1644  "TARGET_VX"
1645  [(set (match_dup 0) (not:V (match_dup 3)))]
1646{
1647  PUT_MODE (operands[3], <V:MODE>mode);
1648})
1649
1650; a = b != c
1651(define_split
1652  [(set (match_operand:V 0 "register_operand" "")
1653	(if_then_else:V
1654	 (ne (match_operand:<tointvec> 3 "register_operand" "")
1655	     (match_operand:V 4 "const0_operand" ""))
1656	 (match_operand:V 1 "all_ones_operand" "")
1657	 (match_operand:V 2 "const0_operand" "")))]
1658  "TARGET_VX"
1659  [(set (match_dup 0) (match_dup 3))]
1660{
1661  PUT_MODE (operands[3], <V:MODE>mode);
1662})
1663
1664; a = ~(b != c)
1665(define_split
1666  [(set (match_operand:V 0 "register_operand" "")
1667	(if_then_else:V
1668	 (ne (match_operand:<tointvec> 3 "register_operand" "")
1669	     (match_operand:V 4 "const0_operand" ""))
1670	 (match_operand:V 1 "const0_operand" "")
1671	 (match_operand:V 2 "all_ones_operand" "")))]
1672  "TARGET_VX"
1673  [(set (match_dup 0) (not:V (match_dup 3)))]
1674{
1675  PUT_MODE (operands[3], <V:MODE>mode);
1676})
1677
1678; op0 = op3 == 0 ? op1 : op2
1679(define_insn "*vec_sel0<mode>"
1680  [(set (match_operand:V 0 "register_operand" "=v")
1681	(if_then_else:V
1682	 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1683	     (match_operand:<tointvec> 4 "const0_operand" ""))
1684	 (match_operand:V 1 "register_operand" "v")
1685	 (match_operand:V 2 "register_operand" "v")))]
1686  "TARGET_VX"
1687  "vsel\t%v0,%2,%1,%3"
1688  [(set_attr "op_type" "VRR")])
1689
1690; op0 = !op3 == 0 ? op1 : op2
1691(define_insn "*vec_sel0<mode>"
1692  [(set (match_operand:V 0 "register_operand" "=v")
1693	(if_then_else:V
1694	 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1695	     (match_operand:<tointvec> 4 "const0_operand" ""))
1696	 (match_operand:V 1 "register_operand" "v")
1697	 (match_operand:V 2 "register_operand" "v")))]
1698  "TARGET_VX"
1699  "vsel\t%v0,%1,%2,%3"
1700  [(set_attr "op_type" "VRR")])
1701
1702; op0 = op3 == -1 ? op1 : op2
1703(define_insn "*vec_sel1<mode>"
1704  [(set (match_operand:V 0 "register_operand" "=v")
1705	(if_then_else:V
1706	 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1707	     (match_operand:<tointvec> 4 "all_ones_operand" ""))
1708	 (match_operand:V 1 "register_operand" "v")
1709	 (match_operand:V 2 "register_operand" "v")))]
1710  "TARGET_VX"
1711  "vsel\t%v0,%1,%2,%3"
1712  [(set_attr "op_type" "VRR")])
1713
1714; op0 = !op3 == -1 ? op1 : op2
1715(define_insn "*vec_sel1<mode>"
1716  [(set (match_operand:V 0 "register_operand" "=v")
1717	(if_then_else:V
1718	 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1719	     (match_operand:<tointvec> 4 "all_ones_operand" ""))
1720	 (match_operand:V 1 "register_operand" "v")
1721	 (match_operand:V 2 "register_operand" "v")))]
1722  "TARGET_VX"
1723  "vsel\t%v0,%2,%1,%3"
1724  [(set_attr "op_type" "VRR")])
1725
1726; vec_pack_trunc
1727
1728; vpkh, vpkf, vpkg
1729(define_insn "vec_pack_trunc_<mode>"
1730  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1731	(vec_concat:<vec_half>
1732	 (truncate:<vec_halfhalf>
1733	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1734	 (truncate:<vec_halfhalf>
1735	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1736  "TARGET_VX"
1737  "vpk<bhfgq>\t%0,%1,%2"
1738  [(set_attr "op_type" "VRR")])
1739
1740; vpksh, vpksf, vpksg
1741(define_insn "vec_pack_ssat_<mode>"
1742  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1743	(vec_concat:<vec_half>
1744	 (ss_truncate:<vec_halfhalf>
1745	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1746	 (ss_truncate:<vec_halfhalf>
1747	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1748  "TARGET_VX"
1749  "vpks<bhfgq>\t%0,%1,%2"
1750  [(set_attr "op_type" "VRR")])
1751
1752; vpklsh, vpklsf, vpklsg
1753(define_insn "vec_pack_usat_<mode>"
1754  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1755	(vec_concat:<vec_half>
1756	 (us_truncate:<vec_halfhalf>
1757	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1758	 (us_truncate:<vec_halfhalf>
1759	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1760  "TARGET_VX"
1761  "vpkls<bhfgq>\t%0,%1,%2"
1762  [(set_attr "op_type" "VRR")])
1763
1764;; vector unpack v16qi
1765
1766; signed
1767
1768(define_insn "vec_unpacks_hi_v16qi"
1769  [(set (match_operand:V8HI 0 "register_operand" "=v")
1770	(sign_extend:V8HI
1771	 (vec_select:V8QI
1772	  (match_operand:V16QI 1 "register_operand" "v")
1773	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
1774		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1775  "TARGET_VX"
1776  "vuphb\t%0,%1"
1777  [(set_attr "op_type" "VRR")])
1778
1779(define_insn "vec_unpacks_lo_v16qi"
1780  [(set (match_operand:V8HI 0 "register_operand" "=v")
1781	(sign_extend:V8HI
1782	 (vec_select:V8QI
1783	  (match_operand:V16QI 1 "register_operand" "v")
1784	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
1785		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
1786  "TARGET_VX"
1787  "vuplb\t%0,%1"
1788  [(set_attr "op_type" "VRR")])
1789
1790; unsigned
1791
1792(define_insn "vec_unpacku_hi_v16qi"
1793  [(set (match_operand:V8HI 0 "register_operand" "=v")
1794	(zero_extend:V8HI
1795	 (vec_select:V8QI
1796	  (match_operand:V16QI 1 "register_operand" "v")
1797	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
1798		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1799  "TARGET_VX"
1800  "vuplhb\t%0,%1"
1801  [(set_attr "op_type" "VRR")])
1802
1803(define_insn "vec_unpacku_lo_v16qi"
1804  [(set (match_operand:V8HI 0 "register_operand" "=v")
1805	(zero_extend:V8HI
1806	 (vec_select:V8QI
1807	  (match_operand:V16QI 1 "register_operand" "v")
1808	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
1809		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
1810  "TARGET_VX"
1811  "vupllb\t%0,%1"
1812  [(set_attr "op_type" "VRR")])
1813
1814;; vector unpack v8hi
1815
1816; signed
1817
1818(define_insn "vec_unpacks_hi_v8hi"
1819  [(set (match_operand:V4SI 0 "register_operand" "=v")
1820	(sign_extend:V4SI
1821	 (vec_select:V4HI
1822	  (match_operand:V8HI 1 "register_operand" "v")
1823	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
1824  "TARGET_VX"
1825  "vuphh\t%0,%1"
1826  [(set_attr "op_type" "VRR")])
1827
1828(define_insn "vec_unpacks_lo_v8hi"
1829  [(set (match_operand:V4SI 0 "register_operand" "=v")
1830	(sign_extend:V4SI
1831	 (vec_select:V4HI
1832	  (match_operand:V8HI 1 "register_operand" "v")
1833	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1834  "TARGET_VX"
1835  "vuplhw\t%0,%1"
1836  [(set_attr "op_type" "VRR")])
1837
1838; unsigned
1839
1840(define_insn "vec_unpacku_hi_v8hi"
1841  [(set (match_operand:V4SI 0 "register_operand" "=v")
1842	(zero_extend:V4SI
1843	 (vec_select:V4HI
1844	  (match_operand:V8HI 1 "register_operand" "v")
1845	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
1846  "TARGET_VX"
1847  "vuplhh\t%0,%1"
1848  [(set_attr "op_type" "VRR")])
1849
1850(define_insn "vec_unpacku_lo_v8hi"
1851  [(set (match_operand:V4SI 0 "register_operand" "=v")
1852	(zero_extend:V4SI
1853	 (vec_select:V4HI
1854	  (match_operand:V8HI 1 "register_operand" "v")
1855	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1856  "TARGET_VX"
1857  "vupllh\t%0,%1"
1858  [(set_attr "op_type" "VRR")])
1859
1860;; vector unpack v4si
1861
1862; signed
1863
1864(define_insn "vec_unpacks_hi_v4si"
1865  [(set (match_operand:V2DI 0 "register_operand" "=v")
1866	(sign_extend:V2DI
1867	 (vec_select:V2SI
1868	  (match_operand:V4SI 1 "register_operand" "v")
1869	  (parallel [(const_int 0)(const_int 1)]))))]
1870  "TARGET_VX"
1871  "vuphf\t%0,%1"
1872  [(set_attr "op_type" "VRR")])
1873
1874(define_insn "vec_unpacks_lo_v4si"
1875  [(set (match_operand:V2DI 0 "register_operand" "=v")
1876	(sign_extend:V2DI
1877	 (vec_select:V2SI
1878	  (match_operand:V4SI 1 "register_operand" "v")
1879	  (parallel [(const_int 2)(const_int 3)]))))]
1880  "TARGET_VX"
1881  "vuplf\t%0,%1"
1882  [(set_attr "op_type" "VRR")])
1883
1884; unsigned
1885
1886(define_insn "vec_unpacku_hi_v4si"
1887  [(set (match_operand:V2DI 0 "register_operand" "=v")
1888	(zero_extend:V2DI
1889	 (vec_select:V2SI
1890	  (match_operand:V4SI 1 "register_operand" "v")
1891	  (parallel [(const_int 0)(const_int 1)]))))]
1892  "TARGET_VX"
1893  "vuplhf\t%0,%1"
1894  [(set_attr "op_type" "VRR")])
1895
1896(define_insn "vec_unpacku_lo_v4si"
1897  [(set (match_operand:V2DI 0 "register_operand" "=v")
1898	(zero_extend:V2DI
1899	 (vec_select:V2SI
1900	  (match_operand:V4SI 1 "register_operand" "v")
1901	  (parallel [(const_int 2)(const_int 3)]))))]
1902  "TARGET_VX"
1903  "vupllf\t%0,%1"
1904  [(set_attr "op_type" "VRR")])
1905
1906;; vector load lengthened
1907
1908; vflls float -> double
1909(define_insn "*vec_extendv4sf"
1910  [(set (match_operand:V2DF 0 "register_operand" "=v")
1911	(float_extend:V2DF
1912	 (vec_select:V2SF
1913	  (match_operand:V4SF 1 "register_operand" "v")
1914	  (parallel [(const_int 0) (const_int 2)]))))]
1915  "TARGET_VX"
1916  "vldeb\t%v0,%v1"
1917  [(set_attr "op_type" "VRR")])
1918
1919(define_expand "vec_unpacks_lo_v4sf"
1920  [(set (match_dup 2)
1921	(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
1922		      (match_dup 1)]
1923		     UNSPEC_VEC_MERGEL))
1924   (set (match_operand:V2DF               0 "register_operand" "=v")
1925	(float_extend:V2DF
1926	 (vec_select:V2SF
1927	  (match_dup 2)
1928	  (parallel [(const_int 0) (const_int 2)]))))]
1929  "TARGET_VX"
1930{ operands[2] = gen_reg_rtx(V4SFmode); })
1931
1932(define_expand "vec_unpacks_hi_v4sf"
1933  [(set (match_dup 2)
1934	(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
1935		      (match_dup 1)]
1936		     UNSPEC_VEC_MERGEH))
1937   (set (match_operand:V2DF               0 "register_operand" "=v")
1938	(float_extend:V2DF
1939	 (vec_select:V2SF
1940	  (match_dup 2)
1941	  (parallel [(const_int 0) (const_int 2)]))))]
1942  "TARGET_VX"
1943{ operands[2] = gen_reg_rtx(V4SFmode); })
1944
1945
1946; double -> long double
1947(define_insn "*vec_extendv2df"
1948  [(set (match_operand:V1TF 0 "register_operand" "=v")
1949	(float_extend:V1TF
1950	 (vec_select:V1DF
1951	  (match_operand:V2DF 1 "register_operand" "v")
1952	  (parallel [(const_int 0)]))))]
1953  "TARGET_VXE"
1954  "wflld\t%v0,%v1"
1955  [(set_attr "op_type" "VRR")])
1956
1957(define_expand "vec_unpacks_lo_v2df"
1958  [(set (match_dup 2)
1959	(unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
1960		      (match_dup 1)]
1961		     UNSPEC_VEC_MERGEL))
1962   (set (match_operand:V1TF               0 "register_operand" "=v")
1963	(float_extend:V1TF
1964	 (vec_select:V1DF
1965	  (match_dup 2)
1966	  (parallel [(const_int 0)]))))]
1967  "TARGET_VXE"
1968{ operands[2] = gen_reg_rtx (V2DFmode); })
1969
1970(define_expand "vec_unpacks_hi_v2df"
1971  [(set (match_dup 2)
1972	(unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
1973		      (match_dup 1)]
1974		     UNSPEC_VEC_MERGEH))
1975   (set (match_operand:V1TF               0 "register_operand" "=v")
1976	(float_extend:V1TF
1977	 (vec_select:V1DF
1978	  (match_dup 2)
1979	  (parallel [(const_int 0)]))))]
1980  "TARGET_VXE"
1981{ operands[2] = gen_reg_rtx (V2DFmode); })
1982
1983
1984; 2 x v2df -> 1 x v4sf
1985(define_expand "vec_pack_trunc_v2df"
1986  [(set (match_dup 3)
1987	(unspec:V4SF [(match_operand:V2DF 1 "register_operand" "")
1988		      (const_int VEC_INEXACT)
1989		      (const_int VEC_RND_CURRENT)]
1990		     UNSPEC_VEC_VFLR))
1991   (set (match_dup 4)
1992	(unspec:V4SF [(match_operand:V2DF 2 "register_operand" "")
1993		      (const_int VEC_INEXACT)
1994		      (const_int VEC_RND_CURRENT)]
1995		     UNSPEC_VEC_VFLR))
1996   (set (match_dup 6)
1997	(unspec:V16QI [(subreg:V16QI (match_dup 3) 0)
1998		       (subreg:V16QI (match_dup 4) 0)
1999		       (match_dup 5)]
2000		      UNSPEC_VEC_PERM))
2001   (set (match_operand:V4SF 0 "register_operand" "")
2002	(subreg:V4SF (match_dup 6) 0))]
2003  "TARGET_VX"
2004{
2005  rtx constv, perm[16];
2006  int i;
2007
2008  for (i = 0; i < 4; ++i)
2009    {
2010      perm[i] = GEN_INT (i);
2011      perm[i + 4] = GEN_INT (i + 8);
2012      perm[i + 8] = GEN_INT (i + 16);
2013      perm[i + 12] = GEN_INT (i + 24);
2014    }
2015  constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
2016
2017  operands[3] = gen_reg_rtx (V4SFmode);
2018  operands[4] = gen_reg_rtx (V4SFmode);
2019  operands[5] = force_reg (V16QImode, constv);
2020  operands[6] = gen_reg_rtx (V16QImode);
2021})
2022
2023;
2024; BFP <-> integer conversions
2025;
2026
2027; signed integer to floating point
2028
2029; op2: inexact exception not suppressed (IEEE 754 2008)
2030; op3: according to current rounding mode
2031; vcdgb, vcefb
2032(define_insn "float<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2033  [(set (match_operand:VX_VEC_CONV_BFP                        0 "register_operand" "=v")
2034	(float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2035  "TARGET_VX
2036   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2037  "vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2038  [(set_attr "op_type" "VRR")])
2039
2040; unsigned integer to floating point
2041
2042; op2: inexact exception not suppressed (IEEE 754 2008)
2043; op3: according to current rounding mode
2044; vcdlgb, vcelfb
2045(define_insn "floatuns<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2046  [(set (match_operand:VX_VEC_CONV_BFP                                 0 "register_operand" "=v")
2047	(unsigned_float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2048  "TARGET_VX
2049   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2050  "vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2051  [(set_attr "op_type" "VRR")])
2052
2053; floating point to signed integer
2054
2055; op2: inexact exception not suppressed (IEEE 754 2008)
2056; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2057; vcgdb, vcfeb
2058(define_insn "fix_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2059  [(set (match_operand:VX_VEC_CONV_INT                      0 "register_operand" "=v")
2060	(fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2061  "TARGET_VX
2062   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2063  "vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2064  [(set_attr "op_type" "VRR")])
2065
2066; floating point to unsigned integer
2067
2068; op2: inexact exception not suppressed (IEEE 754 2008)
2069; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2070; vclgdb, vclfeb
2071(define_insn "fixuns_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2072  [(set (match_operand:VX_VEC_CONV_INT                               0 "register_operand" "=v")
2073	(unsigned_fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2074  "TARGET_VX
2075   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2076  "vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2077  [(set_attr "op_type" "VRR")])
2078
2079;
2080; Vector byte swap patterns
2081;
2082
2083; FIXME: The bswap rtl standard name currently does not appear to be
2084; used for vector modes.
2085(define_expand "bswap<mode>"
2086  [(parallel
2087    [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand" "")
2088	  (bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand" "")))
2089     (use (match_dup 2))])]
2090  "TARGET_VX"
2091{
2092  static char p[4][16] =
2093    { { 1,  0,  3,  2,  5,  4,  7, 6, 9,  8,  11, 10, 13, 12, 15, 14 },   /* H */
2094      { 3,  2,  1,  0,  7,  6,  5, 4, 11, 10, 9,  8,  15, 14, 13, 12 },   /* S */
2095      { 7,  6,  5,  4,  3,  2,  1, 0, 15, 14, 13, 12, 11, 10, 9,  8  },   /* D */
2096      { 15, 14, 13, 12, 11, 10, 9, 8, 7,  6,  5,  4,  3,  2,  1,  0  } }; /* T */
2097  char *perm;
2098  rtx perm_rtx[16];
2099
2100  switch (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)))
2101    {
2102    case 2: perm = p[0]; break;
2103    case 4: perm = p[1]; break;
2104    case 8: perm = p[2]; break;
2105    case 16: perm = p[3]; break;
2106    default: gcc_unreachable ();
2107    }
2108  for (int i = 0; i < 16; i++)
2109    perm_rtx[i] = GEN_INT (perm[i]);
2110
2111  operands[2] = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm_rtx));
2112
2113  /* Without vxe2 we do not have byte swap instructions dealing
2114     directly with memory operands.  So instead of waiting until
2115     reload to fix that up switch over to vector permute right
2116     now.  */
2117  if (!TARGET_VXE2)
2118    {
2119      rtx in = force_reg (V16QImode, simplify_gen_subreg (V16QImode, operands[1], <MODE>mode, 0));
2120      rtx permute = force_reg (V16QImode, force_const_mem (V16QImode, operands[2]));
2121      rtx out = gen_reg_rtx (V16QImode);
2122
2123      emit_insn (gen_vec_permv16qi (out, in, in, permute));
2124      emit_move_insn (operands[0], simplify_gen_subreg (<MODE>mode, out, V16QImode, 0));
2125      DONE;
2126    }
2127})
2128
2129; Switching late to the reg-reg variant requires the vector permute
2130; pattern to be pushed into literal pool and allocating a vector
2131; register to load it into.  We rely on both being provided by LRA
2132; when fixing up the v constraint for operand 2.
2133
2134; permute_pattern_operand: general_operand would reject the permute
2135; pattern constants since these are not accepted by
2136; s390_legimitate_constant_p
2137
2138; ^R: Prevent these alternatives from being chosen if it would require
2139; pushing the operand into memory first
2140
2141; vlbrh, vlbrf, vlbrg, vlbrq, vstbrh, vstbrf, vstbrg, vstbrq
2142(define_insn_and_split "*bswap<mode>"
2143  [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand"    "=v, v,^R")
2144	(bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand"     "v,^R, v")))
2145   (use (match_operand:V16QI                        2 "permute_pattern_operand"  "v, X, X"))]
2146  "TARGET_VXE2"
2147  "@
2148   #
2149   vlbr<bhfgq>\t%v0,%v1
2150   vstbr<bhfgq>\t%v1,%v0"
2151  "&& reload_completed
2152   && !memory_operand (operands[0], <MODE>mode)
2153   && !memory_operand (operands[1], <MODE>mode)"
2154  [(set (match_dup 0)
2155	(subreg:VT_HW_HSDT
2156	 (unspec:V16QI [(subreg:V16QI (match_dup 1) 0)
2157			(subreg:V16QI (match_dup 1) 0)
2158			(match_dup 2)]
2159		       UNSPEC_VEC_PERM) 0))]
2160  ""
2161  [(set_attr "op_type"      "*,VRX,VRX")])
2162
2163; reduc_smin
2164; reduc_smax
2165; reduc_umin
2166; reduc_umax
2167
2168; vec_pack_sfix_trunc: convert + pack ?
2169; vec_pack_ufix_trunc
2170; vec_unpacks_float_hi
2171; vec_unpacks_float_lo
2172; vec_unpacku_float_hi
2173; vec_unpacku_float_lo
2174