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