1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012
3 ;; Free Software Foundation, Inc.
4 ;; Written by CodeSourcery.
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 ;; Enumerators for unspecs.
23 (define_c_enum "unspec" [
25 UNSPEC_ASHIFT_UNSIGNED
148 UNSPEC_MISALIGNED_ACCESS
154 ;; Attribute used to permit string comparisons against <VQH_mnem> in
155 ;; neon_type attribute definitions.
156 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
158 (define_insn "*neon_mov<mode>"
159 [(set (match_operand:VDX 0 "nonimmediate_operand"
160 "=w,Uv,w, w, ?r,?w,?r,?r, ?Us")
161 (match_operand:VDX 1 "general_operand"
162 " w,w, Dn,Uvi, w, r, r, Usi,r"))]
164 && (register_operand (operands[0], <MODE>mode)
165 || register_operand (operands[1], <MODE>mode))"
167 if (which_alternative == 2)
170 static char templ[40];
172 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
173 &operands[1], &width);
175 gcc_assert (is_valid != 0);
178 return "vmov.f32\t%P0, %1 @ <mode>";
180 sprintf (templ, "vmov.i%d\t%%P0, %%x1 @ <mode>", width);
185 /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp
186 below must be changed to output_move_neon (which will use the
187 element/structure loads/stores), and the constraint changed to 'Um' instead
190 switch (which_alternative)
192 case 0: return "vmov\t%P0, %P1 @ <mode>";
193 case 1: case 3: return output_move_vfp (operands);
194 case 2: gcc_unreachable ();
195 case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>";
196 case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>";
197 default: return output_move_double (operands, true, NULL);
200 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
201 (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2")
202 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
203 (set_attr "length" "4,4,4,4,4,4,8,8,8")
204 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
205 (set_attr "neg_pool_range" "*,*,*,1004,*,*,*,1004,*")])
207 (define_insn "*neon_mov<mode>"
208 [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
209 "=w,Un,w, w, ?r,?w,?r,?r, ?Us")
210 (match_operand:VQXMOV 1 "general_operand"
211 " w,w, Dn,Uni, w, r, r, Usi, r"))]
213 && (register_operand (operands[0], <MODE>mode)
214 || register_operand (operands[1], <MODE>mode))"
216 if (which_alternative == 2)
219 static char templ[40];
221 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
222 &operands[1], &width);
224 gcc_assert (is_valid != 0);
227 return "vmov.f32\t%q0, %1 @ <mode>";
229 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width);
234 switch (which_alternative)
236 case 0: return "vmov\t%q0, %q1 @ <mode>";
237 case 1: case 3: return output_move_neon (operands);
238 case 2: gcc_unreachable ();
239 case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1";
240 case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1";
241 default: return output_move_quad (operands);
244 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
245 neon_mrrc,neon_mcr_2_mcrr,*,*,*")
246 (set_attr "type" "*,*,*,*,*,*,alu,load4,store4")
247 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
248 (set_attr "length" "4,8,4,8,8,8,16,8,16")
249 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
250 (set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
252 (define_expand "movti"
253 [(set (match_operand:TI 0 "nonimmediate_operand" "")
254 (match_operand:TI 1 "general_operand" ""))]
257 if (can_create_pseudo_p ())
259 if (GET_CODE (operands[0]) != REG)
260 operands[1] = force_reg (TImode, operands[1]);
264 (define_expand "mov<mode>"
265 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
266 (match_operand:VSTRUCT 1 "general_operand" ""))]
269 if (can_create_pseudo_p ())
271 if (GET_CODE (operands[0]) != REG)
272 operands[1] = force_reg (<MODE>mode, operands[1]);
276 (define_insn "*neon_mov<mode>"
277 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
278 (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))]
280 && (register_operand (operands[0], <MODE>mode)
281 || register_operand (operands[1], <MODE>mode))"
283 switch (which_alternative)
286 case 1: case 2: return output_move_neon (operands);
287 default: gcc_unreachable ();
290 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2")
291 (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
294 [(set (match_operand:EI 0 "s_register_operand" "")
295 (match_operand:EI 1 "s_register_operand" ""))]
296 "TARGET_NEON && reload_completed"
297 [(set (match_dup 0) (match_dup 1))
298 (set (match_dup 2) (match_dup 3))]
300 int rdest = REGNO (operands[0]);
301 int rsrc = REGNO (operands[1]);
304 dest[0] = gen_rtx_REG (TImode, rdest);
305 src[0] = gen_rtx_REG (TImode, rsrc);
306 dest[1] = gen_rtx_REG (DImode, rdest + 4);
307 src[1] = gen_rtx_REG (DImode, rsrc + 4);
309 neon_disambiguate_copy (operands, dest, src, 2);
313 [(set (match_operand:OI 0 "s_register_operand" "")
314 (match_operand:OI 1 "s_register_operand" ""))]
315 "TARGET_NEON && reload_completed"
316 [(set (match_dup 0) (match_dup 1))
317 (set (match_dup 2) (match_dup 3))]
319 int rdest = REGNO (operands[0]);
320 int rsrc = REGNO (operands[1]);
323 dest[0] = gen_rtx_REG (TImode, rdest);
324 src[0] = gen_rtx_REG (TImode, rsrc);
325 dest[1] = gen_rtx_REG (TImode, rdest + 4);
326 src[1] = gen_rtx_REG (TImode, rsrc + 4);
328 neon_disambiguate_copy (operands, dest, src, 2);
332 [(set (match_operand:CI 0 "s_register_operand" "")
333 (match_operand:CI 1 "s_register_operand" ""))]
334 "TARGET_NEON && reload_completed"
335 [(set (match_dup 0) (match_dup 1))
336 (set (match_dup 2) (match_dup 3))
337 (set (match_dup 4) (match_dup 5))]
339 int rdest = REGNO (operands[0]);
340 int rsrc = REGNO (operands[1]);
343 dest[0] = gen_rtx_REG (TImode, rdest);
344 src[0] = gen_rtx_REG (TImode, rsrc);
345 dest[1] = gen_rtx_REG (TImode, rdest + 4);
346 src[1] = gen_rtx_REG (TImode, rsrc + 4);
347 dest[2] = gen_rtx_REG (TImode, rdest + 8);
348 src[2] = gen_rtx_REG (TImode, rsrc + 8);
350 neon_disambiguate_copy (operands, dest, src, 3);
354 [(set (match_operand:XI 0 "s_register_operand" "")
355 (match_operand:XI 1 "s_register_operand" ""))]
356 "TARGET_NEON && reload_completed"
357 [(set (match_dup 0) (match_dup 1))
358 (set (match_dup 2) (match_dup 3))
359 (set (match_dup 4) (match_dup 5))
360 (set (match_dup 6) (match_dup 7))]
362 int rdest = REGNO (operands[0]);
363 int rsrc = REGNO (operands[1]);
366 dest[0] = gen_rtx_REG (TImode, rdest);
367 src[0] = gen_rtx_REG (TImode, rsrc);
368 dest[1] = gen_rtx_REG (TImode, rdest + 4);
369 src[1] = gen_rtx_REG (TImode, rsrc + 4);
370 dest[2] = gen_rtx_REG (TImode, rdest + 8);
371 src[2] = gen_rtx_REG (TImode, rsrc + 8);
372 dest[3] = gen_rtx_REG (TImode, rdest + 12);
373 src[3] = gen_rtx_REG (TImode, rsrc + 12);
375 neon_disambiguate_copy (operands, dest, src, 4);
378 (define_expand "movmisalign<mode>"
379 [(set (match_operand:VDQX 0 "neon_struct_or_register_operand")
380 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_or_register_operand")]
381 UNSPEC_MISALIGNED_ACCESS))]
382 "TARGET_NEON && !BYTES_BIG_ENDIAN"
384 /* This pattern is not permitted to fail during expansion: if both arguments
385 are non-registers (e.g. memory := constant, which can be created by the
386 auto-vectorizer), force operand 1 into a register. */
387 if (!s_register_operand (operands[0], <MODE>mode)
388 && !s_register_operand (operands[1], <MODE>mode))
389 operands[1] = force_reg (<MODE>mode, operands[1]);
392 (define_insn "*movmisalign<mode>_neon_store"
393 [(set (match_operand:VDX 0 "neon_struct_operand" "=Um")
394 (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
395 UNSPEC_MISALIGNED_ACCESS))]
396 "TARGET_NEON && !BYTES_BIG_ENDIAN"
397 "vst1.<V_sz_elem>\t{%P1}, %A0"
398 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
400 (define_insn "*movmisalign<mode>_neon_load"
401 [(set (match_operand:VDX 0 "s_register_operand" "=w")
402 (unspec:VDX [(match_operand:VDX 1 "neon_struct_operand" " Um")]
403 UNSPEC_MISALIGNED_ACCESS))]
404 "TARGET_NEON && !BYTES_BIG_ENDIAN"
405 "vld1.<V_sz_elem>\t{%P0}, %A1"
406 [(set_attr "neon_type" "neon_vld1_1_2_regs")])
408 (define_insn "*movmisalign<mode>_neon_store"
409 [(set (match_operand:VQX 0 "neon_struct_operand" "=Um")
410 (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")]
411 UNSPEC_MISALIGNED_ACCESS))]
412 "TARGET_NEON && !BYTES_BIG_ENDIAN"
413 "vst1.<V_sz_elem>\t{%q1}, %A0"
414 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
416 (define_insn "*movmisalign<mode>_neon_load"
417 [(set (match_operand:VQX 0 "s_register_operand" "=w")
418 (unspec:VQX [(match_operand:VQX 1 "neon_struct_operand" " Um")]
419 UNSPEC_MISALIGNED_ACCESS))]
420 "TARGET_NEON && !BYTES_BIG_ENDIAN"
421 "vld1.<V_sz_elem>\t{%q0}, %A1"
422 [(set_attr "neon_type" "neon_vld1_1_2_regs")])
424 (define_insn "vec_set<mode>_internal"
425 [(set (match_operand:VD 0 "s_register_operand" "=w")
428 (match_operand:<V_elem> 1 "s_register_operand" "r"))
429 (match_operand:VD 3 "s_register_operand" "0")
430 (match_operand:SI 2 "immediate_operand" "i")))]
433 int elt = ffs ((int) INTVAL (operands[2])) - 1;
434 if (BYTES_BIG_ENDIAN)
435 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
436 operands[2] = GEN_INT (elt);
438 return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
440 [(set_attr "predicable" "yes")
441 (set_attr "neon_type" "neon_mcr")])
443 (define_insn "vec_set<mode>_internal"
444 [(set (match_operand:VQ 0 "s_register_operand" "=w")
447 (match_operand:<V_elem> 1 "s_register_operand" "r"))
448 (match_operand:VQ 3 "s_register_operand" "0")
449 (match_operand:SI 2 "immediate_operand" "i")))]
452 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
453 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
454 int elt = elem % half_elts;
455 int hi = (elem / half_elts) * 2;
456 int regno = REGNO (operands[0]);
458 if (BYTES_BIG_ENDIAN)
459 elt = half_elts - 1 - elt;
461 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
462 operands[2] = GEN_INT (elt);
464 return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
466 [(set_attr "predicable" "yes")
467 (set_attr "neon_type" "neon_mcr")]
470 (define_insn "vec_setv2di_internal"
471 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
474 (match_operand:DI 1 "s_register_operand" "r"))
475 (match_operand:V2DI 3 "s_register_operand" "0")
476 (match_operand:SI 2 "immediate_operand" "i")))]
479 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
480 int regno = REGNO (operands[0]) + 2 * elem;
482 operands[0] = gen_rtx_REG (DImode, regno);
484 return "vmov%?\t%P0, %Q1, %R1";
486 [(set_attr "predicable" "yes")
487 (set_attr "neon_type" "neon_mcr_2_mcrr")]
490 (define_expand "vec_set<mode>"
491 [(match_operand:VDQ 0 "s_register_operand" "")
492 (match_operand:<V_elem> 1 "s_register_operand" "")
493 (match_operand:SI 2 "immediate_operand" "")]
496 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
497 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
498 GEN_INT (elem), operands[0]));
502 (define_insn "vec_extract<mode>"
503 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
505 (match_operand:VD 1 "s_register_operand" "w")
506 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
509 if (BYTES_BIG_ENDIAN)
511 int elt = INTVAL (operands[2]);
512 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
513 operands[2] = GEN_INT (elt);
515 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
517 [(set_attr "predicable" "yes")
518 (set_attr "neon_type" "neon_bp_simple")]
521 (define_insn "vec_extract<mode>"
522 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
524 (match_operand:VQ 1 "s_register_operand" "w")
525 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
528 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
529 int elt = INTVAL (operands[2]) % half_elts;
530 int hi = (INTVAL (operands[2]) / half_elts) * 2;
531 int regno = REGNO (operands[1]);
533 if (BYTES_BIG_ENDIAN)
534 elt = half_elts - 1 - elt;
536 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
537 operands[2] = GEN_INT (elt);
539 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
541 [(set_attr "predicable" "yes")
542 (set_attr "neon_type" "neon_bp_simple")]
545 (define_insn "vec_extractv2di"
546 [(set (match_operand:DI 0 "s_register_operand" "=r")
548 (match_operand:V2DI 1 "s_register_operand" "w")
549 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
552 int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
554 operands[1] = gen_rtx_REG (DImode, regno);
556 return "vmov%?\t%Q0, %R0, %P1 @ v2di";
558 [(set_attr "predicable" "yes")
559 (set_attr "neon_type" "neon_int_1")]
562 (define_expand "vec_init<mode>"
563 [(match_operand:VDQ 0 "s_register_operand" "")
564 (match_operand 1 "" "")]
567 neon_expand_vector_init (operands[0], operands[1]);
571 ;; Doubleword and quadword arithmetic.
573 ;; NOTE: some other instructions also support 64-bit integer
574 ;; element size, which we could potentially use for "long long" operations.
576 (define_insn "*add<mode>3_neon"
577 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
578 (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
579 (match_operand:VDQ 2 "s_register_operand" "w")))]
580 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
581 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
582 [(set (attr "neon_type")
583 (if_then_else (match_test "<Is_float_mode>")
584 (if_then_else (match_test "<Is_d_reg>")
585 (const_string "neon_fp_vadd_ddd_vabs_dd")
586 (const_string "neon_fp_vadd_qqq_vabs_qq"))
587 (const_string "neon_int_1")))]
590 (define_insn "adddi3_neon"
591 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w")
592 (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w")
593 (match_operand:DI 2 "s_register_operand" "w,r,0,w")))
594 (clobber (reg:CC CC_REGNUM))]
597 switch (which_alternative)
599 case 0: /* fall through */
600 case 3: return "vadd.i64\t%P0, %P1, %P2";
603 default: gcc_unreachable ();
606 [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
607 (set_attr "conds" "*,clob,clob,*")
608 (set_attr "length" "*,8,8,*")
609 (set_attr "arch" "nota8,*,*,onlya8")]
612 (define_insn "*sub<mode>3_neon"
613 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
614 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
615 (match_operand:VDQ 2 "s_register_operand" "w")))]
616 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
617 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
618 [(set (attr "neon_type")
619 (if_then_else (match_test "<Is_float_mode>")
620 (if_then_else (match_test "<Is_d_reg>")
621 (const_string "neon_fp_vadd_ddd_vabs_dd")
622 (const_string "neon_fp_vadd_qqq_vabs_qq"))
623 (const_string "neon_int_2")))]
626 (define_insn "subdi3_neon"
627 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r,?w")
628 (minus:DI (match_operand:DI 1 "s_register_operand" "w,0,r,0,w")
629 (match_operand:DI 2 "s_register_operand" "w,r,0,0,w")))
630 (clobber (reg:CC CC_REGNUM))]
633 switch (which_alternative)
635 case 0: /* fall through */
636 case 4: return "vsub.i64\t%P0, %P1, %P2";
637 case 1: /* fall through */
638 case 2: /* fall through */
639 case 3: return "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2";
640 default: gcc_unreachable ();
643 [(set_attr "neon_type" "neon_int_2,*,*,*,neon_int_2")
644 (set_attr "conds" "*,clob,clob,clob,*")
645 (set_attr "length" "*,8,8,8,*")
646 (set_attr "arch" "nota8,*,*,*,onlya8")]
649 (define_insn "*mul<mode>3_neon"
650 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
651 (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
652 (match_operand:VDQ 2 "s_register_operand" "w")))]
653 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
654 "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
655 [(set (attr "neon_type")
656 (if_then_else (match_test "<Is_float_mode>")
657 (if_then_else (match_test "<Is_d_reg>")
658 (const_string "neon_fp_vadd_ddd_vabs_dd")
659 (const_string "neon_fp_vadd_qqq_vabs_qq"))
660 (if_then_else (match_test "<Is_d_reg>")
662 (match_test "<Scalar_mul_8_16>")
663 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
664 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
665 (if_then_else (match_test "<Scalar_mul_8_16>")
666 (const_string "neon_mul_qqq_8_16_32_ddd_32")
667 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
670 (define_insn "mul<mode>3add<mode>_neon"
671 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
672 (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
673 (match_operand:VDQ 3 "s_register_operand" "w"))
674 (match_operand:VDQ 1 "s_register_operand" "0")))]
675 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
676 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
677 [(set (attr "neon_type")
678 (if_then_else (match_test "<Is_float_mode>")
679 (if_then_else (match_test "<Is_d_reg>")
680 (const_string "neon_fp_vmla_ddd")
681 (const_string "neon_fp_vmla_qqq"))
682 (if_then_else (match_test "<Is_d_reg>")
684 (match_test "<Scalar_mul_8_16>")
685 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
686 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
687 (if_then_else (match_test "<Scalar_mul_8_16>")
688 (const_string "neon_mla_qqq_8_16")
689 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
692 (define_insn "mul<mode>3neg<mode>add<mode>_neon"
693 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
694 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
695 (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
696 (match_operand:VDQ 3 "s_register_operand" "w"))))]
697 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
698 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
699 [(set (attr "neon_type")
700 (if_then_else (match_test "<Is_float_mode>")
701 (if_then_else (match_test "<Is_d_reg>")
702 (const_string "neon_fp_vmla_ddd")
703 (const_string "neon_fp_vmla_qqq"))
704 (if_then_else (match_test "<Is_d_reg>")
706 (match_test "<Scalar_mul_8_16>")
707 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
708 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
709 (if_then_else (match_test "<Scalar_mul_8_16>")
710 (const_string "neon_mla_qqq_8_16")
711 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
714 (define_insn "ior<mode>3"
715 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
716 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
717 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
720 switch (which_alternative)
722 case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
723 case 1: return neon_output_logic_immediate ("vorr", &operands[2],
724 <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));
725 default: gcc_unreachable ();
728 [(set_attr "neon_type" "neon_int_1")]
731 (define_insn "iordi3_neon"
732 [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r,?w,?w")
733 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r,w,0")
734 (match_operand:DI 2 "neon_logic_op2" "w,Dl,r,r,w,Dl")))]
737 switch (which_alternative)
739 case 0: /* fall through */
740 case 4: return "vorr\t%P0, %P1, %P2";
741 case 1: /* fall through */
742 case 5: return neon_output_logic_immediate ("vorr", &operands[2],
743 DImode, 0, VALID_NEON_QREG_MODE (DImode));
746 default: gcc_unreachable ();
749 [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
750 (set_attr "length" "*,*,8,8,*,*")
751 (set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")]
754 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
755 ;; vorr. We support the pseudo-instruction vand instead, because that
756 ;; corresponds to the canonical form the middle-end expects to use for
757 ;; immediate bitwise-ANDs.
759 (define_insn "and<mode>3"
760 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
761 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
762 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
765 switch (which_alternative)
767 case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
768 case 1: return neon_output_logic_immediate ("vand", &operands[2],
769 <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));
770 default: gcc_unreachable ();
773 [(set_attr "neon_type" "neon_int_1")]
776 (define_insn "anddi3_neon"
777 [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r,?w,?w")
778 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r,w,0")
779 (match_operand:DI 2 "neon_inv_logic_op2" "w,DL,r,r,w,DL")))]
782 switch (which_alternative)
784 case 0: /* fall through */
785 case 4: return "vand\t%P0, %P1, %P2";
786 case 1: /* fall through */
787 case 5: return neon_output_logic_immediate ("vand", &operands[2],
788 DImode, 1, VALID_NEON_QREG_MODE (DImode));
791 default: gcc_unreachable ();
794 [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
795 (set_attr "length" "*,*,8,8,*,*")
796 (set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")]
799 (define_insn "orn<mode>3_neon"
800 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
801 (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
802 (match_operand:VDQ 1 "s_register_operand" "w")))]
804 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
805 [(set_attr "neon_type" "neon_int_1")]
808 ;; TODO: investigate whether we should disable
809 ;; this and bicdi3_neon for the A8 in line with the other
811 (define_insn_and_split "orndi3_neon"
812 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r")
813 (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,0,0,r"))
814 (match_operand:DI 1 "s_register_operand" "w,r,r,0")))]
822 (TARGET_NEON && !(IS_VFP_REGNUM (REGNO (operands[0]))))"
823 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
824 (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
829 operands[3] = gen_highpart (SImode, operands[0]);
830 operands[0] = gen_lowpart (SImode, operands[0]);
831 operands[4] = gen_highpart (SImode, operands[2]);
832 operands[2] = gen_lowpart (SImode, operands[2]);
833 operands[5] = gen_highpart (SImode, operands[1]);
834 operands[1] = gen_lowpart (SImode, operands[1]);
838 emit_insn (gen_one_cmpldi2 (operands[0], operands[2]));
839 emit_insn (gen_iordi3 (operands[0], operands[1], operands[0]));
843 [(set_attr "neon_type" "neon_int_1,*,*,*")
844 (set_attr "length" "*,16,8,8")
845 (set_attr "arch" "any,a,t2,t2")]
848 (define_insn "bic<mode>3_neon"
849 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
850 (and:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
851 (match_operand:VDQ 1 "s_register_operand" "w")))]
853 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
854 [(set_attr "neon_type" "neon_int_1")]
857 ;; Compare to *anddi_notdi_di.
858 (define_insn "bicdi3_neon"
859 [(set (match_operand:DI 0 "s_register_operand" "=w,?=&r,?&r")
860 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
861 (match_operand:DI 1 "s_register_operand" "w,0,r")))]
867 [(set_attr "neon_type" "neon_int_1,*,*")
868 (set_attr "length" "*,8,8")]
871 (define_insn "xor<mode>3"
872 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
873 (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
874 (match_operand:VDQ 2 "s_register_operand" "w")))]
876 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
877 [(set_attr "neon_type" "neon_int_1")]
880 (define_insn "xordi3_neon"
881 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w")
882 (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w")
883 (match_operand:DI 2 "s_register_operand" "w,r,r,w")))]
890 [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
891 (set_attr "length" "*,8,8,*")
892 (set_attr "arch" "nota8,*,*,onlya8")]
895 (define_insn "one_cmpl<mode>2"
896 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
897 (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
899 "vmvn\t%<V_reg>0, %<V_reg>1"
900 [(set_attr "neon_type" "neon_int_1")]
903 (define_insn "abs<mode>2"
904 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
905 (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
907 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
908 [(set (attr "neon_type")
909 (if_then_else (match_test "<Is_float_mode>")
910 (if_then_else (match_test "<Is_d_reg>")
911 (const_string "neon_fp_vadd_ddd_vabs_dd")
912 (const_string "neon_fp_vadd_qqq_vabs_qq"))
913 (const_string "neon_int_3")))]
916 (define_insn "neg<mode>2"
917 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
918 (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
920 "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
921 [(set (attr "neon_type")
922 (if_then_else (match_test "<Is_float_mode>")
923 (if_then_else (match_test "<Is_d_reg>")
924 (const_string "neon_fp_vadd_ddd_vabs_dd")
925 (const_string "neon_fp_vadd_qqq_vabs_qq"))
926 (const_string "neon_int_3")))]
929 (define_insn "negdi2_neon"
930 [(set (match_operand:DI 0 "s_register_operand" "=&w, w,r,&r")
931 (neg:DI (match_operand:DI 1 "s_register_operand" " w, w,0, r")))
932 (clobber (match_scratch:DI 2 "= X,&w,X, X"))
933 (clobber (reg:CC CC_REGNUM))]
936 [(set_attr "length" "8")]
939 ; Split negdi2_neon for vfp registers
941 [(set (match_operand:DI 0 "s_register_operand" "")
942 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
943 (clobber (match_scratch:DI 2 ""))
944 (clobber (reg:CC CC_REGNUM))]
945 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
946 [(set (match_dup 2) (const_int 0))
947 (parallel [(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 1)))
948 (clobber (reg:CC CC_REGNUM))])]
950 if (!REG_P (operands[2]))
951 operands[2] = operands[0];
955 ; Split negdi2_neon for core registers
957 [(set (match_operand:DI 0 "s_register_operand" "")
958 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
959 (clobber (match_scratch:DI 2 ""))
960 (clobber (reg:CC CC_REGNUM))]
961 "TARGET_32BIT && reload_completed
962 && arm_general_register_operand (operands[0], DImode)"
963 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
964 (clobber (reg:CC CC_REGNUM))])]
968 (define_insn "*umin<mode>3_neon"
969 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
970 (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
971 (match_operand:VDQIW 2 "s_register_operand" "w")))]
973 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
974 [(set_attr "neon_type" "neon_int_5")]
977 (define_insn "*umax<mode>3_neon"
978 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
979 (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
980 (match_operand:VDQIW 2 "s_register_operand" "w")))]
982 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
983 [(set_attr "neon_type" "neon_int_5")]
986 (define_insn "*smin<mode>3_neon"
987 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
988 (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
989 (match_operand:VDQW 2 "s_register_operand" "w")))]
991 "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
992 [(set (attr "neon_type")
993 (if_then_else (match_test "<Is_float_mode>")
994 (const_string "neon_fp_vadd_ddd_vabs_dd")
995 (const_string "neon_int_5")))]
998 (define_insn "*smax<mode>3_neon"
999 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1000 (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
1001 (match_operand:VDQW 2 "s_register_operand" "w")))]
1003 "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1004 [(set (attr "neon_type")
1005 (if_then_else (match_test "<Is_float_mode>")
1006 (const_string "neon_fp_vadd_ddd_vabs_dd")
1007 (const_string "neon_int_5")))]
1010 ; TODO: V2DI shifts are current disabled because there are bugs in the
1011 ; generic vectorizer code. It ends up creating a V2DI constructor with
1014 (define_insn "vashl<mode>3"
1015 [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
1016 (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
1017 (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
1020 switch (which_alternative)
1022 case 0: return "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
1023 case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2],
1025 VALID_NEON_QREG_MODE (<MODE>mode),
1027 default: gcc_unreachable ();
1030 [(set (attr "neon_type")
1031 (if_then_else (match_test "<Is_d_reg>")
1032 (const_string "neon_vshl_ddd")
1033 (const_string "neon_shift_3")))]
1036 (define_insn "vashr<mode>3_imm"
1037 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1038 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1039 (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
1042 return neon_output_shift_immediate ("vshr", 's', &operands[2],
1043 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
1046 [(set (attr "neon_type")
1047 (if_then_else (match_test "<Is_d_reg>")
1048 (const_string "neon_vshl_ddd")
1049 (const_string "neon_shift_3")))]
1052 (define_insn "vlshr<mode>3_imm"
1053 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1054 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1055 (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
1058 return neon_output_shift_immediate ("vshr", 'u', &operands[2],
1059 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
1062 [(set (attr "neon_type")
1063 (if_then_else (match_test "<Is_d_reg>")
1064 (const_string "neon_vshl_ddd")
1065 (const_string "neon_shift_3")))]
1068 ; Used for implementing logical shift-right, which is a left-shift by a negative
1069 ; amount, with signed operands. This is essentially the same as ashl<mode>3
1070 ; above, but using an unspec in case GCC tries anything tricky with negative
1073 (define_insn "ashl<mode>3_signed"
1074 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1075 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1076 (match_operand:VDQI 2 "s_register_operand" "w")]
1077 UNSPEC_ASHIFT_SIGNED))]
1079 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1080 [(set (attr "neon_type")
1081 (if_then_else (match_test "<Is_d_reg>")
1082 (const_string "neon_vshl_ddd")
1083 (const_string "neon_shift_3")))]
1086 ; Used for implementing logical shift-right, which is a left-shift by a negative
1087 ; amount, with unsigned operands.
1089 (define_insn "ashl<mode>3_unsigned"
1090 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1091 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1092 (match_operand:VDQI 2 "s_register_operand" "w")]
1093 UNSPEC_ASHIFT_UNSIGNED))]
1095 "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1096 [(set (attr "neon_type")
1097 (if_then_else (match_test "<Is_d_reg>")
1098 (const_string "neon_vshl_ddd")
1099 (const_string "neon_shift_3")))]
1102 (define_expand "vashr<mode>3"
1103 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1104 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1105 (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1108 if (s_register_operand (operands[2], <MODE>mode))
1110 rtx neg = gen_reg_rtx (<MODE>mode);
1111 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1112 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1115 emit_insn (gen_vashr<mode>3_imm (operands[0], operands[1], operands[2]));
1119 (define_expand "vlshr<mode>3"
1120 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1121 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1122 (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1125 if (s_register_operand (operands[2], <MODE>mode))
1127 rtx neg = gen_reg_rtx (<MODE>mode);
1128 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1129 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1132 emit_insn (gen_vlshr<mode>3_imm (operands[0], operands[1], operands[2]));
1136 ;; Widening operations
1138 (define_insn "widen_ssum<mode>3"
1139 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1140 (plus:<V_widen> (sign_extend:<V_widen>
1141 (match_operand:VW 1 "s_register_operand" "%w"))
1142 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1144 "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1145 [(set_attr "neon_type" "neon_int_3")]
1148 (define_insn "widen_usum<mode>3"
1149 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1150 (plus:<V_widen> (zero_extend:<V_widen>
1151 (match_operand:VW 1 "s_register_operand" "%w"))
1152 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1154 "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1155 [(set_attr "neon_type" "neon_int_3")]
1158 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1159 ;; shift-count granularity. That's good enough for the middle-end's current
1162 ;; Note that it's not safe to perform such an operation in big-endian mode,
1163 ;; due to element-ordering issues.
1165 (define_expand "vec_shr_<mode>"
1166 [(match_operand:VDQ 0 "s_register_operand" "")
1167 (match_operand:VDQ 1 "s_register_operand" "")
1168 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1169 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1172 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1173 const int width = GET_MODE_BITSIZE (<MODE>mode);
1174 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1175 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1176 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1178 if (num_bits == width)
1180 emit_move_insn (operands[0], operands[1]);
1184 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1185 operands[0] = gen_lowpart (bvecmode, operands[0]);
1186 operands[1] = gen_lowpart (bvecmode, operands[1]);
1188 emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1189 GEN_INT (num_bits / BITS_PER_UNIT)));
1193 (define_expand "vec_shl_<mode>"
1194 [(match_operand:VDQ 0 "s_register_operand" "")
1195 (match_operand:VDQ 1 "s_register_operand" "")
1196 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1197 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1200 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1201 const int width = GET_MODE_BITSIZE (<MODE>mode);
1202 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1203 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1204 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1208 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1212 num_bits = width - num_bits;
1214 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1215 operands[0] = gen_lowpart (bvecmode, operands[0]);
1216 operands[1] = gen_lowpart (bvecmode, operands[1]);
1218 emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1219 GEN_INT (num_bits / BITS_PER_UNIT)));
1223 ;; Helpers for quad-word reduction operations
1225 ; Add (or smin, smax...) the low N/2 elements of the N-element vector
1226 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1227 ; N/2-element vector.
1229 (define_insn "quad_halves_<code>v4si"
1230 [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1232 (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1233 (parallel [(const_int 0) (const_int 1)]))
1234 (vec_select:V2SI (match_dup 1)
1235 (parallel [(const_int 2) (const_int 3)]))))]
1237 "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
1238 [(set_attr "vqh_mnem" "<VQH_mnem>")
1239 (set (attr "neon_type")
1240 (if_then_else (eq_attr "vqh_mnem" "vadd")
1241 (const_string "neon_int_1") (const_string "neon_int_5")))]
1244 (define_insn "quad_halves_<code>v4sf"
1245 [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1247 (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1248 (parallel [(const_int 0) (const_int 1)]))
1249 (vec_select:V2SF (match_dup 1)
1250 (parallel [(const_int 2) (const_int 3)]))))]
1251 "TARGET_NEON && flag_unsafe_math_optimizations"
1252 "<VQH_mnem>.f32\t%P0, %e1, %f1"
1253 [(set_attr "vqh_mnem" "<VQH_mnem>")
1254 (set (attr "neon_type")
1255 (if_then_else (eq_attr "vqh_mnem" "vadd")
1256 (const_string "neon_int_1") (const_string "neon_int_5")))]
1259 (define_insn "quad_halves_<code>v8hi"
1260 [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1262 (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1263 (parallel [(const_int 0) (const_int 1)
1264 (const_int 2) (const_int 3)]))
1265 (vec_select:V4HI (match_dup 1)
1266 (parallel [(const_int 4) (const_int 5)
1267 (const_int 6) (const_int 7)]))))]
1269 "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
1270 [(set_attr "vqh_mnem" "<VQH_mnem>")
1271 (set (attr "neon_type")
1272 (if_then_else (eq_attr "vqh_mnem" "vadd")
1273 (const_string "neon_int_1") (const_string "neon_int_5")))]
1276 (define_insn "quad_halves_<code>v16qi"
1277 [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1279 (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1280 (parallel [(const_int 0) (const_int 1)
1281 (const_int 2) (const_int 3)
1282 (const_int 4) (const_int 5)
1283 (const_int 6) (const_int 7)]))
1284 (vec_select:V8QI (match_dup 1)
1285 (parallel [(const_int 8) (const_int 9)
1286 (const_int 10) (const_int 11)
1287 (const_int 12) (const_int 13)
1288 (const_int 14) (const_int 15)]))))]
1290 "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
1291 [(set_attr "vqh_mnem" "<VQH_mnem>")
1292 (set (attr "neon_type")
1293 (if_then_else (eq_attr "vqh_mnem" "vadd")
1294 (const_string "neon_int_1") (const_string "neon_int_5")))]
1297 (define_expand "move_hi_quad_<mode>"
1298 [(match_operand:ANY128 0 "s_register_operand" "")
1299 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1302 emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0], <MODE>mode,
1303 GET_MODE_SIZE (<V_HALF>mode)),
1308 (define_expand "move_lo_quad_<mode>"
1309 [(match_operand:ANY128 0 "s_register_operand" "")
1310 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1313 emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0],
1319 ;; Reduction operations
1321 (define_expand "reduc_splus_<mode>"
1322 [(match_operand:VD 0 "s_register_operand" "")
1323 (match_operand:VD 1 "s_register_operand" "")]
1324 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1326 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1327 &gen_neon_vpadd_internal<mode>);
1331 (define_expand "reduc_splus_<mode>"
1332 [(match_operand:VQ 0 "s_register_operand" "")
1333 (match_operand:VQ 1 "s_register_operand" "")]
1334 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1335 && !BYTES_BIG_ENDIAN"
1337 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1338 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1340 emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
1341 emit_insn (gen_reduc_splus_<V_half> (res_d, step1));
1342 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1347 (define_insn "reduc_splus_v2di"
1348 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1349 (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1351 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1352 "vadd.i64\t%e0, %e1, %f1"
1353 [(set_attr "neon_type" "neon_int_1")]
1356 ;; NEON does not distinguish between signed and unsigned addition except on
1357 ;; widening operations.
1358 (define_expand "reduc_uplus_<mode>"
1359 [(match_operand:VDQI 0 "s_register_operand" "")
1360 (match_operand:VDQI 1 "s_register_operand" "")]
1361 "TARGET_NEON && (<Is_d_reg> || !BYTES_BIG_ENDIAN)"
1363 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
1367 (define_expand "reduc_smin_<mode>"
1368 [(match_operand:VD 0 "s_register_operand" "")
1369 (match_operand:VD 1 "s_register_operand" "")]
1370 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1372 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1373 &gen_neon_vpsmin<mode>);
1377 (define_expand "reduc_smin_<mode>"
1378 [(match_operand:VQ 0 "s_register_operand" "")
1379 (match_operand:VQ 1 "s_register_operand" "")]
1380 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1381 && !BYTES_BIG_ENDIAN"
1383 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1384 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1386 emit_insn (gen_quad_halves_smin<mode> (step1, operands[1]));
1387 emit_insn (gen_reduc_smin_<V_half> (res_d, step1));
1388 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1393 (define_expand "reduc_smax_<mode>"
1394 [(match_operand:VD 0 "s_register_operand" "")
1395 (match_operand:VD 1 "s_register_operand" "")]
1396 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1398 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1399 &gen_neon_vpsmax<mode>);
1403 (define_expand "reduc_smax_<mode>"
1404 [(match_operand:VQ 0 "s_register_operand" "")
1405 (match_operand:VQ 1 "s_register_operand" "")]
1406 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1407 && !BYTES_BIG_ENDIAN"
1409 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1410 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1412 emit_insn (gen_quad_halves_smax<mode> (step1, operands[1]));
1413 emit_insn (gen_reduc_smax_<V_half> (res_d, step1));
1414 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1419 (define_expand "reduc_umin_<mode>"
1420 [(match_operand:VDI 0 "s_register_operand" "")
1421 (match_operand:VDI 1 "s_register_operand" "")]
1424 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1425 &gen_neon_vpumin<mode>);
1429 (define_expand "reduc_umin_<mode>"
1430 [(match_operand:VQI 0 "s_register_operand" "")
1431 (match_operand:VQI 1 "s_register_operand" "")]
1432 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1434 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1435 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1437 emit_insn (gen_quad_halves_umin<mode> (step1, operands[1]));
1438 emit_insn (gen_reduc_umin_<V_half> (res_d, step1));
1439 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1444 (define_expand "reduc_umax_<mode>"
1445 [(match_operand:VDI 0 "s_register_operand" "")
1446 (match_operand:VDI 1 "s_register_operand" "")]
1449 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1450 &gen_neon_vpumax<mode>);
1454 (define_expand "reduc_umax_<mode>"
1455 [(match_operand:VQI 0 "s_register_operand" "")
1456 (match_operand:VQI 1 "s_register_operand" "")]
1457 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1459 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1460 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1462 emit_insn (gen_quad_halves_umax<mode> (step1, operands[1]));
1463 emit_insn (gen_reduc_umax_<V_half> (res_d, step1));
1464 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1469 (define_insn "neon_vpadd_internal<mode>"
1470 [(set (match_operand:VD 0 "s_register_operand" "=w")
1471 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1472 (match_operand:VD 2 "s_register_operand" "w")]
1475 "vpadd.<V_if_elem>\t%P0, %P1, %P2"
1476 ;; Assume this schedules like vadd.
1477 [(set (attr "neon_type")
1478 (if_then_else (match_test "<Is_float_mode>")
1479 (if_then_else (match_test "<Is_d_reg>")
1480 (const_string "neon_fp_vadd_ddd_vabs_dd")
1481 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1482 (const_string "neon_int_1")))]
1485 (define_insn "neon_vpsmin<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 "vpmin.<V_s_elem>\t%P0, %P1, %P2"
1492 ;; Assume this schedules like vmin.
1493 [(set (attr "neon_type")
1494 (if_then_else (match_test "<Is_float_mode>")
1495 (const_string "neon_fp_vadd_ddd_vabs_dd")
1496 (const_string "neon_int_5")))]
1499 (define_insn "neon_vpsmax<mode>"
1500 [(set (match_operand:VD 0 "s_register_operand" "=w")
1501 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1502 (match_operand:VD 2 "s_register_operand" "w")]
1505 "vpmax.<V_s_elem>\t%P0, %P1, %P2"
1506 ;; Assume this schedules like vmax.
1507 [(set (attr "neon_type")
1508 (if_then_else (match_test "<Is_float_mode>")
1509 (const_string "neon_fp_vadd_ddd_vabs_dd")
1510 (const_string "neon_int_5")))]
1513 (define_insn "neon_vpumin<mode>"
1514 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1515 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1516 (match_operand:VDI 2 "s_register_operand" "w")]
1519 "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1520 ;; Assume this schedules like umin.
1521 [(set_attr "neon_type" "neon_int_5")]
1524 (define_insn "neon_vpumax<mode>"
1525 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1526 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1527 (match_operand:VDI 2 "s_register_operand" "w")]
1530 "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1531 ;; Assume this schedules like umax.
1532 [(set_attr "neon_type" "neon_int_5")]
1535 ;; Saturating arithmetic
1537 ; NOTE: Neon supports many more saturating variants of instructions than the
1538 ; following, but these are all GCC currently understands.
1539 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1540 ; yet either, although these patterns may be used by intrinsics when they're
1543 (define_insn "*ss_add<mode>_neon"
1544 [(set (match_operand:VD 0 "s_register_operand" "=w")
1545 (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1546 (match_operand:VD 2 "s_register_operand" "w")))]
1548 "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1549 [(set_attr "neon_type" "neon_int_4")]
1552 (define_insn "*us_add<mode>_neon"
1553 [(set (match_operand:VD 0 "s_register_operand" "=w")
1554 (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1555 (match_operand:VD 2 "s_register_operand" "w")))]
1557 "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1558 [(set_attr "neon_type" "neon_int_4")]
1561 (define_insn "*ss_sub<mode>_neon"
1562 [(set (match_operand:VD 0 "s_register_operand" "=w")
1563 (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1564 (match_operand:VD 2 "s_register_operand" "w")))]
1566 "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1567 [(set_attr "neon_type" "neon_int_5")]
1570 (define_insn "*us_sub<mode>_neon"
1571 [(set (match_operand:VD 0 "s_register_operand" "=w")
1572 (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1573 (match_operand:VD 2 "s_register_operand" "w")))]
1575 "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1576 [(set_attr "neon_type" "neon_int_5")]
1579 ;; Conditional instructions. These are comparisons with conditional moves for
1580 ;; vectors. They perform the assignment:
1582 ;; Vop0 = (Vop4 <op3> Vop5) ? Vop1 : Vop2;
1584 ;; where op3 is <, <=, ==, !=, >= or >. Operations are performed
1587 (define_expand "vcond<mode><mode>"
1588 [(set (match_operand:VDQW 0 "s_register_operand" "")
1590 (match_operator 3 "arm_comparison_operator"
1591 [(match_operand:VDQW 4 "s_register_operand" "")
1592 (match_operand:VDQW 5 "nonmemory_operand" "")])
1593 (match_operand:VDQW 1 "s_register_operand" "")
1594 (match_operand:VDQW 2 "s_register_operand" "")))]
1595 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1598 int inverse = 0, immediate_zero = 0;
1599 /* See the description of "magic" bits in the 'T' case of
1600 arm_print_operand. */
1601 HOST_WIDE_INT magic_word = (<MODE>mode == V2SFmode || <MODE>mode == V4SFmode)
1603 rtx magic_rtx = GEN_INT (magic_word);
1605 mask = gen_reg_rtx (<V_cmp_result>mode);
1607 if (operands[5] == CONST0_RTX (<MODE>mode))
1609 else if (!REG_P (operands[5]))
1610 operands[5] = force_reg (<MODE>mode, operands[5]);
1612 switch (GET_CODE (operands[3]))
1615 emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1620 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1625 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1631 emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1634 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1640 emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1643 emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1648 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1658 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1661 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1667 (define_expand "vcondu<mode><mode>"
1668 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1670 (match_operator 3 "arm_comparison_operator"
1671 [(match_operand:VDQIW 4 "s_register_operand" "")
1672 (match_operand:VDQIW 5 "s_register_operand" "")])
1673 (match_operand:VDQIW 1 "s_register_operand" "")
1674 (match_operand:VDQIW 2 "s_register_operand" "")))]
1678 int inverse = 0, immediate_zero = 0;
1680 mask = gen_reg_rtx (<V_cmp_result>mode);
1682 if (operands[5] == CONST0_RTX (<MODE>mode))
1684 else if (!REG_P (operands[5]))
1685 operands[5] = force_reg (<MODE>mode, operands[5]);
1687 switch (GET_CODE (operands[3]))
1690 emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1695 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1700 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1706 emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1709 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1715 emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1718 emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1723 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1733 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1736 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1742 ;; Patterns for builtins.
1744 ; good for plain vadd, vaddq.
1746 (define_expand "neon_vadd<mode>"
1747 [(match_operand:VDQX 0 "s_register_operand" "=w")
1748 (match_operand:VDQX 1 "s_register_operand" "w")
1749 (match_operand:VDQX 2 "s_register_operand" "w")
1750 (match_operand:SI 3 "immediate_operand" "i")]
1753 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1754 emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2]));
1756 emit_insn (gen_neon_vadd<mode>_unspec (operands[0], operands[1],
1761 ; Note that NEON operations don't support the full IEEE 754 standard: in
1762 ; particular, denormal values are flushed to zero. This means that GCC cannot
1763 ; use those instructions for autovectorization, etc. unless
1764 ; -funsafe-math-optimizations is in effect (in which case flush-to-zero
1765 ; behaviour is permissible). Intrinsic operations (provided by the arm_neon.h
1766 ; header) must work in either case: if -funsafe-math-optimizations is given,
1767 ; intrinsics expand to "canonical" RTL where possible, otherwise intrinsics
1768 ; expand to unspecs (which may potentially limit the extent to which they might
1769 ; be optimized by generic code).
1771 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
1773 (define_insn "neon_vadd<mode>_unspec"
1774 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1775 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1776 (match_operand:VDQX 2 "s_register_operand" "w")]
1779 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1780 [(set (attr "neon_type")
1781 (if_then_else (match_test "<Is_float_mode>")
1782 (if_then_else (match_test "<Is_d_reg>")
1783 (const_string "neon_fp_vadd_ddd_vabs_dd")
1784 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1785 (const_string "neon_int_1")))]
1788 ; operand 3 represents in bits:
1789 ; bit 0: signed (vs unsigned).
1790 ; bit 1: rounding (vs none).
1792 (define_insn "neon_vaddl<mode>"
1793 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1794 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1795 (match_operand:VDI 2 "s_register_operand" "w")
1796 (match_operand:SI 3 "immediate_operand" "i")]
1799 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1800 [(set_attr "neon_type" "neon_int_3")]
1803 (define_insn "neon_vaddw<mode>"
1804 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1805 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1806 (match_operand:VDI 2 "s_register_operand" "w")
1807 (match_operand:SI 3 "immediate_operand" "i")]
1810 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1811 [(set_attr "neon_type" "neon_int_2")]
1816 (define_insn "neon_vhadd<mode>"
1817 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1818 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1819 (match_operand:VDQIW 2 "s_register_operand" "w")
1820 (match_operand:SI 3 "immediate_operand" "i")]
1823 "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1824 [(set_attr "neon_type" "neon_int_4")]
1827 (define_insn "neon_vqadd<mode>"
1828 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1829 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1830 (match_operand:VDQIX 2 "s_register_operand" "w")
1831 (match_operand:SI 3 "immediate_operand" "i")]
1834 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1835 [(set_attr "neon_type" "neon_int_4")]
1838 (define_insn "neon_vaddhn<mode>"
1839 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
1840 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
1841 (match_operand:VN 2 "s_register_operand" "w")
1842 (match_operand:SI 3 "immediate_operand" "i")]
1845 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1846 [(set_attr "neon_type" "neon_int_4")]
1849 ;; We cannot replace this unspec with mul<mode>3 because of the odd
1850 ;; polynomial multiplication case that can specified by operand 3.
1851 (define_insn "neon_vmul<mode>"
1852 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1853 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1854 (match_operand:VDQW 2 "s_register_operand" "w")
1855 (match_operand:SI 3 "immediate_operand" "i")]
1858 "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1859 [(set (attr "neon_type")
1860 (if_then_else (match_test "<Is_float_mode>")
1861 (if_then_else (match_test "<Is_d_reg>")
1862 (const_string "neon_fp_vadd_ddd_vabs_dd")
1863 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1864 (if_then_else (match_test "<Is_d_reg>")
1866 (match_test "<Scalar_mul_8_16>")
1867 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1868 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1869 (if_then_else (match_test "<Scalar_mul_8_16>")
1870 (const_string "neon_mul_qqq_8_16_32_ddd_32")
1871 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
1874 (define_expand "neon_vmla<mode>"
1875 [(match_operand:VDQW 0 "s_register_operand" "=w")
1876 (match_operand:VDQW 1 "s_register_operand" "0")
1877 (match_operand:VDQW 2 "s_register_operand" "w")
1878 (match_operand:VDQW 3 "s_register_operand" "w")
1879 (match_operand:SI 4 "immediate_operand" "i")]
1882 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1883 emit_insn (gen_mul<mode>3add<mode>_neon (operands[0], operands[1],
1884 operands[2], operands[3]));
1886 emit_insn (gen_neon_vmla<mode>_unspec (operands[0], operands[1],
1887 operands[2], operands[3]));
1891 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
1893 (define_insn "neon_vmla<mode>_unspec"
1894 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1895 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
1896 (match_operand:VDQ 2 "s_register_operand" "w")
1897 (match_operand:VDQ 3 "s_register_operand" "w")]
1900 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1901 [(set (attr "neon_type")
1902 (if_then_else (match_test "<Is_float_mode>")
1903 (if_then_else (match_test "<Is_d_reg>")
1904 (const_string "neon_fp_vmla_ddd")
1905 (const_string "neon_fp_vmla_qqq"))
1906 (if_then_else (match_test "<Is_d_reg>")
1908 (match_test "<Scalar_mul_8_16>")
1909 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1910 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1911 (if_then_else (match_test "<Scalar_mul_8_16>")
1912 (const_string "neon_mla_qqq_8_16")
1913 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1916 (define_insn "neon_vmlal<mode>"
1917 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1918 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1919 (match_operand:VW 2 "s_register_operand" "w")
1920 (match_operand:VW 3 "s_register_operand" "w")
1921 (match_operand:SI 4 "immediate_operand" "i")]
1924 "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1925 [(set (attr "neon_type")
1926 (if_then_else (match_test "<Scalar_mul_8_16>")
1927 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1928 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1931 (define_expand "neon_vmls<mode>"
1932 [(match_operand:VDQW 0 "s_register_operand" "=w")
1933 (match_operand:VDQW 1 "s_register_operand" "0")
1934 (match_operand:VDQW 2 "s_register_operand" "w")
1935 (match_operand:VDQW 3 "s_register_operand" "w")
1936 (match_operand:SI 4 "immediate_operand" "i")]
1939 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1940 emit_insn (gen_mul<mode>3neg<mode>add<mode>_neon (operands[0],
1941 operands[1], operands[2], operands[3]));
1943 emit_insn (gen_neon_vmls<mode>_unspec (operands[0], operands[1],
1944 operands[2], operands[3]));
1948 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
1950 (define_insn "neon_vmls<mode>_unspec"
1951 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1952 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
1953 (match_operand:VDQ 2 "s_register_operand" "w")
1954 (match_operand:VDQ 3 "s_register_operand" "w")]
1957 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1958 [(set (attr "neon_type")
1959 (if_then_else (match_test "<Is_float_mode>")
1960 (if_then_else (match_test "<Is_d_reg>")
1961 (const_string "neon_fp_vmla_ddd")
1962 (const_string "neon_fp_vmla_qqq"))
1963 (if_then_else (match_test "<Is_d_reg>")
1965 (match_test "<Scalar_mul_8_16>")
1966 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1967 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1969 (match_test "<Scalar_mul_8_16>")
1970 (const_string "neon_mla_qqq_8_16")
1971 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1974 (define_insn "neon_vmlsl<mode>"
1975 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1976 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1977 (match_operand:VW 2 "s_register_operand" "w")
1978 (match_operand:VW 3 "s_register_operand" "w")
1979 (match_operand:SI 4 "immediate_operand" "i")]
1982 "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1983 [(set (attr "neon_type")
1984 (if_then_else (match_test "<Scalar_mul_8_16>")
1985 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1986 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1989 (define_insn "neon_vqdmulh<mode>"
1990 [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
1991 (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
1992 (match_operand:VMDQI 2 "s_register_operand" "w")
1993 (match_operand:SI 3 "immediate_operand" "i")]
1996 "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1997 [(set (attr "neon_type")
1998 (if_then_else (match_test "<Is_d_reg>")
1999 (if_then_else (match_test "<Scalar_mul_8_16>")
2000 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2001 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
2002 (if_then_else (match_test "<Scalar_mul_8_16>")
2003 (const_string "neon_mul_qqq_8_16_32_ddd_32")
2004 (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
2007 (define_insn "neon_vqdmlal<mode>"
2008 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2009 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2010 (match_operand:VMDI 2 "s_register_operand" "w")
2011 (match_operand:VMDI 3 "s_register_operand" "w")
2012 (match_operand:SI 4 "immediate_operand" "i")]
2015 "vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
2016 [(set (attr "neon_type")
2017 (if_then_else (match_test "<Scalar_mul_8_16>")
2018 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2019 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2022 (define_insn "neon_vqdmlsl<mode>"
2023 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2024 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2025 (match_operand:VMDI 2 "s_register_operand" "w")
2026 (match_operand:VMDI 3 "s_register_operand" "w")
2027 (match_operand:SI 4 "immediate_operand" "i")]
2030 "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
2031 [(set (attr "neon_type")
2032 (if_then_else (match_test "<Scalar_mul_8_16>")
2033 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2034 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2037 (define_insn "neon_vmull<mode>"
2038 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2039 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2040 (match_operand:VW 2 "s_register_operand" "w")
2041 (match_operand:SI 3 "immediate_operand" "i")]
2044 "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2045 [(set (attr "neon_type")
2046 (if_then_else (match_test "<Scalar_mul_8_16>")
2047 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2048 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2051 (define_insn "neon_vqdmull<mode>"
2052 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2053 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2054 (match_operand:VMDI 2 "s_register_operand" "w")
2055 (match_operand:SI 3 "immediate_operand" "i")]
2058 "vqdmull.<V_s_elem>\t%q0, %P1, %P2"
2059 [(set (attr "neon_type")
2060 (if_then_else (match_test "<Scalar_mul_8_16>")
2061 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2062 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2065 (define_expand "neon_vsub<mode>"
2066 [(match_operand:VDQX 0 "s_register_operand" "=w")
2067 (match_operand:VDQX 1 "s_register_operand" "w")
2068 (match_operand:VDQX 2 "s_register_operand" "w")
2069 (match_operand:SI 3 "immediate_operand" "i")]
2072 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2073 emit_insn (gen_sub<mode>3 (operands[0], operands[1], operands[2]));
2075 emit_insn (gen_neon_vsub<mode>_unspec (operands[0], operands[1],
2080 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2082 (define_insn "neon_vsub<mode>_unspec"
2083 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
2084 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
2085 (match_operand:VDQX 2 "s_register_operand" "w")]
2088 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2089 [(set (attr "neon_type")
2090 (if_then_else (match_test "<Is_float_mode>")
2091 (if_then_else (match_test "<Is_d_reg>")
2092 (const_string "neon_fp_vadd_ddd_vabs_dd")
2093 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2094 (const_string "neon_int_2")))]
2097 (define_insn "neon_vsubl<mode>"
2098 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2099 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
2100 (match_operand:VDI 2 "s_register_operand" "w")
2101 (match_operand:SI 3 "immediate_operand" "i")]
2104 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2105 [(set_attr "neon_type" "neon_int_2")]
2108 (define_insn "neon_vsubw<mode>"
2109 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2110 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
2111 (match_operand:VDI 2 "s_register_operand" "w")
2112 (match_operand:SI 3 "immediate_operand" "i")]
2115 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
2116 [(set_attr "neon_type" "neon_int_2")]
2119 (define_insn "neon_vqsub<mode>"
2120 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2121 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2122 (match_operand:VDQIX 2 "s_register_operand" "w")
2123 (match_operand:SI 3 "immediate_operand" "i")]
2126 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2127 [(set_attr "neon_type" "neon_int_5")]
2130 (define_insn "neon_vhsub<mode>"
2131 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2132 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2133 (match_operand:VDQIW 2 "s_register_operand" "w")
2134 (match_operand:SI 3 "immediate_operand" "i")]
2137 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2138 [(set_attr "neon_type" "neon_int_5")]
2141 (define_insn "neon_vsubhn<mode>"
2142 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2143 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2144 (match_operand:VN 2 "s_register_operand" "w")
2145 (match_operand:SI 3 "immediate_operand" "i")]
2148 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2149 [(set_attr "neon_type" "neon_int_4")]
2152 (define_insn "neon_vceq<mode>"
2153 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2154 (unspec:<V_cmp_result>
2155 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2156 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2157 (match_operand:SI 3 "immediate_operand" "i,i")]
2161 vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2162 vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
2163 [(set (attr "neon_type")
2164 (if_then_else (match_test "<Is_float_mode>")
2165 (if_then_else (match_test "<Is_d_reg>")
2166 (const_string "neon_fp_vadd_ddd_vabs_dd")
2167 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2168 (const_string "neon_int_5")))]
2171 (define_insn "neon_vcge<mode>"
2172 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2173 (unspec:<V_cmp_result>
2174 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2175 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2176 (match_operand:SI 3 "immediate_operand" "i,i")]
2180 vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2181 vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2182 [(set (attr "neon_type")
2183 (if_then_else (match_test "<Is_float_mode>")
2184 (if_then_else (match_test "<Is_d_reg>")
2185 (const_string "neon_fp_vadd_ddd_vabs_dd")
2186 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2187 (const_string "neon_int_5")))]
2190 (define_insn "neon_vcgeu<mode>"
2191 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2192 (unspec:<V_cmp_result>
2193 [(match_operand:VDQIW 1 "s_register_operand" "w")
2194 (match_operand:VDQIW 2 "s_register_operand" "w")
2195 (match_operand:SI 3 "immediate_operand" "i")]
2198 "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2199 [(set_attr "neon_type" "neon_int_5")]
2202 (define_insn "neon_vcgt<mode>"
2203 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2204 (unspec:<V_cmp_result>
2205 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2206 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2207 (match_operand:SI 3 "immediate_operand" "i,i")]
2211 vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2212 vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2213 [(set (attr "neon_type")
2214 (if_then_else (match_test "<Is_float_mode>")
2215 (if_then_else (match_test "<Is_d_reg>")
2216 (const_string "neon_fp_vadd_ddd_vabs_dd")
2217 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2218 (const_string "neon_int_5")))]
2221 (define_insn "neon_vcgtu<mode>"
2222 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2223 (unspec:<V_cmp_result>
2224 [(match_operand:VDQIW 1 "s_register_operand" "w")
2225 (match_operand:VDQIW 2 "s_register_operand" "w")
2226 (match_operand:SI 3 "immediate_operand" "i")]
2229 "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2230 [(set_attr "neon_type" "neon_int_5")]
2233 ;; VCLE and VCLT only support comparisons with immediate zero (register
2234 ;; variants are VCGE and VCGT with operands reversed).
2236 (define_insn "neon_vcle<mode>"
2237 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2238 (unspec:<V_cmp_result>
2239 [(match_operand:VDQW 1 "s_register_operand" "w")
2240 (match_operand:VDQW 2 "zero_operand" "Dz")
2241 (match_operand:SI 3 "immediate_operand" "i")]
2244 "vcle.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2245 [(set (attr "neon_type")
2246 (if_then_else (match_test "<Is_float_mode>")
2247 (if_then_else (match_test "<Is_d_reg>")
2248 (const_string "neon_fp_vadd_ddd_vabs_dd")
2249 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2250 (const_string "neon_int_5")))]
2253 (define_insn "neon_vclt<mode>"
2254 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2255 (unspec:<V_cmp_result>
2256 [(match_operand:VDQW 1 "s_register_operand" "w")
2257 (match_operand:VDQW 2 "zero_operand" "Dz")
2258 (match_operand:SI 3 "immediate_operand" "i")]
2261 "vclt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2262 [(set (attr "neon_type")
2263 (if_then_else (match_test "<Is_float_mode>")
2264 (if_then_else (match_test "<Is_d_reg>")
2265 (const_string "neon_fp_vadd_ddd_vabs_dd")
2266 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2267 (const_string "neon_int_5")))]
2270 (define_insn "neon_vcage<mode>"
2271 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2272 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2273 (match_operand:VCVTF 2 "s_register_operand" "w")
2274 (match_operand:SI 3 "immediate_operand" "i")]
2277 "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2278 [(set (attr "neon_type")
2279 (if_then_else (match_test "<Is_d_reg>")
2280 (const_string "neon_fp_vadd_ddd_vabs_dd")
2281 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2284 (define_insn "neon_vcagt<mode>"
2285 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2286 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2287 (match_operand:VCVTF 2 "s_register_operand" "w")
2288 (match_operand:SI 3 "immediate_operand" "i")]
2291 "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2292 [(set (attr "neon_type")
2293 (if_then_else (match_test "<Is_d_reg>")
2294 (const_string "neon_fp_vadd_ddd_vabs_dd")
2295 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2298 (define_insn "neon_vtst<mode>"
2299 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2300 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2301 (match_operand:VDQIW 2 "s_register_operand" "w")
2302 (match_operand:SI 3 "immediate_operand" "i")]
2305 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2306 [(set_attr "neon_type" "neon_int_4")]
2309 (define_insn "neon_vabd<mode>"
2310 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2311 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2312 (match_operand:VDQW 2 "s_register_operand" "w")
2313 (match_operand:SI 3 "immediate_operand" "i")]
2316 "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2317 [(set (attr "neon_type")
2318 (if_then_else (match_test "<Is_float_mode>")
2319 (if_then_else (match_test "<Is_d_reg>")
2320 (const_string "neon_fp_vadd_ddd_vabs_dd")
2321 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2322 (const_string "neon_int_5")))]
2325 (define_insn "neon_vabdl<mode>"
2326 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2327 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2328 (match_operand:VW 2 "s_register_operand" "w")
2329 (match_operand:SI 3 "immediate_operand" "i")]
2332 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2333 [(set_attr "neon_type" "neon_int_5")]
2336 (define_insn "neon_vaba<mode>"
2337 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2338 (plus:VDQIW (match_operand:VDQIW 1 "s_register_operand" "0")
2339 (unspec:VDQIW [(match_operand:VDQIW 2 "s_register_operand" "w")
2340 (match_operand:VDQIW 3 "s_register_operand" "w")
2341 (match_operand:SI 4 "immediate_operand" "i")]
2344 "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2345 [(set (attr "neon_type")
2346 (if_then_else (match_test "<Is_d_reg>")
2347 (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2350 (define_insn "neon_vabal<mode>"
2351 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2352 (plus:<V_widen> (match_operand:<V_widen> 1 "s_register_operand" "0")
2353 (unspec:<V_widen> [(match_operand:VW 2 "s_register_operand" "w")
2354 (match_operand:VW 3 "s_register_operand" "w")
2355 (match_operand:SI 4 "immediate_operand" "i")]
2358 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2359 [(set_attr "neon_type" "neon_vaba")]
2362 (define_insn "neon_vmax<mode>"
2363 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2364 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2365 (match_operand:VDQW 2 "s_register_operand" "w")
2366 (match_operand:SI 3 "immediate_operand" "i")]
2369 "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2370 [(set (attr "neon_type")
2371 (if_then_else (match_test "<Is_float_mode>")
2372 (if_then_else (match_test "<Is_d_reg>")
2373 (const_string "neon_fp_vadd_ddd_vabs_dd")
2374 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2375 (const_string "neon_int_5")))]
2378 (define_insn "neon_vmin<mode>"
2379 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2380 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2381 (match_operand:VDQW 2 "s_register_operand" "w")
2382 (match_operand:SI 3 "immediate_operand" "i")]
2385 "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2386 [(set (attr "neon_type")
2387 (if_then_else (match_test "<Is_float_mode>")
2388 (if_then_else (match_test "<Is_d_reg>")
2389 (const_string "neon_fp_vadd_ddd_vabs_dd")
2390 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2391 (const_string "neon_int_5")))]
2394 (define_expand "neon_vpadd<mode>"
2395 [(match_operand:VD 0 "s_register_operand" "=w")
2396 (match_operand:VD 1 "s_register_operand" "w")
2397 (match_operand:VD 2 "s_register_operand" "w")
2398 (match_operand:SI 3 "immediate_operand" "i")]
2401 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
2406 (define_insn "neon_vpaddl<mode>"
2407 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2408 (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w")
2409 (match_operand:SI 2 "immediate_operand" "i")]
2412 "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2413 ;; Assume this schedules like vaddl.
2414 [(set_attr "neon_type" "neon_int_3")]
2417 (define_insn "neon_vpadal<mode>"
2418 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2419 (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0")
2420 (match_operand:VDQIW 2 "s_register_operand" "w")
2421 (match_operand:SI 3 "immediate_operand" "i")]
2424 "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
2425 ;; Assume this schedules like vpadd.
2426 [(set_attr "neon_type" "neon_int_1")]
2429 (define_insn "neon_vpmax<mode>"
2430 [(set (match_operand:VD 0 "s_register_operand" "=w")
2431 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2432 (match_operand:VD 2 "s_register_operand" "w")
2433 (match_operand:SI 3 "immediate_operand" "i")]
2436 "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2437 ;; Assume this schedules like vmax.
2438 [(set (attr "neon_type")
2439 (if_then_else (match_test "<Is_float_mode>")
2440 (const_string "neon_fp_vadd_ddd_vabs_dd")
2441 (const_string "neon_int_5")))]
2444 (define_insn "neon_vpmin<mode>"
2445 [(set (match_operand:VD 0 "s_register_operand" "=w")
2446 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2447 (match_operand:VD 2 "s_register_operand" "w")
2448 (match_operand:SI 3 "immediate_operand" "i")]
2451 "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2452 ;; Assume this schedules like vmin.
2453 [(set (attr "neon_type")
2454 (if_then_else (match_test "<Is_float_mode>")
2455 (const_string "neon_fp_vadd_ddd_vabs_dd")
2456 (const_string "neon_int_5")))]
2459 (define_insn "neon_vrecps<mode>"
2460 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2461 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2462 (match_operand:VCVTF 2 "s_register_operand" "w")
2463 (match_operand:SI 3 "immediate_operand" "i")]
2466 "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2467 [(set (attr "neon_type")
2468 (if_then_else (match_test "<Is_d_reg>")
2469 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2470 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2473 (define_insn "neon_vrsqrts<mode>"
2474 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2475 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2476 (match_operand:VCVTF 2 "s_register_operand" "w")
2477 (match_operand:SI 3 "immediate_operand" "i")]
2480 "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2481 [(set (attr "neon_type")
2482 (if_then_else (match_test "<Is_d_reg>")
2483 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2484 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2487 (define_expand "neon_vabs<mode>"
2488 [(match_operand:VDQW 0 "s_register_operand" "")
2489 (match_operand:VDQW 1 "s_register_operand" "")
2490 (match_operand:SI 2 "immediate_operand" "")]
2493 emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
2497 (define_insn "neon_vqabs<mode>"
2498 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2499 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2500 (match_operand:SI 2 "immediate_operand" "i")]
2503 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2504 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2507 (define_expand "neon_vneg<mode>"
2508 [(match_operand:VDQW 0 "s_register_operand" "")
2509 (match_operand:VDQW 1 "s_register_operand" "")
2510 (match_operand:SI 2 "immediate_operand" "")]
2513 emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
2517 (define_insn "neon_vqneg<mode>"
2518 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2519 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2520 (match_operand:SI 2 "immediate_operand" "i")]
2523 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2524 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2527 (define_insn "neon_vcls<mode>"
2528 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2529 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2530 (match_operand:SI 2 "immediate_operand" "i")]
2533 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2534 [(set_attr "neon_type" "neon_int_1")]
2537 (define_insn "clz<mode>2"
2538 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2539 (clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
2541 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2542 [(set_attr "neon_type" "neon_int_1")]
2545 (define_expand "neon_vclz<mode>"
2546 [(match_operand:VDQIW 0 "s_register_operand" "")
2547 (match_operand:VDQIW 1 "s_register_operand" "")
2548 (match_operand:SI 2 "immediate_operand" "")]
2551 emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
2555 (define_insn "popcount<mode>2"
2556 [(set (match_operand:VE 0 "s_register_operand" "=w")
2557 (popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
2559 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2560 [(set_attr "neon_type" "neon_int_1")]
2563 (define_expand "neon_vcnt<mode>"
2564 [(match_operand:VE 0 "s_register_operand" "=w")
2565 (match_operand:VE 1 "s_register_operand" "w")
2566 (match_operand:SI 2 "immediate_operand" "i")]
2569 emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
2573 (define_insn "neon_vrecpe<mode>"
2574 [(set (match_operand:V32 0 "s_register_operand" "=w")
2575 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2576 (match_operand:SI 2 "immediate_operand" "i")]
2579 "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2580 [(set (attr "neon_type")
2581 (if_then_else (match_test "<Is_d_reg>")
2582 (const_string "neon_fp_vadd_ddd_vabs_dd")
2583 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2586 (define_insn "neon_vrsqrte<mode>"
2587 [(set (match_operand:V32 0 "s_register_operand" "=w")
2588 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2589 (match_operand:SI 2 "immediate_operand" "i")]
2592 "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2593 [(set (attr "neon_type")
2594 (if_then_else (match_test "<Is_d_reg>")
2595 (const_string "neon_fp_vadd_ddd_vabs_dd")
2596 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2599 (define_expand "neon_vmvn<mode>"
2600 [(match_operand:VDQIW 0 "s_register_operand" "")
2601 (match_operand:VDQIW 1 "s_register_operand" "")
2602 (match_operand:SI 2 "immediate_operand" "")]
2605 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2609 (define_insn "neon_vget_lane<mode>_sext_internal"
2610 [(set (match_operand:SI 0 "s_register_operand" "=r")
2612 (vec_select:<V_elem>
2613 (match_operand:VD 1 "s_register_operand" "w")
2614 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2617 if (BYTES_BIG_ENDIAN)
2619 int elt = INTVAL (operands[2]);
2620 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2621 operands[2] = GEN_INT (elt);
2623 return "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]";
2625 [(set_attr "predicable" "yes")
2626 (set_attr "neon_type" "neon_bp_simple")]
2629 (define_insn "neon_vget_lane<mode>_zext_internal"
2630 [(set (match_operand:SI 0 "s_register_operand" "=r")
2632 (vec_select:<V_elem>
2633 (match_operand:VD 1 "s_register_operand" "w")
2634 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2637 if (BYTES_BIG_ENDIAN)
2639 int elt = INTVAL (operands[2]);
2640 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2641 operands[2] = GEN_INT (elt);
2643 return "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]";
2645 [(set_attr "predicable" "yes")
2646 (set_attr "neon_type" "neon_bp_simple")]
2649 (define_insn "neon_vget_lane<mode>_sext_internal"
2650 [(set (match_operand:SI 0 "s_register_operand" "=r")
2652 (vec_select:<V_elem>
2653 (match_operand:VQ 1 "s_register_operand" "w")
2654 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2658 int regno = REGNO (operands[1]);
2659 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2660 unsigned int elt = INTVAL (operands[2]);
2661 unsigned int elt_adj = elt % halfelts;
2663 if (BYTES_BIG_ENDIAN)
2664 elt_adj = halfelts - 1 - elt_adj;
2666 ops[0] = operands[0];
2667 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2668 ops[2] = GEN_INT (elt_adj);
2669 output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops);
2673 [(set_attr "predicable" "yes")
2674 (set_attr "neon_type" "neon_bp_simple")]
2677 (define_insn "neon_vget_lane<mode>_zext_internal"
2678 [(set (match_operand:SI 0 "s_register_operand" "=r")
2680 (vec_select:<V_elem>
2681 (match_operand:VQ 1 "s_register_operand" "w")
2682 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2686 int regno = REGNO (operands[1]);
2687 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2688 unsigned int elt = INTVAL (operands[2]);
2689 unsigned int elt_adj = elt % halfelts;
2691 if (BYTES_BIG_ENDIAN)
2692 elt_adj = halfelts - 1 - elt_adj;
2694 ops[0] = operands[0];
2695 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2696 ops[2] = GEN_INT (elt_adj);
2697 output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops);
2701 [(set_attr "predicable" "yes")
2702 (set_attr "neon_type" "neon_bp_simple")]
2705 (define_expand "neon_vget_lane<mode>"
2706 [(match_operand:<V_ext> 0 "s_register_operand" "")
2707 (match_operand:VDQW 1 "s_register_operand" "")
2708 (match_operand:SI 2 "immediate_operand" "")
2709 (match_operand:SI 3 "immediate_operand" "")]
2712 HOST_WIDE_INT magic = INTVAL (operands[3]);
2715 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2717 if (BYTES_BIG_ENDIAN)
2719 /* The intrinsics are defined in terms of a model where the
2720 element ordering in memory is vldm order, whereas the generic
2721 RTL is defined in terms of a model where the element ordering
2722 in memory is array order. Convert the lane number to conform
2724 unsigned int elt = INTVAL (operands[2]);
2725 unsigned int reg_nelts
2726 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2727 elt ^= reg_nelts - 1;
2728 operands[2] = GEN_INT (elt);
2731 if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
2732 insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
2735 if ((magic & 1) != 0)
2736 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2739 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2746 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2749 (define_expand "neon_vget_lanedi"
2750 [(match_operand:DI 0 "s_register_operand" "=r")
2751 (match_operand:DI 1 "s_register_operand" "w")
2752 (match_operand:SI 2 "immediate_operand" "i")
2753 (match_operand:SI 3 "immediate_operand" "i")]
2756 neon_lane_bounds (operands[2], 0, 1);
2757 emit_move_insn (operands[0], operands[1]);
2761 (define_expand "neon_vget_lanev2di"
2762 [(match_operand:DI 0 "s_register_operand" "")
2763 (match_operand:V2DI 1 "s_register_operand" "")
2764 (match_operand:SI 2 "immediate_operand" "")
2765 (match_operand:SI 3 "immediate_operand" "")]
2768 switch (INTVAL (operands[2]))
2771 emit_move_insn (operands[0], gen_lowpart (DImode, operands[1]));
2774 emit_move_insn (operands[0], gen_highpart (DImode, operands[1]));
2777 neon_lane_bounds (operands[2], 0, 1);
2783 (define_expand "neon_vset_lane<mode>"
2784 [(match_operand:VDQ 0 "s_register_operand" "=w")
2785 (match_operand:<V_elem> 1 "s_register_operand" "r")
2786 (match_operand:VDQ 2 "s_register_operand" "0")
2787 (match_operand:SI 3 "immediate_operand" "i")]
2790 unsigned int elt = INTVAL (operands[3]);
2791 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2793 if (BYTES_BIG_ENDIAN)
2795 unsigned int reg_nelts
2796 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2797 elt ^= reg_nelts - 1;
2800 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
2801 GEN_INT (1 << elt), operands[2]));
2805 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2807 (define_expand "neon_vset_lanedi"
2808 [(match_operand:DI 0 "s_register_operand" "=w")
2809 (match_operand:DI 1 "s_register_operand" "r")
2810 (match_operand:DI 2 "s_register_operand" "0")
2811 (match_operand:SI 3 "immediate_operand" "i")]
2814 neon_lane_bounds (operands[3], 0, 1);
2815 emit_move_insn (operands[0], operands[1]);
2819 (define_expand "neon_vcreate<mode>"
2820 [(match_operand:VDX 0 "s_register_operand" "")
2821 (match_operand:DI 1 "general_operand" "")]
2824 rtx src = gen_lowpart (<MODE>mode, operands[1]);
2825 emit_move_insn (operands[0], src);
2829 (define_insn "neon_vdup_n<mode>"
2830 [(set (match_operand:VX 0 "s_register_operand" "=w")
2831 (vec_duplicate:VX (match_operand:<V_elem> 1 "s_register_operand" "r")))]
2833 "vdup%?.<V_sz_elem>\t%<V_reg>0, %1"
2834 ;; Assume this schedules like vmov.
2835 [(set_attr "predicable" "yes")
2836 (set_attr "neon_type" "neon_bp_simple")]
2839 (define_insn "neon_vdup_n<mode>"
2840 [(set (match_operand:V32 0 "s_register_operand" "=w,w")
2841 (vec_duplicate:V32 (match_operand:<V_elem> 1 "s_register_operand" "r,t")))]
2844 vdup%?.<V_sz_elem>\t%<V_reg>0, %1
2845 vdup%?.<V_sz_elem>\t%<V_reg>0, %y1"
2846 ;; Assume this schedules like vmov.
2847 [(set_attr "predicable" "yes")
2848 (set_attr "neon_type" "neon_bp_simple")]
2851 (define_expand "neon_vdup_ndi"
2852 [(match_operand:DI 0 "s_register_operand" "=w")
2853 (match_operand:DI 1 "s_register_operand" "r")]
2856 emit_move_insn (operands[0], operands[1]);
2861 (define_insn "neon_vdup_nv2di"
2862 [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
2863 (vec_duplicate:V2DI (match_operand:DI 1 "s_register_operand" "r,w")))]
2866 vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1
2867 vmov%?\t%e0, %P1\;vmov%?\t%f0, %P1"
2868 [(set_attr "predicable" "yes")
2869 (set_attr "length" "8")
2870 (set_attr "neon_type" "neon_bp_simple")]
2873 (define_insn "neon_vdup_lane<mode>_internal"
2874 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2876 (vec_select:<V_elem>
2877 (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
2878 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2881 if (BYTES_BIG_ENDIAN)
2883 int elt = INTVAL (operands[2]);
2884 elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt;
2885 operands[2] = GEN_INT (elt);
2888 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
2890 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
2892 ;; Assume this schedules like vmov.
2893 [(set_attr "neon_type" "neon_bp_simple")]
2896 (define_expand "neon_vdup_lane<mode>"
2897 [(match_operand:VDQW 0 "s_register_operand" "=w")
2898 (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
2899 (match_operand:SI 2 "immediate_operand" "i")]
2902 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
2903 if (BYTES_BIG_ENDIAN)
2905 unsigned int elt = INTVAL (operands[2]);
2906 unsigned int reg_nelts
2907 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<V_double_vector_mode>mode));
2908 elt ^= reg_nelts - 1;
2909 operands[2] = GEN_INT (elt);
2911 emit_insn (gen_neon_vdup_lane<mode>_internal (operands[0], operands[1],
2916 ; Scalar index is ignored, since only zero is valid here.
2917 (define_expand "neon_vdup_lanedi"
2918 [(match_operand:DI 0 "s_register_operand" "=w")
2919 (match_operand:DI 1 "s_register_operand" "w")
2920 (match_operand:SI 2 "immediate_operand" "i")]
2923 neon_lane_bounds (operands[2], 0, 1);
2924 emit_move_insn (operands[0], operands[1]);
2928 ; Likewise for v2di, as the DImode second operand has only a single element.
2929 (define_expand "neon_vdup_lanev2di"
2930 [(match_operand:V2DI 0 "s_register_operand" "=w")
2931 (match_operand:DI 1 "s_register_operand" "w")
2932 (match_operand:SI 2 "immediate_operand" "i")]
2935 neon_lane_bounds (operands[2], 0, 1);
2936 emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
2940 ; Disabled before reload because we don't want combine doing something silly,
2941 ; but used by the post-reload expansion of neon_vcombine.
2942 (define_insn "*neon_vswp<mode>"
2943 [(set (match_operand:VDQX 0 "s_register_operand" "+w")
2944 (match_operand:VDQX 1 "s_register_operand" "+w"))
2945 (set (match_dup 1) (match_dup 0))]
2946 "TARGET_NEON && reload_completed"
2947 "vswp\t%<V_reg>0, %<V_reg>1"
2948 [(set (attr "neon_type")
2949 (if_then_else (match_test "<Is_d_reg>")
2950 (const_string "neon_bp_simple")
2951 (const_string "neon_bp_2cycle")))]
2954 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
2956 ;; FIXME: A different implementation of this builtin could make it much
2957 ;; more likely that we wouldn't actually need to output anything (we could make
2958 ;; it so that the reg allocator puts things in the right places magically
2959 ;; instead). Lack of subregs for vectors makes that tricky though, I think.
2961 (define_insn_and_split "neon_vcombine<mode>"
2962 [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
2963 (vec_concat:<V_DOUBLE>
2964 (match_operand:VDX 1 "s_register_operand" "w")
2965 (match_operand:VDX 2 "s_register_operand" "w")))]
2968 "&& reload_completed"
2971 neon_split_vcombine (operands);
2975 (define_expand "neon_vget_high<mode>"
2976 [(match_operand:<V_HALF> 0 "s_register_operand")
2977 (match_operand:VQX 1 "s_register_operand")]
2980 emit_move_insn (operands[0],
2981 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
2982 GET_MODE_SIZE (<V_HALF>mode)));
2986 (define_expand "neon_vget_low<mode>"
2987 [(match_operand:<V_HALF> 0 "s_register_operand")
2988 (match_operand:VQX 1 "s_register_operand")]
2991 emit_move_insn (operands[0],
2992 simplify_gen_subreg (<V_HALF>mode, operands[1],
2997 (define_insn "float<mode><V_cvtto>2"
2998 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2999 (float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
3000 "TARGET_NEON && !flag_rounding_math"
3001 "vcvt.f32.s32\t%<V_reg>0, %<V_reg>1"
3002 [(set (attr "neon_type")
3003 (if_then_else (match_test "<Is_d_reg>")
3004 (const_string "neon_fp_vadd_ddd_vabs_dd")
3005 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3008 (define_insn "floatuns<mode><V_cvtto>2"
3009 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3010 (unsigned_float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
3011 "TARGET_NEON && !flag_rounding_math"
3012 "vcvt.f32.u32\t%<V_reg>0, %<V_reg>1"
3013 [(set (attr "neon_type")
3014 (if_then_else (match_test "<Is_d_reg>")
3015 (const_string "neon_fp_vadd_ddd_vabs_dd")
3016 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3019 (define_insn "fix_trunc<mode><V_cvtto>2"
3020 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3021 (fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3023 "vcvt.s32.f32\t%<V_reg>0, %<V_reg>1"
3024 [(set (attr "neon_type")
3025 (if_then_else (match_test "<Is_d_reg>")
3026 (const_string "neon_fp_vadd_ddd_vabs_dd")
3027 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3030 (define_insn "fixuns_trunc<mode><V_cvtto>2"
3031 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3032 (unsigned_fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3034 "vcvt.u32.f32\t%<V_reg>0, %<V_reg>1"
3035 [(set (attr "neon_type")
3036 (if_then_else (match_test "<Is_d_reg>")
3037 (const_string "neon_fp_vadd_ddd_vabs_dd")
3038 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3041 (define_insn "neon_vcvt<mode>"
3042 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3043 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3044 (match_operand:SI 2 "immediate_operand" "i")]
3047 "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
3048 [(set (attr "neon_type")
3049 (if_then_else (match_test "<Is_d_reg>")
3050 (const_string "neon_fp_vadd_ddd_vabs_dd")
3051 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3054 (define_insn "neon_vcvt<mode>"
3055 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3056 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3057 (match_operand:SI 2 "immediate_operand" "i")]
3060 "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
3061 [(set (attr "neon_type")
3062 (if_then_else (match_test "<Is_d_reg>")
3063 (const_string "neon_fp_vadd_ddd_vabs_dd")
3064 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3067 (define_insn "neon_vcvt_n<mode>"
3068 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3069 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3070 (match_operand:SI 2 "immediate_operand" "i")
3071 (match_operand:SI 3 "immediate_operand" "i")]
3075 neon_const_bounds (operands[2], 1, 33);
3076 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
3078 [(set (attr "neon_type")
3079 (if_then_else (match_test "<Is_d_reg>")
3080 (const_string "neon_fp_vadd_ddd_vabs_dd")
3081 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3084 (define_insn "neon_vcvt_n<mode>"
3085 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3086 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3087 (match_operand:SI 2 "immediate_operand" "i")
3088 (match_operand:SI 3 "immediate_operand" "i")]
3092 neon_const_bounds (operands[2], 1, 33);
3093 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
3095 [(set (attr "neon_type")
3096 (if_then_else (match_test "<Is_d_reg>")
3097 (const_string "neon_fp_vadd_ddd_vabs_dd")
3098 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3101 (define_insn "neon_vmovn<mode>"
3102 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3103 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3104 (match_operand:SI 2 "immediate_operand" "i")]
3107 "vmovn.<V_if_elem>\t%P0, %q1"
3108 [(set_attr "neon_type" "neon_bp_simple")]
3111 (define_insn "neon_vqmovn<mode>"
3112 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3113 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3114 (match_operand:SI 2 "immediate_operand" "i")]
3117 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
3118 [(set_attr "neon_type" "neon_shift_2")]
3121 (define_insn "neon_vqmovun<mode>"
3122 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3123 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3124 (match_operand:SI 2 "immediate_operand" "i")]
3127 "vqmovun.<V_s_elem>\t%P0, %q1"
3128 [(set_attr "neon_type" "neon_shift_2")]
3131 (define_insn "neon_vmovl<mode>"
3132 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3133 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
3134 (match_operand:SI 2 "immediate_operand" "i")]
3137 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
3138 [(set_attr "neon_type" "neon_shift_1")]
3141 (define_insn "neon_vmul_lane<mode>"
3142 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3143 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
3144 (match_operand:VMD 2 "s_register_operand"
3145 "<scalar_mul_constraint>")
3146 (match_operand:SI 3 "immediate_operand" "i")
3147 (match_operand:SI 4 "immediate_operand" "i")]
3151 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3152 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
3154 [(set (attr "neon_type")
3155 (if_then_else (match_test "<Is_float_mode>")
3156 (const_string "neon_fp_vmul_ddd")
3157 (if_then_else (match_test "<Scalar_mul_8_16>")
3158 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3159 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
3162 (define_insn "neon_vmul_lane<mode>"
3163 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3164 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
3165 (match_operand:<V_HALF> 2 "s_register_operand"
3166 "<scalar_mul_constraint>")
3167 (match_operand:SI 3 "immediate_operand" "i")
3168 (match_operand:SI 4 "immediate_operand" "i")]
3172 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
3173 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
3175 [(set (attr "neon_type")
3176 (if_then_else (match_test "<Is_float_mode>")
3177 (const_string "neon_fp_vmul_qqd")
3178 (if_then_else (match_test "<Scalar_mul_8_16>")
3179 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3180 (const_string "neon_mul_qqd_32_scalar"))))]
3183 (define_insn "neon_vmull_lane<mode>"
3184 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3185 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3186 (match_operand:VMDI 2 "s_register_operand"
3187 "<scalar_mul_constraint>")
3188 (match_operand:SI 3 "immediate_operand" "i")
3189 (match_operand:SI 4 "immediate_operand" "i")]
3190 UNSPEC_VMULL_LANE))]
3193 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3194 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
3196 [(set (attr "neon_type")
3197 (if_then_else (match_test "<Scalar_mul_8_16>")
3198 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3199 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3202 (define_insn "neon_vqdmull_lane<mode>"
3203 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3204 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3205 (match_operand:VMDI 2 "s_register_operand"
3206 "<scalar_mul_constraint>")
3207 (match_operand:SI 3 "immediate_operand" "i")
3208 (match_operand:SI 4 "immediate_operand" "i")]
3209 UNSPEC_VQDMULL_LANE))]
3212 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3213 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
3215 [(set (attr "neon_type")
3216 (if_then_else (match_test "<Scalar_mul_8_16>")
3217 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3218 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3221 (define_insn "neon_vqdmulh_lane<mode>"
3222 [(set (match_operand:VMQI 0 "s_register_operand" "=w")
3223 (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
3224 (match_operand:<V_HALF> 2 "s_register_operand"
3225 "<scalar_mul_constraint>")
3226 (match_operand:SI 3 "immediate_operand" "i")
3227 (match_operand:SI 4 "immediate_operand" "i")]
3228 UNSPEC_VQDMULH_LANE))]
3231 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3232 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
3234 [(set (attr "neon_type")
3235 (if_then_else (match_test "<Scalar_mul_8_16>")
3236 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3237 (const_string "neon_mul_qqd_32_scalar")))]
3240 (define_insn "neon_vqdmulh_lane<mode>"
3241 [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3242 (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3243 (match_operand:VMDI 2 "s_register_operand"
3244 "<scalar_mul_constraint>")
3245 (match_operand:SI 3 "immediate_operand" "i")
3246 (match_operand:SI 4 "immediate_operand" "i")]
3247 UNSPEC_VQDMULH_LANE))]
3250 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3251 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
3253 [(set (attr "neon_type")
3254 (if_then_else (match_test "<Scalar_mul_8_16>")
3255 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3256 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3259 (define_insn "neon_vmla_lane<mode>"
3260 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3261 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3262 (match_operand:VMD 2 "s_register_operand" "w")
3263 (match_operand:VMD 3 "s_register_operand"
3264 "<scalar_mul_constraint>")
3265 (match_operand:SI 4 "immediate_operand" "i")
3266 (match_operand:SI 5 "immediate_operand" "i")]
3270 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3271 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3273 [(set (attr "neon_type")
3274 (if_then_else (match_test "<Is_float_mode>")
3275 (const_string "neon_fp_vmla_ddd_scalar")
3276 (if_then_else (match_test "<Scalar_mul_8_16>")
3277 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3278 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3281 (define_insn "neon_vmla_lane<mode>"
3282 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3283 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3284 (match_operand:VMQ 2 "s_register_operand" "w")
3285 (match_operand:<V_HALF> 3 "s_register_operand"
3286 "<scalar_mul_constraint>")
3287 (match_operand:SI 4 "immediate_operand" "i")
3288 (match_operand:SI 5 "immediate_operand" "i")]
3292 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3293 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3295 [(set (attr "neon_type")
3296 (if_then_else (match_test "<Is_float_mode>")
3297 (const_string "neon_fp_vmla_qqq_scalar")
3298 (if_then_else (match_test "<Scalar_mul_8_16>")
3299 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3300 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3303 (define_insn "neon_vmlal_lane<mode>"
3304 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3305 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3306 (match_operand:VMDI 2 "s_register_operand" "w")
3307 (match_operand:VMDI 3 "s_register_operand"
3308 "<scalar_mul_constraint>")
3309 (match_operand:SI 4 "immediate_operand" "i")
3310 (match_operand:SI 5 "immediate_operand" "i")]
3311 UNSPEC_VMLAL_LANE))]
3314 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3315 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3317 [(set (attr "neon_type")
3318 (if_then_else (match_test "<Scalar_mul_8_16>")
3319 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3320 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3323 (define_insn "neon_vqdmlal_lane<mode>"
3324 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3325 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3326 (match_operand:VMDI 2 "s_register_operand" "w")
3327 (match_operand:VMDI 3 "s_register_operand"
3328 "<scalar_mul_constraint>")
3329 (match_operand:SI 4 "immediate_operand" "i")
3330 (match_operand:SI 5 "immediate_operand" "i")]
3331 UNSPEC_VQDMLAL_LANE))]
3334 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3335 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3337 [(set (attr "neon_type")
3338 (if_then_else (match_test "<Scalar_mul_8_16>")
3339 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3340 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3343 (define_insn "neon_vmls_lane<mode>"
3344 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3345 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3346 (match_operand:VMD 2 "s_register_operand" "w")
3347 (match_operand:VMD 3 "s_register_operand"
3348 "<scalar_mul_constraint>")
3349 (match_operand:SI 4 "immediate_operand" "i")
3350 (match_operand:SI 5 "immediate_operand" "i")]
3354 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3355 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3357 [(set (attr "neon_type")
3358 (if_then_else (match_test "<Is_float_mode>")
3359 (const_string "neon_fp_vmla_ddd_scalar")
3360 (if_then_else (match_test "<Scalar_mul_8_16>")
3361 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3362 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3365 (define_insn "neon_vmls_lane<mode>"
3366 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3367 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3368 (match_operand:VMQ 2 "s_register_operand" "w")
3369 (match_operand:<V_HALF> 3 "s_register_operand"
3370 "<scalar_mul_constraint>")
3371 (match_operand:SI 4 "immediate_operand" "i")
3372 (match_operand:SI 5 "immediate_operand" "i")]
3376 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3377 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3379 [(set (attr "neon_type")
3380 (if_then_else (match_test "<Is_float_mode>")
3381 (const_string "neon_fp_vmla_qqq_scalar")
3382 (if_then_else (match_test "<Scalar_mul_8_16>")
3383 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3384 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3387 (define_insn "neon_vmlsl_lane<mode>"
3388 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3389 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3390 (match_operand:VMDI 2 "s_register_operand" "w")
3391 (match_operand:VMDI 3 "s_register_operand"
3392 "<scalar_mul_constraint>")
3393 (match_operand:SI 4 "immediate_operand" "i")
3394 (match_operand:SI 5 "immediate_operand" "i")]
3395 UNSPEC_VMLSL_LANE))]
3398 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3399 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3401 [(set (attr "neon_type")
3402 (if_then_else (match_test "<Scalar_mul_8_16>")
3403 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3404 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3407 (define_insn "neon_vqdmlsl_lane<mode>"
3408 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3409 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3410 (match_operand:VMDI 2 "s_register_operand" "w")
3411 (match_operand:VMDI 3 "s_register_operand"
3412 "<scalar_mul_constraint>")
3413 (match_operand:SI 4 "immediate_operand" "i")
3414 (match_operand:SI 5 "immediate_operand" "i")]
3415 UNSPEC_VQDMLSL_LANE))]
3418 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3419 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3421 [(set (attr "neon_type")
3422 (if_then_else (match_test "<Scalar_mul_8_16>")
3423 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3424 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3427 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3428 ; core register into a temp register, then use a scalar taken from that. This
3429 ; isn't an optimal solution if e.g. the scalar has just been read from memory
3430 ; or extracted from another vector. The latter case it's currently better to
3431 ; use the "_lane" variant, and the former case can probably be implemented
3432 ; using vld1_lane, but that hasn't been done yet.
3434 (define_expand "neon_vmul_n<mode>"
3435 [(match_operand:VMD 0 "s_register_operand" "")
3436 (match_operand:VMD 1 "s_register_operand" "")
3437 (match_operand:<V_elem> 2 "s_register_operand" "")
3438 (match_operand:SI 3 "immediate_operand" "")]
3441 rtx tmp = gen_reg_rtx (<MODE>mode);
3442 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3443 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3444 const0_rtx, const0_rtx));
3448 (define_expand "neon_vmul_n<mode>"
3449 [(match_operand:VMQ 0 "s_register_operand" "")
3450 (match_operand:VMQ 1 "s_register_operand" "")
3451 (match_operand:<V_elem> 2 "s_register_operand" "")
3452 (match_operand:SI 3 "immediate_operand" "")]
3455 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3456 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3457 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3458 const0_rtx, const0_rtx));
3462 (define_expand "neon_vmull_n<mode>"
3463 [(match_operand:<V_widen> 0 "s_register_operand" "")
3464 (match_operand:VMDI 1 "s_register_operand" "")
3465 (match_operand:<V_elem> 2 "s_register_operand" "")
3466 (match_operand:SI 3 "immediate_operand" "")]
3469 rtx tmp = gen_reg_rtx (<MODE>mode);
3470 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3471 emit_insn (gen_neon_vmull_lane<mode> (operands[0], operands[1], tmp,
3472 const0_rtx, operands[3]));
3476 (define_expand "neon_vqdmull_n<mode>"
3477 [(match_operand:<V_widen> 0 "s_register_operand" "")
3478 (match_operand:VMDI 1 "s_register_operand" "")
3479 (match_operand:<V_elem> 2 "s_register_operand" "")
3480 (match_operand:SI 3 "immediate_operand" "")]
3483 rtx tmp = gen_reg_rtx (<MODE>mode);
3484 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3485 emit_insn (gen_neon_vqdmull_lane<mode> (operands[0], operands[1], tmp,
3486 const0_rtx, const0_rtx));
3490 (define_expand "neon_vqdmulh_n<mode>"
3491 [(match_operand:VMDI 0 "s_register_operand" "")
3492 (match_operand:VMDI 1 "s_register_operand" "")
3493 (match_operand:<V_elem> 2 "s_register_operand" "")
3494 (match_operand:SI 3 "immediate_operand" "")]
3497 rtx tmp = gen_reg_rtx (<MODE>mode);
3498 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3499 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3500 const0_rtx, operands[3]));
3504 (define_expand "neon_vqdmulh_n<mode>"
3505 [(match_operand:VMQI 0 "s_register_operand" "")
3506 (match_operand:VMQI 1 "s_register_operand" "")
3507 (match_operand:<V_elem> 2 "s_register_operand" "")
3508 (match_operand:SI 3 "immediate_operand" "")]
3511 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3512 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3513 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3514 const0_rtx, operands[3]));
3518 (define_expand "neon_vmla_n<mode>"
3519 [(match_operand:VMD 0 "s_register_operand" "")
3520 (match_operand:VMD 1 "s_register_operand" "")
3521 (match_operand:VMD 2 "s_register_operand" "")
3522 (match_operand:<V_elem> 3 "s_register_operand" "")
3523 (match_operand:SI 4 "immediate_operand" "")]
3526 rtx tmp = gen_reg_rtx (<MODE>mode);
3527 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3528 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3529 tmp, const0_rtx, operands[4]));
3533 (define_expand "neon_vmla_n<mode>"
3534 [(match_operand:VMQ 0 "s_register_operand" "")
3535 (match_operand:VMQ 1 "s_register_operand" "")
3536 (match_operand:VMQ 2 "s_register_operand" "")
3537 (match_operand:<V_elem> 3 "s_register_operand" "")
3538 (match_operand:SI 4 "immediate_operand" "")]
3541 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3542 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3543 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3544 tmp, const0_rtx, operands[4]));
3548 (define_expand "neon_vmlal_n<mode>"
3549 [(match_operand:<V_widen> 0 "s_register_operand" "")
3550 (match_operand:<V_widen> 1 "s_register_operand" "")
3551 (match_operand:VMDI 2 "s_register_operand" "")
3552 (match_operand:<V_elem> 3 "s_register_operand" "")
3553 (match_operand:SI 4 "immediate_operand" "")]
3556 rtx tmp = gen_reg_rtx (<MODE>mode);
3557 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3558 emit_insn (gen_neon_vmlal_lane<mode> (operands[0], operands[1], operands[2],
3559 tmp, const0_rtx, operands[4]));
3563 (define_expand "neon_vqdmlal_n<mode>"
3564 [(match_operand:<V_widen> 0 "s_register_operand" "")
3565 (match_operand:<V_widen> 1 "s_register_operand" "")
3566 (match_operand:VMDI 2 "s_register_operand" "")
3567 (match_operand:<V_elem> 3 "s_register_operand" "")
3568 (match_operand:SI 4 "immediate_operand" "")]
3571 rtx tmp = gen_reg_rtx (<MODE>mode);
3572 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3573 emit_insn (gen_neon_vqdmlal_lane<mode> (operands[0], operands[1], operands[2],
3574 tmp, const0_rtx, operands[4]));
3578 (define_expand "neon_vmls_n<mode>"
3579 [(match_operand:VMD 0 "s_register_operand" "")
3580 (match_operand:VMD 1 "s_register_operand" "")
3581 (match_operand:VMD 2 "s_register_operand" "")
3582 (match_operand:<V_elem> 3 "s_register_operand" "")
3583 (match_operand:SI 4 "immediate_operand" "")]
3586 rtx tmp = gen_reg_rtx (<MODE>mode);
3587 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3588 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3589 tmp, const0_rtx, operands[4]));
3593 (define_expand "neon_vmls_n<mode>"
3594 [(match_operand:VMQ 0 "s_register_operand" "")
3595 (match_operand:VMQ 1 "s_register_operand" "")
3596 (match_operand:VMQ 2 "s_register_operand" "")
3597 (match_operand:<V_elem> 3 "s_register_operand" "")
3598 (match_operand:SI 4 "immediate_operand" "")]
3601 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3602 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3603 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3604 tmp, const0_rtx, operands[4]));
3608 (define_expand "neon_vmlsl_n<mode>"
3609 [(match_operand:<V_widen> 0 "s_register_operand" "")
3610 (match_operand:<V_widen> 1 "s_register_operand" "")
3611 (match_operand:VMDI 2 "s_register_operand" "")
3612 (match_operand:<V_elem> 3 "s_register_operand" "")
3613 (match_operand:SI 4 "immediate_operand" "")]
3616 rtx tmp = gen_reg_rtx (<MODE>mode);
3617 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3618 emit_insn (gen_neon_vmlsl_lane<mode> (operands[0], operands[1], operands[2],
3619 tmp, const0_rtx, operands[4]));
3623 (define_expand "neon_vqdmlsl_n<mode>"
3624 [(match_operand:<V_widen> 0 "s_register_operand" "")
3625 (match_operand:<V_widen> 1 "s_register_operand" "")
3626 (match_operand:VMDI 2 "s_register_operand" "")
3627 (match_operand:<V_elem> 3 "s_register_operand" "")
3628 (match_operand:SI 4 "immediate_operand" "")]
3631 rtx tmp = gen_reg_rtx (<MODE>mode);
3632 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3633 emit_insn (gen_neon_vqdmlsl_lane<mode> (operands[0], operands[1], operands[2],
3634 tmp, const0_rtx, operands[4]));
3638 (define_insn "neon_vext<mode>"
3639 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
3640 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
3641 (match_operand:VDQX 2 "s_register_operand" "w")
3642 (match_operand:SI 3 "immediate_operand" "i")]
3646 neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3647 return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3";
3649 [(set (attr "neon_type")
3650 (if_then_else (match_test "<Is_d_reg>")
3651 (const_string "neon_bp_simple")
3652 (const_string "neon_bp_2cycle")))]
3655 (define_insn "neon_vrev64<mode>"
3656 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
3657 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
3658 (match_operand:SI 2 "immediate_operand" "i")]
3661 "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3662 [(set_attr "neon_type" "neon_bp_simple")]
3665 (define_insn "neon_vrev32<mode>"
3666 [(set (match_operand:VX 0 "s_register_operand" "=w")
3667 (unspec:VX [(match_operand:VX 1 "s_register_operand" "w")
3668 (match_operand:SI 2 "immediate_operand" "i")]
3671 "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3672 [(set_attr "neon_type" "neon_bp_simple")]
3675 (define_insn "neon_vrev16<mode>"
3676 [(set (match_operand:VE 0 "s_register_operand" "=w")
3677 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
3678 (match_operand:SI 2 "immediate_operand" "i")]
3681 "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3682 [(set_attr "neon_type" "neon_bp_simple")]
3685 ; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register
3686 ; allocation. For an intrinsic of form:
3687 ; rD = vbsl_* (rS, rN, rM)
3688 ; We can use any of:
3689 ; vbsl rS, rN, rM (if D = S)
3690 ; vbit rD, rN, rS (if D = M, so 1-bits in rS choose bits from rN, else rM)
3691 ; vbif rD, rM, rS (if D = N, so 0-bits in rS choose bits from rM, else rN)
3693 (define_insn "neon_vbsl<mode>_internal"
3694 [(set (match_operand:VDQX 0 "s_register_operand" "=w,w,w")
3695 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w")
3696 (match_operand:VDQX 2 "s_register_operand" " w,w,0")
3697 (match_operand:VDQX 3 "s_register_operand" " w,0,w")]
3701 vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3
3702 vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1
3703 vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1"
3704 [(set_attr "neon_type" "neon_int_1")]
3707 (define_expand "neon_vbsl<mode>"
3708 [(set (match_operand:VDQX 0 "s_register_operand" "")
3709 (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "")
3710 (match_operand:VDQX 2 "s_register_operand" "")
3711 (match_operand:VDQX 3 "s_register_operand" "")]
3715 /* We can't alias operands together if they have different modes. */
3716 operands[1] = gen_lowpart (<MODE>mode, operands[1]);
3719 (define_insn "neon_vshl<mode>"
3720 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3721 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3722 (match_operand:VDQIX 2 "s_register_operand" "w")
3723 (match_operand:SI 3 "immediate_operand" "i")]
3726 "v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3727 [(set (attr "neon_type")
3728 (if_then_else (match_test "<Is_d_reg>")
3729 (const_string "neon_vshl_ddd")
3730 (const_string "neon_shift_3")))]
3733 (define_insn "neon_vqshl<mode>"
3734 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3735 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3736 (match_operand:VDQIX 2 "s_register_operand" "w")
3737 (match_operand:SI 3 "immediate_operand" "i")]
3740 "vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3741 [(set (attr "neon_type")
3742 (if_then_else (match_test "<Is_d_reg>")
3743 (const_string "neon_shift_2")
3744 (const_string "neon_vqshl_vrshl_vqrshl_qqq")))]
3747 (define_insn "neon_vshr_n<mode>"
3748 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3749 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3750 (match_operand:SI 2 "immediate_operand" "i")
3751 (match_operand:SI 3 "immediate_operand" "i")]
3755 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1);
3756 return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
3758 [(set_attr "neon_type" "neon_shift_1")]
3761 (define_insn "neon_vshrn_n<mode>"
3762 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3763 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3764 (match_operand:SI 2 "immediate_operand" "i")
3765 (match_operand:SI 3 "immediate_operand" "i")]
3769 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3770 return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2";
3772 [(set_attr "neon_type" "neon_shift_1")]
3775 (define_insn "neon_vqshrn_n<mode>"
3776 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3777 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3778 (match_operand:SI 2 "immediate_operand" "i")
3779 (match_operand:SI 3 "immediate_operand" "i")]
3783 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3784 return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3786 [(set_attr "neon_type" "neon_shift_2")]
3789 (define_insn "neon_vqshrun_n<mode>"
3790 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3791 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3792 (match_operand:SI 2 "immediate_operand" "i")
3793 (match_operand:SI 3 "immediate_operand" "i")]
3797 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3798 return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3800 [(set_attr "neon_type" "neon_shift_2")]
3803 (define_insn "neon_vshl_n<mode>"
3804 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3805 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3806 (match_operand:SI 2 "immediate_operand" "i")
3807 (match_operand:SI 3 "immediate_operand" "i")]
3811 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
3812 return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2";
3814 [(set_attr "neon_type" "neon_shift_1")]
3817 (define_insn "neon_vqshl_n<mode>"
3818 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3819 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3820 (match_operand:SI 2 "immediate_operand" "i")
3821 (match_operand:SI 3 "immediate_operand" "i")]
3825 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
3826 return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
3828 [(set_attr "neon_type" "neon_shift_2")]
3831 (define_insn "neon_vqshlu_n<mode>"
3832 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3833 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3834 (match_operand:SI 2 "immediate_operand" "i")
3835 (match_operand:SI 3 "immediate_operand" "i")]
3839 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
3840 return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
3842 [(set_attr "neon_type" "neon_shift_2")]
3845 (define_insn "neon_vshll_n<mode>"
3846 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3847 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
3848 (match_operand:SI 2 "immediate_operand" "i")
3849 (match_operand:SI 3 "immediate_operand" "i")]
3853 /* The boundaries are: 0 < imm <= size. */
3854 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1);
3855 return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2";
3857 [(set_attr "neon_type" "neon_shift_1")]
3860 (define_insn "neon_vsra_n<mode>"
3861 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3862 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3863 (match_operand:VDQIX 2 "s_register_operand" "w")
3864 (match_operand:SI 3 "immediate_operand" "i")
3865 (match_operand:SI 4 "immediate_operand" "i")]
3869 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
3870 return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
3872 [(set_attr "neon_type" "neon_vsra_vrsra")]
3875 (define_insn "neon_vsri_n<mode>"
3876 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3877 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3878 (match_operand:VDQIX 2 "s_register_operand" "w")
3879 (match_operand:SI 3 "immediate_operand" "i")]
3883 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
3884 return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
3886 [(set (attr "neon_type")
3887 (if_then_else (match_test "<Is_d_reg>")
3888 (const_string "neon_shift_1")
3889 (const_string "neon_shift_3")))]
3892 (define_insn "neon_vsli_n<mode>"
3893 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3894 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3895 (match_operand:VDQIX 2 "s_register_operand" "w")
3896 (match_operand:SI 3 "immediate_operand" "i")]
3900 neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode));
3901 return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
3903 [(set (attr "neon_type")
3904 (if_then_else (match_test "<Is_d_reg>")
3905 (const_string "neon_shift_1")
3906 (const_string "neon_shift_3")))]
3909 (define_insn "neon_vtbl1v8qi"
3910 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3911 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w")
3912 (match_operand:V8QI 2 "s_register_operand" "w")]
3915 "vtbl.8\t%P0, {%P1}, %P2"
3916 [(set_attr "neon_type" "neon_bp_2cycle")]
3919 (define_insn "neon_vtbl2v8qi"
3920 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3921 (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w")
3922 (match_operand:V8QI 2 "s_register_operand" "w")]
3927 int tabbase = REGNO (operands[1]);
3929 ops[0] = operands[0];
3930 ops[1] = gen_rtx_REG (V8QImode, tabbase);
3931 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3932 ops[3] = operands[2];
3933 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops);
3937 [(set_attr "neon_type" "neon_bp_2cycle")]
3940 (define_insn "neon_vtbl3v8qi"
3941 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3942 (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w")
3943 (match_operand:V8QI 2 "s_register_operand" "w")]
3948 int tabbase = REGNO (operands[1]);
3950 ops[0] = operands[0];
3951 ops[1] = gen_rtx_REG (V8QImode, tabbase);
3952 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3953 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
3954 ops[4] = operands[2];
3955 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
3959 [(set_attr "neon_type" "neon_bp_3cycle")]
3962 (define_insn "neon_vtbl4v8qi"
3963 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3964 (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w")
3965 (match_operand:V8QI 2 "s_register_operand" "w")]
3970 int tabbase = REGNO (operands[1]);
3972 ops[0] = operands[0];
3973 ops[1] = gen_rtx_REG (V8QImode, tabbase);
3974 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3975 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
3976 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
3977 ops[5] = operands[2];
3978 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
3982 [(set_attr "neon_type" "neon_bp_3cycle")]
3985 ;; These three are used by the vec_perm infrastructure for V16QImode.
3986 (define_insn_and_split "neon_vtbl1v16qi"
3987 [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
3988 (unspec:V16QI [(match_operand:V16QI 1 "s_register_operand" "w")
3989 (match_operand:V16QI 2 "s_register_operand" "w")]
3993 "&& reload_completed"
3996 rtx op0, op1, op2, part0, part2;
4000 op1 = gen_lowpart (TImode, operands[1]);
4003 ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4004 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4005 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4006 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4008 ofs = subreg_highpart_offset (V8QImode, V16QImode);
4009 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4010 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4011 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4015 (define_insn_and_split "neon_vtbl2v16qi"
4016 [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
4017 (unspec:V16QI [(match_operand:OI 1 "s_register_operand" "w")
4018 (match_operand:V16QI 2 "s_register_operand" "w")]
4022 "&& reload_completed"
4025 rtx op0, op1, op2, part0, part2;
4032 ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4033 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4034 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4035 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4037 ofs = subreg_highpart_offset (V8QImode, V16QImode);
4038 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4039 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4040 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4044 ;; ??? Logically we should extend the regular neon_vcombine pattern to
4045 ;; handle quad-word input modes, producing octa-word output modes. But
4046 ;; that requires us to add support for octa-word vector modes in moves.
4047 ;; That seems overkill for this one use in vec_perm.
4048 (define_insn_and_split "neon_vcombinev16qi"
4049 [(set (match_operand:OI 0 "s_register_operand" "=w")
4050 (unspec:OI [(match_operand:V16QI 1 "s_register_operand" "w")
4051 (match_operand:V16QI 2 "s_register_operand" "w")]
4055 "&& reload_completed"
4058 neon_split_vcombine (operands);
4062 (define_insn "neon_vtbx1v8qi"
4063 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4064 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4065 (match_operand:V8QI 2 "s_register_operand" "w")
4066 (match_operand:V8QI 3 "s_register_operand" "w")]
4069 "vtbx.8\t%P0, {%P2}, %P3"
4070 [(set_attr "neon_type" "neon_bp_2cycle")]
4073 (define_insn "neon_vtbx2v8qi"
4074 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4075 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4076 (match_operand:TI 2 "s_register_operand" "w")
4077 (match_operand:V8QI 3 "s_register_operand" "w")]
4082 int tabbase = REGNO (operands[2]);
4084 ops[0] = operands[0];
4085 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4086 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4087 ops[3] = operands[3];
4088 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops);
4092 [(set_attr "neon_type" "neon_bp_2cycle")]
4095 (define_insn "neon_vtbx3v8qi"
4096 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4097 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4098 (match_operand:EI 2 "s_register_operand" "w")
4099 (match_operand:V8QI 3 "s_register_operand" "w")]
4104 int tabbase = REGNO (operands[2]);
4106 ops[0] = operands[0];
4107 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4108 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4109 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4110 ops[4] = operands[3];
4111 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4115 [(set_attr "neon_type" "neon_bp_3cycle")]
4118 (define_insn "neon_vtbx4v8qi"
4119 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4120 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4121 (match_operand:OI 2 "s_register_operand" "w")
4122 (match_operand:V8QI 3 "s_register_operand" "w")]
4127 int tabbase = REGNO (operands[2]);
4129 ops[0] = operands[0];
4130 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4131 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4132 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4133 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4134 ops[5] = operands[3];
4135 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4139 [(set_attr "neon_type" "neon_bp_3cycle")]
4142 (define_insn "neon_vtrn<mode>_internal"
4143 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4144 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4145 (match_operand:VDQW 2 "s_register_operand" "w")]
4147 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4148 (unspec:VDQW [(match_dup 1) (match_dup 2)]
4151 "vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>3"
4152 [(set (attr "neon_type")
4153 (if_then_else (match_test "<Is_d_reg>")
4154 (const_string "neon_bp_simple")
4155 (const_string "neon_bp_3cycle")))]
4158 (define_expand "neon_vtrn<mode>"
4159 [(match_operand:SI 0 "s_register_operand" "r")
4160 (match_operand:VDQW 1 "s_register_operand" "w")
4161 (match_operand:VDQW 2 "s_register_operand" "w")]
4164 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal,
4165 operands[0], operands[1], operands[2]);
4169 (define_insn "neon_vzip<mode>_internal"
4170 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4171 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4172 (match_operand:VDQW 2 "s_register_operand" "w")]
4174 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4175 (unspec:VDQW [(match_dup 1) (match_dup 2)]
4178 "vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>3"
4179 [(set (attr "neon_type")
4180 (if_then_else (match_test "<Is_d_reg>")
4181 (const_string "neon_bp_simple")
4182 (const_string "neon_bp_3cycle")))]
4185 (define_expand "neon_vzip<mode>"
4186 [(match_operand:SI 0 "s_register_operand" "r")
4187 (match_operand:VDQW 1 "s_register_operand" "w")
4188 (match_operand:VDQW 2 "s_register_operand" "w")]
4191 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal,
4192 operands[0], operands[1], operands[2]);
4196 (define_insn "neon_vuzp<mode>_internal"
4197 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4198 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4199 (match_operand:VDQW 2 "s_register_operand" "w")]
4201 (set (match_operand:VDQW 3 "s_register_operand" "=2")
4202 (unspec:VDQW [(match_dup 1) (match_dup 2)]
4205 "vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>3"
4206 [(set (attr "neon_type")
4207 (if_then_else (match_test "<Is_d_reg>")
4208 (const_string "neon_bp_simple")
4209 (const_string "neon_bp_3cycle")))]
4212 (define_expand "neon_vuzp<mode>"
4213 [(match_operand:SI 0 "s_register_operand" "r")
4214 (match_operand:VDQW 1 "s_register_operand" "w")
4215 (match_operand:VDQW 2 "s_register_operand" "w")]
4218 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal,
4219 operands[0], operands[1], operands[2]);
4223 (define_expand "neon_vreinterpretv8qi<mode>"
4224 [(match_operand:V8QI 0 "s_register_operand" "")
4225 (match_operand:VDX 1 "s_register_operand" "")]
4228 neon_reinterpret (operands[0], operands[1]);
4232 (define_expand "neon_vreinterpretv4hi<mode>"
4233 [(match_operand:V4HI 0 "s_register_operand" "")
4234 (match_operand:VDX 1 "s_register_operand" "")]
4237 neon_reinterpret (operands[0], operands[1]);
4241 (define_expand "neon_vreinterpretv2si<mode>"
4242 [(match_operand:V2SI 0 "s_register_operand" "")
4243 (match_operand:VDX 1 "s_register_operand" "")]
4246 neon_reinterpret (operands[0], operands[1]);
4250 (define_expand "neon_vreinterpretv2sf<mode>"
4251 [(match_operand:V2SF 0 "s_register_operand" "")
4252 (match_operand:VDX 1 "s_register_operand" "")]
4255 neon_reinterpret (operands[0], operands[1]);
4259 (define_expand "neon_vreinterpretdi<mode>"
4260 [(match_operand:DI 0 "s_register_operand" "")
4261 (match_operand:VDX 1 "s_register_operand" "")]
4264 neon_reinterpret (operands[0], operands[1]);
4268 (define_expand "neon_vreinterpretv16qi<mode>"
4269 [(match_operand:V16QI 0 "s_register_operand" "")
4270 (match_operand:VQX 1 "s_register_operand" "")]
4273 neon_reinterpret (operands[0], operands[1]);
4277 (define_expand "neon_vreinterpretv8hi<mode>"
4278 [(match_operand:V8HI 0 "s_register_operand" "")
4279 (match_operand:VQX 1 "s_register_operand" "")]
4282 neon_reinterpret (operands[0], operands[1]);
4286 (define_expand "neon_vreinterpretv4si<mode>"
4287 [(match_operand:V4SI 0 "s_register_operand" "")
4288 (match_operand:VQX 1 "s_register_operand" "")]
4291 neon_reinterpret (operands[0], operands[1]);
4295 (define_expand "neon_vreinterpretv4sf<mode>"
4296 [(match_operand:V4SF 0 "s_register_operand" "")
4297 (match_operand:VQX 1 "s_register_operand" "")]
4300 neon_reinterpret (operands[0], operands[1]);
4304 (define_expand "neon_vreinterpretv2di<mode>"
4305 [(match_operand:V2DI 0 "s_register_operand" "")
4306 (match_operand:VQX 1 "s_register_operand" "")]
4309 neon_reinterpret (operands[0], operands[1]);
4313 (define_expand "vec_load_lanes<mode><mode>"
4314 [(set (match_operand:VDQX 0 "s_register_operand")
4315 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand")]
4319 (define_insn "neon_vld1<mode>"
4320 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
4321 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand" "Um")]
4324 "vld1.<V_sz_elem>\t%h0, %A1"
4325 [(set_attr "neon_type" "neon_vld1_1_2_regs")]
4328 (define_insn "neon_vld1_lane<mode>"
4329 [(set (match_operand:VDX 0 "s_register_operand" "=w")
4330 (unspec:VDX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4331 (match_operand:VDX 2 "s_register_operand" "0")
4332 (match_operand:SI 3 "immediate_operand" "i")]
4336 HOST_WIDE_INT lane = INTVAL (operands[3]);
4337 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4338 if (lane < 0 || lane >= max)
4339 error ("lane out of range");
4341 return "vld1.<V_sz_elem>\t%P0, %A1";
4343 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4345 [(set (attr "neon_type")
4346 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4347 (const_string "neon_vld1_1_2_regs")
4348 (const_string "neon_vld1_vld2_lane")))]
4351 (define_insn "neon_vld1_lane<mode>"
4352 [(set (match_operand:VQX 0 "s_register_operand" "=w")
4353 (unspec:VQX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4354 (match_operand:VQX 2 "s_register_operand" "0")
4355 (match_operand:SI 3 "immediate_operand" "i")]
4359 HOST_WIDE_INT lane = INTVAL (operands[3]);
4360 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4361 int regno = REGNO (operands[0]);
4362 if (lane < 0 || lane >= max)
4363 error ("lane out of range");
4364 else if (lane >= max / 2)
4368 operands[3] = GEN_INT (lane);
4370 operands[0] = gen_rtx_REG (<V_HALF>mode, regno);
4372 return "vld1.<V_sz_elem>\t%P0, %A1";
4374 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4376 [(set (attr "neon_type")
4377 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4378 (const_string "neon_vld1_1_2_regs")
4379 (const_string "neon_vld1_vld2_lane")))]
4382 (define_insn "neon_vld1_dup<mode>"
4383 [(set (match_operand:VDX 0 "s_register_operand" "=w")
4384 (unspec:VDX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")]
4388 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4389 return "vld1.<V_sz_elem>\t{%P0[]}, %A1";
4391 return "vld1.<V_sz_elem>\t%h0, %A1";
4393 [(set (attr "neon_type")
4394 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4395 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4396 (const_string "neon_vld1_1_2_regs")))]
4399 (define_insn "neon_vld1_dup<mode>"
4400 [(set (match_operand:VQX 0 "s_register_operand" "=w")
4401 (unspec:VQX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")]
4405 if (GET_MODE_NUNITS (<MODE>mode) > 2)
4406 return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4408 return "vld1.<V_sz_elem>\t%h0, %A1";
4410 [(set (attr "neon_type")
4411 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4412 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4413 (const_string "neon_vld1_1_2_regs")))]
4416 (define_expand "vec_store_lanes<mode><mode>"
4417 [(set (match_operand:VDQX 0 "neon_struct_operand")
4418 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand")]
4422 (define_insn "neon_vst1<mode>"
4423 [(set (match_operand:VDQX 0 "neon_struct_operand" "=Um")
4424 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")]
4427 "vst1.<V_sz_elem>\t%h1, %A0"
4428 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
4430 (define_insn "neon_vst1_lane<mode>"
4431 [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4432 (vec_select:<V_elem>
4433 (match_operand:VDX 1 "s_register_operand" "w")
4434 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))]
4437 HOST_WIDE_INT lane = INTVAL (operands[2]);
4438 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4439 if (lane < 0 || lane >= max)
4440 error ("lane out of range");
4442 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4444 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4446 [(set (attr "neon_type")
4447 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1))
4448 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4449 (const_string "neon_vst1_vst2_lane")))])
4451 (define_insn "neon_vst1_lane<mode>"
4452 [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4453 (vec_select:<V_elem>
4454 (match_operand:VQX 1 "s_register_operand" "w")
4455 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))]
4458 HOST_WIDE_INT lane = INTVAL (operands[2]);
4459 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4460 int regno = REGNO (operands[1]);
4461 if (lane < 0 || lane >= max)
4462 error ("lane out of range");
4463 else if (lane >= max / 2)
4467 operands[2] = GEN_INT (lane);
4469 operands[1] = gen_rtx_REG (<V_HALF>mode, regno);
4471 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4473 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4475 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4478 (define_expand "vec_load_lanesti<mode>"
4479 [(set (match_operand:TI 0 "s_register_operand")
4480 (unspec:TI [(match_operand:TI 1 "neon_struct_operand")
4481 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4485 (define_insn "neon_vld2<mode>"
4486 [(set (match_operand:TI 0 "s_register_operand" "=w")
4487 (unspec:TI [(match_operand:TI 1 "neon_struct_operand" "Um")
4488 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4492 if (<V_sz_elem> == 64)
4493 return "vld1.64\t%h0, %A1";
4495 return "vld2.<V_sz_elem>\t%h0, %A1";
4497 [(set (attr "neon_type")
4498 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4499 (const_string "neon_vld1_1_2_regs")
4500 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
4503 (define_expand "vec_load_lanesoi<mode>"
4504 [(set (match_operand:OI 0 "s_register_operand")
4505 (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
4506 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4510 (define_insn "neon_vld2<mode>"
4511 [(set (match_operand:OI 0 "s_register_operand" "=w")
4512 (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
4513 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4516 "vld2.<V_sz_elem>\t%h0, %A1"
4517 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
4519 (define_insn "neon_vld2_lane<mode>"
4520 [(set (match_operand:TI 0 "s_register_operand" "=w")
4521 (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4522 (match_operand:TI 2 "s_register_operand" "0")
4523 (match_operand:SI 3 "immediate_operand" "i")
4524 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4528 HOST_WIDE_INT lane = INTVAL (operands[3]);
4529 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4530 int regno = REGNO (operands[0]);
4532 if (lane < 0 || lane >= max)
4533 error ("lane out of range");
4534 ops[0] = gen_rtx_REG (DImode, regno);
4535 ops[1] = gen_rtx_REG (DImode, regno + 2);
4536 ops[2] = operands[1];
4537 ops[3] = operands[3];
4538 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4541 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4544 (define_insn "neon_vld2_lane<mode>"
4545 [(set (match_operand:OI 0 "s_register_operand" "=w")
4546 (unspec:OI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4547 (match_operand:OI 2 "s_register_operand" "0")
4548 (match_operand:SI 3 "immediate_operand" "i")
4549 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4553 HOST_WIDE_INT lane = INTVAL (operands[3]);
4554 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4555 int regno = REGNO (operands[0]);
4557 if (lane < 0 || lane >= max)
4558 error ("lane out of range");
4559 else if (lane >= max / 2)
4564 ops[0] = gen_rtx_REG (DImode, regno);
4565 ops[1] = gen_rtx_REG (DImode, regno + 4);
4566 ops[2] = operands[1];
4567 ops[3] = GEN_INT (lane);
4568 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4571 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4574 (define_insn "neon_vld2_dup<mode>"
4575 [(set (match_operand:TI 0 "s_register_operand" "=w")
4576 (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4577 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4581 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4582 return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4584 return "vld1.<V_sz_elem>\t%h0, %A1";
4586 [(set (attr "neon_type")
4587 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4588 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4589 (const_string "neon_vld1_1_2_regs")))]
4592 (define_expand "vec_store_lanesti<mode>"
4593 [(set (match_operand:TI 0 "neon_struct_operand")
4594 (unspec:TI [(match_operand:TI 1 "s_register_operand")
4595 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4599 (define_insn "neon_vst2<mode>"
4600 [(set (match_operand:TI 0 "neon_struct_operand" "=Um")
4601 (unspec:TI [(match_operand:TI 1 "s_register_operand" "w")
4602 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4606 if (<V_sz_elem> == 64)
4607 return "vst1.64\t%h1, %A0";
4609 return "vst2.<V_sz_elem>\t%h1, %A0";
4611 [(set (attr "neon_type")
4612 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4613 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4614 (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
4617 (define_expand "vec_store_lanesoi<mode>"
4618 [(set (match_operand:OI 0 "neon_struct_operand")
4619 (unspec:OI [(match_operand:OI 1 "s_register_operand")
4620 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4624 (define_insn "neon_vst2<mode>"
4625 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
4626 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
4627 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4630 "vst2.<V_sz_elem>\t%h1, %A0"
4631 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]
4634 (define_insn "neon_vst2_lane<mode>"
4635 [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4636 (unspec:<V_two_elem>
4637 [(match_operand:TI 1 "s_register_operand" "w")
4638 (match_operand:SI 2 "immediate_operand" "i")
4639 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4643 HOST_WIDE_INT lane = INTVAL (operands[2]);
4644 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4645 int regno = REGNO (operands[1]);
4647 if (lane < 0 || lane >= max)
4648 error ("lane out of range");
4649 ops[0] = operands[0];
4650 ops[1] = gen_rtx_REG (DImode, regno);
4651 ops[2] = gen_rtx_REG (DImode, regno + 2);
4652 ops[3] = operands[2];
4653 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4656 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4659 (define_insn "neon_vst2_lane<mode>"
4660 [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4661 (unspec:<V_two_elem>
4662 [(match_operand:OI 1 "s_register_operand" "w")
4663 (match_operand:SI 2 "immediate_operand" "i")
4664 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4668 HOST_WIDE_INT lane = INTVAL (operands[2]);
4669 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4670 int regno = REGNO (operands[1]);
4672 if (lane < 0 || lane >= max)
4673 error ("lane out of range");
4674 else if (lane >= max / 2)
4679 ops[0] = operands[0];
4680 ops[1] = gen_rtx_REG (DImode, regno);
4681 ops[2] = gen_rtx_REG (DImode, regno + 4);
4682 ops[3] = GEN_INT (lane);
4683 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4686 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4689 (define_expand "vec_load_lanesei<mode>"
4690 [(set (match_operand:EI 0 "s_register_operand")
4691 (unspec:EI [(match_operand:EI 1 "neon_struct_operand")
4692 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4696 (define_insn "neon_vld3<mode>"
4697 [(set (match_operand:EI 0 "s_register_operand" "=w")
4698 (unspec:EI [(match_operand:EI 1 "neon_struct_operand" "Um")
4699 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4703 if (<V_sz_elem> == 64)
4704 return "vld1.64\t%h0, %A1";
4706 return "vld3.<V_sz_elem>\t%h0, %A1";
4708 [(set (attr "neon_type")
4709 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4710 (const_string "neon_vld1_1_2_regs")
4711 (const_string "neon_vld3_vld4")))]
4714 (define_expand "vec_load_lanesci<mode>"
4715 [(match_operand:CI 0 "s_register_operand")
4716 (match_operand:CI 1 "neon_struct_operand")
4717 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4720 emit_insn (gen_neon_vld3<mode> (operands[0], operands[1]));
4724 (define_expand "neon_vld3<mode>"
4725 [(match_operand:CI 0 "s_register_operand")
4726 (match_operand:CI 1 "neon_struct_operand")
4727 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4732 mem = adjust_address (operands[1], EImode, 0);
4733 emit_insn (gen_neon_vld3qa<mode> (operands[0], mem));
4734 mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4735 emit_insn (gen_neon_vld3qb<mode> (operands[0], mem, operands[0]));
4739 (define_insn "neon_vld3qa<mode>"
4740 [(set (match_operand:CI 0 "s_register_operand" "=w")
4741 (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4742 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4746 int regno = REGNO (operands[0]);
4748 ops[0] = gen_rtx_REG (DImode, regno);
4749 ops[1] = gen_rtx_REG (DImode, regno + 4);
4750 ops[2] = gen_rtx_REG (DImode, regno + 8);
4751 ops[3] = operands[1];
4752 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4755 [(set_attr "neon_type" "neon_vld3_vld4")]
4758 (define_insn "neon_vld3qb<mode>"
4759 [(set (match_operand:CI 0 "s_register_operand" "=w")
4760 (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4761 (match_operand:CI 2 "s_register_operand" "0")
4762 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4766 int regno = REGNO (operands[0]);
4768 ops[0] = gen_rtx_REG (DImode, regno + 2);
4769 ops[1] = gen_rtx_REG (DImode, regno + 6);
4770 ops[2] = gen_rtx_REG (DImode, regno + 10);
4771 ops[3] = operands[1];
4772 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4775 [(set_attr "neon_type" "neon_vld3_vld4")]
4778 (define_insn "neon_vld3_lane<mode>"
4779 [(set (match_operand:EI 0 "s_register_operand" "=w")
4780 (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
4781 (match_operand:EI 2 "s_register_operand" "0")
4782 (match_operand:SI 3 "immediate_operand" "i")
4783 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4787 HOST_WIDE_INT lane = INTVAL (operands[3]);
4788 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4789 int regno = REGNO (operands[0]);
4791 if (lane < 0 || lane >= max)
4792 error ("lane out of range");
4793 ops[0] = gen_rtx_REG (DImode, regno);
4794 ops[1] = gen_rtx_REG (DImode, regno + 2);
4795 ops[2] = gen_rtx_REG (DImode, regno + 4);
4796 ops[3] = operands[1];
4797 ops[4] = operands[3];
4798 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %A3",
4802 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
4805 (define_insn "neon_vld3_lane<mode>"
4806 [(set (match_operand:CI 0 "s_register_operand" "=w")
4807 (unspec:CI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
4808 (match_operand:CI 2 "s_register_operand" "0")
4809 (match_operand:SI 3 "immediate_operand" "i")
4810 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4814 HOST_WIDE_INT lane = INTVAL (operands[3]);
4815 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4816 int regno = REGNO (operands[0]);
4818 if (lane < 0 || lane >= max)
4819 error ("lane out of range");
4820 else if (lane >= max / 2)
4825 ops[0] = gen_rtx_REG (DImode, regno);
4826 ops[1] = gen_rtx_REG (DImode, regno + 4);
4827 ops[2] = gen_rtx_REG (DImode, regno + 8);
4828 ops[3] = operands[1];
4829 ops[4] = GEN_INT (lane);
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_dup<mode>"
4838 [(set (match_operand:EI 0 "s_register_operand" "=w")
4839 (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
4840 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4844 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4846 int regno = REGNO (operands[0]);
4848 ops[0] = gen_rtx_REG (DImode, regno);
4849 ops[1] = gen_rtx_REG (DImode, regno + 2);
4850 ops[2] = gen_rtx_REG (DImode, regno + 4);
4851 ops[3] = operands[1];
4852 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[], %P1[], %P2[]}, %A3", ops);
4856 return "vld1.<V_sz_elem>\t%h0, %A1";
4858 [(set (attr "neon_type")
4859 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4860 (const_string "neon_vld3_vld4_all_lanes")
4861 (const_string "neon_vld1_1_2_regs")))])
4863 (define_expand "vec_store_lanesei<mode>"
4864 [(set (match_operand:EI 0 "neon_struct_operand")
4865 (unspec:EI [(match_operand:EI 1 "s_register_operand")
4866 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4870 (define_insn "neon_vst3<mode>"
4871 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4872 (unspec:EI [(match_operand:EI 1 "s_register_operand" "w")
4873 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4877 if (<V_sz_elem> == 64)
4878 return "vst1.64\t%h1, %A0";
4880 return "vst3.<V_sz_elem>\t%h1, %A0";
4882 [(set (attr "neon_type")
4883 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4884 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4885 (const_string "neon_vst2_4_regs_vst3_vst4")))])
4887 (define_expand "vec_store_lanesci<mode>"
4888 [(match_operand:CI 0 "neon_struct_operand")
4889 (match_operand:CI 1 "s_register_operand")
4890 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4893 emit_insn (gen_neon_vst3<mode> (operands[0], operands[1]));
4897 (define_expand "neon_vst3<mode>"
4898 [(match_operand:CI 0 "neon_struct_operand")
4899 (match_operand:CI 1 "s_register_operand")
4900 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4905 mem = adjust_address (operands[0], EImode, 0);
4906 emit_insn (gen_neon_vst3qa<mode> (mem, operands[1]));
4907 mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4908 emit_insn (gen_neon_vst3qb<mode> (mem, operands[1]));
4912 (define_insn "neon_vst3qa<mode>"
4913 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4914 (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
4915 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4919 int regno = REGNO (operands[1]);
4921 ops[0] = operands[0];
4922 ops[1] = gen_rtx_REG (DImode, regno);
4923 ops[2] = gen_rtx_REG (DImode, regno + 4);
4924 ops[3] = gen_rtx_REG (DImode, regno + 8);
4925 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
4928 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
4931 (define_insn "neon_vst3qb<mode>"
4932 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4933 (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
4934 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4938 int regno = REGNO (operands[1]);
4940 ops[0] = operands[0];
4941 ops[1] = gen_rtx_REG (DImode, regno + 2);
4942 ops[2] = gen_rtx_REG (DImode, regno + 6);
4943 ops[3] = gen_rtx_REG (DImode, regno + 10);
4944 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
4947 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
4950 (define_insn "neon_vst3_lane<mode>"
4951 [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
4952 (unspec:<V_three_elem>
4953 [(match_operand:EI 1 "s_register_operand" "w")
4954 (match_operand:SI 2 "immediate_operand" "i")
4955 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4959 HOST_WIDE_INT lane = INTVAL (operands[2]);
4960 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4961 int regno = REGNO (operands[1]);
4963 if (lane < 0 || lane >= max)
4964 error ("lane out of range");
4965 ops[0] = operands[0];
4966 ops[1] = gen_rtx_REG (DImode, regno);
4967 ops[2] = gen_rtx_REG (DImode, regno + 2);
4968 ops[3] = gen_rtx_REG (DImode, regno + 4);
4969 ops[4] = operands[2];
4970 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %A0",
4974 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
4977 (define_insn "neon_vst3_lane<mode>"
4978 [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
4979 (unspec:<V_three_elem>
4980 [(match_operand:CI 1 "s_register_operand" "w")
4981 (match_operand:SI 2 "immediate_operand" "i")
4982 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4986 HOST_WIDE_INT lane = INTVAL (operands[2]);
4987 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4988 int regno = REGNO (operands[1]);
4990 if (lane < 0 || lane >= max)
4991 error ("lane out of range");
4992 else if (lane >= max / 2)
4997 ops[0] = operands[0];
4998 ops[1] = gen_rtx_REG (DImode, regno);
4999 ops[2] = gen_rtx_REG (DImode, regno + 4);
5000 ops[3] = gen_rtx_REG (DImode, regno + 8);
5001 ops[4] = GEN_INT (lane);
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")])
5008 (define_expand "vec_load_lanesoi<mode>"
5009 [(set (match_operand:OI 0 "s_register_operand")
5010 (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
5011 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5015 (define_insn "neon_vld4<mode>"
5016 [(set (match_operand:OI 0 "s_register_operand" "=w")
5017 (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
5018 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5022 if (<V_sz_elem> == 64)
5023 return "vld1.64\t%h0, %A1";
5025 return "vld4.<V_sz_elem>\t%h0, %A1";
5027 [(set (attr "neon_type")
5028 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5029 (const_string "neon_vld1_1_2_regs")
5030 (const_string "neon_vld3_vld4")))]
5033 (define_expand "vec_load_lanesxi<mode>"
5034 [(match_operand:XI 0 "s_register_operand")
5035 (match_operand:XI 1 "neon_struct_operand")
5036 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5039 emit_insn (gen_neon_vld4<mode> (operands[0], operands[1]));
5043 (define_expand "neon_vld4<mode>"
5044 [(match_operand:XI 0 "s_register_operand")
5045 (match_operand:XI 1 "neon_struct_operand")
5046 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5051 mem = adjust_address (operands[1], OImode, 0);
5052 emit_insn (gen_neon_vld4qa<mode> (operands[0], mem));
5053 mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5054 emit_insn (gen_neon_vld4qb<mode> (operands[0], mem, operands[0]));
5058 (define_insn "neon_vld4qa<mode>"
5059 [(set (match_operand:XI 0 "s_register_operand" "=w")
5060 (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5061 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5065 int regno = REGNO (operands[0]);
5067 ops[0] = gen_rtx_REG (DImode, regno);
5068 ops[1] = gen_rtx_REG (DImode, regno + 4);
5069 ops[2] = gen_rtx_REG (DImode, regno + 8);
5070 ops[3] = gen_rtx_REG (DImode, regno + 12);
5071 ops[4] = operands[1];
5072 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5075 [(set_attr "neon_type" "neon_vld3_vld4")]
5078 (define_insn "neon_vld4qb<mode>"
5079 [(set (match_operand:XI 0 "s_register_operand" "=w")
5080 (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5081 (match_operand:XI 2 "s_register_operand" "0")
5082 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5086 int regno = REGNO (operands[0]);
5088 ops[0] = gen_rtx_REG (DImode, regno + 2);
5089 ops[1] = gen_rtx_REG (DImode, regno + 6);
5090 ops[2] = gen_rtx_REG (DImode, regno + 10);
5091 ops[3] = gen_rtx_REG (DImode, regno + 14);
5092 ops[4] = operands[1];
5093 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5096 [(set_attr "neon_type" "neon_vld3_vld4")]
5099 (define_insn "neon_vld4_lane<mode>"
5100 [(set (match_operand:OI 0 "s_register_operand" "=w")
5101 (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5102 (match_operand:OI 2 "s_register_operand" "0")
5103 (match_operand:SI 3 "immediate_operand" "i")
5104 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5108 HOST_WIDE_INT lane = INTVAL (operands[3]);
5109 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5110 int regno = REGNO (operands[0]);
5112 if (lane < 0 || lane >= max)
5113 error ("lane out of range");
5114 ops[0] = gen_rtx_REG (DImode, regno);
5115 ops[1] = gen_rtx_REG (DImode, regno + 2);
5116 ops[2] = gen_rtx_REG (DImode, regno + 4);
5117 ops[3] = gen_rtx_REG (DImode, regno + 6);
5118 ops[4] = operands[1];
5119 ops[5] = operands[3];
5120 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5124 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5127 (define_insn "neon_vld4_lane<mode>"
5128 [(set (match_operand:XI 0 "s_register_operand" "=w")
5129 (unspec:XI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5130 (match_operand:XI 2 "s_register_operand" "0")
5131 (match_operand:SI 3 "immediate_operand" "i")
5132 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5136 HOST_WIDE_INT lane = INTVAL (operands[3]);
5137 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5138 int regno = REGNO (operands[0]);
5140 if (lane < 0 || lane >= max)
5141 error ("lane out of range");
5142 else if (lane >= max / 2)
5147 ops[0] = gen_rtx_REG (DImode, regno);
5148 ops[1] = gen_rtx_REG (DImode, regno + 4);
5149 ops[2] = gen_rtx_REG (DImode, regno + 8);
5150 ops[3] = gen_rtx_REG (DImode, regno + 12);
5151 ops[4] = operands[1];
5152 ops[5] = GEN_INT (lane);
5153 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5157 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5160 (define_insn "neon_vld4_dup<mode>"
5161 [(set (match_operand:OI 0 "s_register_operand" "=w")
5162 (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5163 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5167 if (GET_MODE_NUNITS (<MODE>mode) > 1)
5169 int regno = REGNO (operands[0]);
5171 ops[0] = gen_rtx_REG (DImode, regno);
5172 ops[1] = gen_rtx_REG (DImode, regno + 2);
5173 ops[2] = gen_rtx_REG (DImode, regno + 4);
5174 ops[3] = gen_rtx_REG (DImode, regno + 6);
5175 ops[4] = operands[1];
5176 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[], %P1[], %P2[], %P3[]}, %A4",
5181 return "vld1.<V_sz_elem>\t%h0, %A1";
5183 [(set (attr "neon_type")
5184 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
5185 (const_string "neon_vld3_vld4_all_lanes")
5186 (const_string "neon_vld1_1_2_regs")))]
5189 (define_expand "vec_store_lanesoi<mode>"
5190 [(set (match_operand:OI 0 "neon_struct_operand")
5191 (unspec:OI [(match_operand:OI 1 "s_register_operand")
5192 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5196 (define_insn "neon_vst4<mode>"
5197 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5198 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
5199 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5203 if (<V_sz_elem> == 64)
5204 return "vst1.64\t%h1, %A0";
5206 return "vst4.<V_sz_elem>\t%h1, %A0";
5208 [(set (attr "neon_type")
5209 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5210 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5211 (const_string "neon_vst2_4_regs_vst3_vst4")))]
5214 (define_expand "vec_store_lanesxi<mode>"
5215 [(match_operand:XI 0 "neon_struct_operand")
5216 (match_operand:XI 1 "s_register_operand")
5217 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5220 emit_insn (gen_neon_vst4<mode> (operands[0], operands[1]));
5224 (define_expand "neon_vst4<mode>"
5225 [(match_operand:XI 0 "neon_struct_operand")
5226 (match_operand:XI 1 "s_register_operand")
5227 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5232 mem = adjust_address (operands[0], OImode, 0);
5233 emit_insn (gen_neon_vst4qa<mode> (mem, operands[1]));
5234 mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5235 emit_insn (gen_neon_vst4qb<mode> (mem, operands[1]));
5239 (define_insn "neon_vst4qa<mode>"
5240 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5241 (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5242 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5246 int regno = REGNO (operands[1]);
5248 ops[0] = operands[0];
5249 ops[1] = gen_rtx_REG (DImode, regno);
5250 ops[2] = gen_rtx_REG (DImode, regno + 4);
5251 ops[3] = gen_rtx_REG (DImode, regno + 8);
5252 ops[4] = gen_rtx_REG (DImode, regno + 12);
5253 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5256 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5259 (define_insn "neon_vst4qb<mode>"
5260 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5261 (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5262 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5266 int regno = REGNO (operands[1]);
5268 ops[0] = operands[0];
5269 ops[1] = gen_rtx_REG (DImode, regno + 2);
5270 ops[2] = gen_rtx_REG (DImode, regno + 6);
5271 ops[3] = gen_rtx_REG (DImode, regno + 10);
5272 ops[4] = gen_rtx_REG (DImode, regno + 14);
5273 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5276 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5279 (define_insn "neon_vst4_lane<mode>"
5280 [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5281 (unspec:<V_four_elem>
5282 [(match_operand:OI 1 "s_register_operand" "w")
5283 (match_operand:SI 2 "immediate_operand" "i")
5284 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5288 HOST_WIDE_INT lane = INTVAL (operands[2]);
5289 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5290 int regno = REGNO (operands[1]);
5292 if (lane < 0 || lane >= max)
5293 error ("lane out of range");
5294 ops[0] = operands[0];
5295 ops[1] = gen_rtx_REG (DImode, regno);
5296 ops[2] = gen_rtx_REG (DImode, regno + 2);
5297 ops[3] = gen_rtx_REG (DImode, regno + 4);
5298 ops[4] = gen_rtx_REG (DImode, regno + 6);
5299 ops[5] = operands[2];
5300 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5304 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5307 (define_insn "neon_vst4_lane<mode>"
5308 [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5309 (unspec:<V_four_elem>
5310 [(match_operand:XI 1 "s_register_operand" "w")
5311 (match_operand:SI 2 "immediate_operand" "i")
5312 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5316 HOST_WIDE_INT lane = INTVAL (operands[2]);
5317 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5318 int regno = REGNO (operands[1]);
5320 if (lane < 0 || lane >= max)
5321 error ("lane out of range");
5322 else if (lane >= max / 2)
5327 ops[0] = operands[0];
5328 ops[1] = gen_rtx_REG (DImode, regno);
5329 ops[2] = gen_rtx_REG (DImode, regno + 4);
5330 ops[3] = gen_rtx_REG (DImode, regno + 8);
5331 ops[4] = gen_rtx_REG (DImode, regno + 12);
5332 ops[5] = GEN_INT (lane);
5333 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5337 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5340 (define_expand "neon_vand<mode>"
5341 [(match_operand:VDQX 0 "s_register_operand" "")
5342 (match_operand:VDQX 1 "s_register_operand" "")
5343 (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5344 (match_operand:SI 3 "immediate_operand" "")]
5347 emit_insn (gen_and<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
5351 (define_expand "neon_vorr<mode>"
5352 [(match_operand:VDQX 0 "s_register_operand" "")
5353 (match_operand:VDQX 1 "s_register_operand" "")
5354 (match_operand:VDQX 2 "neon_logic_op2" "")
5355 (match_operand:SI 3 "immediate_operand" "")]
5358 emit_insn (gen_ior<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
5362 (define_expand "neon_veor<mode>"
5363 [(match_operand:VDQX 0 "s_register_operand" "")
5364 (match_operand:VDQX 1 "s_register_operand" "")
5365 (match_operand:VDQX 2 "s_register_operand" "")
5366 (match_operand:SI 3 "immediate_operand" "")]
5369 emit_insn (gen_xor<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
5373 (define_expand "neon_vbic<mode>"
5374 [(match_operand:VDQX 0 "s_register_operand" "")
5375 (match_operand:VDQX 1 "s_register_operand" "")
5376 (match_operand:VDQX 2 "neon_logic_op2" "")
5377 (match_operand:SI 3 "immediate_operand" "")]
5380 emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2]));
5384 (define_expand "neon_vorn<mode>"
5385 [(match_operand:VDQX 0 "s_register_operand" "")
5386 (match_operand:VDQX 1 "s_register_operand" "")
5387 (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5388 (match_operand:SI 3 "immediate_operand" "")]
5391 emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2]));
5395 (define_insn "neon_vec_unpack<US>_lo_<mode>"
5396 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5397 (SE:<V_unpack> (vec_select:<V_HALF>
5398 (match_operand:VU 1 "register_operand" "w")
5399 (match_operand:VU 2 "vect_par_constant_low" ""))))]
5400 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5401 "vmovl.<US><V_sz_elem> %q0, %e1"
5402 [(set_attr "neon_type" "neon_shift_1")]
5405 (define_insn "neon_vec_unpack<US>_hi_<mode>"
5406 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5407 (SE:<V_unpack> (vec_select:<V_HALF>
5408 (match_operand:VU 1 "register_operand" "w")
5409 (match_operand:VU 2 "vect_par_constant_high" ""))))]
5410 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5411 "vmovl.<US><V_sz_elem> %q0, %f1"
5412 [(set_attr "neon_type" "neon_shift_1")]
5415 (define_expand "vec_unpack<US>_hi_<mode>"
5416 [(match_operand:<V_unpack> 0 "register_operand" "")
5417 (SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
5418 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5420 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5423 for (i = 0; i < (<V_mode_nunits>/2); i++)
5424 RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
5426 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5427 emit_insn (gen_neon_vec_unpack<US>_hi_<mode> (operands[0],
5434 (define_expand "vec_unpack<US>_lo_<mode>"
5435 [(match_operand:<V_unpack> 0 "register_operand" "")
5436 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))]
5437 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5439 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5442 for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5443 RTVEC_ELT (v, i) = GEN_INT (i);
5444 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5445 emit_insn (gen_neon_vec_unpack<US>_lo_<mode> (operands[0],
5452 (define_insn "neon_vec_<US>mult_lo_<mode>"
5453 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5454 (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5455 (match_operand:VU 1 "register_operand" "w")
5456 (match_operand:VU 2 "vect_par_constant_low" "")))
5457 (SE:<V_unpack> (vec_select:<V_HALF>
5458 (match_operand:VU 3 "register_operand" "w")
5460 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5461 "vmull.<US><V_sz_elem> %q0, %e1, %e3"
5462 [(set_attr "neon_type" "neon_shift_1")]
5465 (define_expand "vec_widen_<US>mult_lo_<mode>"
5466 [(match_operand:<V_unpack> 0 "register_operand" "")
5467 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5468 (SE:<V_unpack> (match_operand:VU 2 "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);
5478 emit_insn (gen_neon_vec_<US>mult_lo_<mode> (operands[0],
5486 (define_insn "neon_vec_<US>mult_hi_<mode>"
5487 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5488 (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5489 (match_operand:VU 1 "register_operand" "w")
5490 (match_operand:VU 2 "vect_par_constant_high" "")))
5491 (SE:<V_unpack> (vec_select:<V_HALF>
5492 (match_operand:VU 3 "register_operand" "w")
5494 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5495 "vmull.<US><V_sz_elem> %q0, %f1, %f3"
5496 [(set_attr "neon_type" "neon_shift_1")]
5499 (define_expand "vec_widen_<US>mult_hi_<mode>"
5500 [(match_operand:<V_unpack> 0 "register_operand" "")
5501 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5502 (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
5503 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5505 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5508 for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5509 RTVEC_ELT (v, i) = GEN_INT (<V_mode_nunits>/2 + i);
5510 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5512 emit_insn (gen_neon_vec_<US>mult_hi_<mode> (operands[0],
5521 (define_insn "neon_vec_<US>shiftl_<mode>"
5522 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5523 (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
5524 (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
5527 return "vshll.<US><V_sz_elem> %q0, %P1, %2";
5529 [(set_attr "neon_type" "neon_shift_1")]
5532 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5533 [(match_operand:<V_unpack> 0 "register_operand" "")
5534 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5535 (match_operand:SI 2 "immediate_operand" "i")]
5536 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5538 emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5539 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
5545 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5546 [(match_operand:<V_unpack> 0 "register_operand" "")
5547 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5548 (match_operand:SI 2 "immediate_operand" "i")]
5549 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5551 emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5552 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
5553 GET_MODE_SIZE (<V_HALF>mode)),
5559 ;; Vectorize for non-neon-quad case
5560 (define_insn "neon_unpack<US>_<mode>"
5561 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5562 (SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
5564 "vmovl.<US><V_sz_elem> %q0, %P1"
5565 [(set_attr "neon_type" "neon_shift_1")]
5568 (define_expand "vec_unpack<US>_lo_<mode>"
5569 [(match_operand:<V_double_width> 0 "register_operand" "")
5570 (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5573 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5574 emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5575 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5581 (define_expand "vec_unpack<US>_hi_<mode>"
5582 [(match_operand:<V_double_width> 0 "register_operand" "")
5583 (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5586 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5587 emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5588 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5594 (define_insn "neon_vec_<US>mult_<mode>"
5595 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5596 (mult:<V_widen> (SE:<V_widen>
5597 (match_operand:VDI 1 "register_operand" "w"))
5599 (match_operand:VDI 2 "register_operand" "w"))))]
5601 "vmull.<US><V_sz_elem> %q0, %P1, %P2"
5602 [(set_attr "neon_type" "neon_shift_1")]
5605 (define_expand "vec_widen_<US>mult_hi_<mode>"
5606 [(match_operand:<V_double_width> 0 "register_operand" "")
5607 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5608 (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5611 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5612 emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5613 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5620 (define_expand "vec_widen_<US>mult_lo_<mode>"
5621 [(match_operand:<V_double_width> 0 "register_operand" "")
5622 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5623 (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5626 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5627 emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5628 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5635 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5636 [(match_operand:<V_double_width> 0 "register_operand" "")
5637 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5638 (match_operand:SI 2 "immediate_operand" "i")]
5641 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5642 emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5643 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5649 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5650 [(match_operand:<V_double_width> 0 "register_operand" "")
5651 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5652 (match_operand:SI 2 "immediate_operand" "i")]
5655 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5656 emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5657 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5663 ; FIXME: These instruction patterns can't be used safely in big-endian mode
5664 ; because the ordering of vector elements in Q registers is different from what
5665 ; the semantics of the instructions require.
5667 (define_insn "vec_pack_trunc_<mode>"
5668 [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
5669 (vec_concat:<V_narrow_pack>
5670 (truncate:<V_narrow>
5671 (match_operand:VN 1 "register_operand" "w"))
5672 (truncate:<V_narrow>
5673 (match_operand:VN 2 "register_operand" "w"))))]
5674 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5675 "vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
5676 [(set_attr "neon_type" "neon_shift_1")
5677 (set_attr "length" "8")]
5680 ;; For the non-quad case.
5681 (define_insn "neon_vec_pack_trunc_<mode>"
5682 [(set (match_operand:<V_narrow> 0 "register_operand" "=w")
5683 (truncate:<V_narrow> (match_operand:VN 1 "register_operand" "w")))]
5684 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5685 "vmovn.i<V_sz_elem>\t%P0, %q1"
5686 [(set_attr "neon_type" "neon_shift_1")]
5689 (define_expand "vec_pack_trunc_<mode>"
5690 [(match_operand:<V_narrow_pack> 0 "register_operand" "")
5691 (match_operand:VSHFT 1 "register_operand" "")
5692 (match_operand:VSHFT 2 "register_operand")]
5693 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5695 rtx tempreg = gen_reg_rtx (<V_DOUBLE>mode);
5697 emit_insn (gen_move_lo_quad_<V_double> (tempreg, operands[1]));
5698 emit_insn (gen_move_hi_quad_<V_double> (tempreg, operands[2]));
5699 emit_insn (gen_neon_vec_pack_trunc_<V_double> (operands[0], tempreg));
5703 (define_insn "neon_vabd<mode>_2"
5704 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5705 (abs:VDQ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
5706 (match_operand:VDQ 2 "s_register_operand" "w"))))]
5707 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5708 "vabd.<V_s_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5709 [(set (attr "neon_type")
5710 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5711 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5712 (const_string "neon_fp_vadd_ddd_vabs_dd")
5713 (const_string "neon_fp_vadd_qqq_vabs_qq"))
5714 (const_string "neon_int_5")))]
5717 (define_insn "neon_vabd<mode>_3"
5718 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5719 (abs:VDQ (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
5720 (match_operand:VDQ 2 "s_register_operand" "w")]
5722 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5723 "vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5724 [(set (attr "neon_type")
5725 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5726 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5727 (const_string "neon_fp_vadd_ddd_vabs_dd")
5728 (const_string "neon_fp_vadd_qqq_vabs_qq"))
5729 (const_string "neon_int_5")))]