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