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