arm.md (attribute "type"): Rename "simple_alu_imm" to "arlo_imm".
[official-gcc.git] / gcc / config / arm / neon.md
blobbcc93de0da49af34dc04db7d94847ddf1fb079d1
1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006-2013 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/>.
22 ;; Attribute used to permit string comparisons against <VQH_mnem> in
23 ;; neon_type attribute definitions.
24 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
26 (define_insn "*neon_mov<mode>"
27   [(set (match_operand:VDX 0 "nonimmediate_operand"
28           "=w,Un,w, w,  ?r,?w,?r,?r, ?Us")
29         (match_operand:VDX 1 "general_operand"
30           " w,w, Dn,Uni, w, r, r, Usi,r"))]
31   "TARGET_NEON
32    && (register_operand (operands[0], <MODE>mode)
33        || register_operand (operands[1], <MODE>mode))"
35   if (which_alternative == 2)
36     {
37       int width, is_valid;
38       static char templ[40];
40       is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
41         &operands[1], &width);
43       gcc_assert (is_valid != 0);
45       if (width == 0)
46         return "vmov.f32\t%P0, %1  @ <mode>";
47       else
48         sprintf (templ, "vmov.i%d\t%%P0, %%x1  @ <mode>", width);
50       return templ;
51     }
53   switch (which_alternative)
54     {
55     case 0: return "vmov\t%P0, %P1  @ <mode>";
56     case 1: case 3: return output_move_neon (operands);
57     case 2: gcc_unreachable ();
58     case 4: return "vmov\t%Q0, %R0, %P1  @ <mode>";
59     case 5: return "vmov\t%P0, %Q1, %R1  @ <mode>";
60     default: return output_move_double (operands, true, NULL);
61     }
63  [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
64   (set_attr "type" "*,f_stored,*,f_loadd,*,*,arlo_reg,load2,store2")
65   (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
66   (set_attr "length" "4,4,4,4,4,4,8,8,8")
67   (set_attr "arm_pool_range"     "*,*,*,1020,*,*,*,1020,*")
68   (set_attr "thumb2_pool_range"     "*,*,*,1018,*,*,*,1018,*")
69   (set_attr "neg_pool_range" "*,*,*,1004,*,*,*,1004,*")])
71 (define_insn "*neon_mov<mode>"
72   [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
73           "=w,Un,w, w,  ?r,?w,?r,?r,  ?Us")
74         (match_operand:VQXMOV 1 "general_operand"
75           " w,w, Dn,Uni, w, r, r, Usi, r"))]
76   "TARGET_NEON
77    && (register_operand (operands[0], <MODE>mode)
78        || register_operand (operands[1], <MODE>mode))"
80   if (which_alternative == 2)
81     {
82       int width, is_valid;
83       static char templ[40];
85       is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
86         &operands[1], &width);
88       gcc_assert (is_valid != 0);
90       if (width == 0)
91         return "vmov.f32\t%q0, %1  @ <mode>";
92       else
93         sprintf (templ, "vmov.i%d\t%%q0, %%1  @ <mode>", width);
95       return templ;
96     }
98   switch (which_alternative)
99     {
100     case 0: return "vmov\t%q0, %q1  @ <mode>";
101     case 1: case 3: return output_move_neon (operands);
102     case 2: gcc_unreachable ();
103     case 4: return "vmov\t%Q0, %R0, %e1  @ <mode>\;vmov\t%J0, %K0, %f1";
104     case 5: return "vmov\t%e0, %Q1, %R1  @ <mode>\;vmov\t%f0, %J1, %K1";
105     default: return output_move_quad (operands);
106     }
108   [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
109                           neon_mrrc,neon_mcr_2_mcrr,*,*,*")
110    (set_attr "type" "*,*,*,*,*,*,arlo_reg,load4,store4")
111    (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
112    (set_attr "length" "4,8,4,8,8,8,16,8,16")
113    (set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
114    (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
115    (set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
117 (define_expand "movti"
118   [(set (match_operand:TI 0 "nonimmediate_operand" "")
119         (match_operand:TI 1 "general_operand" ""))]
120   "TARGET_NEON"
122   if (can_create_pseudo_p ())
123     {
124       if (!REG_P (operands[0]))
125         operands[1] = force_reg (TImode, operands[1]);
126     }
129 (define_expand "mov<mode>"
130   [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
131         (match_operand:VSTRUCT 1 "general_operand" ""))]
132   "TARGET_NEON"
134   if (can_create_pseudo_p ())
135     {
136       if (!REG_P (operands[0]))
137         operands[1] = force_reg (<MODE>mode, operands[1]);
138     }
141 (define_insn "*neon_mov<mode>"
142   [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
143         (match_operand:VSTRUCT 1 "general_operand"      " w,w, Ut"))]
144   "TARGET_NEON
145    && (register_operand (operands[0], <MODE>mode)
146        || register_operand (operands[1], <MODE>mode))"
148   switch (which_alternative)
149     {
150     case 0: return "#";
151     case 1: case 2: return output_move_neon (operands);
152     default: gcc_unreachable ();
153     }
155   [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2")
156    (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
158 (define_split
159   [(set (match_operand:EI 0 "s_register_operand" "")
160         (match_operand:EI 1 "s_register_operand" ""))]
161   "TARGET_NEON && reload_completed"
162   [(set (match_dup 0) (match_dup 1))
163    (set (match_dup 2) (match_dup 3))]
165   int rdest = REGNO (operands[0]);
166   int rsrc = REGNO (operands[1]);
167   rtx dest[2], src[2];
169   dest[0] = gen_rtx_REG (TImode, rdest);
170   src[0] = gen_rtx_REG (TImode, rsrc);
171   dest[1] = gen_rtx_REG (DImode, rdest + 4);
172   src[1] = gen_rtx_REG (DImode, rsrc + 4);
174   neon_disambiguate_copy (operands, dest, src, 2);
177 (define_split
178   [(set (match_operand:OI 0 "s_register_operand" "")
179         (match_operand:OI 1 "s_register_operand" ""))]
180   "TARGET_NEON && reload_completed"
181   [(set (match_dup 0) (match_dup 1))
182    (set (match_dup 2) (match_dup 3))]
184   int rdest = REGNO (operands[0]);
185   int rsrc = REGNO (operands[1]);
186   rtx dest[2], src[2];
188   dest[0] = gen_rtx_REG (TImode, rdest);
189   src[0] = gen_rtx_REG (TImode, rsrc);
190   dest[1] = gen_rtx_REG (TImode, rdest + 4);
191   src[1] = gen_rtx_REG (TImode, rsrc + 4);
193   neon_disambiguate_copy (operands, dest, src, 2);
196 (define_split
197   [(set (match_operand:CI 0 "s_register_operand" "")
198         (match_operand:CI 1 "s_register_operand" ""))]
199   "TARGET_NEON && reload_completed"
200   [(set (match_dup 0) (match_dup 1))
201    (set (match_dup 2) (match_dup 3))
202    (set (match_dup 4) (match_dup 5))]
204   int rdest = REGNO (operands[0]);
205   int rsrc = REGNO (operands[1]);
206   rtx dest[3], src[3];
208   dest[0] = gen_rtx_REG (TImode, rdest);
209   src[0] = gen_rtx_REG (TImode, rsrc);
210   dest[1] = gen_rtx_REG (TImode, rdest + 4);
211   src[1] = gen_rtx_REG (TImode, rsrc + 4);
212   dest[2] = gen_rtx_REG (TImode, rdest + 8);
213   src[2] = gen_rtx_REG (TImode, rsrc + 8);
215   neon_disambiguate_copy (operands, dest, src, 3);
218 (define_split
219   [(set (match_operand:XI 0 "s_register_operand" "")
220         (match_operand:XI 1 "s_register_operand" ""))]
221   "TARGET_NEON && reload_completed"
222   [(set (match_dup 0) (match_dup 1))
223    (set (match_dup 2) (match_dup 3))
224    (set (match_dup 4) (match_dup 5))
225    (set (match_dup 6) (match_dup 7))]
227   int rdest = REGNO (operands[0]);
228   int rsrc = REGNO (operands[1]);
229   rtx dest[4], src[4];
231   dest[0] = gen_rtx_REG (TImode, rdest);
232   src[0] = gen_rtx_REG (TImode, rsrc);
233   dest[1] = gen_rtx_REG (TImode, rdest + 4);
234   src[1] = gen_rtx_REG (TImode, rsrc + 4);
235   dest[2] = gen_rtx_REG (TImode, rdest + 8);
236   src[2] = gen_rtx_REG (TImode, rsrc + 8);
237   dest[3] = gen_rtx_REG (TImode, rdest + 12);
238   src[3] = gen_rtx_REG (TImode, rsrc + 12);
240   neon_disambiguate_copy (operands, dest, src, 4);
243 (define_expand "movmisalign<mode>"
244   [(set (match_operand:VDQX 0 "neon_perm_struct_or_reg_operand")
245         (unspec:VDQX [(match_operand:VDQX 1 "neon_perm_struct_or_reg_operand")]
246                      UNSPEC_MISALIGNED_ACCESS))]
247   "TARGET_NEON && !BYTES_BIG_ENDIAN"
249   /* This pattern is not permitted to fail during expansion: if both arguments
250      are non-registers (e.g. memory := constant, which can be created by the
251      auto-vectorizer), force operand 1 into a register.  */
252   if (!s_register_operand (operands[0], <MODE>mode)
253       && !s_register_operand (operands[1], <MODE>mode))
254     operands[1] = force_reg (<MODE>mode, operands[1]);
257 (define_insn "*movmisalign<mode>_neon_store"
258   [(set (match_operand:VDX 0 "neon_permissive_struct_operand"   "=Um")
259         (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
260                     UNSPEC_MISALIGNED_ACCESS))]
261   "TARGET_NEON && !BYTES_BIG_ENDIAN"
262   "vst1.<V_sz_elem>\t{%P1}, %A0"
263   [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
265 (define_insn "*movmisalign<mode>_neon_load"
266   [(set (match_operand:VDX 0 "s_register_operand"                       "=w")
267         (unspec:VDX [(match_operand:VDX 1 "neon_permissive_struct_operand"
268                                                                         " Um")]
269                     UNSPEC_MISALIGNED_ACCESS))]
270   "TARGET_NEON && !BYTES_BIG_ENDIAN"
271   "vld1.<V_sz_elem>\t{%P0}, %A1"
272   [(set_attr "neon_type" "neon_vld1_1_2_regs")])
274 (define_insn "*movmisalign<mode>_neon_store"
275   [(set (match_operand:VQX 0 "neon_permissive_struct_operand"  "=Um")
276         (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")]
277                     UNSPEC_MISALIGNED_ACCESS))]
278   "TARGET_NEON && !BYTES_BIG_ENDIAN"
279   "vst1.<V_sz_elem>\t{%q1}, %A0"
280   [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
282 (define_insn "*movmisalign<mode>_neon_load"
283   [(set (match_operand:VQX 0 "s_register_operand"                       "=w")
284         (unspec:VQX [(match_operand:VQX 1 "neon_permissive_struct_operand"
285                                                                         " Um")]
286                     UNSPEC_MISALIGNED_ACCESS))]
287   "TARGET_NEON && !BYTES_BIG_ENDIAN"
288   "vld1.<V_sz_elem>\t{%q0}, %A1"
289   [(set_attr "neon_type" "neon_vld1_1_2_regs")])
291 (define_insn "vec_set<mode>_internal"
292   [(set (match_operand:VD 0 "s_register_operand" "=w,w")
293         (vec_merge:VD
294           (vec_duplicate:VD
295             (match_operand:<V_elem> 1 "nonimmediate_operand" "Um,r"))
296           (match_operand:VD 3 "s_register_operand" "0,0")
297           (match_operand:SI 2 "immediate_operand" "i,i")))]
298   "TARGET_NEON"
300   int elt = ffs ((int) INTVAL (operands[2])) - 1;
301   if (BYTES_BIG_ENDIAN)
302     elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
303   operands[2] = GEN_INT (elt);
305   if (which_alternative == 0)
306     return "vld1.<V_sz_elem>\t{%P0[%c2]}, %A1";
307   else
308     return "vmov.<V_sz_elem>\t%P0[%c2], %1";
310   [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")])
312 (define_insn "vec_set<mode>_internal"
313   [(set (match_operand:VQ 0 "s_register_operand" "=w,w")
314         (vec_merge:VQ
315           (vec_duplicate:VQ
316             (match_operand:<V_elem> 1 "nonimmediate_operand" "Um,r"))
317           (match_operand:VQ 3 "s_register_operand" "0,0")
318           (match_operand:SI 2 "immediate_operand" "i,i")))]
319   "TARGET_NEON"
321   HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
322   int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
323   int elt = elem % half_elts;
324   int hi = (elem / half_elts) * 2;
325   int regno = REGNO (operands[0]);
327   if (BYTES_BIG_ENDIAN)
328     elt = half_elts - 1 - elt;
330   operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
331   operands[2] = GEN_INT (elt);
333   if (which_alternative == 0)
334     return "vld1.<V_sz_elem>\t{%P0[%c2]}, %A1";
335   else
336     return "vmov.<V_sz_elem>\t%P0[%c2], %1";
338   [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")]
341 (define_insn "vec_setv2di_internal"
342   [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
343         (vec_merge:V2DI
344           (vec_duplicate:V2DI
345             (match_operand:DI 1 "nonimmediate_operand" "Um,r"))
346           (match_operand:V2DI 3 "s_register_operand" "0,0")
347           (match_operand:SI 2 "immediate_operand" "i,i")))]
348   "TARGET_NEON"
350   HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
351   int regno = REGNO (operands[0]) + 2 * elem;
353   operands[0] = gen_rtx_REG (DImode, regno);
355   if (which_alternative == 0)
356     return "vld1.64\t%P0, %A1";
357   else
358     return "vmov\t%P0, %Q1, %R1";
360   [(set_attr "neon_type" "neon_vld1_1_2_regs,neon_mcr_2_mcrr")]
363 (define_expand "vec_set<mode>"
364   [(match_operand:VDQ 0 "s_register_operand" "")
365    (match_operand:<V_elem> 1 "s_register_operand" "")
366    (match_operand:SI 2 "immediate_operand" "")]
367   "TARGET_NEON"
369   HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
370   emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
371                                          GEN_INT (elem), operands[0]));
372   DONE;
375 (define_insn "vec_extract<mode>"
376   [(set (match_operand:<V_elem> 0 "nonimmediate_operand" "=Um,r")
377         (vec_select:<V_elem>
378           (match_operand:VD 1 "s_register_operand" "w,w")
379           (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
380   "TARGET_NEON"
382   if (BYTES_BIG_ENDIAN)
383     {
384       int elt = INTVAL (operands[2]);
385       elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
386       operands[2] = GEN_INT (elt);
387     }
389   if (which_alternative == 0)
390     return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
391   else
392     return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
394   [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_bp_simple")]
397 (define_insn "vec_extract<mode>"
398   [(set (match_operand:<V_elem> 0 "nonimmediate_operand" "=Um,r")
399         (vec_select:<V_elem>
400           (match_operand:VQ 1 "s_register_operand" "w,w")
401           (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
402   "TARGET_NEON"
404   int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
405   int elt = INTVAL (operands[2]) % half_elts;
406   int hi = (INTVAL (operands[2]) / half_elts) * 2;
407   int regno = REGNO (operands[1]);
409   if (BYTES_BIG_ENDIAN)
410     elt = half_elts - 1 - elt;
412   operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
413   operands[2] = GEN_INT (elt);
415   if (which_alternative == 0)
416     return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
417   else
418     return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
420   [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_bp_simple")]
423 (define_insn "vec_extractv2di"
424   [(set (match_operand:DI 0 "nonimmediate_operand" "=Um,r")
425         (vec_select:DI
426           (match_operand:V2DI 1 "s_register_operand" "w,w")
427           (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
428   "TARGET_NEON"
430   int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
432   operands[1] = gen_rtx_REG (DImode, regno);
434   if (which_alternative == 0)
435     return "vst1.64\t{%P1}, %A0  @ v2di";
436   else
437     return "vmov\t%Q0, %R0, %P1  @ v2di";
439   [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_int_1")]
442 (define_expand "vec_init<mode>"
443   [(match_operand:VDQ 0 "s_register_operand" "")
444    (match_operand 1 "" "")]
445   "TARGET_NEON"
447   neon_expand_vector_init (operands[0], operands[1]);
448   DONE;
451 ;; Doubleword and quadword arithmetic.
453 ;; NOTE: some other instructions also support 64-bit integer
454 ;; element size, which we could potentially use for "long long" operations.
456 (define_insn "*add<mode>3_neon"
457   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
458         (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
459                   (match_operand:VDQ 2 "s_register_operand" "w")))]
460   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
461   "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
462   [(set (attr "neon_type")
463       (if_then_else (match_test "<Is_float_mode>")
464                     (if_then_else (match_test "<Is_d_reg>")
465                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
466                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
467                     (const_string "neon_int_1")))]
470 (define_insn "adddi3_neon"
471   [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r,?&r")
472         (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w,r,0,r")
473                  (match_operand:DI 2 "arm_adddi_operand"     "w,r,0,w,r,Dd,Dd")))
474    (clobber (reg:CC CC_REGNUM))]
475   "TARGET_NEON"
477   switch (which_alternative)
478     {
479     case 0: /* fall through */
480     case 3: return "vadd.i64\t%P0, %P1, %P2";
481     case 1: return "#";
482     case 2: return "#";
483     case 4: return "#";
484     case 5: return "#";
485     case 6: return "#";
486     default: gcc_unreachable ();
487     }
489   [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*,*")
490    (set_attr "conds" "*,clob,clob,*,clob,clob,clob")
491    (set_attr "length" "*,8,8,*,8,8,8")
492    (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits,*,*,*")]
495 (define_insn "*sub<mode>3_neon"
496   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
497         (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
498                    (match_operand:VDQ 2 "s_register_operand" "w")))]
499   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
500   "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
501   [(set (attr "neon_type")
502       (if_then_else (match_test "<Is_float_mode>")
503                     (if_then_else (match_test "<Is_d_reg>")
504                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
505                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
506                     (const_string "neon_int_2")))]
509 (define_insn "subdi3_neon"
510   [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r,?w")
511         (minus:DI (match_operand:DI 1 "s_register_operand" "w,0,r,0,w")
512                   (match_operand:DI 2 "s_register_operand" "w,r,0,0,w")))
513    (clobber (reg:CC CC_REGNUM))]
514   "TARGET_NEON"
516   switch (which_alternative)
517     {
518     case 0: /* fall through */
519     case 4: return "vsub.i64\t%P0, %P1, %P2";
520     case 1: /* fall through */ 
521     case 2: /* fall through */
522     case 3: return  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2";
523     default: gcc_unreachable ();
524     }
526   [(set_attr "neon_type" "neon_int_2,*,*,*,neon_int_2")
527    (set_attr "conds" "*,clob,clob,clob,*")
528    (set_attr "length" "*,8,8,8,*")
529    (set_attr "arch" "neon_for_64bits,*,*,*,avoid_neon_for_64bits")]
532 (define_insn "*mul<mode>3_neon"
533   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
534         (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
535                   (match_operand:VDQ 2 "s_register_operand" "w")))]
536   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
537   "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
538   [(set (attr "neon_type")
539       (if_then_else (match_test "<Is_float_mode>")
540                     (if_then_else (match_test "<Is_d_reg>")
541                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
542                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
543                     (if_then_else (match_test "<Is_d_reg>")
544                                   (if_then_else
545                                     (match_test "<Scalar_mul_8_16>")
546                                     (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
547                                     (const_string "neon_mul_qqq_8_16_32_ddd_32"))
548                                   (if_then_else (match_test "<Scalar_mul_8_16>")
549                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")
550                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
553 (define_insn "mul<mode>3add<mode>_neon"
554   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
555         (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
556                             (match_operand:VDQ 3 "s_register_operand" "w"))
557                   (match_operand:VDQ 1 "s_register_operand" "0")))]
558   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
559   "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
560   [(set (attr "neon_type")
561       (if_then_else (match_test "<Is_float_mode>")
562                     (if_then_else (match_test "<Is_d_reg>")
563                                   (const_string "neon_fp_vmla_ddd")
564                                   (const_string "neon_fp_vmla_qqq"))
565                     (if_then_else (match_test "<Is_d_reg>")
566                                   (if_then_else
567                                     (match_test "<Scalar_mul_8_16>")
568                                     (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
569                                     (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
570                                   (if_then_else (match_test "<Scalar_mul_8_16>")
571                                     (const_string "neon_mla_qqq_8_16")
572                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
575 (define_insn "mul<mode>3neg<mode>add<mode>_neon"
576   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
577         (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
578                    (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
579                              (match_operand:VDQ 3 "s_register_operand" "w"))))]
580   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
581   "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
582   [(set (attr "neon_type")
583       (if_then_else (match_test "<Is_float_mode>")
584                     (if_then_else (match_test "<Is_d_reg>")
585                                   (const_string "neon_fp_vmla_ddd")
586                                   (const_string "neon_fp_vmla_qqq"))
587                     (if_then_else (match_test "<Is_d_reg>")
588                                   (if_then_else
589                                     (match_test "<Scalar_mul_8_16>")
590                                     (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
591                                     (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
592                                   (if_then_else (match_test "<Scalar_mul_8_16>")
593                                     (const_string "neon_mla_qqq_8_16")
594                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
597 ;; Fused multiply-accumulate
598 ;; We define each insn twice here:
599 ;;    1: with flag_unsafe_math_optimizations for the widening multiply phase
600 ;;       to be able to use when converting to FMA.
601 ;;    2: without flag_unsafe_math_optimizations for the intrinsics to use.
602 (define_insn "fma<VCVTF:mode>4"
603   [(set (match_operand:VCVTF 0 "register_operand" "=w")
604         (fma:VCVTF (match_operand:VCVTF 1 "register_operand" "w")
605                  (match_operand:VCVTF 2 "register_operand" "w")
606                  (match_operand:VCVTF 3 "register_operand" "0")))]
607   "TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
608   "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
609   [(set (attr "neon_type")
610         (if_then_else (match_test "<Is_d_reg>")
611                       (const_string "neon_fp_vmla_ddd")
612                       (const_string "neon_fp_vmla_qqq")))]
615 (define_insn "fma<VCVTF:mode>4_intrinsic"
616   [(set (match_operand:VCVTF 0 "register_operand" "=w")
617         (fma:VCVTF (match_operand:VCVTF 1 "register_operand" "w")
618                  (match_operand:VCVTF 2 "register_operand" "w")
619                  (match_operand:VCVTF 3 "register_operand" "0")))]
620   "TARGET_NEON && TARGET_FMA"
621   "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
622   [(set (attr "neon_type")
623         (if_then_else (match_test "<Is_d_reg>")
624                       (const_string "neon_fp_vmla_ddd")
625                       (const_string "neon_fp_vmla_qqq")))]
628 (define_insn "*fmsub<VCVTF:mode>4"
629   [(set (match_operand:VCVTF 0 "register_operand" "=w")
630         (fma:VCVTF (neg:VCVTF (match_operand:VCVTF 1 "register_operand" "w"))
631                    (match_operand:VCVTF 2 "register_operand" "w")
632                    (match_operand:VCVTF 3 "register_operand" "0")))]
633   "TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
634   "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
635   [(set (attr "neon_type")
636         (if_then_else (match_test "<Is_d_reg>")
637                       (const_string "neon_fp_vmla_ddd")
638                       (const_string "neon_fp_vmla_qqq")))]
641 (define_insn "fmsub<VCVTF:mode>4_intrinsic"
642   [(set (match_operand:VCVTF 0 "register_operand" "=w")
643         (fma:VCVTF (neg:VCVTF (match_operand:VCVTF 1 "register_operand" "w"))
644                    (match_operand:VCVTF 2 "register_operand" "w")
645                    (match_operand:VCVTF 3 "register_operand" "0")))]
646   "TARGET_NEON && TARGET_FMA"
647   "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
648   [(set (attr "neon_type")
649         (if_then_else (match_test "<Is_d_reg>")
650                       (const_string "neon_fp_vmla_ddd")
651                       (const_string "neon_fp_vmla_qqq")))]
654 (define_insn "neon_vrint<NEON_VRINT:nvrint_variant><VCVTF:mode>"
655   [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
656         (unspec:VCVTF [(match_operand:VCVTF 1
657                          "s_register_operand" "w")]
658                 NEON_VRINT))]
659   "TARGET_NEON && TARGET_FPU_ARMV8"
660   "vrint<nvrint_variant>%?.f32\\t%<V_reg>0, %<V_reg>1"
661   [(set (attr "neon_type")
662         (if_then_else (match_test "<Is_d_reg>")
663                 (const_string "neon_fp_vadd_ddd_vabs_dd")
664                 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
667 (define_insn "ior<mode>3"
668   [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
669         (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
670                  (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
671   "TARGET_NEON"
673   switch (which_alternative)
674     {
675     case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
676     case 1: return neon_output_logic_immediate ("vorr", &operands[2],
677                      <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));
678     default: gcc_unreachable ();
679     }
681   [(set_attr "neon_type" "neon_int_1")]
684 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
685 ;; vorr. We support the pseudo-instruction vand instead, because that
686 ;; corresponds to the canonical form the middle-end expects to use for
687 ;; immediate bitwise-ANDs.
689 (define_insn "and<mode>3"
690   [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
691         (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
692                  (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
693   "TARGET_NEON"
695   switch (which_alternative)
696     {
697     case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
698     case 1: return neon_output_logic_immediate ("vand", &operands[2],
699                      <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));
700     default: gcc_unreachable ();
701     }
703   [(set_attr "neon_type" "neon_int_1")]
706 (define_insn "orn<mode>3_neon"
707   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
708         (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
709                  (match_operand:VDQ 1 "s_register_operand" "w")))]
710   "TARGET_NEON"
711   "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
712   [(set_attr "neon_type" "neon_int_1")]
715 ;; TODO: investigate whether we should disable 
716 ;; this and bicdi3_neon for the A8 in line with the other
717 ;; changes above. 
718 (define_insn_and_split "orndi3_neon"
719   [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r")
720         (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,0,0,r"))
721                 (match_operand:DI 1 "s_register_operand" "w,r,r,0")))]
722   "TARGET_NEON"
723   "@
724    vorn\t%P0, %P1, %P2
725    #
726    #
727    #"
728   "reload_completed && 
729    (TARGET_NEON && !(IS_VFP_REGNUM (REGNO (operands[0]))))"
730   [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
731    (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
732   "
733   {
734     if (TARGET_THUMB2)
735       {
736         operands[3] = gen_highpart (SImode, operands[0]);
737         operands[0] = gen_lowpart (SImode, operands[0]);
738         operands[4] = gen_highpart (SImode, operands[2]);
739         operands[2] = gen_lowpart (SImode, operands[2]);
740         operands[5] = gen_highpart (SImode, operands[1]);
741         operands[1] = gen_lowpart (SImode, operands[1]);
742       }
743     else
744       {
745         emit_insn (gen_one_cmpldi2 (operands[0], operands[2]));
746         emit_insn (gen_iordi3 (operands[0], operands[1], operands[0]));
747         DONE;
748       }
749   }"
750   [(set_attr "neon_type" "neon_int_1,*,*,*")
751    (set_attr "length" "*,16,8,8")
752    (set_attr "arch" "any,a,t2,t2")]
755 (define_insn "bic<mode>3_neon"
756   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
757         (and:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
758                  (match_operand:VDQ 1 "s_register_operand" "w")))]
759   "TARGET_NEON"
760   "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
761   [(set_attr "neon_type" "neon_int_1")]
764 ;; Compare to *anddi_notdi_di.
765 (define_insn "bicdi3_neon"
766   [(set (match_operand:DI 0 "s_register_operand" "=w,?=&r,?&r")
767         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
768                 (match_operand:DI 1 "s_register_operand" "w,0,r")))]
769   "TARGET_NEON"
770   "@
771    vbic\t%P0, %P1, %P2
772    #
773    #"
774   [(set_attr "neon_type" "neon_int_1,*,*")
775    (set_attr "length" "*,8,8")]
778 (define_insn "xor<mode>3"
779   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
780         (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
781                  (match_operand:VDQ 2 "s_register_operand" "w")))]
782   "TARGET_NEON"
783   "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
784   [(set_attr "neon_type" "neon_int_1")]
787 (define_insn "one_cmpl<mode>2"
788   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
789         (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
790   "TARGET_NEON"
791   "vmvn\t%<V_reg>0, %<V_reg>1"
792   [(set_attr "neon_type" "neon_int_1")]
795 (define_insn "abs<mode>2"
796   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
797         (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
798   "TARGET_NEON"
799   "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
800   [(set (attr "neon_type")
801       (if_then_else (match_test "<Is_float_mode>")
802                     (if_then_else (match_test "<Is_d_reg>")
803                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
804                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
805                     (const_string "neon_int_3")))]
808 (define_insn "neg<mode>2"
809   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
810         (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
811   "TARGET_NEON"
812   "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
813   [(set (attr "neon_type")
814       (if_then_else (match_test "<Is_float_mode>")
815                     (if_then_else (match_test "<Is_d_reg>")
816                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
817                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
818                     (const_string "neon_int_3")))]
821 (define_insn "negdi2_neon"
822   [(set (match_operand:DI 0 "s_register_operand"         "=&w, w,r,&r")
823         (neg:DI (match_operand:DI 1 "s_register_operand" "  w, w,0, r")))
824    (clobber (match_scratch:DI 2                          "= X,&w,X, X"))
825    (clobber (reg:CC CC_REGNUM))]
826   "TARGET_NEON"
827   "#"
828   [(set_attr "length" "8")]
831 ; Split negdi2_neon for vfp registers
832 (define_split
833   [(set (match_operand:DI 0 "s_register_operand" "")
834         (neg:DI (match_operand:DI 1 "s_register_operand" "")))
835    (clobber (match_scratch:DI 2 ""))
836    (clobber (reg:CC CC_REGNUM))]
837   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
838   [(set (match_dup 2) (const_int 0))
839    (parallel [(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 1)))
840               (clobber (reg:CC CC_REGNUM))])]
841   {
842     if (!REG_P (operands[2]))
843       operands[2] = operands[0];
844   }
847 ; Split negdi2_neon for core registers
848 (define_split
849   [(set (match_operand:DI 0 "s_register_operand" "")
850         (neg:DI (match_operand:DI 1 "s_register_operand" "")))
851    (clobber (match_scratch:DI 2 ""))
852    (clobber (reg:CC CC_REGNUM))]
853   "TARGET_32BIT && reload_completed
854    && arm_general_register_operand (operands[0], DImode)"
855   [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
856               (clobber (reg:CC CC_REGNUM))])]
857   ""
860 (define_insn "*umin<mode>3_neon"
861   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
862         (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
863                     (match_operand:VDQIW 2 "s_register_operand" "w")))]
864   "TARGET_NEON"
865   "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
866   [(set_attr "neon_type" "neon_int_5")]
869 (define_insn "*umax<mode>3_neon"
870   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
871         (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
872                     (match_operand:VDQIW 2 "s_register_operand" "w")))]
873   "TARGET_NEON"
874   "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
875   [(set_attr "neon_type" "neon_int_5")]
878 (define_insn "*smin<mode>3_neon"
879   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
880         (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
881                    (match_operand:VDQW 2 "s_register_operand" "w")))]
882   "TARGET_NEON"
883   "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
884   [(set (attr "neon_type")
885       (if_then_else (match_test "<Is_float_mode>")
886                     (const_string "neon_fp_vadd_ddd_vabs_dd")
887                     (const_string "neon_int_5")))]
890 (define_insn "*smax<mode>3_neon"
891   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
892         (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
893                    (match_operand:VDQW 2 "s_register_operand" "w")))]
894   "TARGET_NEON"
895   "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
896   [(set (attr "neon_type")
897       (if_then_else (match_test "<Is_float_mode>")
898                     (const_string "neon_fp_vadd_ddd_vabs_dd")
899                     (const_string "neon_int_5")))]
902 ; TODO: V2DI shifts are current disabled because there are bugs in the
903 ; generic vectorizer code.  It ends up creating a V2DI constructor with
904 ; SImode elements.
906 (define_insn "vashl<mode>3"
907   [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
908         (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
909                       (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
910   "TARGET_NEON"
911   {
912     switch (which_alternative)
913       {
914         case 0: return "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
915         case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2],
916                                                     <MODE>mode,
917                                                     VALID_NEON_QREG_MODE (<MODE>mode),
918                                                     true);
919         default: gcc_unreachable ();
920       }
921   }
922   [(set (attr "neon_type")
923       (if_then_else (match_test "<Is_d_reg>")
924                     (const_string "neon_vshl_ddd")
925                     (const_string "neon_shift_3")))]
928 (define_insn "vashr<mode>3_imm"
929   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
930         (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
931                         (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
932   "TARGET_NEON"
933   {
934     return neon_output_shift_immediate ("vshr", 's', &operands[2],
935                                         <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
936                                         false);
937   }
938   [(set (attr "neon_type")
939       (if_then_else (match_test "<Is_d_reg>")
940                     (const_string "neon_vshl_ddd")
941                     (const_string "neon_shift_3")))]
944 (define_insn "vlshr<mode>3_imm"
945   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
946         (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
947                         (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
948   "TARGET_NEON"
949   {
950     return neon_output_shift_immediate ("vshr", 'u', &operands[2],
951                                         <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
952                                         false);
953   }              
954   [(set (attr "neon_type")
955         (if_then_else (match_test "<Is_d_reg>")
956                       (const_string "neon_vshl_ddd")
957                       (const_string "neon_shift_3")))]
960 ; Used for implementing logical shift-right, which is a left-shift by a negative
961 ; amount, with signed operands. This is essentially the same as ashl<mode>3
962 ; above, but using an unspec in case GCC tries anything tricky with negative
963 ; shift amounts.
965 (define_insn "ashl<mode>3_signed"
966   [(set (match_operand:VDQI 0 "s_register_operand" "=w")
967         (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
968                       (match_operand:VDQI 2 "s_register_operand" "w")]
969                      UNSPEC_ASHIFT_SIGNED))]
970   "TARGET_NEON"
971   "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
972   [(set (attr "neon_type")
973       (if_then_else (match_test "<Is_d_reg>")
974                     (const_string "neon_vshl_ddd")
975                     (const_string "neon_shift_3")))]
978 ; Used for implementing logical shift-right, which is a left-shift by a negative
979 ; amount, with unsigned operands.
981 (define_insn "ashl<mode>3_unsigned"
982   [(set (match_operand:VDQI 0 "s_register_operand" "=w")
983         (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
984                       (match_operand:VDQI 2 "s_register_operand" "w")]
985                      UNSPEC_ASHIFT_UNSIGNED))]
986   "TARGET_NEON"
987   "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
988   [(set (attr "neon_type")
989       (if_then_else (match_test "<Is_d_reg>")
990                     (const_string "neon_vshl_ddd")
991                     (const_string "neon_shift_3")))]
994 (define_expand "vashr<mode>3"
995   [(set (match_operand:VDQIW 0 "s_register_operand" "")
996         (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
997                         (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
998   "TARGET_NEON"
1000   if (s_register_operand (operands[2], <MODE>mode))
1001     {
1002       rtx neg = gen_reg_rtx (<MODE>mode);
1003       emit_insn (gen_neg<mode>2 (neg, operands[2]));
1004       emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1005     }
1006   else
1007     emit_insn (gen_vashr<mode>3_imm (operands[0], operands[1], operands[2]));
1008   DONE;
1011 (define_expand "vlshr<mode>3"
1012   [(set (match_operand:VDQIW 0 "s_register_operand" "")
1013         (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1014                         (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1015   "TARGET_NEON"
1017   if (s_register_operand (operands[2], <MODE>mode))
1018     {
1019       rtx neg = gen_reg_rtx (<MODE>mode);
1020       emit_insn (gen_neg<mode>2 (neg, operands[2]));
1021       emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1022     }
1023   else
1024     emit_insn (gen_vlshr<mode>3_imm (operands[0], operands[1], operands[2]));
1025   DONE;
1028 ;; 64-bit shifts
1030 ;; This pattern loads a 32-bit shift count into a 64-bit NEON register,
1031 ;; leaving the upper half uninitalized.  This is OK since the shift
1032 ;; instruction only looks at the low 8 bits anyway.  To avoid confusing
1033 ;; data flow analysis however, we pretend the full register is set
1034 ;; using an unspec.
1035 (define_insn "neon_load_count"
1036   [(set (match_operand:DI 0 "s_register_operand" "=w,w")
1037         (unspec:DI [(match_operand:SI 1 "nonimmediate_operand" "Um,r")]
1038                    UNSPEC_LOAD_COUNT))]
1039   "TARGET_NEON"
1040   "@
1041    vld1.32\t{%P0[0]}, %A1
1042    vmov.32\t%P0[0], %1"
1043   [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")]
1046 (define_insn "ashldi3_neon_noclobber"
1047   [(set (match_operand:DI 0 "s_register_operand"            "=w,w")
1048         (ashift:DI (match_operand:DI 1 "s_register_operand" " w,w")
1049                    (match_operand:DI 2 "reg_or_int_operand" " i,w")))]
1050   "TARGET_NEON && reload_completed
1051    && (!CONST_INT_P (operands[2])
1052        || (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 64))"
1053   "@
1054    vshl.u64\t%P0, %P1, %2
1055    vshl.u64\t%P0, %P1, %P2"
1056   [(set_attr "neon_type" "neon_vshl_ddd,neon_vshl_ddd")]
1059 (define_insn_and_split "ashldi3_neon"
1060   [(set (match_operand:DI 0 "s_register_operand"            "= w, w,?&r,?r, ?w,w")
1061         (ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r, 0w,w")
1062                    (match_operand:SI 2 "general_operand"    "rUm, i,  r, i,rUm,i")))
1063    (clobber (match_scratch:SI 3                             "= X, X,?&r, X,  X,X"))
1064    (clobber (match_scratch:SI 4                             "= X, X,?&r, X,  X,X"))
1065    (clobber (match_scratch:DI 5                             "=&w, X,  X, X, &w,X"))
1066    (clobber (reg:CC_C CC_REGNUM))]
1067   "TARGET_NEON"
1068   "#"
1069   "TARGET_NEON && reload_completed"
1070   [(const_int 0)]
1071   "
1072   {
1073     if (IS_VFP_REGNUM (REGNO (operands[0])))
1074       {
1075         if (CONST_INT_P (operands[2]))
1076           {
1077             if (INTVAL (operands[2]) < 1)
1078               {
1079                 emit_insn (gen_movdi (operands[0], operands[1]));
1080                 DONE;
1081               }
1082             else if (INTVAL (operands[2]) > 63)
1083               operands[2] = gen_rtx_CONST_INT (VOIDmode, 63);
1084           }
1085         else
1086           {
1087             emit_insn (gen_neon_load_count (operands[5], operands[2]));
1088             operands[2] = operands[5];
1089           }
1091         /* Ditch the unnecessary clobbers.  */
1092         emit_insn (gen_ashldi3_neon_noclobber (operands[0], operands[1],
1093                                                operands[2]));
1094       }
1095     else
1096       {
1097         if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
1098           /* This clobbers CC.  */
1099           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
1100         else
1101           arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
1102                                          operands[2], operands[3], operands[4]);
1103       }
1104     DONE;
1105   }"
1106   [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
1107    (set_attr "opt" "*,*,speed,speed,*,*")]
1110 ; The shift amount needs to be negated for right-shifts
1111 (define_insn "signed_shift_di3_neon"
1112   [(set (match_operand:DI 0 "s_register_operand"             "=w")
1113         (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
1114                     (match_operand:DI 2 "s_register_operand" " w")]
1115                    UNSPEC_ASHIFT_SIGNED))]
1116   "TARGET_NEON && reload_completed"
1117   "vshl.s64\t%P0, %P1, %P2"
1118   [(set_attr "neon_type" "neon_vshl_ddd")]
1121 ; The shift amount needs to be negated for right-shifts
1122 (define_insn "unsigned_shift_di3_neon"
1123   [(set (match_operand:DI 0 "s_register_operand"             "=w")
1124         (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
1125                     (match_operand:DI 2 "s_register_operand" " w")]
1126                    UNSPEC_ASHIFT_UNSIGNED))]
1127   "TARGET_NEON && reload_completed"
1128   "vshl.u64\t%P0, %P1, %P2"
1129   [(set_attr "neon_type" "neon_vshl_ddd")]
1132 (define_insn "ashrdi3_neon_imm_noclobber"
1133   [(set (match_operand:DI 0 "s_register_operand"              "=w")
1134         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
1135                      (match_operand:DI 2 "const_int_operand"  " i")))]
1136   "TARGET_NEON && reload_completed
1137    && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
1138   "vshr.s64\t%P0, %P1, %2"
1139   [(set_attr "neon_type" "neon_vshl_ddd")]
1142 (define_insn "lshrdi3_neon_imm_noclobber"
1143   [(set (match_operand:DI 0 "s_register_operand"              "=w")
1144         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
1145                      (match_operand:DI 2 "const_int_operand"  " i")))]
1146   "TARGET_NEON && reload_completed
1147    && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
1148   "vshr.u64\t%P0, %P1, %2"
1149   [(set_attr "neon_type" "neon_vshl_ddd")]
1152 ;; ashrdi3_neon
1153 ;; lshrdi3_neon
1154 (define_insn_and_split "<shift>di3_neon"
1155   [(set (match_operand:DI 0 "s_register_operand"             "= w, w,?&r,?r,?w,?w")
1156         (rshifts:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r,0w, w")
1157                     (match_operand:SI 2 "reg_or_int_operand" "  r, i,  r, i, r, i")))
1158    (clobber (match_scratch:SI 3                              "=2r, X, &r, X,2r, X"))
1159    (clobber (match_scratch:SI 4                              "= X, X, &r, X, X, X"))
1160    (clobber (match_scratch:DI 5                              "=&w, X,  X, X,&w, X"))
1161    (clobber (reg:CC CC_REGNUM))]
1162   "TARGET_NEON"
1163   "#"
1164   "TARGET_NEON && reload_completed"
1165   [(const_int 0)]
1166   "
1167   {
1168     if (IS_VFP_REGNUM (REGNO (operands[0])))
1169       {
1170         if (CONST_INT_P (operands[2]))
1171           {
1172             if (INTVAL (operands[2]) < 1)
1173               {
1174                 emit_insn (gen_movdi (operands[0], operands[1]));
1175                 DONE;
1176               }
1177             else if (INTVAL (operands[2]) > 64)
1178               operands[2] = gen_rtx_CONST_INT (VOIDmode, 64);
1180             /* Ditch the unnecessary clobbers.  */
1181             emit_insn (gen_<shift>di3_neon_imm_noclobber (operands[0],
1182                                                           operands[1],
1183                                                           operands[2]));
1184           }
1185         else 
1186           {
1187             /* We must use a negative left-shift.  */
1188             emit_insn (gen_negsi2 (operands[3], operands[2]));
1189             emit_insn (gen_neon_load_count (operands[5], operands[3]));
1190             emit_insn (gen_<shifttype>_shift_di3_neon (operands[0], operands[1],
1191                                                        operands[5]));
1192           }
1193       }
1194     else
1195       {
1196         if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
1197           /* This clobbers CC.  */
1198           emit_insn (gen_arm_<shift>di3_1bit (operands[0], operands[1]));
1199         else
1200           /* This clobbers CC (ASHIFTRT by register only).  */
1201           arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
1202                                          operands[2], operands[3], operands[4]);
1203       }
1205     DONE;
1206   }"
1207   [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
1208    (set_attr "opt" "*,*,speed,speed,*,*")]
1211 ;; Widening operations
1213 (define_insn "widen_ssum<mode>3"
1214   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1215         (plus:<V_widen> (sign_extend:<V_widen>
1216                           (match_operand:VW 1 "s_register_operand" "%w"))
1217                         (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1218   "TARGET_NEON"
1219   "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1220   [(set_attr "neon_type" "neon_int_3")]
1223 (define_insn "widen_usum<mode>3"
1224   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1225         (plus:<V_widen> (zero_extend:<V_widen>
1226                           (match_operand:VW 1 "s_register_operand" "%w"))
1227                         (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1228   "TARGET_NEON"
1229   "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1230   [(set_attr "neon_type" "neon_int_3")]
1233 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1234 ;; shift-count granularity. That's good enough for the middle-end's current
1235 ;; needs.
1237 ;; Note that it's not safe to perform such an operation in big-endian mode,
1238 ;; due to element-ordering issues.
1240 (define_expand "vec_shr_<mode>"
1241   [(match_operand:VDQ 0 "s_register_operand" "")
1242    (match_operand:VDQ 1 "s_register_operand" "")
1243    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1244   "TARGET_NEON && !BYTES_BIG_ENDIAN"
1246   rtx zero_reg;
1247   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1248   const int width = GET_MODE_BITSIZE (<MODE>mode);
1249   const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1250   rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1251     (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1253   if (num_bits == width)
1254     {
1255       emit_move_insn (operands[0], operands[1]);
1256       DONE;
1257     }
1259   zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1260   operands[0] = gen_lowpart (bvecmode, operands[0]);
1261   operands[1] = gen_lowpart (bvecmode, operands[1]);
1263   emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1264                       GEN_INT (num_bits / BITS_PER_UNIT)));
1265   DONE;
1268 (define_expand "vec_shl_<mode>"
1269   [(match_operand:VDQ 0 "s_register_operand" "")
1270    (match_operand:VDQ 1 "s_register_operand" "")
1271    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1272   "TARGET_NEON && !BYTES_BIG_ENDIAN"
1274   rtx zero_reg;
1275   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1276   const int width = GET_MODE_BITSIZE (<MODE>mode);
1277   const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1278   rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1279     (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1281   if (num_bits == 0)
1282     {
1283       emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1284       DONE;
1285     }
1287   num_bits = width - num_bits;
1289   zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1290   operands[0] = gen_lowpart (bvecmode, operands[0]);
1291   operands[1] = gen_lowpart (bvecmode, operands[1]);
1293   emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1294                       GEN_INT (num_bits / BITS_PER_UNIT)));
1295   DONE;
1298 ;; Helpers for quad-word reduction operations
1300 ; Add (or smin, smax...) the low N/2 elements of the N-element vector
1301 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1302 ; N/2-element vector.
1304 (define_insn "quad_halves_<code>v4si"
1305   [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1306         (vqh_ops:V2SI
1307           (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1308                            (parallel [(const_int 0) (const_int 1)]))
1309           (vec_select:V2SI (match_dup 1)
1310                            (parallel [(const_int 2) (const_int 3)]))))]
1311   "TARGET_NEON"
1312   "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
1313   [(set_attr "vqh_mnem" "<VQH_mnem>")
1314    (set (attr "neon_type")
1315       (if_then_else (eq_attr "vqh_mnem" "vadd")
1316                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1319 (define_insn "quad_halves_<code>v4sf"
1320   [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1321         (vqhs_ops:V2SF
1322           (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1323                            (parallel [(const_int 0) (const_int 1)]))
1324           (vec_select:V2SF (match_dup 1)
1325                            (parallel [(const_int 2) (const_int 3)]))))]
1326   "TARGET_NEON && flag_unsafe_math_optimizations"
1327   "<VQH_mnem>.f32\t%P0, %e1, %f1"
1328   [(set_attr "vqh_mnem" "<VQH_mnem>")
1329    (set (attr "neon_type")
1330       (if_then_else (eq_attr "vqh_mnem" "vadd")
1331                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1334 (define_insn "quad_halves_<code>v8hi"
1335   [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1336         (vqh_ops:V4HI
1337           (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1338                            (parallel [(const_int 0) (const_int 1)
1339                                       (const_int 2) (const_int 3)]))
1340           (vec_select:V4HI (match_dup 1)
1341                            (parallel [(const_int 4) (const_int 5)
1342                                       (const_int 6) (const_int 7)]))))]
1343   "TARGET_NEON"
1344   "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
1345   [(set_attr "vqh_mnem" "<VQH_mnem>")
1346    (set (attr "neon_type")
1347       (if_then_else (eq_attr "vqh_mnem" "vadd")
1348                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1351 (define_insn "quad_halves_<code>v16qi"
1352   [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1353         (vqh_ops:V8QI
1354           (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1355                            (parallel [(const_int 0) (const_int 1)
1356                                       (const_int 2) (const_int 3)
1357                                       (const_int 4) (const_int 5)
1358                                       (const_int 6) (const_int 7)]))
1359           (vec_select:V8QI (match_dup 1)
1360                            (parallel [(const_int 8) (const_int 9)
1361                                       (const_int 10) (const_int 11)
1362                                       (const_int 12) (const_int 13)
1363                                       (const_int 14) (const_int 15)]))))]
1364   "TARGET_NEON"
1365   "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
1366   [(set_attr "vqh_mnem" "<VQH_mnem>")
1367    (set (attr "neon_type")
1368       (if_then_else (eq_attr "vqh_mnem" "vadd")
1369                     (const_string "neon_int_1") (const_string "neon_int_5")))]
1372 (define_expand "move_hi_quad_<mode>"
1373  [(match_operand:ANY128 0 "s_register_operand" "")
1374   (match_operand:<V_HALF> 1 "s_register_operand" "")]
1375  "TARGET_NEON"
1377   emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0], <MODE>mode,
1378                                        GET_MODE_SIZE (<V_HALF>mode)),
1379                   operands[1]);
1380   DONE;
1383 (define_expand "move_lo_quad_<mode>"
1384  [(match_operand:ANY128 0 "s_register_operand" "")
1385   (match_operand:<V_HALF> 1 "s_register_operand" "")]
1386  "TARGET_NEON"
1388   emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0],
1389                                        <MODE>mode, 0),
1390                   operands[1]);
1391   DONE;
1394 ;; Reduction operations
1396 (define_expand "reduc_splus_<mode>"
1397   [(match_operand:VD 0 "s_register_operand" "")
1398    (match_operand:VD 1 "s_register_operand" "")]
1399   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1401   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1402                         &gen_neon_vpadd_internal<mode>);
1403   DONE;
1406 (define_expand "reduc_splus_<mode>"
1407   [(match_operand:VQ 0 "s_register_operand" "")
1408    (match_operand:VQ 1 "s_register_operand" "")]
1409   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1410    && !BYTES_BIG_ENDIAN"
1412   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1413   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1415   emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
1416   emit_insn (gen_reduc_splus_<V_half> (res_d, step1));
1417   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1419   DONE;
1422 (define_insn "reduc_splus_v2di"
1423   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1424         (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1425                      UNSPEC_VPADD))]
1426   "TARGET_NEON && !BYTES_BIG_ENDIAN"
1427   "vadd.i64\t%e0, %e1, %f1"
1428   [(set_attr "neon_type" "neon_int_1")]
1431 ;; NEON does not distinguish between signed and unsigned addition except on
1432 ;; widening operations.
1433 (define_expand "reduc_uplus_<mode>"
1434   [(match_operand:VDQI 0 "s_register_operand" "")
1435    (match_operand:VDQI 1 "s_register_operand" "")]
1436   "TARGET_NEON && (<Is_d_reg> || !BYTES_BIG_ENDIAN)"
1438   emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
1439   DONE;
1442 (define_expand "reduc_smin_<mode>"
1443   [(match_operand:VD 0 "s_register_operand" "")
1444    (match_operand:VD 1 "s_register_operand" "")]
1445   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1447   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1448                         &gen_neon_vpsmin<mode>);
1449   DONE;
1452 (define_expand "reduc_smin_<mode>"
1453   [(match_operand:VQ 0 "s_register_operand" "")
1454    (match_operand:VQ 1 "s_register_operand" "")]
1455   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1456    && !BYTES_BIG_ENDIAN"
1458   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1459   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1461   emit_insn (gen_quad_halves_smin<mode> (step1, operands[1]));
1462   emit_insn (gen_reduc_smin_<V_half> (res_d, step1));
1463   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1465   DONE;
1468 (define_expand "reduc_smax_<mode>"
1469   [(match_operand:VD 0 "s_register_operand" "")
1470    (match_operand:VD 1 "s_register_operand" "")]
1471   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1473   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1474                         &gen_neon_vpsmax<mode>);
1475   DONE;
1478 (define_expand "reduc_smax_<mode>"
1479   [(match_operand:VQ 0 "s_register_operand" "")
1480    (match_operand:VQ 1 "s_register_operand" "")]
1481   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1482    && !BYTES_BIG_ENDIAN"
1484   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1485   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1487   emit_insn (gen_quad_halves_smax<mode> (step1, operands[1]));
1488   emit_insn (gen_reduc_smax_<V_half> (res_d, step1));
1489   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1491   DONE;
1494 (define_expand "reduc_umin_<mode>"
1495   [(match_operand:VDI 0 "s_register_operand" "")
1496    (match_operand:VDI 1 "s_register_operand" "")]
1497   "TARGET_NEON"
1499   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1500                         &gen_neon_vpumin<mode>);
1501   DONE;
1504 (define_expand "reduc_umin_<mode>"
1505   [(match_operand:VQI 0 "s_register_operand" "")
1506    (match_operand:VQI 1 "s_register_operand" "")]
1507   "TARGET_NEON && !BYTES_BIG_ENDIAN"
1509   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1510   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1512   emit_insn (gen_quad_halves_umin<mode> (step1, operands[1]));
1513   emit_insn (gen_reduc_umin_<V_half> (res_d, step1));
1514   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1516   DONE;
1519 (define_expand "reduc_umax_<mode>"
1520   [(match_operand:VDI 0 "s_register_operand" "")
1521    (match_operand:VDI 1 "s_register_operand" "")]
1522   "TARGET_NEON"
1524   neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1525                         &gen_neon_vpumax<mode>);
1526   DONE;
1529 (define_expand "reduc_umax_<mode>"
1530   [(match_operand:VQI 0 "s_register_operand" "")
1531    (match_operand:VQI 1 "s_register_operand" "")]
1532   "TARGET_NEON && !BYTES_BIG_ENDIAN"
1534   rtx step1 = gen_reg_rtx (<V_HALF>mode);
1535   rtx res_d = gen_reg_rtx (<V_HALF>mode);
1537   emit_insn (gen_quad_halves_umax<mode> (step1, operands[1]));
1538   emit_insn (gen_reduc_umax_<V_half> (res_d, step1));
1539   emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1541   DONE;
1544 (define_insn "neon_vpadd_internal<mode>"
1545   [(set (match_operand:VD 0 "s_register_operand" "=w")
1546         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1547                     (match_operand:VD 2 "s_register_operand" "w")]
1548                    UNSPEC_VPADD))]
1549   "TARGET_NEON"
1550   "vpadd.<V_if_elem>\t%P0, %P1, %P2"
1551   ;; Assume this schedules like vadd.
1552   [(set (attr "neon_type")
1553       (if_then_else (match_test "<Is_float_mode>")
1554                     (if_then_else (match_test "<Is_d_reg>")
1555                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1556                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1557                     (const_string "neon_int_1")))]
1560 (define_insn "neon_vpsmin<mode>"
1561   [(set (match_operand:VD 0 "s_register_operand" "=w")
1562         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1563                     (match_operand:VD 2 "s_register_operand" "w")]
1564                    UNSPEC_VPSMIN))]
1565   "TARGET_NEON"
1566   "vpmin.<V_s_elem>\t%P0, %P1, %P2"
1567   ;; Assume this schedules like vmin.
1568   [(set (attr "neon_type")
1569       (if_then_else (match_test "<Is_float_mode>")
1570                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1571                     (const_string "neon_int_5")))]
1574 (define_insn "neon_vpsmax<mode>"
1575   [(set (match_operand:VD 0 "s_register_operand" "=w")
1576         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1577                     (match_operand:VD 2 "s_register_operand" "w")]
1578                    UNSPEC_VPSMAX))]
1579   "TARGET_NEON"
1580   "vpmax.<V_s_elem>\t%P0, %P1, %P2"
1581   ;; Assume this schedules like vmax.
1582   [(set (attr "neon_type")
1583       (if_then_else (match_test "<Is_float_mode>")
1584                     (const_string "neon_fp_vadd_ddd_vabs_dd")
1585                     (const_string "neon_int_5")))]
1588 (define_insn "neon_vpumin<mode>"
1589   [(set (match_operand:VDI 0 "s_register_operand" "=w")
1590         (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1591                      (match_operand:VDI 2 "s_register_operand" "w")]
1592                    UNSPEC_VPUMIN))]
1593   "TARGET_NEON"
1594   "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1595   ;; Assume this schedules like umin.
1596   [(set_attr "neon_type" "neon_int_5")]
1599 (define_insn "neon_vpumax<mode>"
1600   [(set (match_operand:VDI 0 "s_register_operand" "=w")
1601         (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1602                      (match_operand:VDI 2 "s_register_operand" "w")]
1603                    UNSPEC_VPUMAX))]
1604   "TARGET_NEON"
1605   "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1606   ;; Assume this schedules like umax.
1607   [(set_attr "neon_type" "neon_int_5")]
1610 ;; Saturating arithmetic
1612 ; NOTE: Neon supports many more saturating variants of instructions than the
1613 ; following, but these are all GCC currently understands.
1614 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1615 ; yet either, although these patterns may be used by intrinsics when they're
1616 ; added.
1618 (define_insn "*ss_add<mode>_neon"
1619   [(set (match_operand:VD 0 "s_register_operand" "=w")
1620        (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1621                    (match_operand:VD 2 "s_register_operand" "w")))]
1622   "TARGET_NEON"
1623   "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1624   [(set_attr "neon_type" "neon_int_4")]
1627 (define_insn "*us_add<mode>_neon"
1628   [(set (match_operand:VD 0 "s_register_operand" "=w")
1629        (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1630                    (match_operand:VD 2 "s_register_operand" "w")))]
1631   "TARGET_NEON"
1632   "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1633   [(set_attr "neon_type" "neon_int_4")]
1636 (define_insn "*ss_sub<mode>_neon"
1637   [(set (match_operand:VD 0 "s_register_operand" "=w")
1638        (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1639                     (match_operand:VD 2 "s_register_operand" "w")))]
1640   "TARGET_NEON"
1641   "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1642   [(set_attr "neon_type" "neon_int_5")]
1645 (define_insn "*us_sub<mode>_neon"
1646   [(set (match_operand:VD 0 "s_register_operand" "=w")
1647        (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1648                     (match_operand:VD 2 "s_register_operand" "w")))]
1649   "TARGET_NEON"
1650   "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1651   [(set_attr "neon_type" "neon_int_5")]
1654 ;; Conditional instructions.  These are comparisons with conditional moves for
1655 ;; vectors.  They perform the assignment:
1656 ;;   
1657 ;;     Vop0 = (Vop4 <op3> Vop5) ? Vop1 : Vop2;
1659 ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
1660 ;; element-wise.
1662 (define_expand "vcond<mode><mode>"
1663   [(set (match_operand:VDQW 0 "s_register_operand" "")
1664         (if_then_else:VDQW
1665           (match_operator 3 "comparison_operator"
1666             [(match_operand:VDQW 4 "s_register_operand" "")
1667              (match_operand:VDQW 5 "nonmemory_operand" "")])
1668           (match_operand:VDQW 1 "s_register_operand" "")
1669           (match_operand:VDQW 2 "s_register_operand" "")))]
1670   "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1672   HOST_WIDE_INT magic_word = (<MODE>mode == V2SFmode || <MODE>mode == V4SFmode)
1673                              ? 3 : 1;
1674   rtx magic_rtx = GEN_INT (magic_word);
1675   int inverse = 0;
1676   int swap_bsl_operands = 0;
1677   rtx mask = gen_reg_rtx (<V_cmp_result>mode);
1678   rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
1680   rtx (*base_comparison) (rtx, rtx, rtx, rtx);
1681   rtx (*complimentary_comparison) (rtx, rtx, rtx, rtx);
1683   switch (GET_CODE (operands[3]))
1684     {
1685     case GE:
1686     case LE:
1687     case EQ:
1688       if (!REG_P (operands[5])
1689           && (operands[5] != CONST0_RTX (<MODE>mode)))
1690         operands[5] = force_reg (<MODE>mode, operands[5]);
1691       break;
1692     default:
1693       if (!REG_P (operands[5]))
1694         operands[5] = force_reg (<MODE>mode, operands[5]);
1695     }
1697   switch (GET_CODE (operands[3]))
1698     {
1699     case LT:
1700     case UNLT:
1701       inverse = 1;
1702       /* Fall through.  */
1703     case GE:
1704     case UNGE:
1705     case ORDERED:
1706     case UNORDERED:
1707       base_comparison = gen_neon_vcge<mode>;
1708       complimentary_comparison = gen_neon_vcgt<mode>;
1709       break;
1710     case LE:
1711     case UNLE:
1712       inverse = 1;
1713       /* Fall through.  */
1714     case GT:
1715     case UNGT:
1716       base_comparison = gen_neon_vcgt<mode>;
1717       complimentary_comparison = gen_neon_vcge<mode>;
1718       break;
1719     case EQ:
1720     case NE:
1721     case UNEQ:
1722       base_comparison = gen_neon_vceq<mode>;
1723       complimentary_comparison = gen_neon_vceq<mode>;
1724       break;
1725     default:
1726       gcc_unreachable ();
1727     }
1729   switch (GET_CODE (operands[3]))
1730     {
1731     case LT:
1732     case LE:
1733     case GT:
1734     case GE:
1735     case EQ:
1736       /* The easy case.  Here we emit one of vcge, vcgt or vceq.
1737          As a LT b <=> b GE a && a LE b <=> b GT a.  Our transformations are:
1738          a GE b -> a GE b
1739          a GT b -> a GT b
1740          a LE b -> b GE a
1741          a LT b -> b GT a
1742          a EQ b -> a EQ b  */
1744       if (!inverse)
1745         emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));
1746       else
1747         emit_insn (complimentary_comparison (mask, operands[5], operands[4], magic_rtx));
1748       break;
1749     case UNLT:
1750     case UNLE:
1751     case UNGT:
1752     case UNGE:
1753     case NE:
1754       /* Vector compare returns false for lanes which are unordered, so if we use
1755          the inverse of the comparison we actually want to emit, then
1756          swap the operands to BSL, we will end up with the correct result.
1757          Note that a NE NaN and NaN NE b are true for all a, b.
1759          Our transformations are:
1760          a GE b -> !(b GT a)
1761          a GT b -> !(b GE a)
1762          a LE b -> !(a GT b)
1763          a LT b -> !(a GE b)
1764          a NE b -> !(a EQ b)  */
1766       if (inverse)
1767         emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));
1768       else
1769         emit_insn (complimentary_comparison (mask, operands[5], operands[4], magic_rtx));
1771       swap_bsl_operands = 1;
1772       break;
1773     case UNEQ:
1774       /* We check (a > b ||  b > a).  combining these comparisons give us
1775          true iff !(a != b && a ORDERED b), swapping the operands to BSL
1776          will then give us (a == b ||  a UNORDERED b) as intended.  */
1778       emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5], magic_rtx));
1779       emit_insn (gen_neon_vcgt<mode> (tmp, operands[5], operands[4], magic_rtx));
1780       emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1781       swap_bsl_operands = 1;
1782       break;
1783     case UNORDERED:
1784        /* Operands are ORDERED iff (a > b || b >= a).
1785          Swapping the operands to BSL will give the UNORDERED case.  */
1786      swap_bsl_operands = 1;
1787      /* Fall through.  */
1788     case ORDERED:
1789       emit_insn (gen_neon_vcgt<mode> (tmp, operands[4], operands[5], magic_rtx));
1790       emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4], magic_rtx));
1791       emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1792       break;
1793     default:
1794       gcc_unreachable ();
1795     }
1797   if (swap_bsl_operands)
1798     emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1799                                     operands[1]));
1800   else
1801     emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1802                                     operands[2]));
1803   DONE;
1806 (define_expand "vcondu<mode><mode>"
1807   [(set (match_operand:VDQIW 0 "s_register_operand" "")
1808         (if_then_else:VDQIW
1809           (match_operator 3 "arm_comparison_operator"
1810             [(match_operand:VDQIW 4 "s_register_operand" "")
1811              (match_operand:VDQIW 5 "s_register_operand" "")])
1812           (match_operand:VDQIW 1 "s_register_operand" "")
1813           (match_operand:VDQIW 2 "s_register_operand" "")))]
1814   "TARGET_NEON"
1816   rtx mask;
1817   int inverse = 0, immediate_zero = 0;
1818   
1819   mask = gen_reg_rtx (<V_cmp_result>mode);
1820   
1821   if (operands[5] == CONST0_RTX (<MODE>mode))
1822     immediate_zero = 1;
1823   else if (!REG_P (operands[5]))
1824     operands[5] = force_reg (<MODE>mode, operands[5]);
1825   
1826   switch (GET_CODE (operands[3]))
1827     {
1828     case GEU:
1829       emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1830                                       const0_rtx));
1831       break;
1832     
1833     case GTU:
1834       emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1835                                       const0_rtx));
1836       break;
1837     
1838     case EQ:
1839       emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1840                                       const0_rtx));
1841       break;
1842     
1843     case LEU:
1844       if (immediate_zero)
1845         emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1846                                         const0_rtx));
1847       else
1848         emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1849                                         const0_rtx));
1850       break;
1851     
1852     case LTU:
1853       if (immediate_zero)
1854         emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1855                                         const0_rtx));
1856       else
1857         emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1858                                         const0_rtx));
1859       break;
1860     
1861     case NE:
1862       emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1863                                       const0_rtx));
1864       inverse = 1;
1865       break;
1866     
1867     default:
1868       gcc_unreachable ();
1869     }
1870   
1871   if (inverse)
1872     emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1873                                     operands[1]));
1874   else
1875     emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1876                                     operands[2]));
1878   DONE;
1881 ;; Patterns for builtins.
1883 ; good for plain vadd, vaddq.
1885 (define_expand "neon_vadd<mode>"
1886   [(match_operand:VDQX 0 "s_register_operand" "=w")
1887    (match_operand:VDQX 1 "s_register_operand" "w")
1888    (match_operand:VDQX 2 "s_register_operand" "w")
1889    (match_operand:SI 3 "immediate_operand" "i")]
1890   "TARGET_NEON"
1892   if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1893     emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2]));
1894   else
1895     emit_insn (gen_neon_vadd<mode>_unspec (operands[0], operands[1],
1896                                            operands[2]));
1897   DONE;
1900 ; Note that NEON operations don't support the full IEEE 754 standard: in
1901 ; particular, denormal values are flushed to zero.  This means that GCC cannot
1902 ; use those instructions for autovectorization, etc. unless
1903 ; -funsafe-math-optimizations is in effect (in which case flush-to-zero
1904 ; behaviour is permissible).  Intrinsic operations (provided by the arm_neon.h
1905 ; header) must work in either case: if -funsafe-math-optimizations is given,
1906 ; intrinsics expand to "canonical" RTL where possible, otherwise intrinsics
1907 ; expand to unspecs (which may potentially limit the extent to which they might
1908 ; be optimized by generic code).
1910 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
1912 (define_insn "neon_vadd<mode>_unspec"
1913   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1914         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1915                       (match_operand:VDQX 2 "s_register_operand" "w")]
1916                      UNSPEC_VADD))]
1917   "TARGET_NEON"
1918   "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1919   [(set (attr "neon_type")
1920       (if_then_else (match_test "<Is_float_mode>")
1921                     (if_then_else (match_test "<Is_d_reg>")
1922                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
1923                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
1924                     (const_string "neon_int_1")))]
1927 ; operand 3 represents in bits:
1928 ;  bit 0: signed (vs unsigned).
1929 ;  bit 1: rounding (vs none).
1931 (define_insn "neon_vaddl<mode>"
1932   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1933         (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1934                            (match_operand:VDI 2 "s_register_operand" "w")
1935                            (match_operand:SI 3 "immediate_operand" "i")]
1936                           UNSPEC_VADDL))]
1937   "TARGET_NEON"
1938   "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1939   [(set_attr "neon_type" "neon_int_3")]
1942 (define_insn "neon_vaddw<mode>"
1943   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1944         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1945                            (match_operand:VDI 2 "s_register_operand" "w")
1946                            (match_operand:SI 3 "immediate_operand" "i")]
1947                           UNSPEC_VADDW))]
1948   "TARGET_NEON"
1949   "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1950   [(set_attr "neon_type" "neon_int_2")]
1953 ; vhadd and vrhadd.
1955 (define_insn "neon_vhadd<mode>"
1956   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1957         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1958                        (match_operand:VDQIW 2 "s_register_operand" "w")
1959                        (match_operand:SI 3 "immediate_operand" "i")]
1960                       UNSPEC_VHADD))]
1961   "TARGET_NEON"
1962   "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1963   [(set_attr "neon_type" "neon_int_4")]
1966 (define_insn "neon_vqadd<mode>"
1967   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1968         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1969                        (match_operand:VDQIX 2 "s_register_operand" "w")
1970                        (match_operand:SI 3 "immediate_operand" "i")]
1971                      UNSPEC_VQADD))]
1972   "TARGET_NEON"
1973   "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1974   [(set_attr "neon_type" "neon_int_4")]
1977 (define_insn "neon_vaddhn<mode>"
1978   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
1979         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
1980                             (match_operand:VN 2 "s_register_operand" "w")
1981                             (match_operand:SI 3 "immediate_operand" "i")]
1982                            UNSPEC_VADDHN))]
1983   "TARGET_NEON"
1984   "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1985   [(set_attr "neon_type" "neon_int_4")]
1988 ;; We cannot replace this unspec with mul<mode>3 because of the odd 
1989 ;; polynomial multiplication case that can specified by operand 3.
1990 (define_insn "neon_vmul<mode>"
1991   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1992         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1993                       (match_operand:VDQW 2 "s_register_operand" "w")
1994                       (match_operand:SI 3 "immediate_operand" "i")]
1995                      UNSPEC_VMUL))]
1996   "TARGET_NEON"
1997   "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1998   [(set (attr "neon_type")
1999       (if_then_else (match_test "<Is_float_mode>")
2000                     (if_then_else (match_test "<Is_d_reg>")
2001                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2002                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2003                     (if_then_else (match_test "<Is_d_reg>")
2004                                   (if_then_else
2005                                     (match_test "<Scalar_mul_8_16>")
2006                                     (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2007                                     (const_string "neon_mul_qqq_8_16_32_ddd_32"))
2008                                   (if_then_else (match_test "<Scalar_mul_8_16>")
2009                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")
2010                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
2013 (define_expand "neon_vmla<mode>"
2014   [(match_operand:VDQW 0 "s_register_operand" "=w")
2015    (match_operand:VDQW 1 "s_register_operand" "0")
2016    (match_operand:VDQW 2 "s_register_operand" "w")
2017    (match_operand:VDQW 3 "s_register_operand" "w")
2018    (match_operand:SI 4 "immediate_operand" "i")]
2019   "TARGET_NEON"
2021   if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2022     emit_insn (gen_mul<mode>3add<mode>_neon (operands[0], operands[1],
2023                                              operands[2], operands[3]));
2024   else
2025     emit_insn (gen_neon_vmla<mode>_unspec (operands[0], operands[1],
2026                                            operands[2], operands[3]));
2027   DONE;
2030 (define_expand "neon_vfma<VCVTF:mode>"
2031   [(match_operand:VCVTF 0 "s_register_operand")
2032    (match_operand:VCVTF 1 "s_register_operand")
2033    (match_operand:VCVTF 2 "s_register_operand")
2034    (match_operand:VCVTF 3 "s_register_operand")
2035    (match_operand:SI 4 "immediate_operand")]
2036   "TARGET_NEON && TARGET_FMA"
2038   emit_insn (gen_fma<mode>4_intrinsic (operands[0], operands[2], operands[3],
2039                                        operands[1]));
2040   DONE;
2043 (define_expand "neon_vfms<VCVTF:mode>"
2044   [(match_operand:VCVTF 0 "s_register_operand")
2045    (match_operand:VCVTF 1 "s_register_operand")
2046    (match_operand:VCVTF 2 "s_register_operand")
2047    (match_operand:VCVTF 3 "s_register_operand")
2048    (match_operand:SI 4 "immediate_operand")]
2049   "TARGET_NEON && TARGET_FMA"
2051   emit_insn (gen_fmsub<mode>4_intrinsic (operands[0], operands[2], operands[3],
2052                                          operands[1]));
2053   DONE;
2056 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2058 (define_insn "neon_vmla<mode>_unspec"
2059   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
2060         (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
2061                      (match_operand:VDQ 2 "s_register_operand" "w")
2062                      (match_operand:VDQ 3 "s_register_operand" "w")]
2063                     UNSPEC_VMLA))]
2064   "TARGET_NEON"
2065   "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2066   [(set (attr "neon_type")
2067       (if_then_else (match_test "<Is_float_mode>")
2068                     (if_then_else (match_test "<Is_d_reg>")
2069                                   (const_string "neon_fp_vmla_ddd")
2070                                   (const_string "neon_fp_vmla_qqq"))
2071                     (if_then_else (match_test "<Is_d_reg>")
2072                                   (if_then_else
2073                                     (match_test "<Scalar_mul_8_16>")
2074                                     (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2075                                     (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
2076                                   (if_then_else (match_test "<Scalar_mul_8_16>")
2077                                     (const_string "neon_mla_qqq_8_16")
2078                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
2081 (define_insn "neon_vmlal<mode>"
2082   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2083         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2084                            (match_operand:VW 2 "s_register_operand" "w")
2085                            (match_operand:VW 3 "s_register_operand" "w")
2086                            (match_operand:SI 4 "immediate_operand" "i")]
2087                           UNSPEC_VMLAL))]
2088   "TARGET_NEON"
2089   "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2090   [(set (attr "neon_type")
2091      (if_then_else (match_test "<Scalar_mul_8_16>")
2092                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2093                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2096 (define_expand "neon_vmls<mode>"
2097   [(match_operand:VDQW 0 "s_register_operand" "=w")
2098    (match_operand:VDQW 1 "s_register_operand" "0")
2099    (match_operand:VDQW 2 "s_register_operand" "w")
2100    (match_operand:VDQW 3 "s_register_operand" "w")
2101    (match_operand:SI 4 "immediate_operand" "i")]
2102   "TARGET_NEON"
2104   if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2105     emit_insn (gen_mul<mode>3neg<mode>add<mode>_neon (operands[0],
2106                  operands[1], operands[2], operands[3]));
2107   else
2108     emit_insn (gen_neon_vmls<mode>_unspec (operands[0], operands[1],
2109                                            operands[2], operands[3]));
2110   DONE;
2113 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2115 (define_insn "neon_vmls<mode>_unspec"
2116   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
2117         (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
2118                      (match_operand:VDQ 2 "s_register_operand" "w")
2119                      (match_operand:VDQ 3 "s_register_operand" "w")]
2120                     UNSPEC_VMLS))]
2121   "TARGET_NEON"
2122   "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2123   [(set (attr "neon_type")
2124       (if_then_else (match_test "<Is_float_mode>")
2125                     (if_then_else (match_test "<Is_d_reg>")
2126                                   (const_string "neon_fp_vmla_ddd")
2127                                   (const_string "neon_fp_vmla_qqq"))
2128                     (if_then_else (match_test "<Is_d_reg>")
2129                                   (if_then_else
2130                                     (match_test "<Scalar_mul_8_16>")
2131                                     (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2132                                     (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
2133                                   (if_then_else
2134                                     (match_test "<Scalar_mul_8_16>")
2135                                     (const_string "neon_mla_qqq_8_16")
2136                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
2139 (define_insn "neon_vmlsl<mode>"
2140   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2141         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2142                            (match_operand:VW 2 "s_register_operand" "w")
2143                            (match_operand:VW 3 "s_register_operand" "w")
2144                            (match_operand:SI 4 "immediate_operand" "i")]
2145                           UNSPEC_VMLSL))]
2146   "TARGET_NEON"
2147   "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2148   [(set (attr "neon_type")
2149      (if_then_else (match_test "<Scalar_mul_8_16>")
2150                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2151                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2154 (define_insn "neon_vqdmulh<mode>"
2155   [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
2156         (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
2157                        (match_operand:VMDQI 2 "s_register_operand" "w")
2158                        (match_operand:SI 3 "immediate_operand" "i")]
2159                       UNSPEC_VQDMULH))]
2160   "TARGET_NEON"
2161   "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2162   [(set (attr "neon_type")
2163      (if_then_else (match_test "<Is_d_reg>")
2164         (if_then_else (match_test "<Scalar_mul_8_16>")
2165                       (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2166                       (const_string "neon_mul_qqq_8_16_32_ddd_32"))
2167         (if_then_else (match_test "<Scalar_mul_8_16>")
2168                       (const_string "neon_mul_qqq_8_16_32_ddd_32")
2169                       (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
2172 (define_insn "neon_vqdmlal<mode>"
2173   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2174         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2175                            (match_operand:VMDI 2 "s_register_operand" "w")
2176                            (match_operand:VMDI 3 "s_register_operand" "w")
2177                            (match_operand:SI 4 "immediate_operand" "i")]
2178                           UNSPEC_VQDMLAL))]
2179   "TARGET_NEON"
2180   "vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
2181   [(set (attr "neon_type")
2182      (if_then_else (match_test "<Scalar_mul_8_16>")
2183                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2184                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2187 (define_insn "neon_vqdmlsl<mode>"
2188   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2189         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2190                            (match_operand:VMDI 2 "s_register_operand" "w")
2191                            (match_operand:VMDI 3 "s_register_operand" "w")
2192                            (match_operand:SI 4 "immediate_operand" "i")]
2193                           UNSPEC_VQDMLSL))]
2194   "TARGET_NEON"
2195   "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
2196   [(set (attr "neon_type")
2197      (if_then_else (match_test "<Scalar_mul_8_16>")
2198                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2199                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2202 (define_insn "neon_vmull<mode>"
2203   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2204         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2205                            (match_operand:VW 2 "s_register_operand" "w")
2206                            (match_operand:SI 3 "immediate_operand" "i")]
2207                           UNSPEC_VMULL))]
2208   "TARGET_NEON"
2209   "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2210   [(set (attr "neon_type")
2211      (if_then_else (match_test "<Scalar_mul_8_16>")
2212                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2213                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2216 (define_insn "neon_vqdmull<mode>"
2217   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2218         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2219                            (match_operand:VMDI 2 "s_register_operand" "w")
2220                            (match_operand:SI 3 "immediate_operand" "i")]
2221                           UNSPEC_VQDMULL))]
2222   "TARGET_NEON"
2223   "vqdmull.<V_s_elem>\t%q0, %P1, %P2"
2224   [(set (attr "neon_type")
2225      (if_then_else (match_test "<Scalar_mul_8_16>")
2226                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2227                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2230 (define_expand "neon_vsub<mode>"
2231   [(match_operand:VDQX 0 "s_register_operand" "=w")
2232    (match_operand:VDQX 1 "s_register_operand" "w")
2233    (match_operand:VDQX 2 "s_register_operand" "w")
2234    (match_operand:SI 3 "immediate_operand" "i")]
2235   "TARGET_NEON"
2237   if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2238     emit_insn (gen_sub<mode>3 (operands[0], operands[1], operands[2]));
2239   else
2240     emit_insn (gen_neon_vsub<mode>_unspec (operands[0], operands[1],
2241                                            operands[2]));
2242   DONE;
2245 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2247 (define_insn "neon_vsub<mode>_unspec"
2248   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
2249         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
2250                       (match_operand:VDQX 2 "s_register_operand" "w")]
2251                      UNSPEC_VSUB))]
2252   "TARGET_NEON"
2253   "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2254   [(set (attr "neon_type")
2255       (if_then_else (match_test "<Is_float_mode>")
2256                     (if_then_else (match_test "<Is_d_reg>")
2257                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2258                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2259                     (const_string "neon_int_2")))]
2262 (define_insn "neon_vsubl<mode>"
2263   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2264         (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
2265                            (match_operand:VDI 2 "s_register_operand" "w")
2266                            (match_operand:SI 3 "immediate_operand" "i")]
2267                           UNSPEC_VSUBL))]
2268   "TARGET_NEON"
2269   "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2270   [(set_attr "neon_type" "neon_int_2")]
2273 (define_insn "neon_vsubw<mode>"
2274   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2275         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
2276                            (match_operand:VDI 2 "s_register_operand" "w")
2277                            (match_operand:SI 3 "immediate_operand" "i")]
2278                           UNSPEC_VSUBW))]
2279   "TARGET_NEON"
2280   "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
2281   [(set_attr "neon_type" "neon_int_2")]
2284 (define_insn "neon_vqsub<mode>"
2285   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2286         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2287                        (match_operand:VDQIX 2 "s_register_operand" "w")
2288                        (match_operand:SI 3 "immediate_operand" "i")]
2289                       UNSPEC_VQSUB))]
2290   "TARGET_NEON"
2291   "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2292   [(set_attr "neon_type" "neon_int_5")]
2295 (define_insn "neon_vhsub<mode>"
2296   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2297         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2298                        (match_operand:VDQIW 2 "s_register_operand" "w")
2299                        (match_operand:SI 3 "immediate_operand" "i")]
2300                       UNSPEC_VHSUB))]
2301   "TARGET_NEON"
2302   "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2303   [(set_attr "neon_type" "neon_int_5")]
2306 (define_insn "neon_vsubhn<mode>"
2307   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2308         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2309                             (match_operand:VN 2 "s_register_operand" "w")
2310                             (match_operand:SI 3 "immediate_operand" "i")]
2311                            UNSPEC_VSUBHN))]
2312   "TARGET_NEON"
2313   "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2314   [(set_attr "neon_type" "neon_int_4")]
2317 (define_insn "neon_vceq<mode>"
2318   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2319         (unspec:<V_cmp_result>
2320           [(match_operand:VDQW 1 "s_register_operand" "w,w")
2321            (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2322            (match_operand:SI 3 "immediate_operand" "i,i")]
2323           UNSPEC_VCEQ))]
2324   "TARGET_NEON"
2325   "@
2326   vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2327   vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
2328   [(set (attr "neon_type")
2329       (if_then_else (match_test "<Is_float_mode>")
2330                     (if_then_else (match_test "<Is_d_reg>")
2331                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2332                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2333                     (const_string "neon_int_5")))]
2336 (define_insn "neon_vcge<mode>"
2337   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2338         (unspec:<V_cmp_result>
2339           [(match_operand:VDQW 1 "s_register_operand" "w,w")
2340            (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2341            (match_operand:SI 3 "immediate_operand" "i,i")]
2342           UNSPEC_VCGE))]
2343   "TARGET_NEON"
2344   "@
2345   vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2346   vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2347   [(set (attr "neon_type")
2348      (if_then_else (match_test "<Is_float_mode>")
2349                    (if_then_else (match_test "<Is_d_reg>")
2350                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2351                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2352                    (const_string "neon_int_5")))]
2355 (define_insn "neon_vcgeu<mode>"
2356   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2357         (unspec:<V_cmp_result>
2358           [(match_operand:VDQIW 1 "s_register_operand" "w")
2359            (match_operand:VDQIW 2 "s_register_operand" "w")
2360            (match_operand:SI 3 "immediate_operand" "i")]
2361           UNSPEC_VCGEU))]
2362   "TARGET_NEON"
2363   "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2364   [(set_attr "neon_type" "neon_int_5")]
2367 (define_insn "neon_vcgt<mode>"
2368   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2369         (unspec:<V_cmp_result>
2370           [(match_operand:VDQW 1 "s_register_operand" "w,w")
2371            (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2372            (match_operand:SI 3 "immediate_operand" "i,i")]
2373           UNSPEC_VCGT))]
2374   "TARGET_NEON"
2375   "@
2376   vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2377   vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2378   [(set (attr "neon_type")
2379      (if_then_else (match_test "<Is_float_mode>")
2380                    (if_then_else (match_test "<Is_d_reg>")
2381                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2382                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2383                    (const_string "neon_int_5")))]
2386 (define_insn "neon_vcgtu<mode>"
2387   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2388         (unspec:<V_cmp_result>
2389           [(match_operand:VDQIW 1 "s_register_operand" "w")
2390            (match_operand:VDQIW 2 "s_register_operand" "w")
2391            (match_operand:SI 3 "immediate_operand" "i")]
2392           UNSPEC_VCGTU))]
2393   "TARGET_NEON"
2394   "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2395   [(set_attr "neon_type" "neon_int_5")]
2398 ;; VCLE and VCLT only support comparisons with immediate zero (register
2399 ;; variants are VCGE and VCGT with operands reversed).
2401 (define_insn "neon_vcle<mode>"
2402   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2403         (unspec:<V_cmp_result>
2404           [(match_operand:VDQW 1 "s_register_operand" "w")
2405            (match_operand:VDQW 2 "zero_operand" "Dz")
2406            (match_operand:SI 3 "immediate_operand" "i")]
2407           UNSPEC_VCLE))]
2408   "TARGET_NEON"
2409   "vcle.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2410   [(set (attr "neon_type")
2411       (if_then_else (match_test "<Is_float_mode>")
2412                     (if_then_else (match_test "<Is_d_reg>")
2413                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2414                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2415                     (const_string "neon_int_5")))]
2418 (define_insn "neon_vclt<mode>"
2419   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2420         (unspec:<V_cmp_result>
2421           [(match_operand:VDQW 1 "s_register_operand" "w")
2422            (match_operand:VDQW 2 "zero_operand" "Dz")
2423            (match_operand:SI 3 "immediate_operand" "i")]
2424           UNSPEC_VCLT))]
2425   "TARGET_NEON"
2426   "vclt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2427   [(set (attr "neon_type")
2428       (if_then_else (match_test "<Is_float_mode>")
2429                     (if_then_else (match_test "<Is_d_reg>")
2430                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2431                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
2432                     (const_string "neon_int_5")))]
2435 (define_insn "neon_vcage<mode>"
2436   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2437         (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2438                                 (match_operand:VCVTF 2 "s_register_operand" "w")
2439                                 (match_operand:SI 3 "immediate_operand" "i")]
2440                                UNSPEC_VCAGE))]
2441   "TARGET_NEON"
2442   "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2443   [(set (attr "neon_type")
2444      (if_then_else (match_test "<Is_d_reg>")
2445                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2446                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2449 (define_insn "neon_vcagt<mode>"
2450   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2451         (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2452                                 (match_operand:VCVTF 2 "s_register_operand" "w")
2453                                 (match_operand:SI 3 "immediate_operand" "i")]
2454                                UNSPEC_VCAGT))]
2455   "TARGET_NEON"
2456   "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2457   [(set (attr "neon_type")
2458      (if_then_else (match_test "<Is_d_reg>")
2459                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2460                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2463 (define_insn "neon_vtst<mode>"
2464   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2465         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2466                        (match_operand:VDQIW 2 "s_register_operand" "w")
2467                        (match_operand:SI 3 "immediate_operand" "i")]
2468                       UNSPEC_VTST))]
2469   "TARGET_NEON"
2470   "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2471   [(set_attr "neon_type" "neon_int_4")]
2474 (define_insn "neon_vabd<mode>"
2475   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2476         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2477                       (match_operand:VDQW 2 "s_register_operand" "w")
2478                       (match_operand:SI 3 "immediate_operand" "i")]
2479                      UNSPEC_VABD))]
2480   "TARGET_NEON"
2481   "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2482   [(set (attr "neon_type")
2483      (if_then_else (match_test "<Is_float_mode>")
2484                    (if_then_else (match_test "<Is_d_reg>")
2485                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2486                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2487                    (const_string "neon_int_5")))]
2490 (define_insn "neon_vabdl<mode>"
2491   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2492         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2493                            (match_operand:VW 2 "s_register_operand" "w")
2494                            (match_operand:SI 3 "immediate_operand" "i")]
2495                           UNSPEC_VABDL))]
2496   "TARGET_NEON"
2497   "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2498   [(set_attr "neon_type" "neon_int_5")]
2501 (define_insn "neon_vaba<mode>"
2502   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2503         (plus:VDQIW (unspec:VDQIW [(match_operand:VDQIW 2 "s_register_operand" "w")
2504                                    (match_operand:VDQIW 3 "s_register_operand" "w")
2505                                    (match_operand:SI 4 "immediate_operand" "i")]
2506                                   UNSPEC_VABD)
2507                     (match_operand:VDQIW 1 "s_register_operand" "0")))]
2508   "TARGET_NEON"
2509   "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2510   [(set (attr "neon_type")
2511      (if_then_else (match_test "<Is_d_reg>")
2512                    (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2515 (define_insn "neon_vabal<mode>"
2516   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2517         (plus:<V_widen> (unspec:<V_widen> [(match_operand:VW 2 "s_register_operand" "w")
2518                                            (match_operand:VW 3 "s_register_operand" "w")
2519                                            (match_operand:SI 4 "immediate_operand" "i")]
2520                                            UNSPEC_VABDL)
2521                          (match_operand:<V_widen> 1 "s_register_operand" "0")))]
2522   "TARGET_NEON"
2523   "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2524   [(set_attr "neon_type" "neon_vaba")]
2527 (define_insn "neon_vmax<mode>"
2528   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2529         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2530                       (match_operand:VDQW 2 "s_register_operand" "w")
2531                       (match_operand:SI 3 "immediate_operand" "i")]
2532                      UNSPEC_VMAX))]
2533   "TARGET_NEON"
2534   "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2535   [(set (attr "neon_type")
2536     (if_then_else (match_test "<Is_float_mode>")
2537                   (if_then_else (match_test "<Is_d_reg>")
2538                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2539                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2540                   (const_string "neon_int_5")))]
2543 (define_insn "neon_vmin<mode>"
2544   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2545         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2546                       (match_operand:VDQW 2 "s_register_operand" "w")
2547                       (match_operand:SI 3 "immediate_operand" "i")]
2548                      UNSPEC_VMIN))]
2549   "TARGET_NEON"
2550   "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2551   [(set (attr "neon_type")
2552     (if_then_else (match_test "<Is_float_mode>")
2553                   (if_then_else (match_test "<Is_d_reg>")
2554                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2555                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2556                   (const_string "neon_int_5")))]
2559 (define_expand "neon_vpadd<mode>"
2560   [(match_operand:VD 0 "s_register_operand" "=w")
2561    (match_operand:VD 1 "s_register_operand" "w")
2562    (match_operand:VD 2 "s_register_operand" "w")
2563    (match_operand:SI 3 "immediate_operand" "i")]
2564   "TARGET_NEON"
2566   emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
2567                                             operands[2]));
2568   DONE;
2571 (define_insn "neon_vpaddl<mode>"
2572   [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2573         (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w")
2574                                   (match_operand:SI 2 "immediate_operand" "i")]
2575                                  UNSPEC_VPADDL))]
2576   "TARGET_NEON"
2577   "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2578   ;; Assume this schedules like vaddl.
2579   [(set_attr "neon_type" "neon_int_3")]
2582 (define_insn "neon_vpadal<mode>"
2583   [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2584         (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0")
2585                                   (match_operand:VDQIW 2 "s_register_operand" "w")
2586                                   (match_operand:SI 3 "immediate_operand" "i")]
2587                                  UNSPEC_VPADAL))]
2588   "TARGET_NEON"
2589   "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
2590   ;; Assume this schedules like vpadd.
2591   [(set_attr "neon_type" "neon_int_1")]
2594 (define_insn "neon_vpmax<mode>"
2595   [(set (match_operand:VD 0 "s_register_operand" "=w")
2596         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2597                     (match_operand:VD 2 "s_register_operand" "w")
2598                     (match_operand:SI 3 "immediate_operand" "i")]
2599                    UNSPEC_VPMAX))]
2600   "TARGET_NEON"
2601   "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2602   ;; Assume this schedules like vmax.
2603   [(set (attr "neon_type")
2604     (if_then_else (match_test "<Is_float_mode>")
2605                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2606                   (const_string "neon_int_5")))]
2609 (define_insn "neon_vpmin<mode>"
2610   [(set (match_operand:VD 0 "s_register_operand" "=w")
2611         (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2612                     (match_operand:VD 2 "s_register_operand" "w")
2613                     (match_operand:SI 3 "immediate_operand" "i")]
2614                    UNSPEC_VPMIN))]
2615   "TARGET_NEON"
2616   "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2617   ;; Assume this schedules like vmin.
2618   [(set (attr "neon_type")
2619     (if_then_else (match_test "<Is_float_mode>")
2620                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2621                   (const_string "neon_int_5")))]
2624 (define_insn "neon_vrecps<mode>"
2625   [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2626         (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2627                        (match_operand:VCVTF 2 "s_register_operand" "w")
2628                        (match_operand:SI 3 "immediate_operand" "i")]
2629                       UNSPEC_VRECPS))]
2630   "TARGET_NEON"
2631   "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2632   [(set (attr "neon_type")
2633       (if_then_else (match_test "<Is_d_reg>")
2634                     (const_string "neon_fp_vrecps_vrsqrts_ddd")
2635                     (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2638 (define_insn "neon_vrsqrts<mode>"
2639   [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2640         (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2641                        (match_operand:VCVTF 2 "s_register_operand" "w")
2642                        (match_operand:SI 3 "immediate_operand" "i")]
2643                       UNSPEC_VRSQRTS))]
2644   "TARGET_NEON"
2645   "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2646   [(set (attr "neon_type")
2647       (if_then_else (match_test "<Is_d_reg>")
2648                     (const_string "neon_fp_vrecps_vrsqrts_ddd")
2649                     (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2652 (define_expand "neon_vabs<mode>"
2653   [(match_operand:VDQW 0 "s_register_operand" "")
2654    (match_operand:VDQW 1 "s_register_operand" "")
2655    (match_operand:SI 2 "immediate_operand" "")]
2656   "TARGET_NEON"
2658   emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
2659   DONE;
2662 (define_insn "neon_vqabs<mode>"
2663   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2664         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2665                        (match_operand:SI 2 "immediate_operand" "i")]
2666                       UNSPEC_VQABS))]
2667   "TARGET_NEON"
2668   "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2669   [(set_attr "neon_type" "neon_vqneg_vqabs")]
2672 (define_expand "neon_vneg<mode>"
2673   [(match_operand:VDQW 0 "s_register_operand" "")
2674    (match_operand:VDQW 1 "s_register_operand" "")
2675    (match_operand:SI 2 "immediate_operand" "")]
2676   "TARGET_NEON"
2678   emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
2679   DONE;
2682 (define_insn "neon_vqneg<mode>"
2683   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2684         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2685                        (match_operand:SI 2 "immediate_operand" "i")]
2686                       UNSPEC_VQNEG))]
2687   "TARGET_NEON"
2688   "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2689   [(set_attr "neon_type" "neon_vqneg_vqabs")]
2692 (define_insn "neon_vcls<mode>"
2693   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2694         (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2695                        (match_operand:SI 2 "immediate_operand" "i")]
2696                       UNSPEC_VCLS))]
2697   "TARGET_NEON"
2698   "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2699   [(set_attr "neon_type" "neon_int_1")]
2702 (define_insn "clz<mode>2"
2703   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2704         (clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
2705   "TARGET_NEON"
2706   "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2707   [(set_attr "neon_type" "neon_int_1")]
2710 (define_expand "neon_vclz<mode>"
2711   [(match_operand:VDQIW 0 "s_register_operand" "")
2712    (match_operand:VDQIW 1 "s_register_operand" "")
2713    (match_operand:SI 2 "immediate_operand" "")]
2714   "TARGET_NEON"
2716   emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
2717   DONE;
2720 (define_insn "popcount<mode>2"
2721   [(set (match_operand:VE 0 "s_register_operand" "=w")
2722         (popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
2723   "TARGET_NEON"
2724   "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2725   [(set_attr "neon_type" "neon_int_1")]
2728 (define_expand "neon_vcnt<mode>"
2729   [(match_operand:VE 0 "s_register_operand" "=w")
2730    (match_operand:VE 1 "s_register_operand" "w")
2731    (match_operand:SI 2 "immediate_operand" "i")]
2732   "TARGET_NEON"
2734   emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
2735   DONE;
2738 (define_insn "neon_vrecpe<mode>"
2739   [(set (match_operand:V32 0 "s_register_operand" "=w")
2740         (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2741                      (match_operand:SI 2 "immediate_operand" "i")]
2742                     UNSPEC_VRECPE))]
2743   "TARGET_NEON"
2744   "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2745   [(set (attr "neon_type")
2746       (if_then_else (match_test "<Is_d_reg>")
2747                     (const_string "neon_fp_vadd_ddd_vabs_dd")
2748                     (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2751 (define_insn "neon_vrsqrte<mode>"
2752   [(set (match_operand:V32 0 "s_register_operand" "=w")
2753         (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2754                      (match_operand:SI 2 "immediate_operand" "i")]
2755                     UNSPEC_VRSQRTE))]
2756   "TARGET_NEON"
2757   "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2758   [(set (attr "neon_type")
2759       (if_then_else (match_test "<Is_d_reg>")
2760                     (const_string "neon_fp_vadd_ddd_vabs_dd")
2761                     (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2764 (define_expand "neon_vmvn<mode>"
2765   [(match_operand:VDQIW 0 "s_register_operand" "")
2766    (match_operand:VDQIW 1 "s_register_operand" "")
2767    (match_operand:SI 2 "immediate_operand" "")]
2768   "TARGET_NEON"
2770   emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2771   DONE;
2774 (define_insn "neon_vget_lane<mode>_sext_internal"
2775   [(set (match_operand:SI 0 "s_register_operand" "=r")
2776         (sign_extend:SI
2777           (vec_select:<V_elem>
2778             (match_operand:VD 1 "s_register_operand" "w")
2779             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2780   "TARGET_NEON"
2782   if (BYTES_BIG_ENDIAN)
2783     {
2784       int elt = INTVAL (operands[2]);
2785       elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2786       operands[2] = GEN_INT (elt);
2787     }
2788   return "vmov.s<V_sz_elem>\t%0, %P1[%c2]";
2790   [(set_attr "neon_type" "neon_bp_simple")]
2793 (define_insn "neon_vget_lane<mode>_zext_internal"
2794   [(set (match_operand:SI 0 "s_register_operand" "=r")
2795         (zero_extend:SI
2796           (vec_select:<V_elem>
2797             (match_operand:VD 1 "s_register_operand" "w")
2798             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2799   "TARGET_NEON"
2801   if (BYTES_BIG_ENDIAN)
2802     {
2803       int elt = INTVAL (operands[2]);
2804       elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2805       operands[2] = GEN_INT (elt);
2806     }
2807   return "vmov.u<V_sz_elem>\t%0, %P1[%c2]";
2809   [(set_attr "neon_type" "neon_bp_simple")]
2812 (define_insn "neon_vget_lane<mode>_sext_internal"
2813   [(set (match_operand:SI 0 "s_register_operand" "=r")
2814         (sign_extend:SI
2815           (vec_select:<V_elem>
2816             (match_operand:VQ 1 "s_register_operand" "w")
2817             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2818   "TARGET_NEON"
2820   rtx ops[3];
2821   int regno = REGNO (operands[1]);
2822   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2823   unsigned int elt = INTVAL (operands[2]);
2824   unsigned int elt_adj = elt % halfelts;
2826   if (BYTES_BIG_ENDIAN)
2827     elt_adj = halfelts - 1 - elt_adj;
2829   ops[0] = operands[0];
2830   ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2831   ops[2] = GEN_INT (elt_adj);
2832   output_asm_insn ("vmov.s<V_sz_elem>\t%0, %P1[%c2]", ops);
2834   return "";
2836   [(set_attr "neon_type" "neon_bp_simple")]
2839 (define_insn "neon_vget_lane<mode>_zext_internal"
2840   [(set (match_operand:SI 0 "s_register_operand" "=r")
2841         (zero_extend:SI
2842           (vec_select:<V_elem>
2843             (match_operand:VQ 1 "s_register_operand" "w")
2844             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2845   "TARGET_NEON"
2847   rtx ops[3];
2848   int regno = REGNO (operands[1]);
2849   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2850   unsigned int elt = INTVAL (operands[2]);
2851   unsigned int elt_adj = elt % halfelts;
2853   if (BYTES_BIG_ENDIAN)
2854     elt_adj = halfelts - 1 - elt_adj;
2856   ops[0] = operands[0];
2857   ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2858   ops[2] = GEN_INT (elt_adj);
2859   output_asm_insn ("vmov.u<V_sz_elem>\t%0, %P1[%c2]", ops);
2861   return "";
2863   [(set_attr "neon_type" "neon_bp_simple")]
2866 (define_expand "neon_vget_lane<mode>"
2867   [(match_operand:<V_ext> 0 "s_register_operand" "")
2868    (match_operand:VDQW 1 "s_register_operand" "")
2869    (match_operand:SI 2 "immediate_operand" "")
2870    (match_operand:SI 3 "immediate_operand" "")]
2871   "TARGET_NEON"
2873   HOST_WIDE_INT magic = INTVAL (operands[3]);
2874   rtx insn;
2876   neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2878   if (BYTES_BIG_ENDIAN)
2879     {
2880       /* The intrinsics are defined in terms of a model where the
2881          element ordering in memory is vldm order, whereas the generic
2882          RTL is defined in terms of a model where the element ordering
2883          in memory is array order.  Convert the lane number to conform
2884          to this model.  */
2885       unsigned int elt = INTVAL (operands[2]);
2886       unsigned int reg_nelts
2887         = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2888       elt ^= reg_nelts - 1;
2889       operands[2] = GEN_INT (elt);
2890     }
2892   if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
2893     insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
2894   else
2895     {
2896       if ((magic & 1) != 0)
2897         insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2898                                                        operands[2]);
2899       else
2900         insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2901                                                        operands[2]);
2902     }
2903   emit_insn (insn);
2904   DONE;
2907 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2908 ; elements.
2910 (define_expand "neon_vget_lanedi"
2911   [(match_operand:DI 0 "s_register_operand" "=r")
2912    (match_operand:DI 1 "s_register_operand" "w")
2913    (match_operand:SI 2 "immediate_operand" "i")
2914    (match_operand:SI 3 "immediate_operand" "i")]
2915   "TARGET_NEON"
2917   neon_lane_bounds (operands[2], 0, 1);
2918   emit_move_insn (operands[0], operands[1]);
2919   DONE;
2922 (define_expand "neon_vget_lanev2di"
2923   [(match_operand:DI 0 "s_register_operand" "")
2924    (match_operand:V2DI 1 "s_register_operand" "")
2925    (match_operand:SI 2 "immediate_operand" "")
2926    (match_operand:SI 3 "immediate_operand" "")]
2927   "TARGET_NEON"
2929   switch (INTVAL (operands[2]))
2930     {
2931     case 0:
2932       emit_move_insn (operands[0], gen_lowpart (DImode, operands[1]));
2933       break;
2934     case 1:
2935       emit_move_insn (operands[0], gen_highpart (DImode, operands[1]));
2936       break;
2937     default:
2938       neon_lane_bounds (operands[2], 0, 1);
2939       FAIL;
2940     }
2941   DONE;
2944 (define_expand "neon_vset_lane<mode>"
2945   [(match_operand:VDQ 0 "s_register_operand" "=w")
2946    (match_operand:<V_elem> 1 "s_register_operand" "r")
2947    (match_operand:VDQ 2 "s_register_operand" "0")
2948    (match_operand:SI 3 "immediate_operand" "i")]
2949   "TARGET_NEON"
2951   unsigned int elt = INTVAL (operands[3]);
2952   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2954   if (BYTES_BIG_ENDIAN)
2955     {
2956       unsigned int reg_nelts
2957         = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2958       elt ^= reg_nelts - 1;
2959     }
2961   emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
2962                                          GEN_INT (1 << elt), operands[2]));
2963   DONE;
2966 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2968 (define_expand "neon_vset_lanedi"
2969   [(match_operand:DI 0 "s_register_operand" "=w")
2970    (match_operand:DI 1 "s_register_operand" "r")
2971    (match_operand:DI 2 "s_register_operand" "0")
2972    (match_operand:SI 3 "immediate_operand" "i")]
2973   "TARGET_NEON"
2975   neon_lane_bounds (operands[3], 0, 1);
2976   emit_move_insn (operands[0], operands[1]);
2977   DONE;
2980 (define_expand "neon_vcreate<mode>"
2981   [(match_operand:VDX 0 "s_register_operand" "")
2982    (match_operand:DI 1 "general_operand" "")]
2983   "TARGET_NEON"
2985   rtx src = gen_lowpart (<MODE>mode, operands[1]);
2986   emit_move_insn (operands[0], src);
2987   DONE;
2990 (define_insn "neon_vdup_n<mode>"
2991   [(set (match_operand:VX 0 "s_register_operand" "=w")
2992         (vec_duplicate:VX (match_operand:<V_elem> 1 "s_register_operand" "r")))]
2993   "TARGET_NEON"
2994   "vdup.<V_sz_elem>\t%<V_reg>0, %1"
2995   ;; Assume this schedules like vmov.
2996   [(set_attr "neon_type" "neon_bp_simple")]
2999 (define_insn "neon_vdup_n<mode>"
3000   [(set (match_operand:V32 0 "s_register_operand" "=w,w")
3001         (vec_duplicate:V32 (match_operand:<V_elem> 1 "s_register_operand" "r,t")))]
3002   "TARGET_NEON"
3003   "@
3004   vdup.<V_sz_elem>\t%<V_reg>0, %1
3005   vdup.<V_sz_elem>\t%<V_reg>0, %y1"
3006   ;; Assume this schedules like vmov.
3007   [(set_attr "neon_type" "neon_bp_simple")]
3010 (define_expand "neon_vdup_ndi"
3011   [(match_operand:DI 0 "s_register_operand" "=w")
3012    (match_operand:DI 1 "s_register_operand" "r")]
3013   "TARGET_NEON"
3015   emit_move_insn (operands[0], operands[1]);
3016   DONE;
3020 (define_insn "neon_vdup_nv2di"
3021   [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
3022         (vec_duplicate:V2DI (match_operand:DI 1 "s_register_operand" "r,w")))]
3023   "TARGET_NEON"
3024   "@
3025   vmov\t%e0, %Q1, %R1\;vmov\t%f0, %Q1, %R1
3026   vmov\t%e0, %P1\;vmov\t%f0, %P1"
3027   [(set_attr "length" "8")
3028    (set_attr "neon_type" "neon_bp_simple")]
3031 (define_insn "neon_vdup_lane<mode>_internal"
3032   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
3033         (vec_duplicate:VDQW 
3034           (vec_select:<V_elem>
3035             (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
3036             (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
3037   "TARGET_NEON"
3039   if (BYTES_BIG_ENDIAN)
3040     {
3041       int elt = INTVAL (operands[2]);
3042       elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt;
3043       operands[2] = GEN_INT (elt);
3044     }
3045   if (<Is_d_reg>)
3046     return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
3047   else
3048     return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
3050   ;; Assume this schedules like vmov.
3051   [(set_attr "neon_type" "neon_bp_simple")]
3054 (define_expand "neon_vdup_lane<mode>"
3055   [(match_operand:VDQW 0 "s_register_operand" "=w")
3056    (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
3057    (match_operand:SI 2 "immediate_operand" "i")]
3058   "TARGET_NEON"
3060   neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
3061   if (BYTES_BIG_ENDIAN)
3062     {
3063       unsigned int elt = INTVAL (operands[2]);
3064       unsigned int reg_nelts
3065         = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<V_double_vector_mode>mode));
3066       elt ^= reg_nelts - 1;
3067       operands[2] = GEN_INT (elt);
3068     }
3069     emit_insn (gen_neon_vdup_lane<mode>_internal (operands[0], operands[1],
3070                                                   operands[2]));
3071     DONE;
3074 ; Scalar index is ignored, since only zero is valid here.
3075 (define_expand "neon_vdup_lanedi"
3076   [(match_operand:DI 0 "s_register_operand" "=w")
3077    (match_operand:DI 1 "s_register_operand" "w")
3078    (match_operand:SI 2 "immediate_operand" "i")]
3079   "TARGET_NEON"
3081   neon_lane_bounds (operands[2], 0, 1);
3082   emit_move_insn (operands[0], operands[1]);
3083   DONE;
3086 ; Likewise for v2di, as the DImode second operand has only a single element.
3087 (define_expand "neon_vdup_lanev2di"
3088   [(match_operand:V2DI 0 "s_register_operand" "=w")
3089    (match_operand:DI 1 "s_register_operand" "w")
3090    (match_operand:SI 2 "immediate_operand" "i")]
3091   "TARGET_NEON"
3093   neon_lane_bounds (operands[2], 0, 1);
3094   emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
3095   DONE;
3098 ; Disabled before reload because we don't want combine doing something silly,
3099 ; but used by the post-reload expansion of neon_vcombine.
3100 (define_insn "*neon_vswp<mode>"
3101   [(set (match_operand:VDQX 0 "s_register_operand" "+w")
3102         (match_operand:VDQX 1 "s_register_operand" "+w"))
3103    (set (match_dup 1) (match_dup 0))]
3104   "TARGET_NEON && reload_completed"
3105   "vswp\t%<V_reg>0, %<V_reg>1"
3106   [(set (attr "neon_type")
3107         (if_then_else (match_test "<Is_d_reg>")
3108                       (const_string "neon_bp_simple")
3109                       (const_string "neon_bp_2cycle")))]
3112 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
3113 ;; dest vector.
3114 ;; FIXME: A different implementation of this builtin could make it much
3115 ;; more likely that we wouldn't actually need to output anything (we could make
3116 ;; it so that the reg allocator puts things in the right places magically
3117 ;; instead). Lack of subregs for vectors makes that tricky though, I think.
3119 (define_insn_and_split "neon_vcombine<mode>"
3120   [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
3121         (vec_concat:<V_DOUBLE>
3122           (match_operand:VDX 1 "s_register_operand" "w")
3123           (match_operand:VDX 2 "s_register_operand" "w")))]
3124   "TARGET_NEON"
3125   "#"
3126   "&& reload_completed"
3127   [(const_int 0)]
3129   neon_split_vcombine (operands);
3130   DONE;
3133 (define_expand "neon_vget_high<mode>"
3134   [(match_operand:<V_HALF> 0 "s_register_operand")
3135    (match_operand:VQX 1 "s_register_operand")]
3136   "TARGET_NEON"
3138   emit_move_insn (operands[0],
3139                   simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
3140                                        GET_MODE_SIZE (<V_HALF>mode)));
3141   DONE;
3144 (define_expand "neon_vget_low<mode>"
3145   [(match_operand:<V_HALF> 0 "s_register_operand")
3146    (match_operand:VQX 1 "s_register_operand")]
3147   "TARGET_NEON"
3149   emit_move_insn (operands[0],
3150                   simplify_gen_subreg (<V_HALF>mode, operands[1],
3151                                        <MODE>mode, 0));
3152   DONE;
3155 (define_insn "float<mode><V_cvtto>2"
3156   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3157         (float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
3158   "TARGET_NEON && !flag_rounding_math"
3159   "vcvt.f32.s32\t%<V_reg>0, %<V_reg>1"
3160   [(set (attr "neon_type")
3161      (if_then_else (match_test "<Is_d_reg>")
3162                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3163                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3166 (define_insn "floatuns<mode><V_cvtto>2"
3167   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3168         (unsigned_float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))] 
3169   "TARGET_NEON && !flag_rounding_math"
3170   "vcvt.f32.u32\t%<V_reg>0, %<V_reg>1"
3171   [(set (attr "neon_type")
3172      (if_then_else (match_test "<Is_d_reg>")
3173                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3174                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3177 (define_insn "fix_trunc<mode><V_cvtto>2"
3178   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3179         (fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3180   "TARGET_NEON"
3181   "vcvt.s32.f32\t%<V_reg>0, %<V_reg>1"
3182   [(set (attr "neon_type")
3183      (if_then_else (match_test "<Is_d_reg>")
3184                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3185                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3188 (define_insn "fixuns_trunc<mode><V_cvtto>2"
3189   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3190         (unsigned_fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3191   "TARGET_NEON"
3192   "vcvt.u32.f32\t%<V_reg>0, %<V_reg>1"
3193   [(set (attr "neon_type")
3194      (if_then_else (match_test "<Is_d_reg>")
3195                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3196                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3199 (define_insn "neon_vcvt<mode>"
3200   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3201         (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3202                            (match_operand:SI 2 "immediate_operand" "i")]
3203                           UNSPEC_VCVT))]
3204   "TARGET_NEON"
3205   "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
3206   [(set (attr "neon_type")
3207      (if_then_else (match_test "<Is_d_reg>")
3208                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3209                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3212 (define_insn "neon_vcvt<mode>"
3213   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3214         (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3215                            (match_operand:SI 2 "immediate_operand" "i")]
3216                           UNSPEC_VCVT))]
3217   "TARGET_NEON"
3218   "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
3219   [(set (attr "neon_type")
3220      (if_then_else (match_test "<Is_d_reg>")
3221                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3222                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3225 (define_insn "neon_vcvtv4sfv4hf"
3226   [(set (match_operand:V4SF 0 "s_register_operand" "=w")
3227         (unspec:V4SF [(match_operand:V4HF 1 "s_register_operand" "w")]
3228                           UNSPEC_VCVT))]
3229   "TARGET_NEON && TARGET_FP16"
3230   "vcvt.f32.f16\t%q0, %P1"
3231   [(set_attr "neon_type" "neon_fp_vadd_ddd_vabs_dd")]
3234 (define_insn "neon_vcvtv4hfv4sf"
3235   [(set (match_operand:V4HF 0 "s_register_operand" "=w")
3236         (unspec:V4HF [(match_operand:V4SF 1 "s_register_operand" "w")]
3237                           UNSPEC_VCVT))]
3238   "TARGET_NEON && TARGET_FP16"
3239   "vcvt.f16.f32\t%P0, %q1"
3240   [(set_attr "neon_type" "neon_fp_vadd_ddd_vabs_dd")]
3243 (define_insn "neon_vcvt_n<mode>"
3244   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3245         (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3246                            (match_operand:SI 2 "immediate_operand" "i")
3247                            (match_operand:SI 3 "immediate_operand" "i")]
3248                           UNSPEC_VCVT_N))]
3249   "TARGET_NEON"
3251   neon_const_bounds (operands[2], 1, 33);
3252   return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
3254   [(set (attr "neon_type")
3255      (if_then_else (match_test "<Is_d_reg>")
3256                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3257                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3260 (define_insn "neon_vcvt_n<mode>"
3261   [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3262         (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3263                            (match_operand:SI 2 "immediate_operand" "i")
3264                            (match_operand:SI 3 "immediate_operand" "i")]
3265                           UNSPEC_VCVT_N))]
3266   "TARGET_NEON"
3268   neon_const_bounds (operands[2], 1, 33);
3269   return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
3271   [(set (attr "neon_type")
3272      (if_then_else (match_test "<Is_d_reg>")
3273                    (const_string "neon_fp_vadd_ddd_vabs_dd")
3274                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3277 (define_insn "neon_vmovn<mode>"
3278   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3279         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3280                             (match_operand:SI 2 "immediate_operand" "i")]
3281                            UNSPEC_VMOVN))]
3282   "TARGET_NEON"
3283   "vmovn.<V_if_elem>\t%P0, %q1"
3284   [(set_attr "neon_type" "neon_bp_simple")]
3287 (define_insn "neon_vqmovn<mode>"
3288   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3289         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3290                             (match_operand:SI 2 "immediate_operand" "i")]
3291                            UNSPEC_VQMOVN))]
3292   "TARGET_NEON"
3293   "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
3294   [(set_attr "neon_type" "neon_shift_2")]
3297 (define_insn "neon_vqmovun<mode>"
3298   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3299         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3300                             (match_operand:SI 2 "immediate_operand" "i")]
3301                            UNSPEC_VQMOVUN))]
3302   "TARGET_NEON"
3303   "vqmovun.<V_s_elem>\t%P0, %q1"
3304   [(set_attr "neon_type" "neon_shift_2")]
3307 (define_insn "neon_vmovl<mode>"
3308   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3309         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
3310                            (match_operand:SI 2 "immediate_operand" "i")]
3311                           UNSPEC_VMOVL))]
3312   "TARGET_NEON"
3313   "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
3314   [(set_attr "neon_type" "neon_shift_1")]
3317 (define_insn "neon_vmul_lane<mode>"
3318   [(set (match_operand:VMD 0 "s_register_operand" "=w")
3319         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
3320                      (match_operand:VMD 2 "s_register_operand"
3321                                         "<scalar_mul_constraint>")
3322                      (match_operand:SI 3 "immediate_operand" "i")
3323                      (match_operand:SI 4 "immediate_operand" "i")]
3324                     UNSPEC_VMUL_LANE))]
3325   "TARGET_NEON"
3327   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3328   return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
3330   [(set (attr "neon_type")
3331      (if_then_else (match_test "<Is_float_mode>")
3332                    (const_string "neon_fp_vmul_ddd")
3333                    (if_then_else (match_test "<Scalar_mul_8_16>")
3334                                  (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3335                                  (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
3338 (define_insn "neon_vmul_lane<mode>"
3339   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3340         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
3341                      (match_operand:<V_HALF> 2 "s_register_operand"
3342                                              "<scalar_mul_constraint>")
3343                      (match_operand:SI 3 "immediate_operand" "i")
3344                      (match_operand:SI 4 "immediate_operand" "i")]
3345                     UNSPEC_VMUL_LANE))]
3346   "TARGET_NEON"
3348   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
3349   return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
3351   [(set (attr "neon_type")
3352      (if_then_else (match_test "<Is_float_mode>")
3353                    (const_string "neon_fp_vmul_qqd")
3354                    (if_then_else (match_test "<Scalar_mul_8_16>")
3355                                  (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3356                                  (const_string "neon_mul_qqd_32_scalar"))))]
3359 (define_insn "neon_vmull_lane<mode>"
3360   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3361         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3362                            (match_operand:VMDI 2 "s_register_operand"
3363                                                "<scalar_mul_constraint>")
3364                            (match_operand:SI 3 "immediate_operand" "i")
3365                            (match_operand:SI 4 "immediate_operand" "i")]
3366                           UNSPEC_VMULL_LANE))]
3367   "TARGET_NEON"
3369   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3370   return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
3372   [(set (attr "neon_type")
3373      (if_then_else (match_test "<Scalar_mul_8_16>")
3374                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3375                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3378 (define_insn "neon_vqdmull_lane<mode>"
3379   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3380         (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3381                            (match_operand:VMDI 2 "s_register_operand"
3382                                                "<scalar_mul_constraint>")
3383                            (match_operand:SI 3 "immediate_operand" "i")
3384                            (match_operand:SI 4 "immediate_operand" "i")]
3385                           UNSPEC_VQDMULL_LANE))]
3386   "TARGET_NEON"
3388   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3389   return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
3391   [(set (attr "neon_type")
3392      (if_then_else (match_test "<Scalar_mul_8_16>")
3393                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3394                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3397 (define_insn "neon_vqdmulh_lane<mode>"
3398   [(set (match_operand:VMQI 0 "s_register_operand" "=w")
3399         (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
3400                       (match_operand:<V_HALF> 2 "s_register_operand"
3401                                               "<scalar_mul_constraint>")
3402                       (match_operand:SI 3 "immediate_operand" "i")
3403                       (match_operand:SI 4 "immediate_operand" "i")]
3404                       UNSPEC_VQDMULH_LANE))]
3405   "TARGET_NEON"
3407   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3408   return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
3410   [(set (attr "neon_type")
3411      (if_then_else (match_test "<Scalar_mul_8_16>")
3412                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3413                    (const_string "neon_mul_qqd_32_scalar")))]
3416 (define_insn "neon_vqdmulh_lane<mode>"
3417   [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3418         (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3419                       (match_operand:VMDI 2 "s_register_operand"
3420                                           "<scalar_mul_constraint>")
3421                       (match_operand:SI 3 "immediate_operand" "i")
3422                       (match_operand:SI 4 "immediate_operand" "i")]
3423                       UNSPEC_VQDMULH_LANE))]
3424   "TARGET_NEON"
3426   neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3427   return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
3429   [(set (attr "neon_type")
3430      (if_then_else (match_test "<Scalar_mul_8_16>")
3431                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3432                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3435 (define_insn "neon_vmla_lane<mode>"
3436   [(set (match_operand:VMD 0 "s_register_operand" "=w")
3437         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3438                      (match_operand:VMD 2 "s_register_operand" "w")
3439                      (match_operand:VMD 3 "s_register_operand"
3440                                         "<scalar_mul_constraint>")
3441                      (match_operand:SI 4 "immediate_operand" "i")
3442                      (match_operand:SI 5 "immediate_operand" "i")]
3443                      UNSPEC_VMLA_LANE))]
3444   "TARGET_NEON"
3446   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3447   return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3449   [(set (attr "neon_type")
3450      (if_then_else (match_test "<Is_float_mode>")
3451                    (const_string "neon_fp_vmla_ddd_scalar")
3452                    (if_then_else (match_test "<Scalar_mul_8_16>")
3453                                  (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3454                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3457 (define_insn "neon_vmla_lane<mode>"
3458   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3459         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3460                      (match_operand:VMQ 2 "s_register_operand" "w")
3461                      (match_operand:<V_HALF> 3 "s_register_operand"
3462                                              "<scalar_mul_constraint>")
3463                      (match_operand:SI 4 "immediate_operand" "i")
3464                      (match_operand:SI 5 "immediate_operand" "i")]
3465                      UNSPEC_VMLA_LANE))]
3466   "TARGET_NEON"
3468   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3469   return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3471   [(set (attr "neon_type")
3472      (if_then_else (match_test "<Is_float_mode>")
3473                    (const_string "neon_fp_vmla_qqq_scalar")
3474                    (if_then_else (match_test "<Scalar_mul_8_16>")
3475                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3476                                  (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3479 (define_insn "neon_vmlal_lane<mode>"
3480   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3481         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3482                            (match_operand:VMDI 2 "s_register_operand" "w")
3483                            (match_operand:VMDI 3 "s_register_operand"
3484                                                "<scalar_mul_constraint>")
3485                            (match_operand:SI 4 "immediate_operand" "i")
3486                            (match_operand:SI 5 "immediate_operand" "i")]
3487                           UNSPEC_VMLAL_LANE))]
3488   "TARGET_NEON"
3490   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3491   return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3493   [(set (attr "neon_type")
3494      (if_then_else (match_test "<Scalar_mul_8_16>")
3495                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3496                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3499 (define_insn "neon_vqdmlal_lane<mode>"
3500   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3501         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3502                            (match_operand:VMDI 2 "s_register_operand" "w")
3503                            (match_operand:VMDI 3 "s_register_operand"
3504                                                "<scalar_mul_constraint>")
3505                            (match_operand:SI 4 "immediate_operand" "i")
3506                            (match_operand:SI 5 "immediate_operand" "i")]
3507                           UNSPEC_VQDMLAL_LANE))]
3508   "TARGET_NEON"
3510   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3511   return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3513   [(set (attr "neon_type")
3514      (if_then_else (match_test "<Scalar_mul_8_16>")
3515                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3516                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3519 (define_insn "neon_vmls_lane<mode>"
3520   [(set (match_operand:VMD 0 "s_register_operand" "=w")
3521         (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3522                      (match_operand:VMD 2 "s_register_operand" "w")
3523                      (match_operand:VMD 3 "s_register_operand"
3524                                         "<scalar_mul_constraint>")
3525                      (match_operand:SI 4 "immediate_operand" "i")
3526                      (match_operand:SI 5 "immediate_operand" "i")]
3527                     UNSPEC_VMLS_LANE))]
3528   "TARGET_NEON"
3530   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3531   return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3533   [(set (attr "neon_type")
3534      (if_then_else (match_test "<Is_float_mode>")
3535                    (const_string "neon_fp_vmla_ddd_scalar")
3536                    (if_then_else (match_test "<Scalar_mul_8_16>")
3537                                  (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3538                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3541 (define_insn "neon_vmls_lane<mode>"
3542   [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3543         (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3544                      (match_operand:VMQ 2 "s_register_operand" "w")
3545                      (match_operand:<V_HALF> 3 "s_register_operand"
3546                                              "<scalar_mul_constraint>")
3547                      (match_operand:SI 4 "immediate_operand" "i")
3548                      (match_operand:SI 5 "immediate_operand" "i")]
3549                     UNSPEC_VMLS_LANE))]
3550   "TARGET_NEON"
3552   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3553   return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3555   [(set (attr "neon_type")
3556      (if_then_else (match_test "<Is_float_mode>")
3557                    (const_string "neon_fp_vmla_qqq_scalar")
3558                    (if_then_else (match_test "<Scalar_mul_8_16>")
3559                                  (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3560                                  (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3563 (define_insn "neon_vmlsl_lane<mode>"
3564   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3565         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3566                            (match_operand:VMDI 2 "s_register_operand" "w")
3567                            (match_operand:VMDI 3 "s_register_operand"
3568                                                "<scalar_mul_constraint>")
3569                            (match_operand:SI 4 "immediate_operand" "i")
3570                            (match_operand:SI 5 "immediate_operand" "i")]
3571                           UNSPEC_VMLSL_LANE))]
3572   "TARGET_NEON"
3574   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3575   return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3577   [(set (attr "neon_type")
3578      (if_then_else (match_test "<Scalar_mul_8_16>")
3579                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3580                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3583 (define_insn "neon_vqdmlsl_lane<mode>"
3584   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3585         (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3586                            (match_operand:VMDI 2 "s_register_operand" "w")
3587                            (match_operand:VMDI 3 "s_register_operand"
3588                                                "<scalar_mul_constraint>")
3589                            (match_operand:SI 4 "immediate_operand" "i")
3590                            (match_operand:SI 5 "immediate_operand" "i")]
3591                           UNSPEC_VQDMLSL_LANE))]
3592   "TARGET_NEON"
3594   neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3595   return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3597   [(set (attr "neon_type")
3598      (if_then_else (match_test "<Scalar_mul_8_16>")
3599                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3600                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3603 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3604 ; core register into a temp register, then use a scalar taken from that. This
3605 ; isn't an optimal solution if e.g. the scalar has just been read from memory
3606 ; or extracted from another vector. The latter case it's currently better to
3607 ; use the "_lane" variant, and the former case can probably be implemented
3608 ; using vld1_lane, but that hasn't been done yet.
3610 (define_expand "neon_vmul_n<mode>"
3611   [(match_operand:VMD 0 "s_register_operand" "")
3612    (match_operand:VMD 1 "s_register_operand" "")
3613    (match_operand:<V_elem> 2 "s_register_operand" "")
3614    (match_operand:SI 3 "immediate_operand" "")]
3615   "TARGET_NEON"
3617   rtx tmp = gen_reg_rtx (<MODE>mode);
3618   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3619   emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3620                                        const0_rtx, const0_rtx));
3621   DONE;
3624 (define_expand "neon_vmul_n<mode>"
3625   [(match_operand:VMQ 0 "s_register_operand" "")
3626    (match_operand:VMQ 1 "s_register_operand" "")
3627    (match_operand:<V_elem> 2 "s_register_operand" "")
3628    (match_operand:SI 3 "immediate_operand" "")]
3629   "TARGET_NEON"
3631   rtx tmp = gen_reg_rtx (<V_HALF>mode);
3632   emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3633   emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3634                                        const0_rtx, const0_rtx));
3635   DONE;
3638 (define_expand "neon_vmull_n<mode>"
3639   [(match_operand:<V_widen> 0 "s_register_operand" "")
3640    (match_operand:VMDI 1 "s_register_operand" "")
3641    (match_operand:<V_elem> 2 "s_register_operand" "")
3642    (match_operand:SI 3 "immediate_operand" "")]
3643   "TARGET_NEON"
3645   rtx tmp = gen_reg_rtx (<MODE>mode);
3646   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3647   emit_insn (gen_neon_vmull_lane<mode> (operands[0], operands[1], tmp,
3648                                         const0_rtx, operands[3]));
3649   DONE;
3652 (define_expand "neon_vqdmull_n<mode>"
3653   [(match_operand:<V_widen> 0 "s_register_operand" "")
3654    (match_operand:VMDI 1 "s_register_operand" "")
3655    (match_operand:<V_elem> 2 "s_register_operand" "")
3656    (match_operand:SI 3 "immediate_operand" "")]
3657   "TARGET_NEON"
3659   rtx tmp = gen_reg_rtx (<MODE>mode);
3660   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3661   emit_insn (gen_neon_vqdmull_lane<mode> (operands[0], operands[1], tmp,
3662                                           const0_rtx, const0_rtx));
3663   DONE;
3666 (define_expand "neon_vqdmulh_n<mode>"
3667   [(match_operand:VMDI 0 "s_register_operand" "")
3668    (match_operand:VMDI 1 "s_register_operand" "")
3669    (match_operand:<V_elem> 2 "s_register_operand" "")
3670    (match_operand:SI 3 "immediate_operand" "")]
3671   "TARGET_NEON"
3673   rtx tmp = gen_reg_rtx (<MODE>mode);
3674   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3675   emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3676                                           const0_rtx, operands[3]));
3677   DONE;
3680 (define_expand "neon_vqdmulh_n<mode>"
3681   [(match_operand:VMQI 0 "s_register_operand" "")
3682    (match_operand:VMQI 1 "s_register_operand" "")
3683    (match_operand:<V_elem> 2 "s_register_operand" "")
3684    (match_operand:SI 3 "immediate_operand" "")]
3685   "TARGET_NEON"
3687   rtx tmp = gen_reg_rtx (<V_HALF>mode);
3688   emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3689   emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3690                                           const0_rtx, operands[3]));
3691   DONE;
3694 (define_expand "neon_vmla_n<mode>"
3695   [(match_operand:VMD 0 "s_register_operand" "")
3696    (match_operand:VMD 1 "s_register_operand" "")
3697    (match_operand:VMD 2 "s_register_operand" "")
3698    (match_operand:<V_elem> 3 "s_register_operand" "")
3699    (match_operand:SI 4 "immediate_operand" "")]
3700   "TARGET_NEON"
3702   rtx tmp = gen_reg_rtx (<MODE>mode);
3703   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3704   emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3705                                        tmp, const0_rtx, operands[4]));
3706   DONE;
3709 (define_expand "neon_vmla_n<mode>"
3710   [(match_operand:VMQ 0 "s_register_operand" "")
3711    (match_operand:VMQ 1 "s_register_operand" "")
3712    (match_operand:VMQ 2 "s_register_operand" "")
3713    (match_operand:<V_elem> 3 "s_register_operand" "")
3714    (match_operand:SI 4 "immediate_operand" "")]
3715   "TARGET_NEON"
3717   rtx tmp = gen_reg_rtx (<V_HALF>mode);
3718   emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3719   emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3720                                        tmp, const0_rtx, operands[4]));
3721   DONE;
3724 (define_expand "neon_vmlal_n<mode>"
3725   [(match_operand:<V_widen> 0 "s_register_operand" "")
3726    (match_operand:<V_widen> 1 "s_register_operand" "")
3727    (match_operand:VMDI 2 "s_register_operand" "")
3728    (match_operand:<V_elem> 3 "s_register_operand" "")
3729    (match_operand:SI 4 "immediate_operand" "")]
3730   "TARGET_NEON"
3732   rtx tmp = gen_reg_rtx (<MODE>mode);
3733   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3734   emit_insn (gen_neon_vmlal_lane<mode> (operands[0], operands[1], operands[2],
3735                                         tmp, const0_rtx, operands[4]));
3736   DONE;
3739 (define_expand "neon_vqdmlal_n<mode>"
3740   [(match_operand:<V_widen> 0 "s_register_operand" "")
3741    (match_operand:<V_widen> 1 "s_register_operand" "")
3742    (match_operand:VMDI 2 "s_register_operand" "")
3743    (match_operand:<V_elem> 3 "s_register_operand" "")
3744    (match_operand:SI 4 "immediate_operand" "")]
3745   "TARGET_NEON"
3747   rtx tmp = gen_reg_rtx (<MODE>mode);
3748   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3749   emit_insn (gen_neon_vqdmlal_lane<mode> (operands[0], operands[1], operands[2],
3750                                           tmp, const0_rtx, operands[4]));
3751   DONE;
3754 (define_expand "neon_vmls_n<mode>"
3755   [(match_operand:VMD 0 "s_register_operand" "")
3756    (match_operand:VMD 1 "s_register_operand" "")
3757    (match_operand:VMD 2 "s_register_operand" "")
3758    (match_operand:<V_elem> 3 "s_register_operand" "")
3759    (match_operand:SI 4 "immediate_operand" "")]
3760   "TARGET_NEON"
3762   rtx tmp = gen_reg_rtx (<MODE>mode);
3763   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3764   emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3765                                        tmp, const0_rtx, operands[4]));
3766   DONE;
3769 (define_expand "neon_vmls_n<mode>"
3770   [(match_operand:VMQ 0 "s_register_operand" "")
3771    (match_operand:VMQ 1 "s_register_operand" "")
3772    (match_operand:VMQ 2 "s_register_operand" "")
3773    (match_operand:<V_elem> 3 "s_register_operand" "")
3774    (match_operand:SI 4 "immediate_operand" "")]
3775   "TARGET_NEON"
3777   rtx tmp = gen_reg_rtx (<V_HALF>mode);
3778   emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3779   emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3780                                        tmp, const0_rtx, operands[4]));
3781   DONE;
3784 (define_expand "neon_vmlsl_n<mode>"
3785   [(match_operand:<V_widen> 0 "s_register_operand" "")
3786    (match_operand:<V_widen> 1 "s_register_operand" "")
3787    (match_operand:VMDI 2 "s_register_operand" "")
3788    (match_operand:<V_elem> 3 "s_register_operand" "")
3789    (match_operand:SI 4 "immediate_operand" "")]
3790   "TARGET_NEON"
3792   rtx tmp = gen_reg_rtx (<MODE>mode);
3793   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3794   emit_insn (gen_neon_vmlsl_lane<mode> (operands[0], operands[1], operands[2],
3795                                         tmp, const0_rtx, operands[4]));
3796   DONE;
3799 (define_expand "neon_vqdmlsl_n<mode>"
3800   [(match_operand:<V_widen> 0 "s_register_operand" "")
3801    (match_operand:<V_widen> 1 "s_register_operand" "")
3802    (match_operand:VMDI 2 "s_register_operand" "")
3803    (match_operand:<V_elem> 3 "s_register_operand" "")
3804    (match_operand:SI 4 "immediate_operand" "")]
3805   "TARGET_NEON"
3807   rtx tmp = gen_reg_rtx (<MODE>mode);
3808   emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3809   emit_insn (gen_neon_vqdmlsl_lane<mode> (operands[0], operands[1], operands[2],
3810                                           tmp, const0_rtx, operands[4]));
3811   DONE;
3814 (define_insn "neon_vext<mode>"
3815   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
3816         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
3817                       (match_operand:VDQX 2 "s_register_operand" "w")
3818                       (match_operand:SI 3 "immediate_operand" "i")]
3819                      UNSPEC_VEXT))]
3820   "TARGET_NEON"
3822   neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3823   return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3";
3825   [(set (attr "neon_type")
3826       (if_then_else (match_test "<Is_d_reg>")
3827                     (const_string "neon_bp_simple")
3828                     (const_string "neon_bp_2cycle")))]
3831 (define_insn "neon_vrev64<mode>"
3832   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
3833         (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
3834                      (match_operand:SI 2 "immediate_operand" "i")]
3835                     UNSPEC_VREV64))]
3836   "TARGET_NEON"
3837   "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3838   [(set_attr "neon_type" "neon_bp_simple")]
3841 (define_insn "neon_vrev32<mode>"
3842   [(set (match_operand:VX 0 "s_register_operand" "=w")
3843         (unspec:VX [(match_operand:VX 1 "s_register_operand" "w")
3844                     (match_operand:SI 2 "immediate_operand" "i")]
3845                    UNSPEC_VREV32))]
3846   "TARGET_NEON"
3847   "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3848   [(set_attr "neon_type" "neon_bp_simple")]
3851 (define_insn "neon_vrev16<mode>"
3852   [(set (match_operand:VE 0 "s_register_operand" "=w")
3853         (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
3854                     (match_operand:SI 2 "immediate_operand" "i")]
3855                    UNSPEC_VREV16))]
3856   "TARGET_NEON"
3857   "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3858   [(set_attr "neon_type" "neon_bp_simple")]
3861 ; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register
3862 ; allocation. For an intrinsic of form:
3863 ;   rD = vbsl_* (rS, rN, rM)
3864 ; We can use any of:
3865 ;   vbsl rS, rN, rM  (if D = S)
3866 ;   vbit rD, rN, rS  (if D = M, so 1-bits in rS choose bits from rN, else rM)
3867 ;   vbif rD, rM, rS  (if D = N, so 0-bits in rS choose bits from rM, else rN)
3869 (define_insn "neon_vbsl<mode>_internal"
3870   [(set (match_operand:VDQX 0 "s_register_operand"               "=w,w,w")
3871         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w")
3872                       (match_operand:VDQX 2 "s_register_operand" " w,w,0")
3873                       (match_operand:VDQX 3 "s_register_operand" " w,0,w")]
3874                      UNSPEC_VBSL))]
3875   "TARGET_NEON"
3876   "@
3877   vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3
3878   vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1
3879   vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1"
3880   [(set_attr "neon_type" "neon_int_1")]
3883 (define_expand "neon_vbsl<mode>"
3884   [(set (match_operand:VDQX 0 "s_register_operand" "")
3885         (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "")
3886                       (match_operand:VDQX 2 "s_register_operand" "")
3887                       (match_operand:VDQX 3 "s_register_operand" "")]
3888                      UNSPEC_VBSL))]
3889   "TARGET_NEON"
3891   /* We can't alias operands together if they have different modes.  */
3892   operands[1] = gen_lowpart (<MODE>mode, operands[1]);
3895 (define_insn "neon_vshl<mode>"
3896   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3897         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3898                        (match_operand:VDQIX 2 "s_register_operand" "w")
3899                        (match_operand:SI 3 "immediate_operand" "i")]
3900                       UNSPEC_VSHL))]
3901   "TARGET_NEON"
3902   "v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3903   [(set (attr "neon_type")
3904       (if_then_else (match_test "<Is_d_reg>")
3905                     (const_string "neon_vshl_ddd")
3906                     (const_string "neon_shift_3")))]
3909 (define_insn "neon_vqshl<mode>"
3910   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3911         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3912                        (match_operand:VDQIX 2 "s_register_operand" "w")
3913                        (match_operand:SI 3 "immediate_operand" "i")]
3914                       UNSPEC_VQSHL))]
3915   "TARGET_NEON"
3916   "vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3917   [(set (attr "neon_type")
3918       (if_then_else (match_test "<Is_d_reg>")
3919                     (const_string "neon_shift_2")
3920                     (const_string "neon_vqshl_vrshl_vqrshl_qqq")))]
3923 (define_insn "neon_vshr_n<mode>"
3924   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3925         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3926                        (match_operand:SI 2 "immediate_operand" "i")
3927                        (match_operand:SI 3 "immediate_operand" "i")]
3928                       UNSPEC_VSHR_N))]
3929   "TARGET_NEON"
3931   neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1);
3932   return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
3934   [(set_attr "neon_type" "neon_shift_1")]
3937 (define_insn "neon_vshrn_n<mode>"
3938   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3939         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3940                             (match_operand:SI 2 "immediate_operand" "i")
3941                             (match_operand:SI 3 "immediate_operand" "i")]
3942                            UNSPEC_VSHRN_N))]
3943   "TARGET_NEON"
3945   neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3946   return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2";
3948   [(set_attr "neon_type" "neon_shift_1")]
3951 (define_insn "neon_vqshrn_n<mode>"
3952   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3953         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3954                             (match_operand:SI 2 "immediate_operand" "i")
3955                             (match_operand:SI 3 "immediate_operand" "i")]
3956                            UNSPEC_VQSHRN_N))]
3957   "TARGET_NEON"
3959   neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3960   return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3962   [(set_attr "neon_type" "neon_shift_2")]
3965 (define_insn "neon_vqshrun_n<mode>"
3966   [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3967         (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3968                             (match_operand:SI 2 "immediate_operand" "i")
3969                             (match_operand:SI 3 "immediate_operand" "i")]
3970                            UNSPEC_VQSHRUN_N))]
3971   "TARGET_NEON"
3973   neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3974   return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3976   [(set_attr "neon_type" "neon_shift_2")]
3979 (define_insn "neon_vshl_n<mode>"
3980   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3981         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3982                        (match_operand:SI 2 "immediate_operand" "i")
3983                        (match_operand:SI 3 "immediate_operand" "i")]
3984                       UNSPEC_VSHL_N))]
3985   "TARGET_NEON"
3987   neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
3988   return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2";
3990   [(set_attr "neon_type" "neon_shift_1")]
3993 (define_insn "neon_vqshl_n<mode>"
3994   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3995         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3996                        (match_operand:SI 2 "immediate_operand" "i")
3997                        (match_operand:SI 3 "immediate_operand" "i")]
3998                       UNSPEC_VQSHL_N))]
3999   "TARGET_NEON"
4001   neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
4002   return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
4004   [(set_attr "neon_type" "neon_shift_2")]
4007 (define_insn "neon_vqshlu_n<mode>"
4008   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4009         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
4010                        (match_operand:SI 2 "immediate_operand" "i")
4011                        (match_operand:SI 3 "immediate_operand" "i")]
4012                       UNSPEC_VQSHLU_N))]
4013   "TARGET_NEON"
4015   neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
4016   return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
4018   [(set_attr "neon_type" "neon_shift_2")]
4021 (define_insn "neon_vshll_n<mode>"
4022   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
4023         (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
4024                            (match_operand:SI 2 "immediate_operand" "i")
4025                            (match_operand:SI 3 "immediate_operand" "i")]
4026                           UNSPEC_VSHLL_N))]
4027   "TARGET_NEON"
4029   /* The boundaries are: 0 < imm <= size.  */
4030   neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1);
4031   return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2";
4033   [(set_attr "neon_type" "neon_shift_1")]
4036 (define_insn "neon_vsra_n<mode>"
4037   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4038         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4039                        (match_operand:VDQIX 2 "s_register_operand" "w")
4040                        (match_operand:SI 3 "immediate_operand" "i")
4041                        (match_operand:SI 4 "immediate_operand" "i")]
4042                       UNSPEC_VSRA_N))]
4043   "TARGET_NEON"
4045   neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
4046   return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4048   [(set_attr "neon_type" "neon_vsra_vrsra")]
4051 (define_insn "neon_vsri_n<mode>"
4052   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4053         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4054                        (match_operand:VDQIX 2 "s_register_operand" "w")
4055                        (match_operand:SI 3 "immediate_operand" "i")]
4056                       UNSPEC_VSRI))]
4057   "TARGET_NEON"
4059   neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
4060   return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4062   [(set (attr "neon_type")
4063       (if_then_else (match_test "<Is_d_reg>")
4064                     (const_string "neon_shift_1")
4065                     (const_string "neon_shift_3")))]
4068 (define_insn "neon_vsli_n<mode>"
4069   [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4070         (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4071                        (match_operand:VDQIX 2 "s_register_operand" "w")
4072                        (match_operand:SI 3 "immediate_operand" "i")]
4073                       UNSPEC_VSLI))]
4074   "TARGET_NEON"
4076   neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode));
4077   return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4079   [(set (attr "neon_type")
4080       (if_then_else (match_test "<Is_d_reg>")
4081                     (const_string "neon_shift_1")
4082                     (const_string "neon_shift_3")))]
4085 (define_insn "neon_vtbl1v8qi"
4086   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4087         (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w")
4088                       (match_operand:V8QI 2 "s_register_operand" "w")]
4089                      UNSPEC_VTBL))]
4090   "TARGET_NEON"
4091   "vtbl.8\t%P0, {%P1}, %P2"
4092   [(set_attr "neon_type" "neon_bp_2cycle")]
4095 (define_insn "neon_vtbl2v8qi"
4096   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4097         (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w")
4098                       (match_operand:V8QI 2 "s_register_operand" "w")]
4099                      UNSPEC_VTBL))]
4100   "TARGET_NEON"
4102   rtx ops[4];
4103   int tabbase = REGNO (operands[1]);
4105   ops[0] = operands[0];
4106   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4107   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4108   ops[3] = operands[2];
4109   output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops);
4111   return "";
4113   [(set_attr "neon_type" "neon_bp_2cycle")]
4116 (define_insn "neon_vtbl3v8qi"
4117   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4118         (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w")
4119                       (match_operand:V8QI 2 "s_register_operand" "w")]
4120                      UNSPEC_VTBL))]
4121   "TARGET_NEON"
4123   rtx ops[5];
4124   int tabbase = REGNO (operands[1]);
4126   ops[0] = operands[0];
4127   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4128   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4129   ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4130   ops[4] = operands[2];
4131   output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4133   return "";
4135   [(set_attr "neon_type" "neon_bp_3cycle")]
4138 (define_insn "neon_vtbl4v8qi"
4139   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4140         (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w")
4141                       (match_operand:V8QI 2 "s_register_operand" "w")]
4142                      UNSPEC_VTBL))]
4143   "TARGET_NEON"
4145   rtx ops[6];
4146   int tabbase = REGNO (operands[1]);
4148   ops[0] = operands[0];
4149   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4150   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4151   ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4152   ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4153   ops[5] = operands[2];
4154   output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4156   return "";
4158   [(set_attr "neon_type" "neon_bp_3cycle")]
4161 ;; These three are used by the vec_perm infrastructure for V16QImode.
4162 (define_insn_and_split "neon_vtbl1v16qi"
4163   [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
4164         (unspec:V16QI [(match_operand:V16QI 1 "s_register_operand" "w")
4165                        (match_operand:V16QI 2 "s_register_operand" "w")]
4166                       UNSPEC_VTBL))]
4167   "TARGET_NEON"
4168   "#"
4169   "&& reload_completed"
4170   [(const_int 0)]
4172   rtx op0, op1, op2, part0, part2;
4173   unsigned ofs;
4175   op0 = operands[0];
4176   op1 = gen_lowpart (TImode, operands[1]);
4177   op2 = operands[2];
4179   ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4180   part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4181   part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4182   emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4184   ofs = subreg_highpart_offset (V8QImode, V16QImode);
4185   part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4186   part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4187   emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4188   DONE;
4191 (define_insn_and_split "neon_vtbl2v16qi"
4192   [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
4193         (unspec:V16QI [(match_operand:OI 1 "s_register_operand" "w")
4194                        (match_operand:V16QI 2 "s_register_operand" "w")]
4195                       UNSPEC_VTBL))]
4196   "TARGET_NEON"
4197   "#"
4198   "&& reload_completed"
4199   [(const_int 0)]
4201   rtx op0, op1, op2, part0, part2;
4202   unsigned ofs;
4204   op0 = operands[0];
4205   op1 = operands[1];
4206   op2 = operands[2];
4208   ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4209   part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4210   part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4211   emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4213   ofs = subreg_highpart_offset (V8QImode, V16QImode);
4214   part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4215   part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4216   emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4217   DONE;
4220 ;; ??? Logically we should extend the regular neon_vcombine pattern to
4221 ;; handle quad-word input modes, producing octa-word output modes.  But
4222 ;; that requires us to add support for octa-word vector modes in moves.
4223 ;; That seems overkill for this one use in vec_perm.
4224 (define_insn_and_split "neon_vcombinev16qi"
4225   [(set (match_operand:OI 0 "s_register_operand" "=w")
4226         (unspec:OI [(match_operand:V16QI 1 "s_register_operand" "w")
4227                     (match_operand:V16QI 2 "s_register_operand" "w")]
4228                    UNSPEC_VCONCAT))]
4229   "TARGET_NEON"
4230   "#"
4231   "&& reload_completed"
4232   [(const_int 0)]
4234   neon_split_vcombine (operands);
4235   DONE;
4238 (define_insn "neon_vtbx1v8qi"
4239   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4240         (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4241                       (match_operand:V8QI 2 "s_register_operand" "w")
4242                       (match_operand:V8QI 3 "s_register_operand" "w")]
4243                      UNSPEC_VTBX))]
4244   "TARGET_NEON"
4245   "vtbx.8\t%P0, {%P2}, %P3"
4246   [(set_attr "neon_type" "neon_bp_2cycle")]
4249 (define_insn "neon_vtbx2v8qi"
4250   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4251         (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4252                       (match_operand:TI 2 "s_register_operand" "w")
4253                       (match_operand:V8QI 3 "s_register_operand" "w")]
4254                      UNSPEC_VTBX))]
4255   "TARGET_NEON"
4257   rtx ops[4];
4258   int tabbase = REGNO (operands[2]);
4260   ops[0] = operands[0];
4261   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4262   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4263   ops[3] = operands[3];
4264   output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops);
4266   return "";
4268   [(set_attr "neon_type" "neon_bp_2cycle")]
4271 (define_insn "neon_vtbx3v8qi"
4272   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4273         (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4274                       (match_operand:EI 2 "s_register_operand" "w")
4275                       (match_operand:V8QI 3 "s_register_operand" "w")]
4276                      UNSPEC_VTBX))]
4277   "TARGET_NEON"
4279   rtx ops[5];
4280   int tabbase = REGNO (operands[2]);
4282   ops[0] = operands[0];
4283   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4284   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4285   ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4286   ops[4] = operands[3];
4287   output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4289   return "";
4291   [(set_attr "neon_type" "neon_bp_3cycle")]
4294 (define_insn "neon_vtbx4v8qi"
4295   [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4296         (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4297                       (match_operand:OI 2 "s_register_operand" "w")
4298                       (match_operand:V8QI 3 "s_register_operand" "w")]
4299                      UNSPEC_VTBX))]
4300   "TARGET_NEON"
4302   rtx ops[6];
4303   int tabbase = REGNO (operands[2]);
4305   ops[0] = operands[0];
4306   ops[1] = gen_rtx_REG (V8QImode, tabbase);
4307   ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4308   ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4309   ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4310   ops[5] = operands[3];
4311   output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4313   return "";
4315   [(set_attr "neon_type" "neon_bp_3cycle")]
4318 (define_expand "neon_vtrn<mode>_internal"
4319   [(parallel
4320     [(set (match_operand:VDQW 0 "s_register_operand" "")
4321           (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4322                         (match_operand:VDQW 2 "s_register_operand" "")]
4323            UNSPEC_VTRN1))
4324      (set (match_operand:VDQW 3 "s_register_operand" "")
4325           (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VTRN2))])]
4326   "TARGET_NEON"
4327   ""
4330 ;; Note: Different operand numbering to handle tied registers correctly.
4331 (define_insn "*neon_vtrn<mode>_insn"
4332   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4333         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4334                       (match_operand:VDQW 3 "s_register_operand" "2")]
4335                      UNSPEC_VTRN1))
4336    (set (match_operand:VDQW 2 "s_register_operand" "=w")
4337          (unspec:VDQW [(match_dup 1) (match_dup 3)]
4338                      UNSPEC_VTRN2))]
4339   "TARGET_NEON"
4340   "vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4341   [(set (attr "neon_type")
4342       (if_then_else (match_test "<Is_d_reg>")
4343                     (const_string "neon_bp_simple")
4344                     (const_string "neon_bp_3cycle")))]
4347 (define_expand "neon_vtrn<mode>"
4348   [(match_operand:SI 0 "s_register_operand" "r")
4349    (match_operand:VDQW 1 "s_register_operand" "w")
4350    (match_operand:VDQW 2 "s_register_operand" "w")]
4351   "TARGET_NEON"
4353   neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal,
4354                               operands[0], operands[1], operands[2]);
4355   DONE;
4358 (define_expand "neon_vzip<mode>_internal"
4359   [(parallel
4360     [(set (match_operand:VDQW 0 "s_register_operand" "")
4361           (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4362                         (match_operand:VDQW 2 "s_register_operand" "")]
4363                        UNSPEC_VZIP1))
4364     (set (match_operand:VDQW 3 "s_register_operand" "")
4365          (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VZIP2))])]
4366   "TARGET_NEON"
4367   ""
4370 ;; Note: Different operand numbering to handle tied registers correctly.
4371 (define_insn "*neon_vzip<mode>_insn"
4372   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4373         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4374                       (match_operand:VDQW 3 "s_register_operand" "2")]
4375                      UNSPEC_VZIP1))
4376    (set (match_operand:VDQW 2 "s_register_operand" "=w")
4377         (unspec:VDQW [(match_dup 1) (match_dup 3)]
4378                      UNSPEC_VZIP2))]
4379   "TARGET_NEON"
4380   "vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4381   [(set (attr "neon_type")
4382       (if_then_else (match_test "<Is_d_reg>")
4383                     (const_string "neon_bp_simple")
4384                     (const_string "neon_bp_3cycle")))]
4387 (define_expand "neon_vzip<mode>"
4388   [(match_operand:SI 0 "s_register_operand" "r")
4389    (match_operand:VDQW 1 "s_register_operand" "w")
4390    (match_operand:VDQW 2 "s_register_operand" "w")]
4391   "TARGET_NEON"
4393   neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal,
4394                               operands[0], operands[1], operands[2]);
4395   DONE;
4398 (define_expand "neon_vuzp<mode>_internal"
4399   [(parallel
4400     [(set (match_operand:VDQW 0 "s_register_operand" "")
4401           (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4402                         (match_operand:VDQW 2 "s_register_operand" "")]
4403            UNSPEC_VUZP1))
4404      (set (match_operand:VDQW 3 "s_register_operand" "")
4405           (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VUZP2))])]
4406   "TARGET_NEON"
4407   ""
4410 ;; Note: Different operand numbering to handle tied registers correctly.
4411 (define_insn "*neon_vuzp<mode>_insn"
4412   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4413         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4414                       (match_operand:VDQW 3 "s_register_operand" "2")]
4415                      UNSPEC_VUZP1))
4416    (set (match_operand:VDQW 2 "s_register_operand" "=w")
4417         (unspec:VDQW [(match_dup 1) (match_dup 3)]
4418                      UNSPEC_VUZP2))]
4419   "TARGET_NEON"
4420   "vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4421   [(set (attr "neon_type")
4422       (if_then_else (match_test "<Is_d_reg>")
4423                     (const_string "neon_bp_simple")
4424                     (const_string "neon_bp_3cycle")))]
4427 (define_expand "neon_vuzp<mode>"
4428   [(match_operand:SI 0 "s_register_operand" "r")
4429    (match_operand:VDQW 1 "s_register_operand" "w")
4430    (match_operand:VDQW 2 "s_register_operand" "w")]
4431   "TARGET_NEON"
4433   neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal,
4434                               operands[0], operands[1], operands[2]);
4435   DONE;
4438 (define_expand "neon_vreinterpretv8qi<mode>"
4439   [(match_operand:V8QI 0 "s_register_operand" "")
4440    (match_operand:VDX 1 "s_register_operand" "")]
4441   "TARGET_NEON"
4443   neon_reinterpret (operands[0], operands[1]);
4444   DONE;
4447 (define_expand "neon_vreinterpretv4hi<mode>"
4448   [(match_operand:V4HI 0 "s_register_operand" "")
4449    (match_operand:VDX 1 "s_register_operand" "")]
4450   "TARGET_NEON"
4452   neon_reinterpret (operands[0], operands[1]);
4453   DONE;
4456 (define_expand "neon_vreinterpretv2si<mode>"
4457   [(match_operand:V2SI 0 "s_register_operand" "")
4458    (match_operand:VDX 1 "s_register_operand" "")]
4459   "TARGET_NEON"
4461   neon_reinterpret (operands[0], operands[1]);
4462   DONE;
4465 (define_expand "neon_vreinterpretv2sf<mode>"
4466   [(match_operand:V2SF 0 "s_register_operand" "")
4467    (match_operand:VDX 1 "s_register_operand" "")]
4468   "TARGET_NEON"
4470   neon_reinterpret (operands[0], operands[1]);
4471   DONE;
4474 (define_expand "neon_vreinterpretdi<mode>"
4475   [(match_operand:DI 0 "s_register_operand" "")
4476    (match_operand:VDX 1 "s_register_operand" "")]
4477   "TARGET_NEON"
4479   neon_reinterpret (operands[0], operands[1]);
4480   DONE;
4483 (define_expand "neon_vreinterpretv16qi<mode>"
4484   [(match_operand:V16QI 0 "s_register_operand" "")
4485    (match_operand:VQX 1 "s_register_operand" "")]
4486   "TARGET_NEON"
4488   neon_reinterpret (operands[0], operands[1]);
4489   DONE;
4492 (define_expand "neon_vreinterpretv8hi<mode>"
4493   [(match_operand:V8HI 0 "s_register_operand" "")
4494    (match_operand:VQX 1 "s_register_operand" "")]
4495   "TARGET_NEON"
4497   neon_reinterpret (operands[0], operands[1]);
4498   DONE;
4501 (define_expand "neon_vreinterpretv4si<mode>"
4502   [(match_operand:V4SI 0 "s_register_operand" "")
4503    (match_operand:VQX 1 "s_register_operand" "")]
4504   "TARGET_NEON"
4506   neon_reinterpret (operands[0], operands[1]);
4507   DONE;
4510 (define_expand "neon_vreinterpretv4sf<mode>"
4511   [(match_operand:V4SF 0 "s_register_operand" "")
4512    (match_operand:VQX 1 "s_register_operand" "")]
4513   "TARGET_NEON"
4515   neon_reinterpret (operands[0], operands[1]);
4516   DONE;
4519 (define_expand "neon_vreinterpretv2di<mode>"
4520   [(match_operand:V2DI 0 "s_register_operand" "")
4521    (match_operand:VQX 1 "s_register_operand" "")]
4522   "TARGET_NEON"
4524   neon_reinterpret (operands[0], operands[1]);
4525   DONE;
4528 (define_expand "vec_load_lanes<mode><mode>"
4529   [(set (match_operand:VDQX 0 "s_register_operand")
4530         (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand")]
4531                      UNSPEC_VLD1))]
4532   "TARGET_NEON")
4534 (define_insn "neon_vld1<mode>"
4535   [(set (match_operand:VDQX 0 "s_register_operand" "=w")
4536         (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand" "Um")]
4537                     UNSPEC_VLD1))]
4538   "TARGET_NEON"
4539   "vld1.<V_sz_elem>\t%h0, %A1"
4540   [(set_attr "neon_type" "neon_vld1_1_2_regs")]
4543 (define_insn "neon_vld1_lane<mode>"
4544   [(set (match_operand:VDX 0 "s_register_operand" "=w")
4545         (unspec:VDX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4546                      (match_operand:VDX 2 "s_register_operand" "0")
4547                      (match_operand:SI 3 "immediate_operand" "i")]
4548                     UNSPEC_VLD1_LANE))]
4549   "TARGET_NEON"
4551   HOST_WIDE_INT lane = INTVAL (operands[3]);
4552   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4553   if (lane < 0 || lane >= max)
4554     error ("lane out of range");
4555   if (max == 1)
4556     return "vld1.<V_sz_elem>\t%P0, %A1";
4557   else
4558     return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4560   [(set (attr "neon_type")
4561       (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4562                     (const_string "neon_vld1_1_2_regs")
4563                     (const_string "neon_vld1_vld2_lane")))]
4566 (define_insn "neon_vld1_lane<mode>"
4567   [(set (match_operand:VQX 0 "s_register_operand" "=w")
4568         (unspec:VQX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4569                      (match_operand:VQX 2 "s_register_operand" "0")
4570                      (match_operand:SI 3 "immediate_operand" "i")]
4571                     UNSPEC_VLD1_LANE))]
4572   "TARGET_NEON"
4574   HOST_WIDE_INT lane = INTVAL (operands[3]);
4575   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4576   int regno = REGNO (operands[0]);
4577   if (lane < 0 || lane >= max)
4578     error ("lane out of range");
4579   else if (lane >= max / 2)
4580     {
4581       lane -= max / 2;
4582       regno += 2;
4583       operands[3] = GEN_INT (lane);
4584     }
4585   operands[0] = gen_rtx_REG (<V_HALF>mode, regno);
4586   if (max == 2)
4587     return "vld1.<V_sz_elem>\t%P0, %A1";
4588   else
4589     return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4591   [(set (attr "neon_type")
4592       (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4593                     (const_string "neon_vld1_1_2_regs")
4594                     (const_string "neon_vld1_vld2_lane")))]
4597 (define_insn "neon_vld1_dup<mode>"
4598   [(set (match_operand:VDX 0 "s_register_operand" "=w")
4599         (vec_duplicate:VDX (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))]
4600   "TARGET_NEON"
4602   if (GET_MODE_NUNITS (<MODE>mode) > 1)
4603     return "vld1.<V_sz_elem>\t{%P0[]}, %A1";
4604   else
4605     return "vld1.<V_sz_elem>\t%h0, %A1";
4607   [(set (attr "neon_type")
4608       (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4609                     (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4610                     (const_string "neon_vld1_1_2_regs")))]
4613 (define_insn "neon_vld1_dup<mode>"
4614   [(set (match_operand:VQ 0 "s_register_operand" "=w")
4615         (vec_duplicate:VQ (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))]
4616   "TARGET_NEON"
4618   return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4620   [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
4623 (define_insn_and_split "neon_vld1_dupv2di"
4624    [(set (match_operand:V2DI 0 "s_register_operand" "=w")
4625     (vec_duplicate:V2DI (match_operand:DI 1 "neon_struct_operand" "Um")))]
4626    "TARGET_NEON"
4627    "#"
4628    "&& reload_completed"
4629    [(const_int 0)]
4630    {
4631     rtx tmprtx = gen_lowpart (DImode, operands[0]);
4632     emit_insn (gen_neon_vld1_dupdi (tmprtx, operands[1]));
4633     emit_move_insn (gen_highpart (DImode, operands[0]), tmprtx );
4634     DONE;
4635     }
4636   [(set_attr "length" "8")
4637    (set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
4640 (define_expand "vec_store_lanes<mode><mode>"
4641   [(set (match_operand:VDQX 0 "neon_struct_operand")
4642         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand")]
4643                      UNSPEC_VST1))]
4644   "TARGET_NEON")
4646 (define_insn "neon_vst1<mode>"
4647   [(set (match_operand:VDQX 0 "neon_struct_operand" "=Um")
4648         (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")]
4649                      UNSPEC_VST1))]
4650   "TARGET_NEON"
4651   "vst1.<V_sz_elem>\t%h1, %A0"
4652   [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
4654 (define_insn "neon_vst1_lane<mode>"
4655   [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4656         (unspec:<V_elem>
4657           [(match_operand:VDX 1 "s_register_operand" "w")
4658            (match_operand:SI 2 "immediate_operand" "i")]
4659           UNSPEC_VST1_LANE))]
4660   "TARGET_NEON"
4662   HOST_WIDE_INT lane = INTVAL (operands[2]);
4663   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4664   if (lane < 0 || lane >= max)
4665     error ("lane out of range");
4666   if (max == 1)
4667     return "vst1.<V_sz_elem>\t{%P1}, %A0";
4668   else
4669     return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4671   [(set (attr "neon_type")
4672       (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1))
4673                     (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4674                     (const_string "neon_vst1_vst2_lane")))])
4676 (define_insn "neon_vst1_lane<mode>"
4677   [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4678         (unspec:<V_elem>
4679           [(match_operand:VQX 1 "s_register_operand" "w")
4680            (match_operand:SI 2 "immediate_operand" "i")]
4681           UNSPEC_VST1_LANE))]
4682   "TARGET_NEON"
4684   HOST_WIDE_INT lane = INTVAL (operands[2]);
4685   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4686   int regno = REGNO (operands[1]);
4687   if (lane < 0 || lane >= max)
4688     error ("lane out of range");
4689   else if (lane >= max / 2)
4690     {
4691       lane -= max / 2;
4692       regno += 2;
4693       operands[2] = GEN_INT (lane);
4694     }
4695   operands[1] = gen_rtx_REG (<V_HALF>mode, regno);
4696   if (max == 2)
4697     return "vst1.<V_sz_elem>\t{%P1}, %A0";
4698   else
4699     return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4701   [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4704 (define_expand "vec_load_lanesti<mode>"
4705   [(set (match_operand:TI 0 "s_register_operand")
4706         (unspec:TI [(match_operand:TI 1 "neon_struct_operand")
4707                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4708                    UNSPEC_VLD2))]
4709   "TARGET_NEON")
4711 (define_insn "neon_vld2<mode>"
4712   [(set (match_operand:TI 0 "s_register_operand" "=w")
4713         (unspec:TI [(match_operand:TI 1 "neon_struct_operand" "Um")
4714                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4715                    UNSPEC_VLD2))]
4716   "TARGET_NEON"
4718   if (<V_sz_elem> == 64)
4719     return "vld1.64\t%h0, %A1";
4720   else
4721     return "vld2.<V_sz_elem>\t%h0, %A1";
4723   [(set (attr "neon_type")
4724       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4725                     (const_string "neon_vld1_1_2_regs")
4726                     (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
4729 (define_expand "vec_load_lanesoi<mode>"
4730   [(set (match_operand:OI 0 "s_register_operand")
4731         (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
4732                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4733                    UNSPEC_VLD2))]
4734   "TARGET_NEON")
4736 (define_insn "neon_vld2<mode>"
4737   [(set (match_operand:OI 0 "s_register_operand" "=w")
4738         (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
4739                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4740                    UNSPEC_VLD2))]
4741   "TARGET_NEON"
4742   "vld2.<V_sz_elem>\t%h0, %A1"
4743   [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
4745 (define_insn "neon_vld2_lane<mode>"
4746   [(set (match_operand:TI 0 "s_register_operand" "=w")
4747         (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4748                     (match_operand:TI 2 "s_register_operand" "0")
4749                     (match_operand:SI 3 "immediate_operand" "i")
4750                     (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4751                    UNSPEC_VLD2_LANE))]
4752   "TARGET_NEON"
4754   HOST_WIDE_INT lane = INTVAL (operands[3]);
4755   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4756   int regno = REGNO (operands[0]);
4757   rtx ops[4];
4758   if (lane < 0 || lane >= max)
4759     error ("lane out of range");
4760   ops[0] = gen_rtx_REG (DImode, regno);
4761   ops[1] = gen_rtx_REG (DImode, regno + 2);
4762   ops[2] = operands[1];
4763   ops[3] = operands[3];
4764   output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4765   return "";
4767   [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4770 (define_insn "neon_vld2_lane<mode>"
4771   [(set (match_operand:OI 0 "s_register_operand" "=w")
4772         (unspec:OI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4773                     (match_operand:OI 2 "s_register_operand" "0")
4774                     (match_operand:SI 3 "immediate_operand" "i")
4775                     (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4776                    UNSPEC_VLD2_LANE))]
4777   "TARGET_NEON"
4779   HOST_WIDE_INT lane = INTVAL (operands[3]);
4780   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4781   int regno = REGNO (operands[0]);
4782   rtx ops[4];
4783   if (lane < 0 || lane >= max)
4784     error ("lane out of range");
4785   else if (lane >= max / 2)
4786     {
4787       lane -= max / 2;
4788       regno += 2;
4789     }
4790   ops[0] = gen_rtx_REG (DImode, regno);
4791   ops[1] = gen_rtx_REG (DImode, regno + 4);
4792   ops[2] = operands[1];
4793   ops[3] = GEN_INT (lane);
4794   output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4795   return "";
4797   [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4800 (define_insn "neon_vld2_dup<mode>"
4801   [(set (match_operand:TI 0 "s_register_operand" "=w")
4802         (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4803                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4804                    UNSPEC_VLD2_DUP))]
4805   "TARGET_NEON"
4807   if (GET_MODE_NUNITS (<MODE>mode) > 1)
4808     return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4809   else
4810     return "vld1.<V_sz_elem>\t%h0, %A1";
4812   [(set (attr "neon_type")
4813       (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4814                     (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4815                     (const_string "neon_vld1_1_2_regs")))]
4818 (define_expand "vec_store_lanesti<mode>"
4819   [(set (match_operand:TI 0 "neon_struct_operand")
4820         (unspec:TI [(match_operand:TI 1 "s_register_operand")
4821                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4822                    UNSPEC_VST2))]
4823   "TARGET_NEON")
4825 (define_insn "neon_vst2<mode>"
4826   [(set (match_operand:TI 0 "neon_struct_operand" "=Um")
4827         (unspec:TI [(match_operand:TI 1 "s_register_operand" "w")
4828                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4829                    UNSPEC_VST2))]
4830   "TARGET_NEON"
4832   if (<V_sz_elem> == 64)
4833     return "vst1.64\t%h1, %A0";
4834   else
4835     return "vst2.<V_sz_elem>\t%h1, %A0";
4837   [(set (attr "neon_type")
4838       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4839                     (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4840                     (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
4843 (define_expand "vec_store_lanesoi<mode>"
4844   [(set (match_operand:OI 0 "neon_struct_operand")
4845         (unspec:OI [(match_operand:OI 1 "s_register_operand")
4846                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4847                    UNSPEC_VST2))]
4848   "TARGET_NEON")
4850 (define_insn "neon_vst2<mode>"
4851   [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
4852         (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
4853                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4854                    UNSPEC_VST2))]
4855   "TARGET_NEON"
4856   "vst2.<V_sz_elem>\t%h1, %A0"
4857   [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]
4860 (define_insn "neon_vst2_lane<mode>"
4861   [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4862         (unspec:<V_two_elem>
4863           [(match_operand:TI 1 "s_register_operand" "w")
4864            (match_operand:SI 2 "immediate_operand" "i")
4865            (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4866           UNSPEC_VST2_LANE))]
4867   "TARGET_NEON"
4869   HOST_WIDE_INT lane = INTVAL (operands[2]);
4870   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4871   int regno = REGNO (operands[1]);
4872   rtx ops[4];
4873   if (lane < 0 || lane >= max)
4874     error ("lane out of range");
4875   ops[0] = operands[0];
4876   ops[1] = gen_rtx_REG (DImode, regno);
4877   ops[2] = gen_rtx_REG (DImode, regno + 2);
4878   ops[3] = operands[2];
4879   output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4880   return "";
4882   [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4885 (define_insn "neon_vst2_lane<mode>"
4886   [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4887         (unspec:<V_two_elem>
4888            [(match_operand:OI 1 "s_register_operand" "w")
4889             (match_operand:SI 2 "immediate_operand" "i")
4890             (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4891            UNSPEC_VST2_LANE))]
4892   "TARGET_NEON"
4894   HOST_WIDE_INT lane = INTVAL (operands[2]);
4895   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4896   int regno = REGNO (operands[1]);
4897   rtx ops[4];
4898   if (lane < 0 || lane >= max)
4899     error ("lane out of range");
4900   else if (lane >= max / 2)
4901     {
4902       lane -= max / 2;
4903       regno += 2;
4904     }
4905   ops[0] = operands[0];
4906   ops[1] = gen_rtx_REG (DImode, regno);
4907   ops[2] = gen_rtx_REG (DImode, regno + 4);
4908   ops[3] = GEN_INT (lane);
4909   output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4910   return "";
4912   [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4915 (define_expand "vec_load_lanesei<mode>"
4916   [(set (match_operand:EI 0 "s_register_operand")
4917         (unspec:EI [(match_operand:EI 1 "neon_struct_operand")
4918                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4919                    UNSPEC_VLD3))]
4920   "TARGET_NEON")
4922 (define_insn "neon_vld3<mode>"
4923   [(set (match_operand:EI 0 "s_register_operand" "=w")
4924         (unspec:EI [(match_operand:EI 1 "neon_struct_operand" "Um")
4925                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4926                    UNSPEC_VLD3))]
4927   "TARGET_NEON"
4929   if (<V_sz_elem> == 64)
4930     return "vld1.64\t%h0, %A1";
4931   else
4932     return "vld3.<V_sz_elem>\t%h0, %A1";
4934   [(set (attr "neon_type")
4935       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4936                     (const_string "neon_vld1_1_2_regs")
4937                     (const_string "neon_vld3_vld4")))]
4940 (define_expand "vec_load_lanesci<mode>"
4941   [(match_operand:CI 0 "s_register_operand")
4942    (match_operand:CI 1 "neon_struct_operand")
4943    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4944   "TARGET_NEON"
4946   emit_insn (gen_neon_vld3<mode> (operands[0], operands[1]));
4947   DONE;
4950 (define_expand "neon_vld3<mode>"
4951   [(match_operand:CI 0 "s_register_operand")
4952    (match_operand:CI 1 "neon_struct_operand")
4953    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4954   "TARGET_NEON"
4956   rtx mem;
4958   mem = adjust_address (operands[1], EImode, 0);
4959   emit_insn (gen_neon_vld3qa<mode> (operands[0], mem));
4960   mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4961   emit_insn (gen_neon_vld3qb<mode> (operands[0], mem, operands[0]));
4962   DONE;
4965 (define_insn "neon_vld3qa<mode>"
4966   [(set (match_operand:CI 0 "s_register_operand" "=w")
4967         (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4968                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4969                    UNSPEC_VLD3A))]
4970   "TARGET_NEON"
4972   int regno = REGNO (operands[0]);
4973   rtx ops[4];
4974   ops[0] = gen_rtx_REG (DImode, regno);
4975   ops[1] = gen_rtx_REG (DImode, regno + 4);
4976   ops[2] = gen_rtx_REG (DImode, regno + 8);
4977   ops[3] = operands[1];
4978   output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4979   return "";
4981   [(set_attr "neon_type" "neon_vld3_vld4")]
4984 (define_insn "neon_vld3qb<mode>"
4985   [(set (match_operand:CI 0 "s_register_operand" "=w")
4986         (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4987                     (match_operand:CI 2 "s_register_operand" "0")
4988                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4989                    UNSPEC_VLD3B))]
4990   "TARGET_NEON"
4992   int regno = REGNO (operands[0]);
4993   rtx ops[4];
4994   ops[0] = gen_rtx_REG (DImode, regno + 2);
4995   ops[1] = gen_rtx_REG (DImode, regno + 6);
4996   ops[2] = gen_rtx_REG (DImode, regno + 10);
4997   ops[3] = operands[1];
4998   output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4999   return "";
5001   [(set_attr "neon_type" "neon_vld3_vld4")]
5004 (define_insn "neon_vld3_lane<mode>"
5005   [(set (match_operand:EI 0 "s_register_operand" "=w")
5006         (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5007                     (match_operand:EI 2 "s_register_operand" "0")
5008                     (match_operand:SI 3 "immediate_operand" "i")
5009                     (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5010                    UNSPEC_VLD3_LANE))]
5011   "TARGET_NEON"
5013   HOST_WIDE_INT lane = INTVAL (operands[3]);
5014   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5015   int regno = REGNO (operands[0]);
5016   rtx ops[5];
5017   if (lane < 0 || lane >= max)
5018     error ("lane out of range");
5019   ops[0] = gen_rtx_REG (DImode, regno);
5020   ops[1] = gen_rtx_REG (DImode, regno + 2);
5021   ops[2] = gen_rtx_REG (DImode, regno + 4);
5022   ops[3] = operands[1];
5023   ops[4] = operands[3];
5024   output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %3",
5025                    ops);
5026   return "";
5028   [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5031 (define_insn "neon_vld3_lane<mode>"
5032   [(set (match_operand:CI 0 "s_register_operand" "=w")
5033         (unspec:CI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5034                     (match_operand:CI 2 "s_register_operand" "0")
5035                     (match_operand:SI 3 "immediate_operand" "i")
5036                     (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5037                    UNSPEC_VLD3_LANE))]
5038   "TARGET_NEON"
5040   HOST_WIDE_INT lane = INTVAL (operands[3]);
5041   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5042   int regno = REGNO (operands[0]);
5043   rtx ops[5];
5044   if (lane < 0 || lane >= max)
5045     error ("lane out of range");
5046   else if (lane >= max / 2)
5047     {
5048       lane -= max / 2;
5049       regno += 2;
5050     }
5051   ops[0] = gen_rtx_REG (DImode, regno);
5052   ops[1] = gen_rtx_REG (DImode, regno + 4);
5053   ops[2] = gen_rtx_REG (DImode, regno + 8);
5054   ops[3] = operands[1];
5055   ops[4] = GEN_INT (lane);
5056   output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %3",
5057                    ops);
5058   return "";
5060   [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5063 (define_insn "neon_vld3_dup<mode>"
5064   [(set (match_operand:EI 0 "s_register_operand" "=w")
5065         (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5066                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5067                    UNSPEC_VLD3_DUP))]
5068   "TARGET_NEON"
5070   if (GET_MODE_NUNITS (<MODE>mode) > 1)
5071     {
5072       int regno = REGNO (operands[0]);
5073       rtx ops[4];
5074       ops[0] = gen_rtx_REG (DImode, regno);
5075       ops[1] = gen_rtx_REG (DImode, regno + 2);
5076       ops[2] = gen_rtx_REG (DImode, regno + 4);
5077       ops[3] = operands[1];
5078       output_asm_insn ("vld3.<V_sz_elem>\t{%P0[], %P1[], %P2[]}, %3", ops);
5079       return "";
5080     }
5081   else
5082     return "vld1.<V_sz_elem>\t%h0, %A1";
5084   [(set (attr "neon_type")
5085       (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
5086                     (const_string "neon_vld3_vld4_all_lanes")
5087                     (const_string "neon_vld1_1_2_regs")))])
5089 (define_expand "vec_store_lanesei<mode>"
5090   [(set (match_operand:EI 0 "neon_struct_operand")
5091         (unspec:EI [(match_operand:EI 1 "s_register_operand")
5092                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5093                    UNSPEC_VST3))]
5094   "TARGET_NEON")
5096 (define_insn "neon_vst3<mode>"
5097   [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5098         (unspec:EI [(match_operand:EI 1 "s_register_operand" "w")
5099                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5100                    UNSPEC_VST3))]
5101   "TARGET_NEON"
5103   if (<V_sz_elem> == 64)
5104     return "vst1.64\t%h1, %A0";
5105   else
5106     return "vst3.<V_sz_elem>\t%h1, %A0";
5108   [(set (attr "neon_type")
5109       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5110                     (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5111                     (const_string "neon_vst2_4_regs_vst3_vst4")))])
5113 (define_expand "vec_store_lanesci<mode>"
5114   [(match_operand:CI 0 "neon_struct_operand")
5115    (match_operand:CI 1 "s_register_operand")
5116    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5117   "TARGET_NEON"
5119   emit_insn (gen_neon_vst3<mode> (operands[0], operands[1]));
5120   DONE;
5123 (define_expand "neon_vst3<mode>"
5124   [(match_operand:CI 0 "neon_struct_operand")
5125    (match_operand:CI 1 "s_register_operand")
5126    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5127   "TARGET_NEON"
5129   rtx mem;
5131   mem = adjust_address (operands[0], EImode, 0);
5132   emit_insn (gen_neon_vst3qa<mode> (mem, operands[1]));
5133   mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
5134   emit_insn (gen_neon_vst3qb<mode> (mem, operands[1]));
5135   DONE;
5138 (define_insn "neon_vst3qa<mode>"
5139   [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5140         (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
5141                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5142                    UNSPEC_VST3A))]
5143   "TARGET_NEON"
5145   int regno = REGNO (operands[1]);
5146   rtx ops[4];
5147   ops[0] = operands[0];
5148   ops[1] = gen_rtx_REG (DImode, regno);
5149   ops[2] = gen_rtx_REG (DImode, regno + 4);
5150   ops[3] = gen_rtx_REG (DImode, regno + 8);
5151   output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
5152   return "";
5154   [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5157 (define_insn "neon_vst3qb<mode>"
5158   [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5159         (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
5160                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5161                    UNSPEC_VST3B))]
5162   "TARGET_NEON"
5164   int regno = REGNO (operands[1]);
5165   rtx ops[4];
5166   ops[0] = operands[0];
5167   ops[1] = gen_rtx_REG (DImode, regno + 2);
5168   ops[2] = gen_rtx_REG (DImode, regno + 6);
5169   ops[3] = gen_rtx_REG (DImode, regno + 10);
5170   output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
5171   return "";
5173   [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5176 (define_insn "neon_vst3_lane<mode>"
5177   [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
5178         (unspec:<V_three_elem>
5179            [(match_operand:EI 1 "s_register_operand" "w")
5180             (match_operand:SI 2 "immediate_operand" "i")
5181             (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5182            UNSPEC_VST3_LANE))]
5183   "TARGET_NEON"
5185   HOST_WIDE_INT lane = INTVAL (operands[2]);
5186   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5187   int regno = REGNO (operands[1]);
5188   rtx ops[5];
5189   if (lane < 0 || lane >= max)
5190     error ("lane out of range");
5191   ops[0] = operands[0];
5192   ops[1] = gen_rtx_REG (DImode, regno);
5193   ops[2] = gen_rtx_REG (DImode, regno + 2);
5194   ops[3] = gen_rtx_REG (DImode, regno + 4);
5195   ops[4] = operands[2];
5196   output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %0",
5197                    ops);
5198   return "";
5200   [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5203 (define_insn "neon_vst3_lane<mode>"
5204   [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
5205         (unspec:<V_three_elem>
5206            [(match_operand:CI 1 "s_register_operand" "w")
5207             (match_operand:SI 2 "immediate_operand" "i")
5208             (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5209            UNSPEC_VST3_LANE))]
5210   "TARGET_NEON"
5212   HOST_WIDE_INT lane = INTVAL (operands[2]);
5213   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5214   int regno = REGNO (operands[1]);
5215   rtx ops[5];
5216   if (lane < 0 || lane >= max)
5217     error ("lane out of range");
5218   else if (lane >= max / 2)
5219     {
5220       lane -= max / 2;
5221       regno += 2;
5222     }
5223   ops[0] = operands[0];
5224   ops[1] = gen_rtx_REG (DImode, regno);
5225   ops[2] = gen_rtx_REG (DImode, regno + 4);
5226   ops[3] = gen_rtx_REG (DImode, regno + 8);
5227   ops[4] = GEN_INT (lane);
5228   output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %0",
5229                    ops);
5230   return "";
5232 [(set_attr "neon_type" "neon_vst3_vst4_lane")])
5234 (define_expand "vec_load_lanesoi<mode>"
5235   [(set (match_operand:OI 0 "s_register_operand")
5236         (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
5237                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5238                    UNSPEC_VLD4))]
5239   "TARGET_NEON")
5241 (define_insn "neon_vld4<mode>"
5242   [(set (match_operand:OI 0 "s_register_operand" "=w")
5243         (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
5244                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5245                    UNSPEC_VLD4))]
5246   "TARGET_NEON"
5248   if (<V_sz_elem> == 64)
5249     return "vld1.64\t%h0, %A1";
5250   else
5251     return "vld4.<V_sz_elem>\t%h0, %A1";
5253   [(set (attr "neon_type")
5254       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5255                     (const_string "neon_vld1_1_2_regs")
5256                     (const_string "neon_vld3_vld4")))]
5259 (define_expand "vec_load_lanesxi<mode>"
5260   [(match_operand:XI 0 "s_register_operand")
5261    (match_operand:XI 1 "neon_struct_operand")
5262    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5263   "TARGET_NEON"
5265   emit_insn (gen_neon_vld4<mode> (operands[0], operands[1]));
5266   DONE;
5269 (define_expand "neon_vld4<mode>"
5270   [(match_operand:XI 0 "s_register_operand")
5271    (match_operand:XI 1 "neon_struct_operand")
5272    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5273   "TARGET_NEON"
5275   rtx mem;
5277   mem = adjust_address (operands[1], OImode, 0);
5278   emit_insn (gen_neon_vld4qa<mode> (operands[0], mem));
5279   mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5280   emit_insn (gen_neon_vld4qb<mode> (operands[0], mem, operands[0]));
5281   DONE;
5284 (define_insn "neon_vld4qa<mode>"
5285   [(set (match_operand:XI 0 "s_register_operand" "=w")
5286         (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5287                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5288                    UNSPEC_VLD4A))]
5289   "TARGET_NEON"
5291   int regno = REGNO (operands[0]);
5292   rtx ops[5];
5293   ops[0] = gen_rtx_REG (DImode, regno);
5294   ops[1] = gen_rtx_REG (DImode, regno + 4);
5295   ops[2] = gen_rtx_REG (DImode, regno + 8);
5296   ops[3] = gen_rtx_REG (DImode, regno + 12);
5297   ops[4] = operands[1];
5298   output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5299   return "";
5301   [(set_attr "neon_type" "neon_vld3_vld4")]
5304 (define_insn "neon_vld4qb<mode>"
5305   [(set (match_operand:XI 0 "s_register_operand" "=w")
5306         (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5307                     (match_operand:XI 2 "s_register_operand" "0")
5308                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5309                    UNSPEC_VLD4B))]
5310   "TARGET_NEON"
5312   int regno = REGNO (operands[0]);
5313   rtx ops[5];
5314   ops[0] = gen_rtx_REG (DImode, regno + 2);
5315   ops[1] = gen_rtx_REG (DImode, regno + 6);
5316   ops[2] = gen_rtx_REG (DImode, regno + 10);
5317   ops[3] = gen_rtx_REG (DImode, regno + 14);
5318   ops[4] = operands[1];
5319   output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5320   return "";
5322   [(set_attr "neon_type" "neon_vld3_vld4")]
5325 (define_insn "neon_vld4_lane<mode>"
5326   [(set (match_operand:OI 0 "s_register_operand" "=w")
5327         (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5328                     (match_operand:OI 2 "s_register_operand" "0")
5329                     (match_operand:SI 3 "immediate_operand" "i")
5330                     (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5331                    UNSPEC_VLD4_LANE))]
5332   "TARGET_NEON"
5334   HOST_WIDE_INT lane = INTVAL (operands[3]);
5335   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5336   int regno = REGNO (operands[0]);
5337   rtx ops[6];
5338   if (lane < 0 || lane >= max)
5339     error ("lane out of range");
5340   ops[0] = gen_rtx_REG (DImode, regno);
5341   ops[1] = gen_rtx_REG (DImode, regno + 2);
5342   ops[2] = gen_rtx_REG (DImode, regno + 4);
5343   ops[3] = gen_rtx_REG (DImode, regno + 6);
5344   ops[4] = operands[1];
5345   ops[5] = operands[3];
5346   output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5347                    ops);
5348   return "";
5350   [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5353 (define_insn "neon_vld4_lane<mode>"
5354   [(set (match_operand:XI 0 "s_register_operand" "=w")
5355         (unspec:XI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5356                     (match_operand:XI 2 "s_register_operand" "0")
5357                     (match_operand:SI 3 "immediate_operand" "i")
5358                     (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5359                    UNSPEC_VLD4_LANE))]
5360   "TARGET_NEON"
5362   HOST_WIDE_INT lane = INTVAL (operands[3]);
5363   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5364   int regno = REGNO (operands[0]);
5365   rtx ops[6];
5366   if (lane < 0 || lane >= max)
5367     error ("lane out of range");
5368   else if (lane >= max / 2)
5369     {
5370       lane -= max / 2;
5371       regno += 2;
5372     }
5373   ops[0] = gen_rtx_REG (DImode, regno);
5374   ops[1] = gen_rtx_REG (DImode, regno + 4);
5375   ops[2] = gen_rtx_REG (DImode, regno + 8);
5376   ops[3] = gen_rtx_REG (DImode, regno + 12);
5377   ops[4] = operands[1];
5378   ops[5] = GEN_INT (lane);
5379   output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5380                    ops);
5381   return "";
5383   [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5386 (define_insn "neon_vld4_dup<mode>"
5387   [(set (match_operand:OI 0 "s_register_operand" "=w")
5388         (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5389                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5390                    UNSPEC_VLD4_DUP))]
5391   "TARGET_NEON"
5393   if (GET_MODE_NUNITS (<MODE>mode) > 1)
5394     {
5395       int regno = REGNO (operands[0]);
5396       rtx ops[5];
5397       ops[0] = gen_rtx_REG (DImode, regno);
5398       ops[1] = gen_rtx_REG (DImode, regno + 2);
5399       ops[2] = gen_rtx_REG (DImode, regno + 4);
5400       ops[3] = gen_rtx_REG (DImode, regno + 6);
5401       ops[4] = operands[1];
5402       output_asm_insn ("vld4.<V_sz_elem>\t{%P0[], %P1[], %P2[], %P3[]}, %A4",
5403                        ops);
5404       return "";
5405     }
5406   else
5407     return "vld1.<V_sz_elem>\t%h0, %A1";
5409   [(set (attr "neon_type")
5410       (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
5411                     (const_string "neon_vld3_vld4_all_lanes")
5412                     (const_string "neon_vld1_1_2_regs")))]
5415 (define_expand "vec_store_lanesoi<mode>"
5416   [(set (match_operand:OI 0 "neon_struct_operand")
5417         (unspec:OI [(match_operand:OI 1 "s_register_operand")
5418                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5419                    UNSPEC_VST4))]
5420   "TARGET_NEON")
5422 (define_insn "neon_vst4<mode>"
5423   [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5424         (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
5425                     (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5426                    UNSPEC_VST4))]
5427   "TARGET_NEON"
5429   if (<V_sz_elem> == 64)
5430     return "vst1.64\t%h1, %A0";
5431   else
5432     return "vst4.<V_sz_elem>\t%h1, %A0";
5434   [(set (attr "neon_type")
5435       (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5436                     (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5437                     (const_string "neon_vst2_4_regs_vst3_vst4")))]
5440 (define_expand "vec_store_lanesxi<mode>"
5441   [(match_operand:XI 0 "neon_struct_operand")
5442    (match_operand:XI 1 "s_register_operand")
5443    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5444   "TARGET_NEON"
5446   emit_insn (gen_neon_vst4<mode> (operands[0], operands[1]));
5447   DONE;
5450 (define_expand "neon_vst4<mode>"
5451   [(match_operand:XI 0 "neon_struct_operand")
5452    (match_operand:XI 1 "s_register_operand")
5453    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5454   "TARGET_NEON"
5456   rtx mem;
5458   mem = adjust_address (operands[0], OImode, 0);
5459   emit_insn (gen_neon_vst4qa<mode> (mem, operands[1]));
5460   mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5461   emit_insn (gen_neon_vst4qb<mode> (mem, operands[1]));
5462   DONE;
5465 (define_insn "neon_vst4qa<mode>"
5466   [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5467         (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5468                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5469                    UNSPEC_VST4A))]
5470   "TARGET_NEON"
5472   int regno = REGNO (operands[1]);
5473   rtx ops[5];
5474   ops[0] = operands[0];
5475   ops[1] = gen_rtx_REG (DImode, regno);
5476   ops[2] = gen_rtx_REG (DImode, regno + 4);
5477   ops[3] = gen_rtx_REG (DImode, regno + 8);
5478   ops[4] = gen_rtx_REG (DImode, regno + 12);
5479   output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5480   return "";
5482   [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5485 (define_insn "neon_vst4qb<mode>"
5486   [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5487         (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5488                     (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5489                    UNSPEC_VST4B))]
5490   "TARGET_NEON"
5492   int regno = REGNO (operands[1]);
5493   rtx ops[5];
5494   ops[0] = operands[0];
5495   ops[1] = gen_rtx_REG (DImode, regno + 2);
5496   ops[2] = gen_rtx_REG (DImode, regno + 6);
5497   ops[3] = gen_rtx_REG (DImode, regno + 10);
5498   ops[4] = gen_rtx_REG (DImode, regno + 14);
5499   output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5500   return "";
5502   [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5505 (define_insn "neon_vst4_lane<mode>"
5506   [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5507         (unspec:<V_four_elem>
5508            [(match_operand:OI 1 "s_register_operand" "w")
5509             (match_operand:SI 2 "immediate_operand" "i")
5510             (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5511            UNSPEC_VST4_LANE))]
5512   "TARGET_NEON"
5514   HOST_WIDE_INT lane = INTVAL (operands[2]);
5515   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5516   int regno = REGNO (operands[1]);
5517   rtx ops[6];
5518   if (lane < 0 || lane >= max)
5519     error ("lane out of range");
5520   ops[0] = operands[0];
5521   ops[1] = gen_rtx_REG (DImode, regno);
5522   ops[2] = gen_rtx_REG (DImode, regno + 2);
5523   ops[3] = gen_rtx_REG (DImode, regno + 4);
5524   ops[4] = gen_rtx_REG (DImode, regno + 6);
5525   ops[5] = operands[2];
5526   output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5527                    ops);
5528   return "";
5530   [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5533 (define_insn "neon_vst4_lane<mode>"
5534   [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5535         (unspec:<V_four_elem>
5536            [(match_operand:XI 1 "s_register_operand" "w")
5537             (match_operand:SI 2 "immediate_operand" "i")
5538             (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5539            UNSPEC_VST4_LANE))]
5540   "TARGET_NEON"
5542   HOST_WIDE_INT lane = INTVAL (operands[2]);
5543   HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5544   int regno = REGNO (operands[1]);
5545   rtx ops[6];
5546   if (lane < 0 || lane >= max)
5547     error ("lane out of range");
5548   else if (lane >= max / 2)
5549     {
5550       lane -= max / 2;
5551       regno += 2;
5552     }
5553   ops[0] = operands[0];
5554   ops[1] = gen_rtx_REG (DImode, regno);
5555   ops[2] = gen_rtx_REG (DImode, regno + 4);
5556   ops[3] = gen_rtx_REG (DImode, regno + 8);
5557   ops[4] = gen_rtx_REG (DImode, regno + 12);
5558   ops[5] = GEN_INT (lane);
5559   output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5560                    ops);
5561   return "";
5563   [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5566 (define_expand "neon_vand<mode>"
5567   [(match_operand:VDQX 0 "s_register_operand" "")
5568    (match_operand:VDQX 1 "s_register_operand" "")
5569    (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5570    (match_operand:SI 3 "immediate_operand" "")]
5571   "TARGET_NEON"
5573   emit_insn (gen_and<mode>3 (operands[0], operands[1], operands[2]));
5574   DONE;
5577 (define_expand "neon_vorr<mode>"
5578   [(match_operand:VDQX 0 "s_register_operand" "")
5579    (match_operand:VDQX 1 "s_register_operand" "")
5580    (match_operand:VDQX 2 "neon_logic_op2" "")
5581    (match_operand:SI 3 "immediate_operand" "")]
5582   "TARGET_NEON"
5584   emit_insn (gen_ior<mode>3 (operands[0], operands[1], operands[2]));
5585   DONE;
5588 (define_expand "neon_veor<mode>"
5589   [(match_operand:VDQX 0 "s_register_operand" "")
5590    (match_operand:VDQX 1 "s_register_operand" "")
5591    (match_operand:VDQX 2 "s_register_operand" "")
5592    (match_operand:SI 3 "immediate_operand" "")]
5593   "TARGET_NEON"
5595   emit_insn (gen_xor<mode>3 (operands[0], operands[1], operands[2]));
5596   DONE;
5599 (define_expand "neon_vbic<mode>"
5600   [(match_operand:VDQX 0 "s_register_operand" "")
5601    (match_operand:VDQX 1 "s_register_operand" "")
5602    (match_operand:VDQX 2 "neon_logic_op2" "")
5603    (match_operand:SI 3 "immediate_operand" "")]
5604   "TARGET_NEON"
5606   emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2]));
5607   DONE;
5610 (define_expand "neon_vorn<mode>"
5611   [(match_operand:VDQX 0 "s_register_operand" "")
5612    (match_operand:VDQX 1 "s_register_operand" "")
5613    (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5614    (match_operand:SI 3 "immediate_operand" "")]
5615   "TARGET_NEON"
5617   emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2]));
5618   DONE;
5621 (define_insn "neon_vec_unpack<US>_lo_<mode>"
5622   [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5623         (SE:<V_unpack> (vec_select:<V_HALF>
5624                           (match_operand:VU 1 "register_operand" "w")
5625                           (match_operand:VU 2 "vect_par_constant_low" ""))))]
5626   "TARGET_NEON && !BYTES_BIG_ENDIAN"
5627   "vmovl.<US><V_sz_elem> %q0, %e1"
5628   [(set_attr "neon_type" "neon_shift_1")]
5631 (define_insn "neon_vec_unpack<US>_hi_<mode>"
5632   [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5633         (SE:<V_unpack> (vec_select:<V_HALF>
5634                           (match_operand:VU 1 "register_operand" "w")
5635                           (match_operand:VU 2 "vect_par_constant_high" ""))))]
5636   "TARGET_NEON && !BYTES_BIG_ENDIAN"
5637   "vmovl.<US><V_sz_elem> %q0, %f1"
5638   [(set_attr "neon_type" "neon_shift_1")]
5641 (define_expand "vec_unpack<US>_hi_<mode>"
5642   [(match_operand:<V_unpack> 0 "register_operand" "")
5643    (SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
5644  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5645   {
5646    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
5647    rtx t1;
5648    int i;
5649    for (i = 0; i < (<V_mode_nunits>/2); i++)
5650      RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
5651   
5652    t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5653    emit_insn (gen_neon_vec_unpack<US>_hi_<mode> (operands[0], 
5654                                                  operands[1], 
5655                                                  t1));
5656    DONE;
5657   }
5660 (define_expand "vec_unpack<US>_lo_<mode>"
5661   [(match_operand:<V_unpack> 0 "register_operand" "")
5662    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))]
5663  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5664   {
5665    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
5666    rtx t1;
5667    int i;
5668    for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5669      RTVEC_ELT (v, i) = GEN_INT (i);
5670    t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5671    emit_insn (gen_neon_vec_unpack<US>_lo_<mode> (operands[0], 
5672                                                  operands[1], 
5673                                                  t1));
5674    DONE;
5675   }
5678 (define_insn "neon_vec_<US>mult_lo_<mode>"
5679  [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5680        (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5681                            (match_operand:VU 1 "register_operand" "w") 
5682                            (match_operand:VU 2 "vect_par_constant_low" "")))
5683                         (SE:<V_unpack> (vec_select:<V_HALF>
5684                            (match_operand:VU 3 "register_operand" "w") 
5685                            (match_dup 2)))))]
5686   "TARGET_NEON && !BYTES_BIG_ENDIAN"
5687   "vmull.<US><V_sz_elem> %q0, %e1, %e3"
5688   [(set_attr "neon_type" "neon_shift_1")]
5691 (define_expand "vec_widen_<US>mult_lo_<mode>"
5692   [(match_operand:<V_unpack> 0 "register_operand" "")
5693    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5694    (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
5695  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5697    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
5698    rtx t1;
5699    int i;
5700    for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5701      RTVEC_ELT (v, i) = GEN_INT (i);
5702    t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5704    emit_insn (gen_neon_vec_<US>mult_lo_<mode> (operands[0],
5705                                                operands[1],
5706                                                t1,
5707                                                operands[2]));
5708    DONE;
5712 (define_insn "neon_vec_<US>mult_hi_<mode>"
5713  [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5714       (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5715                             (match_operand:VU 1 "register_operand" "w") 
5716                             (match_operand:VU 2 "vect_par_constant_high" "")))
5717                        (SE:<V_unpack> (vec_select:<V_HALF>
5718                             (match_operand:VU 3 "register_operand" "w") 
5719                             (match_dup 2)))))]
5720   "TARGET_NEON && !BYTES_BIG_ENDIAN"
5721   "vmull.<US><V_sz_elem> %q0, %f1, %f3"
5722   [(set_attr "neon_type" "neon_shift_1")]
5725 (define_expand "vec_widen_<US>mult_hi_<mode>"
5726   [(match_operand:<V_unpack> 0 "register_operand" "")
5727    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5728    (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
5729  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5731    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
5732    rtx t1;
5733    int i;
5734    for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5735      RTVEC_ELT (v, i) = GEN_INT (<V_mode_nunits>/2 + i);
5736    t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5738    emit_insn (gen_neon_vec_<US>mult_hi_<mode> (operands[0],
5739                                                operands[1],
5740                                                t1,
5741                                                operands[2]));
5742    DONE;
5747 (define_insn "neon_vec_<US>shiftl_<mode>"
5748  [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5749        (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
5750        (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
5751   "TARGET_NEON"
5753   return "vshll.<US><V_sz_elem> %q0, %P1, %2";
5755   [(set_attr "neon_type" "neon_shift_1")]
5758 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5759   [(match_operand:<V_unpack> 0 "register_operand" "")
5760    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5761    (match_operand:SI 2 "immediate_operand" "i")]
5762  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5764   emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5765                 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
5766                 operands[2]));
5767    DONE;
5771 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5772   [(match_operand:<V_unpack> 0 "register_operand" "")
5773    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5774    (match_operand:SI 2 "immediate_operand" "i")]
5775  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5777   emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5778                 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
5779                                      GET_MODE_SIZE (<V_HALF>mode)),
5780                 operands[2]));
5781    DONE;
5785 ;; Vectorize for non-neon-quad case
5786 (define_insn "neon_unpack<US>_<mode>"
5787  [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5788        (SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
5789  "TARGET_NEON"
5790  "vmovl.<US><V_sz_elem> %q0, %P1"
5791   [(set_attr "neon_type" "neon_shift_1")]
5794 (define_expand "vec_unpack<US>_lo_<mode>"
5795  [(match_operand:<V_double_width> 0 "register_operand" "")
5796   (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5797  "TARGET_NEON"
5799   rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5800   emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5801   emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5803   DONE;
5807 (define_expand "vec_unpack<US>_hi_<mode>"
5808  [(match_operand:<V_double_width> 0 "register_operand" "")
5809   (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5810  "TARGET_NEON"
5812   rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5813   emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5814   emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5816   DONE;
5820 (define_insn "neon_vec_<US>mult_<mode>"
5821  [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5822        (mult:<V_widen> (SE:<V_widen> 
5823                            (match_operand:VDI 1 "register_operand" "w"))
5824                        (SE:<V_widen> 
5825                            (match_operand:VDI 2 "register_operand" "w"))))]
5826   "TARGET_NEON"
5827   "vmull.<US><V_sz_elem> %q0, %P1, %P2"
5828   [(set_attr "neon_type" "neon_shift_1")]
5831 (define_expand "vec_widen_<US>mult_hi_<mode>"
5832   [(match_operand:<V_double_width> 0 "register_operand" "")
5833    (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5834    (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5835  "TARGET_NEON"
5837    rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5838    emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5839    emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5840                                             
5841    DONE;
5846 (define_expand "vec_widen_<US>mult_lo_<mode>"
5847   [(match_operand:<V_double_width> 0 "register_operand" "")
5848    (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5849    (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5850  "TARGET_NEON"
5852    rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5853    emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5854    emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5855                                             
5856    DONE;
5861 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5862  [(match_operand:<V_double_width> 0 "register_operand" "")
5863    (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5864    (match_operand:SI 2 "immediate_operand" "i")]
5865  "TARGET_NEON"
5867    rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5868    emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5869    emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5871    DONE;
5875 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5876   [(match_operand:<V_double_width> 0 "register_operand" "")
5877    (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5878    (match_operand:SI 2 "immediate_operand" "i")]
5879  "TARGET_NEON"
5881    rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5882    emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5883    emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5885    DONE;
5889 ; FIXME: These instruction patterns can't be used safely in big-endian mode
5890 ; because the ordering of vector elements in Q registers is different from what
5891 ; the semantics of the instructions require.
5893 (define_insn "vec_pack_trunc_<mode>"
5894  [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
5895        (vec_concat:<V_narrow_pack> 
5896                 (truncate:<V_narrow> 
5897                         (match_operand:VN 1 "register_operand" "w"))
5898                 (truncate:<V_narrow>
5899                         (match_operand:VN 2 "register_operand" "w"))))]
5900  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5901  "vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
5902  [(set_attr "neon_type" "neon_shift_1")
5903   (set_attr "length" "8")]
5906 ;; For the non-quad case.
5907 (define_insn "neon_vec_pack_trunc_<mode>"
5908  [(set (match_operand:<V_narrow> 0 "register_operand" "=w")
5909        (truncate:<V_narrow> (match_operand:VN 1 "register_operand" "w")))]
5910  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5911  "vmovn.i<V_sz_elem>\t%P0, %q1"
5912  [(set_attr "neon_type" "neon_shift_1")]
5915 (define_expand "vec_pack_trunc_<mode>"
5916  [(match_operand:<V_narrow_pack> 0 "register_operand" "")
5917   (match_operand:VSHFT 1 "register_operand" "")
5918   (match_operand:VSHFT 2 "register_operand")]
5919  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5921   rtx tempreg = gen_reg_rtx (<V_DOUBLE>mode);
5922   
5923   emit_insn (gen_move_lo_quad_<V_double> (tempreg, operands[1])); 
5924   emit_insn (gen_move_hi_quad_<V_double> (tempreg, operands[2])); 
5925   emit_insn (gen_neon_vec_pack_trunc_<V_double> (operands[0], tempreg));
5926   DONE;
5929 (define_insn "neon_vabd<mode>_2"
5930  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5931        (abs:VDQ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
5932                            (match_operand:VDQ 2 "s_register_operand" "w"))))]
5933  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5934  "vabd.<V_s_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5935  [(set (attr "neon_type")
5936        (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5937                      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5938                                    (const_string "neon_fp_vadd_ddd_vabs_dd")
5939                                    (const_string "neon_fp_vadd_qqq_vabs_qq"))
5940                      (const_string "neon_int_5")))]
5943 (define_insn "neon_vabd<mode>_3"
5944  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5945        (abs:VDQ (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
5946                              (match_operand:VDQ 2 "s_register_operand" "w")]
5947                  UNSPEC_VSUB)))]
5948  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5949  "vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5950  [(set (attr "neon_type")
5951        (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5952                      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5953                                    (const_string "neon_fp_vadd_ddd_vabs_dd")
5954                                    (const_string "neon_fp_vadd_qqq_vabs_qq"))
5955                      (const_string "neon_int_5")))]
5958 ;; Copy from core-to-neon regs, then extend, not vice-versa
5960 (define_split
5961   [(set (match_operand:DI 0 "s_register_operand" "")
5962         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
5963   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5964   [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
5965    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 32)))]
5966   {
5967     operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
5968   })
5970 (define_split
5971   [(set (match_operand:DI 0 "s_register_operand" "")
5972         (sign_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
5973   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5974   [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
5975    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
5976   {
5977     operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
5978   })
5980 (define_split
5981   [(set (match_operand:DI 0 "s_register_operand" "")
5982         (sign_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
5983   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5984   [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
5985    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
5986   {
5987     operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));
5988   })
5990 (define_split
5991   [(set (match_operand:DI 0 "s_register_operand" "")
5992         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
5993   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5994   [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
5995    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 32)))]
5996   {
5997     operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
5998   })
6000 (define_split
6001   [(set (match_operand:DI 0 "s_register_operand" "")
6002         (zero_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
6003   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
6004   [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
6005    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6006   {
6007     operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
6008   })
6010 (define_split
6011   [(set (match_operand:DI 0 "s_register_operand" "")
6012         (zero_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
6013   "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
6014   [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
6015    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 56)))]
6016   {
6017     operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));
6018   })