OSDN Git Service

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