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