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