OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / neon.md
1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006 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 2, 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 COPYING.  If not, write to the Free
19 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 ;; 02110-1301, USA.
21
22 ;; Constants for unspecs.
23 (define_constants
24   [(UNSPEC_ASHIFT_SIGNED        65)
25    (UNSPEC_ASHIFT_UNSIGNED      66)
26    (UNSPEC_VABA                 67)
27    (UNSPEC_VABAL                68)
28    (UNSPEC_VABD                 69)
29    (UNSPEC_VABDL                70)
30    (UNSPEC_VABS                 71)
31    (UNSPEC_VADD                 72)
32    (UNSPEC_VADDHN               73)
33    (UNSPEC_VADDL                74)
34    (UNSPEC_VADDW                75)
35    (UNSPEC_VAND                 76)
36    (UNSPEC_VBIC                 77)
37    (UNSPEC_VBSL                 78)
38    (UNSPEC_VCAGE                79)
39    (UNSPEC_VCAGT                80)
40    (UNSPEC_VCEQ                 81)
41    (UNSPEC_VCGE                 82)
42    (UNSPEC_VCGT                 83)
43    (UNSPEC_VCLS                 84)
44    (UNSPEC_VCLZ                 85)
45    (UNSPEC_VCNT                 86)
46    (UNSPEC_VCOMBINE             87)
47    (UNSPEC_VCVT                 88)
48    (UNSPEC_VCVT_N               89)
49    (UNSPEC_VDUP_LANE            90)
50    (UNSPEC_VDUP_N               91)
51    (UNSPEC_VEOR                 92)
52    (UNSPEC_VEXT                 93)
53    (UNSPEC_VGET_HIGH            94)
54    (UNSPEC_VGET_LANE            95)
55    (UNSPEC_VGET_LOW             96)
56    (UNSPEC_VHADD                97)
57    (UNSPEC_VHSUB                98)
58    (UNSPEC_VLD1                 99)
59    (UNSPEC_VLD1_DUP             100)
60    (UNSPEC_VLD1_LANE            101)
61    (UNSPEC_VLD2                 102)
62    (UNSPEC_VLD2_DUP             103)
63    (UNSPEC_VLD2_LANE            104)
64    (UNSPEC_VLD3                 105)
65    (UNSPEC_VLD3A                106)
66    (UNSPEC_VLD3B                107)
67    (UNSPEC_VLD3_DUP             108)
68    (UNSPEC_VLD3_LANE            109)
69    (UNSPEC_VLD4                 110)
70    (UNSPEC_VLD4A                111)
71    (UNSPEC_VLD4B                112)
72    (UNSPEC_VLD4_DUP             113)
73    (UNSPEC_VLD4_LANE            114)
74    (UNSPEC_VMAX                 115)
75    (UNSPEC_VMIN                 116)
76    (UNSPEC_VMLA                 117)
77    (UNSPEC_VMLAL                118)
78    (UNSPEC_VMLA_LANE            119)
79    (UNSPEC_VMLAL_LANE           120)
80    (UNSPEC_VMLS                 121)
81    (UNSPEC_VMLSL                122)
82    (UNSPEC_VMLS_LANE            123)
83    (UNSPEC_VMLSL_LANE           124)
84    (UNSPEC_VMOVL                125)
85    (UNSPEC_VMOVN                126)
86    (UNSPEC_VMUL                 127)
87    (UNSPEC_VMULL                128)
88    (UNSPEC_VMUL_LANE            129)
89    (UNSPEC_VMULL_LANE           130)
90    (UNSPEC_VMUL_N               131)
91    (UNSPEC_VMVN                 132)
92    (UNSPEC_VORN                 133)
93    (UNSPEC_VORR                 134)
94    (UNSPEC_VPADAL               135)
95    (UNSPEC_VPADD                136)
96    (UNSPEC_VPADDL               137)
97    (UNSPEC_VPMAX                138)
98    (UNSPEC_VPMIN                139)
99    (UNSPEC_VPSMAX               140)
100    (UNSPEC_VPSMIN               141)
101    (UNSPEC_VPUMAX               142)
102    (UNSPEC_VPUMIN               143)
103    (UNSPEC_VQABS                144)
104    (UNSPEC_VQADD                145)
105    (UNSPEC_VQDMLAL              146)
106    (UNSPEC_VQDMLAL_LANE         147)
107    (UNSPEC_VQDMLSL              148)
108    (UNSPEC_VQDMLSL_LANE         149)
109    (UNSPEC_VQDMULH              150)
110    (UNSPEC_VQDMULH_LANE         151)
111    (UNSPEC_VQDMULL              152)
112    (UNSPEC_VQDMULL_LANE         153)
113    (UNSPEC_VQMOVN               154)
114    (UNSPEC_VQMOVUN              155)
115    (UNSPEC_VQNEG                156)
116    (UNSPEC_VQSHL                157)
117    (UNSPEC_VQSHL_N              158)
118    (UNSPEC_VQSHLU_N             159)
119    (UNSPEC_VQSHRN_N             160)
120    (UNSPEC_VQSHRUN_N            161)
121    (UNSPEC_VQSUB                162)
122    (UNSPEC_VRECPE               163)
123    (UNSPEC_VRECPS               164)
124    (UNSPEC_VREV16               165)
125    (UNSPEC_VREV32               166)
126    (UNSPEC_VREV64               167)
127    (UNSPEC_VRSQRTE              168)
128    (UNSPEC_VRSQRTS              169)
129    (UNSPEC_VSET_LANE            170)
130    (UNSPEC_VSHL                 171)
131    (UNSPEC_VSHLL_N              172)
132    (UNSPEC_VSHL_N               173)
133    (UNSPEC_VSHR_N               174)
134    (UNSPEC_VSHRN_N              175)
135    (UNSPEC_VSLI                 176)
136    (UNSPEC_VSRA_N               177)
137    (UNSPEC_VSRI                 178)
138    (UNSPEC_VST1                 179)
139    (UNSPEC_VST1_LANE            180)
140    (UNSPEC_VST2                 181)
141    (UNSPEC_VST2_LANE            182)
142    (UNSPEC_VST3                 183)
143    (UNSPEC_VST3A                184)
144    (UNSPEC_VST3B                185)
145    (UNSPEC_VST3_LANE            186)
146    (UNSPEC_VST4                 187)
147    (UNSPEC_VST4A                188)
148    (UNSPEC_VST4B                189)
149    (UNSPEC_VST4_LANE            190)
150    (UNSPEC_VSTRUCTDUMMY         191)
151    (UNSPEC_VSUB                 192)
152    (UNSPEC_VSUBHN               193)
153    (UNSPEC_VSUBL                194)
154    (UNSPEC_VSUBW                195)
155    (UNSPEC_VTBL                 196)
156    (UNSPEC_VTBX                 197)
157    (UNSPEC_VTRN1                198)
158    (UNSPEC_VTRN2                199)
159    (UNSPEC_VTST                 200)
160    (UNSPEC_VUZP1                201)
161    (UNSPEC_VUZP2                202)
162    (UNSPEC_VZIP1                203)
163    (UNSPEC_VZIP2                204)])
164
165 ;; Double-width vector modes.
166 (define_mode_macro VD [V8QI V4HI V2SI V2SF])
167
168 ;; Double-width vector modes plus 64-bit elements.
169 (define_mode_macro VDX [V8QI V4HI V2SI V2SF DI])
170
171 ;; Same, without floating-point elements.
172 (define_mode_macro VDI [V8QI V4HI V2SI])
173
174 ;; Quad-width vector modes.
175 (define_mode_macro VQ [V16QI V8HI V4SI V4SF])
176
177 ;; Quad-width vector modes plus 64-bit elements.
178 (define_mode_macro VQX [V16QI V8HI V4SI V4SF V2DI])
179
180 ;; Same, without floating-point elements.
181 (define_mode_macro VQI [V16QI V8HI V4SI])
182
183 ;; Same, with TImode added, for moves.
184 (define_mode_macro VQXMOV [V16QI V8HI V4SI V4SF V2DI TI])
185
186 ;; Opaque structure types wider than TImode.
187 (define_mode_macro VSTRUCT [EI OI CI XI])
188
189 ;; Number of instructions needed to load/store struct elements. FIXME!
190 (define_mode_attr V_slen [(EI "2") (OI "2") (CI "3") (XI "4")])
191
192 ;; Opaque structure types used in table lookups (except vtbl1/vtbx1).
193 (define_mode_macro VTAB [TI EI OI])
194
195 ;; vtbl<n> suffix for above modes.
196 (define_mode_attr VTAB_n [(TI "2") (EI "3") (OI "4")])
197
198 ;; Widenable modes.
199 (define_mode_macro VW [V8QI V4HI V2SI])
200
201 ;; Narrowable modes.
202 (define_mode_macro VN [V8HI V4SI V2DI])
203
204 ;; All supported vector modes (except singleton DImode).
205 (define_mode_macro VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF V2DI])
206
207 ;; All supported vector modes (except those with 64-bit integer elements).
208 (define_mode_macro VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF])
209
210 ;; Supported integer vector modes (not 64 bit elements).
211 (define_mode_macro VDQIW [V8QI V16QI V4HI V8HI V2SI V4SI])
212
213 ;; Supported integer vector modes (not singleton DI)
214 (define_mode_macro VDQI [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
215
216 ;; Vector modes, including 64-bit integer elements.
217 (define_mode_macro VDQX [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF DI V2DI])
218
219 ;; Vector modes including 64-bit integer elements, but no floats.
220 (define_mode_macro VDQIX [V8QI V16QI V4HI V8HI V2SI V4SI DI V2DI])
221
222 ;; Vector modes for float->int conversions.
223 (define_mode_macro VCVTF [V2SF V4SF])
224
225 ;; Vector modes form int->float conversions.
226 (define_mode_macro VCVTI [V2SI V4SI])
227
228 ;; Vector modes for doubleword multiply-accumulate, etc. insns.
229 (define_mode_macro VMD [V4HI V2SI V2SF])
230
231 ;; Vector modes for quadword multiply-accumulate, etc. insns.
232 (define_mode_macro VMQ [V8HI V4SI V4SF])
233
234 ;; Above modes combined.
235 (define_mode_macro VMDQ [V4HI V2SI V2SF V8HI V4SI V4SF])
236
237 ;; As VMD, but integer modes only.
238 (define_mode_macro VMDI [V4HI V2SI])
239
240 ;; As VMQ, but integer modes only.
241 (define_mode_macro VMQI [V8HI V4SI])
242
243 ;; Above modes combined.
244 (define_mode_macro VMDQI [V4HI V2SI V8HI V4SI])
245
246 ;; Modes with 8-bit and 16-bit elements.
247 (define_mode_macro VX [V8QI V4HI V16QI V8HI])
248
249 ;; Modes with 8-bit elements.
250 (define_mode_macro VE [V8QI V16QI])
251
252 ;; Modes with 64-bit elements only.
253 (define_mode_macro V64 [DI V2DI])
254
255 ;; Modes with 32-bit elements only.
256 (define_mode_macro V32 [V2SI V2SF V4SI V4SF])
257
258 ;; (Opposite) mode to convert to/from for above conversions.
259 (define_mode_attr V_CVTTO [(V2SI "V2SF") (V2SF "V2SI")
260                            (V4SI "V4SF") (V4SF "V4SI")])
261
262 ;; Define element mode for each vector mode.
263 (define_mode_attr V_elem [(V8QI "QI") (V16QI "QI")
264                           (V4HI "HI") (V8HI "HI")
265                           (V2SI "SI") (V4SI "SI")
266                           (V2SF "SF") (V4SF "SF")
267                           (DI "DI")   (V2DI "DI")])
268
269 ;; Element modes for vector extraction, padded up to register size.
270
271 (define_mode_attr V_ext [(V8QI "SI") (V16QI "SI")
272                          (V4HI "SI") (V8HI "SI")
273                          (V2SI "SI") (V4SI "SI")
274                          (V2SF "SF") (V4SF "SF")
275                          (DI "DI") (V2DI "DI")])
276
277 ;; Mode of pair of elements for each vector mode, to define transfer
278 ;; size for structure lane/dup loads and stores.
279 (define_mode_attr V_two_elem [(V8QI "HI") (V16QI "HI")
280                               (V4HI "SI") (V8HI "SI")
281                               (V2SI "V2SI") (V4SI "V2SI")
282                               (V2SF "V2SF") (V4SF "V2SF")
283                               (DI "V2DI")   (V2DI "V2DI")])
284
285 ;; Similar, for three elements.
286 ;; ??? Should we define extra modes so that sizes of all three-element
287 ;; accesses can be accurately represented?
288 (define_mode_attr V_three_elem [(V8QI "SI")   (V16QI "SI")
289                                 (V4HI "V4HI") (V8HI "V4HI")
290                                 (V2SI "V4SI") (V4SI "V4SI")
291                                 (V2SF "V4SF") (V4SF "V4SF")
292                                 (DI "EI")     (V2DI "EI")])
293
294 ;; Similar, for four elements.
295 (define_mode_attr V_four_elem [(V8QI "SI")   (V16QI "SI")
296                                (V4HI "V4HI") (V8HI "V4HI")
297                                (V2SI "V4SI") (V4SI "V4SI")
298                                (V2SF "V4SF") (V4SF "V4SF")
299                                (DI "OI")     (V2DI "OI")])
300
301 ;; Register width from element mode
302 (define_mode_attr V_reg [(V8QI "P") (V16QI "q")
303                          (V4HI "P") (V8HI  "q")
304                          (V2SI "P") (V4SI  "q")
305                          (V2SF "P") (V4SF  "q")
306                          (DI   "P") (V2DI  "q")])
307
308 ;; Wider modes with the same number of elements.
309 (define_mode_attr V_widen [(V8QI "V8HI") (V4HI "V4SI") (V2SI "V2DI")])
310
311 ;; Narrower modes with the same number of elements.
312 (define_mode_attr V_narrow [(V8HI "V8QI") (V4SI "V4HI") (V2DI "V2SI")])
313
314 ;; Modes with half the number of equal-sized elements.
315 (define_mode_attr V_HALF [(V16QI "V8QI") (V8HI "V4HI")
316                           (V4SI  "V2SI") (V4SF "V2SF")
317                           (V2DI "DI")])
318
319 ;; Same, but lower-case.
320 (define_mode_attr V_half [(V16QI "v8qi") (V8HI "v4hi")
321                           (V4SI  "v2si") (V4SF "v2sf")
322                           (V2DI "di")])
323
324 ;; Modes with twice the number of equal-sized elements.
325 (define_mode_attr V_DOUBLE [(V8QI "V16QI") (V4HI "V8HI")
326                             (V2SI "V4SI") (V2SF "V4SF")
327                             (DI "V2DI")])
328
329 ;; Same, but lower-case.
330 (define_mode_attr V_double [(V8QI "v16qi") (V4HI "v8hi")
331                             (V2SI "v4si") (V2SF "v4sf")
332                             (DI "v2di")])
333
334 ;; Modes with double-width elements.
335 (define_mode_attr V_double_width [(V8QI "V4HI") (V16QI "V8HI")
336                                   (V4HI "V2SI") (V8HI "V4SI")
337                                   (V2SI "DI")   (V4SI "V2DI")])
338
339 ;; Mode of result of comparison operations (and bit-select operand 1).
340 (define_mode_attr V_cmp_result [(V8QI "V8QI") (V16QI "V16QI")
341                                 (V4HI "V4HI") (V8HI  "V8HI")
342                                 (V2SI "V2SI") (V4SI  "V4SI")
343                                 (V2SF "V2SI") (V4SF  "V4SI")
344                                 (DI   "DI")   (V2DI  "V2DI")])
345
346 ;; Get element type from double-width mode, for operations where we don't care
347 ;; about signedness.
348 (define_mode_attr V_if_elem [(V8QI "i8")  (V16QI "i8")
349                              (V4HI "i16") (V8HI  "i16")
350                              (V2SI "i32") (V4SI  "i32")
351                              (DI   "i64") (V2DI  "i64")
352                              (V2SF "f32") (V4SF  "f32")])
353
354 ;; Same, but for operations which work on signed values.
355 (define_mode_attr V_s_elem [(V8QI "s8")  (V16QI "s8")
356                             (V4HI "s16") (V8HI  "s16")
357                             (V2SI "s32") (V4SI  "s32")
358                             (DI   "s64") (V2DI  "s64")
359                             (V2SF "f32") (V4SF  "f32")])
360
361 ;; Same, but for operations which work on unsigned values.
362 (define_mode_attr V_u_elem [(V8QI "u8")  (V16QI "u8")
363                             (V4HI "u16") (V8HI  "u16")
364                             (V2SI "u32") (V4SI  "u32")
365                             (DI   "u64") (V2DI  "u64")
366                             (V2SF "f32") (V4SF  "f32")])
367
368 ;; Element types for extraction of unsigned scalars.
369 (define_mode_attr V_uf_sclr [(V8QI "u8")  (V16QI "u8")
370                              (V4HI "u16") (V8HI "u16")
371                              (V2SI "32") (V4SI "32")
372                              (V2SF "32") (V4SF "32")])
373
374 (define_mode_attr V_sz_elem [(V8QI "8")  (V16QI "8")
375                              (V4HI "16") (V8HI  "16")
376                              (V2SI "32") (V4SI  "32")
377                              (DI   "64") (V2DI  "64")
378                              (V2SF "32") (V4SF  "32")])
379
380 ;; Element sizes for duplicating ARM registers to all elements of a vector.
381 (define_mode_attr VD_dup [(V8QI "8") (V4HI "16") (V2SI "32") (V2SF "32")])
382
383 ;; Opaque integer types for results of pair-forming intrinsics (vtrn, etc.)
384 (define_mode_attr V_PAIR [(V8QI "TI") (V16QI "OI")
385                           (V4HI "TI") (V8HI  "OI")
386                           (V2SI "TI") (V4SI  "OI")
387                           (V2SF "TI") (V4SF  "OI")
388                           (DI   "TI") (V2DI  "OI")])
389
390 ;; Same, but lower-case.
391 (define_mode_attr V_pair [(V8QI "ti") (V16QI "oi")
392                           (V4HI "ti") (V8HI  "oi")
393                           (V2SI "ti") (V4SI  "oi")
394                           (V2SF "ti") (V4SF  "oi")
395                           (DI   "ti") (V2DI  "oi")])
396
397 ;; Operations on two halves of a quadword vector.
398 (define_code_macro vqh_ops [plus smin smax umin umax])
399
400 ;; Same, without unsigned variants (for use with *SFmode pattern).
401 (define_code_macro vqhs_ops [plus smin smax])
402
403 ;; Assembler mnemonics for above codes.
404 (define_code_attr VQH_mnem [(plus "vadd") (smin "vmin") (smax "vmax")
405                             (umin "vmin") (umax "vmax")])
406
407 ;; Signs of above, where relevant.
408 (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
409                             (umax "u")])
410
411 ;; Extra suffix on some 64-bit insn names (to avoid collision with standard
412 ;; names which we don't want to define).
413 (define_mode_attr V_suf64 [(V8QI "") (V16QI "")
414                            (V4HI "") (V8HI "")
415                            (V2SI "") (V4SI "")
416                            (V2SF "") (V4SF "")
417                            (DI "_neon") (V2DI "")])
418
419 ;; Scalars to be presented to scalar multiplication instructions
420 ;; must satisfy the following constraints.
421 ;; 1. If the mode specifies 16-bit elements, the scalar must be in D0-D7.
422 ;; 2. If the mode specifies 32-bit elements, the scalar must be in D0-D15.
423 ;; This mode attribute is used to obtain the correct register constraints.
424 (define_mode_attr scalar_mul_constraint [(V4HI "x") (V2SI "t") (V2SF "t")
425                                          (V8HI "x") (V4SI "t") (V4SF "t")])
426
427 ;; Attribute used to permit string comparisons against <VQH_mnem> in
428 ;; neon_type attribute definitions.
429 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
430
431 ;; Classification of NEON instructions for scheduling purposes.
432 ;; Do not set this attribute and the "type" attribute together in
433 ;; any one instruction pattern.
434 (define_attr "neon_type"
435    "neon_int_1,\
436    neon_int_2,\
437    neon_int_3,\
438    neon_int_4,\
439    neon_int_5,\
440    neon_vqneg_vqabs,\
441    neon_vmov,\
442    neon_vaba,\
443    neon_vsma,\
444    neon_vaba_qqq,\
445    neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
446    neon_mul_qqq_8_16_32_ddd_32,\
447    neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
448    neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
449    neon_mla_qqq_8_16,\
450    neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
451    neon_mla_qqq_32_qqd_32_scalar,\
452    neon_mul_ddd_16_scalar_32_16_long_scalar,\
453    neon_mul_qqd_32_scalar,\
454    neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
455    neon_shift_1,\
456    neon_shift_2,\
457    neon_shift_3,\
458    neon_vshl_ddd,\
459    neon_vqshl_vrshl_vqrshl_qqq,\
460    neon_vsra_vrsra,\
461    neon_fp_vadd_ddd_vabs_dd,\
462    neon_fp_vadd_qqq_vabs_qq,\
463    neon_fp_vsum,\
464    neon_fp_vmul_ddd,\
465    neon_fp_vmul_qqd,\
466    neon_fp_vmla_ddd,\
467    neon_fp_vmla_qqq,\
468    neon_fp_vmla_ddd_scalar,\
469    neon_fp_vmla_qqq_scalar,\
470    neon_fp_vrecps_vrsqrts_ddd,\
471    neon_fp_vrecps_vrsqrts_qqq,\
472    neon_bp_simple,\
473    neon_bp_2cycle,\
474    neon_bp_3cycle,\
475    neon_ldr,\
476    neon_str,\
477    neon_vld1_1_2_regs,\
478    neon_vld1_3_4_regs,\
479    neon_vld2_2_regs_vld1_vld2_all_lanes,\
480    neon_vld2_4_regs,\
481    neon_vld3_vld4,\
482    neon_vst1_1_2_regs_vst2_2_regs,\
483    neon_vst1_3_4_regs,\
484    neon_vst2_4_regs_vst3_vst4,\
485    neon_vst3_vst4,\
486    neon_vld1_vld2_lane,\
487    neon_vld3_vld4_lane,\
488    neon_vst1_vst2_lane,\
489    neon_vst3_vst4_lane,\
490    neon_vld3_vld4_all_lanes,\
491    neon_mcr,\
492    neon_mcr_2_mcrr,\
493    neon_mrc,\
494    neon_mrrc,\
495    neon_ldm_2,\
496    neon_stm_2,\
497    none"
498  (const_string "none"))
499
500 ;; Predicates used for setting the above attribute.
501
502 (define_mode_attr Is_float_mode [(V8QI "false") (V16QI "false")
503                                  (V4HI "false") (V8HI "false")
504                                  (V2SI "false") (V4SI "false")
505                                  (V2SF "true") (V4SF "true")
506                                  (DI "false") (V2DI "false")])
507
508 (define_mode_attr Scalar_mul_8_16 [(V8QI "true") (V16QI "true")
509                                    (V4HI "true") (V8HI "true")
510                                    (V2SI "false") (V4SI "false")
511                                    (V2SF "false") (V4SF "false")
512                                    (DI "false") (V2DI "false")])
513
514
515 (define_mode_attr Is_d_reg [(V8QI "true") (V16QI "false")
516                             (V4HI "true") (V8HI  "false")
517                             (V2SI "true") (V4SI  "false")
518                             (V2SF "true") (V4SF  "false")
519                             (DI   "true") (V2DI  "false")])
520
521 (define_mode_attr V_mode_nunits [(V8QI "8") (V16QI "16")
522                                  (V4HI "4") (V8HI "8")
523                                  (V2SI "2") (V4SI "4")
524                                  (V2SF "2") (V4SF "4")
525                                  (DI "1")   (V2DI "2")])
526
527 (define_insn "*neon_mov<mode>"
528   [(set (match_operand:VD 0 "nonimmediate_operand"
529           "=w,Uv,w, w,  ?r,?w,?r,?r, ?Us")
530         (match_operand:VD 1 "general_operand"
531           " w,w, Dn,Uvi, w, r, r, Usi,r"))]
532   "TARGET_NEON"
533 {
534   if (which_alternative == 2)
535     {
536       int width, is_valid;
537       static char templ[40];
538
539       is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
540         &operands[1], &width);
541
542       gcc_assert (is_valid != 0);
543
544       if (width == 0)
545         return "vmov.f32\t%P0, %1  @ <mode>";
546       else
547         sprintf (templ, "vmov.i%d\t%%P0, %%1  @ <mode>", width);
548
549       return templ;
550     }
551
552   /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp
553      below must be changed to output_move_neon (which will use the
554      element/structure loads/stores), and the constraint changed to 'Un' instead
555      of 'Uv'.  */
556
557   switch (which_alternative)
558     {
559     case 0: return "vmov\t%P0, %P1  @ <mode>";
560     case 1: case 3: return output_move_vfp (operands);
561     case 2: gcc_unreachable ();
562     case 4: return "vmov\t%Q0, %R0, %P1  @ <mode>";
563     case 5: return "vmov\t%P0, %Q1, %R1  @ <mode>";
564     default: return output_move_double (operands);
565     }
566 }
567  [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
568   (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2")
569   (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
570   (set_attr "length" "4,4,4,4,4,4,8,8,8")
571   (set_attr "pool_range"     "*,*,*,1020,*,*,*,1020,*")
572   (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")])
573
574 (define_insn "*neon_mov<mode>"
575   [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
576           "=w,Un,w, w,  ?r,?w,?r,?r,  ?Us")
577         (match_operand:VQXMOV 1 "general_operand"
578           " w,w, Dn,Uni, w, r, r, Usi, r"))]
579   "TARGET_NEON"
580 {
581   if (which_alternative == 2)
582     {
583       int width, is_valid;
584       static char templ[40];
585
586       is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
587         &operands[1], &width);
588
589       gcc_assert (is_valid != 0);
590
591       if (width == 0)
592         return "vmov.f32\t%q0, %1  @ <mode>";
593       else
594         sprintf (templ, "vmov.i%d\t%%q0, %%1  @ <mode>", width);
595
596       return templ;
597     }
598
599   switch (which_alternative)
600     {
601     case 0: return "vmov\t%q0, %q1  @ <mode>";
602     case 1: case 3: return output_move_neon (operands);
603     case 2: gcc_unreachable ();
604     case 4: return "vmov\t%Q0, %R0, %e1  @ <mode>\;vmov\t%J0, %K0, %f1";
605     case 5: return "vmov\t%e0, %Q1, %R1  @ <mode>\;vmov\t%f0, %J1, %K1";
606     default: return output_move_quad (operands);
607     }
608 }
609   [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
610                           neon_mrrc,neon_mcr_2_mcrr,*,*,*")
611    (set_attr "type" "*,*,*,*,*,*,alu,load4,store4")
612    (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
613    (set_attr "length" "4,8,4,8,8,8,16,8,16")
614    (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
615    (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")])
616
617 (define_expand "movti"
618   [(set (match_operand:TI 0 "nonimmediate_operand" "")
619         (match_operand:TI 1 "general_operand" ""))]
620   "TARGET_NEON"
621 {
622 })
623
624 (define_expand "mov<mode>"
625   [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
626         (match_operand:VSTRUCT 1 "general_operand" ""))]
627   "TARGET_NEON"
628 {
629 })
630
631 (define_insn "*neon_mov<mode>"
632   [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
633         (match_operand:VSTRUCT 1 "general_operand"      " w,w, Ut"))]
634   "TARGET_NEON"
635 {
636   switch (which_alternative)
637     {
638     case 0: return "#";
639     case 1: case 2: return output_move_neon (operands);
640     default: gcc_unreachable ();
641     }
642 }
643   [(set_attr "length" "<V_slen>,<V_slen>,<V_slen>")])
644
645 (define_split
646   [(set (match_operand:EI 0 "s_register_operand" "")
647         (match_operand:EI 1 "s_register_operand" ""))]
648   "TARGET_NEON && reload_completed"
649   [(set (match_dup 0) (match_dup 1))
650    (set (match_dup 2) (match_dup 3))]
651 {
652   int rdest = REGNO (operands[0]);
653   int rsrc = REGNO (operands[1]);
654   rtx dest[2], src[2];
655
656   dest[0] = gen_rtx_REG (TImode, rdest);
657   src[0] = gen_rtx_REG (TImode, rsrc);
658   dest[1] = gen_rtx_REG (DImode, rdest + 4);
659   src[1] = gen_rtx_REG (DImode, rsrc + 4);
660
661   neon_disambiguate_copy (operands, dest, src, 2);
662 })
663
664 (define_split
665   [(set (match_operand:OI 0 "s_register_operand" "")
666         (match_operand:OI 1 "s_register_operand" ""))]
667   "TARGET_NEON && reload_completed"
668   [(set (match_dup 0) (match_dup 1))
669    (set (match_dup 2) (match_dup 3))]
670 {
671   int rdest = REGNO (operands[0]);
672   int rsrc = REGNO (operands[1]);
673   rtx dest[2], src[2];
674
675   dest[0] = gen_rtx_REG (TImode, rdest);
676   src[0] = gen_rtx_REG (TImode, rsrc);
677   dest[1] = gen_rtx_REG (TImode, rdest + 4);
678   src[1] = gen_rtx_REG (TImode, rsrc + 4);
679
680   neon_disambiguate_copy (operands, dest, src, 2);
681 })
682
683 (define_split
684   [(set (match_operand:CI 0 "s_register_operand" "")
685         (match_operand:CI 1 "s_register_operand" ""))]
686   "TARGET_NEON && reload_completed"
687   [(set (match_dup 0) (match_dup 1))
688    (set (match_dup 2) (match_dup 3))
689    (set (match_dup 4) (match_dup 5))]
690 {
691   int rdest = REGNO (operands[0]);
692   int rsrc = REGNO (operands[1]);
693   rtx dest[3], src[3];
694
695   dest[0] = gen_rtx_REG (TImode, rdest);
696   src[0] = gen_rtx_REG (TImode, rsrc);
697   dest[1] = gen_rtx_REG (TImode, rdest + 4);
698   src[1] = gen_rtx_REG (TImode, rsrc + 4);
699   dest[2] = gen_rtx_REG (TImode, rdest + 8);
700   src[2] = gen_rtx_REG (TImode, rsrc + 8);
701
702   neon_disambiguate_copy (operands, dest, src, 3);
703 })
704
705 (define_split
706   [(set (match_operand:XI 0 "s_register_operand" "")
707         (match_operand:XI 1 "s_register_operand" ""))]
708   "TARGET_NEON && reload_completed"
709   [(set (match_dup 0) (match_dup 1))
710    (set (match_dup 2) (match_dup 3))
711    (set (match_dup 4) (match_dup 5))
712    (set (match_dup 6) (match_dup 7))]
713 {
714   int rdest = REGNO (operands[0]);
715   int rsrc = REGNO (operands[1]);
716   rtx dest[4], src[4];
717
718   dest[0] = gen_rtx_REG (TImode, rdest);
719   src[0] = gen_rtx_REG (TImode, rsrc);
720   dest[1] = gen_rtx_REG (TImode, rdest + 4);
721   src[1] = gen_rtx_REG (TImode, rsrc + 4);
722   dest[2] = gen_rtx_REG (TImode, rdest + 8);
723   src[2] = gen_rtx_REG (TImode, rsrc + 8);
724   dest[3] = gen_rtx_REG (TImode, rdest + 12);
725   src[3] = gen_rtx_REG (TImode, rsrc + 12);
726
727   neon_disambiguate_copy (operands, dest, src, 4);
728 })
729
730 (define_insn "vec_set<mode>_internal"
731   [(set (match_operand:VD 0 "s_register_operand" "=w")
732         (vec_merge:VD
733           (vec_duplicate:VD
734             (match_operand:<V_elem> 1 "s_register_operand" "r"))
735           (match_operand:VD 3 "s_register_operand" "0")
736           (match_operand:SI 2 "immediate_operand" "i")))]
737   "TARGET_NEON"
738 {
739   operands[2] = GEN_INT (ffs ((int) INTVAL (operands[2]) - 1));
740   
741   return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
742 }
743   [(set_attr "predicable" "yes")
744    (set_attr "neon_type" "neon_mcr")])
745
746 (define_insn "vec_set<mode>_internal"
747   [(set (match_operand:VQ 0 "s_register_operand" "=w")
748         (vec_merge:VQ
749           (vec_duplicate:VQ
750             (match_operand:<V_elem> 1 "s_register_operand" "r"))
751           (match_operand:VQ 3 "s_register_operand" "0")
752           (match_operand:SI 2 "immediate_operand" "i")))]
753   "TARGET_NEON"
754 {
755   HOST_WIDE_INT elem = ffs (operands[2]) - 1;
756   int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
757   int elt = elem % half_elts;
758   int hi = (elem / half_elts) * 2;
759   int regno = REGNO (operands[0]);
760
761   operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
762   operands[2] = GEN_INT (elt);
763
764   return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
765 }
766   [(set_attr "predicable" "yes")
767    (set_attr "neon_type" "neon_mcr")]
768 )
769
770 (define_insn "vec_setv2di_internal"
771   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
772         (vec_merge:V2DI
773           (vec_duplicate:V2DI
774             (match_operand:DI 1 "s_register_operand" "r"))
775           (match_operand:V2DI 3 "s_register_operand" "0")
776           (match_operand:SI 2 "immediate_operand" "i")))]
777   "TARGET_NEON"
778 {
779   HOST_WIDE_INT elem = ffs (operands[2]) - 1;
780   int regno = REGNO (operands[0]) + 2 * elem;
781
782   operands[0] = gen_rtx_REG (DImode, regno);
783
784   return "vmov%?.64\t%P0, %Q1, %R1";
785 }
786   [(set_attr "predicable" "yes")
787    (set_attr "neon_type" "neon_mcr_2_mcrr")]
788 )
789
790 (define_expand "vec_set<mode>"
791   [(match_operand:VDQ 0 "s_register_operand" "")
792    (match_operand:<V_elem> 1 "s_register_operand" "")
793    (match_operand:SI 2 "immediate_operand" "")]
794   "TARGET_NEON"
795 {
796   HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
797   emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
798                                          GEN_INT (elem), operands[0]));
799   DONE;
800 })
801
802 (define_insn "vec_extract<mode>"
803   [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
804         (vec_select:<V_elem>
805           (match_operand:VD 1 "s_register_operand" "w")
806           (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
807   "TARGET_NEON"
808   "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"
809   [(set_attr "predicable" "yes")
810    (set_attr "neon_type" "neon_bp_simple")]
811 )
812
813 (define_insn "vec_extract<mode>"
814   [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
815         (vec_select:<V_elem>
816           (match_operand:VQ 1 "s_register_operand" "w")
817           (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
818   "TARGET_NEON"
819 {
820   int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
821   int elt = INTVAL (operands[2]) % half_elts;
822   int hi = (INTVAL (operands[2]) / half_elts) * 2;
823   int regno = REGNO (operands[1]);
824
825   operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
826   operands[2] = GEN_INT (elt);
827
828   return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
829 }
830   [(set_attr "predicable" "yes")
831    (set_attr "neon_type" "neon_bp_simple")]
832 )
833
834 (define_insn "vec_extractv2di"
835   [(set (match_operand:DI 0 "s_register_operand" "=r")
836         (vec_select:DI
837           (match_operand:V2DI 1 "s_register_operand" "w")
838           (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
839   "TARGET_NEON"
840 {
841   int regno = REGNO (operands[1]) + INTVAL (operands[2]);
842
843   operands[1] = gen_rtx_REG (DImode, regno);
844
845   return "vmov%?.64\t%Q0, %R0, %P1";
846 }
847   [(set_attr "predicable" "yes")
848    (set_attr "neon_type" "neon_int_1")]
849 )
850
851 (define_expand "vec_init<mode>"
852   [(match_operand:VDQ 0 "s_register_operand" "")
853    (match_operand 1 "" "")]
854   "TARGET_NEON"
855 {
856   neon_expand_vector_init (operands[0], operands[1]);
857   DONE;
858 })
859
860 ;; Doubleword and quadword arithmetic.
861
862 ;; NOTE: vadd/vsub and some other instructions also support 64-bit integer
863 ;; element size, which we could potentially use for "long long" operations. We
864 ;; don't want to do this at present though, because moving values from the
865 ;; vector unit to the ARM core is currently slow and 64-bit addition (etc.) is
866 ;; easy to do with ARM instructions anyway.
867
868 (define_insn "*add<mode>3_neon"
869   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
870         (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
871                   (match_operand:VDQ 2 "s_register_operand" "w")))]
872   "TARGET_NEON"
873   "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
874   [(set (attr "neon_type")
875       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
876                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
877                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
878                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
879                     (const_string "neon_int_1")))]
880 )
881
882 (define_insn "*sub<mode>3_neon"
883   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
884         (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
885                    (match_operand:VDQ 2 "s_register_operand" "w")))]
886   "TARGET_NEON"
887   "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
888   [(set (attr "neon_type")
889       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
890                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
891                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
892                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
893                     (const_string "neon_int_2")))]
894 )
895
896 (define_insn "*mul<mode>3_neon"
897   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
898         (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
899                   (match_operand:VDQ 2 "s_register_operand" "w")))]
900   "TARGET_NEON"
901   "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
902   [(set (attr "neon_type")
903       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
904                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
905                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
906                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
907                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
908                                   (if_then_else
909                                     (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
910                                     (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
911                                     (const_string "neon_mul_qqq_8_16_32_ddd_32"))
912                                   (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
913                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")
914                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
915 )
916
917 (define_insn "ior<mode>3"
918   [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
919         (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
920                  (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
921   "TARGET_NEON"
922 {
923   switch (which_alternative)
924     {
925     case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
926     case 1: return neon_output_logic_immediate ("vorr", &operands[2],
927                      <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));
928     default: gcc_unreachable ();
929     }
930 }
931   [(set_attr "neon_type" "neon_int_1")]
932 )
933
934 (define_insn "iordi3_neon"
935   [(set (match_operand:DI 0 "s_register_operand" "=w,w")
936         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
937                     (match_operand:DI 2 "neon_logic_op2" "w,Dl")]
938                     UNSPEC_VORR))]
939   "TARGET_NEON"
940 {
941   switch (which_alternative)
942     {
943     case 0: return "vorr\t%P0, %P1, %P2";
944     case 1: return neon_output_logic_immediate ("vorr", &operands[2],
945                      DImode, 0, VALID_NEON_QREG_MODE (DImode));
946     default: gcc_unreachable ();
947     }
948 }
949   [(set_attr "neon_type" "neon_int_1")]
950 )
951
952 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
953 ;; vorr. We support the pseudo-instruction vand instead, because that
954 ;; corresponds to the canonical form the middle-end expects to use for
955 ;; immediate bitwise-ANDs.
956
957 (define_insn "and<mode>3"
958   [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
959         (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
960                  (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
961   "TARGET_NEON"
962 {
963   switch (which_alternative)
964     {
965     case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
966     case 1: return neon_output_logic_immediate ("vand", &operands[2],
967                      <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));
968     default: gcc_unreachable ();
969     }
970 }
971   [(set_attr "neon_type" "neon_int_1")]
972 )
973
974 (define_insn "anddi3_neon"
975   [(set (match_operand:DI 0 "s_register_operand" "=w,w")
976         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
977                     (match_operand:DI 2 "neon_inv_logic_op2" "w,DL")]
978                     UNSPEC_VAND))]
979   "TARGET_NEON"
980 {
981   switch (which_alternative)
982     {
983     case 0: return "vand\t%P0, %P1, %P2";
984     case 1: return neon_output_logic_immediate ("vand", &operands[2],
985                      DImode, 1, VALID_NEON_QREG_MODE (DImode));
986     default: gcc_unreachable ();
987     }
988 }
989   [(set_attr "neon_type" "neon_int_1")]
990 )
991
992 (define_insn "orn<mode>3_neon"
993   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
994         (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
995                  (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))]
996   "TARGET_NEON"
997   "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
998   [(set_attr "neon_type" "neon_int_1")]
999 )
1000
1001 (define_insn "orndi3_neon"
1002   [(set (match_operand:DI 0 "s_register_operand" "=w")
1003         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1004                     (match_operand:DI 2 "s_register_operand" "w")]
1005                     UNSPEC_VORN))]
1006   "TARGET_NEON"
1007   "vorn\t%P0, %P1, %P2"
1008   [(set_attr "neon_type" "neon_int_1")]
1009 )
1010
1011 (define_insn "bic<mode>3_neon"
1012   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1013         (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
1014                   (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))]
1015   "TARGET_NEON"
1016   "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1017   [(set_attr "neon_type" "neon_int_1")]
1018 )
1019
1020 (define_insn "bicdi3_neon"
1021   [(set (match_operand:DI 0 "s_register_operand" "=w")
1022         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1023                      (match_operand:DI 2 "s_register_operand" "w")]
1024                     UNSPEC_VBIC))]
1025   "TARGET_NEON"
1026   "vbic\t%P0, %P1, %P2"
1027   [(set_attr "neon_type" "neon_int_1")]
1028 )
1029
1030 (define_insn "xor<mode>3"
1031   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1032         (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
1033                  (match_operand:VDQ 2 "s_register_operand" "w")))]
1034   "TARGET_NEON"
1035   "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1036   [(set_attr "neon_type" "neon_int_1")]
1037 )
1038
1039 (define_insn "xordi3_neon"
1040   [(set (match_operand:DI 0 "s_register_operand" "=w")
1041         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1042                      (match_operand:DI 2 "s_register_operand" "w")]
1043                     UNSPEC_VEOR))]
1044   "TARGET_NEON"
1045   "veor\t%P0, %P1, %P2"
1046   [(set_attr "neon_type" "neon_int_1")]
1047 )
1048
1049 (define_insn "one_cmpl<mode>2"
1050   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1051         (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
1052   "TARGET_NEON"
1053   "vmvn\t%<V_reg>0, %<V_reg>1"
1054   [(set_attr "neon_type" "neon_int_1")]
1055 )
1056
1057 (define_insn "abs<mode>2"
1058   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1059         (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
1060   "TARGET_NEON"
1061   "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
1062   [(set (attr "neon_type")
1063       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1064                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1065                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1066                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1067                     (const_string "neon_int_3")))]
1068 )
1069
1070 (define_insn "neg<mode>2"
1071   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1072         (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
1073   "TARGET_NEON"
1074   "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
1075   [(set (attr "neon_type")
1076       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1077                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1078                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1079                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1080                     (const_string "neon_int_3")))]
1081 )
1082
1083 (define_insn "*umin<mode>3_neon"
1084   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1085         (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1086                     (match_operand:VDQIW 2 "s_register_operand" "w")))]
1087   "TARGET_NEON"
1088   "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1089   [(set_attr "neon_type" "neon_int_5")]
1090 )
1091
1092 (define_insn "*umax<mode>3_neon"
1093   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1094         (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1095                     (match_operand:VDQIW 2 "s_register_operand" "w")))]
1096   "TARGET_NEON"
1097   "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1098   [(set_attr "neon_type" "neon_int_5")]
1099 )
1100
1101 (define_insn "*smin<mode>3_neon"
1102   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1103         (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
1104                    (match_operand:VDQW 2 "s_register_operand" "w")))]
1105   "TARGET_NEON"
1106   "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1107   [(set (attr "neon_type")
1108       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1109                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1110                     (const_string "neon_int_5")))]
1111 )
1112
1113 (define_insn "*smax<mode>3_neon"
1114   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1115         (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
1116                    (match_operand:VDQW 2 "s_register_operand" "w")))]
1117   "TARGET_NEON"
1118   "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1119   [(set (attr "neon_type")
1120       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1121                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1122                     (const_string "neon_int_5")))]
1123 )
1124
1125 ; TODO: V2DI shifts are current disabled because there are bugs in the
1126 ; generic vectorizer code.  It ends up creating a V2DI constructor with
1127 ; SImode elements.
1128
1129 (define_insn "ashl<mode>3"
1130   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1131         (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1132                       (match_operand:VDQIW 2 "s_register_operand" "w")))]
1133   "TARGET_NEON"
1134   "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1135   [(set (attr "neon_type")
1136       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1137                     (const_string "neon_vshl_ddd")
1138                     (const_string "neon_shift_3")))]
1139 )
1140
1141 ; Used for implementing logical shift-right, which is a left-shift by a negative
1142 ; amount, with signed operands. This is essentially the same as ashl<mode>3
1143 ; above, but using an unspec in case GCC tries anything tricky with negative
1144 ; shift amounts.
1145
1146 (define_insn "ashl<mode>3_signed"
1147   [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1148         (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1149                       (match_operand:VDQI 2 "s_register_operand" "w")]
1150                      UNSPEC_ASHIFT_SIGNED))]
1151   "TARGET_NEON"
1152   "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1153   [(set (attr "neon_type")
1154       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1155                     (const_string "neon_vshl_ddd")
1156                     (const_string "neon_shift_3")))]
1157 )
1158
1159 ; Used for implementing logical shift-right, which is a left-shift by a negative
1160 ; amount, with unsigned operands.
1161
1162 (define_insn "ashl<mode>3_unsigned"
1163   [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1164         (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1165                       (match_operand:VDQI 2 "s_register_operand" "w")]
1166                      UNSPEC_ASHIFT_UNSIGNED))]
1167   "TARGET_NEON"
1168   "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1169   [(set (attr "neon_type")
1170       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1171                     (const_string "neon_vshl_ddd")
1172                     (const_string "neon_shift_3")))]
1173 )
1174
1175 (define_expand "ashr<mode>3"
1176   [(set (match_operand:VDQIW 0 "s_register_operand" "")
1177         (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1178                         (match_operand:VDQIW 2 "s_register_operand" "")))]
1179   "TARGET_NEON"
1180 {
1181   rtx neg = gen_reg_rtx (<MODE>mode);
1182
1183   emit_insn (gen_neg<mode>2 (neg, operands[2]));
1184   emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1185
1186   DONE;
1187 })
1188
1189 (define_expand "lshr<mode>3"
1190   [(set (match_operand:VDQIW 0 "s_register_operand" "")
1191         (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1192                         (match_operand:VDQIW 2 "s_register_operand" "")))]
1193   "TARGET_NEON"
1194 {
1195   rtx neg = gen_reg_rtx (<MODE>mode);
1196
1197   emit_insn (gen_neg<mode>2 (neg, operands[2]));
1198   emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1199
1200   DONE;
1201 })
1202
1203 ;; Widening operations
1204
1205 (define_insn "widen_ssum<mode>3"
1206   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1207         (plus:<V_widen> (sign_extend:<V_widen>
1208                           (match_operand:VW 1 "s_register_operand" "%w"))
1209                         (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1210   "TARGET_NEON"
1211   "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1212   [(set_attr "neon_type" "neon_int_3")]
1213 )
1214
1215 (define_insn "widen_usum<mode>3"
1216   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1217         (plus:<V_widen> (zero_extend:<V_widen>
1218                           (match_operand:VW 1 "s_register_operand" "%w"))
1219                         (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1220   "TARGET_NEON"
1221   "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1222   [(set_attr "neon_type" "neon_int_3")]
1223 )
1224
1225 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1226 ;; shift-count granularity. That's good enough for the middle-end's current
1227 ;; needs.
1228
1229 (define_expand "vec_shr_<mode>"
1230   [(match_operand:VDQ 0 "s_register_operand" "")
1231    (match_operand:VDQ 1 "s_register_operand" "")
1232    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1233   "TARGET_NEON"
1234 {
1235   rtx zero_reg;
1236   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1237   const int width = GET_MODE_BITSIZE (<MODE>mode);
1238   const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1239   rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1240     (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1241
1242   if (num_bits == width)
1243     {
1244       emit_move_insn (operands[0], operands[1]);
1245       DONE;
1246     }
1247
1248   zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1249   operands[0] = gen_lowpart (bvecmode, operands[0]);
1250   operands[1] = gen_lowpart (bvecmode, operands[1]);
1251
1252   emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1253                       GEN_INT (num_bits / BITS_PER_UNIT)));
1254   DONE;
1255 })
1256
1257 (define_expand "vec_shl_<mode>"
1258   [(match_operand:VDQ 0 "s_register_operand" "")
1259    (match_operand:VDQ 1 "s_register_operand" "")
1260    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1261   "TARGET_NEON"
1262 {
1263   rtx zero_reg;
1264   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1265   const int width = GET_MODE_BITSIZE (<MODE>mode);
1266   const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1267   rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1268     (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1269
1270   if (num_bits == 0)
1271     {
1272       emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1273       DONE;
1274     }
1275
1276   num_bits = width - num_bits;
1277
1278   zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1279   operands[0] = gen_lowpart (bvecmode, operands[0]);
1280   operands[1] = gen_lowpart (bvecmode, operands[1]);
1281
1282   emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1283                       GEN_INT (num_bits / BITS_PER_UNIT)));
1284   DONE;
1285 })
1286
1287 ;; Helpers for quad-word reduction operations
1288
1289 ; Add (or smin, smax...) the low N/2 elements of the N-element vector
1290 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1291 ; N/2-element vector.
1292
1293 (define_insn "quad_halves_<code>v4si"
1294   [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1295         (vqh_ops:V2SI
1296           (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1297                            (parallel [(const_int 0) (const_int 1)]))
1298           (vec_select:V2SI (match_dup 1)
1299                            (parallel [(const_int 2) (const_int 3)]))))]
1300   "TARGET_NEON"
1301   "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
1302   [(set_attr "vqh_mnem" "<VQH_mnem>")
1303    (set (attr "neon_type")
1304       (if_then_else (eq_attr "vqh_mnem" "vadd")
1305                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1306 )
1307
1308 (define_insn "quad_halves_<code>v4sf"
1309   [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1310         (vqhs_ops:V2SF
1311           (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1312                            (parallel [(const_int 0) (const_int 1)]))
1313           (vec_select:V2SF (match_dup 1)
1314                            (parallel [(const_int 2) (const_int 3)]))))]
1315   "TARGET_NEON"
1316   "<VQH_mnem>.f32\t%P0, %e1, %f1"
1317   [(set_attr "vqh_mnem" "<VQH_mnem>")
1318    (set (attr "neon_type")
1319       (if_then_else (eq_attr "vqh_mnem" "vadd")
1320                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1321 )
1322
1323 (define_insn "quad_halves_<code>v8hi"
1324   [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1325         (vqh_ops:V4HI
1326           (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1327                            (parallel [(const_int 0) (const_int 1)
1328                                       (const_int 2) (const_int 3)]))
1329           (vec_select:V4HI (match_dup 1)
1330                            (parallel [(const_int 4) (const_int 5)
1331                                       (const_int 6) (const_int 7)]))))]
1332   "TARGET_NEON"
1333   "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
1334   [(set_attr "vqh_mnem" "<VQH_mnem>")
1335    (set (attr "neon_type")
1336       (if_then_else (eq_attr "vqh_mnem" "vadd")
1337                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1338 )
1339
1340 (define_insn "quad_halves_<code>v16qi"
1341   [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1342         (vqh_ops:V8QI
1343           (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1344                            (parallel [(const_int 0) (const_int 1)
1345                                       (const_int 2) (const_int 3)
1346                                       (const_int 4) (const_int 5)
1347                                       (const_int 6) (const_int 7)]))
1348           (vec_select:V8QI (match_dup 1)
1349                            (parallel [(const_int 8) (const_int 9)
1350                                       (const_int 10) (const_int 11)
1351                                       (const_int 12) (const_int 13)
1352                                       (const_int 14) (const_int 15)]))))]
1353   "TARGET_NEON"
1354   "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
1355   [(set_attr "vqh_mnem" "<VQH_mnem>")
1356    (set (attr "neon_type")
1357       (if_then_else (eq_attr "vqh_mnem" "vadd")
1358                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1359 )
1360
1361 ; FIXME: We wouldn't need the following insns if we could write subregs of
1362 ; vector registers. Make an attempt at removing unnecessary moves, though
1363 ; we're really at the mercy of the register allocator.
1364
1365 (define_insn "move_lo_quad_v4si"
1366   [(set (match_operand:V4SI 0 "s_register_operand" "+w")
1367         (vec_concat:V4SI
1368           (match_operand:V2SI 1 "s_register_operand" "w")
1369           (vec_select:V2SI (match_dup 0)
1370                            (parallel [(const_int 2) (const_int 3)]))))]
1371   "TARGET_NEON"
1372 {
1373   int dest = REGNO (operands[0]);
1374   int src = REGNO (operands[1]);
1375
1376   if (dest != src)
1377     return "vmov\t%e0, %P1";
1378   else
1379     return "";
1380 }
1381   [(set_attr "neon_type" "neon_bp_simple")]
1382 )
1383
1384 (define_insn "move_lo_quad_v4sf"
1385   [(set (match_operand:V4SF 0 "s_register_operand" "+w")
1386         (vec_concat:V4SF
1387           (match_operand:V2SF 1 "s_register_operand" "w")
1388           (vec_select:V2SF (match_dup 0)
1389                            (parallel [(const_int 2) (const_int 3)]))))]
1390   "TARGET_NEON"
1391 {
1392   int dest = REGNO (operands[0]);
1393   int src = REGNO (operands[1]);
1394
1395   if (dest != src)
1396     return "vmov\t%e0, %P1";
1397   else
1398     return "";
1399 }
1400   [(set_attr "neon_type" "neon_bp_simple")]
1401 )
1402
1403 (define_insn "move_lo_quad_v8hi"
1404   [(set (match_operand:V8HI 0 "s_register_operand" "+w")
1405         (vec_concat:V8HI
1406           (match_operand:V4HI 1 "s_register_operand" "w")
1407           (vec_select:V4HI (match_dup 0)
1408                            (parallel [(const_int 4) (const_int 5)
1409                                       (const_int 6) (const_int 7)]))))]
1410   "TARGET_NEON"
1411 {
1412   int dest = REGNO (operands[0]);
1413   int src = REGNO (operands[1]);
1414
1415   if (dest != src)
1416     return "vmov\t%e0, %P1";
1417   else
1418     return "";
1419 }
1420   [(set_attr "neon_type" "neon_bp_simple")]
1421 )
1422
1423 (define_insn "move_lo_quad_v16qi"
1424   [(set (match_operand:V16QI 0 "s_register_operand" "+w")
1425         (vec_concat:V16QI
1426           (match_operand:V8QI 1 "s_register_operand" "w")
1427           (vec_select:V8QI (match_dup 0)
1428                            (parallel [(const_int 8)  (const_int 9)
1429                                       (const_int 10) (const_int 11)
1430                                       (const_int 12) (const_int 13)
1431                                       (const_int 14) (const_int 15)]))))]
1432   "TARGET_NEON"
1433 {
1434   int dest = REGNO (operands[0]);
1435   int src = REGNO (operands[1]);
1436
1437   if (dest != src)
1438     return "vmov\t%e0, %P1";
1439   else
1440     return "";
1441 }
1442   [(set_attr "neon_type" "neon_bp_simple")]
1443 )
1444
1445 ;; Reduction operations
1446
1447 (define_expand "reduc_splus_<mode>"
1448   [(match_operand:VD 0 "s_register_operand" "")
1449    (match_operand:VD 1 "s_register_operand" "")]
1450   "TARGET_NEON"
1451 {
1452   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1453                         &gen_neon_vpadd_internal<mode>);
1454   DONE;
1455 })
1456
1457 (define_expand "reduc_splus_<mode>"
1458   [(match_operand:VQ 0 "s_register_operand" "")
1459    (match_operand:VQ 1 "s_register_operand" "")]
1460   "TARGET_NEON"
1461 {
1462   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1463   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1464
1465   emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
1466   emit_insn (gen_reduc_splus_<V_half> (res_d, step1));
1467   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1468
1469   DONE;
1470 })
1471
1472 (define_insn "reduc_splus_v2di"
1473   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1474         (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1475                      UNSPEC_VPADD))]
1476   "TARGET_NEON"
1477   "vadd.i64\t%e0, %e1, %f1"
1478   [(set_attr "neon_type" "neon_int_1")]
1479 )
1480
1481 ;; NEON does not distinguish between signed and unsigned addition except on
1482 ;; widening operations.
1483 (define_expand "reduc_uplus_<mode>"
1484   [(match_operand:VDQI 0 "s_register_operand" "")
1485    (match_operand:VDQI 1 "s_register_operand" "")]
1486   "TARGET_NEON"
1487 {
1488   emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
1489   DONE;
1490 })
1491
1492 (define_expand "reduc_smin_<mode>"
1493   [(match_operand:VD 0 "s_register_operand" "")
1494    (match_operand:VD 1 "s_register_operand" "")]
1495   "TARGET_NEON"
1496 {
1497   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1498                         &gen_neon_vpsmin<mode>);
1499   DONE;
1500 })
1501
1502 (define_expand "reduc_smin_<mode>"
1503   [(match_operand:VQ 0 "s_register_operand" "")
1504    (match_operand:VQ 1 "s_register_operand" "")]
1505   "TARGET_NEON"
1506 {
1507   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1508   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1509
1510   emit_insn (gen_quad_halves_smin<mode> (step1, operands[1]));
1511   emit_insn (gen_reduc_smin_<V_half> (res_d, step1));
1512   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1513
1514   DONE;
1515 })
1516
1517 (define_expand "reduc_smax_<mode>"
1518   [(match_operand:VD 0 "s_register_operand" "")
1519    (match_operand:VD 1 "s_register_operand" "")]
1520   "TARGET_NEON"
1521 {
1522   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1523                         &gen_neon_vpsmax<mode>);
1524   DONE;
1525 })
1526
1527 (define_expand "reduc_smax_<mode>"
1528   [(match_operand:VQ 0 "s_register_operand" "")
1529    (match_operand:VQ 1 "s_register_operand" "")]
1530   "TARGET_NEON"
1531 {
1532   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1533   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1534
1535   emit_insn (gen_quad_halves_smax<mode> (step1, operands[1]));
1536   emit_insn (gen_reduc_smax_<V_half> (res_d, step1));
1537   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1538
1539   DONE;
1540 })
1541
1542 (define_expand "reduc_umin_<mode>"
1543   [(match_operand:VDI 0 "s_register_operand" "")
1544    (match_operand:VDI 1 "s_register_operand" "")]
1545   "TARGET_NEON"
1546 {
1547   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1548                         &gen_neon_vpumin<mode>);
1549   DONE;
1550 })
1551
1552 (define_expand "reduc_umin_<mode>"
1553   [(match_operand:VQI 0 "s_register_operand" "")
1554    (match_operand:VQI 1 "s_register_operand" "")]
1555   "TARGET_NEON"
1556 {
1557   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1558   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1559
1560   emit_insn (gen_quad_halves_umin<mode> (step1, operands[1]));
1561   emit_insn (gen_reduc_umin_<V_half> (res_d, step1));
1562   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1563
1564   DONE;
1565 })
1566
1567 (define_expand "reduc_umax_<mode>"
1568   [(match_operand:VDI 0 "s_register_operand" "")
1569    (match_operand:VDI 1 "s_register_operand" "")]
1570   "TARGET_NEON"
1571 {
1572   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1573                         &gen_neon_vpumax<mode>);
1574   DONE;
1575 })
1576
1577 (define_expand "reduc_umax_<mode>"
1578   [(match_operand:VQI 0 "s_register_operand" "")
1579    (match_operand:VQI 1 "s_register_operand" "")]
1580   "TARGET_NEON"
1581 {
1582   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1583   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1584
1585   emit_insn (gen_quad_halves_umax<mode> (step1, operands[1]));
1586   emit_insn (gen_reduc_umax_<V_half> (res_d, step1));
1587   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1588
1589   DONE;
1590 })
1591
1592 (define_insn "neon_vpadd_internal<mode>"
1593   [(set (match_operand:VD 0 "s_register_operand" "=w")
1594         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1595                     (match_operand:VD 2 "s_register_operand" "w")]
1596                    UNSPEC_VPADD))]
1597   "TARGET_NEON"
1598   "vpadd.<V_if_elem>\t%P0, %P1, %P2"
1599   ;; Assume this schedules like vadd.
1600   [(set (attr "neon_type")
1601       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1602                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1603                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1604                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1605                     (const_string "neon_int_1")))]
1606 )
1607
1608 (define_insn "neon_vpsmin<mode>"
1609   [(set (match_operand:VD 0 "s_register_operand" "=w")
1610         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1611                     (match_operand:VD 2 "s_register_operand" "w")]
1612                    UNSPEC_VPSMIN))]
1613   "TARGET_NEON"
1614   "vpmin.<V_s_elem>\t%P0, %P1, %P2"
1615   ;; Assume this schedules like vmin.
1616   [(set (attr "neon_type")
1617       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1618                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1619                     (const_string "neon_int_5")))]
1620 )
1621
1622 (define_insn "neon_vpsmax<mode>"
1623   [(set (match_operand:VD 0 "s_register_operand" "=w")
1624         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1625                     (match_operand:VD 2 "s_register_operand" "w")]
1626                    UNSPEC_VPSMAX))]
1627   "TARGET_NEON"
1628   "vpmax.<V_s_elem>\t%P0, %P1, %P2"
1629   ;; Assume this schedules like vmax.
1630   [(set (attr "neon_type")
1631       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1632                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1633                     (const_string "neon_int_5")))]
1634 )
1635
1636 (define_insn "neon_vpumin<mode>"
1637   [(set (match_operand:VDI 0 "s_register_operand" "=w")
1638         (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1639                      (match_operand:VDI 2 "s_register_operand" "w")]
1640                    UNSPEC_VPUMIN))]
1641   "TARGET_NEON"
1642   "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1643   ;; Assume this schedules like umin.
1644   [(set_attr "neon_type" "neon_int_5")]
1645 )
1646
1647 (define_insn "neon_vpumax<mode>"
1648   [(set (match_operand:VDI 0 "s_register_operand" "=w")
1649         (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1650                      (match_operand:VDI 2 "s_register_operand" "w")]
1651                    UNSPEC_VPUMAX))]
1652   "TARGET_NEON"
1653   "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1654   ;; Assume this schedules like umax.
1655   [(set_attr "neon_type" "neon_int_5")]
1656 )
1657
1658 ;; Saturating arithmetic
1659
1660 ; NOTE: Neon supports many more saturating variants of instructions than the
1661 ; following, but these are all GCC currently understands.
1662 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1663 ; yet either, although these patterns may be used by intrinsics when they're
1664 ; added.
1665
1666 (define_insn "*ss_add<mode>_neon"
1667   [(set (match_operand:VD 0 "s_register_operand" "=w")
1668        (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1669                    (match_operand:VD 2 "s_register_operand" "w")))]
1670   "TARGET_NEON"
1671   "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1672   [(set_attr "neon_type" "neon_int_4")]
1673 )
1674
1675 (define_insn "*us_add<mode>_neon"
1676   [(set (match_operand:VD 0 "s_register_operand" "=w")
1677        (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1678                    (match_operand:VD 2 "s_register_operand" "w")))]
1679   "TARGET_NEON"
1680   "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1681   [(set_attr "neon_type" "neon_int_4")]
1682 )
1683
1684 (define_insn "*ss_sub<mode>_neon"
1685   [(set (match_operand:VD 0 "s_register_operand" "=w")
1686        (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1687                     (match_operand:VD 2 "s_register_operand" "w")))]
1688   "TARGET_NEON"
1689   "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1690   [(set_attr "neon_type" "neon_int_5")]
1691 )
1692
1693 (define_insn "*us_sub<mode>_neon"
1694   [(set (match_operand:VD 0 "s_register_operand" "=w")
1695        (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1696                     (match_operand:VD 2 "s_register_operand" "w")))]
1697   "TARGET_NEON"
1698   "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1699   [(set_attr "neon_type" "neon_int_5")]
1700 )
1701
1702 ;; Patterns for builtins.
1703
1704 ; good for plain vadd, vaddq.
1705
1706 (define_insn "neon_vadd<mode>"
1707   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1708         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1709                       (match_operand:VDQX 2 "s_register_operand" "w")
1710                       (match_operand:SI 3 "immediate_operand" "i")]
1711                      UNSPEC_VADD))]
1712   "TARGET_NEON"
1713   "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1714   [(set (attr "neon_type")
1715       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1716                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1717                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1718                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1719                     (const_string "neon_int_1")))]
1720 )
1721
1722 ; operand 3 represents in bits:
1723 ;  bit 0: signed (vs unsigned).
1724 ;  bit 1: rounding (vs none).
1725
1726 (define_insn "neon_vaddl<mode>"
1727   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1728         (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1729                            (match_operand:VDI 2 "s_register_operand" "w")
1730                            (match_operand:SI 3 "immediate_operand" "i")]
1731                           UNSPEC_VADDL))]
1732   "TARGET_NEON"
1733   "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1734   [(set_attr "neon_type" "neon_int_3")]
1735 )
1736
1737 (define_insn "neon_vaddw<mode>"
1738   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1739         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1740                            (match_operand:VDI 2 "s_register_operand" "w")
1741                            (match_operand:SI 3 "immediate_operand" "i")]
1742                           UNSPEC_VADDW))]
1743   "TARGET_NEON"
1744   "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1745   [(set_attr "neon_type" "neon_int_2")]
1746 )
1747
1748 ; vhadd and vrhadd.
1749
1750 (define_insn "neon_vhadd<mode>"
1751   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1752         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1753                        (match_operand:VDQIW 2 "s_register_operand" "w")
1754                        (match_operand:SI 3 "immediate_operand" "i")]
1755                       UNSPEC_VHADD))]
1756   "TARGET_NEON"
1757   "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1758   [(set_attr "neon_type" "neon_int_4")]
1759 )
1760
1761 (define_insn "neon_vqadd<mode>"
1762   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1763         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1764                        (match_operand:VDQIX 2 "s_register_operand" "w")
1765                        (match_operand:SI 3 "immediate_operand" "i")]
1766                      UNSPEC_VQADD))]
1767   "TARGET_NEON"
1768   "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1769   [(set_attr "neon_type" "neon_int_4")]
1770 )
1771
1772 (define_insn "neon_vaddhn<mode>"
1773   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
1774         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
1775                             (match_operand:VN 2 "s_register_operand" "w")
1776                             (match_operand:SI 3 "immediate_operand" "i")]
1777                            UNSPEC_VADDHN))]
1778   "TARGET_NEON"
1779   "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1780   [(set_attr "neon_type" "neon_int_4")]
1781 )
1782
1783 (define_insn "neon_vmul<mode>"
1784   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1785         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1786                       (match_operand:VDQW 2 "s_register_operand" "w")
1787                       (match_operand:SI 3 "immediate_operand" "i")]
1788                      UNSPEC_VMUL))]
1789   "TARGET_NEON"
1790   "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1791   [(set (attr "neon_type")
1792       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1793                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1794                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1795                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1796                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1797                                   (if_then_else
1798                                     (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1799                                     (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1800                                     (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1801                                   (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1802                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")
1803                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
1804 )
1805
1806 (define_insn "neon_vmla<mode>"
1807   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1808         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
1809                       (match_operand:VDQW 2 "s_register_operand" "w")
1810                       (match_operand:VDQW 3 "s_register_operand" "w")
1811                      (match_operand:SI 4 "immediate_operand" "i")]
1812                     UNSPEC_VMLA))]
1813   "TARGET_NEON"
1814   "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1815   [(set (attr "neon_type")
1816       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1817                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1818                                   (const_string "neon_fp_vmla_ddd")
1819                                   (const_string "neon_fp_vmla_qqq"))
1820                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1821                                   (if_then_else
1822                                     (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1823                                     (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1824                                     (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1825                                   (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1826                                     (const_string "neon_mla_qqq_8_16")
1827                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1828 )
1829
1830 (define_insn "neon_vmlal<mode>"
1831   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1832         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1833                            (match_operand:VW 2 "s_register_operand" "w")
1834                            (match_operand:VW 3 "s_register_operand" "w")
1835                            (match_operand:SI 4 "immediate_operand" "i")]
1836                           UNSPEC_VMLAL))]
1837   "TARGET_NEON"
1838   "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1839   [(set (attr "neon_type")
1840      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1841                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1842                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1843 )
1844
1845 (define_insn "neon_vmls<mode>"
1846   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1847         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
1848                       (match_operand:VDQW 2 "s_register_operand" "w")
1849                       (match_operand:VDQW 3 "s_register_operand" "w")
1850                      (match_operand:SI 4 "immediate_operand" "i")]
1851                     UNSPEC_VMLS))]
1852   "TARGET_NEON"
1853   "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1854   [(set (attr "neon_type")
1855       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1856                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1857                                   (const_string "neon_fp_vmla_ddd")
1858                                   (const_string "neon_fp_vmla_qqq"))
1859                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1860                                   (if_then_else
1861                                     (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                                   (if_then_else
1865                                     (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1866                                     (const_string "neon_mla_qqq_8_16")
1867                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1868 )
1869
1870 (define_insn "neon_vmlsl<mode>"
1871   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1872         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1873                            (match_operand:VW 2 "s_register_operand" "w")
1874                            (match_operand:VW 3 "s_register_operand" "w")
1875                            (match_operand:SI 4 "immediate_operand" "i")]
1876                           UNSPEC_VMLSL))]
1877   "TARGET_NEON"
1878   "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1879   [(set (attr "neon_type")
1880      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1881                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1882                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1883 )
1884
1885 (define_insn "neon_vqdmulh<mode>"
1886   [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
1887         (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
1888                        (match_operand:VMDQI 2 "s_register_operand" "w")
1889                        (match_operand:SI 3 "immediate_operand" "i")]
1890                       UNSPEC_VQDMULH))]
1891   "TARGET_NEON"
1892   "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1893   [(set (attr "neon_type")
1894      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1895         (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1896                       (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1897                       (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1898         (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1899                       (const_string "neon_mul_qqq_8_16_32_ddd_32")
1900                       (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
1901 )
1902
1903 (define_insn "neon_vqdmlal<mode>"
1904   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1905         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1906                            (match_operand:VMDI 2 "s_register_operand" "w")
1907                            (match_operand:VMDI 3 "s_register_operand" "w")
1908                            (match_operand:SI 4 "immediate_operand" "i")]
1909                           UNSPEC_VQDMLAL))]
1910   "TARGET_NEON"
1911   "vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
1912   [(set (attr "neon_type")
1913      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1914                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1915                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1916 )
1917
1918 (define_insn "neon_vqdmlsl<mode>"
1919   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1920         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1921                            (match_operand:VMDI 2 "s_register_operand" "w")
1922                            (match_operand:VMDI 3 "s_register_operand" "w")
1923                            (match_operand:SI 4 "immediate_operand" "i")]
1924                           UNSPEC_VQDMLSL))]
1925   "TARGET_NEON"
1926   "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
1927   [(set (attr "neon_type")
1928      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1929                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1930                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1931 )
1932
1933 (define_insn "neon_vmull<mode>"
1934   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1935         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
1936                            (match_operand:VW 2 "s_register_operand" "w")
1937                            (match_operand:SI 3 "immediate_operand" "i")]
1938                           UNSPEC_VMULL))]
1939   "TARGET_NEON"
1940   "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1941   [(set (attr "neon_type")
1942      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1943                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1944                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
1945 )
1946
1947 (define_insn "neon_vqdmull<mode>"
1948   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1949         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
1950                            (match_operand:VMDI 2 "s_register_operand" "w")
1951                            (match_operand:SI 3 "immediate_operand" "i")]
1952                           UNSPEC_VQDMULL))]
1953   "TARGET_NEON"
1954   "vqdmull.<V_s_elem>\t%q0, %P1, %P2"
1955   [(set (attr "neon_type")
1956      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1957                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1958                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
1959 )
1960
1961 (define_insn "neon_vsub<mode>"
1962   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1963         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1964                       (match_operand:VDQX 2 "s_register_operand" "w")
1965                       (match_operand:SI 3 "immediate_operand" "i")]
1966                      UNSPEC_VSUB))]
1967   "TARGET_NEON"
1968   "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1969   [(set (attr "neon_type")
1970       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1971                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1972                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1973                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1974                     (const_string "neon_int_2")))]
1975 )
1976
1977 (define_insn "neon_vsubl<mode>"
1978   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1979         (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1980                            (match_operand:VDI 2 "s_register_operand" "w")
1981                            (match_operand:SI 3 "immediate_operand" "i")]
1982                           UNSPEC_VSUBL))]
1983   "TARGET_NEON"
1984   "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1985   [(set_attr "neon_type" "neon_int_2")]
1986 )
1987
1988 (define_insn "neon_vsubw<mode>"
1989   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1990         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1991                            (match_operand:VDI 2 "s_register_operand" "w")
1992                            (match_operand:SI 3 "immediate_operand" "i")]
1993                           UNSPEC_VSUBW))]
1994   "TARGET_NEON"
1995   "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1996   [(set_attr "neon_type" "neon_int_2")]
1997 )
1998
1999 (define_insn "neon_vqsub<mode>"
2000   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2001         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2002                        (match_operand:VDQIX 2 "s_register_operand" "w")
2003                        (match_operand:SI 3 "immediate_operand" "i")]
2004                       UNSPEC_VQSUB))]
2005   "TARGET_NEON"
2006   "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2007   [(set_attr "neon_type" "neon_int_5")]
2008 )
2009
2010 (define_insn "neon_vhsub<mode>"
2011   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2012         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2013                        (match_operand:VDQIW 2 "s_register_operand" "w")
2014                        (match_operand:SI 3 "immediate_operand" "i")]
2015                       UNSPEC_VHSUB))]
2016   "TARGET_NEON"
2017   "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2018   [(set_attr "neon_type" "neon_int_5")]
2019 )
2020
2021 (define_insn "neon_vsubhn<mode>"
2022   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2023         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2024                             (match_operand:VN 2 "s_register_operand" "w")
2025                             (match_operand:SI 3 "immediate_operand" "i")]
2026                            UNSPEC_VSUBHN))]
2027   "TARGET_NEON"
2028   "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2029   [(set_attr "neon_type" "neon_int_4")]
2030 )
2031
2032 (define_insn "neon_vceq<mode>"
2033   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2034         (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2035                                 (match_operand:VDQW 2 "s_register_operand" "w")
2036                                 (match_operand:SI 3 "immediate_operand" "i")]
2037                                UNSPEC_VCEQ))]
2038   "TARGET_NEON"
2039   "vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2040   [(set (attr "neon_type")
2041       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2042                     (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2043                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2044                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2045                     (const_string "neon_int_5")))]
2046 )
2047
2048 (define_insn "neon_vcge<mode>"
2049   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2050         (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2051                                 (match_operand:VDQW 2 "s_register_operand" "w")
2052                                 (match_operand:SI 3 "immediate_operand" "i")]
2053                                UNSPEC_VCGE))]
2054   "TARGET_NEON"
2055   "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2056   [(set (attr "neon_type")
2057      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2058                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2059                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2060                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2061                    (const_string "neon_int_5")))]
2062 )
2063
2064 (define_insn "neon_vcgt<mode>"
2065   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2066         (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2067                                 (match_operand:VDQW 2 "s_register_operand" "w")
2068                                 (match_operand:SI 3 "immediate_operand" "i")]
2069                                UNSPEC_VCGT))]
2070   "TARGET_NEON"
2071   "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2072   [(set (attr "neon_type")
2073      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2074                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2075                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2076                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2077                    (const_string "neon_int_5")))]
2078 )
2079
2080 (define_insn "neon_vcage<mode>"
2081   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2082         (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2083                                 (match_operand:VCVTF 2 "s_register_operand" "w")
2084                                 (match_operand:SI 3 "immediate_operand" "i")]
2085                                UNSPEC_VCAGE))]
2086   "TARGET_NEON"
2087   "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2088   [(set (attr "neon_type")
2089      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2090                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2091                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2092 )
2093
2094 (define_insn "neon_vcagt<mode>"
2095   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2096         (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2097                                 (match_operand:VCVTF 2 "s_register_operand" "w")
2098                                 (match_operand:SI 3 "immediate_operand" "i")]
2099                                UNSPEC_VCAGT))]
2100   "TARGET_NEON"
2101   "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2102   [(set (attr "neon_type")
2103      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2104                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2105                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2106 )
2107
2108 (define_insn "neon_vtst<mode>"
2109   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2110         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2111                        (match_operand:VDQIW 2 "s_register_operand" "w")
2112                        (match_operand:SI 3 "immediate_operand" "i")]
2113                       UNSPEC_VTST))]
2114   "TARGET_NEON"
2115   "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2116   [(set_attr "neon_type" "neon_int_4")]
2117 )
2118
2119 (define_insn "neon_vabd<mode>"
2120   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2121         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2122                       (match_operand:VDQW 2 "s_register_operand" "w")
2123                       (match_operand:SI 3 "immediate_operand" "i")]
2124                      UNSPEC_VABD))]
2125   "TARGET_NEON"
2126   "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2127   [(set (attr "neon_type")
2128      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2129                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2130                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2131                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2132                    (const_string "neon_int_5")))]
2133 )
2134
2135 (define_insn "neon_vabdl<mode>"
2136   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2137         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2138                            (match_operand:VW 2 "s_register_operand" "w")
2139                            (match_operand:SI 3 "immediate_operand" "i")]
2140                           UNSPEC_VABDL))]
2141   "TARGET_NEON"
2142   "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2143   [(set_attr "neon_type" "neon_int_5")]
2144 )
2145
2146 (define_insn "neon_vaba<mode>"
2147   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2148         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "0")
2149                        (match_operand:VDQIW 2 "s_register_operand" "w")
2150                        (match_operand:VDQIW 3 "s_register_operand" "w")
2151                        (match_operand:SI 4 "immediate_operand" "i")]
2152                       UNSPEC_VABA))]
2153   "TARGET_NEON"
2154   "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2155   [(set (attr "neon_type")
2156      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2157                    (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2158 )
2159
2160 (define_insn "neon_vabal<mode>"
2161   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2162         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2163                            (match_operand:VW 2 "s_register_operand" "w")
2164                            (match_operand:VW 3 "s_register_operand" "w")
2165                            (match_operand:SI 4 "immediate_operand" "i")]
2166                           UNSPEC_VABAL))]
2167   "TARGET_NEON"
2168   "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2169   [(set_attr "neon_type" "neon_vaba")]
2170 )
2171
2172 (define_insn "neon_vmax<mode>"
2173   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2174         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2175                       (match_operand:VDQW 2 "s_register_operand" "w")
2176                       (match_operand:SI 3 "immediate_operand" "i")]
2177                      UNSPEC_VMAX))]
2178   "TARGET_NEON"
2179   "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2180   [(set (attr "neon_type")
2181     (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2182                   (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2183                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2184                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2185                   (const_string "neon_int_5")))]
2186 )
2187
2188 (define_insn "neon_vmin<mode>"
2189   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2190         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2191                       (match_operand:VDQW 2 "s_register_operand" "w")
2192                       (match_operand:SI 3 "immediate_operand" "i")]
2193                      UNSPEC_VMIN))]
2194   "TARGET_NEON"
2195   "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2196   [(set (attr "neon_type")
2197     (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2198                   (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2199                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2200                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2201                   (const_string "neon_int_5")))]
2202 )
2203
2204 (define_expand "neon_vpadd<mode>"
2205   [(match_operand:VD 0 "s_register_operand" "=w")
2206    (match_operand:VD 1 "s_register_operand" "w")
2207    (match_operand:VD 2 "s_register_operand" "w")
2208    (match_operand:SI 3 "immediate_operand" "i")]
2209   "TARGET_NEON"
2210 {
2211   emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
2212                                             operands[2]));
2213   DONE;
2214 })
2215
2216 (define_insn "neon_vpaddl<mode>"
2217   [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2218         (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w")
2219                                   (match_operand:SI 2 "immediate_operand" "i")]
2220                                  UNSPEC_VPADDL))]
2221   "TARGET_NEON"
2222   "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2223   ;; Assume this schedules like vaddl.
2224   [(set_attr "neon_type" "neon_int_3")]
2225 )
2226
2227 (define_insn "neon_vpadal<mode>"
2228   [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2229         (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0")
2230                                   (match_operand:VDQIW 2 "s_register_operand" "w")
2231                                   (match_operand:SI 3 "immediate_operand" "i")]
2232                                  UNSPEC_VPADAL))]
2233   "TARGET_NEON"
2234   "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
2235   ;; Assume this schedules like vpadd.
2236   [(set_attr "neon_type" "neon_int_1")]
2237 )
2238
2239 (define_insn "neon_vpmax<mode>"
2240   [(set (match_operand:VD 0 "s_register_operand" "=w")
2241         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2242                     (match_operand:VD 2 "s_register_operand" "w")
2243                     (match_operand:SI 3 "immediate_operand" "i")]
2244                    UNSPEC_VPMAX))]
2245   "TARGET_NEON"
2246   "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2247   ;; Assume this schedules like vmax.
2248   [(set (attr "neon_type")
2249     (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2250                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2251                   (const_string "neon_int_5")))]
2252 )
2253
2254 (define_insn "neon_vpmin<mode>"
2255   [(set (match_operand:VD 0 "s_register_operand" "=w")
2256         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2257                     (match_operand:VD 2 "s_register_operand" "w")
2258                     (match_operand:SI 3 "immediate_operand" "i")]
2259                    UNSPEC_VPMIN))]
2260   "TARGET_NEON"
2261   "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2262   ;; Assume this schedules like vmin.
2263   [(set (attr "neon_type")
2264     (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2265                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2266                   (const_string "neon_int_5")))]
2267 )
2268
2269 (define_insn "neon_vrecps<mode>"
2270   [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2271         (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2272                        (match_operand:VCVTF 2 "s_register_operand" "w")
2273                        (match_operand:SI 3 "immediate_operand" "i")]
2274                       UNSPEC_VRECPS))]
2275   "TARGET_NEON"
2276   "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2277   [(set (attr "neon_type")
2278       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2279                     (const_string "neon_fp_vrecps_vrsqrts_ddd")
2280                     (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2281 )
2282
2283 (define_insn "neon_vrsqrts<mode>"
2284   [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2285         (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2286                        (match_operand:VCVTF 2 "s_register_operand" "w")
2287                        (match_operand:SI 3 "immediate_operand" "i")]
2288                       UNSPEC_VRSQRTS))]
2289   "TARGET_NEON"
2290   "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2291   [(set (attr "neon_type")
2292       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2293                     (const_string "neon_fp_vrecps_vrsqrts_ddd")
2294                     (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2295 )
2296
2297 (define_insn "neon_vabs<mode>"
2298   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2299         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2300                       (match_operand:SI 2 "immediate_operand" "i")]
2301                      UNSPEC_VABS))]
2302   "TARGET_NEON"
2303   "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2304   [(set (attr "neon_type")
2305      (if_then_else (ior (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2306                         (ne (symbol_ref "<Is_float_mode>") (const_int 0)))
2307                    (if_then_else
2308                       (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2309                       (const_string "neon_fp_vadd_ddd_vabs_dd")
2310                       (const_string "neon_fp_vadd_qqq_vabs_qq"))
2311                    (const_string "neon_vqneg_vqabs")))]
2312 )
2313
2314 (define_insn "neon_vqabs<mode>"
2315   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2316         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2317                        (match_operand:SI 2 "immediate_operand" "i")]
2318                       UNSPEC_VQABS))]
2319   "TARGET_NEON"
2320   "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2321   [(set_attr "neon_type" "neon_vqneg_vqabs")]
2322 )
2323
2324 (define_expand "neon_vneg<mode>"
2325   [(match_operand:VDQW 0 "s_register_operand" "")
2326    (match_operand:VDQW 1 "s_register_operand" "")
2327    (match_operand:SI 2 "immediate_operand" "")]
2328   "TARGET_NEON"
2329 {
2330   emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
2331   DONE;
2332 })
2333
2334 (define_insn "neon_vqneg<mode>"
2335   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2336         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2337                        (match_operand:SI 2 "immediate_operand" "i")]
2338                       UNSPEC_VQNEG))]
2339   "TARGET_NEON"
2340   "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2341   [(set_attr "neon_type" "neon_vqneg_vqabs")]
2342 )
2343
2344 (define_insn "neon_vcls<mode>"
2345   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2346         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2347                        (match_operand:SI 2 "immediate_operand" "i")]
2348                       UNSPEC_VCLS))]
2349   "TARGET_NEON"
2350   "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2351   [(set_attr "neon_type" "neon_int_1")]
2352 )
2353
2354 (define_insn "neon_vclz<mode>"
2355   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2356         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2357                        (match_operand:SI 2 "immediate_operand" "i")]
2358                       UNSPEC_VCLZ))]
2359   "TARGET_NEON"
2360   "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2361   [(set_attr "neon_type" "neon_int_1")]
2362 )
2363
2364 (define_insn "neon_vcnt<mode>"
2365   [(set (match_operand:VE 0 "s_register_operand" "=w")
2366         (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
2367                     (match_operand:SI 2 "immediate_operand" "i")]
2368                    UNSPEC_VCNT))]
2369   "TARGET_NEON"
2370   "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2371   [(set_attr "neon_type" "neon_int_1")]
2372 )
2373
2374 (define_insn "neon_vrecpe<mode>"
2375   [(set (match_operand:V32 0 "s_register_operand" "=w")
2376         (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2377                      (match_operand:SI 2 "immediate_operand" "i")]
2378                     UNSPEC_VRECPE))]
2379   "TARGET_NEON"
2380   "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2381   [(set (attr "neon_type")
2382       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2383                     (const_string "neon_fp_vadd_ddd_vabs_dd")
2384                     (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2385 )
2386
2387 (define_insn "neon_vrsqrte<mode>"
2388   [(set (match_operand:V32 0 "s_register_operand" "=w")
2389         (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2390                      (match_operand:SI 2 "immediate_operand" "i")]
2391                     UNSPEC_VRSQRTE))]
2392   "TARGET_NEON"
2393   "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2394   [(set (attr "neon_type")
2395       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2396                     (const_string "neon_fp_vadd_ddd_vabs_dd")
2397                     (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2398 )
2399
2400 (define_expand "neon_vmvn<mode>"
2401   [(match_operand:VDQIW 0 "s_register_operand" "")
2402    (match_operand:VDQIW 1 "s_register_operand" "")
2403    (match_operand:SI 2 "immediate_operand" "")]
2404   "TARGET_NEON"
2405 {
2406   emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2407   DONE;
2408 })
2409
2410 (define_insn "neon_vget_lane<mode>_sext_internal"
2411   [(set (match_operand:SI 0 "s_register_operand" "=r")
2412         (sign_extend:SI
2413           (vec_select:<V_elem>
2414             (match_operand:VD 1 "s_register_operand" "w")
2415             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2416   "TARGET_NEON"
2417   "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]"
2418   [(set_attr "predicable" "yes")
2419    (set_attr "neon_type" "neon_bp_simple")]
2420 )
2421
2422 (define_insn "neon_vget_lane<mode>_zext_internal"
2423   [(set (match_operand:SI 0 "s_register_operand" "=r")
2424         (zero_extend:SI
2425           (vec_select:<V_elem>
2426             (match_operand:VD 1 "s_register_operand" "w")
2427             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2428   "TARGET_NEON"
2429   "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]"
2430   [(set_attr "predicable" "yes")
2431    (set_attr "neon_type" "neon_bp_simple")]
2432 )
2433
2434 (define_insn "neon_vget_lane<mode>_sext_internal"
2435   [(set (match_operand:SI 0 "s_register_operand" "=r")
2436         (sign_extend:SI
2437           (vec_select:<V_elem>
2438             (match_operand:VQ 1 "s_register_operand" "w")
2439             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2440   "TARGET_NEON"
2441 {
2442   rtx ops[3];
2443   int regno = REGNO (operands[1]);
2444   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2445   unsigned int elt = INTVAL (operands[2]);
2446
2447   ops[0] = operands[0];
2448   ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2449   ops[2] = GEN_INT (elt % halfelts);
2450   output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops);
2451
2452   return "";
2453 }
2454   [(set_attr "predicable" "yes")
2455    (set_attr "neon_type" "neon_bp_simple")]
2456 )
2457
2458 (define_insn "neon_vget_lane<mode>_zext_internal"
2459   [(set (match_operand:SI 0 "s_register_operand" "=r")
2460         (zero_extend:SI
2461           (vec_select:<V_elem>
2462             (match_operand:VQ 1 "s_register_operand" "w")
2463             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2464   "TARGET_NEON"
2465 {
2466   rtx ops[3];
2467   int regno = REGNO (operands[1]);
2468   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2469   unsigned int elt = INTVAL (operands[2]);
2470
2471   ops[0] = operands[0];
2472   ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2473   ops[2] = GEN_INT (elt % halfelts);
2474   output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops);
2475
2476   return "";
2477 }
2478   [(set_attr "predicable" "yes")
2479    (set_attr "neon_type" "neon_bp_simple")]
2480 )
2481
2482 (define_expand "neon_vget_lane<mode>"
2483   [(match_operand:<V_ext> 0 "s_register_operand" "")
2484    (match_operand:VDQW 1 "s_register_operand" "")
2485    (match_operand:SI 2 "immediate_operand" "")
2486    (match_operand:SI 3 "immediate_operand" "")]
2487   "TARGET_NEON"
2488 {
2489   HOST_WIDE_INT magic = INTVAL (operands[3]);
2490   rtx insn;
2491
2492   neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2493
2494   if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
2495     insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
2496   else
2497     {
2498       if ((magic & 1) != 0)
2499         insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2500                                                        operands[2]);
2501       else
2502         insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2503                                                        operands[2]);
2504     }
2505   emit_insn (insn);
2506   DONE;
2507 })
2508
2509 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2510 ; elements.
2511
2512 (define_insn "neon_vget_lanedi"
2513   [(set (match_operand:DI 0 "s_register_operand" "=r")
2514        (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
2515                    (match_operand:SI 2 "immediate_operand" "i")
2516                    (match_operand:SI 3 "immediate_operand" "i")]
2517                   UNSPEC_VGET_LANE))]
2518   "TARGET_NEON"
2519 {
2520   neon_lane_bounds (operands[2], 0, 1);
2521   return "vmov%?\t%Q0, %R0, %P1  @ di";
2522 }
2523   [(set_attr "predicable" "yes")
2524    (set_attr "neon_type" "neon_bp_simple")]
2525 )
2526
2527 (define_insn "neon_vget_lanev2di"
2528   [(set (match_operand:DI 0 "s_register_operand" "=r")
2529        (unspec:DI [(match_operand:V2DI 1 "s_register_operand" "w")
2530                    (match_operand:SI 2 "immediate_operand" "i")
2531                    (match_operand:SI 3 "immediate_operand" "i")]
2532                   UNSPEC_VGET_LANE))]
2533   "TARGET_NEON"
2534 {
2535   rtx ops[2];
2536   unsigned int regno = REGNO (operands[1]);
2537   unsigned int elt = INTVAL (operands[2]);
2538
2539   neon_lane_bounds (operands[2], 0, 2);
2540
2541   ops[0] = operands[0];
2542   ops[1] = gen_rtx_REG (DImode, regno + 2 * elt);
2543   output_asm_insn ("vmov%?\t%Q0, %R0, %P1  @ v2di", ops);
2544
2545   return "";
2546 }
2547   [(set_attr "predicable" "yes")
2548    (set_attr "neon_type" "neon_bp_simple")]
2549 )
2550
2551 (define_insn "neon_vset_lane<mode>"
2552   [(set (match_operand:VD 0 "s_register_operand" "=w")
2553         (unspec:VD [(match_operand:<V_elem> 1 "s_register_operand" "r")
2554                     (match_operand:VD 2 "s_register_operand" "0")
2555                     (match_operand:SI 3 "immediate_operand" "i")]
2556                    UNSPEC_VSET_LANE))]
2557   "TARGET_NEON"
2558 {
2559   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2560   return "vmov%?.<V_sz_elem>\t%P0[%c3], %1";
2561 }
2562   [(set_attr "predicable" "yes")
2563    (set_attr "neon_type" "neon_bp_simple")]
2564 )
2565
2566 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2567
2568 (define_insn "neon_vset_lanedi"
2569   [(set (match_operand:DI 0 "s_register_operand" "=w")
2570         (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")
2571                     (match_operand:DI 2 "s_register_operand" "0")
2572                     (match_operand:SI 3 "immediate_operand" "i")]
2573                    UNSPEC_VSET_LANE))]
2574   "TARGET_NEON"
2575 {
2576   neon_lane_bounds (operands[3], 0, 1);
2577   return "vmov%?\t%P0, %Q1, %R1  @ di";
2578 }
2579   [(set_attr "predicable" "yes")
2580    (set_attr "neon_type" "neon_bp_simple")]
2581 )
2582
2583 (define_insn "neon_vset_lane<mode>"
2584   [(set (match_operand:VQ 0 "s_register_operand" "=w")
2585         (unspec:VQ [(match_operand:<V_elem> 1 "s_register_operand" "r")
2586                     (match_operand:VQ 2 "s_register_operand" "0")
2587                     (match_operand:SI 3 "immediate_operand" "i")]
2588                    UNSPEC_VSET_LANE))]
2589   "TARGET_NEON"
2590 {
2591   rtx ops[4];
2592   unsigned int regno = REGNO (operands[0]);
2593   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2594   unsigned int elt = INTVAL (operands[3]);
2595
2596   neon_lane_bounds (operands[3], 0, halfelts * 2);
2597
2598   ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2599   ops[1] = operands[1];
2600   ops[2] = GEN_INT (elt % halfelts);
2601   output_asm_insn ("vmov%?.<V_sz_elem>\t%P0[%c2], %1", ops);
2602
2603   return "";
2604 }
2605   [(set_attr "predicable" "yes")
2606    (set_attr "neon_type" "neon_bp_simple")]
2607 )
2608
2609 (define_insn "neon_vset_lanev2di"
2610   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2611         (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")
2612                       (match_operand:V2DI 2 "s_register_operand" "0")
2613                       (match_operand:SI 3 "immediate_operand" "i")]
2614                    UNSPEC_VSET_LANE))]
2615   "TARGET_NEON"
2616 {
2617   rtx ops[2];
2618   unsigned int regno = REGNO (operands[0]);
2619   unsigned int elt = INTVAL (operands[3]);
2620
2621   neon_lane_bounds (operands[3], 0, 2);
2622
2623   ops[0] = gen_rtx_REG (DImode, regno + 2 * elt);
2624   ops[1] = operands[1];
2625   output_asm_insn ("vmov%?\t%P0, %Q1, %R1  @ v2di", ops);
2626
2627   return "";
2628 }
2629   [(set_attr "predicable" "yes")
2630    (set_attr "neon_type" "neon_bp_simple")]
2631 )
2632
2633 (define_expand "neon_vcreate<mode>"
2634   [(match_operand:VDX 0 "s_register_operand" "")
2635    (match_operand:DI 1 "general_operand" "")]
2636   "TARGET_NEON"
2637 {
2638   rtx src = gen_lowpart (<MODE>mode, operands[1]);
2639   emit_move_insn (operands[0], src);
2640   DONE;
2641 })
2642
2643 (define_insn "neon_vdup_n<mode>"
2644   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2645         (unspec:VDQW [(match_operand:<V_elem> 1 "s_register_operand" "r")]
2646                     UNSPEC_VDUP_N))]
2647   "TARGET_NEON"
2648   "vdup%?.<V_sz_elem>\t%<V_reg>0, %1"
2649   ;; Assume this schedules like vmov.
2650   [(set_attr "predicable" "yes")
2651    (set_attr "neon_type" "neon_bp_simple")]
2652 )
2653
2654 (define_insn "neon_vdup_ndi"
2655   [(set (match_operand:DI 0 "s_register_operand" "=w")
2656         (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
2657                    UNSPEC_VDUP_N))]
2658   "TARGET_NEON"
2659   "vmov%?\t%P0, %Q1, %R1"
2660   [(set_attr "predicable" "yes")
2661    (set_attr "neon_type" "neon_bp_simple")]
2662 )
2663
2664 (define_insn "neon_vdup_nv2di"
2665   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2666         (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")]
2667                      UNSPEC_VDUP_N))]
2668   "TARGET_NEON"
2669   "vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1"
2670   [(set_attr "predicable" "yes")
2671    (set_attr "length" "8")
2672    (set_attr "neon_type" "neon_bp_simple")]
2673 )
2674
2675 (define_insn "neon_vdup_lane<mode>"
2676   [(set (match_operand:VD 0 "s_register_operand" "=w")
2677         (unspec:VD [(match_operand:VD 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 (<MODE>mode));
2683   return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
2684 }
2685   ;; Assume this schedules like vmov.
2686   [(set_attr "neon_type" "neon_bp_simple")]
2687 )
2688
2689 (define_insn "neon_vdup_lane<mode>"
2690   [(set (match_operand:VQ 0 "s_register_operand" "=w")
2691         (unspec:VQ [(match_operand:<V_HALF> 1 "s_register_operand" "w")
2692                     (match_operand:SI 2 "immediate_operand" "i")]
2693                    UNSPEC_VDUP_LANE))]
2694   "TARGET_NEON"
2695 {
2696   neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode));
2697   return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
2698 }
2699   ;; Assume this schedules like vmov.
2700   [(set_attr "neon_type" "neon_bp_simple")]
2701 )
2702
2703 ; Scalar index is ignored, since only zero is valid here.
2704 (define_expand "neon_vdup_lanedi"
2705   [(set (match_operand:DI 0 "s_register_operand" "=w")
2706         (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
2707                     (match_operand:SI 2 "immediate_operand" "i")]
2708                    UNSPEC_VDUP_LANE))]
2709   "TARGET_NEON"
2710 {
2711   neon_lane_bounds (operands[2], 0, 1);
2712   emit_move_insn (operands[0], operands[1]);
2713   DONE;
2714 })
2715
2716 ; Likewise.
2717 (define_insn "neon_vdup_lanev2di"
2718   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2719         (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "w")
2720                       (match_operand:SI 2 "immediate_operand" "i")]
2721                      UNSPEC_VDUP_LANE))]
2722   "TARGET_NEON"
2723 {
2724   neon_lane_bounds (operands[2], 0, 1);
2725   return "vmov\t%e0, %P1\;vmov\t%f0, %P1";
2726 }
2727   [(set_attr "length" "8")
2728    (set_attr "neon_type" "neon_bp_simple")]
2729 )
2730
2731 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
2732 ;; dest vector.
2733 ;; FIXME: A different implementation of this builtin could make it much
2734 ;; more likely that we wouldn't actually need to output anything (we could make
2735 ;; it so that the reg allocator puts things in the right places magically
2736 ;; instead). Lack of subregs for vectors makes that tricky though, I think.
2737
2738 (define_insn "neon_vcombine<mode>"
2739   [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
2740         (unspec:<V_DOUBLE> [(match_operand:VDX 1 "s_register_operand" "w")
2741                             (match_operand:VDX 2 "s_register_operand" "w")]
2742                            UNSPEC_VCOMBINE))]
2743   "TARGET_NEON"
2744 {
2745   int dest = REGNO (operands[0]);
2746   int src1 = REGNO (operands[1]);
2747   int src2 = REGNO (operands[2]);
2748   rtx destlo;
2749
2750   if (src1 == dest && src2 == dest + 2)
2751     return "";
2752   else if (src2 == dest && src1 == dest + 2)
2753     /* Special case of reversed high/low parts.  */
2754     return "vswp\t%P1, %P2";
2755
2756   destlo = gen_rtx_REG (<MODE>mode, dest);
2757
2758   if (!reg_overlap_mentioned_p (operands[2], destlo))
2759     {
2760       /* Try to avoid unnecessary moves if part of the result is in the right
2761          place already.  */
2762       if (src1 != dest)
2763         output_asm_insn ("vmov\t%e0, %P1", operands);
2764       if (src2 != dest + 2)
2765         output_asm_insn ("vmov\t%f0, %P2", operands);
2766     }
2767   else
2768     {
2769       if (src2 != dest + 2)
2770         output_asm_insn ("vmov\t%f0, %P2", operands);
2771       if (src1 != dest)
2772         output_asm_insn ("vmov\t%e0, %P1", operands);
2773     }
2774
2775   return "";
2776 }
2777   ;; We set the neon_type attribute based on the vmov instructions above.
2778   [(set_attr "length" "8")
2779    (set_attr "neon_type" "neon_bp_simple")]
2780 )
2781
2782 (define_insn "neon_vget_high<mode>"
2783   [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
2784         (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
2785                          UNSPEC_VGET_HIGH))]
2786   "TARGET_NEON"
2787 {
2788   int dest = REGNO (operands[0]);
2789   int src = REGNO (operands[1]);
2790
2791   if (dest != src + 2)
2792     return "vmov\t%P0, %f1";
2793   else
2794     return "";
2795 }
2796   [(set_attr "neon_type" "neon_bp_simple")]
2797 )
2798
2799 (define_insn "neon_vget_low<mode>"
2800   [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
2801         (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
2802                          UNSPEC_VGET_LOW))]
2803   "TARGET_NEON"
2804 {
2805   int dest = REGNO (operands[0]);
2806   int src = REGNO (operands[1]);
2807
2808   if (dest != src)
2809     return "vmov\t%P0, %e1";
2810   else
2811     return "";
2812 }
2813   [(set_attr "neon_type" "neon_bp_simple")]
2814 )
2815
2816 (define_insn "neon_vcvt<mode>"
2817   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2818         (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
2819                            (match_operand:SI 2 "immediate_operand" "i")]
2820                           UNSPEC_VCVT))]
2821   "TARGET_NEON"
2822   "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
2823   [(set (attr "neon_type")
2824      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2825                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2826                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2827 )
2828
2829 (define_insn "neon_vcvt<mode>"
2830   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2831         (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
2832                            (match_operand:SI 2 "immediate_operand" "i")]
2833                           UNSPEC_VCVT))]
2834   "TARGET_NEON"
2835   "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
2836   [(set (attr "neon_type")
2837      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2838                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2839                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2840 )
2841
2842 (define_insn "neon_vcvt_n<mode>"
2843   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2844         (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
2845                            (match_operand:SI 2 "immediate_operand" "i")
2846                            (match_operand:SI 3 "immediate_operand" "i")]
2847                           UNSPEC_VCVT_N))]
2848   "TARGET_NEON"
2849 {
2850   neon_const_bounds (operands[2], 1, 33);
2851   return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
2852 }
2853   [(set (attr "neon_type")
2854      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2855                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2856                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2857 )
2858
2859 (define_insn "neon_vcvt_n<mode>"
2860   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2861         (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
2862                            (match_operand:SI 2 "immediate_operand" "i")
2863                            (match_operand:SI 3 "immediate_operand" "i")]
2864                           UNSPEC_VCVT_N))]
2865   "TARGET_NEON"
2866 {
2867   neon_const_bounds (operands[2], 1, 33);
2868   return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
2869 }
2870   [(set (attr "neon_type")
2871      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2872                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2873                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2874 )
2875
2876 (define_insn "neon_vmovn<mode>"
2877   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2878         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2879                             (match_operand:SI 2 "immediate_operand" "i")]
2880                            UNSPEC_VMOVN))]
2881   "TARGET_NEON"
2882   "vmovn.<V_if_elem>\t%P0, %q1"
2883   [(set_attr "neon_type" "neon_bp_simple")]
2884 )
2885
2886 (define_insn "neon_vqmovn<mode>"
2887   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2888         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2889                             (match_operand:SI 2 "immediate_operand" "i")]
2890                            UNSPEC_VQMOVN))]
2891   "TARGET_NEON"
2892   "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
2893   [(set_attr "neon_type" "neon_shift_2")]
2894 )
2895
2896 (define_insn "neon_vqmovun<mode>"
2897   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2898         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2899                             (match_operand:SI 2 "immediate_operand" "i")]
2900                            UNSPEC_VQMOVUN))]
2901   "TARGET_NEON"
2902   "vqmovun.<V_s_elem>\t%P0, %q1"
2903   [(set_attr "neon_type" "neon_shift_2")]
2904 )
2905
2906 (define_insn "neon_vmovl<mode>"
2907   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2908         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2909                            (match_operand:SI 2 "immediate_operand" "i")]
2910                           UNSPEC_VMOVL))]
2911   "TARGET_NEON"
2912   "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
2913   [(set_attr "neon_type" "neon_shift_1")]
2914 )
2915
2916 (define_insn "neon_vmul_lane<mode>"
2917   [(set (match_operand:VMD 0 "s_register_operand" "=w")
2918         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
2919                      (match_operand:VMD 2 "s_register_operand"
2920                                         "<scalar_mul_constraint>")
2921                      (match_operand:SI 3 "immediate_operand" "i")
2922                      (match_operand:SI 4 "immediate_operand" "i")]
2923                     UNSPEC_VMUL_LANE))]
2924   "TARGET_NEON"
2925 {
2926   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2927   return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
2928 }
2929   [(set (attr "neon_type")
2930      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2931                    (const_string "neon_fp_vmul_ddd")
2932                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2933                                  (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2934                                  (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
2935 )
2936
2937 (define_insn "neon_vmul_lane<mode>"
2938   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
2939         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
2940                      (match_operand:<V_HALF> 2 "s_register_operand"
2941                                              "<scalar_mul_constraint>")
2942                      (match_operand:SI 3 "immediate_operand" "i")
2943                      (match_operand:SI 4 "immediate_operand" "i")]
2944                     UNSPEC_VMUL_LANE))]
2945   "TARGET_NEON"
2946 {
2947   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
2948   return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
2949 }
2950   [(set (attr "neon_type")
2951      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2952                    (const_string "neon_fp_vmul_qqd")
2953                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2954                                  (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
2955                                  (const_string "neon_mul_qqd_32_scalar"))))]
2956 )
2957
2958 (define_insn "neon_vmull_lane<mode>"
2959   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2960         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2961                            (match_operand:VMDI 2 "s_register_operand"
2962                                                "<scalar_mul_constraint>")
2963                            (match_operand:SI 3 "immediate_operand" "i")
2964                            (match_operand:SI 4 "immediate_operand" "i")]
2965                           UNSPEC_VMULL_LANE))]
2966   "TARGET_NEON"
2967 {
2968   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2969   return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
2970 }
2971   [(set (attr "neon_type")
2972      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2973                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2974                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2975 )
2976
2977 (define_insn "neon_vqdmull_lane<mode>"
2978   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2979         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2980                            (match_operand:VMDI 2 "s_register_operand"
2981                                                "<scalar_mul_constraint>")
2982                            (match_operand:SI 3 "immediate_operand" "i")
2983                            (match_operand:SI 4 "immediate_operand" "i")]
2984                           UNSPEC_VQDMULL_LANE))]
2985   "TARGET_NEON"
2986 {
2987   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2988   return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
2989 }
2990   [(set (attr "neon_type")
2991      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2992                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2993                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2994 )
2995
2996 (define_insn "neon_vqdmulh_lane<mode>"
2997   [(set (match_operand:VMQI 0 "s_register_operand" "=w")
2998         (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
2999                       (match_operand:<V_HALF> 2 "s_register_operand"
3000                                               "<scalar_mul_constraint>")
3001                       (match_operand:SI 3 "immediate_operand" "i")
3002                       (match_operand:SI 4 "immediate_operand" "i")]
3003                       UNSPEC_VQDMULH_LANE))]
3004   "TARGET_NEON"
3005 {
3006   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3007   return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
3008 }
3009   [(set (attr "neon_type")
3010      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3011                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3012                    (const_string "neon_mul_qqd_32_scalar")))]
3013 )
3014
3015 (define_insn "neon_vqdmulh_lane<mode>"
3016   [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3017         (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3018                       (match_operand:VMDI 2 "s_register_operand"
3019                                           "<scalar_mul_constraint>")
3020                       (match_operand:SI 3 "immediate_operand" "i")
3021                       (match_operand:SI 4 "immediate_operand" "i")]
3022                       UNSPEC_VQDMULH_LANE))]
3023   "TARGET_NEON"
3024 {
3025   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3026   return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
3027 }
3028   [(set (attr "neon_type")
3029      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3030                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3031                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3032 )
3033
3034 (define_insn "neon_vmla_lane<mode>"
3035   [(set (match_operand:VMD 0 "s_register_operand" "=w")
3036         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3037                      (match_operand:VMD 2 "s_register_operand" "w")
3038                      (match_operand:VMD 3 "s_register_operand"
3039                                         "<scalar_mul_constraint>")
3040                      (match_operand:SI 4 "immediate_operand" "i")
3041                      (match_operand:SI 5 "immediate_operand" "i")]
3042                      UNSPEC_VMLA_LANE))]
3043   "TARGET_NEON"
3044 {
3045   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3046   return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3047 }
3048   [(set (attr "neon_type")
3049      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3050                    (const_string "neon_fp_vmla_ddd_scalar")
3051                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3052                                  (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3053                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3054 )
3055
3056 (define_insn "neon_vmla_lane<mode>"
3057   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3058         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3059                      (match_operand:VMQ 2 "s_register_operand" "w")
3060                      (match_operand:<V_HALF> 3 "s_register_operand"
3061                                              "<scalar_mul_constraint>")
3062                      (match_operand:SI 4 "immediate_operand" "i")
3063                      (match_operand:SI 5 "immediate_operand" "i")]
3064                      UNSPEC_VMLA_LANE))]
3065   "TARGET_NEON"
3066 {
3067   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3068   return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3069 }
3070   [(set (attr "neon_type")
3071      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3072                    (const_string "neon_fp_vmla_qqq_scalar")
3073                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3074                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3075                                  (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3076 )
3077
3078 (define_insn "neon_vmlal_lane<mode>"
3079   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3080         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3081                            (match_operand:VMDI 2 "s_register_operand" "w")
3082                            (match_operand:VMDI 3 "s_register_operand"
3083                                                "<scalar_mul_constraint>")
3084                            (match_operand:SI 4 "immediate_operand" "i")
3085                            (match_operand:SI 5 "immediate_operand" "i")]
3086                           UNSPEC_VMLAL_LANE))]
3087   "TARGET_NEON"
3088 {
3089   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3090   return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3091 }
3092   [(set (attr "neon_type")
3093      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3094                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3095                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3096 )
3097
3098 (define_insn "neon_vqdmlal_lane<mode>"
3099   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3100         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3101                            (match_operand:VMDI 2 "s_register_operand" "w")
3102                            (match_operand:VMDI 3 "s_register_operand"
3103                                                "<scalar_mul_constraint>")
3104                            (match_operand:SI 4 "immediate_operand" "i")
3105                            (match_operand:SI 5 "immediate_operand" "i")]
3106                           UNSPEC_VQDMLAL_LANE))]
3107   "TARGET_NEON"
3108 {
3109   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3110   return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3111 }
3112   [(set (attr "neon_type")
3113      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3114                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3115                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3116 )
3117
3118 (define_insn "neon_vmls_lane<mode>"
3119   [(set (match_operand:VMD 0 "s_register_operand" "=w")
3120         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3121                      (match_operand:VMD 2 "s_register_operand" "w")
3122                      (match_operand:VMD 3 "s_register_operand"
3123                                         "<scalar_mul_constraint>")
3124                      (match_operand:SI 4 "immediate_operand" "i")
3125                      (match_operand:SI 5 "immediate_operand" "i")]
3126                     UNSPEC_VMLS_LANE))]
3127   "TARGET_NEON"
3128 {
3129   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3130   return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3131 }
3132   [(set (attr "neon_type")
3133      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3134                    (const_string "neon_fp_vmla_ddd_scalar")
3135                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3136                                  (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3137                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3138 )
3139
3140 (define_insn "neon_vmls_lane<mode>"
3141   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3142         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3143                      (match_operand:VMQ 2 "s_register_operand" "w")
3144                      (match_operand:<V_HALF> 3 "s_register_operand"
3145                                              "<scalar_mul_constraint>")
3146                      (match_operand:SI 4 "immediate_operand" "i")
3147                      (match_operand:SI 5 "immediate_operand" "i")]
3148                     UNSPEC_VMLS_LANE))]
3149   "TARGET_NEON"
3150 {
3151   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3152   return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3153 }
3154   [(set (attr "neon_type")
3155      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3156                    (const_string "neon_fp_vmla_qqq_scalar")
3157                    (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3158                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3159                                  (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3160 )
3161
3162 (define_insn "neon_vmlsl_lane<mode>"
3163   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3164         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3165                            (match_operand:VMDI 2 "s_register_operand" "w")
3166                            (match_operand:VMDI 3 "s_register_operand"
3167                                                "<scalar_mul_constraint>")
3168                            (match_operand:SI 4 "immediate_operand" "i")
3169                            (match_operand:SI 5 "immediate_operand" "i")]
3170                           UNSPEC_VMLSL_LANE))]
3171   "TARGET_NEON"
3172 {
3173   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3174   return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3175 }
3176   [(set (attr "neon_type")
3177      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3178                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3179                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3180 )
3181
3182 (define_insn "neon_vqdmlsl_lane<mode>"
3183   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3184         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3185                            (match_operand:VMDI 2 "s_register_operand" "w")
3186                            (match_operand:VMDI 3 "s_register_operand"
3187                                                "<scalar_mul_constraint>")
3188                            (match_operand:SI 4 "immediate_operand" "i")
3189                            (match_operand:SI 5 "immediate_operand" "i")]
3190                           UNSPEC_VQDMLSL_LANE))]
3191   "TARGET_NEON"
3192 {
3193   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3194   return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3195 }
3196   [(set (attr "neon_type")
3197      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3198                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3199                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3200 )
3201
3202 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3203 ; core register into a temp register, then use a scalar taken from that. This
3204 ; isn't an optimal solution if e.g. the scalar has just been read from memory
3205 ; or extracted from another vector. The latter case it's currently better to
3206 ; use the "_lane" variant, and the former case can probably be implemented
3207 ; using vld1_lane, but that hasn't been done yet.
3208
3209 (define_expand "neon_vmul_n<mode>"
3210   [(match_operand:VMD 0 "s_register_operand" "")
3211    (match_operand:VMD 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 (<MODE>mode);
3217   emit_insn (gen_neon_vset_lane<mode> (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_vmul_n<mode>"
3224   [(match_operand:VMQ 0 "s_register_operand" "")
3225    (match_operand:VMQ 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 (<V_HALF>mode);
3231   emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3232   emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3233                                        const0_rtx, const0_rtx));
3234   DONE;
3235 })
3236