1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
5 ;; This file is part of GCC.
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)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Enumerators for unspecs.
22 (define_c_enum "unspec" [
24 UNSPEC_ASHIFT_UNSIGNED
144 UNSPEC_MISALIGNED_ACCESS
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"))
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"))]
160 && (register_operand (operands[0], <MODE>mode)
161 || register_operand (operands[1], <MODE>mode))"
163 if (which_alternative == 2)
166 static char templ[40];
168 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
169 &operands[1], &width);
171 gcc_assert (is_valid != 0);
174 return "vmov.f32\t%P0, %1 @ <mode>";
176 sprintf (templ, "vmov.i%d\t%%P0, %%1 @ <mode>", width);
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
186 switch (which_alternative)
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);
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,*")])
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"))]
209 && (register_operand (operands[0], <MODE>mode)
210 || register_operand (operands[1], <MODE>mode))"
212 if (which_alternative == 2)
215 static char templ[40];
217 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
218 &operands[1], &width);
220 gcc_assert (is_valid != 0);
223 return "vmov.f32\t%q0, %1 @ <mode>";
225 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width);
230 switch (which_alternative)
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);
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,*")])
248 (define_expand "movti"
249 [(set (match_operand:TI 0 "nonimmediate_operand" "")
250 (match_operand:TI 1 "general_operand" ""))]
253 if (can_create_pseudo_p ())
255 if (GET_CODE (operands[0]) != REG)
256 operands[1] = force_reg (TImode, operands[1]);
260 (define_expand "mov<mode>"
261 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
262 (match_operand:VSTRUCT 1 "general_operand" ""))]
265 if (can_create_pseudo_p ())
267 if (GET_CODE (operands[0]) != REG)
268 operands[1] = force_reg (<MODE>mode, operands[1]);
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"))]
276 && (register_operand (operands[0], <MODE>mode)
277 || register_operand (operands[1], <MODE>mode))"
279 switch (which_alternative)
282 case 1: case 2: return output_move_neon (operands);
283 default: gcc_unreachable ();
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)"))])
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))]
296 int rdest = REGNO (operands[0]);
297 int rsrc = REGNO (operands[1]);
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);
305 neon_disambiguate_copy (operands, dest, src, 2);
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))]
315 int rdest = REGNO (operands[0]);
316 int rsrc = REGNO (operands[1]);
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);
324 neon_disambiguate_copy (operands, dest, src, 2);
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))]
335 int rdest = REGNO (operands[0]);
336 int rsrc = REGNO (operands[1]);
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);
346 neon_disambiguate_copy (operands, dest, src, 3);
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))]
358 int rdest = REGNO (operands[0]);
359 int rsrc = REGNO (operands[1]);
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);
371 neon_disambiguate_copy (operands, dest, src, 4);
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"
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]);
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")])
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")])
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")])
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")])
420 (define_insn "vec_set<mode>_internal"
421 [(set (match_operand:VD 0 "s_register_operand" "=w")
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")))]
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);
434 return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
436 [(set_attr "predicable" "yes")
437 (set_attr "neon_type" "neon_mcr")])
439 (define_insn "vec_set<mode>_internal"
440 [(set (match_operand:VQ 0 "s_register_operand" "=w")
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")))]
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]);
454 if (BYTES_BIG_ENDIAN)
455 elt = half_elts - 1 - elt;
457 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
458 operands[2] = GEN_INT (elt);
460 return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
462 [(set_attr "predicable" "yes")
463 (set_attr "neon_type" "neon_mcr")]
466 (define_insn "vec_setv2di_internal"
467 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
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")))]
475 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
476 int regno = REGNO (operands[0]) + 2 * elem;
478 operands[0] = gen_rtx_REG (DImode, regno);
480 return "vmov%?\t%P0, %Q1, %R1";
482 [(set_attr "predicable" "yes")
483 (set_attr "neon_type" "neon_mcr_2_mcrr")]
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" "")]
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]));
498 (define_insn "vec_extract<mode>"
499 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
501 (match_operand:VD 1 "s_register_operand" "w")
502 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
505 if (BYTES_BIG_ENDIAN)
507 int elt = INTVAL (operands[2]);
508 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
509 operands[2] = GEN_INT (elt);
511 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
513 [(set_attr "predicable" "yes")
514 (set_attr "neon_type" "neon_bp_simple")]
517 (define_insn "vec_extract<mode>"
518 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
520 (match_operand:VQ 1 "s_register_operand" "w")
521 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
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]);
529 if (BYTES_BIG_ENDIAN)
530 elt = half_elts - 1 - elt;
532 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
533 operands[2] = GEN_INT (elt);
535 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
537 [(set_attr "predicable" "yes")
538 (set_attr "neon_type" "neon_bp_simple")]
541 (define_insn "vec_extractv2di"
542 [(set (match_operand:DI 0 "s_register_operand" "=r")
544 (match_operand:V2DI 1 "s_register_operand" "w")
545 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
548 int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
550 operands[1] = gen_rtx_REG (DImode, regno);
552 return "vmov%?\t%Q0, %R0, %P1 @ v2di";
554 [(set_attr "predicable" "yes")
555 (set_attr "neon_type" "neon_int_1")]
558 (define_expand "vec_init<mode>"
559 [(match_operand:VDQ 0 "s_register_operand" "")
560 (match_operand 1 "" "")]
563 neon_expand_vector_init (operands[0], operands[1]);
567 ;; Doubleword and quadword arithmetic.
569 ;; NOTE: some other instructions also support 64-bit integer
570 ;; element size, which we could potentially use for "long long" operations.
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")))]
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))]
593 switch (which_alternative)
595 case 0: /* fall through */
596 case 3: return "vadd.i64\t%P0, %P1, %P2";
599 default: gcc_unreachable ();
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")]
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")))]
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))]
629 switch (which_alternative)
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 ();
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")]
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>")
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")))))]
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>")
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")))))]
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>")
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")))))]
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")))]
716 switch (which_alternative)
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 ();
724 [(set_attr "neon_type" "neon_int_1")]
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")))]
733 switch (which_alternative)
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));
742 default: gcc_unreachable ();
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")]
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.
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")))]
761 switch (which_alternative)
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 ();
769 [(set_attr "neon_type" "neon_int_1")]
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")))]
778 switch (which_alternative)
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));
787 default: gcc_unreachable ();
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")]
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")))]
800 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
801 [(set_attr "neon_type" "neon_int_1")]
804 ;; TODO: investigate whether we should disable
805 ;; this and bicdi3_neon for the A8 in line with the other
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")))]
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)))]
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]);
834 emit_insn (gen_one_cmpldi2 (operands[0], operands[2]));
835 emit_insn (gen_iordi3 (operands[0], operands[1], operands[0]));
839 [(set_attr "neon_type" "neon_int_1,*,*,*")
840 (set_attr "length" "*,16,8,8")
841 (set_attr "arch" "any,a,t2,t2")]
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")))]
849 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
850 [(set_attr "neon_type" "neon_int_1")]
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")))]
863 [(set_attr "neon_type" "neon_int_1,*,*")
864 (set_attr "length" "*,8,8")]
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")))]
872 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
873 [(set_attr "neon_type" "neon_int_1")]
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")))]
886 [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
887 (set_attr "length" "*,8,8,*")
888 (set_attr "arch" "nota8,*,*,onlya8")]
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")))]
895 "vmvn\t%<V_reg>0, %<V_reg>1"
896 [(set_attr "neon_type" "neon_int_1")]
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")))]
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")))]
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")))]
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")))]
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")))]
930 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
931 [(set_attr "neon_type" "neon_int_5")]
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")))]
939 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
940 [(set_attr "neon_type" "neon_int_5")]
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")))]
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")))]
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")))]
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")))]
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
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")))]
977 switch (which_alternative)
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],
982 VALID_NEON_QREG_MODE (<MODE>mode),
984 default: gcc_unreachable ();
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")))]
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")))]
999 return neon_output_shift_immediate ("vshr", 's', &operands[2],
1000 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
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")))]
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")))]
1015 return neon_output_shift_immediate ("vshr", 'u', &operands[2],
1016 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
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")))]
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
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))]
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")))]
1043 ; Used for implementing logical shift-right, which is a left-shift by a negative
1044 ; amount, with unsigned operands.
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))]
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")))]
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" "")))]
1065 rtx neg = gen_reg_rtx (<MODE>mode);
1066 if (REG_P (operands[2]))
1068 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1069 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1072 emit_insn (gen_vashr<mode>3_imm (operands[0], operands[1], operands[2]));
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" "")))]
1082 rtx neg = gen_reg_rtx (<MODE>mode);
1083 if (REG_P (operands[2]))
1085 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1086 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1089 emit_insn (gen_vlshr<mode>3_imm (operands[0], operands[1], operands[2]));
1093 ;; Widening operations
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")))]
1101 "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1102 [(set_attr "neon_type" "neon_int_3")]
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")))]
1111 "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1112 [(set_attr "neon_type" "neon_int_3")]
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
1119 ;; Note that it's not safe to perform such an operation in big-endian mode,
1120 ;; due to element-ordering issues.
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"
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;
1135 if (num_bits == width)
1137 emit_move_insn (operands[0], operands[1]);
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]);
1145 emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1146 GEN_INT (num_bits / BITS_PER_UNIT)));
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"
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;
1165 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1169 num_bits = width - num_bits;
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]);
1175 emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1176 GEN_INT (num_bits / BITS_PER_UNIT)));
1180 ;; Helpers for quad-word reduction operations
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.
1186 (define_insn "quad_halves_<code>v4si"
1187 [(set (match_operand:V2SI 0 "s_register_operand" "=w")
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)]))))]
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")))]
1201 (define_insn "quad_halves_<code>v4sf"
1202 [(set (match_operand:V2SF 0 "s_register_operand" "=w")
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")))]
1216 (define_insn "quad_halves_<code>v8hi"
1217 [(set (match_operand:V4HI 0 "s_register_operand" "+w")
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)]))))]
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")))]
1233 (define_insn "quad_halves_<code>v16qi"
1234 [(set (match_operand:V8QI 0 "s_register_operand" "+w")
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)]))))]
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")))]
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.
1258 (define_insn "neon_move_lo_quad_<mode>"
1259 [(set (match_operand:ANY128 0 "s_register_operand" "+w")
1261 (match_operand:<V_HALF> 1 "s_register_operand" "w")
1262 (vec_select:<V_HALF>
1264 (match_operand:ANY128 2 "vect_par_constant_high" ""))))]
1267 int dest = REGNO (operands[0]);
1268 int src = REGNO (operands[1]);
1271 return "vmov\t%e0, %P1";
1275 [(set_attr "neon_type" "neon_bp_simple")]
1278 (define_insn "neon_move_hi_quad_<mode>"
1279 [(set (match_operand:ANY128 0 "s_register_operand" "+w")
1281 (vec_select:<V_HALF>
1283 (match_operand:ANY128 2 "vect_par_constant_low" ""))
1284 (match_operand:<V_HALF> 1 "s_register_operand" "w")))]
1288 int dest = REGNO (operands[0]);
1289 int src = REGNO (operands[1]);
1292 return "vmov\t%f0, %P1";
1296 [(set_attr "neon_type" "neon_bp_simple")]
1299 (define_expand "move_hi_quad_<mode>"
1300 [(match_operand:ANY128 0 "s_register_operand" "")
1301 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1304 rtvec v = rtvec_alloc (<V_mode_nunits>/2);
1308 for (i=0; i < (<V_mode_nunits>/2); i++)
1309 RTVEC_ELT (v, i) = GEN_INT (i);
1311 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
1312 emit_insn (gen_neon_move_hi_quad_<mode> (operands[0], operands[1], t1));
1317 (define_expand "move_lo_quad_<mode>"
1318 [(match_operand:ANY128 0 "s_register_operand" "")
1319 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1322 rtvec v = rtvec_alloc (<V_mode_nunits>/2);
1326 for (i=0; i < (<V_mode_nunits>/2); i++)
1327 RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
1329 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
1330 emit_insn (gen_neon_move_lo_quad_<mode> (operands[0], operands[1], t1));
1335 ;; Reduction operations
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)"
1342 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1343 &gen_neon_vpadd_internal<mode>);
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"
1353 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1354 rtx res_d = gen_reg_rtx (<V_HALF>mode);
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));
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")]
1367 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1368 "vadd.i64\t%e0, %e1, %f1"
1369 [(set_attr "neon_type" "neon_int_1")]
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)"
1379 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
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)"
1388 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1389 &gen_neon_vpsmin<mode>);
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"
1399 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1400 rtx res_d = gen_reg_rtx (<V_HALF>mode);
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));
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)"
1414 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1415 &gen_neon_vpsmax<mode>);
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"
1425 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1426 rtx res_d = gen_reg_rtx (<V_HALF>mode);
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));
1435 (define_expand "reduc_umin_<mode>"
1436 [(match_operand:VDI 0 "s_register_operand" "")
1437 (match_operand:VDI 1 "s_register_operand" "")]
1440 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1441 &gen_neon_vpumin<mode>);
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"
1450 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1451 rtx res_d = gen_reg_rtx (<V_HALF>mode);
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));
1460 (define_expand "reduc_umax_<mode>"
1461 [(match_operand:VDI 0 "s_register_operand" "")
1462 (match_operand:VDI 1 "s_register_operand" "")]
1465 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1466 &gen_neon_vpumax<mode>);
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"
1475 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1476 rtx res_d = gen_reg_rtx (<V_HALF>mode);
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));
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
1535 "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1536 ;; Assume this schedules like umin.
1537 [(set_attr "neon_type" "neon_int_5")]
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")]
1546 "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1547 ;; Assume this schedules like umax.
1548 [(set_attr "neon_type" "neon_int_5")]
1551 ;; Saturating arithmetic
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
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")))]
1564 "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1565 [(set_attr "neon_type" "neon_int_4")]
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")))]
1573 "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1574 [(set_attr "neon_type" "neon_int_4")]
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")))]
1582 "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1583 [(set_attr "neon_type" "neon_int_5")]
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")))]
1591 "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1592 [(set_attr "neon_type" "neon_int_5")]
1595 ;; Conditional instructions. These are comparisons with conditional moves for
1596 ;; vectors. They perform the assignment:
1598 ;; Vop0 = (Vop4 <op3> Vop5) ? Vop1 : Vop2;
1600 ;; where op3 is <, <=, ==, !=, >= or >. Operations are performed
1603 (define_expand "vcond<mode><mode>"
1604 [(set (match_operand:VDQW 0 "s_register_operand" "")
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)"
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)
1619 rtx magic_rtx = GEN_INT (magic_word);
1621 mask = gen_reg_rtx (<V_cmp_result>mode);
1623 if (operands[5] == CONST0_RTX (<MODE>mode))
1625 else if (!REG_P (operands[5]))
1626 operands[5] = force_reg (<MODE>mode, operands[5]);
1628 switch (GET_CODE (operands[3]))
1631 emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1636 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1641 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1647 emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1650 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1656 emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1659 emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1664 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1674 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1677 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1683 (define_expand "vcondu<mode><mode>"
1684 [(set (match_operand:VDQIW 0 "s_register_operand" "")
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" "")))]
1694 int inverse = 0, immediate_zero = 0;
1696 mask = gen_reg_rtx (<V_cmp_result>mode);
1698 if (operands[5] == CONST0_RTX (<MODE>mode))
1700 else if (!REG_P (operands[5]))
1701 operands[5] = force_reg (<MODE>mode, operands[5]);
1703 switch (GET_CODE (operands[3]))
1706 emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1711 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1716 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1722 emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1725 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1731 emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1734 emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1739 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1749 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1752 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1758 ;; Patterns for builtins.
1760 ; good for plain vadd, vaddq.
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")]
1769 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1770 emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2]));
1772 emit_insn (gen_neon_vadd<mode>_unspec (operands[0], operands[1],
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).
1787 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
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")]
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")))]
1804 ; operand 3 represents in bits:
1805 ; bit 0: signed (vs unsigned).
1806 ; bit 1: rounding (vs none).
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")]
1815 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1816 [(set_attr "neon_type" "neon_int_3")]
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")]
1826 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1827 [(set_attr "neon_type" "neon_int_2")]
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")]
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")]
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")]
1850 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1851 [(set_attr "neon_type" "neon_int_4")]
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")]
1861 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1862 [(set_attr "neon_type" "neon_int_4")]
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")]
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>")
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")))))]
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")]
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]));
1902 emit_insn (gen_neon_vmla<mode>_unspec (operands[0], operands[1],
1903 operands[2], operands[3]));
1907 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
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")]
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>")
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")))))]
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")]
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")))]
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")]
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]));
1959 emit_insn (gen_neon_vmls<mode>_unspec (operands[0], operands[1],
1960 operands[2], operands[3]));
1964 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
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")]
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>")
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"))
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")))))]
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")]
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")))]
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")]
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"))))]
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
2088 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2089 emit_insn (gen_sub<mode>3 (operands[0], operands[1], operands[2]));
2091 emit_insn (gen_neon_vsub<mode>_unspec (operands[0], operands[1],
2096 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
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")]
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")))]
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")]
2120 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2121 [(set_attr "neon_type" "neon_int_2")]
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")]
2131 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
2132 [(set_attr "neon_type" "neon_int_2")]
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")]
2142 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2143 [(set_attr "neon_type" "neon_int_5")]
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")]
2153 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2154 [(set_attr "neon_type" "neon_int_5")]
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")]
2164 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2165 [(set_attr "neon_type" "neon_int_4")]
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")]
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")))]
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")]
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")))]
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")]
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")))]
2225 ;; VCLE and VCLT only support comparisons with immediate zero (register
2226 ;; variants are VCGE and VCGT with operands reversed).
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
2297 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2298 [(set_attr "neon_type" "neon_int_4")]
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")]
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")))]
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")]
2324 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2325 [(set_attr "neon_type" "neon_int_5")]
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")]
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")))]
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")]
2350 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2351 [(set_attr "neon_type" "neon_vaba")]
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")]
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")))]
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")]
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")))]
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")]
2393 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
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")]
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")]
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")]
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")]
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")]
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")))]
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")]
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")))]
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")]
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")))]
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")]
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")))]
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" "")]
2485 emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
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")]
2495 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2496 [(set_attr "neon_type" "neon_vqneg_vqabs")]
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" "")]
2505 emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
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")]
2515 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2516 [(set_attr "neon_type" "neon_vqneg_vqabs")]
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")]
2525 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2526 [(set_attr "neon_type" "neon_int_1")]
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")))]
2533 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2534 [(set_attr "neon_type" "neon_int_1")]
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" "")]
2543 emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
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")))]
2551 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2552 [(set_attr "neon_type" "neon_int_1")]
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")]
2561 emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
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")]
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")))]
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")]
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")))]
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" "")]
2597 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2601 (define_insn "neon_vget_lane<mode>_sext_internal"
2602 [(set (match_operand:SI 0 "s_register_operand" "=r")
2604 (vec_select:<V_elem>
2605 (match_operand:VD 1 "s_register_operand" "w")
2606 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2609 if (BYTES_BIG_ENDIAN)
2611 int elt = INTVAL (operands[2]);
2612 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2613 operands[2] = GEN_INT (elt);
2615 return "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]";
2617 [(set_attr "predicable" "yes")
2618 (set_attr "neon_type" "neon_bp_simple")]
2621 (define_insn "neon_vget_lane<mode>_zext_internal"
2622 [(set (match_operand:SI 0 "s_register_operand" "=r")
2624 (vec_select:<V_elem>
2625 (match_operand:VD 1 "s_register_operand" "w")
2626 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2629 if (BYTES_BIG_ENDIAN)
2631 int elt = INTVAL (operands[2]);
2632 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2633 operands[2] = GEN_INT (elt);
2635 return "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]";
2637 [(set_attr "predicable" "yes")
2638 (set_attr "neon_type" "neon_bp_simple")]
2641 (define_insn "neon_vget_lane<mode>_sext_internal"
2642 [(set (match_operand:SI 0 "s_register_operand" "=r")
2644 (vec_select:<V_elem>
2645 (match_operand:VQ 1 "s_register_operand" "w")
2646 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
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;
2655 if (BYTES_BIG_ENDIAN)
2656 elt_adj = halfelts - 1 - elt_adj;
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);
2665 [(set_attr "predicable" "yes")
2666 (set_attr "neon_type" "neon_bp_simple")]
2669 (define_insn "neon_vget_lane<mode>_zext_internal"
2670 [(set (match_operand:SI 0 "s_register_operand" "=r")
2672 (vec_select:<V_elem>
2673 (match_operand:VQ 1 "s_register_operand" "w")
2674 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
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;
2683 if (BYTES_BIG_ENDIAN)
2684 elt_adj = halfelts - 1 - elt_adj;
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);
2693 [(set_attr "predicable" "yes")
2694 (set_attr "neon_type" "neon_bp_simple")]
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" "")]
2704 HOST_WIDE_INT magic = INTVAL (operands[3]);
2707 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2709 if (BYTES_BIG_ENDIAN)
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
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);
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]);
2727 if ((magic & 1) != 0)
2728 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2731 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2738 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
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")]
2748 neon_lane_bounds (operands[2], 0, 1);
2749 emit_move_insn (operands[0], operands[1]);
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")]
2760 neon_lane_bounds (operands[2], 0, 2);
2761 emit_insn (gen_vec_extractv2di (operands[0], operands[1], operands[2]));
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")]
2772 unsigned int elt = INTVAL (operands[3]);
2773 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2775 if (BYTES_BIG_ENDIAN)
2777 unsigned int reg_nelts
2778 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2779 elt ^= reg_nelts - 1;
2782 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
2783 GEN_INT (1 << elt), operands[2]));
2787 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
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")]
2796 neon_lane_bounds (operands[3], 0, 1);
2797 emit_move_insn (operands[0], operands[1]);
2801 (define_expand "neon_vcreate<mode>"
2802 [(match_operand:VDX 0 "s_register_operand" "")
2803 (match_operand:DI 1 "general_operand" "")]
2806 rtx src = gen_lowpart (<MODE>mode, operands[1]);
2807 emit_move_insn (operands[0], src);
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")))]
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")]
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")))]
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")]
2833 (define_expand "neon_vdup_ndi"
2834 [(match_operand:DI 0 "s_register_operand" "=w")
2835 (match_operand:DI 1 "s_register_operand" "r")]
2838 emit_move_insn (operands[0], operands[1]);
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")))]
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")]
2855 (define_insn "neon_vdup_lane<mode>_internal"
2856 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
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")]))))]
2863 if (BYTES_BIG_ENDIAN)
2865 int elt = INTVAL (operands[2]);
2866 elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt;
2867 operands[2] = GEN_INT (elt);
2870 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
2872 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
2874 ;; Assume this schedules like vmov.
2875 [(set_attr "neon_type" "neon_bp_simple")]
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")]
2884 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
2885 if (BYTES_BIG_ENDIAN)
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);
2893 emit_insn (gen_neon_vdup_lane<mode>_internal (operands[0], operands[1],
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")]
2905 neon_lane_bounds (operands[2], 0, 1);
2906 emit_move_insn (operands[0], operands[1]);
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")]
2917 neon_lane_bounds (operands[2], 0, 1);
2918 emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
2922 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
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.
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")))]
2935 int dest = REGNO (operands[0]);
2936 int src1 = REGNO (operands[1]);
2937 int src2 = REGNO (operands[2]);
2940 if (src1 == dest && src2 == dest + 2)
2942 else if (src2 == dest && src1 == dest + 2)
2943 /* Special case of reversed high/low parts. */
2944 return "vswp\t%P1, %P2";
2946 destlo = gen_rtx_REG (<MODE>mode, dest);
2948 if (!reg_overlap_mentioned_p (operands[2], destlo))
2950 /* Try to avoid unnecessary moves if part of the result is in the right
2953 output_asm_insn ("vmov\t%e0, %P1", operands);
2954 if (src2 != dest + 2)
2955 output_asm_insn ("vmov\t%f0, %P2", operands);
2959 if (src2 != dest + 2)
2960 output_asm_insn ("vmov\t%f0, %P2", operands);
2962 output_asm_insn ("vmov\t%e0, %P1", operands);
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")]
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)])))]
2981 int dest = REGNO (operands[0]);
2982 int src = REGNO (operands[1]);
2984 if (dest != src + 2)
2985 return "vmov\t%P0, %f1";
2989 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
2999 int dest = REGNO (operands[0]);
3000 int src = REGNO (operands[1]);
3002 if (dest != src + 2)
3003 return "vmov\t%P0, %f1";
3007 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3016 int dest = REGNO (operands[0]);
3017 int src = REGNO (operands[1]);
3019 if (dest != src + 2)
3020 return "vmov\t%P0, %f1";
3024 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3033 int dest = REGNO (operands[0]);
3034 int src = REGNO (operands[1]);
3036 if (dest != src + 2)
3037 return "vmov\t%P0, %f1";
3041 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3050 int dest = REGNO (operands[0]);
3051 int src = REGNO (operands[1]);
3053 if (dest != src + 2)
3054 return "vmov\t%P0, %f1";
3058 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3070 int dest = REGNO (operands[0]);
3071 int src = REGNO (operands[1]);
3074 return "vmov\t%P0, %e1";
3078 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3088 int dest = REGNO (operands[0]);
3089 int src = REGNO (operands[1]);
3092 return "vmov\t%P0, %e1";
3096 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3105 int dest = REGNO (operands[0]);
3106 int src = REGNO (operands[1]);
3109 return "vmov\t%P0, %e1";
3113 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3122 int dest = REGNO (operands[0]);
3123 int src = REGNO (operands[1]);
3126 return "vmov\t%P0, %e1";
3130 [(set_attr "neon_type" "neon_bp_simple")]
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)])))]
3139 int dest = REGNO (operands[0]);
3140 int src = REGNO (operands[1]);
3143 return "vmov\t%P0, %e1";
3147 [(set_attr "neon_type" "neon_bp_simple")]
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")]
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")))]
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")]
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")))]
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")]
3184 neon_const_bounds (operands[2], 1, 33);
3185 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
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")))]
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")]
3201 neon_const_bounds (operands[2], 1, 33);
3202 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
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")))]
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")]
3216 "vmovn.<V_if_elem>\t%P0, %q1"
3217 [(set_attr "neon_type" "neon_bp_simple")]
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")]
3226 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
3227 [(set_attr "neon_type" "neon_shift_2")]
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")]
3236 "vqmovun.<V_s_elem>\t%P0, %q1"
3237 [(set_attr "neon_type" "neon_shift_2")]
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")]
3246 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
3247 [(set_attr "neon_type" "neon_shift_1")]
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")]
3260 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3261 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
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"))))]
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")]
3281 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
3282 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
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"))))]
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))]
3302 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3303 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
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")))]
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))]
3321 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3322 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
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")))]
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))]
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]";
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")))]
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))]
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]";
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")))]
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")]
3379 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3380 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
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"))))]
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")]
3401 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3402 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
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"))))]
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))]
3423 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3424 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
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")))]
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))]
3443 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3444 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
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")))]
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")]
3463 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3464 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
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"))))]
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")]
3485 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3486 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
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"))))]
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))]
3507 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3508 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
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")))]
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))]
3527 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3528 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
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")))]
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.
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" "")]
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));
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" "")]
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));
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" "")]
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]));
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" "")]
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));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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" "")]
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]));
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")]
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";
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")))]
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")]
3770 "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3771 [(set_attr "neon_type" "neon_bp_simple")]
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")]
3780 "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3781 [(set_attr "neon_type" "neon_bp_simple")]
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")]
3790 "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3791 [(set_attr "neon_type" "neon_bp_simple")]
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)
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")]
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")]
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" "")]
3824 /* We can't alias operands together if they have different modes. */
3825 operands[1] = gen_lowpart (<MODE>mode, operands[1]);
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")]
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")))]
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")]
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")))]
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")]
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";
3867 [(set_attr "neon_type" "neon_shift_1")]
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")]
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";
3881 [(set_attr "neon_type" "neon_shift_1")]
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")]
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";
3895 [(set_attr "neon_type" "neon_shift_2")]
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")]
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";
3909 [(set_attr "neon_type" "neon_shift_2")]
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")]
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";
3923 [(set_attr "neon_type" "neon_shift_1")]
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")]
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";
3937 [(set_attr "neon_type" "neon_shift_2")]
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")]
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";
3951 [(set_attr "neon_type" "neon_shift_2")]
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")]
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";
3966 [(set_attr "neon_type" "neon_shift_1")]
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")]
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";
3981 [(set_attr "neon_type" "neon_vsra_vrsra")]
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")]
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";
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")))]
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")]
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";
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")))]
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")]
4024 "vtbl.8\t%P0, {%P1}, %P2"
4025 [(set_attr "neon_type" "neon_bp_2cycle")]
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")]
4036 int tabbase = REGNO (operands[1]);
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);
4046 [(set_attr "neon_type" "neon_bp_2cycle")]
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")]
4057 int tabbase = REGNO (operands[1]);
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);
4068 [(set_attr "neon_type" "neon_bp_3cycle")]
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")]
4079 int tabbase = REGNO (operands[1]);
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);
4091 [(set_attr "neon_type" "neon_bp_3cycle")]
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")]
4101 "vtbx.8\t%P0, {%P2}, %P3"
4102 [(set_attr "neon_type" "neon_bp_2cycle")]
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")]
4114 int tabbase = REGNO (operands[2]);
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);
4124 [(set_attr "neon_type" "neon_bp_2cycle")]
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")]
4136 int tabbase = REGNO (operands[2]);
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);
4147 [(set_attr "neon_type" "neon_bp_3cycle")]
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")]
4159 int tabbase = REGNO (operands[2]);
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);
4171 [(set_attr "neon_type" "neon_bp_3cycle")]
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")]
4179 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4180 (unspec:VDQW [(match_dup 1) (match_dup 2)]
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")))]
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")]
4196 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal,
4197 operands[0], operands[1], operands[2]);
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")]
4206 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4207 (unspec:VDQW [(match_dup 1) (match_dup 2)]
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")))]
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")]
4223 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal,
4224 operands[0], operands[1], operands[2]);
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")]
4233 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4234 (unspec:VDQW [(match_dup 1) (match_dup 2)]
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")))]
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")]
4250 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal,
4251 operands[0], operands[1], operands[2]);
4255 (define_expand "neon_vreinterpretv8qi<mode>"
4256 [(match_operand:V8QI 0 "s_register_operand" "")
4257 (match_operand:VDX 1 "s_register_operand" "")]
4260 neon_reinterpret (operands[0], operands[1]);
4264 (define_expand "neon_vreinterpretv4hi<mode>"
4265 [(match_operand:V4HI 0 "s_register_operand" "")
4266 (match_operand:VDX 1 "s_register_operand" "")]
4269 neon_reinterpret (operands[0], operands[1]);
4273 (define_expand "neon_vreinterpretv2si<mode>"
4274 [(match_operand:V2SI 0 "s_register_operand" "")
4275 (match_operand:VDX 1 "s_register_operand" "")]
4278 neon_reinterpret (operands[0], operands[1]);
4282 (define_expand "neon_vreinterpretv2sf<mode>"
4283 [(match_operand:V2SF 0 "s_register_operand" "")
4284 (match_operand:VDX 1 "s_register_operand" "")]
4287 neon_reinterpret (operands[0], operands[1]);
4291 (define_expand "neon_vreinterpretdi<mode>"
4292 [(match_operand:DI 0 "s_register_operand" "")
4293 (match_operand:VDX 1 "s_register_operand" "")]
4296 neon_reinterpret (operands[0], operands[1]);
4300 (define_expand "neon_vreinterpretv16qi<mode>"
4301 [(match_operand:V16QI 0 "s_register_operand" "")
4302 (match_operand:VQX 1 "s_register_operand" "")]
4305 neon_reinterpret (operands[0], operands[1]);
4309 (define_expand "neon_vreinterpretv8hi<mode>"
4310 [(match_operand:V8HI 0 "s_register_operand" "")
4311 (match_operand:VQX 1 "s_register_operand" "")]
4314 neon_reinterpret (operands[0], operands[1]);
4318 (define_expand "neon_vreinterpretv4si<mode>"
4319 [(match_operand:V4SI 0 "s_register_operand" "")
4320 (match_operand:VQX 1 "s_register_operand" "")]
4323 neon_reinterpret (operands[0], operands[1]);
4327 (define_expand "neon_vreinterpretv4sf<mode>"
4328 [(match_operand:V4SF 0 "s_register_operand" "")
4329 (match_operand:VQX 1 "s_register_operand" "")]
4332 neon_reinterpret (operands[0], operands[1]);
4336 (define_expand "neon_vreinterpretv2di<mode>"
4337 [(match_operand:V2DI 0 "s_register_operand" "")
4338 (match_operand:VQX 1 "s_register_operand" "")]
4341 neon_reinterpret (operands[0], operands[1]);
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")]
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")]
4356 "vld1.<V_sz_elem>\t%h0, %A1"
4357 [(set_attr "neon_type" "neon_vld1_1_2_regs")]
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")]
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");
4373 return "vld1.<V_sz_elem>\t%P0, %A1";
4375 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
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")))]
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")]
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)
4400 operands[3] = GEN_INT (lane);
4402 operands[0] = gen_rtx_REG (<V_HALF>mode, regno);
4404 return "vld1.<V_sz_elem>\t%P0, %A1";
4406 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
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")))]
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")]
4420 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4421 return "vld1.<V_sz_elem>\t{%P0[]}, %A1";
4423 return "vld1.<V_sz_elem>\t%h0, %A1";
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")))]
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")]
4437 if (GET_MODE_NUNITS (<MODE>mode) > 2)
4438 return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4440 return "vld1.<V_sz_elem>\t%h0, %A1";
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")))]
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")]
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")]
4459 "vst1.<V_sz_elem>\t%h1, %A0"
4460 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
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")])))]
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");
4474 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4476 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
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")))])
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")])))]
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)
4499 operands[2] = GEN_INT (lane);
4501 operands[1] = gen_rtx_REG (<V_HALF>mode, regno);
4503 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4505 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4507 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
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)]
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)]
4524 if (<V_sz_elem> == 64)
4525 return "vld1.64\t%h0, %A1";
4527 return "vld2.<V_sz_elem>\t%h0, %A1";
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")))]
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)]
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)]
4548 "vld2.<V_sz_elem>\t%h0, %A1"
4549 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
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)]
4560 HOST_WIDE_INT lane = INTVAL (operands[3]);
4561 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4562 int regno = REGNO (operands[0]);
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);
4573 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
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)]
4585 HOST_WIDE_INT lane = INTVAL (operands[3]);
4586 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4587 int regno = REGNO (operands[0]);
4589 if (lane < 0 || lane >= max)
4590 error ("lane out of range");
4591 else if (lane >= max / 2)
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);
4603 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
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)]
4613 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4614 return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4616 return "vld1.<V_sz_elem>\t%h0, %A1";
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")))]
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)]
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)]
4638 if (<V_sz_elem> == 64)
4639 return "vst1.64\t%h1, %A0";
4641 return "vst2.<V_sz_elem>\t%h1, %A0";
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")))]
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)]
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)]
4662 "vst2.<V_sz_elem>\t%h1, %A0"
4663 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]
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)]
4675 HOST_WIDE_INT lane = INTVAL (operands[2]);
4676 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4677 int regno = REGNO (operands[1]);
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);
4688 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
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)]
4700 HOST_WIDE_INT lane = INTVAL (operands[2]);
4701 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4702 int regno = REGNO (operands[1]);
4704 if (lane < 0 || lane >= max)
4705 error ("lane out of range");
4706 else if (lane >= max / 2)
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);
4718 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
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)]
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)]
4735 if (<V_sz_elem> == 64)
4736 return "vld1.64\t%h0, %A1";
4738 return "vld3.<V_sz_elem>\t%h0, %A1";
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")))]
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)]
4752 emit_insn (gen_neon_vld3<mode> (operands[0], operands[1]));
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)]
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]));
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)]
4778 int regno = REGNO (operands[0]);
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);
4787 [(set_attr "neon_type" "neon_vld3_vld4")]
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)]
4798 int regno = REGNO (operands[0]);
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);
4807 [(set_attr "neon_type" "neon_vld3_vld4")]
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)]
4819 HOST_WIDE_INT lane = INTVAL (operands[3]);
4820 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4821 int regno = REGNO (operands[0]);
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",
4834 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
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)]
4846 HOST_WIDE_INT lane = INTVAL (operands[3]);
4847 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4848 int regno = REGNO (operands[0]);
4850 if (lane < 0 || lane >= max)
4851 error ("lane out of range");
4852 else if (lane >= max / 2)
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",
4866 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
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)]
4876 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4878 int regno = REGNO (operands[0]);
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);
4888 return "vld1.<V_sz_elem>\t%h0, %A1";
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")))])
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)]
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)]
4909 if (<V_sz_elem> == 64)
4910 return "vst1.64\t%h1, %A0";
4912 return "vst3.<V_sz_elem>\t%h1, %A0";
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")))])
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)]
4925 emit_insn (gen_neon_vst3<mode> (operands[0], operands[1]));
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)]
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]));
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)]
4951 int regno = REGNO (operands[1]);
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);
4960 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
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)]
4970 int regno = REGNO (operands[1]);
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);
4979 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
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)]
4991 HOST_WIDE_INT lane = INTVAL (operands[2]);
4992 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4993 int regno = REGNO (operands[1]);
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",
5006 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
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)]
5018 HOST_WIDE_INT lane = INTVAL (operands[2]);
5019 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5020 int regno = REGNO (operands[1]);
5022 if (lane < 0 || lane >= max)
5023 error ("lane out of range");
5024 else if (lane >= max / 2)
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",
5038 [(set_attr "neon_type" "neon_vst3_vst4_lane")])
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)]
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)]
5054 if (<V_sz_elem> == 64)
5055 return "vld1.64\t%h0, %A1";
5057 return "vld4.<V_sz_elem>\t%h0, %A1";
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")))]
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)]
5071 emit_insn (gen_neon_vld4<mode> (operands[0], operands[1]));
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)]
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]));
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)]
5097 int regno = REGNO (operands[0]);
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);
5107 [(set_attr "neon_type" "neon_vld3_vld4")]
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)]
5118 int regno = REGNO (operands[0]);
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);
5128 [(set_attr "neon_type" "neon_vld3_vld4")]
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)]
5140 HOST_WIDE_INT lane = INTVAL (operands[3]);
5141 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5142 int regno = REGNO (operands[0]);
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",
5156 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
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)]
5168 HOST_WIDE_INT lane = INTVAL (operands[3]);
5169 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5170 int regno = REGNO (operands[0]);
5172 if (lane < 0 || lane >= max)
5173 error ("lane out of range");
5174 else if (lane >= max / 2)
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",
5189 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
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)]
5199 if (GET_MODE_NUNITS (<MODE>mode) > 1)
5201 int regno = REGNO (operands[0]);
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",
5213 return "vld1.<V_sz_elem>\t%h0, %A1";
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")))]
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)]
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)]
5235 if (<V_sz_elem> == 64)
5236 return "vst1.64\t%h1, %A0";
5238 return "vst4.<V_sz_elem>\t%h1, %A0";
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")))]
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)]
5252 emit_insn (gen_neon_vst4<mode> (operands[0], operands[1]));
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)]
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]));
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)]
5278 int regno = REGNO (operands[1]);
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);
5288 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
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)]
5298 int regno = REGNO (operands[1]);
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);
5308 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
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)]
5320 HOST_WIDE_INT lane = INTVAL (operands[2]);
5321 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5322 int regno = REGNO (operands[1]);
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",
5336 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
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)]
5348 HOST_WIDE_INT lane = INTVAL (operands[2]);
5349 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5350 int regno = REGNO (operands[1]);
5352 if (lane < 0 || lane >= max)
5353 error ("lane out of range");
5354 else if (lane >= max / 2)
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",
5369 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
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" "")]
5379 emit_insn (gen_and<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
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" "")]
5390 emit_insn (gen_ior<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
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" "")]
5401 emit_insn (gen_xor<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
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" "")]
5412 emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2]));
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" "")]
5423 emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2]));
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")]
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")]
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"
5452 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5455 for (i = 0; i < (<V_mode_nunits>/2); i++)
5456 RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
5458 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5459 emit_insn (gen_neon_vec_unpack<US>_hi_<mode> (operands[0],
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"
5471 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
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],
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")
5492 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5493 "vmull.<US><V_sz_elem> %q0, %e1, %e3"
5494 [(set_attr "neon_type" "neon_shift_1")]
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"
5503 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
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);
5510 emit_insn (gen_neon_vec_<US>mult_lo_<mode> (operands[0],
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")
5526 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5527 "vmull.<US><V_sz_elem> %q0, %f1, %f3"
5528 [(set_attr "neon_type" "neon_shift_1")]
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"
5537 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
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);
5544 emit_insn (gen_neon_vec_<US>mult_hi_<mode> (operands[0],
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")))]
5558 "vmovl.<US><V_sz_elem> %q0, %P1"
5559 [(set_attr "neon_type" "neon_shift_1")]
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"))]
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));
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"))]
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));
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"))
5593 (match_operand:VDI 2 "register_operand" "w"))))]
5595 "vmull.<US><V_sz_elem> %q0, %P1, %P2"
5596 [(set_attr "neon_type" "neon_shift_1")]
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" ""))]
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));
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" ""))]
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));
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.
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")]
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")]
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"
5661 rtx tempreg = gen_reg_rtx (<V_DOUBLE>mode);
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));
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")))]
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")]
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")))]