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