]>
Commit | Line | Data |
---|---|---|
085261c8 AK |
1 | ;;- Instruction patterns for the System z vector facility |
2 | ;; Copyright (C) 2015 Free Software Foundation, Inc. | |
3 | ;; Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com) | |
4 | ||
5 | ;; This file is part of GCC. | |
6 | ||
7 | ;; GCC is free software; you can redistribute it and/or modify it under | |
8 | ;; the terms of the GNU General Public License as published by the Free | |
9 | ;; Software Foundation; either version 3, or (at your option) any later | |
10 | ;; version. | |
11 | ||
12 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | ;; for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with GCC; see the file COPYING3. If not see | |
19 | ;; <http://www.gnu.org/licenses/>. | |
20 | ||
21 | ; All vector modes supported in a vector register | |
22 | (define_mode_iterator V | |
23 | [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF | |
24 | V2SF V4SF V1DF V2DF]) | |
25 | (define_mode_iterator VT | |
26 | [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF | |
27 | V2SF V4SF V1DF V2DF V1TF V1TI TI]) | |
28 | ||
29 | ; All vector modes directly supported by the hardware having full vector reg size | |
30 | ; V_HW2 is duplicate of V_HW for having two iterators expanding | |
31 | ; independently e.g. vcond | |
32 | (define_mode_iterator V_HW [V16QI V8HI V4SI V2DI V2DF]) | |
33 | (define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF]) | |
34 | ; Including TI for instructions that support it (va, vn, ...) | |
35 | (define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI]) | |
36 | ||
37 | ; All full size integer vector modes supported in a vector register + TImode | |
38 | (define_mode_iterator VIT_HW [V16QI V8HI V4SI V2DI V1TI TI]) | |
39 | (define_mode_iterator VI_HW [V16QI V8HI V4SI V2DI]) | |
40 | (define_mode_iterator VI_HW_QHS [V16QI V8HI V4SI]) | |
41 | (define_mode_iterator VI_HW_HS [V8HI V4SI]) | |
42 | (define_mode_iterator VI_HW_QH [V16QI V8HI]) | |
43 | ||
44 | ; All integer vector modes supported in a vector register + TImode | |
45 | (define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI]) | |
46 | (define_mode_iterator VI [V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI]) | |
47 | (define_mode_iterator VI_QHS [V4QI V8QI V16QI V4HI V8HI V4SI]) | |
48 | ||
49 | (define_mode_iterator V_8 [V1QI]) | |
50 | (define_mode_iterator V_16 [V2QI V1HI]) | |
51 | (define_mode_iterator V_32 [V4QI V2HI V1SI V1SF]) | |
52 | (define_mode_iterator V_64 [V8QI V4HI V2SI V2SF V1DI V1DF]) | |
53 | (define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF]) | |
54 | ||
55 | ; A blank for vector modes and a * for TImode. This is used to hide | |
56 | ; the TImode expander name in case it is defined already. See addti3 | |
57 | ; for an example. | |
58 | (define_mode_attr ti* [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "") | |
59 | (V1HI "") (V2HI "") (V4HI "") (V8HI "") | |
60 | (V1SI "") (V2SI "") (V4SI "") | |
61 | (V1DI "") (V2DI "") | |
62 | (V1TI "*") (TI "*")]) | |
63 | ||
64 | ; The element type of the vector. | |
65 | (define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI") | |
66 | (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI") | |
67 | (V1SI "SI") (V2SI "SI") (V4SI "SI") | |
68 | (V1DI "DI") (V2DI "DI") | |
69 | (V1TI "TI") | |
70 | (V1SF "SF") (V2SF "SF") (V4SF "SF") | |
71 | (V1DF "DF") (V2DF "DF") | |
72 | (V1TF "TF")]) | |
73 | ||
74 | ; The instruction suffix | |
75 | (define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b") | |
76 | (V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h") | |
77 | (V1SI "f") (V2SI "f") (V4SI "f") | |
78 | (V1DI "g") (V2DI "g") | |
79 | (V1TI "q") (TI "q") | |
80 | (V1SF "f") (V2SF "f") (V4SF "f") | |
81 | (V1DF "g") (V2DF "g") | |
82 | (V1TF "q")]) | |
83 | ||
84 | ; This is for vmalhw. It gets an 'w' attached to avoid confusion with | |
85 | ; multiply and add logical high vmalh. | |
86 | (define_mode_attr w [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "") | |
87 | (V1HI "w") (V2HI "w") (V4HI "w") (V8HI "w") | |
88 | (V1SI "") (V2SI "") (V4SI "") | |
89 | (V1DI "") (V2DI "")]) | |
90 | ||
91 | ; Resulting mode of a vector comparison. For floating point modes an | |
92 | ; integer vector mode with the same element size is picked. | |
93 | (define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI") | |
94 | (V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI") | |
95 | (V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI") | |
96 | (V1DI "V1DI") (V2DI "V2DI") | |
97 | (V1TI "V1TI") | |
98 | (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI") | |
99 | (V1DF "V1DI") (V2DF "V2DI") | |
100 | (V1TF "V1TI")]) | |
101 | ||
102 | ; Vector with doubled element size. | |
103 | (define_mode_attr vec_double [(V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI") | |
104 | (V2HI "V1SI") (V4HI "V2SI") (V8HI "V4SI") | |
105 | (V2SI "V1DI") (V4SI "V2DI") | |
106 | (V2DI "V1TI") | |
107 | (V2SF "V1DF") (V4SF "V2DF")]) | |
108 | ||
109 | ; Vector with half the element size. | |
110 | (define_mode_attr vec_half [(V1HI "V2QI") (V2HI "V4QI") (V4HI "V8QI") (V8HI "V16QI") | |
111 | (V1SI "V2HI") (V2SI "V4HI") (V4SI "V8HI") | |
112 | (V1DI "V2SI") (V2DI "V4SI") | |
113 | (V1TI "V2DI") | |
114 | (V1DF "V2SF") (V2DF "V4SF") | |
115 | (V1TF "V1DF")]) | |
116 | ||
117 | ; The comparisons not setting CC iterate over the rtx code. | |
118 | (define_code_iterator VFCMP_HW_OP [eq gt ge]) | |
119 | (define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")]) | |
120 | ||
121 | ||
122 | ||
123 | ; Comparison operators on int and fp compares which are directly | |
124 | ; supported by the HW. | |
125 | (define_code_iterator VICMP_HW_OP [eq gt gtu]) | |
126 | ; For int insn_cmp_op can be used in the insn name as well as in the asm output. | |
127 | (define_code_attr insn_cmp_op [(eq "eq") (gt "h") (gtu "hl") (ge "he")]) | |
128 | ||
129 | ; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4) | |
130 | (define_constants | |
131 | [(VSTRING_FLAG_IN 8) ; invert result | |
132 | (VSTRING_FLAG_RT 4) ; result type | |
133 | (VSTRING_FLAG_ZS 2) ; zero search | |
134 | (VSTRING_FLAG_CS 1)]) ; condition code set | |
135 | ||
3af82a61 AK |
136 | (include "vx-builtins.md") |
137 | ||
085261c8 AK |
138 | ; Full HW vector size moves |
139 | (define_insn "mov<mode>" | |
b0057efd AK |
140 | [(set (match_operand:V_128 0 "nonimmediate_operand" "=v, v,QR, v, v, v, v, v,v,d") |
141 | (match_operand:V_128 1 "general_operand" " v,QR, v,j00,jm1,jyy,jxx,jKK,d,v"))] | |
085261c8 AK |
142 | "TARGET_VX" |
143 | "@ | |
144 | vlr\t%v0,%v1 | |
145 | vl\t%v0,%1 | |
146 | vst\t%v1,%0 | |
147 | vzero\t%v0 | |
148 | vone\t%v0 | |
149 | vgbm\t%v0,%t1 | |
150 | vgm<bhfgq>\t%v0,%s1,%e1 | |
b0057efd | 151 | vrepi<bhfgq>\t%v0,%h1 |
085261c8 AK |
152 | vlvgp\t%v0,%1,%N1 |
153 | #" | |
b0057efd | 154 | [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*")]) |
085261c8 AK |
155 | |
156 | (define_split | |
157 | [(set (match_operand:V_128 0 "register_operand" "") | |
158 | (match_operand:V_128 1 "register_operand" ""))] | |
159 | "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])" | |
160 | [(set (match_dup 2) | |
161 | (unspec:DI [(subreg:V2DI (match_dup 1) 0) | |
162 | (const_int 0)] UNSPEC_VEC_EXTRACT)) | |
163 | (set (match_dup 3) | |
164 | (unspec:DI [(subreg:V2DI (match_dup 1) 0) | |
165 | (const_int 1)] UNSPEC_VEC_EXTRACT))] | |
166 | { | |
167 | operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode); | |
168 | operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode); | |
169 | }) | |
170 | ||
171 | ; Moves for smaller vector modes. | |
172 | ||
173 | ; In these patterns only the vlr, vone, and vzero instructions write | |
174 | ; VR bytes outside the mode. This should be ok since we disallow | |
175 | ; formerly bigger modes being accessed with smaller modes via | |
176 | ; subreg. Note: The vone, vzero instructions could easily be replaced | |
177 | ; with vlei which would only access the bytes belonging to the mode. | |
178 | ; However, this would probably be slower. | |
179 | ||
180 | (define_insn "mov<mode>" | |
181 | [(set (match_operand:V_8 0 "nonimmediate_operand" "=v,v,d, v,QR, v, v, v, v,d, Q, S, Q, S, d, d,d,d,d,R,T") | |
182 | (match_operand:V_8 1 "general_operand" " v,d,v,QR, v,j00,jm1,jyy,jxx,d,j00,j00,jm1,jm1,j00,jm1,R,T,b,d,d"))] | |
183 | "" | |
184 | "@ | |
185 | vlr\t%v0,%v1 | |
186 | vlvgb\t%v0,%1,0 | |
187 | vlgvb\t%0,%v1,0 | |
188 | vleb\t%v0,%1,0 | |
189 | vsteb\t%v1,%0,0 | |
190 | vzero\t%v0 | |
191 | vone\t%v0 | |
192 | vgbm\t%v0,%t1 | |
193 | vgm\t%v0,%s1,%e1 | |
194 | lr\t%0,%1 | |
195 | mvi\t%0,0 | |
196 | mviy\t%0,0 | |
197 | mvi\t%0,-1 | |
198 | mviy\t%0,-1 | |
199 | lhi\t%0,0 | |
200 | lhi\t%0,-1 | |
201 | lh\t%0,%1 | |
202 | lhy\t%0,%1 | |
203 | lhrl\t%0,%1 | |
204 | stc\t%1,%0 | |
205 | stcy\t%1,%0" | |
206 | [(set_attr "op_type" "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RX,RXY,RIL,RX,RXY")]) | |
207 | ||
208 | (define_insn "mov<mode>" | |
209 | [(set (match_operand:V_16 0 "nonimmediate_operand" "=v,v,d, v,QR, v, v, v, v,d, Q, Q, d, d,d,d,d,R,T,b") | |
210 | (match_operand:V_16 1 "general_operand" " v,d,v,QR, v,j00,jm1,jyy,jxx,d,j00,jm1,j00,jm1,R,T,b,d,d,d"))] | |
211 | "" | |
212 | "@ | |
213 | vlr\t%v0,%v1 | |
214 | vlvgh\t%v0,%1,0 | |
215 | vlgvh\t%0,%v1,0 | |
216 | vleh\t%v0,%1,0 | |
217 | vsteh\t%v1,%0,0 | |
218 | vzero\t%v0 | |
219 | vone\t%v0 | |
220 | vgbm\t%v0,%t1 | |
221 | vgm\t%v0,%s1,%e1 | |
222 | lr\t%0,%1 | |
223 | mvhhi\t%0,0 | |
224 | mvhhi\t%0,-1 | |
225 | lhi\t%0,0 | |
226 | lhi\t%0,-1 | |
227 | lh\t%0,%1 | |
228 | lhy\t%0,%1 | |
229 | lhrl\t%0,%1 | |
230 | sth\t%1,%0 | |
231 | sthy\t%1,%0 | |
232 | sthrl\t%1,%0" | |
233 | [(set_attr "op_type" "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SIL,SIL,RI,RI,RX,RXY,RIL,RX,RXY,RIL")]) | |
234 | ||
235 | (define_insn "mov<mode>" | |
236 | [(set (match_operand:V_32 0 "nonimmediate_operand" "=f,f,f,R,T,v,v,d, v,QR, f, v, v, v, v, Q, Q, d, d,d,d,d,d,R,T,b") | |
237 | (match_operand:V_32 1 "general_operand" " f,R,T,f,f,v,d,v,QR, v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,b,d,R,T,d,d,d"))] | |
238 | "TARGET_VX" | |
239 | "@ | |
240 | lder\t%v0,%v1 | |
241 | lde\t%0,%1 | |
242 | ley\t%0,%1 | |
243 | ste\t%1,%0 | |
244 | stey\t%1,%0 | |
245 | vlr\t%v0,%v1 | |
246 | vlvgf\t%v0,%1,0 | |
247 | vlgvf\t%0,%v1,0 | |
248 | vlef\t%v0,%1,0 | |
249 | vstef\t%1,%0,0 | |
250 | lzer\t%v0 | |
251 | vzero\t%v0 | |
252 | vone\t%v0 | |
253 | vgbm\t%v0,%t1 | |
254 | vgm\t%v0,%s1,%e1 | |
255 | mvhi\t%0,0 | |
256 | mvhi\t%0,-1 | |
257 | lhi\t%0,0 | |
258 | lhi\t%0,-1 | |
259 | lrl\t%0,%1 | |
260 | lr\t%0,%1 | |
261 | l\t%0,%1 | |
262 | ly\t%0,%1 | |
263 | st\t%1,%0 | |
264 | sty\t%1,%0 | |
265 | strl\t%1,%0" | |
266 | [(set_attr "op_type" "RRE,RXE,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,SIL,SIL,RI,RI, | |
267 | RIL,RR,RX,RXY,RX,RXY,RIL")]) | |
268 | ||
269 | (define_insn "mov<mode>" | |
270 | [(set (match_operand:V_64 0 "nonimmediate_operand" | |
271 | "=f,f,f,R,T,v,v,d, v,QR, f, v, v, v, v, Q, Q, d, d,f,d,d,d, d,RT,b") | |
272 | (match_operand:V_64 1 "general_operand" | |
273 | " f,R,T,f,f,v,d,v,QR, v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,d,f,b,d,RT, d,d"))] | |
274 | "TARGET_ZARCH" | |
275 | "@ | |
276 | ldr\t%0,%1 | |
277 | ld\t%0,%1 | |
278 | ldy\t%0,%1 | |
279 | std\t%1,%0 | |
280 | stdy\t%1,%0 | |
281 | vlr\t%v0,%v1 | |
282 | vlvgg\t%v0,%1,0 | |
283 | vlgvg\t%0,%v1,0 | |
284 | vleg\t%v0,%1,0 | |
285 | vsteg\t%v1,%0,0 | |
286 | lzdr\t%0 | |
287 | vzero\t%v0 | |
288 | vone\t%v0 | |
289 | vgbm\t%v0,%t1 | |
290 | vgm\t%v0,%s1,%e1 | |
291 | mvghi\t%0,0 | |
292 | mvghi\t%0,-1 | |
293 | lghi\t%0,0 | |
294 | lghi\t%0,-1 | |
295 | ldgr\t%0,%1 | |
296 | lgdr\t%0,%1 | |
297 | lgrl\t%0,%1 | |
298 | lgr\t%0,%1 | |
299 | lg\t%0,%1 | |
300 | stg\t%1,%0 | |
301 | stgrl\t%1,%0" | |
302 | [(set_attr "op_type" "RRE,RX,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI, | |
303 | SIL,SIL,RI,RI,RRE,RRE,RIL,RR,RXY,RXY,RIL")]) | |
304 | ||
305 | ||
306 | ; vec_load_lanes? | |
307 | ||
308 | ; vec_store_lanes? | |
309 | ||
310 | ; FIXME: Support also vector mode operands for 1 | |
311 | ; FIXME: A target memory operand seems to be useful otherwise we end | |
312 | ; up with vl vlvgg vst. Shouldn't the middle-end be able to handle | |
313 | ; that itself? | |
314 | (define_insn "*vec_set<mode>" | |
315 | [(set (match_operand:V 0 "register_operand" "=v, v,v") | |
316 | (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K") | |
8eb1b59b | 317 | (match_operand:SI 2 "shift_count_or_setmem_operand" "Y, I,I") |
085261c8 AK |
318 | (match_operand:V 3 "register_operand" "0, 0,0")] |
319 | UNSPEC_VEC_SET))] | |
320 | "TARGET_VX" | |
321 | "@ | |
322 | vlvg<bhfgq>\t%v0,%1,%Y2 | |
323 | vle<bhfgq>\t%v0,%1,%2 | |
324 | vlei<bhfgq>\t%v0,%1,%2" | |
325 | [(set_attr "op_type" "VRS,VRX,VRI")]) | |
326 | ||
327 | ; vec_set is supposed to *modify* an existing vector so operand 0 is | |
328 | ; duplicated as input operand. | |
329 | (define_expand "vec_set<mode>" | |
330 | [(set (match_operand:V 0 "register_operand" "") | |
331 | (unspec:V [(match_operand:<non_vec> 1 "general_operand" "") | |
332 | (match_operand:SI 2 "shift_count_or_setmem_operand" "") | |
333 | (match_dup 0)] | |
334 | UNSPEC_VEC_SET))] | |
335 | "TARGET_VX") | |
336 | ||
337 | ; FIXME: Support also vector mode operands for 0 | |
338 | ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :( | |
339 | ; This is used via RTL standard name as well as for expanding the builtin | |
340 | (define_insn "vec_extract<mode>" | |
341 | [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR") | |
342 | (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v") | |
343 | (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")] | |
344 | UNSPEC_VEC_EXTRACT))] | |
345 | "TARGET_VX" | |
346 | "@ | |
347 | vlgv<bhfgq>\t%0,%v1,%Y2 | |
348 | vste<bhfgq>\t%v1,%0,%2" | |
349 | [(set_attr "op_type" "VRS,VRX")]) | |
350 | ||
351 | (define_expand "vec_init<V_HW:mode>" | |
352 | [(match_operand:V_HW 0 "register_operand" "") | |
353 | (match_operand:V_HW 1 "nonmemory_operand" "")] | |
354 | "TARGET_VX" | |
355 | { | |
356 | s390_expand_vec_init (operands[0], operands[1]); | |
357 | DONE; | |
358 | }) | |
359 | ||
360 | ; Replicate from vector element | |
361 | (define_insn "*vec_splat<mode>" | |
362 | [(set (match_operand:V_HW 0 "register_operand" "=v") | |
363 | (vec_duplicate:V_HW | |
364 | (vec_select:<non_vec> | |
365 | (match_operand:V_HW 1 "register_operand" "v") | |
366 | (parallel | |
e970b4b0 AK |
367 | [(match_operand:QI 2 "const_mask_operand" "C")]))))] |
368 | "TARGET_VX && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW:MODE>mode)" | |
085261c8 AK |
369 | "vrep<bhfgq>\t%v0,%v1,%2" |
370 | [(set_attr "op_type" "VRI")]) | |
371 | ||
372 | (define_insn "*vec_splats<mode>" | |
373 | [(set (match_operand:V_HW 0 "register_operand" "=v,v,v,v") | |
a4a443ce | 374 | (vec_duplicate:V_HW (match_operand:<non_vec> 1 "general_operand" "QR,K,v,d")))] |
085261c8 AK |
375 | "TARGET_VX" |
376 | "@ | |
377 | vlrep<bhfgq>\t%v0,%1 | |
a4a443ce | 378 | vrepi<bhfgq>\t%v0,%h1 |
085261c8 AK |
379 | vrep<bhfgq>\t%v0,%v1,0 |
380 | #" | |
381 | [(set_attr "op_type" "VRX,VRI,VRI,*")]) | |
382 | ||
383 | ; vec_splats is supposed to replicate op1 into all elements of op0 | |
384 | ; This splitter first sets the rightmost element of op0 to op1 and | |
385 | ; then does a vec_splat to replicate that element into all other | |
386 | ; elements. | |
387 | (define_split | |
388 | [(set (match_operand:V_HW 0 "register_operand" "") | |
389 | (vec_duplicate:V_HW (match_operand:<non_vec> 1 "register_operand" "")))] | |
390 | "TARGET_VX && GENERAL_REG_P (operands[1])" | |
391 | [(set (match_dup 0) | |
392 | (unspec:V_HW [(match_dup 1) (match_dup 2) (match_dup 0)] UNSPEC_VEC_SET)) | |
393 | (set (match_dup 0) | |
394 | (vec_duplicate:V_HW | |
395 | (vec_select:<non_vec> | |
396 | (match_dup 0) (parallel [(match_dup 2)]))))] | |
397 | { | |
398 | operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1); | |
399 | }) | |
400 | ||
401 | (define_expand "vcond<V_HW:mode><V_HW2:mode>" | |
402 | [(set (match_operand:V_HW 0 "register_operand" "") | |
403 | (if_then_else:V_HW | |
404 | (match_operator 3 "comparison_operator" | |
405 | [(match_operand:V_HW2 4 "register_operand" "") | |
d958ae79 | 406 | (match_operand:V_HW2 5 "nonmemory_operand" "")]) |
085261c8 AK |
407 | (match_operand:V_HW 1 "nonmemory_operand" "") |
408 | (match_operand:V_HW 2 "nonmemory_operand" "")))] | |
409 | "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)" | |
410 | { | |
411 | s390_expand_vcond (operands[0], operands[1], operands[2], | |
412 | GET_CODE (operands[3]), operands[4], operands[5]); | |
413 | DONE; | |
414 | }) | |
415 | ||
416 | (define_expand "vcondu<V_HW:mode><V_HW2:mode>" | |
417 | [(set (match_operand:V_HW 0 "register_operand" "") | |
418 | (if_then_else:V_HW | |
419 | (match_operator 3 "comparison_operator" | |
420 | [(match_operand:V_HW2 4 "register_operand" "") | |
d958ae79 | 421 | (match_operand:V_HW2 5 "nonmemory_operand" "")]) |
085261c8 AK |
422 | (match_operand:V_HW 1 "nonmemory_operand" "") |
423 | (match_operand:V_HW 2 "nonmemory_operand" "")))] | |
424 | "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)" | |
425 | { | |
426 | s390_expand_vcond (operands[0], operands[1], operands[2], | |
427 | GET_CODE (operands[3]), operands[4], operands[5]); | |
428 | DONE; | |
429 | }) | |
430 | ||
431 | ; We only have HW support for byte vectors. The middle-end is | |
432 | ; supposed to lower the mode if required. | |
433 | (define_insn "vec_permv16qi" | |
434 | [(set (match_operand:V16QI 0 "register_operand" "=v") | |
435 | (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") | |
436 | (match_operand:V16QI 2 "register_operand" "v") | |
437 | (match_operand:V16QI 3 "register_operand" "v")] | |
438 | UNSPEC_VEC_PERM))] | |
439 | "TARGET_VX" | |
440 | "vperm\t%v0,%v1,%v2,%v3" | |
441 | [(set_attr "op_type" "VRR")]) | |
442 | ||
443 | ; vec_perm_const for V2DI using vpdi? | |
444 | ||
445 | ;; | |
446 | ;; Vector integer arithmetic instructions | |
447 | ;; | |
448 | ||
449 | ; vab, vah, vaf, vag, vaq | |
450 | ||
451 | ; We use nonimmediate_operand instead of register_operand since it is | |
452 | ; better to have the reloads into VRs instead of splitting the | |
453 | ; operation into two DImode ADDs. | |
454 | (define_insn "<ti*>add<mode>3" | |
455 | [(set (match_operand:VIT 0 "nonimmediate_operand" "=v") | |
456 | (plus:VIT (match_operand:VIT 1 "nonimmediate_operand" "v") | |
457 | (match_operand:VIT 2 "nonimmediate_operand" "v")))] | |
458 | "TARGET_VX" | |
459 | "va<bhfgq>\t%v0,%v1,%v2" | |
460 | [(set_attr "op_type" "VRR")]) | |
461 | ||
462 | ; vsb, vsh, vsf, vsg, vsq | |
463 | (define_insn "<ti*>sub<mode>3" | |
464 | [(set (match_operand:VIT 0 "nonimmediate_operand" "=v") | |
465 | (minus:VIT (match_operand:VIT 1 "nonimmediate_operand" "v") | |
466 | (match_operand:VIT 2 "nonimmediate_operand" "v")))] | |
467 | "TARGET_VX" | |
468 | "vs<bhfgq>\t%v0,%v1,%v2" | |
469 | [(set_attr "op_type" "VRR")]) | |
470 | ||
471 | ; vmlb, vmlhw, vmlf | |
472 | (define_insn "mul<mode>3" | |
473 | [(set (match_operand:VI_QHS 0 "register_operand" "=v") | |
474 | (mult:VI_QHS (match_operand:VI_QHS 1 "register_operand" "v") | |
475 | (match_operand:VI_QHS 2 "register_operand" "v")))] | |
476 | "TARGET_VX" | |
477 | "vml<bhfgq><w>\t%v0,%v1,%v2" | |
478 | [(set_attr "op_type" "VRR")]) | |
479 | ||
480 | ; vlcb, vlch, vlcf, vlcg | |
481 | (define_insn "neg<mode>2" | |
482 | [(set (match_operand:VI 0 "register_operand" "=v") | |
483 | (neg:VI (match_operand:VI 1 "register_operand" "v")))] | |
484 | "TARGET_VX" | |
485 | "vlc<bhfgq>\t%v0,%v1" | |
486 | [(set_attr "op_type" "VRR")]) | |
487 | ||
488 | ; vlpb, vlph, vlpf, vlpg | |
489 | (define_insn "abs<mode>2" | |
490 | [(set (match_operand:VI 0 "register_operand" "=v") | |
491 | (abs:VI (match_operand:VI 1 "register_operand" "v")))] | |
492 | "TARGET_VX" | |
493 | "vlp<bhfgq>\t%v0,%v1" | |
494 | [(set_attr "op_type" "VRR")]) | |
495 | ||
496 | ||
497 | ; Vector sum across | |
498 | ||
499 | ; Sum across DImode parts of the 1st operand and add the rightmost | |
500 | ; element of 2nd operand | |
501 | ; vsumgh, vsumgf | |
502 | (define_insn "*vec_sum2<mode>" | |
503 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
504 | (unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "v") | |
505 | (match_operand:VI_HW_HS 2 "register_operand" "v")] | |
506 | UNSPEC_VEC_VSUMG))] | |
507 | "TARGET_VX" | |
508 | "vsumg<bhfgq>\t%v0,%v1,%v2" | |
509 | [(set_attr "op_type" "VRR")]) | |
510 | ||
511 | ; vsumb, vsumh | |
512 | (define_insn "*vec_sum4<mode>" | |
513 | [(set (match_operand:V4SI 0 "register_operand" "=v") | |
514 | (unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "v") | |
515 | (match_operand:VI_HW_QH 2 "register_operand" "v")] | |
516 | UNSPEC_VEC_VSUM))] | |
517 | "TARGET_VX" | |
518 | "vsum<bhfgq>\t%v0,%v1,%v2" | |
519 | [(set_attr "op_type" "VRR")]) | |
520 | ||
521 | ;; | |
522 | ;; Vector bit instructions (int + fp) | |
523 | ;; | |
524 | ||
525 | ; Vector and | |
526 | ||
527 | (define_insn "and<mode>3" | |
528 | [(set (match_operand:VT 0 "register_operand" "=v") | |
529 | (and:VT (match_operand:VT 1 "register_operand" "v") | |
530 | (match_operand:VT 2 "register_operand" "v")))] | |
531 | "TARGET_VX" | |
532 | "vn\t%v0,%v1,%v2" | |
533 | [(set_attr "op_type" "VRR")]) | |
534 | ||
535 | ||
536 | ; Vector or | |
537 | ||
538 | (define_insn "ior<mode>3" | |
539 | [(set (match_operand:VT 0 "register_operand" "=v") | |
540 | (ior:VT (match_operand:VT 1 "register_operand" "v") | |
541 | (match_operand:VT 2 "register_operand" "v")))] | |
542 | "TARGET_VX" | |
543 | "vo\t%v0,%v1,%v2" | |
544 | [(set_attr "op_type" "VRR")]) | |
545 | ||
546 | ||
547 | ; Vector xor | |
548 | ||
549 | (define_insn "xor<mode>3" | |
550 | [(set (match_operand:VT 0 "register_operand" "=v") | |
551 | (xor:VT (match_operand:VT 1 "register_operand" "v") | |
552 | (match_operand:VT 2 "register_operand" "v")))] | |
553 | "TARGET_VX" | |
554 | "vx\t%v0,%v1,%v2" | |
555 | [(set_attr "op_type" "VRR")]) | |
556 | ||
557 | ||
558 | ; Bitwise inversion of a vector - used for vec_cmpne | |
559 | (define_insn "*not<mode>" | |
560 | [(set (match_operand:VT 0 "register_operand" "=v") | |
561 | (not:VT (match_operand:VT 1 "register_operand" "v")))] | |
562 | "TARGET_VX" | |
563 | "vnot\t%v0,%v1" | |
564 | [(set_attr "op_type" "VRR")]) | |
565 | ||
566 | ; Vector population count | |
567 | ||
568 | (define_insn "popcountv16qi2" | |
569 | [(set (match_operand:V16QI 0 "register_operand" "=v") | |
570 | (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")] | |
571 | UNSPEC_POPCNT))] | |
572 | "TARGET_VX" | |
573 | "vpopct\t%v0,%v1,0" | |
574 | [(set_attr "op_type" "VRR")]) | |
575 | ||
576 | ; vpopct only counts bits in byte elements. Bigger element sizes need | |
577 | ; to be emulated. Word and doubleword elements can use the sum across | |
578 | ; instructions. For halfword sized elements we do a shift of a copy | |
579 | ; of the result, add it to the result and extend it to halfword | |
580 | ; element size (unpack). | |
581 | ||
582 | (define_expand "popcountv8hi2" | |
583 | [(set (match_dup 2) | |
584 | (unspec:V16QI [(subreg:V16QI (match_operand:V8HI 1 "register_operand" "v") 0)] | |
585 | UNSPEC_POPCNT)) | |
586 | ; Make a copy of the result | |
587 | (set (match_dup 3) (match_dup 2)) | |
588 | ; Generate the shift count operand in a VR (8->byte 7) | |
589 | (set (match_dup 4) (match_dup 5)) | |
590 | (set (match_dup 4) (unspec:V16QI [(const_int 8) | |
591 | (const_int 7) | |
592 | (match_dup 4)] UNSPEC_VEC_SET)) | |
593 | ; Vector shift right logical by one byte | |
594 | (set (match_dup 3) | |
595 | (unspec:V16QI [(match_dup 3) (match_dup 4)] UNSPEC_VEC_SRLB)) | |
596 | ; Add the shifted and the original result | |
597 | (set (match_dup 2) | |
598 | (plus:V16QI (match_dup 2) (match_dup 3))) | |
599 | ; Generate mask for the odd numbered byte elements | |
600 | (set (match_dup 3) | |
601 | (const_vector:V16QI [(const_int 0) (const_int 255) | |
602 | (const_int 0) (const_int 255) | |
603 | (const_int 0) (const_int 255) | |
604 | (const_int 0) (const_int 255) | |
605 | (const_int 0) (const_int 255) | |
606 | (const_int 0) (const_int 255) | |
607 | (const_int 0) (const_int 255) | |
608 | (const_int 0) (const_int 255)])) | |
609 | ; Zero out the even indexed bytes | |
610 | (set (match_operand:V8HI 0 "register_operand" "=v") | |
611 | (and:V8HI (subreg:V8HI (match_dup 2) 0) | |
612 | (subreg:V8HI (match_dup 3) 0))) | |
613 | ] | |
614 | "TARGET_VX" | |
615 | { | |
616 | operands[2] = gen_reg_rtx (V16QImode); | |
617 | operands[3] = gen_reg_rtx (V16QImode); | |
618 | operands[4] = gen_reg_rtx (V16QImode); | |
619 | operands[5] = CONST0_RTX (V16QImode); | |
620 | }) | |
621 | ||
622 | (define_expand "popcountv4si2" | |
623 | [(set (match_dup 2) | |
624 | (unspec:V16QI [(subreg:V16QI (match_operand:V4SI 1 "register_operand" "v") 0)] | |
625 | UNSPEC_POPCNT)) | |
626 | (set (match_operand:V4SI 0 "register_operand" "=v") | |
627 | (unspec:V4SI [(match_dup 2) (match_dup 3)] | |
628 | UNSPEC_VEC_VSUM))] | |
629 | "TARGET_VX" | |
630 | { | |
631 | operands[2] = gen_reg_rtx (V16QImode); | |
632 | operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode)); | |
633 | }) | |
634 | ||
635 | (define_expand "popcountv2di2" | |
636 | [(set (match_dup 2) | |
637 | (unspec:V16QI [(subreg:V16QI (match_operand:V2DI 1 "register_operand" "v") 0)] | |
638 | UNSPEC_POPCNT)) | |
639 | (set (match_dup 3) | |
640 | (unspec:V4SI [(match_dup 2) (match_dup 4)] | |
641 | UNSPEC_VEC_VSUM)) | |
642 | (set (match_operand:V2DI 0 "register_operand" "=v") | |
643 | (unspec:V2DI [(match_dup 3) (match_dup 5)] | |
644 | UNSPEC_VEC_VSUMG))] | |
645 | "TARGET_VX" | |
646 | { | |
647 | operands[2] = gen_reg_rtx (V16QImode); | |
648 | operands[3] = gen_reg_rtx (V4SImode); | |
649 | operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode)); | |
650 | operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode)); | |
651 | }) | |
652 | ||
653 | ; Count leading zeros | |
654 | (define_insn "clz<mode>2" | |
655 | [(set (match_operand:V 0 "register_operand" "=v") | |
656 | (clz:V (match_operand:V 1 "register_operand" "v")))] | |
657 | "TARGET_VX" | |
658 | "vclz<bhfgq>\t%v0,%v1" | |
659 | [(set_attr "op_type" "VRR")]) | |
660 | ||
661 | ; Count trailing zeros | |
662 | (define_insn "ctz<mode>2" | |
663 | [(set (match_operand:V 0 "register_operand" "=v") | |
664 | (ctz:V (match_operand:V 1 "register_operand" "v")))] | |
665 | "TARGET_VX" | |
666 | "vctz<bhfgq>\t%v0,%v1" | |
667 | [(set_attr "op_type" "VRR")]) | |
668 | ||
669 | ||
670 | ; Vector rotate instructions | |
671 | ||
672 | ; Each vector element rotated by a scalar | |
673 | ; verllb, verllh, verllf, verllg | |
674 | (define_insn "rotl<mode>3" | |
675 | [(set (match_operand:VI 0 "register_operand" "=v") | |
676 | (rotate:VI (match_operand:VI 1 "register_operand" "v") | |
677 | (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] | |
678 | "TARGET_VX" | |
679 | "verll<bhfgq>\t%v0,%v1,%Y2" | |
680 | [(set_attr "op_type" "VRS")]) | |
681 | ||
682 | ; Each vector element rotated by the corresponding vector element | |
683 | ; verllvb, verllvh, verllvf, verllvg | |
684 | (define_insn "vrotl<mode>3" | |
685 | [(set (match_operand:VI 0 "register_operand" "=v") | |
686 | (rotate:VI (match_operand:VI 1 "register_operand" "v") | |
687 | (match_operand:VI 2 "register_operand" "v")))] | |
688 | "TARGET_VX" | |
689 | "verllv<bhfgq>\t%v0,%v1,%v2" | |
690 | [(set_attr "op_type" "VRR")]) | |
691 | ||
692 | ||
693 | ; Shift each element by scalar value | |
694 | ||
695 | ; veslb, veslh, veslf, veslg | |
696 | (define_insn "ashl<mode>3" | |
697 | [(set (match_operand:VI 0 "register_operand" "=v") | |
698 | (ashift:VI (match_operand:VI 1 "register_operand" "v") | |
699 | (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] | |
700 | "TARGET_VX" | |
701 | "vesl<bhfgq>\t%v0,%v1,%Y2" | |
702 | [(set_attr "op_type" "VRS")]) | |
703 | ||
704 | ; vesrab, vesrah, vesraf, vesrag | |
705 | (define_insn "ashr<mode>3" | |
706 | [(set (match_operand:VI 0 "register_operand" "=v") | |
707 | (ashiftrt:VI (match_operand:VI 1 "register_operand" "v") | |
708 | (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] | |
709 | "TARGET_VX" | |
710 | "vesra<bhfgq>\t%v0,%v1,%Y2" | |
711 | [(set_attr "op_type" "VRS")]) | |
712 | ||
713 | ; vesrlb, vesrlh, vesrlf, vesrlg | |
714 | (define_insn "lshr<mode>3" | |
715 | [(set (match_operand:VI 0 "register_operand" "=v") | |
716 | (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") | |
717 | (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] | |
718 | "TARGET_VX" | |
719 | "vesrl<bhfgq>\t%v0,%v1,%Y2" | |
720 | [(set_attr "op_type" "VRS")]) | |
721 | ||
722 | ||
723 | ; Shift each element by corresponding vector element | |
724 | ||
725 | ; veslvb, veslvh, veslvf, veslvg | |
726 | (define_insn "vashl<mode>3" | |
727 | [(set (match_operand:VI 0 "register_operand" "=v") | |
728 | (ashift:VI (match_operand:VI 1 "register_operand" "v") | |
729 | (match_operand:VI 2 "register_operand" "v")))] | |
730 | "TARGET_VX" | |
731 | "veslv<bhfgq>\t%v0,%v1,%v2" | |
732 | [(set_attr "op_type" "VRR")]) | |
733 | ||
734 | ; vesravb, vesravh, vesravf, vesravg | |
735 | (define_insn "vashr<mode>3" | |
736 | [(set (match_operand:VI 0 "register_operand" "=v") | |
737 | (ashiftrt:VI (match_operand:VI 1 "register_operand" "v") | |
738 | (match_operand:VI 2 "register_operand" "v")))] | |
739 | "TARGET_VX" | |
740 | "vesrav<bhfgq>\t%v0,%v1,%v2" | |
741 | [(set_attr "op_type" "VRR")]) | |
742 | ||
743 | ; vesrlvb, vesrlvh, vesrlvf, vesrlvg | |
744 | (define_insn "vlshr<mode>3" | |
745 | [(set (match_operand:VI 0 "register_operand" "=v") | |
746 | (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") | |
747 | (match_operand:VI 2 "register_operand" "v")))] | |
748 | "TARGET_VX" | |
749 | "vesrlv<bhfgq>\t%v0,%v1,%v2" | |
750 | [(set_attr "op_type" "VRR")]) | |
751 | ||
752 | ; Vector shift right logical by byte | |
753 | ||
754 | ; Pattern used by e.g. popcount | |
755 | (define_insn "*vec_srb<mode>" | |
756 | [(set (match_operand:V_HW 0 "register_operand" "=v") | |
757 | (unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v") | |
758 | (match_operand:<tointvec> 2 "register_operand" "v")] | |
759 | UNSPEC_VEC_SRLB))] | |
760 | "TARGET_VX" | |
761 | "vsrlb\t%v0,%v1,%v2" | |
762 | [(set_attr "op_type" "VRR")]) | |
763 | ||
764 | ||
765 | ; vmnb, vmnh, vmnf, vmng | |
766 | (define_insn "smin<mode>3" | |
767 | [(set (match_operand:VI 0 "register_operand" "=v") | |
768 | (smin:VI (match_operand:VI 1 "register_operand" "v") | |
769 | (match_operand:VI 2 "register_operand" "v")))] | |
770 | "TARGET_VX" | |
771 | "vmn<bhfgq>\t%v0,%v1,%v2" | |
772 | [(set_attr "op_type" "VRR")]) | |
773 | ||
774 | ; vmxb, vmxh, vmxf, vmxg | |
775 | (define_insn "smax<mode>3" | |
776 | [(set (match_operand:VI 0 "register_operand" "=v") | |
777 | (smax:VI (match_operand:VI 1 "register_operand" "v") | |
778 | (match_operand:VI 2 "register_operand" "v")))] | |
779 | "TARGET_VX" | |
780 | "vmx<bhfgq>\t%v0,%v1,%v2" | |
781 | [(set_attr "op_type" "VRR")]) | |
782 | ||
783 | ; vmnlb, vmnlh, vmnlf, vmnlg | |
784 | (define_insn "umin<mode>3" | |
785 | [(set (match_operand:VI 0 "register_operand" "=v") | |
786 | (umin:VI (match_operand:VI 1 "register_operand" "v") | |
787 | (match_operand:VI 2 "register_operand" "v")))] | |
788 | "TARGET_VX" | |
789 | "vmnl<bhfgq>\t%v0,%v1,%v2" | |
790 | [(set_attr "op_type" "VRR")]) | |
791 | ||
792 | ; vmxlb, vmxlh, vmxlf, vmxlg | |
793 | (define_insn "umax<mode>3" | |
794 | [(set (match_operand:VI 0 "register_operand" "=v") | |
795 | (umax:VI (match_operand:VI 1 "register_operand" "v") | |
796 | (match_operand:VI 2 "register_operand" "v")))] | |
797 | "TARGET_VX" | |
798 | "vmxl<bhfgq>\t%v0,%v1,%v2" | |
799 | [(set_attr "op_type" "VRR")]) | |
800 | ||
801 | ; vmeb, vmeh, vmef | |
802 | (define_insn "vec_widen_smult_even_<mode>" | |
803 | [(set (match_operand:<vec_double> 0 "register_operand" "=v") | |
804 | (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v") | |
805 | (match_operand:VI_QHS 2 "register_operand" "v")] | |
806 | UNSPEC_VEC_SMULT_EVEN))] | |
807 | "TARGET_VX" | |
808 | "vme<bhfgq>\t%v0,%v1,%v2" | |
809 | [(set_attr "op_type" "VRR")]) | |
810 | ||
811 | ; vmleb, vmleh, vmlef | |
812 | (define_insn "vec_widen_umult_even_<mode>" | |
813 | [(set (match_operand:<vec_double> 0 "register_operand" "=v") | |
814 | (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v") | |
815 | (match_operand:VI_QHS 2 "register_operand" "v")] | |
816 | UNSPEC_VEC_UMULT_EVEN))] | |
817 | "TARGET_VX" | |
818 | "vmle<bhfgq>\t%v0,%v1,%v2" | |
819 | [(set_attr "op_type" "VRR")]) | |
820 | ||
821 | ; vmob, vmoh, vmof | |
822 | (define_insn "vec_widen_smult_odd_<mode>" | |
823 | [(set (match_operand:<vec_double> 0 "register_operand" "=v") | |
824 | (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v") | |
825 | (match_operand:VI_QHS 2 "register_operand" "v")] | |
826 | UNSPEC_VEC_SMULT_ODD))] | |
827 | "TARGET_VX" | |
828 | "vmo<bhfgq>\t%v0,%v1,%v2" | |
829 | [(set_attr "op_type" "VRR")]) | |
830 | ||
831 | ; vmlob, vmloh, vmlof | |
832 | (define_insn "vec_widen_umult_odd_<mode>" | |
833 | [(set (match_operand:<vec_double> 0 "register_operand" "=v") | |
834 | (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v") | |
835 | (match_operand:VI_QHS 2 "register_operand" "v")] | |
836 | UNSPEC_VEC_UMULT_ODD))] | |
837 | "TARGET_VX" | |
838 | "vmlo<bhfgq>\t%v0,%v1,%v2" | |
839 | [(set_attr "op_type" "VRR")]) | |
840 | ||
841 | ; vec_widen_umult_hi | |
842 | ; vec_widen_umult_lo | |
843 | ; vec_widen_smult_hi | |
844 | ; vec_widen_smult_lo | |
845 | ||
846 | ; vec_widen_ushiftl_hi | |
847 | ; vec_widen_ushiftl_lo | |
848 | ; vec_widen_sshiftl_hi | |
849 | ; vec_widen_sshiftl_lo | |
850 | ||
851 | ;; | |
852 | ;; Vector floating point arithmetic instructions | |
853 | ;; | |
854 | ||
855 | (define_insn "addv2df3" | |
856 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
857 | (plus:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
858 | (match_operand:V2DF 2 "register_operand" "v")))] | |
859 | "TARGET_VX" | |
860 | "vfadb\t%v0,%v1,%v2" | |
861 | [(set_attr "op_type" "VRR")]) | |
862 | ||
863 | (define_insn "subv2df3" | |
864 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
865 | (minus:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
866 | (match_operand:V2DF 2 "register_operand" "v")))] | |
867 | "TARGET_VX" | |
868 | "vfsdb\t%v0,%v1,%v2" | |
869 | [(set_attr "op_type" "VRR")]) | |
870 | ||
871 | (define_insn "mulv2df3" | |
872 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
873 | (mult:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
874 | (match_operand:V2DF 2 "register_operand" "v")))] | |
875 | "TARGET_VX" | |
876 | "vfmdb\t%v0,%v1,%v2" | |
877 | [(set_attr "op_type" "VRR")]) | |
878 | ||
879 | (define_insn "divv2df3" | |
880 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
881 | (div:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
882 | (match_operand:V2DF 2 "register_operand" "v")))] | |
883 | "TARGET_VX" | |
884 | "vfddb\t%v0,%v1,%v2" | |
885 | [(set_attr "op_type" "VRR")]) | |
886 | ||
887 | (define_insn "sqrtv2df2" | |
888 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
889 | (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "v")))] | |
890 | "TARGET_VX" | |
891 | "vfsqdb\t%v0,%v1" | |
892 | [(set_attr "op_type" "VRR")]) | |
893 | ||
894 | (define_insn "fmav2df4" | |
895 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
896 | (fma:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
897 | (match_operand:V2DF 2 "register_operand" "v") | |
898 | (match_operand:V2DF 3 "register_operand" "v")))] | |
899 | "TARGET_VX" | |
900 | "vfmadb\t%v0,%v1,%v2,%v3" | |
901 | [(set_attr "op_type" "VRR")]) | |
902 | ||
903 | (define_insn "fmsv2df4" | |
904 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
905 | (fma:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
906 | (match_operand:V2DF 2 "register_operand" "v") | |
907 | (neg:V2DF (match_operand:V2DF 3 "register_operand" "v"))))] | |
908 | "TARGET_VX" | |
909 | "vfmsdb\t%v0,%v1,%v2,%v3" | |
910 | [(set_attr "op_type" "VRR")]) | |
911 | ||
912 | (define_insn "negv2df2" | |
913 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
914 | (neg:V2DF (match_operand:V2DF 1 "register_operand" "v")))] | |
915 | "TARGET_VX" | |
916 | "vflcdb\t%v0,%v1" | |
917 | [(set_attr "op_type" "VRR")]) | |
918 | ||
919 | (define_insn "absv2df2" | |
920 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
921 | (abs:V2DF (match_operand:V2DF 1 "register_operand" "v")))] | |
922 | "TARGET_VX" | |
923 | "vflpdb\t%v0,%v1" | |
924 | [(set_attr "op_type" "VRR")]) | |
925 | ||
926 | (define_insn "*negabsv2df2" | |
927 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
928 | (neg:V2DF (abs:V2DF (match_operand:V2DF 1 "register_operand" "v"))))] | |
929 | "TARGET_VX" | |
930 | "vflndb\t%v0,%v1" | |
931 | [(set_attr "op_type" "VRR")]) | |
932 | ||
933 | ; Emulate with compare + select | |
934 | (define_insn_and_split "smaxv2df3" | |
935 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
936 | (smax:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
937 | (match_operand:V2DF 2 "register_operand" "v")))] | |
938 | "TARGET_VX" | |
939 | "#" | |
940 | "" | |
941 | [(set (match_dup 3) | |
942 | (gt:V2DI (match_dup 1) (match_dup 2))) | |
943 | (set (match_dup 0) | |
944 | (if_then_else:V2DF | |
945 | (eq (match_dup 3) (match_dup 4)) | |
946 | (match_dup 2) | |
947 | (match_dup 1)))] | |
948 | { | |
949 | operands[3] = gen_reg_rtx (V2DImode); | |
950 | operands[4] = CONST0_RTX (V2DImode); | |
951 | }) | |
952 | ||
953 | ; Emulate with compare + select | |
954 | (define_insn_and_split "sminv2df3" | |
955 | [(set (match_operand:V2DF 0 "register_operand" "=v") | |
956 | (smin:V2DF (match_operand:V2DF 1 "register_operand" "v") | |
957 | (match_operand:V2DF 2 "register_operand" "v")))] | |
958 | "TARGET_VX" | |
959 | "#" | |
960 | "" | |
961 | [(set (match_dup 3) | |
962 | (gt:V2DI (match_dup 1) (match_dup 2))) | |
963 | (set (match_dup 0) | |
964 | (if_then_else:V2DF | |
965 | (eq (match_dup 3) (match_dup 4)) | |
966 | (match_dup 1) | |
967 | (match_dup 2)))] | |
968 | { | |
969 | operands[3] = gen_reg_rtx (V2DImode); | |
970 | operands[4] = CONST0_RTX (V2DImode); | |
971 | }) | |
972 | ||
973 | ||
974 | ;; | |
975 | ;; Integer compares | |
976 | ;; | |
977 | ||
978 | (define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode>_nocc" | |
979 | [(set (match_operand:VI 2 "register_operand" "=v") | |
980 | (VICMP_HW_OP:VI (match_operand:VI 0 "register_operand" "v") | |
981 | (match_operand:VI 1 "register_operand" "v")))] | |
982 | "TARGET_VX" | |
983 | "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1" | |
984 | [(set_attr "op_type" "VRR")]) | |
985 | ||
986 | ||
987 | ;; | |
988 | ;; Floating point compares | |
989 | ;; | |
990 | ||
991 | ; EQ, GT, GE | |
992 | (define_insn "*vec_cmp<VFCMP_HW_OP:code>v2df_nocc" | |
993 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
994 | (VFCMP_HW_OP:V2DI (match_operand:V2DF 1 "register_operand" "v") | |
995 | (match_operand:V2DF 2 "register_operand" "v")))] | |
996 | "TARGET_VX" | |
997 | "vfc<VFCMP_HW_OP:asm_fcmp_op>db\t%v0,%v1,%v2" | |
998 | [(set_attr "op_type" "VRR")]) | |
999 | ||
1000 | ; Expanders for not directly supported comparisons | |
1001 | ||
1002 | ; UNEQ a u== b -> !(a > b | b > a) | |
1003 | (define_expand "vec_cmpuneqv2df" | |
1004 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
1005 | (gt:V2DI (match_operand:V2DF 1 "register_operand" "v") | |
1006 | (match_operand:V2DF 2 "register_operand" "v"))) | |
1007 | (set (match_dup 3) | |
1008 | (gt:V2DI (match_dup 2) (match_dup 1))) | |
1009 | (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3))) | |
1010 | (set (match_dup 0) (not:V2DI (match_dup 0)))] | |
1011 | "TARGET_VX" | |
1012 | { | |
1013 | operands[3] = gen_reg_rtx (V2DImode); | |
1014 | }) | |
1015 | ||
1016 | ; LTGT a <> b -> a > b | b > a | |
1017 | (define_expand "vec_cmpltgtv2df" | |
1018 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
1019 | (gt:V2DI (match_operand:V2DF 1 "register_operand" "v") | |
1020 | (match_operand:V2DF 2 "register_operand" "v"))) | |
1021 | (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1))) | |
1022 | (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))] | |
1023 | "TARGET_VX" | |
1024 | { | |
1025 | operands[3] = gen_reg_rtx (V2DImode); | |
1026 | }) | |
1027 | ||
1028 | ; ORDERED (a, b): a >= b | b > a | |
1029 | (define_expand "vec_orderedv2df" | |
1030 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
1031 | (ge:V2DI (match_operand:V2DF 1 "register_operand" "v") | |
1032 | (match_operand:V2DF 2 "register_operand" "v"))) | |
1033 | (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1))) | |
1034 | (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))] | |
1035 | "TARGET_VX" | |
1036 | { | |
1037 | operands[3] = gen_reg_rtx (V2DImode); | |
1038 | }) | |
1039 | ||
1040 | ; UNORDERED (a, b): !ORDERED (a, b) | |
1041 | (define_expand "vec_unorderedv2df" | |
1042 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
1043 | (ge:V2DI (match_operand:V2DF 1 "register_operand" "v") | |
1044 | (match_operand:V2DF 2 "register_operand" "v"))) | |
1045 | (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1))) | |
1046 | (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3))) | |
1047 | (set (match_dup 0) (not:V2DI (match_dup 0)))] | |
1048 | "TARGET_VX" | |
1049 | { | |
1050 | operands[3] = gen_reg_rtx (V2DImode); | |
1051 | }) | |
1052 | ||
1053 | (define_insn "*vec_load_pairv2di" | |
1054 | [(set (match_operand:V2DI 0 "register_operand" "=v") | |
1055 | (vec_concat:V2DI (match_operand:DI 1 "register_operand" "d") | |
1056 | (match_operand:DI 2 "register_operand" "d")))] | |
1057 | "TARGET_VX" | |
1058 | "vlvgp\t%v0,%1,%2" | |
1059 | [(set_attr "op_type" "VRR")]) | |
1060 | ||
1061 | (define_insn "vllv16qi" | |
1062 | [(set (match_operand:V16QI 0 "register_operand" "=v") | |
1063 | (unspec:V16QI [(match_operand:SI 1 "register_operand" "d") | |
1064 | (match_operand:BLK 2 "memory_operand" "Q")] | |
1065 | UNSPEC_VEC_LOAD_LEN))] | |
1066 | "TARGET_VX" | |
1067 | "vll\t%v0,%1,%2" | |
1068 | [(set_attr "op_type" "VRS")]) | |
1069 | ||
1070 | ; vfenebs, vfenehs, vfenefs | |
1071 | ; vfenezbs, vfenezhs, vfenezfs | |
1072 | (define_insn "vec_vfenes<mode>" | |
1073 | [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v") | |
1074 | (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v") | |
1075 | (match_operand:VI_HW_QHS 2 "register_operand" "v") | |
e970b4b0 | 1076 | (match_operand:QI 3 "const_mask_operand" "C")] |
085261c8 AK |
1077 | UNSPEC_VEC_VFENE)) |
1078 | (set (reg:CCRAW CC_REGNUM) | |
1079 | (unspec:CCRAW [(match_dup 1) | |
1080 | (match_dup 2) | |
1081 | (match_dup 3)] | |
1082 | UNSPEC_VEC_VFENECC))] | |
1083 | "TARGET_VX" | |
1084 | { | |
1085 | unsigned HOST_WIDE_INT flags = INTVAL (operands[3]); | |
1086 | ||
1087 | gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS))); | |
1088 | flags &= ~VSTRING_FLAG_CS; | |
1089 | ||
1090 | if (flags == VSTRING_FLAG_ZS) | |
1091 | return "vfenez<bhfgq>s\t%v0,%v1,%v2"; | |
1092 | return "vfene<bhfgq>s\t%v0,%v1,%v2"; | |
1093 | } | |
1094 | [(set_attr "op_type" "VRR")]) | |
1095 | ||
1096 | ||
1097 | ; Vector select | |
1098 | ||
1099 | ; The following splitters simplify vec_sel for constant 0 or -1 | |
1100 | ; selection sources. This is required to generate efficient code for | |
1101 | ; vcond. | |
1102 | ||
1103 | ; a = b == c; | |
1104 | (define_split | |
1105 | [(set (match_operand:V 0 "register_operand" "") | |
1106 | (if_then_else:V | |
1107 | (eq (match_operand:<tointvec> 3 "register_operand" "") | |
1108 | (match_operand:V 4 "const0_operand" "")) | |
1109 | (match_operand:V 1 "const0_operand" "") | |
1110 | (match_operand:V 2 "constm1_operand" "")))] | |
1111 | "TARGET_VX" | |
1112 | [(set (match_dup 0) (match_dup 3))] | |
1113 | { | |
1114 | PUT_MODE (operands[3], <V:MODE>mode); | |
1115 | }) | |
1116 | ||
1117 | ; a = ~(b == c) | |
1118 | (define_split | |
1119 | [(set (match_operand:V 0 "register_operand" "") | |
1120 | (if_then_else:V | |
1121 | (eq (match_operand:<tointvec> 3 "register_operand" "") | |
1122 | (match_operand:V 4 "const0_operand" "")) | |
1123 | (match_operand:V 1 "constm1_operand" "") | |
1124 | (match_operand:V 2 "const0_operand" "")))] | |
1125 | "TARGET_VX" | |
1126 | [(set (match_dup 0) (not:V (match_dup 3)))] | |
1127 | { | |
1128 | PUT_MODE (operands[3], <V:MODE>mode); | |
1129 | }) | |
1130 | ||
1131 | ; a = b != c | |
1132 | (define_split | |
1133 | [(set (match_operand:V 0 "register_operand" "") | |
1134 | (if_then_else:V | |
1135 | (ne (match_operand:<tointvec> 3 "register_operand" "") | |
1136 | (match_operand:V 4 "const0_operand" "")) | |
1137 | (match_operand:V 1 "constm1_operand" "") | |
1138 | (match_operand:V 2 "const0_operand" "")))] | |
1139 | "TARGET_VX" | |
1140 | [(set (match_dup 0) (match_dup 3))] | |
1141 | { | |
1142 | PUT_MODE (operands[3], <V:MODE>mode); | |
1143 | }) | |
1144 | ||
1145 | ; a = ~(b != c) | |
1146 | (define_split | |
1147 | [(set (match_operand:V 0 "register_operand" "") | |
1148 | (if_then_else:V | |
1149 | (ne (match_operand:<tointvec> 3 "register_operand" "") | |
1150 | (match_operand:V 4 "const0_operand" "")) | |
1151 | (match_operand:V 1 "const0_operand" "") | |
1152 | (match_operand:V 2 "constm1_operand" "")))] | |
1153 | "TARGET_VX" | |
1154 | [(set (match_dup 0) (not:V (match_dup 3)))] | |
1155 | { | |
1156 | PUT_MODE (operands[3], <V:MODE>mode); | |
1157 | }) | |
1158 | ||
1159 | ; op0 = op3 == 0 ? op1 : op2 | |
1160 | (define_insn "*vec_sel0<mode>" | |
1161 | [(set (match_operand:V 0 "register_operand" "=v") | |
1162 | (if_then_else:V | |
1163 | (eq (match_operand:<tointvec> 3 "register_operand" "v") | |
1164 | (match_operand:<tointvec> 4 "const0_operand" "")) | |
1165 | (match_operand:V 1 "register_operand" "v") | |
1166 | (match_operand:V 2 "register_operand" "v")))] | |
1167 | "TARGET_VX" | |
1168 | "vsel\t%v0,%2,%1,%3" | |
1169 | [(set_attr "op_type" "VRR")]) | |
1170 | ||
1171 | ; op0 = !op3 == 0 ? op1 : op2 | |
1172 | (define_insn "*vec_sel0<mode>" | |
1173 | [(set (match_operand:V 0 "register_operand" "=v") | |
1174 | (if_then_else:V | |
1175 | (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v")) | |
1176 | (match_operand:<tointvec> 4 "const0_operand" "")) | |
1177 | (match_operand:V 1 "register_operand" "v") | |
1178 | (match_operand:V 2 "register_operand" "v")))] | |
1179 | "TARGET_VX" | |
1180 | "vsel\t%v0,%1,%2,%3" | |
1181 | [(set_attr "op_type" "VRR")]) | |
1182 | ||
1183 | ; op0 = op3 == -1 ? op1 : op2 | |
1184 | (define_insn "*vec_sel1<mode>" | |
1185 | [(set (match_operand:V 0 "register_operand" "=v") | |
1186 | (if_then_else:V | |
1187 | (eq (match_operand:<tointvec> 3 "register_operand" "v") | |
1188 | (match_operand:<tointvec> 4 "constm1_operand" "")) | |
1189 | (match_operand:V 1 "register_operand" "v") | |
1190 | (match_operand:V 2 "register_operand" "v")))] | |
1191 | "TARGET_VX" | |
1192 | "vsel\t%v0,%1,%2,%3" | |
1193 | [(set_attr "op_type" "VRR")]) | |
1194 | ||
1195 | ; op0 = !op3 == -1 ? op1 : op2 | |
1196 | (define_insn "*vec_sel1<mode>" | |
1197 | [(set (match_operand:V 0 "register_operand" "=v") | |
1198 | (if_then_else:V | |
1199 | (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v")) | |
1200 | (match_operand:<tointvec> 4 "constm1_operand" "")) | |
1201 | (match_operand:V 1 "register_operand" "v") | |
1202 | (match_operand:V 2 "register_operand" "v")))] | |
1203 | "TARGET_VX" | |
1204 | "vsel\t%v0,%2,%1,%3" | |
1205 | [(set_attr "op_type" "VRR")]) | |
1206 | ||
1207 | ||
1208 | ||
1209 | ; reduc_smin | |
1210 | ; reduc_smax | |
1211 | ; reduc_umin | |
1212 | ; reduc_umax | |
1213 | ||
1214 | ; vec_shl vrep + vsl | |
1215 | ; vec_shr | |
1216 | ||
1217 | ; vec_pack_trunc | |
1218 | ; vec_pack_ssat | |
1219 | ; vec_pack_usat | |
1220 | ; vec_pack_sfix_trunc | |
1221 | ; vec_pack_ufix_trunc | |
1222 | ; vec_unpacks_hi | |
1223 | ; vec_unpacks_low | |
1224 | ; vec_unpacku_hi | |
1225 | ; vec_unpacku_low | |
1226 | ; vec_unpacks_float_hi | |
1227 | ; vec_unpacks_float_lo | |
1228 | ; vec_unpacku_float_hi | |
1229 | ; vec_unpacku_float_lo |