Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/arm/neon.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 3bfb6c00c1e0 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 ;; ARM NEON coprocessor Machine Description | |
2 ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. | |
3 ;; Written by CodeSourcery. | |
4 ;; | |
5 ;; This file is part of GCC. | |
6 ;; | |
7 ;; GCC is free software; you can redistribute it and/or modify it | |
8 ;; under the terms of the GNU General Public License as published by | |
9 ;; the Free Software Foundation; either version 3, or (at your option) | |
10 ;; any later version. | |
11 ;; | |
12 ;; GCC is distributed in the hope that it will be useful, but | |
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 ;; General Public License 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 ;; Constants for unspecs. | |
22 (define_constants | |
23 [(UNSPEC_ASHIFT_SIGNED 65) | |
24 (UNSPEC_ASHIFT_UNSIGNED 66) | |
25 (UNSPEC_VABA 67) | |
26 (UNSPEC_VABAL 68) | |
27 (UNSPEC_VABD 69) | |
28 (UNSPEC_VABDL 70) | |
29 (UNSPEC_VABS 71) | |
30 (UNSPEC_VADD 72) | |
31 (UNSPEC_VADDHN 73) | |
32 (UNSPEC_VADDL 74) | |
33 (UNSPEC_VADDW 75) | |
34 (UNSPEC_VAND 76) | |
35 (UNSPEC_VBIC 77) | |
36 (UNSPEC_VBSL 78) | |
37 (UNSPEC_VCAGE 79) | |
38 (UNSPEC_VCAGT 80) | |
39 (UNSPEC_VCEQ 81) | |
40 (UNSPEC_VCGE 82) | |
41 (UNSPEC_VCGT 83) | |
42 (UNSPEC_VCLS 84) | |
43 (UNSPEC_VCLZ 85) | |
44 (UNSPEC_VCNT 86) | |
45 (UNSPEC_VCOMBINE 87) | |
46 (UNSPEC_VCVT 88) | |
47 (UNSPEC_VCVT_N 89) | |
48 (UNSPEC_VDUP_LANE 90) | |
49 (UNSPEC_VDUP_N 91) | |
50 (UNSPEC_VEOR 92) | |
51 (UNSPEC_VEXT 93) | |
52 (UNSPEC_VGET_HIGH 94) | |
53 (UNSPEC_VGET_LANE 95) | |
54 (UNSPEC_VGET_LOW 96) | |
55 (UNSPEC_VHADD 97) | |
56 (UNSPEC_VHSUB 98) | |
57 (UNSPEC_VLD1 99) | |
58 (UNSPEC_VLD1_DUP 100) | |
59 (UNSPEC_VLD1_LANE 101) | |
60 (UNSPEC_VLD2 102) | |
61 (UNSPEC_VLD2_DUP 103) | |
62 (UNSPEC_VLD2_LANE 104) | |
63 (UNSPEC_VLD3 105) | |
64 (UNSPEC_VLD3A 106) | |
65 (UNSPEC_VLD3B 107) | |
66 (UNSPEC_VLD3_DUP 108) | |
67 (UNSPEC_VLD3_LANE 109) | |
68 (UNSPEC_VLD4 110) | |
69 (UNSPEC_VLD4A 111) | |
70 (UNSPEC_VLD4B 112) | |
71 (UNSPEC_VLD4_DUP 113) | |
72 (UNSPEC_VLD4_LANE 114) | |
73 (UNSPEC_VMAX 115) | |
74 (UNSPEC_VMIN 116) | |
75 (UNSPEC_VMLA 117) | |
76 (UNSPEC_VMLAL 118) | |
77 (UNSPEC_VMLA_LANE 119) | |
78 (UNSPEC_VMLAL_LANE 120) | |
79 (UNSPEC_VMLS 121) | |
80 (UNSPEC_VMLSL 122) | |
81 (UNSPEC_VMLS_LANE 123) | |
82 (UNSPEC_VMLSL_LANE 124) | |
83 (UNSPEC_VMOVL 125) | |
84 (UNSPEC_VMOVN 126) | |
85 (UNSPEC_VMUL 127) | |
86 (UNSPEC_VMULL 128) | |
87 (UNSPEC_VMUL_LANE 129) | |
88 (UNSPEC_VMULL_LANE 130) | |
89 (UNSPEC_VMUL_N 131) | |
90 (UNSPEC_VMVN 132) | |
91 (UNSPEC_VORN 133) | |
92 (UNSPEC_VORR 134) | |
93 (UNSPEC_VPADAL 135) | |
94 (UNSPEC_VPADD 136) | |
95 (UNSPEC_VPADDL 137) | |
96 (UNSPEC_VPMAX 138) | |
97 (UNSPEC_VPMIN 139) | |
98 (UNSPEC_VPSMAX 140) | |
99 (UNSPEC_VPSMIN 141) | |
100 (UNSPEC_VPUMAX 142) | |
101 (UNSPEC_VPUMIN 143) | |
102 (UNSPEC_VQABS 144) | |
103 (UNSPEC_VQADD 145) | |
104 (UNSPEC_VQDMLAL 146) | |
105 (UNSPEC_VQDMLAL_LANE 147) | |
106 (UNSPEC_VQDMLSL 148) | |
107 (UNSPEC_VQDMLSL_LANE 149) | |
108 (UNSPEC_VQDMULH 150) | |
109 (UNSPEC_VQDMULH_LANE 151) | |
110 (UNSPEC_VQDMULL 152) | |
111 (UNSPEC_VQDMULL_LANE 153) | |
112 (UNSPEC_VQMOVN 154) | |
113 (UNSPEC_VQMOVUN 155) | |
114 (UNSPEC_VQNEG 156) | |
115 (UNSPEC_VQSHL 157) | |
116 (UNSPEC_VQSHL_N 158) | |
117 (UNSPEC_VQSHLU_N 159) | |
118 (UNSPEC_VQSHRN_N 160) | |
119 (UNSPEC_VQSHRUN_N 161) | |
120 (UNSPEC_VQSUB 162) | |
121 (UNSPEC_VRECPE 163) | |
122 (UNSPEC_VRECPS 164) | |
123 (UNSPEC_VREV16 165) | |
124 (UNSPEC_VREV32 166) | |
125 (UNSPEC_VREV64 167) | |
126 (UNSPEC_VRSQRTE 168) | |
127 (UNSPEC_VRSQRTS 169) | |
128 (UNSPEC_VSET_LANE 170) | |
129 (UNSPEC_VSHL 171) | |
130 (UNSPEC_VSHLL_N 172) | |
131 (UNSPEC_VSHL_N 173) | |
132 (UNSPEC_VSHR_N 174) | |
133 (UNSPEC_VSHRN_N 175) | |
134 (UNSPEC_VSLI 176) | |
135 (UNSPEC_VSRA_N 177) | |
136 (UNSPEC_VSRI 178) | |
137 (UNSPEC_VST1 179) | |
138 (UNSPEC_VST1_LANE 180) | |
139 (UNSPEC_VST2 181) | |
140 (UNSPEC_VST2_LANE 182) | |
141 (UNSPEC_VST3 183) | |
142 (UNSPEC_VST3A 184) | |
143 (UNSPEC_VST3B 185) | |
144 (UNSPEC_VST3_LANE 186) | |
145 (UNSPEC_VST4 187) | |
146 (UNSPEC_VST4A 188) | |
147 (UNSPEC_VST4B 189) | |
148 (UNSPEC_VST4_LANE 190) | |
149 (UNSPEC_VSTRUCTDUMMY 191) | |
150 (UNSPEC_VSUB 192) | |
151 (UNSPEC_VSUBHN 193) | |
152 (UNSPEC_VSUBL 194) | |
153 (UNSPEC_VSUBW 195) | |
154 (UNSPEC_VTBL 196) | |
155 (UNSPEC_VTBX 197) | |
156 (UNSPEC_VTRN1 198) | |
157 (UNSPEC_VTRN2 199) | |
158 (UNSPEC_VTST 200) | |
159 (UNSPEC_VUZP1 201) | |
160 (UNSPEC_VUZP2 202) | |
161 (UNSPEC_VZIP1 203) | |
162 (UNSPEC_VZIP2 204)]) | |
163 | |
164 ;; Double-width vector modes. | |
165 (define_mode_iterator VD [V8QI V4HI V2SI V2SF]) | |
166 | |
167 ;; Double-width vector modes plus 64-bit elements. | |
168 (define_mode_iterator VDX [V8QI V4HI V2SI V2SF DI]) | |
169 | |
170 ;; Same, without floating-point elements. | |
171 (define_mode_iterator VDI [V8QI V4HI V2SI]) | |
172 | |
173 ;; Quad-width vector modes. | |
174 (define_mode_iterator VQ [V16QI V8HI V4SI V4SF]) | |
175 | |
176 ;; Quad-width vector modes plus 64-bit elements. | |
177 (define_mode_iterator VQX [V16QI V8HI V4SI V4SF V2DI]) | |
178 | |
179 ;; Same, without floating-point elements. | |
180 (define_mode_iterator VQI [V16QI V8HI V4SI]) | |
181 | |
182 ;; Same, with TImode added, for moves. | |
183 (define_mode_iterator VQXMOV [V16QI V8HI V4SI V4SF V2DI TI]) | |
184 | |
185 ;; Opaque structure types wider than TImode. | |
186 (define_mode_iterator VSTRUCT [EI OI CI XI]) | |
187 | |
188 ;; Number of instructions needed to load/store struct elements. FIXME! | |
189 (define_mode_attr V_slen [(EI "2") (OI "2") (CI "3") (XI "4")]) | |
190 | |
191 ;; Opaque structure types used in table lookups (except vtbl1/vtbx1). | |
192 (define_mode_iterator VTAB [TI EI OI]) | |
193 | |
194 ;; vtbl<n> suffix for above modes. | |
195 (define_mode_attr VTAB_n [(TI "2") (EI "3") (OI "4")]) | |
196 | |
197 ;; Widenable modes. | |
198 (define_mode_iterator VW [V8QI V4HI V2SI]) | |
199 | |
200 ;; Narrowable modes. | |
201 (define_mode_iterator VN [V8HI V4SI V2DI]) | |
202 | |
203 ;; All supported vector modes (except singleton DImode). | |
204 (define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF V2DI]) | |
205 | |
206 ;; All supported vector modes (except those with 64-bit integer elements). | |
207 (define_mode_iterator VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF]) | |
208 | |
209 ;; Supported integer vector modes (not 64 bit elements). | |
210 (define_mode_iterator VDQIW [V8QI V16QI V4HI V8HI V2SI V4SI]) | |
211 | |
212 ;; Supported integer vector modes (not singleton DI) | |
213 (define_mode_iterator VDQI [V8QI V16QI V4HI V8HI V2SI V4SI V2DI]) | |
214 | |
215 ;; Vector modes, including 64-bit integer elements. | |
216 (define_mode_iterator VDQX [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF DI V2DI]) | |
217 | |
218 ;; Vector modes including 64-bit integer elements, but no floats. | |
219 (define_mode_iterator VDQIX [V8QI V16QI V4HI V8HI V2SI V4SI DI V2DI]) | |
220 | |
221 ;; Vector modes for float->int conversions. | |
222 (define_mode_iterator VCVTF [V2SF V4SF]) | |
223 | |
224 ;; Vector modes form int->float conversions. | |
225 (define_mode_iterator VCVTI [V2SI V4SI]) | |
226 | |
227 ;; Vector modes for doubleword multiply-accumulate, etc. insns. | |
228 (define_mode_iterator VMD [V4HI V2SI V2SF]) | |
229 | |
230 ;; Vector modes for quadword multiply-accumulate, etc. insns. | |
231 (define_mode_iterator VMQ [V8HI V4SI V4SF]) | |
232 | |
233 ;; Above modes combined. | |
234 (define_mode_iterator VMDQ [V4HI V2SI V2SF V8HI V4SI V4SF]) | |
235 | |
236 ;; As VMD, but integer modes only. | |
237 (define_mode_iterator VMDI [V4HI V2SI]) | |
238 | |
239 ;; As VMQ, but integer modes only. | |
240 (define_mode_iterator VMQI [V8HI V4SI]) | |
241 | |
242 ;; Above modes combined. | |
243 (define_mode_iterator VMDQI [V4HI V2SI V8HI V4SI]) | |
244 | |
245 ;; Modes with 8-bit and 16-bit elements. | |
246 (define_mode_iterator VX [V8QI V4HI V16QI V8HI]) | |
247 | |
248 ;; Modes with 8-bit elements. | |
249 (define_mode_iterator VE [V8QI V16QI]) | |
250 | |
251 ;; Modes with 64-bit elements only. | |
252 (define_mode_iterator V64 [DI V2DI]) | |
253 | |
254 ;; Modes with 32-bit elements only. | |
255 (define_mode_iterator V32 [V2SI V2SF V4SI V4SF]) | |
256 | |
257 ;; (Opposite) mode to convert to/from for above conversions. | |
258 (define_mode_attr V_CVTTO [(V2SI "V2SF") (V2SF "V2SI") | |
259 (V4SI "V4SF") (V4SF "V4SI")]) | |
260 | |
261 ;; Define element mode for each vector mode. | |
262 (define_mode_attr V_elem [(V8QI "QI") (V16QI "QI") | |
263 (V4HI "HI") (V8HI "HI") | |
264 (V2SI "SI") (V4SI "SI") | |
265 (V2SF "SF") (V4SF "SF") | |
266 (DI "DI") (V2DI "DI")]) | |
267 | |
268 ;; Element modes for vector extraction, padded up to register size. | |
269 | |
270 (define_mode_attr V_ext [(V8QI "SI") (V16QI "SI") | |
271 (V4HI "SI") (V8HI "SI") | |
272 (V2SI "SI") (V4SI "SI") | |
273 (V2SF "SF") (V4SF "SF") | |
274 (DI "DI") (V2DI "DI")]) | |
275 | |
276 ;; Mode of pair of elements for each vector mode, to define transfer | |
277 ;; size for structure lane/dup loads and stores. | |
278 (define_mode_attr V_two_elem [(V8QI "HI") (V16QI "HI") | |
279 (V4HI "SI") (V8HI "SI") | |
280 (V2SI "V2SI") (V4SI "V2SI") | |
281 (V2SF "V2SF") (V4SF "V2SF") | |
282 (DI "V2DI") (V2DI "V2DI")]) | |
283 | |
284 ;; Similar, for three elements. | |
285 ;; ??? Should we define extra modes so that sizes of all three-element | |
286 ;; accesses can be accurately represented? | |
287 (define_mode_attr V_three_elem [(V8QI "SI") (V16QI "SI") | |
288 (V4HI "V4HI") (V8HI "V4HI") | |
289 (V2SI "V4SI") (V4SI "V4SI") | |
290 (V2SF "V4SF") (V4SF "V4SF") | |
291 (DI "EI") (V2DI "EI")]) | |
292 | |
293 ;; Similar, for four elements. | |
294 (define_mode_attr V_four_elem [(V8QI "SI") (V16QI "SI") | |
295 (V4HI "V4HI") (V8HI "V4HI") | |
296 (V2SI "V4SI") (V4SI "V4SI") | |
297 (V2SF "V4SF") (V4SF "V4SF") | |
298 (DI "OI") (V2DI "OI")]) | |
299 | |
300 ;; Register width from element mode | |
301 (define_mode_attr V_reg [(V8QI "P") (V16QI "q") | |
302 (V4HI "P") (V8HI "q") | |
303 (V2SI "P") (V4SI "q") | |
304 (V2SF "P") (V4SF "q") | |
305 (DI "P") (V2DI "q")]) | |
306 | |
307 ;; Wider modes with the same number of elements. | |
308 (define_mode_attr V_widen [(V8QI "V8HI") (V4HI "V4SI") (V2SI "V2DI")]) | |
309 | |
310 ;; Narrower modes with the same number of elements. | |
311 (define_mode_attr V_narrow [(V8HI "V8QI") (V4SI "V4HI") (V2DI "V2SI")]) | |
312 | |
313 ;; Modes with half the number of equal-sized elements. | |
314 (define_mode_attr V_HALF [(V16QI "V8QI") (V8HI "V4HI") | |
315 (V4SI "V2SI") (V4SF "V2SF") | |
316 (V2DI "DI")]) | |
317 | |
318 ;; Same, but lower-case. | |
319 (define_mode_attr V_half [(V16QI "v8qi") (V8HI "v4hi") | |
320 (V4SI "v2si") (V4SF "v2sf") | |
321 (V2DI "di")]) | |
322 | |
323 ;; Modes with twice the number of equal-sized elements. | |
324 (define_mode_attr V_DOUBLE [(V8QI "V16QI") (V4HI "V8HI") | |
325 (V2SI "V4SI") (V2SF "V4SF") | |
326 (DI "V2DI")]) | |
327 | |
328 ;; Same, but lower-case. | |
329 (define_mode_attr V_double [(V8QI "v16qi") (V4HI "v8hi") | |
330 (V2SI "v4si") (V2SF "v4sf") | |
331 (DI "v2di")]) | |
332 | |
333 ;; Modes with double-width elements. | |
334 (define_mode_attr V_double_width [(V8QI "V4HI") (V16QI "V8HI") | |
335 (V4HI "V2SI") (V8HI "V4SI") | |
336 (V2SI "DI") (V4SI "V2DI")]) | |
337 | |
338 ;; Mode of result of comparison operations (and bit-select operand 1). | |
339 (define_mode_attr V_cmp_result [(V8QI "V8QI") (V16QI "V16QI") | |
340 (V4HI "V4HI") (V8HI "V8HI") | |
341 (V2SI "V2SI") (V4SI "V4SI") | |
342 (V2SF "V2SI") (V4SF "V4SI") | |
343 (DI "DI") (V2DI "V2DI")]) | |
344 | |
345 ;; Get element type from double-width mode, for operations where we don't care | |
346 ;; about signedness. | |
347 (define_mode_attr V_if_elem [(V8QI "i8") (V16QI "i8") | |
348 (V4HI "i16") (V8HI "i16") | |
349 (V2SI "i32") (V4SI "i32") | |
350 (DI "i64") (V2DI "i64") | |
351 (V2SF "f32") (V4SF "f32")]) | |
352 | |
353 ;; Same, but for operations which work on signed values. | |
354 (define_mode_attr V_s_elem [(V8QI "s8") (V16QI "s8") | |
355 (V4HI "s16") (V8HI "s16") | |
356 (V2SI "s32") (V4SI "s32") | |
357 (DI "s64") (V2DI "s64") | |
358 (V2SF "f32") (V4SF "f32")]) | |
359 | |
360 ;; Same, but for operations which work on unsigned values. | |
361 (define_mode_attr V_u_elem [(V8QI "u8") (V16QI "u8") | |
362 (V4HI "u16") (V8HI "u16") | |
363 (V2SI "u32") (V4SI "u32") | |
364 (DI "u64") (V2DI "u64") | |
365 (V2SF "f32") (V4SF "f32")]) | |
366 | |
367 ;; Element types for extraction of unsigned scalars. | |
368 (define_mode_attr V_uf_sclr [(V8QI "u8") (V16QI "u8") | |
369 (V4HI "u16") (V8HI "u16") | |
370 (V2SI "32") (V4SI "32") | |
371 (V2SF "32") (V4SF "32")]) | |
372 | |
373 (define_mode_attr V_sz_elem [(V8QI "8") (V16QI "8") | |
374 (V4HI "16") (V8HI "16") | |
375 (V2SI "32") (V4SI "32") | |
376 (DI "64") (V2DI "64") | |
377 (V2SF "32") (V4SF "32")]) | |
378 | |
379 ;; Element sizes for duplicating ARM registers to all elements of a vector. | |
380 (define_mode_attr VD_dup [(V8QI "8") (V4HI "16") (V2SI "32") (V2SF "32")]) | |
381 | |
382 ;; Opaque integer types for results of pair-forming intrinsics (vtrn, etc.) | |
383 (define_mode_attr V_PAIR [(V8QI "TI") (V16QI "OI") | |
384 (V4HI "TI") (V8HI "OI") | |
385 (V2SI "TI") (V4SI "OI") | |
386 (V2SF "TI") (V4SF "OI") | |
387 (DI "TI") (V2DI "OI")]) | |
388 | |
389 ;; Same, but lower-case. | |
390 (define_mode_attr V_pair [(V8QI "ti") (V16QI "oi") | |
391 (V4HI "ti") (V8HI "oi") | |
392 (V2SI "ti") (V4SI "oi") | |
393 (V2SF "ti") (V4SF "oi") | |
394 (DI "ti") (V2DI "oi")]) | |
395 | |
396 ;; Operations on two halves of a quadword vector. | |
397 (define_code_iterator vqh_ops [plus smin smax umin umax]) | |
398 | |
399 ;; Same, without unsigned variants (for use with *SFmode pattern). | |
400 (define_code_iterator vqhs_ops [plus smin smax]) | |
401 | |
402 ;; Assembler mnemonics for above codes. | |
403 (define_code_attr VQH_mnem [(plus "vadd") (smin "vmin") (smax "vmax") | |
404 (umin "vmin") (umax "vmax")]) | |
405 | |
406 ;; Signs of above, where relevant. | |
407 (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u") | |
408 (umax "u")]) | |
409 | |
410 ;; Extra suffix on some 64-bit insn names (to avoid collision with standard | |
411 ;; names which we don't want to define). | |
412 (define_mode_attr V_suf64 [(V8QI "") (V16QI "") | |
413 (V4HI "") (V8HI "") | |
414 (V2SI "") (V4SI "") | |
415 (V2SF "") (V4SF "") | |
416 (DI "_neon") (V2DI "")]) | |
417 | |
418 ;; Scalars to be presented to scalar multiplication instructions | |
419 ;; must satisfy the following constraints. | |
420 ;; 1. If the mode specifies 16-bit elements, the scalar must be in D0-D7. | |
421 ;; 2. If the mode specifies 32-bit elements, the scalar must be in D0-D15. | |
422 ;; This mode attribute is used to obtain the correct register constraints. | |
423 (define_mode_attr scalar_mul_constraint [(V4HI "x") (V2SI "t") (V2SF "t") | |
424 (V8HI "x") (V4SI "t") (V4SF "t")]) | |
425 | |
426 ;; Attribute used to permit string comparisons against <VQH_mnem> in | |
427 ;; neon_type attribute definitions. | |
428 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd")) | |
429 | |
430 ;; Predicates used for setting neon_type | |
431 | |
432 (define_mode_attr Is_float_mode [(V8QI "false") (V16QI "false") | |
433 (V4HI "false") (V8HI "false") | |
434 (V2SI "false") (V4SI "false") | |
435 (V2SF "true") (V4SF "true") | |
436 (DI "false") (V2DI "false")]) | |
437 | |
438 (define_mode_attr Scalar_mul_8_16 [(V8QI "true") (V16QI "true") | |
439 (V4HI "true") (V8HI "true") | |
440 (V2SI "false") (V4SI "false") | |
441 (V2SF "false") (V4SF "false") | |
442 (DI "false") (V2DI "false")]) | |
443 | |
444 | |
445 (define_mode_attr Is_d_reg [(V8QI "true") (V16QI "false") | |
446 (V4HI "true") (V8HI "false") | |
447 (V2SI "true") (V4SI "false") | |
448 (V2SF "true") (V4SF "false") | |
449 (DI "true") (V2DI "false")]) | |
450 | |
451 (define_mode_attr V_mode_nunits [(V8QI "8") (V16QI "16") | |
452 (V4HI "4") (V8HI "8") | |
453 (V2SI "2") (V4SI "4") | |
454 (V2SF "2") (V4SF "4") | |
455 (DI "1") (V2DI "2")]) | |
456 | |
457 (define_insn "*neon_mov<mode>" | |
458 [(set (match_operand:VD 0 "nonimmediate_operand" | |
459 "=w,Uv,w, w, ?r,?w,?r,?r, ?Us") | |
460 (match_operand:VD 1 "general_operand" | |
461 " w,w, Dn,Uvi, w, r, r, Usi,r"))] | |
462 "TARGET_NEON" | |
463 { | |
464 if (which_alternative == 2) | |
465 { | |
466 int width, is_valid; | |
467 static char templ[40]; | |
468 | |
469 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode, | |
470 &operands[1], &width); | |
471 | |
472 gcc_assert (is_valid != 0); | |
473 | |
474 if (width == 0) | |
475 return "vmov.f32\t%P0, %1 @ <mode>"; | |
476 else | |
477 sprintf (templ, "vmov.i%d\t%%P0, %%1 @ <mode>", width); | |
478 | |
479 return templ; | |
480 } | |
481 | |
482 /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp | |
483 below must be changed to output_move_neon (which will use the | |
484 element/structure loads/stores), and the constraint changed to 'Un' instead | |
485 of 'Uv'. */ | |
486 | |
487 switch (which_alternative) | |
488 { | |
489 case 0: return "vmov\t%P0, %P1 @ <mode>"; | |
490 case 1: case 3: return output_move_vfp (operands); | |
491 case 2: gcc_unreachable (); | |
492 case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>"; | |
493 case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>"; | |
494 default: return output_move_double (operands); | |
495 } | |
496 } | |
497 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*") | |
498 (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2") | |
499 (set_attr "insn" "*,*,*,*,*,*,mov,*,*") | |
500 (set_attr "length" "4,4,4,4,4,4,8,8,8") | |
501 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*") | |
502 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")]) | |
503 | |
504 (define_insn "*neon_mov<mode>" | |
505 [(set (match_operand:VQXMOV 0 "nonimmediate_operand" | |
506 "=w,Un,w, w, ?r,?w,?r,?r, ?Us") | |
507 (match_operand:VQXMOV 1 "general_operand" | |
508 " w,w, Dn,Uni, w, r, r, Usi, r"))] | |
509 "TARGET_NEON" | |
510 { | |
511 if (which_alternative == 2) | |
512 { | |
513 int width, is_valid; | |
514 static char templ[40]; | |
515 | |
516 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode, | |
517 &operands[1], &width); | |
518 | |
519 gcc_assert (is_valid != 0); | |
520 | |
521 if (width == 0) | |
522 return "vmov.f32\t%q0, %1 @ <mode>"; | |
523 else | |
524 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width); | |
525 | |
526 return templ; | |
527 } | |
528 | |
529 switch (which_alternative) | |
530 { | |
531 case 0: return "vmov\t%q0, %q1 @ <mode>"; | |
532 case 1: case 3: return output_move_neon (operands); | |
533 case 2: gcc_unreachable (); | |
534 case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1"; | |
535 case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1"; | |
536 default: return output_move_quad (operands); | |
537 } | |
538 } | |
539 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\ | |
540 neon_mrrc,neon_mcr_2_mcrr,*,*,*") | |
541 (set_attr "type" "*,*,*,*,*,*,alu,load4,store4") | |
542 (set_attr "insn" "*,*,*,*,*,*,mov,*,*") | |
543 (set_attr "length" "4,8,4,8,8,8,16,8,16") | |
544 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*") | |
545 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")]) | |
546 | |
547 (define_expand "movti" | |
548 [(set (match_operand:TI 0 "nonimmediate_operand" "") | |
549 (match_operand:TI 1 "general_operand" ""))] | |
550 "TARGET_NEON" | |
551 { | |
552 }) | |
553 | |
554 (define_expand "mov<mode>" | |
555 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "") | |
556 (match_operand:VSTRUCT 1 "general_operand" ""))] | |
557 "TARGET_NEON" | |
558 { | |
559 }) | |
560 | |
561 (define_insn "*neon_mov<mode>" | |
562 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w") | |
563 (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))] | |
564 "TARGET_NEON" | |
565 { | |
566 switch (which_alternative) | |
567 { | |
568 case 0: return "#"; | |
569 case 1: case 2: return output_move_neon (operands); | |
570 default: gcc_unreachable (); | |
571 } | |
572 } | |
573 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2") | |
574 (set_attr "length" "<V_slen>,<V_slen>,<V_slen>")]) | |
575 | |
576 (define_split | |
577 [(set (match_operand:EI 0 "s_register_operand" "") | |
578 (match_operand:EI 1 "s_register_operand" ""))] | |
579 "TARGET_NEON && reload_completed" | |
580 [(set (match_dup 0) (match_dup 1)) | |
581 (set (match_dup 2) (match_dup 3))] | |
582 { | |
583 int rdest = REGNO (operands[0]); | |
584 int rsrc = REGNO (operands[1]); | |
585 rtx dest[2], src[2]; | |
586 | |
587 dest[0] = gen_rtx_REG (TImode, rdest); | |
588 src[0] = gen_rtx_REG (TImode, rsrc); | |
589 dest[1] = gen_rtx_REG (DImode, rdest + 4); | |
590 src[1] = gen_rtx_REG (DImode, rsrc + 4); | |
591 | |
592 neon_disambiguate_copy (operands, dest, src, 2); | |
593 }) | |
594 | |
595 (define_split | |
596 [(set (match_operand:OI 0 "s_register_operand" "") | |
597 (match_operand:OI 1 "s_register_operand" ""))] | |
598 "TARGET_NEON && reload_completed" | |
599 [(set (match_dup 0) (match_dup 1)) | |
600 (set (match_dup 2) (match_dup 3))] | |
601 { | |
602 int rdest = REGNO (operands[0]); | |
603 int rsrc = REGNO (operands[1]); | |
604 rtx dest[2], src[2]; | |
605 | |
606 dest[0] = gen_rtx_REG (TImode, rdest); | |
607 src[0] = gen_rtx_REG (TImode, rsrc); | |
608 dest[1] = gen_rtx_REG (TImode, rdest + 4); | |
609 src[1] = gen_rtx_REG (TImode, rsrc + 4); | |
610 | |
611 neon_disambiguate_copy (operands, dest, src, 2); | |
612 }) | |
613 | |
614 (define_split | |
615 [(set (match_operand:CI 0 "s_register_operand" "") | |
616 (match_operand:CI 1 "s_register_operand" ""))] | |
617 "TARGET_NEON && reload_completed" | |
618 [(set (match_dup 0) (match_dup 1)) | |
619 (set (match_dup 2) (match_dup 3)) | |
620 (set (match_dup 4) (match_dup 5))] | |
621 { | |
622 int rdest = REGNO (operands[0]); | |
623 int rsrc = REGNO (operands[1]); | |
624 rtx dest[3], src[3]; | |
625 | |
626 dest[0] = gen_rtx_REG (TImode, rdest); | |
627 src[0] = gen_rtx_REG (TImode, rsrc); | |
628 dest[1] = gen_rtx_REG (TImode, rdest + 4); | |
629 src[1] = gen_rtx_REG (TImode, rsrc + 4); | |
630 dest[2] = gen_rtx_REG (TImode, rdest + 8); | |
631 src[2] = gen_rtx_REG (TImode, rsrc + 8); | |
632 | |
633 neon_disambiguate_copy (operands, dest, src, 3); | |
634 }) | |
635 | |
636 (define_split | |
637 [(set (match_operand:XI 0 "s_register_operand" "") | |
638 (match_operand:XI 1 "s_register_operand" ""))] | |
639 "TARGET_NEON && reload_completed" | |
640 [(set (match_dup 0) (match_dup 1)) | |
641 (set (match_dup 2) (match_dup 3)) | |
642 (set (match_dup 4) (match_dup 5)) | |
643 (set (match_dup 6) (match_dup 7))] | |
644 { | |
645 int rdest = REGNO (operands[0]); | |
646 int rsrc = REGNO (operands[1]); | |
647 rtx dest[4], src[4]; | |
648 | |
649 dest[0] = gen_rtx_REG (TImode, rdest); | |
650 src[0] = gen_rtx_REG (TImode, rsrc); | |
651 dest[1] = gen_rtx_REG (TImode, rdest + 4); | |
652 src[1] = gen_rtx_REG (TImode, rsrc + 4); | |
653 dest[2] = gen_rtx_REG (TImode, rdest + 8); | |
654 src[2] = gen_rtx_REG (TImode, rsrc + 8); | |
655 dest[3] = gen_rtx_REG (TImode, rdest + 12); | |
656 src[3] = gen_rtx_REG (TImode, rsrc + 12); | |
657 | |
658 neon_disambiguate_copy (operands, dest, src, 4); | |
659 }) | |
660 | |
661 (define_insn "vec_set<mode>_internal" | |
662 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
663 (vec_merge:VD | |
664 (vec_duplicate:VD | |
665 (match_operand:<V_elem> 1 "s_register_operand" "r")) | |
666 (match_operand:VD 3 "s_register_operand" "0") | |
667 (match_operand:SI 2 "immediate_operand" "i")))] | |
668 "TARGET_NEON" | |
669 { | |
670 int elt = ffs ((int) INTVAL (operands[2]) - 1); | |
671 if (BYTES_BIG_ENDIAN) | |
672 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; | |
673 operands[2] = GEN_INT (elt); | |
674 | |
675 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1"; | |
676 } | |
677 [(set_attr "predicable" "yes") | |
678 (set_attr "neon_type" "neon_mcr")]) | |
679 | |
680 (define_insn "vec_set<mode>_internal" | |
681 [(set (match_operand:VQ 0 "s_register_operand" "=w") | |
682 (vec_merge:VQ | |
683 (vec_duplicate:VQ | |
684 (match_operand:<V_elem> 1 "s_register_operand" "r")) | |
685 (match_operand:VQ 3 "s_register_operand" "0") | |
686 (match_operand:SI 2 "immediate_operand" "i")))] | |
687 "TARGET_NEON" | |
688 { | |
689 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1; | |
690 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2; | |
691 int elt = elem % half_elts; | |
692 int hi = (elem / half_elts) * 2; | |
693 int regno = REGNO (operands[0]); | |
694 | |
695 if (BYTES_BIG_ENDIAN) | |
696 elt = half_elts - 1 - elt; | |
697 | |
698 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi); | |
699 operands[2] = GEN_INT (elt); | |
700 | |
701 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1"; | |
702 } | |
703 [(set_attr "predicable" "yes") | |
704 (set_attr "neon_type" "neon_mcr")] | |
705 ) | |
706 | |
707 (define_insn "vec_setv2di_internal" | |
708 [(set (match_operand:V2DI 0 "s_register_operand" "=w") | |
709 (vec_merge:V2DI | |
710 (vec_duplicate:V2DI | |
711 (match_operand:DI 1 "s_register_operand" "r")) | |
712 (match_operand:V2DI 3 "s_register_operand" "0") | |
713 (match_operand:SI 2 "immediate_operand" "i")))] | |
714 "TARGET_NEON" | |
715 { | |
716 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1; | |
717 int regno = REGNO (operands[0]) + 2 * elem; | |
718 | |
719 operands[0] = gen_rtx_REG (DImode, regno); | |
720 | |
721 return "vmov%?.64\t%P0, %Q1, %R1"; | |
722 } | |
723 [(set_attr "predicable" "yes") | |
724 (set_attr "neon_type" "neon_mcr_2_mcrr")] | |
725 ) | |
726 | |
727 (define_expand "vec_set<mode>" | |
728 [(match_operand:VDQ 0 "s_register_operand" "") | |
729 (match_operand:<V_elem> 1 "s_register_operand" "") | |
730 (match_operand:SI 2 "immediate_operand" "")] | |
731 "TARGET_NEON" | |
732 { | |
733 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]); | |
734 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1], | |
735 GEN_INT (elem), operands[0])); | |
736 DONE; | |
737 }) | |
738 | |
739 (define_insn "vec_extract<mode>" | |
740 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r") | |
741 (vec_select:<V_elem> | |
742 (match_operand:VD 1 "s_register_operand" "w") | |
743 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] | |
744 "TARGET_NEON" | |
745 { | |
746 if (BYTES_BIG_ENDIAN) | |
747 { | |
748 int elt = INTVAL (operands[2]); | |
749 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; | |
750 operands[2] = GEN_INT (elt); | |
751 } | |
752 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"; | |
753 } | |
754 [(set_attr "predicable" "yes") | |
755 (set_attr "neon_type" "neon_bp_simple")] | |
756 ) | |
757 | |
758 (define_insn "vec_extract<mode>" | |
759 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r") | |
760 (vec_select:<V_elem> | |
761 (match_operand:VQ 1 "s_register_operand" "w") | |
762 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] | |
763 "TARGET_NEON" | |
764 { | |
765 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2; | |
766 int elt = INTVAL (operands[2]) % half_elts; | |
767 int hi = (INTVAL (operands[2]) / half_elts) * 2; | |
768 int regno = REGNO (operands[1]); | |
769 | |
770 if (BYTES_BIG_ENDIAN) | |
771 elt = half_elts - 1 - elt; | |
772 | |
773 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi); | |
774 operands[2] = GEN_INT (elt); | |
775 | |
776 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"; | |
777 } | |
778 [(set_attr "predicable" "yes") | |
779 (set_attr "neon_type" "neon_bp_simple")] | |
780 ) | |
781 | |
782 (define_insn "vec_extractv2di" | |
783 [(set (match_operand:DI 0 "s_register_operand" "=r") | |
784 (vec_select:DI | |
785 (match_operand:V2DI 1 "s_register_operand" "w") | |
786 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] | |
787 "TARGET_NEON" | |
788 { | |
789 int regno = REGNO (operands[1]) + INTVAL (operands[2]); | |
790 | |
791 operands[1] = gen_rtx_REG (DImode, regno); | |
792 | |
793 return "vmov%?.64\t%Q0, %R0, %P1"; | |
794 } | |
795 [(set_attr "predicable" "yes") | |
796 (set_attr "neon_type" "neon_int_1")] | |
797 ) | |
798 | |
799 (define_expand "vec_init<mode>" | |
800 [(match_operand:VDQ 0 "s_register_operand" "") | |
801 (match_operand 1 "" "")] | |
802 "TARGET_NEON" | |
803 { | |
804 neon_expand_vector_init (operands[0], operands[1]); | |
805 DONE; | |
806 }) | |
807 | |
808 ;; Doubleword and quadword arithmetic. | |
809 | |
810 ;; NOTE: vadd/vsub and some other instructions also support 64-bit integer | |
811 ;; element size, which we could potentially use for "long long" operations. We | |
812 ;; don't want to do this at present though, because moving values from the | |
813 ;; vector unit to the ARM core is currently slow and 64-bit addition (etc.) is | |
814 ;; easy to do with ARM instructions anyway. | |
815 | |
816 (define_insn "*add<mode>3_neon" | |
817 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
818 (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
819 (match_operand:VDQ 2 "s_register_operand" "w")))] | |
820 "TARGET_NEON" | |
821 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
822 [(set (attr "neon_type") | |
823 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
824 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
825 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
826 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
827 (const_string "neon_int_1")))] | |
828 ) | |
829 | |
830 (define_insn "*sub<mode>3_neon" | |
831 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
832 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
833 (match_operand:VDQ 2 "s_register_operand" "w")))] | |
834 "TARGET_NEON" | |
835 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
836 [(set (attr "neon_type") | |
837 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
838 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
839 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
840 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
841 (const_string "neon_int_2")))] | |
842 ) | |
843 | |
844 (define_insn "*mul<mode>3_neon" | |
845 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
846 (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
847 (match_operand:VDQ 2 "s_register_operand" "w")))] | |
848 "TARGET_NEON" | |
849 "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
850 [(set (attr "neon_type") | |
851 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
852 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
853 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
854 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
855 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
856 (if_then_else | |
857 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
858 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") | |
859 (const_string "neon_mul_qqq_8_16_32_ddd_32")) | |
860 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
861 (const_string "neon_mul_qqq_8_16_32_ddd_32") | |
862 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))] | |
863 ) | |
864 | |
865 (define_insn "ior<mode>3" | |
866 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") | |
867 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") | |
868 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))] | |
869 "TARGET_NEON" | |
870 { | |
871 switch (which_alternative) | |
872 { | |
873 case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2"; | |
874 case 1: return neon_output_logic_immediate ("vorr", &operands[2], | |
875 <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode)); | |
876 default: gcc_unreachable (); | |
877 } | |
878 } | |
879 [(set_attr "neon_type" "neon_int_1")] | |
880 ) | |
881 | |
882 (define_insn "iordi3_neon" | |
883 [(set (match_operand:DI 0 "s_register_operand" "=w,w") | |
884 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0") | |
885 (match_operand:DI 2 "neon_logic_op2" "w,Dl")] | |
886 UNSPEC_VORR))] | |
887 "TARGET_NEON" | |
888 { | |
889 switch (which_alternative) | |
890 { | |
891 case 0: return "vorr\t%P0, %P1, %P2"; | |
892 case 1: return neon_output_logic_immediate ("vorr", &operands[2], | |
893 DImode, 0, VALID_NEON_QREG_MODE (DImode)); | |
894 default: gcc_unreachable (); | |
895 } | |
896 } | |
897 [(set_attr "neon_type" "neon_int_1")] | |
898 ) | |
899 | |
900 ;; The concrete forms of the Neon immediate-logic instructions are vbic and | |
901 ;; vorr. We support the pseudo-instruction vand instead, because that | |
902 ;; corresponds to the canonical form the middle-end expects to use for | |
903 ;; immediate bitwise-ANDs. | |
904 | |
905 (define_insn "and<mode>3" | |
906 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") | |
907 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") | |
908 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))] | |
909 "TARGET_NEON" | |
910 { | |
911 switch (which_alternative) | |
912 { | |
913 case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2"; | |
914 case 1: return neon_output_logic_immediate ("vand", &operands[2], | |
915 <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode)); | |
916 default: gcc_unreachable (); | |
917 } | |
918 } | |
919 [(set_attr "neon_type" "neon_int_1")] | |
920 ) | |
921 | |
922 (define_insn "anddi3_neon" | |
923 [(set (match_operand:DI 0 "s_register_operand" "=w,w") | |
924 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0") | |
925 (match_operand:DI 2 "neon_inv_logic_op2" "w,DL")] | |
926 UNSPEC_VAND))] | |
927 "TARGET_NEON" | |
928 { | |
929 switch (which_alternative) | |
930 { | |
931 case 0: return "vand\t%P0, %P1, %P2"; | |
932 case 1: return neon_output_logic_immediate ("vand", &operands[2], | |
933 DImode, 1, VALID_NEON_QREG_MODE (DImode)); | |
934 default: gcc_unreachable (); | |
935 } | |
936 } | |
937 [(set_attr "neon_type" "neon_int_1")] | |
938 ) | |
939 | |
940 (define_insn "orn<mode>3_neon" | |
941 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
942 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
943 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))] | |
944 "TARGET_NEON" | |
945 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
946 [(set_attr "neon_type" "neon_int_1")] | |
947 ) | |
948 | |
949 (define_insn "orndi3_neon" | |
950 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
951 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") | |
952 (match_operand:DI 2 "s_register_operand" "w")] | |
953 UNSPEC_VORN))] | |
954 "TARGET_NEON" | |
955 "vorn\t%P0, %P1, %P2" | |
956 [(set_attr "neon_type" "neon_int_1")] | |
957 ) | |
958 | |
959 (define_insn "bic<mode>3_neon" | |
960 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
961 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
962 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))] | |
963 "TARGET_NEON" | |
964 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
965 [(set_attr "neon_type" "neon_int_1")] | |
966 ) | |
967 | |
968 (define_insn "bicdi3_neon" | |
969 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
970 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") | |
971 (match_operand:DI 2 "s_register_operand" "w")] | |
972 UNSPEC_VBIC))] | |
973 "TARGET_NEON" | |
974 "vbic\t%P0, %P1, %P2" | |
975 [(set_attr "neon_type" "neon_int_1")] | |
976 ) | |
977 | |
978 (define_insn "xor<mode>3" | |
979 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
980 (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w") | |
981 (match_operand:VDQ 2 "s_register_operand" "w")))] | |
982 "TARGET_NEON" | |
983 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
984 [(set_attr "neon_type" "neon_int_1")] | |
985 ) | |
986 | |
987 (define_insn "xordi3_neon" | |
988 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
989 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") | |
990 (match_operand:DI 2 "s_register_operand" "w")] | |
991 UNSPEC_VEOR))] | |
992 "TARGET_NEON" | |
993 "veor\t%P0, %P1, %P2" | |
994 [(set_attr "neon_type" "neon_int_1")] | |
995 ) | |
996 | |
997 (define_insn "one_cmpl<mode>2" | |
998 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
999 (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))] | |
1000 "TARGET_NEON" | |
1001 "vmvn\t%<V_reg>0, %<V_reg>1" | |
1002 [(set_attr "neon_type" "neon_int_1")] | |
1003 ) | |
1004 | |
1005 (define_insn "abs<mode>2" | |
1006 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1007 (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))] | |
1008 "TARGET_NEON" | |
1009 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
1010 [(set (attr "neon_type") | |
1011 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1012 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1013 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1014 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1015 (const_string "neon_int_3")))] | |
1016 ) | |
1017 | |
1018 (define_insn "neg<mode>2" | |
1019 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1020 (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))] | |
1021 "TARGET_NEON" | |
1022 "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
1023 [(set (attr "neon_type") | |
1024 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1025 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1026 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1027 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1028 (const_string "neon_int_3")))] | |
1029 ) | |
1030 | |
1031 (define_insn "*umin<mode>3_neon" | |
1032 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
1033 (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") | |
1034 (match_operand:VDQIW 2 "s_register_operand" "w")))] | |
1035 "TARGET_NEON" | |
1036 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1037 [(set_attr "neon_type" "neon_int_5")] | |
1038 ) | |
1039 | |
1040 (define_insn "*umax<mode>3_neon" | |
1041 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
1042 (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") | |
1043 (match_operand:VDQIW 2 "s_register_operand" "w")))] | |
1044 "TARGET_NEON" | |
1045 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1046 [(set_attr "neon_type" "neon_int_5")] | |
1047 ) | |
1048 | |
1049 (define_insn "*smin<mode>3_neon" | |
1050 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1051 (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w") | |
1052 (match_operand:VDQW 2 "s_register_operand" "w")))] | |
1053 "TARGET_NEON" | |
1054 "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1055 [(set (attr "neon_type") | |
1056 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1057 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1058 (const_string "neon_int_5")))] | |
1059 ) | |
1060 | |
1061 (define_insn "*smax<mode>3_neon" | |
1062 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1063 (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w") | |
1064 (match_operand:VDQW 2 "s_register_operand" "w")))] | |
1065 "TARGET_NEON" | |
1066 "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1067 [(set (attr "neon_type") | |
1068 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1069 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1070 (const_string "neon_int_5")))] | |
1071 ) | |
1072 | |
1073 ; TODO: V2DI shifts are current disabled because there are bugs in the | |
1074 ; generic vectorizer code. It ends up creating a V2DI constructor with | |
1075 ; SImode elements. | |
1076 | |
1077 (define_insn "ashl<mode>3" | |
1078 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
1079 (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") | |
1080 (match_operand:VDQIW 2 "s_register_operand" "w")))] | |
1081 "TARGET_NEON" | |
1082 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1083 [(set (attr "neon_type") | |
1084 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1085 (const_string "neon_vshl_ddd") | |
1086 (const_string "neon_shift_3")))] | |
1087 ) | |
1088 | |
1089 ; Used for implementing logical shift-right, which is a left-shift by a negative | |
1090 ; amount, with signed operands. This is essentially the same as ashl<mode>3 | |
1091 ; above, but using an unspec in case GCC tries anything tricky with negative | |
1092 ; shift amounts. | |
1093 | |
1094 (define_insn "ashl<mode>3_signed" | |
1095 [(set (match_operand:VDQI 0 "s_register_operand" "=w") | |
1096 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w") | |
1097 (match_operand:VDQI 2 "s_register_operand" "w")] | |
1098 UNSPEC_ASHIFT_SIGNED))] | |
1099 "TARGET_NEON" | |
1100 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1101 [(set (attr "neon_type") | |
1102 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1103 (const_string "neon_vshl_ddd") | |
1104 (const_string "neon_shift_3")))] | |
1105 ) | |
1106 | |
1107 ; Used for implementing logical shift-right, which is a left-shift by a negative | |
1108 ; amount, with unsigned operands. | |
1109 | |
1110 (define_insn "ashl<mode>3_unsigned" | |
1111 [(set (match_operand:VDQI 0 "s_register_operand" "=w") | |
1112 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w") | |
1113 (match_operand:VDQI 2 "s_register_operand" "w")] | |
1114 UNSPEC_ASHIFT_UNSIGNED))] | |
1115 "TARGET_NEON" | |
1116 "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1117 [(set (attr "neon_type") | |
1118 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1119 (const_string "neon_vshl_ddd") | |
1120 (const_string "neon_shift_3")))] | |
1121 ) | |
1122 | |
1123 (define_expand "ashr<mode>3" | |
1124 [(set (match_operand:VDQIW 0 "s_register_operand" "") | |
1125 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") | |
1126 (match_operand:VDQIW 2 "s_register_operand" "")))] | |
1127 "TARGET_NEON" | |
1128 { | |
1129 rtx neg = gen_reg_rtx (<MODE>mode); | |
1130 | |
1131 emit_insn (gen_neg<mode>2 (neg, operands[2])); | |
1132 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg)); | |
1133 | |
1134 DONE; | |
1135 }) | |
1136 | |
1137 (define_expand "lshr<mode>3" | |
1138 [(set (match_operand:VDQIW 0 "s_register_operand" "") | |
1139 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") | |
1140 (match_operand:VDQIW 2 "s_register_operand" "")))] | |
1141 "TARGET_NEON" | |
1142 { | |
1143 rtx neg = gen_reg_rtx (<MODE>mode); | |
1144 | |
1145 emit_insn (gen_neg<mode>2 (neg, operands[2])); | |
1146 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg)); | |
1147 | |
1148 DONE; | |
1149 }) | |
1150 | |
1151 ;; Widening operations | |
1152 | |
1153 (define_insn "widen_ssum<mode>3" | |
1154 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1155 (plus:<V_widen> (sign_extend:<V_widen> | |
1156 (match_operand:VW 1 "s_register_operand" "%w")) | |
1157 (match_operand:<V_widen> 2 "s_register_operand" "w")))] | |
1158 "TARGET_NEON" | |
1159 "vaddw.<V_s_elem>\t%q0, %q2, %P1" | |
1160 [(set_attr "neon_type" "neon_int_3")] | |
1161 ) | |
1162 | |
1163 (define_insn "widen_usum<mode>3" | |
1164 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1165 (plus:<V_widen> (zero_extend:<V_widen> | |
1166 (match_operand:VW 1 "s_register_operand" "%w")) | |
1167 (match_operand:<V_widen> 2 "s_register_operand" "w")))] | |
1168 "TARGET_NEON" | |
1169 "vaddw.<V_u_elem>\t%q0, %q2, %P1" | |
1170 [(set_attr "neon_type" "neon_int_3")] | |
1171 ) | |
1172 | |
1173 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit | |
1174 ;; shift-count granularity. That's good enough for the middle-end's current | |
1175 ;; needs. | |
1176 | |
1177 (define_expand "vec_shr_<mode>" | |
1178 [(match_operand:VDQ 0 "s_register_operand" "") | |
1179 (match_operand:VDQ 1 "s_register_operand" "") | |
1180 (match_operand:SI 2 "const_multiple_of_8_operand" "")] | |
1181 "TARGET_NEON" | |
1182 { | |
1183 rtx zero_reg; | |
1184 HOST_WIDE_INT num_bits = INTVAL (operands[2]); | |
1185 const int width = GET_MODE_BITSIZE (<MODE>mode); | |
1186 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode; | |
1187 rtx (*gen_ext) (rtx, rtx, rtx, rtx) = | |
1188 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi; | |
1189 | |
1190 if (num_bits == width) | |
1191 { | |
1192 emit_move_insn (operands[0], operands[1]); | |
1193 DONE; | |
1194 } | |
1195 | |
1196 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode)); | |
1197 operands[0] = gen_lowpart (bvecmode, operands[0]); | |
1198 operands[1] = gen_lowpart (bvecmode, operands[1]); | |
1199 | |
1200 emit_insn (gen_ext (operands[0], operands[1], zero_reg, | |
1201 GEN_INT (num_bits / BITS_PER_UNIT))); | |
1202 DONE; | |
1203 }) | |
1204 | |
1205 (define_expand "vec_shl_<mode>" | |
1206 [(match_operand:VDQ 0 "s_register_operand" "") | |
1207 (match_operand:VDQ 1 "s_register_operand" "") | |
1208 (match_operand:SI 2 "const_multiple_of_8_operand" "")] | |
1209 "TARGET_NEON" | |
1210 { | |
1211 rtx zero_reg; | |
1212 HOST_WIDE_INT num_bits = INTVAL (operands[2]); | |
1213 const int width = GET_MODE_BITSIZE (<MODE>mode); | |
1214 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode; | |
1215 rtx (*gen_ext) (rtx, rtx, rtx, rtx) = | |
1216 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi; | |
1217 | |
1218 if (num_bits == 0) | |
1219 { | |
1220 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode)); | |
1221 DONE; | |
1222 } | |
1223 | |
1224 num_bits = width - num_bits; | |
1225 | |
1226 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode)); | |
1227 operands[0] = gen_lowpart (bvecmode, operands[0]); | |
1228 operands[1] = gen_lowpart (bvecmode, operands[1]); | |
1229 | |
1230 emit_insn (gen_ext (operands[0], zero_reg, operands[1], | |
1231 GEN_INT (num_bits / BITS_PER_UNIT))); | |
1232 DONE; | |
1233 }) | |
1234 | |
1235 ;; Helpers for quad-word reduction operations | |
1236 | |
1237 ; Add (or smin, smax...) the low N/2 elements of the N-element vector | |
1238 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an | |
1239 ; N/2-element vector. | |
1240 | |
1241 (define_insn "quad_halves_<code>v4si" | |
1242 [(set (match_operand:V2SI 0 "s_register_operand" "=w") | |
1243 (vqh_ops:V2SI | |
1244 (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w") | |
1245 (parallel [(const_int 0) (const_int 1)])) | |
1246 (vec_select:V2SI (match_dup 1) | |
1247 (parallel [(const_int 2) (const_int 3)]))))] | |
1248 "TARGET_NEON" | |
1249 "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1" | |
1250 [(set_attr "vqh_mnem" "<VQH_mnem>") | |
1251 (set (attr "neon_type") | |
1252 (if_then_else (eq_attr "vqh_mnem" "vadd") | |
1253 (const_string "neon_int_1") (const_string "neon_int_5")))] | |
1254 ) | |
1255 | |
1256 (define_insn "quad_halves_<code>v4sf" | |
1257 [(set (match_operand:V2SF 0 "s_register_operand" "=w") | |
1258 (vqhs_ops:V2SF | |
1259 (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w") | |
1260 (parallel [(const_int 0) (const_int 1)])) | |
1261 (vec_select:V2SF (match_dup 1) | |
1262 (parallel [(const_int 2) (const_int 3)]))))] | |
1263 "TARGET_NEON" | |
1264 "<VQH_mnem>.f32\t%P0, %e1, %f1" | |
1265 [(set_attr "vqh_mnem" "<VQH_mnem>") | |
1266 (set (attr "neon_type") | |
1267 (if_then_else (eq_attr "vqh_mnem" "vadd") | |
1268 (const_string "neon_int_1") (const_string "neon_int_5")))] | |
1269 ) | |
1270 | |
1271 (define_insn "quad_halves_<code>v8hi" | |
1272 [(set (match_operand:V4HI 0 "s_register_operand" "+w") | |
1273 (vqh_ops:V4HI | |
1274 (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w") | |
1275 (parallel [(const_int 0) (const_int 1) | |
1276 (const_int 2) (const_int 3)])) | |
1277 (vec_select:V4HI (match_dup 1) | |
1278 (parallel [(const_int 4) (const_int 5) | |
1279 (const_int 6) (const_int 7)]))))] | |
1280 "TARGET_NEON" | |
1281 "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1" | |
1282 [(set_attr "vqh_mnem" "<VQH_mnem>") | |
1283 (set (attr "neon_type") | |
1284 (if_then_else (eq_attr "vqh_mnem" "vadd") | |
1285 (const_string "neon_int_1") (const_string "neon_int_5")))] | |
1286 ) | |
1287 | |
1288 (define_insn "quad_halves_<code>v16qi" | |
1289 [(set (match_operand:V8QI 0 "s_register_operand" "+w") | |
1290 (vqh_ops:V8QI | |
1291 (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w") | |
1292 (parallel [(const_int 0) (const_int 1) | |
1293 (const_int 2) (const_int 3) | |
1294 (const_int 4) (const_int 5) | |
1295 (const_int 6) (const_int 7)])) | |
1296 (vec_select:V8QI (match_dup 1) | |
1297 (parallel [(const_int 8) (const_int 9) | |
1298 (const_int 10) (const_int 11) | |
1299 (const_int 12) (const_int 13) | |
1300 (const_int 14) (const_int 15)]))))] | |
1301 "TARGET_NEON" | |
1302 "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1" | |
1303 [(set_attr "vqh_mnem" "<VQH_mnem>") | |
1304 (set (attr "neon_type") | |
1305 (if_then_else (eq_attr "vqh_mnem" "vadd") | |
1306 (const_string "neon_int_1") (const_string "neon_int_5")))] | |
1307 ) | |
1308 | |
1309 ; FIXME: We wouldn't need the following insns if we could write subregs of | |
1310 ; vector registers. Make an attempt at removing unnecessary moves, though | |
1311 ; we're really at the mercy of the register allocator. | |
1312 | |
1313 (define_insn "move_lo_quad_v4si" | |
1314 [(set (match_operand:V4SI 0 "s_register_operand" "+w") | |
1315 (vec_concat:V4SI | |
1316 (match_operand:V2SI 1 "s_register_operand" "w") | |
1317 (vec_select:V2SI (match_dup 0) | |
1318 (parallel [(const_int 2) (const_int 3)]))))] | |
1319 "TARGET_NEON" | |
1320 { | |
1321 int dest = REGNO (operands[0]); | |
1322 int src = REGNO (operands[1]); | |
1323 | |
1324 if (dest != src) | |
1325 return "vmov\t%e0, %P1"; | |
1326 else | |
1327 return ""; | |
1328 } | |
1329 [(set_attr "neon_type" "neon_bp_simple")] | |
1330 ) | |
1331 | |
1332 (define_insn "move_lo_quad_v4sf" | |
1333 [(set (match_operand:V4SF 0 "s_register_operand" "+w") | |
1334 (vec_concat:V4SF | |
1335 (match_operand:V2SF 1 "s_register_operand" "w") | |
1336 (vec_select:V2SF (match_dup 0) | |
1337 (parallel [(const_int 2) (const_int 3)]))))] | |
1338 "TARGET_NEON" | |
1339 { | |
1340 int dest = REGNO (operands[0]); | |
1341 int src = REGNO (operands[1]); | |
1342 | |
1343 if (dest != src) | |
1344 return "vmov\t%e0, %P1"; | |
1345 else | |
1346 return ""; | |
1347 } | |
1348 [(set_attr "neon_type" "neon_bp_simple")] | |
1349 ) | |
1350 | |
1351 (define_insn "move_lo_quad_v8hi" | |
1352 [(set (match_operand:V8HI 0 "s_register_operand" "+w") | |
1353 (vec_concat:V8HI | |
1354 (match_operand:V4HI 1 "s_register_operand" "w") | |
1355 (vec_select:V4HI (match_dup 0) | |
1356 (parallel [(const_int 4) (const_int 5) | |
1357 (const_int 6) (const_int 7)]))))] | |
1358 "TARGET_NEON" | |
1359 { | |
1360 int dest = REGNO (operands[0]); | |
1361 int src = REGNO (operands[1]); | |
1362 | |
1363 if (dest != src) | |
1364 return "vmov\t%e0, %P1"; | |
1365 else | |
1366 return ""; | |
1367 } | |
1368 [(set_attr "neon_type" "neon_bp_simple")] | |
1369 ) | |
1370 | |
1371 (define_insn "move_lo_quad_v16qi" | |
1372 [(set (match_operand:V16QI 0 "s_register_operand" "+w") | |
1373 (vec_concat:V16QI | |
1374 (match_operand:V8QI 1 "s_register_operand" "w") | |
1375 (vec_select:V8QI (match_dup 0) | |
1376 (parallel [(const_int 8) (const_int 9) | |
1377 (const_int 10) (const_int 11) | |
1378 (const_int 12) (const_int 13) | |
1379 (const_int 14) (const_int 15)]))))] | |
1380 "TARGET_NEON" | |
1381 { | |
1382 int dest = REGNO (operands[0]); | |
1383 int src = REGNO (operands[1]); | |
1384 | |
1385 if (dest != src) | |
1386 return "vmov\t%e0, %P1"; | |
1387 else | |
1388 return ""; | |
1389 } | |
1390 [(set_attr "neon_type" "neon_bp_simple")] | |
1391 ) | |
1392 | |
1393 ;; Reduction operations | |
1394 | |
1395 (define_expand "reduc_splus_<mode>" | |
1396 [(match_operand:VD 0 "s_register_operand" "") | |
1397 (match_operand:VD 1 "s_register_operand" "")] | |
1398 "TARGET_NEON" | |
1399 { | |
1400 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, | |
1401 &gen_neon_vpadd_internal<mode>); | |
1402 DONE; | |
1403 }) | |
1404 | |
1405 (define_expand "reduc_splus_<mode>" | |
1406 [(match_operand:VQ 0 "s_register_operand" "") | |
1407 (match_operand:VQ 1 "s_register_operand" "")] | |
1408 "TARGET_NEON" | |
1409 { | |
1410 rtx step1 = gen_reg_rtx (<V_HALF>mode); | |
1411 rtx res_d = gen_reg_rtx (<V_HALF>mode); | |
1412 | |
1413 emit_insn (gen_quad_halves_plus<mode> (step1, operands[1])); | |
1414 emit_insn (gen_reduc_splus_<V_half> (res_d, step1)); | |
1415 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); | |
1416 | |
1417 DONE; | |
1418 }) | |
1419 | |
1420 (define_insn "reduc_splus_v2di" | |
1421 [(set (match_operand:V2DI 0 "s_register_operand" "=w") | |
1422 (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")] | |
1423 UNSPEC_VPADD))] | |
1424 "TARGET_NEON" | |
1425 "vadd.i64\t%e0, %e1, %f1" | |
1426 [(set_attr "neon_type" "neon_int_1")] | |
1427 ) | |
1428 | |
1429 ;; NEON does not distinguish between signed and unsigned addition except on | |
1430 ;; widening operations. | |
1431 (define_expand "reduc_uplus_<mode>" | |
1432 [(match_operand:VDQI 0 "s_register_operand" "") | |
1433 (match_operand:VDQI 1 "s_register_operand" "")] | |
1434 "TARGET_NEON" | |
1435 { | |
1436 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1])); | |
1437 DONE; | |
1438 }) | |
1439 | |
1440 (define_expand "reduc_smin_<mode>" | |
1441 [(match_operand:VD 0 "s_register_operand" "") | |
1442 (match_operand:VD 1 "s_register_operand" "")] | |
1443 "TARGET_NEON" | |
1444 { | |
1445 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, | |
1446 &gen_neon_vpsmin<mode>); | |
1447 DONE; | |
1448 }) | |
1449 | |
1450 (define_expand "reduc_smin_<mode>" | |
1451 [(match_operand:VQ 0 "s_register_operand" "") | |
1452 (match_operand:VQ 1 "s_register_operand" "")] | |
1453 "TARGET_NEON" | |
1454 { | |
1455 rtx step1 = gen_reg_rtx (<V_HALF>mode); | |
1456 rtx res_d = gen_reg_rtx (<V_HALF>mode); | |
1457 | |
1458 emit_insn (gen_quad_halves_smin<mode> (step1, operands[1])); | |
1459 emit_insn (gen_reduc_smin_<V_half> (res_d, step1)); | |
1460 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); | |
1461 | |
1462 DONE; | |
1463 }) | |
1464 | |
1465 (define_expand "reduc_smax_<mode>" | |
1466 [(match_operand:VD 0 "s_register_operand" "") | |
1467 (match_operand:VD 1 "s_register_operand" "")] | |
1468 "TARGET_NEON" | |
1469 { | |
1470 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, | |
1471 &gen_neon_vpsmax<mode>); | |
1472 DONE; | |
1473 }) | |
1474 | |
1475 (define_expand "reduc_smax_<mode>" | |
1476 [(match_operand:VQ 0 "s_register_operand" "") | |
1477 (match_operand:VQ 1 "s_register_operand" "")] | |
1478 "TARGET_NEON" | |
1479 { | |
1480 rtx step1 = gen_reg_rtx (<V_HALF>mode); | |
1481 rtx res_d = gen_reg_rtx (<V_HALF>mode); | |
1482 | |
1483 emit_insn (gen_quad_halves_smax<mode> (step1, operands[1])); | |
1484 emit_insn (gen_reduc_smax_<V_half> (res_d, step1)); | |
1485 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); | |
1486 | |
1487 DONE; | |
1488 }) | |
1489 | |
1490 (define_expand "reduc_umin_<mode>" | |
1491 [(match_operand:VDI 0 "s_register_operand" "") | |
1492 (match_operand:VDI 1 "s_register_operand" "")] | |
1493 "TARGET_NEON" | |
1494 { | |
1495 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, | |
1496 &gen_neon_vpumin<mode>); | |
1497 DONE; | |
1498 }) | |
1499 | |
1500 (define_expand "reduc_umin_<mode>" | |
1501 [(match_operand:VQI 0 "s_register_operand" "") | |
1502 (match_operand:VQI 1 "s_register_operand" "")] | |
1503 "TARGET_NEON" | |
1504 { | |
1505 rtx step1 = gen_reg_rtx (<V_HALF>mode); | |
1506 rtx res_d = gen_reg_rtx (<V_HALF>mode); | |
1507 | |
1508 emit_insn (gen_quad_halves_umin<mode> (step1, operands[1])); | |
1509 emit_insn (gen_reduc_umin_<V_half> (res_d, step1)); | |
1510 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); | |
1511 | |
1512 DONE; | |
1513 }) | |
1514 | |
1515 (define_expand "reduc_umax_<mode>" | |
1516 [(match_operand:VDI 0 "s_register_operand" "") | |
1517 (match_operand:VDI 1 "s_register_operand" "")] | |
1518 "TARGET_NEON" | |
1519 { | |
1520 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, | |
1521 &gen_neon_vpumax<mode>); | |
1522 DONE; | |
1523 }) | |
1524 | |
1525 (define_expand "reduc_umax_<mode>" | |
1526 [(match_operand:VQI 0 "s_register_operand" "") | |
1527 (match_operand:VQI 1 "s_register_operand" "")] | |
1528 "TARGET_NEON" | |
1529 { | |
1530 rtx step1 = gen_reg_rtx (<V_HALF>mode); | |
1531 rtx res_d = gen_reg_rtx (<V_HALF>mode); | |
1532 | |
1533 emit_insn (gen_quad_halves_umax<mode> (step1, operands[1])); | |
1534 emit_insn (gen_reduc_umax_<V_half> (res_d, step1)); | |
1535 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); | |
1536 | |
1537 DONE; | |
1538 }) | |
1539 | |
1540 (define_insn "neon_vpadd_internal<mode>" | |
1541 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1542 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
1543 (match_operand:VD 2 "s_register_operand" "w")] | |
1544 UNSPEC_VPADD))] | |
1545 "TARGET_NEON" | |
1546 "vpadd.<V_if_elem>\t%P0, %P1, %P2" | |
1547 ;; Assume this schedules like vadd. | |
1548 [(set (attr "neon_type") | |
1549 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1550 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1551 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1552 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1553 (const_string "neon_int_1")))] | |
1554 ) | |
1555 | |
1556 (define_insn "neon_vpsmin<mode>" | |
1557 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1558 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
1559 (match_operand:VD 2 "s_register_operand" "w")] | |
1560 UNSPEC_VPSMIN))] | |
1561 "TARGET_NEON" | |
1562 "vpmin.<V_s_elem>\t%P0, %P1, %P2" | |
1563 ;; Assume this schedules like vmin. | |
1564 [(set (attr "neon_type") | |
1565 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1566 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1567 (const_string "neon_int_5")))] | |
1568 ) | |
1569 | |
1570 (define_insn "neon_vpsmax<mode>" | |
1571 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1572 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
1573 (match_operand:VD 2 "s_register_operand" "w")] | |
1574 UNSPEC_VPSMAX))] | |
1575 "TARGET_NEON" | |
1576 "vpmax.<V_s_elem>\t%P0, %P1, %P2" | |
1577 ;; Assume this schedules like vmax. | |
1578 [(set (attr "neon_type") | |
1579 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1580 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1581 (const_string "neon_int_5")))] | |
1582 ) | |
1583 | |
1584 (define_insn "neon_vpumin<mode>" | |
1585 [(set (match_operand:VDI 0 "s_register_operand" "=w") | |
1586 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w") | |
1587 (match_operand:VDI 2 "s_register_operand" "w")] | |
1588 UNSPEC_VPUMIN))] | |
1589 "TARGET_NEON" | |
1590 "vpmin.<V_u_elem>\t%P0, %P1, %P2" | |
1591 ;; Assume this schedules like umin. | |
1592 [(set_attr "neon_type" "neon_int_5")] | |
1593 ) | |
1594 | |
1595 (define_insn "neon_vpumax<mode>" | |
1596 [(set (match_operand:VDI 0 "s_register_operand" "=w") | |
1597 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w") | |
1598 (match_operand:VDI 2 "s_register_operand" "w")] | |
1599 UNSPEC_VPUMAX))] | |
1600 "TARGET_NEON" | |
1601 "vpmax.<V_u_elem>\t%P0, %P1, %P2" | |
1602 ;; Assume this schedules like umax. | |
1603 [(set_attr "neon_type" "neon_int_5")] | |
1604 ) | |
1605 | |
1606 ;; Saturating arithmetic | |
1607 | |
1608 ; NOTE: Neon supports many more saturating variants of instructions than the | |
1609 ; following, but these are all GCC currently understands. | |
1610 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself | |
1611 ; yet either, although these patterns may be used by intrinsics when they're | |
1612 ; added. | |
1613 | |
1614 (define_insn "*ss_add<mode>_neon" | |
1615 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1616 (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w") | |
1617 (match_operand:VD 2 "s_register_operand" "w")))] | |
1618 "TARGET_NEON" | |
1619 "vqadd.<V_s_elem>\t%P0, %P1, %P2" | |
1620 [(set_attr "neon_type" "neon_int_4")] | |
1621 ) | |
1622 | |
1623 (define_insn "*us_add<mode>_neon" | |
1624 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1625 (us_plus:VD (match_operand:VD 1 "s_register_operand" "w") | |
1626 (match_operand:VD 2 "s_register_operand" "w")))] | |
1627 "TARGET_NEON" | |
1628 "vqadd.<V_u_elem>\t%P0, %P1, %P2" | |
1629 [(set_attr "neon_type" "neon_int_4")] | |
1630 ) | |
1631 | |
1632 (define_insn "*ss_sub<mode>_neon" | |
1633 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1634 (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w") | |
1635 (match_operand:VD 2 "s_register_operand" "w")))] | |
1636 "TARGET_NEON" | |
1637 "vqsub.<V_s_elem>\t%P0, %P1, %P2" | |
1638 [(set_attr "neon_type" "neon_int_5")] | |
1639 ) | |
1640 | |
1641 (define_insn "*us_sub<mode>_neon" | |
1642 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
1643 (us_minus:VD (match_operand:VD 1 "s_register_operand" "w") | |
1644 (match_operand:VD 2 "s_register_operand" "w")))] | |
1645 "TARGET_NEON" | |
1646 "vqsub.<V_u_elem>\t%P0, %P1, %P2" | |
1647 [(set_attr "neon_type" "neon_int_5")] | |
1648 ) | |
1649 | |
1650 ;; Patterns for builtins. | |
1651 | |
1652 ; good for plain vadd, vaddq. | |
1653 | |
1654 (define_insn "neon_vadd<mode>" | |
1655 [(set (match_operand:VDQX 0 "s_register_operand" "=w") | |
1656 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") | |
1657 (match_operand:VDQX 2 "s_register_operand" "w") | |
1658 (match_operand:SI 3 "immediate_operand" "i")] | |
1659 UNSPEC_VADD))] | |
1660 "TARGET_NEON" | |
1661 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1662 [(set (attr "neon_type") | |
1663 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1664 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1665 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1666 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1667 (const_string "neon_int_1")))] | |
1668 ) | |
1669 | |
1670 ; operand 3 represents in bits: | |
1671 ; bit 0: signed (vs unsigned). | |
1672 ; bit 1: rounding (vs none). | |
1673 | |
1674 (define_insn "neon_vaddl<mode>" | |
1675 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1676 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w") | |
1677 (match_operand:VDI 2 "s_register_operand" "w") | |
1678 (match_operand:SI 3 "immediate_operand" "i")] | |
1679 UNSPEC_VADDL))] | |
1680 "TARGET_NEON" | |
1681 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" | |
1682 [(set_attr "neon_type" "neon_int_3")] | |
1683 ) | |
1684 | |
1685 (define_insn "neon_vaddw<mode>" | |
1686 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1687 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w") | |
1688 (match_operand:VDI 2 "s_register_operand" "w") | |
1689 (match_operand:SI 3 "immediate_operand" "i")] | |
1690 UNSPEC_VADDW))] | |
1691 "TARGET_NEON" | |
1692 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2" | |
1693 [(set_attr "neon_type" "neon_int_2")] | |
1694 ) | |
1695 | |
1696 ; vhadd and vrhadd. | |
1697 | |
1698 (define_insn "neon_vhadd<mode>" | |
1699 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
1700 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
1701 (match_operand:VDQIW 2 "s_register_operand" "w") | |
1702 (match_operand:SI 3 "immediate_operand" "i")] | |
1703 UNSPEC_VHADD))] | |
1704 "TARGET_NEON" | |
1705 "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1706 [(set_attr "neon_type" "neon_int_4")] | |
1707 ) | |
1708 | |
1709 (define_insn "neon_vqadd<mode>" | |
1710 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
1711 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
1712 (match_operand:VDQIX 2 "s_register_operand" "w") | |
1713 (match_operand:SI 3 "immediate_operand" "i")] | |
1714 UNSPEC_VQADD))] | |
1715 "TARGET_NEON" | |
1716 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1717 [(set_attr "neon_type" "neon_int_4")] | |
1718 ) | |
1719 | |
1720 (define_insn "neon_vaddhn<mode>" | |
1721 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
1722 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
1723 (match_operand:VN 2 "s_register_operand" "w") | |
1724 (match_operand:SI 3 "immediate_operand" "i")] | |
1725 UNSPEC_VADDHN))] | |
1726 "TARGET_NEON" | |
1727 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2" | |
1728 [(set_attr "neon_type" "neon_int_4")] | |
1729 ) | |
1730 | |
1731 (define_insn "neon_vmul<mode>" | |
1732 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1733 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") | |
1734 (match_operand:VDQW 2 "s_register_operand" "w") | |
1735 (match_operand:SI 3 "immediate_operand" "i")] | |
1736 UNSPEC_VMUL))] | |
1737 "TARGET_NEON" | |
1738 "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1739 [(set (attr "neon_type") | |
1740 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1741 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1742 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1743 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1744 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1745 (if_then_else | |
1746 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1747 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") | |
1748 (const_string "neon_mul_qqq_8_16_32_ddd_32")) | |
1749 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1750 (const_string "neon_mul_qqq_8_16_32_ddd_32") | |
1751 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))] | |
1752 ) | |
1753 | |
1754 (define_insn "neon_vmla<mode>" | |
1755 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1756 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") | |
1757 (match_operand:VDQW 2 "s_register_operand" "w") | |
1758 (match_operand:VDQW 3 "s_register_operand" "w") | |
1759 (match_operand:SI 4 "immediate_operand" "i")] | |
1760 UNSPEC_VMLA))] | |
1761 "TARGET_NEON" | |
1762 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" | |
1763 [(set (attr "neon_type") | |
1764 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1765 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1766 (const_string "neon_fp_vmla_ddd") | |
1767 (const_string "neon_fp_vmla_qqq")) | |
1768 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1769 (if_then_else | |
1770 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1771 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1772 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) | |
1773 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1774 (const_string "neon_mla_qqq_8_16") | |
1775 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] | |
1776 ) | |
1777 | |
1778 (define_insn "neon_vmlal<mode>" | |
1779 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1780 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
1781 (match_operand:VW 2 "s_register_operand" "w") | |
1782 (match_operand:VW 3 "s_register_operand" "w") | |
1783 (match_operand:SI 4 "immediate_operand" "i")] | |
1784 UNSPEC_VMLAL))] | |
1785 "TARGET_NEON" | |
1786 "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3" | |
1787 [(set (attr "neon_type") | |
1788 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1789 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1790 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
1791 ) | |
1792 | |
1793 (define_insn "neon_vmls<mode>" | |
1794 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
1795 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") | |
1796 (match_operand:VDQW 2 "s_register_operand" "w") | |
1797 (match_operand:VDQW 3 "s_register_operand" "w") | |
1798 (match_operand:SI 4 "immediate_operand" "i")] | |
1799 UNSPEC_VMLS))] | |
1800 "TARGET_NEON" | |
1801 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" | |
1802 [(set (attr "neon_type") | |
1803 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1804 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1805 (const_string "neon_fp_vmla_ddd") | |
1806 (const_string "neon_fp_vmla_qqq")) | |
1807 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1808 (if_then_else | |
1809 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1810 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1811 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) | |
1812 (if_then_else | |
1813 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1814 (const_string "neon_mla_qqq_8_16") | |
1815 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] | |
1816 ) | |
1817 | |
1818 (define_insn "neon_vmlsl<mode>" | |
1819 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1820 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
1821 (match_operand:VW 2 "s_register_operand" "w") | |
1822 (match_operand:VW 3 "s_register_operand" "w") | |
1823 (match_operand:SI 4 "immediate_operand" "i")] | |
1824 UNSPEC_VMLSL))] | |
1825 "TARGET_NEON" | |
1826 "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3" | |
1827 [(set (attr "neon_type") | |
1828 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1829 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1830 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
1831 ) | |
1832 | |
1833 (define_insn "neon_vqdmulh<mode>" | |
1834 [(set (match_operand:VMDQI 0 "s_register_operand" "=w") | |
1835 (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w") | |
1836 (match_operand:VMDQI 2 "s_register_operand" "w") | |
1837 (match_operand:SI 3 "immediate_operand" "i")] | |
1838 UNSPEC_VQDMULH))] | |
1839 "TARGET_NEON" | |
1840 "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1841 [(set (attr "neon_type") | |
1842 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1843 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1844 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") | |
1845 (const_string "neon_mul_qqq_8_16_32_ddd_32")) | |
1846 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1847 (const_string "neon_mul_qqq_8_16_32_ddd_32") | |
1848 (const_string "neon_mul_qqq_8_16_32_ddd_32"))))] | |
1849 ) | |
1850 | |
1851 (define_insn "neon_vqdmlal<mode>" | |
1852 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1853 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
1854 (match_operand:VMDI 2 "s_register_operand" "w") | |
1855 (match_operand:VMDI 3 "s_register_operand" "w") | |
1856 (match_operand:SI 4 "immediate_operand" "i")] | |
1857 UNSPEC_VQDMLAL))] | |
1858 "TARGET_NEON" | |
1859 "vqdmlal.<V_s_elem>\t%q0, %P2, %P3" | |
1860 [(set (attr "neon_type") | |
1861 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1862 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1863 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
1864 ) | |
1865 | |
1866 (define_insn "neon_vqdmlsl<mode>" | |
1867 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1868 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
1869 (match_operand:VMDI 2 "s_register_operand" "w") | |
1870 (match_operand:VMDI 3 "s_register_operand" "w") | |
1871 (match_operand:SI 4 "immediate_operand" "i")] | |
1872 UNSPEC_VQDMLSL))] | |
1873 "TARGET_NEON" | |
1874 "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3" | |
1875 [(set (attr "neon_type") | |
1876 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1877 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") | |
1878 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
1879 ) | |
1880 | |
1881 (define_insn "neon_vmull<mode>" | |
1882 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1883 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") | |
1884 (match_operand:VW 2 "s_register_operand" "w") | |
1885 (match_operand:SI 3 "immediate_operand" "i")] | |
1886 UNSPEC_VMULL))] | |
1887 "TARGET_NEON" | |
1888 "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2" | |
1889 [(set (attr "neon_type") | |
1890 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1891 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") | |
1892 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] | |
1893 ) | |
1894 | |
1895 (define_insn "neon_vqdmull<mode>" | |
1896 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1897 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") | |
1898 (match_operand:VMDI 2 "s_register_operand" "w") | |
1899 (match_operand:SI 3 "immediate_operand" "i")] | |
1900 UNSPEC_VQDMULL))] | |
1901 "TARGET_NEON" | |
1902 "vqdmull.<V_s_elem>\t%q0, %P1, %P2" | |
1903 [(set (attr "neon_type") | |
1904 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
1905 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") | |
1906 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] | |
1907 ) | |
1908 | |
1909 (define_insn "neon_vsub<mode>" | |
1910 [(set (match_operand:VDQX 0 "s_register_operand" "=w") | |
1911 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") | |
1912 (match_operand:VDQX 2 "s_register_operand" "w") | |
1913 (match_operand:SI 3 "immediate_operand" "i")] | |
1914 UNSPEC_VSUB))] | |
1915 "TARGET_NEON" | |
1916 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1917 [(set (attr "neon_type") | |
1918 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1919 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1920 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1921 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1922 (const_string "neon_int_2")))] | |
1923 ) | |
1924 | |
1925 (define_insn "neon_vsubl<mode>" | |
1926 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1927 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w") | |
1928 (match_operand:VDI 2 "s_register_operand" "w") | |
1929 (match_operand:SI 3 "immediate_operand" "i")] | |
1930 UNSPEC_VSUBL))] | |
1931 "TARGET_NEON" | |
1932 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" | |
1933 [(set_attr "neon_type" "neon_int_2")] | |
1934 ) | |
1935 | |
1936 (define_insn "neon_vsubw<mode>" | |
1937 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
1938 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w") | |
1939 (match_operand:VDI 2 "s_register_operand" "w") | |
1940 (match_operand:SI 3 "immediate_operand" "i")] | |
1941 UNSPEC_VSUBW))] | |
1942 "TARGET_NEON" | |
1943 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2" | |
1944 [(set_attr "neon_type" "neon_int_2")] | |
1945 ) | |
1946 | |
1947 (define_insn "neon_vqsub<mode>" | |
1948 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
1949 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
1950 (match_operand:VDQIX 2 "s_register_operand" "w") | |
1951 (match_operand:SI 3 "immediate_operand" "i")] | |
1952 UNSPEC_VQSUB))] | |
1953 "TARGET_NEON" | |
1954 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1955 [(set_attr "neon_type" "neon_int_5")] | |
1956 ) | |
1957 | |
1958 (define_insn "neon_vhsub<mode>" | |
1959 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
1960 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
1961 (match_operand:VDQIW 2 "s_register_operand" "w") | |
1962 (match_operand:SI 3 "immediate_operand" "i")] | |
1963 UNSPEC_VHSUB))] | |
1964 "TARGET_NEON" | |
1965 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1966 [(set_attr "neon_type" "neon_int_5")] | |
1967 ) | |
1968 | |
1969 (define_insn "neon_vsubhn<mode>" | |
1970 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
1971 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
1972 (match_operand:VN 2 "s_register_operand" "w") | |
1973 (match_operand:SI 3 "immediate_operand" "i")] | |
1974 UNSPEC_VSUBHN))] | |
1975 "TARGET_NEON" | |
1976 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2" | |
1977 [(set_attr "neon_type" "neon_int_4")] | |
1978 ) | |
1979 | |
1980 (define_insn "neon_vceq<mode>" | |
1981 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") | |
1982 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") | |
1983 (match_operand:VDQW 2 "s_register_operand" "w") | |
1984 (match_operand:SI 3 "immediate_operand" "i")] | |
1985 UNSPEC_VCEQ))] | |
1986 "TARGET_NEON" | |
1987 "vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
1988 [(set (attr "neon_type") | |
1989 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
1990 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
1991 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
1992 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
1993 (const_string "neon_int_5")))] | |
1994 ) | |
1995 | |
1996 (define_insn "neon_vcge<mode>" | |
1997 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") | |
1998 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") | |
1999 (match_operand:VDQW 2 "s_register_operand" "w") | |
2000 (match_operand:SI 3 "immediate_operand" "i")] | |
2001 UNSPEC_VCGE))] | |
2002 "TARGET_NEON" | |
2003 "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2004 [(set (attr "neon_type") | |
2005 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2006 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2007 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2008 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2009 (const_string "neon_int_5")))] | |
2010 ) | |
2011 | |
2012 (define_insn "neon_vcgt<mode>" | |
2013 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") | |
2014 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") | |
2015 (match_operand:VDQW 2 "s_register_operand" "w") | |
2016 (match_operand:SI 3 "immediate_operand" "i")] | |
2017 UNSPEC_VCGT))] | |
2018 "TARGET_NEON" | |
2019 "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2020 [(set (attr "neon_type") | |
2021 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2022 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2023 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2024 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2025 (const_string "neon_int_5")))] | |
2026 ) | |
2027 | |
2028 (define_insn "neon_vcage<mode>" | |
2029 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") | |
2030 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2031 (match_operand:VCVTF 2 "s_register_operand" "w") | |
2032 (match_operand:SI 3 "immediate_operand" "i")] | |
2033 UNSPEC_VCAGE))] | |
2034 "TARGET_NEON" | |
2035 "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2036 [(set (attr "neon_type") | |
2037 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2038 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2039 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2040 ) | |
2041 | |
2042 (define_insn "neon_vcagt<mode>" | |
2043 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") | |
2044 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2045 (match_operand:VCVTF 2 "s_register_operand" "w") | |
2046 (match_operand:SI 3 "immediate_operand" "i")] | |
2047 UNSPEC_VCAGT))] | |
2048 "TARGET_NEON" | |
2049 "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2050 [(set (attr "neon_type") | |
2051 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2052 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2053 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2054 ) | |
2055 | |
2056 (define_insn "neon_vtst<mode>" | |
2057 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2058 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2059 (match_operand:VDQIW 2 "s_register_operand" "w") | |
2060 (match_operand:SI 3 "immediate_operand" "i")] | |
2061 UNSPEC_VTST))] | |
2062 "TARGET_NEON" | |
2063 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2064 [(set_attr "neon_type" "neon_int_4")] | |
2065 ) | |
2066 | |
2067 (define_insn "neon_vabd<mode>" | |
2068 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
2069 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") | |
2070 (match_operand:VDQW 2 "s_register_operand" "w") | |
2071 (match_operand:SI 3 "immediate_operand" "i")] | |
2072 UNSPEC_VABD))] | |
2073 "TARGET_NEON" | |
2074 "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2075 [(set (attr "neon_type") | |
2076 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2077 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2078 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2079 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2080 (const_string "neon_int_5")))] | |
2081 ) | |
2082 | |
2083 (define_insn "neon_vabdl<mode>" | |
2084 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
2085 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") | |
2086 (match_operand:VW 2 "s_register_operand" "w") | |
2087 (match_operand:SI 3 "immediate_operand" "i")] | |
2088 UNSPEC_VABDL))] | |
2089 "TARGET_NEON" | |
2090 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" | |
2091 [(set_attr "neon_type" "neon_int_5")] | |
2092 ) | |
2093 | |
2094 (define_insn "neon_vaba<mode>" | |
2095 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2096 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "0") | |
2097 (match_operand:VDQIW 2 "s_register_operand" "w") | |
2098 (match_operand:VDQIW 3 "s_register_operand" "w") | |
2099 (match_operand:SI 4 "immediate_operand" "i")] | |
2100 UNSPEC_VABA))] | |
2101 "TARGET_NEON" | |
2102 "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" | |
2103 [(set (attr "neon_type") | |
2104 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2105 (const_string "neon_vaba") (const_string "neon_vaba_qqq")))] | |
2106 ) | |
2107 | |
2108 (define_insn "neon_vabal<mode>" | |
2109 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
2110 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
2111 (match_operand:VW 2 "s_register_operand" "w") | |
2112 (match_operand:VW 3 "s_register_operand" "w") | |
2113 (match_operand:SI 4 "immediate_operand" "i")] | |
2114 UNSPEC_VABAL))] | |
2115 "TARGET_NEON" | |
2116 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3" | |
2117 [(set_attr "neon_type" "neon_vaba")] | |
2118 ) | |
2119 | |
2120 (define_insn "neon_vmax<mode>" | |
2121 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
2122 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") | |
2123 (match_operand:VDQW 2 "s_register_operand" "w") | |
2124 (match_operand:SI 3 "immediate_operand" "i")] | |
2125 UNSPEC_VMAX))] | |
2126 "TARGET_NEON" | |
2127 "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2128 [(set (attr "neon_type") | |
2129 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2130 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2131 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2132 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2133 (const_string "neon_int_5")))] | |
2134 ) | |
2135 | |
2136 (define_insn "neon_vmin<mode>" | |
2137 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
2138 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") | |
2139 (match_operand:VDQW 2 "s_register_operand" "w") | |
2140 (match_operand:SI 3 "immediate_operand" "i")] | |
2141 UNSPEC_VMIN))] | |
2142 "TARGET_NEON" | |
2143 "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2144 [(set (attr "neon_type") | |
2145 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2146 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2147 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2148 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2149 (const_string "neon_int_5")))] | |
2150 ) | |
2151 | |
2152 (define_expand "neon_vpadd<mode>" | |
2153 [(match_operand:VD 0 "s_register_operand" "=w") | |
2154 (match_operand:VD 1 "s_register_operand" "w") | |
2155 (match_operand:VD 2 "s_register_operand" "w") | |
2156 (match_operand:SI 3 "immediate_operand" "i")] | |
2157 "TARGET_NEON" | |
2158 { | |
2159 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1], | |
2160 operands[2])); | |
2161 DONE; | |
2162 }) | |
2163 | |
2164 (define_insn "neon_vpaddl<mode>" | |
2165 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w") | |
2166 (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2167 (match_operand:SI 2 "immediate_operand" "i")] | |
2168 UNSPEC_VPADDL))] | |
2169 "TARGET_NEON" | |
2170 "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1" | |
2171 ;; Assume this schedules like vaddl. | |
2172 [(set_attr "neon_type" "neon_int_3")] | |
2173 ) | |
2174 | |
2175 (define_insn "neon_vpadal<mode>" | |
2176 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w") | |
2177 (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0") | |
2178 (match_operand:VDQIW 2 "s_register_operand" "w") | |
2179 (match_operand:SI 3 "immediate_operand" "i")] | |
2180 UNSPEC_VPADAL))] | |
2181 "TARGET_NEON" | |
2182 "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2" | |
2183 ;; Assume this schedules like vpadd. | |
2184 [(set_attr "neon_type" "neon_int_1")] | |
2185 ) | |
2186 | |
2187 (define_insn "neon_vpmax<mode>" | |
2188 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
2189 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
2190 (match_operand:VD 2 "s_register_operand" "w") | |
2191 (match_operand:SI 3 "immediate_operand" "i")] | |
2192 UNSPEC_VPMAX))] | |
2193 "TARGET_NEON" | |
2194 "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2195 ;; Assume this schedules like vmax. | |
2196 [(set (attr "neon_type") | |
2197 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2198 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2199 (const_string "neon_int_5")))] | |
2200 ) | |
2201 | |
2202 (define_insn "neon_vpmin<mode>" | |
2203 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
2204 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
2205 (match_operand:VD 2 "s_register_operand" "w") | |
2206 (match_operand:SI 3 "immediate_operand" "i")] | |
2207 UNSPEC_VPMIN))] | |
2208 "TARGET_NEON" | |
2209 "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2210 ;; Assume this schedules like vmin. | |
2211 [(set (attr "neon_type") | |
2212 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2213 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2214 (const_string "neon_int_5")))] | |
2215 ) | |
2216 | |
2217 (define_insn "neon_vrecps<mode>" | |
2218 [(set (match_operand:VCVTF 0 "s_register_operand" "=w") | |
2219 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2220 (match_operand:VCVTF 2 "s_register_operand" "w") | |
2221 (match_operand:SI 3 "immediate_operand" "i")] | |
2222 UNSPEC_VRECPS))] | |
2223 "TARGET_NEON" | |
2224 "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2225 [(set (attr "neon_type") | |
2226 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2227 (const_string "neon_fp_vrecps_vrsqrts_ddd") | |
2228 (const_string "neon_fp_vrecps_vrsqrts_qqq")))] | |
2229 ) | |
2230 | |
2231 (define_insn "neon_vrsqrts<mode>" | |
2232 [(set (match_operand:VCVTF 0 "s_register_operand" "=w") | |
2233 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2234 (match_operand:VCVTF 2 "s_register_operand" "w") | |
2235 (match_operand:SI 3 "immediate_operand" "i")] | |
2236 UNSPEC_VRSQRTS))] | |
2237 "TARGET_NEON" | |
2238 "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
2239 [(set (attr "neon_type") | |
2240 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2241 (const_string "neon_fp_vrecps_vrsqrts_ddd") | |
2242 (const_string "neon_fp_vrecps_vrsqrts_qqq")))] | |
2243 ) | |
2244 | |
2245 (define_insn "neon_vabs<mode>" | |
2246 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
2247 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") | |
2248 (match_operand:SI 2 "immediate_operand" "i")] | |
2249 UNSPEC_VABS))] | |
2250 "TARGET_NEON" | |
2251 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
2252 [(set (attr "neon_type") | |
2253 (if_then_else (ior (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2254 (ne (symbol_ref "<Is_float_mode>") (const_int 0))) | |
2255 (if_then_else | |
2256 (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2257 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2258 (const_string "neon_fp_vadd_qqq_vabs_qq")) | |
2259 (const_string "neon_vqneg_vqabs")))] | |
2260 ) | |
2261 | |
2262 (define_insn "neon_vqabs<mode>" | |
2263 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2264 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2265 (match_operand:SI 2 "immediate_operand" "i")] | |
2266 UNSPEC_VQABS))] | |
2267 "TARGET_NEON" | |
2268 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
2269 [(set_attr "neon_type" "neon_vqneg_vqabs")] | |
2270 ) | |
2271 | |
2272 (define_expand "neon_vneg<mode>" | |
2273 [(match_operand:VDQW 0 "s_register_operand" "") | |
2274 (match_operand:VDQW 1 "s_register_operand" "") | |
2275 (match_operand:SI 2 "immediate_operand" "")] | |
2276 "TARGET_NEON" | |
2277 { | |
2278 emit_insn (gen_neg<mode>2 (operands[0], operands[1])); | |
2279 DONE; | |
2280 }) | |
2281 | |
2282 (define_insn "neon_vqneg<mode>" | |
2283 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2284 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2285 (match_operand:SI 2 "immediate_operand" "i")] | |
2286 UNSPEC_VQNEG))] | |
2287 "TARGET_NEON" | |
2288 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
2289 [(set_attr "neon_type" "neon_vqneg_vqabs")] | |
2290 ) | |
2291 | |
2292 (define_insn "neon_vcls<mode>" | |
2293 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2294 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2295 (match_operand:SI 2 "immediate_operand" "i")] | |
2296 UNSPEC_VCLS))] | |
2297 "TARGET_NEON" | |
2298 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1" | |
2299 [(set_attr "neon_type" "neon_int_1")] | |
2300 ) | |
2301 | |
2302 (define_insn "neon_vclz<mode>" | |
2303 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") | |
2304 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") | |
2305 (match_operand:SI 2 "immediate_operand" "i")] | |
2306 UNSPEC_VCLZ))] | |
2307 "TARGET_NEON" | |
2308 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1" | |
2309 [(set_attr "neon_type" "neon_int_1")] | |
2310 ) | |
2311 | |
2312 (define_insn "neon_vcnt<mode>" | |
2313 [(set (match_operand:VE 0 "s_register_operand" "=w") | |
2314 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w") | |
2315 (match_operand:SI 2 "immediate_operand" "i")] | |
2316 UNSPEC_VCNT))] | |
2317 "TARGET_NEON" | |
2318 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" | |
2319 [(set_attr "neon_type" "neon_int_1")] | |
2320 ) | |
2321 | |
2322 (define_insn "neon_vrecpe<mode>" | |
2323 [(set (match_operand:V32 0 "s_register_operand" "=w") | |
2324 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w") | |
2325 (match_operand:SI 2 "immediate_operand" "i")] | |
2326 UNSPEC_VRECPE))] | |
2327 "TARGET_NEON" | |
2328 "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1" | |
2329 [(set (attr "neon_type") | |
2330 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2331 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2332 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2333 ) | |
2334 | |
2335 (define_insn "neon_vrsqrte<mode>" | |
2336 [(set (match_operand:V32 0 "s_register_operand" "=w") | |
2337 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w") | |
2338 (match_operand:SI 2 "immediate_operand" "i")] | |
2339 UNSPEC_VRSQRTE))] | |
2340 "TARGET_NEON" | |
2341 "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1" | |
2342 [(set (attr "neon_type") | |
2343 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2344 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2345 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2346 ) | |
2347 | |
2348 (define_expand "neon_vmvn<mode>" | |
2349 [(match_operand:VDQIW 0 "s_register_operand" "") | |
2350 (match_operand:VDQIW 1 "s_register_operand" "") | |
2351 (match_operand:SI 2 "immediate_operand" "")] | |
2352 "TARGET_NEON" | |
2353 { | |
2354 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1])); | |
2355 DONE; | |
2356 }) | |
2357 | |
2358 (define_insn "neon_vget_lane<mode>_sext_internal" | |
2359 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
2360 (sign_extend:SI | |
2361 (vec_select:<V_elem> | |
2362 (match_operand:VD 1 "s_register_operand" "w") | |
2363 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] | |
2364 "TARGET_NEON" | |
2365 { | |
2366 if (BYTES_BIG_ENDIAN) | |
2367 { | |
2368 int elt = INTVAL (operands[2]); | |
2369 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; | |
2370 operands[2] = GEN_INT (elt); | |
2371 } | |
2372 return "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]"; | |
2373 } | |
2374 [(set_attr "predicable" "yes") | |
2375 (set_attr "neon_type" "neon_bp_simple")] | |
2376 ) | |
2377 | |
2378 (define_insn "neon_vget_lane<mode>_zext_internal" | |
2379 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
2380 (zero_extend:SI | |
2381 (vec_select:<V_elem> | |
2382 (match_operand:VD 1 "s_register_operand" "w") | |
2383 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] | |
2384 "TARGET_NEON" | |
2385 { | |
2386 if (BYTES_BIG_ENDIAN) | |
2387 { | |
2388 int elt = INTVAL (operands[2]); | |
2389 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; | |
2390 operands[2] = GEN_INT (elt); | |
2391 } | |
2392 return "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]"; | |
2393 } | |
2394 [(set_attr "predicable" "yes") | |
2395 (set_attr "neon_type" "neon_bp_simple")] | |
2396 ) | |
2397 | |
2398 (define_insn "neon_vget_lane<mode>_sext_internal" | |
2399 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
2400 (sign_extend:SI | |
2401 (vec_select:<V_elem> | |
2402 (match_operand:VQ 1 "s_register_operand" "w") | |
2403 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] | |
2404 "TARGET_NEON" | |
2405 { | |
2406 rtx ops[3]; | |
2407 int regno = REGNO (operands[1]); | |
2408 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; | |
2409 unsigned int elt = INTVAL (operands[2]); | |
2410 unsigned int elt_adj = elt % halfelts; | |
2411 | |
2412 if (BYTES_BIG_ENDIAN) | |
2413 elt_adj = halfelts - 1 - elt_adj; | |
2414 | |
2415 ops[0] = operands[0]; | |
2416 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); | |
2417 ops[2] = GEN_INT (elt_adj); | |
2418 output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops); | |
2419 | |
2420 return ""; | |
2421 } | |
2422 [(set_attr "predicable" "yes") | |
2423 (set_attr "neon_type" "neon_bp_simple")] | |
2424 ) | |
2425 | |
2426 (define_insn "neon_vget_lane<mode>_zext_internal" | |
2427 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
2428 (zero_extend:SI | |
2429 (vec_select:<V_elem> | |
2430 (match_operand:VQ 1 "s_register_operand" "w") | |
2431 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] | |
2432 "TARGET_NEON" | |
2433 { | |
2434 rtx ops[3]; | |
2435 int regno = REGNO (operands[1]); | |
2436 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; | |
2437 unsigned int elt = INTVAL (operands[2]); | |
2438 unsigned int elt_adj = elt % halfelts; | |
2439 | |
2440 if (BYTES_BIG_ENDIAN) | |
2441 elt_adj = halfelts - 1 - elt_adj; | |
2442 | |
2443 ops[0] = operands[0]; | |
2444 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); | |
2445 ops[2] = GEN_INT (elt_adj); | |
2446 output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops); | |
2447 | |
2448 return ""; | |
2449 } | |
2450 [(set_attr "predicable" "yes") | |
2451 (set_attr "neon_type" "neon_bp_simple")] | |
2452 ) | |
2453 | |
2454 (define_expand "neon_vget_lane<mode>" | |
2455 [(match_operand:<V_ext> 0 "s_register_operand" "") | |
2456 (match_operand:VDQW 1 "s_register_operand" "") | |
2457 (match_operand:SI 2 "immediate_operand" "") | |
2458 (match_operand:SI 3 "immediate_operand" "")] | |
2459 "TARGET_NEON" | |
2460 { | |
2461 HOST_WIDE_INT magic = INTVAL (operands[3]); | |
2462 rtx insn; | |
2463 | |
2464 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2465 | |
2466 if (BYTES_BIG_ENDIAN) | |
2467 { | |
2468 /* The intrinsics are defined in terms of a model where the | |
2469 element ordering in memory is vldm order, whereas the generic | |
2470 RTL is defined in terms of a model where the element ordering | |
2471 in memory is array order. Convert the lane number to conform | |
2472 to this model. */ | |
2473 unsigned int elt = INTVAL (operands[2]); | |
2474 unsigned int reg_nelts | |
2475 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)); | |
2476 elt ^= reg_nelts - 1; | |
2477 operands[2] = GEN_INT (elt); | |
2478 } | |
2479 | |
2480 if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32) | |
2481 insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]); | |
2482 else | |
2483 { | |
2484 if ((magic & 1) != 0) | |
2485 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1], | |
2486 operands[2]); | |
2487 else | |
2488 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1], | |
2489 operands[2]); | |
2490 } | |
2491 emit_insn (insn); | |
2492 DONE; | |
2493 }) | |
2494 | |
2495 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit | |
2496 ; elements. | |
2497 | |
2498 (define_insn "neon_vget_lanedi" | |
2499 [(set (match_operand:DI 0 "s_register_operand" "=r") | |
2500 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") | |
2501 (match_operand:SI 2 "immediate_operand" "i") | |
2502 (match_operand:SI 3 "immediate_operand" "i")] | |
2503 UNSPEC_VGET_LANE))] | |
2504 "TARGET_NEON" | |
2505 { | |
2506 neon_lane_bounds (operands[2], 0, 1); | |
2507 return "vmov%?\t%Q0, %R0, %P1 @ di"; | |
2508 } | |
2509 [(set_attr "predicable" "yes") | |
2510 (set_attr "neon_type" "neon_bp_simple")] | |
2511 ) | |
2512 | |
2513 (define_insn "neon_vget_lanev2di" | |
2514 [(set (match_operand:DI 0 "s_register_operand" "=r") | |
2515 (unspec:DI [(match_operand:V2DI 1 "s_register_operand" "w") | |
2516 (match_operand:SI 2 "immediate_operand" "i") | |
2517 (match_operand:SI 3 "immediate_operand" "i")] | |
2518 UNSPEC_VGET_LANE))] | |
2519 "TARGET_NEON" | |
2520 { | |
2521 rtx ops[2]; | |
2522 unsigned int regno = REGNO (operands[1]); | |
2523 unsigned int elt = INTVAL (operands[2]); | |
2524 | |
2525 neon_lane_bounds (operands[2], 0, 2); | |
2526 | |
2527 ops[0] = operands[0]; | |
2528 ops[1] = gen_rtx_REG (DImode, regno + 2 * elt); | |
2529 output_asm_insn ("vmov%?\t%Q0, %R0, %P1 @ v2di", ops); | |
2530 | |
2531 return ""; | |
2532 } | |
2533 [(set_attr "predicable" "yes") | |
2534 (set_attr "neon_type" "neon_bp_simple")] | |
2535 ) | |
2536 | |
2537 (define_insn "neon_vset_lane<mode>" | |
2538 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
2539 (unspec:VD [(match_operand:<V_elem> 1 "s_register_operand" "r") | |
2540 (match_operand:VD 2 "s_register_operand" "0") | |
2541 (match_operand:SI 3 "immediate_operand" "i")] | |
2542 UNSPEC_VSET_LANE))] | |
2543 "TARGET_NEON" | |
2544 { | |
2545 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2546 return "vmov%?.<V_sz_elem>\t%P0[%c3], %1"; | |
2547 } | |
2548 [(set_attr "predicable" "yes") | |
2549 (set_attr "neon_type" "neon_bp_simple")] | |
2550 ) | |
2551 | |
2552 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored. | |
2553 | |
2554 (define_insn "neon_vset_lanedi" | |
2555 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
2556 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r") | |
2557 (match_operand:DI 2 "s_register_operand" "0") | |
2558 (match_operand:SI 3 "immediate_operand" "i")] | |
2559 UNSPEC_VSET_LANE))] | |
2560 "TARGET_NEON" | |
2561 { | |
2562 neon_lane_bounds (operands[3], 0, 1); | |
2563 return "vmov%?\t%P0, %Q1, %R1 @ di"; | |
2564 } | |
2565 [(set_attr "predicable" "yes") | |
2566 (set_attr "neon_type" "neon_bp_simple")] | |
2567 ) | |
2568 | |
2569 (define_insn "neon_vset_lane<mode>" | |
2570 [(set (match_operand:VQ 0 "s_register_operand" "=w") | |
2571 (unspec:VQ [(match_operand:<V_elem> 1 "s_register_operand" "r") | |
2572 (match_operand:VQ 2 "s_register_operand" "0") | |
2573 (match_operand:SI 3 "immediate_operand" "i")] | |
2574 UNSPEC_VSET_LANE))] | |
2575 "TARGET_NEON" | |
2576 { | |
2577 rtx ops[4]; | |
2578 unsigned int regno = REGNO (operands[0]); | |
2579 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; | |
2580 unsigned int elt = INTVAL (operands[3]); | |
2581 | |
2582 neon_lane_bounds (operands[3], 0, halfelts * 2); | |
2583 | |
2584 ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); | |
2585 ops[1] = operands[1]; | |
2586 ops[2] = GEN_INT (elt % halfelts); | |
2587 output_asm_insn ("vmov%?.<V_sz_elem>\t%P0[%c2], %1", ops); | |
2588 | |
2589 return ""; | |
2590 } | |
2591 [(set_attr "predicable" "yes") | |
2592 (set_attr "neon_type" "neon_bp_simple")] | |
2593 ) | |
2594 | |
2595 (define_insn "neon_vset_lanev2di" | |
2596 [(set (match_operand:V2DI 0 "s_register_operand" "=w") | |
2597 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r") | |
2598 (match_operand:V2DI 2 "s_register_operand" "0") | |
2599 (match_operand:SI 3 "immediate_operand" "i")] | |
2600 UNSPEC_VSET_LANE))] | |
2601 "TARGET_NEON" | |
2602 { | |
2603 rtx ops[2]; | |
2604 unsigned int regno = REGNO (operands[0]); | |
2605 unsigned int elt = INTVAL (operands[3]); | |
2606 | |
2607 neon_lane_bounds (operands[3], 0, 2); | |
2608 | |
2609 ops[0] = gen_rtx_REG (DImode, regno + 2 * elt); | |
2610 ops[1] = operands[1]; | |
2611 output_asm_insn ("vmov%?\t%P0, %Q1, %R1 @ v2di", ops); | |
2612 | |
2613 return ""; | |
2614 } | |
2615 [(set_attr "predicable" "yes") | |
2616 (set_attr "neon_type" "neon_bp_simple")] | |
2617 ) | |
2618 | |
2619 (define_expand "neon_vcreate<mode>" | |
2620 [(match_operand:VDX 0 "s_register_operand" "") | |
2621 (match_operand:DI 1 "general_operand" "")] | |
2622 "TARGET_NEON" | |
2623 { | |
2624 rtx src = gen_lowpart (<MODE>mode, operands[1]); | |
2625 emit_move_insn (operands[0], src); | |
2626 DONE; | |
2627 }) | |
2628 | |
2629 (define_insn "neon_vdup_n<mode>" | |
2630 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
2631 (unspec:VDQW [(match_operand:<V_elem> 1 "s_register_operand" "r")] | |
2632 UNSPEC_VDUP_N))] | |
2633 "TARGET_NEON" | |
2634 "vdup%?.<V_sz_elem>\t%<V_reg>0, %1" | |
2635 ;; Assume this schedules like vmov. | |
2636 [(set_attr "predicable" "yes") | |
2637 (set_attr "neon_type" "neon_bp_simple")] | |
2638 ) | |
2639 | |
2640 (define_insn "neon_vdup_ndi" | |
2641 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
2642 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")] | |
2643 UNSPEC_VDUP_N))] | |
2644 "TARGET_NEON" | |
2645 "vmov%?\t%P0, %Q1, %R1" | |
2646 [(set_attr "predicable" "yes") | |
2647 (set_attr "neon_type" "neon_bp_simple")] | |
2648 ) | |
2649 | |
2650 (define_insn "neon_vdup_nv2di" | |
2651 [(set (match_operand:V2DI 0 "s_register_operand" "=w") | |
2652 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")] | |
2653 UNSPEC_VDUP_N))] | |
2654 "TARGET_NEON" | |
2655 "vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1" | |
2656 [(set_attr "predicable" "yes") | |
2657 (set_attr "length" "8") | |
2658 (set_attr "neon_type" "neon_bp_simple")] | |
2659 ) | |
2660 | |
2661 (define_insn "neon_vdup_lane<mode>" | |
2662 [(set (match_operand:VD 0 "s_register_operand" "=w") | |
2663 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") | |
2664 (match_operand:SI 2 "immediate_operand" "i")] | |
2665 UNSPEC_VDUP_LANE))] | |
2666 "TARGET_NEON" | |
2667 { | |
2668 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2669 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]"; | |
2670 } | |
2671 ;; Assume this schedules like vmov. | |
2672 [(set_attr "neon_type" "neon_bp_simple")] | |
2673 ) | |
2674 | |
2675 (define_insn "neon_vdup_lane<mode>" | |
2676 [(set (match_operand:VQ 0 "s_register_operand" "=w") | |
2677 (unspec:VQ [(match_operand:<V_HALF> 1 "s_register_operand" "w") | |
2678 (match_operand:SI 2 "immediate_operand" "i")] | |
2679 UNSPEC_VDUP_LANE))] | |
2680 "TARGET_NEON" | |
2681 { | |
2682 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode)); | |
2683 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]"; | |
2684 } | |
2685 ;; Assume this schedules like vmov. | |
2686 [(set_attr "neon_type" "neon_bp_simple")] | |
2687 ) | |
2688 | |
2689 ; Scalar index is ignored, since only zero is valid here. | |
2690 (define_expand "neon_vdup_lanedi" | |
2691 [(set (match_operand:DI 0 "s_register_operand" "=w") | |
2692 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") | |
2693 (match_operand:SI 2 "immediate_operand" "i")] | |
2694 UNSPEC_VDUP_LANE))] | |
2695 "TARGET_NEON" | |
2696 { | |
2697 neon_lane_bounds (operands[2], 0, 1); | |
2698 emit_move_insn (operands[0], operands[1]); | |
2699 DONE; | |
2700 }) | |
2701 | |
2702 ; Likewise. | |
2703 (define_insn "neon_vdup_lanev2di" | |
2704 [(set (match_operand:V2DI 0 "s_register_operand" "=w") | |
2705 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "w") | |
2706 (match_operand:SI 2 "immediate_operand" "i")] | |
2707 UNSPEC_VDUP_LANE))] | |
2708 "TARGET_NEON" | |
2709 { | |
2710 neon_lane_bounds (operands[2], 0, 1); | |
2711 return "vmov\t%e0, %P1\;vmov\t%f0, %P1"; | |
2712 } | |
2713 [(set_attr "length" "8") | |
2714 (set_attr "neon_type" "neon_bp_simple")] | |
2715 ) | |
2716 | |
2717 ;; In this insn, operand 1 should be low, and operand 2 the high part of the | |
2718 ;; dest vector. | |
2719 ;; FIXME: A different implementation of this builtin could make it much | |
2720 ;; more likely that we wouldn't actually need to output anything (we could make | |
2721 ;; it so that the reg allocator puts things in the right places magically | |
2722 ;; instead). Lack of subregs for vectors makes that tricky though, I think. | |
2723 | |
2724 (define_insn "neon_vcombine<mode>" | |
2725 [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w") | |
2726 (unspec:<V_DOUBLE> [(match_operand:VDX 1 "s_register_operand" "w") | |
2727 (match_operand:VDX 2 "s_register_operand" "w")] | |
2728 UNSPEC_VCOMBINE))] | |
2729 "TARGET_NEON" | |
2730 { | |
2731 int dest = REGNO (operands[0]); | |
2732 int src1 = REGNO (operands[1]); | |
2733 int src2 = REGNO (operands[2]); | |
2734 rtx destlo; | |
2735 | |
2736 if (src1 == dest && src2 == dest + 2) | |
2737 return ""; | |
2738 else if (src2 == dest && src1 == dest + 2) | |
2739 /* Special case of reversed high/low parts. */ | |
2740 return "vswp\t%P1, %P2"; | |
2741 | |
2742 destlo = gen_rtx_REG (<MODE>mode, dest); | |
2743 | |
2744 if (!reg_overlap_mentioned_p (operands[2], destlo)) | |
2745 { | |
2746 /* Try to avoid unnecessary moves if part of the result is in the right | |
2747 place already. */ | |
2748 if (src1 != dest) | |
2749 output_asm_insn ("vmov\t%e0, %P1", operands); | |
2750 if (src2 != dest + 2) | |
2751 output_asm_insn ("vmov\t%f0, %P2", operands); | |
2752 } | |
2753 else | |
2754 { | |
2755 if (src2 != dest + 2) | |
2756 output_asm_insn ("vmov\t%f0, %P2", operands); | |
2757 if (src1 != dest) | |
2758 output_asm_insn ("vmov\t%e0, %P1", operands); | |
2759 } | |
2760 | |
2761 return ""; | |
2762 } | |
2763 ;; We set the neon_type attribute based on the vmov instructions above. | |
2764 [(set_attr "length" "8") | |
2765 (set_attr "neon_type" "neon_bp_simple")] | |
2766 ) | |
2767 | |
2768 (define_insn "neon_vget_high<mode>" | |
2769 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w") | |
2770 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")] | |
2771 UNSPEC_VGET_HIGH))] | |
2772 "TARGET_NEON" | |
2773 { | |
2774 int dest = REGNO (operands[0]); | |
2775 int src = REGNO (operands[1]); | |
2776 | |
2777 if (dest != src + 2) | |
2778 return "vmov\t%P0, %f1"; | |
2779 else | |
2780 return ""; | |
2781 } | |
2782 [(set_attr "neon_type" "neon_bp_simple")] | |
2783 ) | |
2784 | |
2785 (define_insn "neon_vget_low<mode>" | |
2786 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w") | |
2787 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")] | |
2788 UNSPEC_VGET_LOW))] | |
2789 "TARGET_NEON" | |
2790 { | |
2791 int dest = REGNO (operands[0]); | |
2792 int src = REGNO (operands[1]); | |
2793 | |
2794 if (dest != src) | |
2795 return "vmov\t%P0, %e1"; | |
2796 else | |
2797 return ""; | |
2798 } | |
2799 [(set_attr "neon_type" "neon_bp_simple")] | |
2800 ) | |
2801 | |
2802 (define_insn "neon_vcvt<mode>" | |
2803 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") | |
2804 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2805 (match_operand:SI 2 "immediate_operand" "i")] | |
2806 UNSPEC_VCVT))] | |
2807 "TARGET_NEON" | |
2808 "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1" | |
2809 [(set (attr "neon_type") | |
2810 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2811 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2812 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2813 ) | |
2814 | |
2815 (define_insn "neon_vcvt<mode>" | |
2816 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") | |
2817 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w") | |
2818 (match_operand:SI 2 "immediate_operand" "i")] | |
2819 UNSPEC_VCVT))] | |
2820 "TARGET_NEON" | |
2821 "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1" | |
2822 [(set (attr "neon_type") | |
2823 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2824 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2825 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2826 ) | |
2827 | |
2828 (define_insn "neon_vcvt_n<mode>" | |
2829 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") | |
2830 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w") | |
2831 (match_operand:SI 2 "immediate_operand" "i") | |
2832 (match_operand:SI 3 "immediate_operand" "i")] | |
2833 UNSPEC_VCVT_N))] | |
2834 "TARGET_NEON" | |
2835 { | |
2836 neon_const_bounds (operands[2], 1, 33); | |
2837 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2"; | |
2838 } | |
2839 [(set (attr "neon_type") | |
2840 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2841 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2842 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2843 ) | |
2844 | |
2845 (define_insn "neon_vcvt_n<mode>" | |
2846 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") | |
2847 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w") | |
2848 (match_operand:SI 2 "immediate_operand" "i") | |
2849 (match_operand:SI 3 "immediate_operand" "i")] | |
2850 UNSPEC_VCVT_N))] | |
2851 "TARGET_NEON" | |
2852 { | |
2853 neon_const_bounds (operands[2], 1, 33); | |
2854 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2"; | |
2855 } | |
2856 [(set (attr "neon_type") | |
2857 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
2858 (const_string "neon_fp_vadd_ddd_vabs_dd") | |
2859 (const_string "neon_fp_vadd_qqq_vabs_qq")))] | |
2860 ) | |
2861 | |
2862 (define_insn "neon_vmovn<mode>" | |
2863 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
2864 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
2865 (match_operand:SI 2 "immediate_operand" "i")] | |
2866 UNSPEC_VMOVN))] | |
2867 "TARGET_NEON" | |
2868 "vmovn.<V_if_elem>\t%P0, %q1" | |
2869 [(set_attr "neon_type" "neon_bp_simple")] | |
2870 ) | |
2871 | |
2872 (define_insn "neon_vqmovn<mode>" | |
2873 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
2874 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
2875 (match_operand:SI 2 "immediate_operand" "i")] | |
2876 UNSPEC_VQMOVN))] | |
2877 "TARGET_NEON" | |
2878 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1" | |
2879 [(set_attr "neon_type" "neon_shift_2")] | |
2880 ) | |
2881 | |
2882 (define_insn "neon_vqmovun<mode>" | |
2883 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
2884 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
2885 (match_operand:SI 2 "immediate_operand" "i")] | |
2886 UNSPEC_VQMOVUN))] | |
2887 "TARGET_NEON" | |
2888 "vqmovun.<V_s_elem>\t%P0, %q1" | |
2889 [(set_attr "neon_type" "neon_shift_2")] | |
2890 ) | |
2891 | |
2892 (define_insn "neon_vmovl<mode>" | |
2893 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
2894 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") | |
2895 (match_operand:SI 2 "immediate_operand" "i")] | |
2896 UNSPEC_VMOVL))] | |
2897 "TARGET_NEON" | |
2898 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1" | |
2899 [(set_attr "neon_type" "neon_shift_1")] | |
2900 ) | |
2901 | |
2902 (define_insn "neon_vmul_lane<mode>" | |
2903 [(set (match_operand:VMD 0 "s_register_operand" "=w") | |
2904 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w") | |
2905 (match_operand:VMD 2 "s_register_operand" | |
2906 "<scalar_mul_constraint>") | |
2907 (match_operand:SI 3 "immediate_operand" "i") | |
2908 (match_operand:SI 4 "immediate_operand" "i")] | |
2909 UNSPEC_VMUL_LANE))] | |
2910 "TARGET_NEON" | |
2911 { | |
2912 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2913 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]"; | |
2914 } | |
2915 [(set (attr "neon_type") | |
2916 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2917 (const_string "neon_fp_vmul_ddd") | |
2918 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
2919 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") | |
2920 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))] | |
2921 ) | |
2922 | |
2923 (define_insn "neon_vmul_lane<mode>" | |
2924 [(set (match_operand:VMQ 0 "s_register_operand" "=w") | |
2925 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w") | |
2926 (match_operand:<V_HALF> 2 "s_register_operand" | |
2927 "<scalar_mul_constraint>") | |
2928 (match_operand:SI 3 "immediate_operand" "i") | |
2929 (match_operand:SI 4 "immediate_operand" "i")] | |
2930 UNSPEC_VMUL_LANE))] | |
2931 "TARGET_NEON" | |
2932 { | |
2933 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode)); | |
2934 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]"; | |
2935 } | |
2936 [(set (attr "neon_type") | |
2937 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
2938 (const_string "neon_fp_vmul_qqd") | |
2939 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
2940 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar") | |
2941 (const_string "neon_mul_qqd_32_scalar"))))] | |
2942 ) | |
2943 | |
2944 (define_insn "neon_vmull_lane<mode>" | |
2945 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
2946 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") | |
2947 (match_operand:VMDI 2 "s_register_operand" | |
2948 "<scalar_mul_constraint>") | |
2949 (match_operand:SI 3 "immediate_operand" "i") | |
2950 (match_operand:SI 4 "immediate_operand" "i")] | |
2951 UNSPEC_VMULL_LANE))] | |
2952 "TARGET_NEON" | |
2953 { | |
2954 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2955 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]"; | |
2956 } | |
2957 [(set (attr "neon_type") | |
2958 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
2959 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") | |
2960 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] | |
2961 ) | |
2962 | |
2963 (define_insn "neon_vqdmull_lane<mode>" | |
2964 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
2965 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") | |
2966 (match_operand:VMDI 2 "s_register_operand" | |
2967 "<scalar_mul_constraint>") | |
2968 (match_operand:SI 3 "immediate_operand" "i") | |
2969 (match_operand:SI 4 "immediate_operand" "i")] | |
2970 UNSPEC_VQDMULL_LANE))] | |
2971 "TARGET_NEON" | |
2972 { | |
2973 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2974 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]"; | |
2975 } | |
2976 [(set (attr "neon_type") | |
2977 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
2978 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") | |
2979 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] | |
2980 ) | |
2981 | |
2982 (define_insn "neon_vqdmulh_lane<mode>" | |
2983 [(set (match_operand:VMQI 0 "s_register_operand" "=w") | |
2984 (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w") | |
2985 (match_operand:<V_HALF> 2 "s_register_operand" | |
2986 "<scalar_mul_constraint>") | |
2987 (match_operand:SI 3 "immediate_operand" "i") | |
2988 (match_operand:SI 4 "immediate_operand" "i")] | |
2989 UNSPEC_VQDMULH_LANE))] | |
2990 "TARGET_NEON" | |
2991 { | |
2992 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
2993 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]"; | |
2994 } | |
2995 [(set (attr "neon_type") | |
2996 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
2997 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar") | |
2998 (const_string "neon_mul_qqd_32_scalar")))] | |
2999 ) | |
3000 | |
3001 (define_insn "neon_vqdmulh_lane<mode>" | |
3002 [(set (match_operand:VMDI 0 "s_register_operand" "=w") | |
3003 (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w") | |
3004 (match_operand:VMDI 2 "s_register_operand" | |
3005 "<scalar_mul_constraint>") | |
3006 (match_operand:SI 3 "immediate_operand" "i") | |
3007 (match_operand:SI 4 "immediate_operand" "i")] | |
3008 UNSPEC_VQDMULH_LANE))] | |
3009 "TARGET_NEON" | |
3010 { | |
3011 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3012 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]"; | |
3013 } | |
3014 [(set (attr "neon_type") | |
3015 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3016 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") | |
3017 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] | |
3018 ) | |
3019 | |
3020 (define_insn "neon_vmla_lane<mode>" | |
3021 [(set (match_operand:VMD 0 "s_register_operand" "=w") | |
3022 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0") | |
3023 (match_operand:VMD 2 "s_register_operand" "w") | |
3024 (match_operand:VMD 3 "s_register_operand" | |
3025 "<scalar_mul_constraint>") | |
3026 (match_operand:SI 4 "immediate_operand" "i") | |
3027 (match_operand:SI 5 "immediate_operand" "i")] | |
3028 UNSPEC_VMLA_LANE))] | |
3029 "TARGET_NEON" | |
3030 { | |
3031 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3032 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]"; | |
3033 } | |
3034 [(set (attr "neon_type") | |
3035 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
3036 (const_string "neon_fp_vmla_ddd_scalar") | |
3037 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3038 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3039 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))] | |
3040 ) | |
3041 | |
3042 (define_insn "neon_vmla_lane<mode>" | |
3043 [(set (match_operand:VMQ 0 "s_register_operand" "=w") | |
3044 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0") | |
3045 (match_operand:VMQ 2 "s_register_operand" "w") | |
3046 (match_operand:<V_HALF> 3 "s_register_operand" | |
3047 "<scalar_mul_constraint>") | |
3048 (match_operand:SI 4 "immediate_operand" "i") | |
3049 (match_operand:SI 5 "immediate_operand" "i")] | |
3050 UNSPEC_VMLA_LANE))] | |
3051 "TARGET_NEON" | |
3052 { | |
3053 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3054 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]"; | |
3055 } | |
3056 [(set (attr "neon_type") | |
3057 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
3058 (const_string "neon_fp_vmla_qqq_scalar") | |
3059 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3060 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long") | |
3061 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))] | |
3062 ) | |
3063 | |
3064 (define_insn "neon_vmlal_lane<mode>" | |
3065 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
3066 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
3067 (match_operand:VMDI 2 "s_register_operand" "w") | |
3068 (match_operand:VMDI 3 "s_register_operand" | |
3069 "<scalar_mul_constraint>") | |
3070 (match_operand:SI 4 "immediate_operand" "i") | |
3071 (match_operand:SI 5 "immediate_operand" "i")] | |
3072 UNSPEC_VMLAL_LANE))] | |
3073 "TARGET_NEON" | |
3074 { | |
3075 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3076 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"; | |
3077 } | |
3078 [(set (attr "neon_type") | |
3079 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3080 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3081 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
3082 ) | |
3083 | |
3084 (define_insn "neon_vqdmlal_lane<mode>" | |
3085 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
3086 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
3087 (match_operand:VMDI 2 "s_register_operand" "w") | |
3088 (match_operand:VMDI 3 "s_register_operand" | |
3089 "<scalar_mul_constraint>") | |
3090 (match_operand:SI 4 "immediate_operand" "i") | |
3091 (match_operand:SI 5 "immediate_operand" "i")] | |
3092 UNSPEC_VQDMLAL_LANE))] | |
3093 "TARGET_NEON" | |
3094 { | |
3095 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3096 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]"; | |
3097 } | |
3098 [(set (attr "neon_type") | |
3099 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3100 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3101 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
3102 ) | |
3103 | |
3104 (define_insn "neon_vmls_lane<mode>" | |
3105 [(set (match_operand:VMD 0 "s_register_operand" "=w") | |
3106 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0") | |
3107 (match_operand:VMD 2 "s_register_operand" "w") | |
3108 (match_operand:VMD 3 "s_register_operand" | |
3109 "<scalar_mul_constraint>") | |
3110 (match_operand:SI 4 "immediate_operand" "i") | |
3111 (match_operand:SI 5 "immediate_operand" "i")] | |
3112 UNSPEC_VMLS_LANE))] | |
3113 "TARGET_NEON" | |
3114 { | |
3115 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3116 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]"; | |
3117 } | |
3118 [(set (attr "neon_type") | |
3119 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
3120 (const_string "neon_fp_vmla_ddd_scalar") | |
3121 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3122 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3123 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))] | |
3124 ) | |
3125 | |
3126 (define_insn "neon_vmls_lane<mode>" | |
3127 [(set (match_operand:VMQ 0 "s_register_operand" "=w") | |
3128 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0") | |
3129 (match_operand:VMQ 2 "s_register_operand" "w") | |
3130 (match_operand:<V_HALF> 3 "s_register_operand" | |
3131 "<scalar_mul_constraint>") | |
3132 (match_operand:SI 4 "immediate_operand" "i") | |
3133 (match_operand:SI 5 "immediate_operand" "i")] | |
3134 UNSPEC_VMLS_LANE))] | |
3135 "TARGET_NEON" | |
3136 { | |
3137 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3138 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]"; | |
3139 } | |
3140 [(set (attr "neon_type") | |
3141 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) | |
3142 (const_string "neon_fp_vmla_qqq_scalar") | |
3143 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3144 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long") | |
3145 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))] | |
3146 ) | |
3147 | |
3148 (define_insn "neon_vmlsl_lane<mode>" | |
3149 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
3150 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
3151 (match_operand:VMDI 2 "s_register_operand" "w") | |
3152 (match_operand:VMDI 3 "s_register_operand" | |
3153 "<scalar_mul_constraint>") | |
3154 (match_operand:SI 4 "immediate_operand" "i") | |
3155 (match_operand:SI 5 "immediate_operand" "i")] | |
3156 UNSPEC_VMLSL_LANE))] | |
3157 "TARGET_NEON" | |
3158 { | |
3159 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3160 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"; | |
3161 } | |
3162 [(set (attr "neon_type") | |
3163 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3164 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3165 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
3166 ) | |
3167 | |
3168 (define_insn "neon_vqdmlsl_lane<mode>" | |
3169 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
3170 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") | |
3171 (match_operand:VMDI 2 "s_register_operand" "w") | |
3172 (match_operand:VMDI 3 "s_register_operand" | |
3173 "<scalar_mul_constraint>") | |
3174 (match_operand:SI 4 "immediate_operand" "i") | |
3175 (match_operand:SI 5 "immediate_operand" "i")] | |
3176 UNSPEC_VQDMLSL_LANE))] | |
3177 "TARGET_NEON" | |
3178 { | |
3179 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3180 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]"; | |
3181 } | |
3182 [(set (attr "neon_type") | |
3183 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) | |
3184 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") | |
3185 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] | |
3186 ) | |
3187 | |
3188 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a | |
3189 ; core register into a temp register, then use a scalar taken from that. This | |
3190 ; isn't an optimal solution if e.g. the scalar has just been read from memory | |
3191 ; or extracted from another vector. The latter case it's currently better to | |
3192 ; use the "_lane" variant, and the former case can probably be implemented | |
3193 ; using vld1_lane, but that hasn't been done yet. | |
3194 | |
3195 (define_expand "neon_vmul_n<mode>" | |
3196 [(match_operand:VMD 0 "s_register_operand" "") | |
3197 (match_operand:VMD 1 "s_register_operand" "") | |
3198 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3199 (match_operand:SI 3 "immediate_operand" "")] | |
3200 "TARGET_NEON" | |
3201 { | |
3202 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3203 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); | |
3204 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp, | |
3205 const0_rtx, const0_rtx)); | |
3206 DONE; | |
3207 }) | |
3208 | |
3209 (define_expand "neon_vmul_n<mode>" | |
3210 [(match_operand:VMQ 0 "s_register_operand" "") | |
3211 (match_operand:VMQ 1 "s_register_operand" "") | |
3212 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3213 (match_operand:SI 3 "immediate_operand" "")] | |
3214 "TARGET_NEON" | |
3215 { | |
3216 rtx tmp = gen_reg_rtx (<V_HALF>mode); | |
3217 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx)); | |
3218 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp, | |
3219 const0_rtx, const0_rtx)); | |
3220 DONE; | |
3221 }) | |
3222 | |
3223 (define_expand "neon_vmull_n<mode>" | |
3224 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3225 (match_operand:VMDI 1 "s_register_operand" "") | |
3226 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3227 (match_operand:SI 3 "immediate_operand" "")] | |
3228 "TARGET_NEON" | |
3229 { | |
3230 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3231 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); | |
3232 emit_insn (gen_neon_vmull_lane<mode> (operands[0], operands[1], tmp, | |
3233 const0_rtx, operands[3])); | |
3234 DONE; | |
3235 }) | |
3236 | |
3237 (define_expand "neon_vqdmull_n<mode>" | |
3238 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3239 (match_operand:VMDI 1 "s_register_operand" "") | |
3240 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3241 (match_operand:SI 3 "immediate_operand" "")] | |
3242 "TARGET_NEON" | |
3243 { | |
3244 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3245 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); | |
3246 emit_insn (gen_neon_vqdmull_lane<mode> (operands[0], operands[1], tmp, | |
3247 const0_rtx, const0_rtx)); | |
3248 DONE; | |
3249 }) | |
3250 | |
3251 (define_expand "neon_vqdmulh_n<mode>" | |
3252 [(match_operand:VMDI 0 "s_register_operand" "") | |
3253 (match_operand:VMDI 1 "s_register_operand" "") | |
3254 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3255 (match_operand:SI 3 "immediate_operand" "")] | |
3256 "TARGET_NEON" | |
3257 { | |
3258 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3259 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); | |
3260 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp, | |
3261 const0_rtx, operands[3])); | |
3262 DONE; | |
3263 }) | |
3264 | |
3265 (define_expand "neon_vqdmulh_n<mode>" | |
3266 [(match_operand:VMQI 0 "s_register_operand" "") | |
3267 (match_operand:VMQI 1 "s_register_operand" "") | |
3268 (match_operand:<V_elem> 2 "s_register_operand" "") | |
3269 (match_operand:SI 3 "immediate_operand" "")] | |
3270 "TARGET_NEON" | |
3271 { | |
3272 rtx tmp = gen_reg_rtx (<V_HALF>mode); | |
3273 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx)); | |
3274 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp, | |
3275 const0_rtx, operands[3])); | |
3276 DONE; | |
3277 }) | |
3278 | |
3279 (define_expand "neon_vmla_n<mode>" | |
3280 [(match_operand:VMD 0 "s_register_operand" "") | |
3281 (match_operand:VMD 1 "s_register_operand" "") | |
3282 (match_operand:VMD 2 "s_register_operand" "") | |
3283 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3284 (match_operand:SI 4 "immediate_operand" "")] | |
3285 "TARGET_NEON" | |
3286 { | |
3287 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3288 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3289 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2], | |
3290 tmp, const0_rtx, operands[4])); | |
3291 DONE; | |
3292 }) | |
3293 | |
3294 (define_expand "neon_vmla_n<mode>" | |
3295 [(match_operand:VMQ 0 "s_register_operand" "") | |
3296 (match_operand:VMQ 1 "s_register_operand" "") | |
3297 (match_operand:VMQ 2 "s_register_operand" "") | |
3298 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3299 (match_operand:SI 4 "immediate_operand" "")] | |
3300 "TARGET_NEON" | |
3301 { | |
3302 rtx tmp = gen_reg_rtx (<V_HALF>mode); | |
3303 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx)); | |
3304 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2], | |
3305 tmp, const0_rtx, operands[4])); | |
3306 DONE; | |
3307 }) | |
3308 | |
3309 (define_expand "neon_vmlal_n<mode>" | |
3310 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3311 (match_operand:<V_widen> 1 "s_register_operand" "") | |
3312 (match_operand:VMDI 2 "s_register_operand" "") | |
3313 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3314 (match_operand:SI 4 "immediate_operand" "")] | |
3315 "TARGET_NEON" | |
3316 { | |
3317 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3318 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3319 emit_insn (gen_neon_vmlal_lane<mode> (operands[0], operands[1], operands[2], | |
3320 tmp, const0_rtx, operands[4])); | |
3321 DONE; | |
3322 }) | |
3323 | |
3324 (define_expand "neon_vqdmlal_n<mode>" | |
3325 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3326 (match_operand:<V_widen> 1 "s_register_operand" "") | |
3327 (match_operand:VMDI 2 "s_register_operand" "") | |
3328 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3329 (match_operand:SI 4 "immediate_operand" "")] | |
3330 "TARGET_NEON" | |
3331 { | |
3332 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3333 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3334 emit_insn (gen_neon_vqdmlal_lane<mode> (operands[0], operands[1], operands[2], | |
3335 tmp, const0_rtx, operands[4])); | |
3336 DONE; | |
3337 }) | |
3338 | |
3339 (define_expand "neon_vmls_n<mode>" | |
3340 [(match_operand:VMD 0 "s_register_operand" "") | |
3341 (match_operand:VMD 1 "s_register_operand" "") | |
3342 (match_operand:VMD 2 "s_register_operand" "") | |
3343 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3344 (match_operand:SI 4 "immediate_operand" "")] | |
3345 "TARGET_NEON" | |
3346 { | |
3347 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3348 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3349 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2], | |
3350 tmp, const0_rtx, operands[4])); | |
3351 DONE; | |
3352 }) | |
3353 | |
3354 (define_expand "neon_vmls_n<mode>" | |
3355 [(match_operand:VMQ 0 "s_register_operand" "") | |
3356 (match_operand:VMQ 1 "s_register_operand" "") | |
3357 (match_operand:VMQ 2 "s_register_operand" "") | |
3358 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3359 (match_operand:SI 4 "immediate_operand" "")] | |
3360 "TARGET_NEON" | |
3361 { | |
3362 rtx tmp = gen_reg_rtx (<V_HALF>mode); | |
3363 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx)); | |
3364 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2], | |
3365 tmp, const0_rtx, operands[4])); | |
3366 DONE; | |
3367 }) | |
3368 | |
3369 (define_expand "neon_vmlsl_n<mode>" | |
3370 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3371 (match_operand:<V_widen> 1 "s_register_operand" "") | |
3372 (match_operand:VMDI 2 "s_register_operand" "") | |
3373 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3374 (match_operand:SI 4 "immediate_operand" "")] | |
3375 "TARGET_NEON" | |
3376 { | |
3377 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3378 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3379 emit_insn (gen_neon_vmlsl_lane<mode> (operands[0], operands[1], operands[2], | |
3380 tmp, const0_rtx, operands[4])); | |
3381 DONE; | |
3382 }) | |
3383 | |
3384 (define_expand "neon_vqdmlsl_n<mode>" | |
3385 [(match_operand:<V_widen> 0 "s_register_operand" "") | |
3386 (match_operand:<V_widen> 1 "s_register_operand" "") | |
3387 (match_operand:VMDI 2 "s_register_operand" "") | |
3388 (match_operand:<V_elem> 3 "s_register_operand" "") | |
3389 (match_operand:SI 4 "immediate_operand" "")] | |
3390 "TARGET_NEON" | |
3391 { | |
3392 rtx tmp = gen_reg_rtx (<MODE>mode); | |
3393 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); | |
3394 emit_insn (gen_neon_vqdmlsl_lane<mode> (operands[0], operands[1], operands[2], | |
3395 tmp, const0_rtx, operands[4])); | |
3396 DONE; | |
3397 }) | |
3398 | |
3399 (define_insn "neon_vext<mode>" | |
3400 [(set (match_operand:VDQX 0 "s_register_operand" "=w") | |
3401 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") | |
3402 (match_operand:VDQX 2 "s_register_operand" "w") | |
3403 (match_operand:SI 3 "immediate_operand" "i")] | |
3404 UNSPEC_VEXT))] | |
3405 "TARGET_NEON" | |
3406 { | |
3407 neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); | |
3408 return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3"; | |
3409 } | |
3410 [(set (attr "neon_type") | |
3411 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3412 (const_string "neon_bp_simple") | |
3413 (const_string "neon_bp_2cycle")))] | |
3414 ) | |
3415 | |
3416 (define_insn "neon_vrev64<mode>" | |
3417 [(set (match_operand:VDQ 0 "s_register_operand" "=w") | |
3418 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w") | |
3419 (match_operand:SI 2 "immediate_operand" "i")] | |
3420 UNSPEC_VREV64))] | |
3421 "TARGET_NEON" | |
3422 "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" | |
3423 [(set_attr "neon_type" "neon_bp_simple")] | |
3424 ) | |
3425 | |
3426 (define_insn "neon_vrev32<mode>" | |
3427 [(set (match_operand:VX 0 "s_register_operand" "=w") | |
3428 (unspec:VX [(match_operand:VX 1 "s_register_operand" "w") | |
3429 (match_operand:SI 2 "immediate_operand" "i")] | |
3430 UNSPEC_VREV32))] | |
3431 "TARGET_NEON" | |
3432 "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" | |
3433 [(set_attr "neon_type" "neon_bp_simple")] | |
3434 ) | |
3435 | |
3436 (define_insn "neon_vrev16<mode>" | |
3437 [(set (match_operand:VE 0 "s_register_operand" "=w") | |
3438 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w") | |
3439 (match_operand:SI 2 "immediate_operand" "i")] | |
3440 UNSPEC_VREV16))] | |
3441 "TARGET_NEON" | |
3442 "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" | |
3443 [(set_attr "neon_type" "neon_bp_simple")] | |
3444 ) | |
3445 | |
3446 ; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register | |
3447 ; allocation. For an intrinsic of form: | |
3448 ; rD = vbsl_* (rS, rN, rM) | |
3449 ; We can use any of: | |
3450 ; vbsl rS, rN, rM (if D = S) | |
3451 ; vbit rD, rN, rS (if D = M, so 1-bits in rS choose bits from rN, else rM) | |
3452 ; vbif rD, rM, rS (if D = N, so 0-bits in rS choose bits from rM, else rN) | |
3453 | |
3454 (define_insn "neon_vbsl<mode>_internal" | |
3455 [(set (match_operand:VDQX 0 "s_register_operand" "=w,w,w") | |
3456 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w") | |
3457 (match_operand:VDQX 2 "s_register_operand" " w,w,0") | |
3458 (match_operand:VDQX 3 "s_register_operand" " w,0,w")] | |
3459 UNSPEC_VBSL))] | |
3460 "TARGET_NEON" | |
3461 "@ | |
3462 vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3 | |
3463 vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1 | |
3464 vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1" | |
3465 [(set_attr "neon_type" "neon_int_1")] | |
3466 ) | |
3467 | |
3468 (define_expand "neon_vbsl<mode>" | |
3469 [(set (match_operand:VDQX 0 "s_register_operand" "") | |
3470 (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "") | |
3471 (match_operand:VDQX 2 "s_register_operand" "") | |
3472 (match_operand:VDQX 3 "s_register_operand" "")] | |
3473 UNSPEC_VBSL))] | |
3474 "TARGET_NEON" | |
3475 { | |
3476 /* We can't alias operands together if they have different modes. */ | |
3477 operands[1] = gen_lowpart (<MODE>mode, operands[1]); | |
3478 }) | |
3479 | |
3480 (define_insn "neon_vshl<mode>" | |
3481 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3482 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3483 (match_operand:VDQIX 2 "s_register_operand" "w") | |
3484 (match_operand:SI 3 "immediate_operand" "i")] | |
3485 UNSPEC_VSHL))] | |
3486 "TARGET_NEON" | |
3487 "v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
3488 [(set (attr "neon_type") | |
3489 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3490 (const_string "neon_vshl_ddd") | |
3491 (const_string "neon_shift_3")))] | |
3492 ) | |
3493 | |
3494 (define_insn "neon_vqshl<mode>" | |
3495 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3496 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3497 (match_operand:VDQIX 2 "s_register_operand" "w") | |
3498 (match_operand:SI 3 "immediate_operand" "i")] | |
3499 UNSPEC_VQSHL))] | |
3500 "TARGET_NEON" | |
3501 "vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
3502 [(set (attr "neon_type") | |
3503 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3504 (const_string "neon_shift_2") | |
3505 (const_string "neon_vqshl_vrshl_vqrshl_qqq")))] | |
3506 ) | |
3507 | |
3508 (define_insn "neon_vshr_n<mode>" | |
3509 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3510 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3511 (match_operand:SI 2 "immediate_operand" "i") | |
3512 (match_operand:SI 3 "immediate_operand" "i")] | |
3513 UNSPEC_VSHR_N))] | |
3514 "TARGET_NEON" | |
3515 { | |
3516 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1); | |
3517 return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; | |
3518 } | |
3519 [(set_attr "neon_type" "neon_shift_1")] | |
3520 ) | |
3521 | |
3522 (define_insn "neon_vshrn_n<mode>" | |
3523 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
3524 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
3525 (match_operand:SI 2 "immediate_operand" "i") | |
3526 (match_operand:SI 3 "immediate_operand" "i")] | |
3527 UNSPEC_VSHRN_N))] | |
3528 "TARGET_NEON" | |
3529 { | |
3530 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); | |
3531 return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2"; | |
3532 } | |
3533 [(set_attr "neon_type" "neon_shift_1")] | |
3534 ) | |
3535 | |
3536 (define_insn "neon_vqshrn_n<mode>" | |
3537 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
3538 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
3539 (match_operand:SI 2 "immediate_operand" "i") | |
3540 (match_operand:SI 3 "immediate_operand" "i")] | |
3541 UNSPEC_VQSHRN_N))] | |
3542 "TARGET_NEON" | |
3543 { | |
3544 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); | |
3545 return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2"; | |
3546 } | |
3547 [(set_attr "neon_type" "neon_shift_2")] | |
3548 ) | |
3549 | |
3550 (define_insn "neon_vqshrun_n<mode>" | |
3551 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") | |
3552 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") | |
3553 (match_operand:SI 2 "immediate_operand" "i") | |
3554 (match_operand:SI 3 "immediate_operand" "i")] | |
3555 UNSPEC_VQSHRUN_N))] | |
3556 "TARGET_NEON" | |
3557 { | |
3558 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); | |
3559 return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2"; | |
3560 } | |
3561 [(set_attr "neon_type" "neon_shift_2")] | |
3562 ) | |
3563 | |
3564 (define_insn "neon_vshl_n<mode>" | |
3565 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3566 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3567 (match_operand:SI 2 "immediate_operand" "i") | |
3568 (match_operand:SI 3 "immediate_operand" "i")] | |
3569 UNSPEC_VSHL_N))] | |
3570 "TARGET_NEON" | |
3571 { | |
3572 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); | |
3573 return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2"; | |
3574 } | |
3575 [(set_attr "neon_type" "neon_shift_1")] | |
3576 ) | |
3577 | |
3578 (define_insn "neon_vqshl_n<mode>" | |
3579 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3580 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3581 (match_operand:SI 2 "immediate_operand" "i") | |
3582 (match_operand:SI 3 "immediate_operand" "i")] | |
3583 UNSPEC_VQSHL_N))] | |
3584 "TARGET_NEON" | |
3585 { | |
3586 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); | |
3587 return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; | |
3588 } | |
3589 [(set_attr "neon_type" "neon_shift_2")] | |
3590 ) | |
3591 | |
3592 (define_insn "neon_vqshlu_n<mode>" | |
3593 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3594 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") | |
3595 (match_operand:SI 2 "immediate_operand" "i") | |
3596 (match_operand:SI 3 "immediate_operand" "i")] | |
3597 UNSPEC_VQSHLU_N))] | |
3598 "TARGET_NEON" | |
3599 { | |
3600 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); | |
3601 return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; | |
3602 } | |
3603 [(set_attr "neon_type" "neon_shift_2")] | |
3604 ) | |
3605 | |
3606 (define_insn "neon_vshll_n<mode>" | |
3607 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") | |
3608 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") | |
3609 (match_operand:SI 2 "immediate_operand" "i") | |
3610 (match_operand:SI 3 "immediate_operand" "i")] | |
3611 UNSPEC_VSHLL_N))] | |
3612 "TARGET_NEON" | |
3613 { | |
3614 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); | |
3615 return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2"; | |
3616 } | |
3617 [(set_attr "neon_type" "neon_shift_1")] | |
3618 ) | |
3619 | |
3620 (define_insn "neon_vsra_n<mode>" | |
3621 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3622 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") | |
3623 (match_operand:VDQIX 2 "s_register_operand" "w") | |
3624 (match_operand:SI 3 "immediate_operand" "i") | |
3625 (match_operand:SI 4 "immediate_operand" "i")] | |
3626 UNSPEC_VSRA_N))] | |
3627 "TARGET_NEON" | |
3628 { | |
3629 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1); | |
3630 return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; | |
3631 } | |
3632 [(set_attr "neon_type" "neon_vsra_vrsra")] | |
3633 ) | |
3634 | |
3635 (define_insn "neon_vsri_n<mode>" | |
3636 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3637 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") | |
3638 (match_operand:VDQIX 2 "s_register_operand" "w") | |
3639 (match_operand:SI 3 "immediate_operand" "i")] | |
3640 UNSPEC_VSRI))] | |
3641 "TARGET_NEON" | |
3642 { | |
3643 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1); | |
3644 return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; | |
3645 } | |
3646 [(set (attr "neon_type") | |
3647 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3648 (const_string "neon_shift_1") | |
3649 (const_string "neon_shift_3")))] | |
3650 ) | |
3651 | |
3652 (define_insn "neon_vsli_n<mode>" | |
3653 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") | |
3654 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") | |
3655 (match_operand:VDQIX 2 "s_register_operand" "w") | |
3656 (match_operand:SI 3 "immediate_operand" "i")] | |
3657 UNSPEC_VSLI))] | |
3658 "TARGET_NEON" | |
3659 { | |
3660 neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode)); | |
3661 return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; | |
3662 } | |
3663 [(set (attr "neon_type") | |
3664 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3665 (const_string "neon_shift_1") | |
3666 (const_string "neon_shift_3")))] | |
3667 ) | |
3668 | |
3669 (define_insn "neon_vtbl1v8qi" | |
3670 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3671 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w") | |
3672 (match_operand:V8QI 2 "s_register_operand" "w")] | |
3673 UNSPEC_VTBL))] | |
3674 "TARGET_NEON" | |
3675 "vtbl.8\t%P0, {%P1}, %P2" | |
3676 [(set_attr "neon_type" "neon_bp_2cycle")] | |
3677 ) | |
3678 | |
3679 (define_insn "neon_vtbl2v8qi" | |
3680 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3681 (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w") | |
3682 (match_operand:V8QI 2 "s_register_operand" "w")] | |
3683 UNSPEC_VTBL))] | |
3684 "TARGET_NEON" | |
3685 { | |
3686 rtx ops[4]; | |
3687 int tabbase = REGNO (operands[1]); | |
3688 | |
3689 ops[0] = operands[0]; | |
3690 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3691 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3692 ops[3] = operands[2]; | |
3693 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops); | |
3694 | |
3695 return ""; | |
3696 } | |
3697 [(set_attr "neon_type" "neon_bp_2cycle")] | |
3698 ) | |
3699 | |
3700 (define_insn "neon_vtbl3v8qi" | |
3701 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3702 (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w") | |
3703 (match_operand:V8QI 2 "s_register_operand" "w")] | |
3704 UNSPEC_VTBL))] | |
3705 "TARGET_NEON" | |
3706 { | |
3707 rtx ops[5]; | |
3708 int tabbase = REGNO (operands[1]); | |
3709 | |
3710 ops[0] = operands[0]; | |
3711 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3712 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3713 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); | |
3714 ops[4] = operands[2]; | |
3715 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops); | |
3716 | |
3717 return ""; | |
3718 } | |
3719 [(set_attr "neon_type" "neon_bp_3cycle")] | |
3720 ) | |
3721 | |
3722 (define_insn "neon_vtbl4v8qi" | |
3723 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3724 (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w") | |
3725 (match_operand:V8QI 2 "s_register_operand" "w")] | |
3726 UNSPEC_VTBL))] | |
3727 "TARGET_NEON" | |
3728 { | |
3729 rtx ops[6]; | |
3730 int tabbase = REGNO (operands[1]); | |
3731 | |
3732 ops[0] = operands[0]; | |
3733 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3734 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3735 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); | |
3736 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6); | |
3737 ops[5] = operands[2]; | |
3738 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops); | |
3739 | |
3740 return ""; | |
3741 } | |
3742 [(set_attr "neon_type" "neon_bp_3cycle")] | |
3743 ) | |
3744 | |
3745 (define_insn "neon_vtbx1v8qi" | |
3746 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3747 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") | |
3748 (match_operand:V8QI 2 "s_register_operand" "w") | |
3749 (match_operand:V8QI 3 "s_register_operand" "w")] | |
3750 UNSPEC_VTBX))] | |
3751 "TARGET_NEON" | |
3752 "vtbx.8\t%P0, {%P2}, %P3" | |
3753 [(set_attr "neon_type" "neon_bp_2cycle")] | |
3754 ) | |
3755 | |
3756 (define_insn "neon_vtbx2v8qi" | |
3757 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3758 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") | |
3759 (match_operand:TI 2 "s_register_operand" "w") | |
3760 (match_operand:V8QI 3 "s_register_operand" "w")] | |
3761 UNSPEC_VTBX))] | |
3762 "TARGET_NEON" | |
3763 { | |
3764 rtx ops[4]; | |
3765 int tabbase = REGNO (operands[2]); | |
3766 | |
3767 ops[0] = operands[0]; | |
3768 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3769 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3770 ops[3] = operands[3]; | |
3771 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops); | |
3772 | |
3773 return ""; | |
3774 } | |
3775 [(set_attr "neon_type" "neon_bp_2cycle")] | |
3776 ) | |
3777 | |
3778 (define_insn "neon_vtbx3v8qi" | |
3779 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3780 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") | |
3781 (match_operand:EI 2 "s_register_operand" "w") | |
3782 (match_operand:V8QI 3 "s_register_operand" "w")] | |
3783 UNSPEC_VTBX))] | |
3784 "TARGET_NEON" | |
3785 { | |
3786 rtx ops[5]; | |
3787 int tabbase = REGNO (operands[2]); | |
3788 | |
3789 ops[0] = operands[0]; | |
3790 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3791 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3792 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); | |
3793 ops[4] = operands[3]; | |
3794 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops); | |
3795 | |
3796 return ""; | |
3797 } | |
3798 [(set_attr "neon_type" "neon_bp_3cycle")] | |
3799 ) | |
3800 | |
3801 (define_insn "neon_vtbx4v8qi" | |
3802 [(set (match_operand:V8QI 0 "s_register_operand" "=w") | |
3803 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") | |
3804 (match_operand:OI 2 "s_register_operand" "w") | |
3805 (match_operand:V8QI 3 "s_register_operand" "w")] | |
3806 UNSPEC_VTBX))] | |
3807 "TARGET_NEON" | |
3808 { | |
3809 rtx ops[6]; | |
3810 int tabbase = REGNO (operands[2]); | |
3811 | |
3812 ops[0] = operands[0]; | |
3813 ops[1] = gen_rtx_REG (V8QImode, tabbase); | |
3814 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); | |
3815 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); | |
3816 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6); | |
3817 ops[5] = operands[3]; | |
3818 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops); | |
3819 | |
3820 return ""; | |
3821 } | |
3822 [(set_attr "neon_type" "neon_bp_3cycle")] | |
3823 ) | |
3824 | |
3825 (define_insn "neon_vtrn<mode>_internal" | |
3826 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
3827 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")] | |
3828 UNSPEC_VTRN1)) | |
3829 (set (match_operand:VDQW 2 "s_register_operand" "=w") | |
3830 (unspec:VDQW [(match_operand:VDQW 3 "s_register_operand" "2")] | |
3831 UNSPEC_VTRN2))] | |
3832 "TARGET_NEON" | |
3833 "vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>2" | |
3834 [(set (attr "neon_type") | |
3835 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3836 (const_string "neon_bp_simple") | |
3837 (const_string "neon_bp_3cycle")))] | |
3838 ) | |
3839 | |
3840 (define_expand "neon_vtrn<mode>" | |
3841 [(match_operand:SI 0 "s_register_operand" "r") | |
3842 (match_operand:VDQW 1 "s_register_operand" "w") | |
3843 (match_operand:VDQW 2 "s_register_operand" "w")] | |
3844 "TARGET_NEON" | |
3845 { | |
3846 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal, | |
3847 operands[0], operands[1], operands[2]); | |
3848 DONE; | |
3849 }) | |
3850 | |
3851 (define_insn "neon_vzip<mode>_internal" | |
3852 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
3853 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")] | |
3854 UNSPEC_VZIP1)) | |
3855 (set (match_operand:VDQW 2 "s_register_operand" "=w") | |
3856 (unspec:VDQW [(match_operand:VDQW 3 "s_register_operand" "2")] | |
3857 UNSPEC_VZIP2))] | |
3858 "TARGET_NEON" | |
3859 "vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>2" | |
3860 [(set (attr "neon_type") | |
3861 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3862 (const_string "neon_bp_simple") | |
3863 (const_string "neon_bp_3cycle")))] | |
3864 ) | |
3865 | |
3866 (define_expand "neon_vzip<mode>" | |
3867 [(match_operand:SI 0 "s_register_operand" "r") | |
3868 (match_operand:VDQW 1 "s_register_operand" "w") | |
3869 (match_operand:VDQW 2 "s_register_operand" "w")] | |
3870 "TARGET_NEON" | |
3871 { | |
3872 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal, | |
3873 operands[0], operands[1], operands[2]); | |
3874 DONE; | |
3875 }) | |
3876 | |
3877 (define_insn "neon_vuzp<mode>_internal" | |
3878 [(set (match_operand:VDQW 0 "s_register_operand" "=w") | |
3879 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")] | |
3880 UNSPEC_VUZP1)) | |
3881 (set (match_operand:VDQW 2 "s_register_operand" "=w") | |
3882 (unspec:VDQW [(match_operand:VDQW 3 "s_register_operand" "2")] | |
3883 UNSPEC_VUZP2))] | |
3884 "TARGET_NEON" | |
3885 "vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>2" | |
3886 [(set (attr "neon_type") | |
3887 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) | |
3888 (const_string "neon_bp_simple") | |
3889 (const_string "neon_bp_3cycle")))] | |
3890 ) | |
3891 | |
3892 (define_expand "neon_vuzp<mode>" | |
3893 [(match_operand:SI 0 "s_register_operand" "r") | |
3894 (match_operand:VDQW 1 "s_register_operand" "w") | |
3895 (match_operand:VDQW 2 "s_register_operand" "w")] | |
3896 "TARGET_NEON" | |
3897 { | |
3898 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal, | |
3899 operands[0], operands[1], operands[2]); | |
3900 DONE; | |
3901 }) | |
3902 | |
3903 (define_expand "neon_vreinterpretv8qi<mode>" | |
3904 [(match_operand:V8QI 0 "s_register_operand" "") | |
3905 (match_operand:VDX 1 "s_register_operand" "")] | |
3906 "TARGET_NEON" | |
3907 { | |
3908 neon_reinterpret (operands[0], operands[1]); | |
3909 DONE; | |
3910 }) | |
3911 | |
3912 (define_expand "neon_vreinterpretv4hi<mode>" | |
3913 [(match_operand:V4HI 0 "s_register_operand" "") | |
3914 (match_operand:VDX 1 "s_register_operand" "")] | |
3915 "TARGET_NEON" | |
3916 { | |
3917 neon_reinterpret (operands[0], operands[1]); | |
3918 DONE; | |
3919 }) | |
3920 | |
3921 (define_expand "neon_vreinterpretv2si<mode>" | |
3922 [(match_operand:V2SI 0 "s_register_operand" "") | |
3923 (match_operand:VDX 1 "s_register_operand" "")] | |
3924 "TARGET_NEON" | |
3925 { | |
3926 neon_reinterpret (operands[0], operands[1]); | |
3927 DONE; | |
3928 }) | |
3929 | |
3930 (define_expand "neon_vreinterpretv2sf<mode>" | |
3931 [(match_operand:V2SF 0 "s_register_operand" "") | |
3932 (match_operand:VDX 1 "s_register_operand" "")] | |
3933 "TARGET_NEON" | |
3934 { | |
3935 neon_reinterpret (operands[0], operands[1]); | |
3936 DONE; | |
3937 }) | |
3938 | |
3939 (define_expand "neon_vreinterpretdi<mode>" | |
3940 [(match_operand:DI 0 "s_register_operand" "") | |
3941 (match_operand:VDX 1 "s_register_operand" "")] | |
3942 "TARGET_NEON" | |
3943 { | |
3944 neon_reinterpret (operands[0], operands[1]); | |
3945 DONE; | |
3946 }) | |
3947 | |
3948 (define_expand "neon_vreinterpretv16qi<mode>" | |
3949 [(match_operand:V16QI 0 "s_register_operand" "") | |
3950 (match_operand:VQX 1 "s_register_operand" "")] | |
3951 "TARGET_NEON" | |
3952 { | |
3953 neon_reinterpret (operands[0], operands[1]); | |
3954 DONE; | |
3955 }) | |
3956 | |
3957 (define_expand "neon_vreinterpretv8hi<mode>" | |
3958 [(match_operand:V8HI 0 "s_register_operand" "") | |
3959 (match_operand:VQX 1 "s_register_operand" "")] | |
3960 "TARGET_NEON" | |
3961 { | |
3962 neon_reinterpret (operands[0], operands[1]); | |
3963 DONE; | |
3964 }) | |
3965 | |
3966 (define_expand "neon_vreinterpretv4si<mode>" | |
3967 [(match_operand:V4SI 0 "s_register_operand" "") | |
3968 (match_operand:VQX 1 "s_register_operand" "")] | |
3969 "TARGET_NEON" | |
3970 { | |
3971 neon_reinterpret (operands[0], operands[1]); | |
3972 DONE; | |
3973 }) | |
3974 | |
3975 (define_expand "neon_vreinterpretv4sf<mode>" | |
3976 [(match_operand:V4SF 0 "s_register_operand" "") | |
3977 (match_operand:VQX 1 "s_register_operand" "")] | |
3978 "TARGET_NEON" | |
3979 { | |
3980 neon_reinterpret (operands[0], operands[1]); | |
3981 DONE; | |
3982 }) | |
3983 | |
3984 (define_expand "neon_vreinterpretv2di<mode>" | |
3985 [(match_operand:V2DI 0 "s_register_operand" "") | |
3986 (match_operand:VQX 1 "s_register_operand" "")] | |
3987 "TARGET_NEON" | |
3988 { | |
3989 neon_reinterpret (operands[0], operands[1]); | |
3990 DONE; | |
3991 }) | |
3992 | |
3993 (define_insn "neon_vld1<mode>" | |
3994 [(set (match_operand:VDQX 0 "s_register_operand" "=w") | |
3995 (unspec:VDQX [(mem:VDQX (match_operand:SI 1 "s_register_operand" "r"))] | |
3996 UNSPEC_VLD1))] | |
3997 "TARGET_NEON" | |
3998 "vld1.<V_sz_elem>\t%h0, [%1]" | |
3999 [(set_attr "neon_type" "neon_vld1_1_2_regs")] | |
4000 ) | |
4001 | |
4002 (define_insn "neon_vld1_lane<mode>" | |
4003 [(set (match_operand:VDX 0 "s_register_operand" "=w") | |
4004 (unspec:VDX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4005 (match_operand:VDX 2 "s_register_operand" "0") | |
4006 (match_operand:SI 3 "immediate_operand" "i")] | |
4007 UNSPEC_VLD1_LANE))] | |
4008 "TARGET_NEON" | |
4009 { | |
4010 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4011 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4012 if (lane < 0 || lane >= max) | |
4013 error ("lane out of range"); | |
4014 if (max == 1) | |
4015 return "vld1.<V_sz_elem>\t%P0, [%1]"; | |
4016 else | |
4017 return "vld1.<V_sz_elem>\t{%P0[%c3]}, [%1]"; | |
4018 } | |
4019 [(set (attr "neon_type") | |
4020 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2)) | |
4021 (const_string "neon_vld1_1_2_regs") | |
4022 (const_string "neon_vld1_vld2_lane")))] | |
4023 ) | |
4024 | |
4025 (define_insn "neon_vld1_lane<mode>" | |
4026 [(set (match_operand:VQX 0 "s_register_operand" "=w") | |
4027 (unspec:VQX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4028 (match_operand:VQX 2 "s_register_operand" "0") | |
4029 (match_operand:SI 3 "immediate_operand" "i")] | |
4030 UNSPEC_VLD1_LANE))] | |
4031 "TARGET_NEON" | |
4032 { | |
4033 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4034 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4035 int regno = REGNO (operands[0]); | |
4036 if (lane < 0 || lane >= max) | |
4037 error ("lane out of range"); | |
4038 else if (lane >= max / 2) | |
4039 { | |
4040 lane -= max / 2; | |
4041 regno += 2; | |
4042 operands[3] = GEN_INT (lane); | |
4043 } | |
4044 operands[0] = gen_rtx_REG (<V_HALF>mode, regno); | |
4045 if (max == 2) | |
4046 return "vld1.<V_sz_elem>\t%P0, [%1]"; | |
4047 else | |
4048 return "vld1.<V_sz_elem>\t{%P0[%c3]}, [%1]"; | |
4049 } | |
4050 [(set (attr "neon_type") | |
4051 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2)) | |
4052 (const_string "neon_vld1_1_2_regs") | |
4053 (const_string "neon_vld1_vld2_lane")))] | |
4054 ) | |
4055 | |
4056 (define_insn "neon_vld1_dup<mode>" | |
4057 [(set (match_operand:VDX 0 "s_register_operand" "=w") | |
4058 (unspec:VDX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r"))] | |
4059 UNSPEC_VLD1_DUP))] | |
4060 "TARGET_NEON" | |
4061 { | |
4062 if (GET_MODE_NUNITS (<MODE>mode) > 1) | |
4063 return "vld1.<V_sz_elem>\t{%P0[]}, [%1]"; | |
4064 else | |
4065 return "vld1.<V_sz_elem>\t%h0, [%1]"; | |
4066 } | |
4067 [(set (attr "neon_type") | |
4068 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) | |
4069 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") | |
4070 (const_string "neon_vld1_1_2_regs")))] | |
4071 ) | |
4072 | |
4073 (define_insn "neon_vld1_dup<mode>" | |
4074 [(set (match_operand:VQX 0 "s_register_operand" "=w") | |
4075 (unspec:VQX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r"))] | |
4076 UNSPEC_VLD1_DUP))] | |
4077 "TARGET_NEON" | |
4078 { | |
4079 if (GET_MODE_NUNITS (<MODE>mode) > 2) | |
4080 return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, [%1]"; | |
4081 else | |
4082 return "vld1.<V_sz_elem>\t%h0, [%1]"; | |
4083 } | |
4084 [(set (attr "neon_type") | |
4085 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) | |
4086 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") | |
4087 (const_string "neon_vld1_1_2_regs")))] | |
4088 ) | |
4089 | |
4090 (define_insn "neon_vst1<mode>" | |
4091 [(set (mem:VDQX (match_operand:SI 0 "s_register_operand" "r")) | |
4092 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")] | |
4093 UNSPEC_VST1))] | |
4094 "TARGET_NEON" | |
4095 "vst1.<V_sz_elem>\t%h1, [%0]" | |
4096 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) | |
4097 | |
4098 (define_insn "neon_vst1_lane<mode>" | |
4099 [(set (mem:<V_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4100 (vec_select:<V_elem> | |
4101 (match_operand:VDX 1 "s_register_operand" "w") | |
4102 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))] | |
4103 "TARGET_NEON" | |
4104 { | |
4105 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4106 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4107 if (lane < 0 || lane >= max) | |
4108 error ("lane out of range"); | |
4109 if (max == 1) | |
4110 return "vst1.<V_sz_elem>\t{%P1}, [%0]"; | |
4111 else | |
4112 return "vst1.<V_sz_elem>\t{%P1[%c2]}, [%0]"; | |
4113 } | |
4114 [(set (attr "neon_type") | |
4115 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1)) | |
4116 (const_string "neon_vst1_1_2_regs_vst2_2_regs") | |
4117 (const_string "neon_vst1_vst2_lane")))]) | |
4118 | |
4119 (define_insn "neon_vst1_lane<mode>" | |
4120 [(set (mem:<V_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4121 (vec_select:<V_elem> | |
4122 (match_operand:VQX 1 "s_register_operand" "w") | |
4123 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))] | |
4124 "TARGET_NEON" | |
4125 { | |
4126 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4127 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4128 int regno = REGNO (operands[1]); | |
4129 if (lane < 0 || lane >= max) | |
4130 error ("lane out of range"); | |
4131 else if (lane >= max / 2) | |
4132 { | |
4133 lane -= max / 2; | |
4134 regno += 2; | |
4135 operands[2] = GEN_INT (lane); | |
4136 } | |
4137 operands[1] = gen_rtx_REG (<V_HALF>mode, regno); | |
4138 if (max == 2) | |
4139 return "vst1.<V_sz_elem>\t{%P1}, [%0]"; | |
4140 else | |
4141 return "vst1.<V_sz_elem>\t{%P1[%c2]}, [%0]"; | |
4142 } | |
4143 [(set_attr "neon_type" "neon_vst1_vst2_lane")] | |
4144 ) | |
4145 | |
4146 (define_insn "neon_vld2<mode>" | |
4147 [(set (match_operand:TI 0 "s_register_operand" "=w") | |
4148 (unspec:TI [(mem:TI (match_operand:SI 1 "s_register_operand" "r")) | |
4149 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4150 UNSPEC_VLD2))] | |
4151 "TARGET_NEON" | |
4152 { | |
4153 if (<V_sz_elem> == 64) | |
4154 return "vld1.64\t%h0, [%1]"; | |
4155 else | |
4156 return "vld2.<V_sz_elem>\t%h0, [%1]"; | |
4157 } | |
4158 [(set (attr "neon_type") | |
4159 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4160 (const_string "neon_vld1_1_2_regs") | |
4161 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))] | |
4162 ) | |
4163 | |
4164 (define_insn "neon_vld2<mode>" | |
4165 [(set (match_operand:OI 0 "s_register_operand" "=w") | |
4166 (unspec:OI [(mem:OI (match_operand:SI 1 "s_register_operand" "r")) | |
4167 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4168 UNSPEC_VLD2))] | |
4169 "TARGET_NEON" | |
4170 "vld2.<V_sz_elem>\t%h0, [%1]" | |
4171 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]) | |
4172 | |
4173 (define_insn "neon_vld2_lane<mode>" | |
4174 [(set (match_operand:TI 0 "s_register_operand" "=w") | |
4175 (unspec:TI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4176 (match_operand:TI 2 "s_register_operand" "0") | |
4177 (match_operand:SI 3 "immediate_operand" "i") | |
4178 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4179 UNSPEC_VLD2_LANE))] | |
4180 "TARGET_NEON" | |
4181 { | |
4182 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4183 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4184 int regno = REGNO (operands[0]); | |
4185 rtx ops[4]; | |
4186 if (lane < 0 || lane >= max) | |
4187 error ("lane out of range"); | |
4188 ops[0] = gen_rtx_REG (DImode, regno); | |
4189 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4190 ops[2] = operands[1]; | |
4191 ops[3] = operands[3]; | |
4192 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, [%2]", ops); | |
4193 return ""; | |
4194 } | |
4195 [(set_attr "neon_type" "neon_vld1_vld2_lane")] | |
4196 ) | |
4197 | |
4198 (define_insn "neon_vld2_lane<mode>" | |
4199 [(set (match_operand:OI 0 "s_register_operand" "=w") | |
4200 (unspec:OI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4201 (match_operand:OI 2 "s_register_operand" "0") | |
4202 (match_operand:SI 3 "immediate_operand" "i") | |
4203 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4204 UNSPEC_VLD2_LANE))] | |
4205 "TARGET_NEON" | |
4206 { | |
4207 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4208 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4209 int regno = REGNO (operands[0]); | |
4210 rtx ops[4]; | |
4211 if (lane < 0 || lane >= max) | |
4212 error ("lane out of range"); | |
4213 else if (lane >= max / 2) | |
4214 { | |
4215 lane -= max / 2; | |
4216 regno += 2; | |
4217 } | |
4218 ops[0] = gen_rtx_REG (DImode, regno); | |
4219 ops[1] = gen_rtx_REG (DImode, regno + 4); | |
4220 ops[2] = operands[1]; | |
4221 ops[3] = GEN_INT (lane); | |
4222 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, [%2]", ops); | |
4223 return ""; | |
4224 } | |
4225 [(set_attr "neon_type" "neon_vld1_vld2_lane")] | |
4226 ) | |
4227 | |
4228 (define_insn "neon_vld2_dup<mode>" | |
4229 [(set (match_operand:TI 0 "s_register_operand" "=w") | |
4230 (unspec:TI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4231 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4232 UNSPEC_VLD2_DUP))] | |
4233 "TARGET_NEON" | |
4234 { | |
4235 if (GET_MODE_NUNITS (<MODE>mode) > 1) | |
4236 return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, [%1]"; | |
4237 else | |
4238 return "vld1.<V_sz_elem>\t%h0, [%1]"; | |
4239 } | |
4240 [(set (attr "neon_type") | |
4241 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) | |
4242 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") | |
4243 (const_string "neon_vld1_1_2_regs")))] | |
4244 ) | |
4245 | |
4246 (define_insn "neon_vst2<mode>" | |
4247 [(set (mem:TI (match_operand:SI 0 "s_register_operand" "r")) | |
4248 (unspec:TI [(match_operand:TI 1 "s_register_operand" "w") | |
4249 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4250 UNSPEC_VST2))] | |
4251 "TARGET_NEON" | |
4252 { | |
4253 if (<V_sz_elem> == 64) | |
4254 return "vst1.64\t%h1, [%0]"; | |
4255 else | |
4256 return "vst2.<V_sz_elem>\t%h1, [%0]"; | |
4257 } | |
4258 [(set (attr "neon_type") | |
4259 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4260 (const_string "neon_vst1_1_2_regs_vst2_2_regs") | |
4261 (const_string "neon_vst1_1_2_regs_vst2_2_regs")))] | |
4262 ) | |
4263 | |
4264 (define_insn "neon_vst2<mode>" | |
4265 [(set (mem:OI (match_operand:SI 0 "s_register_operand" "r")) | |
4266 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") | |
4267 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4268 UNSPEC_VST2))] | |
4269 "TARGET_NEON" | |
4270 "vst2.<V_sz_elem>\t%h1, [%0]" | |
4271 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")] | |
4272 ) | |
4273 | |
4274 (define_insn "neon_vst2_lane<mode>" | |
4275 [(set (mem:<V_two_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4276 (unspec:<V_two_elem> | |
4277 [(match_operand:TI 1 "s_register_operand" "w") | |
4278 (match_operand:SI 2 "immediate_operand" "i") | |
4279 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4280 UNSPEC_VST2_LANE))] | |
4281 "TARGET_NEON" | |
4282 { | |
4283 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4284 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4285 int regno = REGNO (operands[1]); | |
4286 rtx ops[4]; | |
4287 if (lane < 0 || lane >= max) | |
4288 error ("lane out of range"); | |
4289 ops[0] = operands[0]; | |
4290 ops[1] = gen_rtx_REG (DImode, regno); | |
4291 ops[2] = gen_rtx_REG (DImode, regno + 2); | |
4292 ops[3] = operands[2]; | |
4293 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, [%0]", ops); | |
4294 return ""; | |
4295 } | |
4296 [(set_attr "neon_type" "neon_vst1_vst2_lane")] | |
4297 ) | |
4298 | |
4299 (define_insn "neon_vst2_lane<mode>" | |
4300 [(set (mem:<V_two_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4301 (unspec:<V_two_elem> | |
4302 [(match_operand:OI 1 "s_register_operand" "w") | |
4303 (match_operand:SI 2 "immediate_operand" "i") | |
4304 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4305 UNSPEC_VST2_LANE))] | |
4306 "TARGET_NEON" | |
4307 { | |
4308 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4309 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4310 int regno = REGNO (operands[1]); | |
4311 rtx ops[4]; | |
4312 if (lane < 0 || lane >= max) | |
4313 error ("lane out of range"); | |
4314 else if (lane >= max / 2) | |
4315 { | |
4316 lane -= max / 2; | |
4317 regno += 2; | |
4318 } | |
4319 ops[0] = operands[0]; | |
4320 ops[1] = gen_rtx_REG (DImode, regno); | |
4321 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4322 ops[3] = GEN_INT (lane); | |
4323 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, [%0]", ops); | |
4324 return ""; | |
4325 } | |
4326 [(set_attr "neon_type" "neon_vst1_vst2_lane")] | |
4327 ) | |
4328 | |
4329 (define_insn "neon_vld3<mode>" | |
4330 [(set (match_operand:EI 0 "s_register_operand" "=w") | |
4331 (unspec:EI [(mem:EI (match_operand:SI 1 "s_register_operand" "r")) | |
4332 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4333 UNSPEC_VLD3))] | |
4334 "TARGET_NEON" | |
4335 { | |
4336 if (<V_sz_elem> == 64) | |
4337 return "vld1.64\t%h0, [%1]"; | |
4338 else | |
4339 return "vld3.<V_sz_elem>\t%h0, [%1]"; | |
4340 } | |
4341 [(set (attr "neon_type") | |
4342 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4343 (const_string "neon_vld1_1_2_regs") | |
4344 (const_string "neon_vld3_vld4")))] | |
4345 ) | |
4346 | |
4347 (define_expand "neon_vld3<mode>" | |
4348 [(match_operand:CI 0 "s_register_operand" "=w") | |
4349 (match_operand:SI 1 "s_register_operand" "+r") | |
4350 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4351 "TARGET_NEON" | |
4352 { | |
4353 emit_insn (gen_neon_vld3qa<mode> (operands[0], operands[0], | |
4354 operands[1], operands[1])); | |
4355 emit_insn (gen_neon_vld3qb<mode> (operands[0], operands[0], | |
4356 operands[1], operands[1])); | |
4357 DONE; | |
4358 }) | |
4359 | |
4360 (define_insn "neon_vld3qa<mode>" | |
4361 [(set (match_operand:CI 0 "s_register_operand" "=w") | |
4362 (unspec:CI [(mem:CI (match_operand:SI 3 "s_register_operand" "2")) | |
4363 (match_operand:CI 1 "s_register_operand" "0") | |
4364 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4365 UNSPEC_VLD3A)) | |
4366 (set (match_operand:SI 2 "s_register_operand" "=r") | |
4367 (plus:SI (match_dup 3) | |
4368 (const_int 24)))] | |
4369 "TARGET_NEON" | |
4370 { | |
4371 int regno = REGNO (operands[0]); | |
4372 rtx ops[4]; | |
4373 ops[0] = gen_rtx_REG (DImode, regno); | |
4374 ops[1] = gen_rtx_REG (DImode, regno + 4); | |
4375 ops[2] = gen_rtx_REG (DImode, regno + 8); | |
4376 ops[3] = operands[2]; | |
4377 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, [%3]!", ops); | |
4378 return ""; | |
4379 } | |
4380 [(set_attr "neon_type" "neon_vld3_vld4")] | |
4381 ) | |
4382 | |
4383 (define_insn "neon_vld3qb<mode>" | |
4384 [(set (match_operand:CI 0 "s_register_operand" "=w") | |
4385 (unspec:CI [(mem:CI (match_operand:SI 3 "s_register_operand" "2")) | |
4386 (match_operand:CI 1 "s_register_operand" "0") | |
4387 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4388 UNSPEC_VLD3B)) | |
4389 (set (match_operand:SI 2 "s_register_operand" "=r") | |
4390 (plus:SI (match_dup 3) | |
4391 (const_int 24)))] | |
4392 "TARGET_NEON" | |
4393 { | |
4394 int regno = REGNO (operands[0]); | |
4395 rtx ops[4]; | |
4396 ops[0] = gen_rtx_REG (DImode, regno + 2); | |
4397 ops[1] = gen_rtx_REG (DImode, regno + 6); | |
4398 ops[2] = gen_rtx_REG (DImode, regno + 10); | |
4399 ops[3] = operands[2]; | |
4400 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, [%3]!", ops); | |
4401 return ""; | |
4402 } | |
4403 [(set_attr "neon_type" "neon_vld3_vld4")] | |
4404 ) | |
4405 | |
4406 (define_insn "neon_vld3_lane<mode>" | |
4407 [(set (match_operand:EI 0 "s_register_operand" "=w") | |
4408 (unspec:EI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4409 (match_operand:EI 2 "s_register_operand" "0") | |
4410 (match_operand:SI 3 "immediate_operand" "i") | |
4411 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4412 UNSPEC_VLD3_LANE))] | |
4413 "TARGET_NEON" | |
4414 { | |
4415 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4416 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4417 int regno = REGNO (operands[0]); | |
4418 rtx ops[5]; | |
4419 if (lane < 0 || lane >= max) | |
4420 error ("lane out of range"); | |
4421 ops[0] = gen_rtx_REG (DImode, regno); | |
4422 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4423 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4424 ops[3] = operands[1]; | |
4425 ops[4] = operands[3]; | |
4426 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, [%3]", | |
4427 ops); | |
4428 return ""; | |
4429 } | |
4430 [(set_attr "neon_type" "neon_vld3_vld4_lane")] | |
4431 ) | |
4432 | |
4433 (define_insn "neon_vld3_lane<mode>" | |
4434 [(set (match_operand:CI 0 "s_register_operand" "=w") | |
4435 (unspec:CI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4436 (match_operand:CI 2 "s_register_operand" "0") | |
4437 (match_operand:SI 3 "immediate_operand" "i") | |
4438 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4439 UNSPEC_VLD3_LANE))] | |
4440 "TARGET_NEON" | |
4441 { | |
4442 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4443 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4444 int regno = REGNO (operands[0]); | |
4445 rtx ops[5]; | |
4446 if (lane < 0 || lane >= max) | |
4447 error ("lane out of range"); | |
4448 else if (lane >= max / 2) | |
4449 { | |
4450 lane -= max / 2; | |
4451 regno += 2; | |
4452 } | |
4453 ops[0] = gen_rtx_REG (DImode, regno); | |
4454 ops[1] = gen_rtx_REG (DImode, regno + 4); | |
4455 ops[2] = gen_rtx_REG (DImode, regno + 8); | |
4456 ops[3] = operands[1]; | |
4457 ops[4] = GEN_INT (lane); | |
4458 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, [%3]", | |
4459 ops); | |
4460 return ""; | |
4461 } | |
4462 [(set_attr "neon_type" "neon_vld3_vld4_lane")] | |
4463 ) | |
4464 | |
4465 (define_insn "neon_vld3_dup<mode>" | |
4466 [(set (match_operand:EI 0 "s_register_operand" "=w") | |
4467 (unspec:EI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4468 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4469 UNSPEC_VLD3_DUP))] | |
4470 "TARGET_NEON" | |
4471 { | |
4472 if (GET_MODE_NUNITS (<MODE>mode) > 1) | |
4473 { | |
4474 int regno = REGNO (operands[0]); | |
4475 rtx ops[4]; | |
4476 ops[0] = gen_rtx_REG (DImode, regno); | |
4477 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4478 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4479 ops[3] = operands[1]; | |
4480 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[], %P1[], %P2[]}, [%3]", ops); | |
4481 return ""; | |
4482 } | |
4483 else | |
4484 return "vld1.<V_sz_elem>\t%h0, [%1]"; | |
4485 } | |
4486 [(set (attr "neon_type") | |
4487 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) | |
4488 (const_string "neon_vld3_vld4_all_lanes") | |
4489 (const_string "neon_vld1_1_2_regs")))]) | |
4490 | |
4491 (define_insn "neon_vst3<mode>" | |
4492 [(set (mem:EI (match_operand:SI 0 "s_register_operand" "r")) | |
4493 (unspec:EI [(match_operand:EI 1 "s_register_operand" "w") | |
4494 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4495 UNSPEC_VST3))] | |
4496 "TARGET_NEON" | |
4497 { | |
4498 if (<V_sz_elem> == 64) | |
4499 return "vst1.64\t%h1, [%0]"; | |
4500 else | |
4501 return "vst3.<V_sz_elem>\t%h1, [%0]"; | |
4502 } | |
4503 [(set (attr "neon_type") | |
4504 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4505 (const_string "neon_vst1_1_2_regs_vst2_2_regs") | |
4506 (const_string "neon_vst2_4_regs_vst3_vst4")))]) | |
4507 | |
4508 (define_expand "neon_vst3<mode>" | |
4509 [(match_operand:SI 0 "s_register_operand" "+r") | |
4510 (match_operand:CI 1 "s_register_operand" "w") | |
4511 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4512 "TARGET_NEON" | |
4513 { | |
4514 emit_insn (gen_neon_vst3qa<mode> (operands[0], operands[0], operands[1])); | |
4515 emit_insn (gen_neon_vst3qb<mode> (operands[0], operands[0], operands[1])); | |
4516 DONE; | |
4517 }) | |
4518 | |
4519 (define_insn "neon_vst3qa<mode>" | |
4520 [(set (mem:EI (match_operand:SI 1 "s_register_operand" "0")) | |
4521 (unspec:EI [(match_operand:CI 2 "s_register_operand" "w") | |
4522 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4523 UNSPEC_VST3A)) | |
4524 (set (match_operand:SI 0 "s_register_operand" "=r") | |
4525 (plus:SI (match_dup 1) | |
4526 (const_int 24)))] | |
4527 "TARGET_NEON" | |
4528 { | |
4529 int regno = REGNO (operands[2]); | |
4530 rtx ops[4]; | |
4531 ops[0] = operands[0]; | |
4532 ops[1] = gen_rtx_REG (DImode, regno); | |
4533 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4534 ops[3] = gen_rtx_REG (DImode, regno + 8); | |
4535 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, [%0]!", ops); | |
4536 return ""; | |
4537 } | |
4538 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] | |
4539 ) | |
4540 | |
4541 (define_insn "neon_vst3qb<mode>" | |
4542 [(set (mem:EI (match_operand:SI 1 "s_register_operand" "0")) | |
4543 (unspec:EI [(match_operand:CI 2 "s_register_operand" "w") | |
4544 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4545 UNSPEC_VST3B)) | |
4546 (set (match_operand:SI 0 "s_register_operand" "=r") | |
4547 (plus:SI (match_dup 1) | |
4548 (const_int 24)))] | |
4549 "TARGET_NEON" | |
4550 { | |
4551 int regno = REGNO (operands[2]); | |
4552 rtx ops[4]; | |
4553 ops[0] = operands[0]; | |
4554 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4555 ops[2] = gen_rtx_REG (DImode, regno + 6); | |
4556 ops[3] = gen_rtx_REG (DImode, regno + 10); | |
4557 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, [%0]!", ops); | |
4558 return ""; | |
4559 } | |
4560 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] | |
4561 ) | |
4562 | |
4563 (define_insn "neon_vst3_lane<mode>" | |
4564 [(set (mem:<V_three_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4565 (unspec:<V_three_elem> | |
4566 [(match_operand:EI 1 "s_register_operand" "w") | |
4567 (match_operand:SI 2 "immediate_operand" "i") | |
4568 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4569 UNSPEC_VST3_LANE))] | |
4570 "TARGET_NEON" | |
4571 { | |
4572 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4573 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4574 int regno = REGNO (operands[1]); | |
4575 rtx ops[5]; | |
4576 if (lane < 0 || lane >= max) | |
4577 error ("lane out of range"); | |
4578 ops[0] = operands[0]; | |
4579 ops[1] = gen_rtx_REG (DImode, regno); | |
4580 ops[2] = gen_rtx_REG (DImode, regno + 2); | |
4581 ops[3] = gen_rtx_REG (DImode, regno + 4); | |
4582 ops[4] = operands[2]; | |
4583 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, [%0]", | |
4584 ops); | |
4585 return ""; | |
4586 } | |
4587 [(set_attr "neon_type" "neon_vst3_vst4_lane")] | |
4588 ) | |
4589 | |
4590 (define_insn "neon_vst3_lane<mode>" | |
4591 [(set (mem:<V_three_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4592 (unspec:<V_three_elem> | |
4593 [(match_operand:CI 1 "s_register_operand" "w") | |
4594 (match_operand:SI 2 "immediate_operand" "i") | |
4595 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4596 UNSPEC_VST3_LANE))] | |
4597 "TARGET_NEON" | |
4598 { | |
4599 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4600 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4601 int regno = REGNO (operands[1]); | |
4602 rtx ops[5]; | |
4603 if (lane < 0 || lane >= max) | |
4604 error ("lane out of range"); | |
4605 else if (lane >= max / 2) | |
4606 { | |
4607 lane -= max / 2; | |
4608 regno += 2; | |
4609 } | |
4610 ops[0] = operands[0]; | |
4611 ops[1] = gen_rtx_REG (DImode, regno); | |
4612 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4613 ops[3] = gen_rtx_REG (DImode, regno + 8); | |
4614 ops[4] = GEN_INT (lane); | |
4615 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, [%0]", | |
4616 ops); | |
4617 return ""; | |
4618 } | |
4619 [(set_attr "neon_type" "neon_vst3_vst4_lane")]) | |
4620 | |
4621 (define_insn "neon_vld4<mode>" | |
4622 [(set (match_operand:OI 0 "s_register_operand" "=w") | |
4623 (unspec:OI [(mem:OI (match_operand:SI 1 "s_register_operand" "r")) | |
4624 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4625 UNSPEC_VLD4))] | |
4626 "TARGET_NEON" | |
4627 { | |
4628 if (<V_sz_elem> == 64) | |
4629 return "vld1.64\t%h0, [%1]"; | |
4630 else | |
4631 return "vld4.<V_sz_elem>\t%h0, [%1]"; | |
4632 } | |
4633 [(set (attr "neon_type") | |
4634 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4635 (const_string "neon_vld1_1_2_regs") | |
4636 (const_string "neon_vld3_vld4")))] | |
4637 ) | |
4638 | |
4639 (define_expand "neon_vld4<mode>" | |
4640 [(match_operand:XI 0 "s_register_operand" "=w") | |
4641 (match_operand:SI 1 "s_register_operand" "+r") | |
4642 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4643 "TARGET_NEON" | |
4644 { | |
4645 emit_insn (gen_neon_vld4qa<mode> (operands[0], operands[0], | |
4646 operands[1], operands[1])); | |
4647 emit_insn (gen_neon_vld4qb<mode> (operands[0], operands[0], | |
4648 operands[1], operands[1])); | |
4649 DONE; | |
4650 }) | |
4651 | |
4652 (define_insn "neon_vld4qa<mode>" | |
4653 [(set (match_operand:XI 0 "s_register_operand" "=w") | |
4654 (unspec:XI [(mem:XI (match_operand:SI 3 "s_register_operand" "2")) | |
4655 (match_operand:XI 1 "s_register_operand" "0") | |
4656 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4657 UNSPEC_VLD4A)) | |
4658 (set (match_operand:SI 2 "s_register_operand" "=r") | |
4659 (plus:SI (match_dup 3) | |
4660 (const_int 32)))] | |
4661 "TARGET_NEON" | |
4662 { | |
4663 int regno = REGNO (operands[0]); | |
4664 rtx ops[5]; | |
4665 ops[0] = gen_rtx_REG (DImode, regno); | |
4666 ops[1] = gen_rtx_REG (DImode, regno + 4); | |
4667 ops[2] = gen_rtx_REG (DImode, regno + 8); | |
4668 ops[3] = gen_rtx_REG (DImode, regno + 12); | |
4669 ops[4] = operands[2]; | |
4670 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, [%4]!", ops); | |
4671 return ""; | |
4672 } | |
4673 [(set_attr "neon_type" "neon_vld3_vld4")] | |
4674 ) | |
4675 | |
4676 (define_insn "neon_vld4qb<mode>" | |
4677 [(set (match_operand:XI 0 "s_register_operand" "=w") | |
4678 (unspec:XI [(mem:XI (match_operand:SI 3 "s_register_operand" "2")) | |
4679 (match_operand:XI 1 "s_register_operand" "0") | |
4680 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4681 UNSPEC_VLD4B)) | |
4682 (set (match_operand:SI 2 "s_register_operand" "=r") | |
4683 (plus:SI (match_dup 3) | |
4684 (const_int 32)))] | |
4685 "TARGET_NEON" | |
4686 { | |
4687 int regno = REGNO (operands[0]); | |
4688 rtx ops[5]; | |
4689 ops[0] = gen_rtx_REG (DImode, regno + 2); | |
4690 ops[1] = gen_rtx_REG (DImode, regno + 6); | |
4691 ops[2] = gen_rtx_REG (DImode, regno + 10); | |
4692 ops[3] = gen_rtx_REG (DImode, regno + 14); | |
4693 ops[4] = operands[2]; | |
4694 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, [%4]!", ops); | |
4695 return ""; | |
4696 } | |
4697 [(set_attr "neon_type" "neon_vld3_vld4")] | |
4698 ) | |
4699 | |
4700 (define_insn "neon_vld4_lane<mode>" | |
4701 [(set (match_operand:OI 0 "s_register_operand" "=w") | |
4702 (unspec:OI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4703 (match_operand:OI 2 "s_register_operand" "0") | |
4704 (match_operand:SI 3 "immediate_operand" "i") | |
4705 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4706 UNSPEC_VLD4_LANE))] | |
4707 "TARGET_NEON" | |
4708 { | |
4709 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4710 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4711 int regno = REGNO (operands[0]); | |
4712 rtx ops[6]; | |
4713 if (lane < 0 || lane >= max) | |
4714 error ("lane out of range"); | |
4715 ops[0] = gen_rtx_REG (DImode, regno); | |
4716 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4717 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4718 ops[3] = gen_rtx_REG (DImode, regno + 6); | |
4719 ops[4] = operands[1]; | |
4720 ops[5] = operands[3]; | |
4721 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, [%4]", | |
4722 ops); | |
4723 return ""; | |
4724 } | |
4725 [(set_attr "neon_type" "neon_vld3_vld4_lane")] | |
4726 ) | |
4727 | |
4728 (define_insn "neon_vld4_lane<mode>" | |
4729 [(set (match_operand:XI 0 "s_register_operand" "=w") | |
4730 (unspec:XI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4731 (match_operand:XI 2 "s_register_operand" "0") | |
4732 (match_operand:SI 3 "immediate_operand" "i") | |
4733 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4734 UNSPEC_VLD4_LANE))] | |
4735 "TARGET_NEON" | |
4736 { | |
4737 HOST_WIDE_INT lane = INTVAL (operands[3]); | |
4738 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4739 int regno = REGNO (operands[0]); | |
4740 rtx ops[6]; | |
4741 if (lane < 0 || lane >= max) | |
4742 error ("lane out of range"); | |
4743 else if (lane >= max / 2) | |
4744 { | |
4745 lane -= max / 2; | |
4746 regno += 2; | |
4747 } | |
4748 ops[0] = gen_rtx_REG (DImode, regno); | |
4749 ops[1] = gen_rtx_REG (DImode, regno + 4); | |
4750 ops[2] = gen_rtx_REG (DImode, regno + 8); | |
4751 ops[3] = gen_rtx_REG (DImode, regno + 12); | |
4752 ops[4] = operands[1]; | |
4753 ops[5] = GEN_INT (lane); | |
4754 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, [%4]", | |
4755 ops); | |
4756 return ""; | |
4757 } | |
4758 [(set_attr "neon_type" "neon_vld3_vld4_lane")] | |
4759 ) | |
4760 | |
4761 (define_insn "neon_vld4_dup<mode>" | |
4762 [(set (match_operand:OI 0 "s_register_operand" "=w") | |
4763 (unspec:OI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) | |
4764 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4765 UNSPEC_VLD4_DUP))] | |
4766 "TARGET_NEON" | |
4767 { | |
4768 if (GET_MODE_NUNITS (<MODE>mode) > 1) | |
4769 { | |
4770 int regno = REGNO (operands[0]); | |
4771 rtx ops[5]; | |
4772 ops[0] = gen_rtx_REG (DImode, regno); | |
4773 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4774 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4775 ops[3] = gen_rtx_REG (DImode, regno + 6); | |
4776 ops[4] = operands[1]; | |
4777 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[], %P1[], %P2[], %P3[]}, [%4]", | |
4778 ops); | |
4779 return ""; | |
4780 } | |
4781 else | |
4782 return "vld1.<V_sz_elem>\t%h0, [%1]"; | |
4783 } | |
4784 [(set (attr "neon_type") | |
4785 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) | |
4786 (const_string "neon_vld3_vld4_all_lanes") | |
4787 (const_string "neon_vld1_1_2_regs")))] | |
4788 ) | |
4789 | |
4790 (define_insn "neon_vst4<mode>" | |
4791 [(set (mem:OI (match_operand:SI 0 "s_register_operand" "r")) | |
4792 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") | |
4793 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4794 UNSPEC_VST4))] | |
4795 "TARGET_NEON" | |
4796 { | |
4797 if (<V_sz_elem> == 64) | |
4798 return "vst1.64\t%h1, [%0]"; | |
4799 else | |
4800 return "vst4.<V_sz_elem>\t%h1, [%0]"; | |
4801 } | |
4802 [(set (attr "neon_type") | |
4803 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) | |
4804 (const_string "neon_vst1_1_2_regs_vst2_2_regs") | |
4805 (const_string "neon_vst2_4_regs_vst3_vst4")))] | |
4806 ) | |
4807 | |
4808 (define_expand "neon_vst4<mode>" | |
4809 [(match_operand:SI 0 "s_register_operand" "+r") | |
4810 (match_operand:XI 1 "s_register_operand" "w") | |
4811 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4812 "TARGET_NEON" | |
4813 { | |
4814 emit_insn (gen_neon_vst4qa<mode> (operands[0], operands[0], operands[1])); | |
4815 emit_insn (gen_neon_vst4qb<mode> (operands[0], operands[0], operands[1])); | |
4816 DONE; | |
4817 }) | |
4818 | |
4819 (define_insn "neon_vst4qa<mode>" | |
4820 [(set (mem:OI (match_operand:SI 1 "s_register_operand" "0")) | |
4821 (unspec:OI [(match_operand:XI 2 "s_register_operand" "w") | |
4822 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4823 UNSPEC_VST4A)) | |
4824 (set (match_operand:SI 0 "s_register_operand" "=r") | |
4825 (plus:SI (match_dup 1) | |
4826 (const_int 32)))] | |
4827 "TARGET_NEON" | |
4828 { | |
4829 int regno = REGNO (operands[2]); | |
4830 rtx ops[5]; | |
4831 ops[0] = operands[0]; | |
4832 ops[1] = gen_rtx_REG (DImode, regno); | |
4833 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4834 ops[3] = gen_rtx_REG (DImode, regno + 8); | |
4835 ops[4] = gen_rtx_REG (DImode, regno + 12); | |
4836 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, [%0]!", ops); | |
4837 return ""; | |
4838 } | |
4839 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] | |
4840 ) | |
4841 | |
4842 (define_insn "neon_vst4qb<mode>" | |
4843 [(set (mem:OI (match_operand:SI 1 "s_register_operand" "0")) | |
4844 (unspec:OI [(match_operand:XI 2 "s_register_operand" "w") | |
4845 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4846 UNSPEC_VST4B)) | |
4847 (set (match_operand:SI 0 "s_register_operand" "=r") | |
4848 (plus:SI (match_dup 1) | |
4849 (const_int 32)))] | |
4850 "TARGET_NEON" | |
4851 { | |
4852 int regno = REGNO (operands[2]); | |
4853 rtx ops[5]; | |
4854 ops[0] = operands[0]; | |
4855 ops[1] = gen_rtx_REG (DImode, regno + 2); | |
4856 ops[2] = gen_rtx_REG (DImode, regno + 6); | |
4857 ops[3] = gen_rtx_REG (DImode, regno + 10); | |
4858 ops[4] = gen_rtx_REG (DImode, regno + 14); | |
4859 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, [%0]!", ops); | |
4860 return ""; | |
4861 } | |
4862 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] | |
4863 ) | |
4864 | |
4865 (define_insn "neon_vst4_lane<mode>" | |
4866 [(set (mem:<V_four_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4867 (unspec:<V_four_elem> | |
4868 [(match_operand:OI 1 "s_register_operand" "w") | |
4869 (match_operand:SI 2 "immediate_operand" "i") | |
4870 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4871 UNSPEC_VST4_LANE))] | |
4872 "TARGET_NEON" | |
4873 { | |
4874 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4875 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4876 int regno = REGNO (operands[1]); | |
4877 rtx ops[6]; | |
4878 if (lane < 0 || lane >= max) | |
4879 error ("lane out of range"); | |
4880 ops[0] = operands[0]; | |
4881 ops[1] = gen_rtx_REG (DImode, regno); | |
4882 ops[2] = gen_rtx_REG (DImode, regno + 2); | |
4883 ops[3] = gen_rtx_REG (DImode, regno + 4); | |
4884 ops[4] = gen_rtx_REG (DImode, regno + 6); | |
4885 ops[5] = operands[2]; | |
4886 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, [%0]", | |
4887 ops); | |
4888 return ""; | |
4889 } | |
4890 [(set_attr "neon_type" "neon_vst3_vst4_lane")] | |
4891 ) | |
4892 | |
4893 (define_insn "neon_vst4_lane<mode>" | |
4894 [(set (mem:<V_four_elem> (match_operand:SI 0 "s_register_operand" "r")) | |
4895 (unspec:<V_four_elem> | |
4896 [(match_operand:XI 1 "s_register_operand" "w") | |
4897 (match_operand:SI 2 "immediate_operand" "i") | |
4898 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] | |
4899 UNSPEC_VST4_LANE))] | |
4900 "TARGET_NEON" | |
4901 { | |
4902 HOST_WIDE_INT lane = INTVAL (operands[2]); | |
4903 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); | |
4904 int regno = REGNO (operands[1]); | |
4905 rtx ops[6]; | |
4906 if (lane < 0 || lane >= max) | |
4907 error ("lane out of range"); | |
4908 else if (lane >= max / 2) | |
4909 { | |
4910 lane -= max / 2; | |
4911 regno += 2; | |
4912 } | |
4913 ops[0] = operands[0]; | |
4914 ops[1] = gen_rtx_REG (DImode, regno); | |
4915 ops[2] = gen_rtx_REG (DImode, regno + 4); | |
4916 ops[3] = gen_rtx_REG (DImode, regno + 8); | |
4917 ops[4] = gen_rtx_REG (DImode, regno + 12); | |
4918 ops[5] = GEN_INT (lane); | |
4919 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, [%0]", | |
4920 ops); | |
4921 return ""; | |
4922 } | |
4923 [(set_attr "neon_type" "neon_vst3_vst4_lane")] | |
4924 ) | |
4925 | |
4926 (define_expand "neon_vand<mode>" | |
4927 [(match_operand:VDQX 0 "s_register_operand" "") | |
4928 (match_operand:VDQX 1 "s_register_operand" "") | |
4929 (match_operand:VDQX 2 "neon_inv_logic_op2" "") | |
4930 (match_operand:SI 3 "immediate_operand" "")] | |
4931 "TARGET_NEON" | |
4932 { | |
4933 emit_insn (gen_and<mode>3<V_suf64> (operands[0], operands[1], operands[2])); | |
4934 DONE; | |
4935 }) | |
4936 | |
4937 (define_expand "neon_vorr<mode>" | |
4938 [(match_operand:VDQX 0 "s_register_operand" "") | |
4939 (match_operand:VDQX 1 "s_register_operand" "") | |
4940 (match_operand:VDQX 2 "neon_logic_op2" "") | |
4941 (match_operand:SI 3 "immediate_operand" "")] | |
4942 "TARGET_NEON" | |
4943 { | |
4944 emit_insn (gen_ior<mode>3<V_suf64> (operands[0], operands[1], operands[2])); | |
4945 DONE; | |
4946 }) | |
4947 | |
4948 (define_expand "neon_veor<mode>" | |
4949 [(match_operand:VDQX 0 "s_register_operand" "") | |
4950 (match_operand:VDQX 1 "s_register_operand" "") | |
4951 (match_operand:VDQX 2 "s_register_operand" "") | |
4952 (match_operand:SI 3 "immediate_operand" "")] | |
4953 "TARGET_NEON" | |
4954 { | |
4955 emit_insn (gen_xor<mode>3<V_suf64> (operands[0], operands[1], operands[2])); | |
4956 DONE; | |
4957 }) | |
4958 | |
4959 (define_expand "neon_vbic<mode>" | |
4960 [(match_operand:VDQX 0 "s_register_operand" "") | |
4961 (match_operand:VDQX 1 "s_register_operand" "") | |
4962 (match_operand:VDQX 2 "neon_logic_op2" "") | |
4963 (match_operand:SI 3 "immediate_operand" "")] | |
4964 "TARGET_NEON" | |
4965 { | |
4966 emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2])); | |
4967 DONE; | |
4968 }) | |
4969 | |
4970 (define_expand "neon_vorn<mode>" | |
4971 [(match_operand:VDQX 0 "s_register_operand" "") | |
4972 (match_operand:VDQX 1 "s_register_operand" "") | |
4973 (match_operand:VDQX 2 "neon_inv_logic_op2" "") | |
4974 (match_operand:SI 3 "immediate_operand" "")] | |
4975 "TARGET_NEON" | |
4976 { | |
4977 emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2])); | |
4978 DONE; | |
4979 }) |