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