1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C)
2009-
2019 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version
3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
88 (LAST_SAVED_REGNUM
63)
92 ;; Defined only to make the DWARF description simpler.
110 ;; Scratch register used by stack clash protection to calculate
111 ;; SVE CFA offsets during probing.
112 (STACK_CLASH_SVE_CFA_REGNUM
11)
113 ;; Scratch registers for prologue/epilogue use.
116 ;; A couple of call-clobbered registers that we need to reserve when
117 ;; tracking speculation this is not ABI, so is subject to change.
118 (SPECULATION_SCRATCH_REGNUM
14)
119 (SPECULATION_TRACKER_REGNUM
15)
120 ;; Scratch registers used in frame layout.
128 (define_c_enum "unspec" [
156 UNSPEC_GOTSMALLPIC28K
238 UNSPEC_SPECULATION_TRACKER
240 UNSPEC_TTEST ; Represent transaction test.
243 (define_c_enum "unspecv" [
244 UNSPECV_EH_RETURN ; Represent EH_RETURN
245 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
246 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
247 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
248 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
249 UNSPECV_BLOCKAGE ; Represent a blockage
250 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
251 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
252 UNSPECV_BTI_NOARG ; Represent BTI.
253 UNSPECV_BTI_C ; Represent BTI c.
254 UNSPECV_BTI_J ; Represent BTI j.
255 UNSPECV_BTI_JC ; Represent BTI jc.
256 UNSPECV_TSTART ; Represent transaction start.
257 UNSPECV_TCOMMIT ; Represent transaction commit.
258 UNSPECV_TCANCEL ; Represent transaction cancel.
262 ;; If further include files are added the defintion of MD_INCLUDES
265 (include "constraints.md")
266 (include "predicates.md")
267 (include "iterators.md")
269 ;; -------------------------------------------------------------------
270 ;; Instruction types and attributes
271 ;; -------------------------------------------------------------------
273 ; The "type" attribute is included here from AArch32 backend to be able
274 ; to share pipeline descriptions.
275 (include "../arm/types.md")
277 ;; It is important to set the fp or simd attributes to yes when a pattern
278 ;; alternative uses the FP or SIMD register files, usually signified by use of
279 ;; the 'w' constraint. This will ensure that the alternative will be
280 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
281 ;; architecture extensions. If all the alternatives in a pattern use the
282 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
285 ;; Attributes of the architecture required to support the instruction (or
286 ;; alternative). This attribute is used to compute attribute "enabled", use type
287 ;; "any" to enable an alternative in all cases.
289 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
291 (define_enum_attr "arch" "arches" (const_string "any"))
293 ;; [For compatibility with Arm in pipeline models]
294 ;; Attribute that specifies whether or not the instruction touches fp
296 ;; Note that this attribute is not used anywhere in either the arm or aarch64
297 ;; backends except in the scheduling description for xgene1. In that
298 ;; scheduling description this attribute is used to subclass the load_4 and
300 (define_attr "fp" "no,yes"
302 (eq_attr "arch" "fp")
304 (const_string "no")))
306 (define_attr "arch_enabled" "no,yes"
309 (eq_attr "arch" "any")
311 (and (eq_attr "arch" "rcpc8_4")
312 (match_test "AARCH64_ISA_RCPC8_4"))
314 (and (eq_attr "arch" "fp")
315 (match_test "TARGET_FLOAT"))
317 (and (eq_attr "arch" "simd")
318 (match_test "TARGET_SIMD"))
320 (and (eq_attr "arch" "fp16")
321 (match_test "TARGET_FP_F16INST"))
323 (and (eq_attr "arch" "sve")
324 (match_test "TARGET_SVE")))
326 (const_string "no")))
328 ;; Attribute that controls whether an alternative is enabled or not.
329 ;; Currently it is only used to disable alternatives which touch fp or simd
330 ;; registers when -mgeneral-regs-only is specified or to require a special
331 ;; architecture support.
332 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
334 ;; Attribute that specifies whether we are dealing with a branch to a
335 ;; label that is far away, i.e. further away than the maximum/minimum
336 ;; representable in a signed
21-bits number.
339 (define_attr "far_branch" "" (const_int
0))
341 ;; Attribute that specifies whether the alternative uses MOVPRFX.
342 (define_attr "movprfx" "no,yes" (const_string "no"))
344 (define_attr "length" ""
345 (cond [(eq_attr "movprfx" "yes")
349 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
350 ;; no predicated insns.
351 (define_attr "predicated" "yes,no" (const_string "no"))
353 ;; Set to true on an insn that requires the speculation tracking state to be
354 ;; in the tracking register before the insn issues. Otherwise the compiler
355 ;; may chose to hold the tracking state encoded in SP.
356 (define_attr "speculation_barrier" "true,false" (const_string "false"))
358 ;; -------------------------------------------------------------------
359 ;; Pipeline descriptions and scheduling
360 ;; -------------------------------------------------------------------
363 (include "aarch64-tune.md")
366 (include "../arm/cortex-a53.md")
367 (include "../arm/cortex-a57.md")
368 (include "../arm/exynos-m1.md")
369 (include "falkor.md")
370 (include "saphira.md")
371 (include "thunderx.md")
372 (include "../arm/xgene1.md")
373 (include "thunderx2t99.md")
374 (include "tsv110.md")
376 ;; -------------------------------------------------------------------
377 ;; Jumps and other miscellaneous insns
378 ;; -------------------------------------------------------------------
380 (define_insn "indirect_jump"
381 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
384 [(set_attr "type" "branch")]
388 [(set (pc) (label_ref (match_operand
0 "" "")))]
391 [(set_attr "type" "branch")]
394 (define_expand "cbranch<mode>
4"
395 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
396 [(match_operand:GPI
1 "register_operand")
397 (match_operand:GPI
2 "aarch64_plus_operand")])
398 (label_ref (match_operand
3 "" ""))
402 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
404 operands[
2] = const0_rtx;
408 (define_expand "cbranch<mode>
4"
409 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
410 [(match_operand:GPF
1 "register_operand")
411 (match_operand:GPF
2 "aarch64_fp_compare_operand")])
412 (label_ref (match_operand
3 "" ""))
416 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
418 operands[
2] = const0_rtx;
422 (define_expand "cbranchcc4"
423 [(set (pc) (if_then_else
424 (match_operator
0 "aarch64_comparison_operator"
425 [(match_operand
1 "cc_register")
426 (match_operand
2 "const0_operand")])
427 (label_ref (match_operand
3 "" ""))
432 (define_insn "ccmp<mode>"
433 [(set (match_operand:CC
1 "cc_register" "")
435 (match_operator
4 "aarch64_comparison_operator"
436 [(match_operand
0 "cc_register" "")
439 (match_operand:GPI
2 "register_operand" "r,r,r")
440 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
441 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
444 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
445 ccmp
\\t%<w>
2, %
3, %k5, %m4
446 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
447 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
450 (define_insn "fccmp<mode>"
451 [(set (match_operand:CCFP
1 "cc_register" "")
453 (match_operator
4 "aarch64_comparison_operator"
454 [(match_operand
0 "cc_register" "")
457 (match_operand:GPF
2 "register_operand" "w")
458 (match_operand:GPF
3 "register_operand" "w"))
459 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
461 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
462 [(set_attr "type" "fccmp<s>")]
465 (define_insn "fccmpe<mode>"
466 [(set (match_operand:CCFPE
1 "cc_register" "")
468 (match_operator
4 "aarch64_comparison_operator"
469 [(match_operand
0 "cc_register" "")
472 (match_operand:GPF
2 "register_operand" "w")
473 (match_operand:GPF
3 "register_operand" "w"))
474 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
476 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
477 [(set_attr "type" "fccmp<s>")]
480 ;; Expansion of signed mod by a power of
2 using CSNEG.
481 ;; For x0 % n where n is a power of
2 produce:
483 ;; and x0, x0, #(n -
1)
484 ;; and x1, x1, #(n -
1)
485 ;; csneg x0, x0, x1, mi
487 (define_expand "mod<mode>
3"
488 [(match_operand:GPI
0 "register_operand")
489 (match_operand:GPI
1 "register_operand")
490 (match_operand:GPI
2 "const_int_operand")]
493 HOST_WIDE_INT val = INTVAL (operands[
2]);
496 || exact_log2 (val) <=
0
497 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
500 rtx mask = GEN_INT (val -
1);
502 /* In the special case of x0 %
2 we can do the even shorter:
508 rtx masked = gen_reg_rtx (<MODE>mode);
509 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
510 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
511 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
512 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
516 rtx neg_op = gen_reg_rtx (<MODE>mode);
517 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
519 /* Extract the condition register and mode. */
520 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
521 rtx cc_reg = SET_DEST (cmp);
522 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
524 rtx masked_pos = gen_reg_rtx (<MODE>mode);
525 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
527 rtx masked_neg = gen_reg_rtx (<MODE>mode);
528 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
530 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
531 masked_neg, masked_pos));
536 (define_insn "condjump"
537 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
538 [(match_operand
1 "cc_register" "") (const_int
0)])
539 (label_ref (match_operand
2 "" ""))
543 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
544 but the "." is required for SVE conditions. */
545 bool use_dot_p = GET_MODE (operands[
1]) == CC_NZCmode;
546 if (get_attr_length (insn) ==
8)
547 return aarch64_gen_far_branch (operands,
2, "Lbcond",
548 use_dot_p ? "b.%M0
\\t" : "b%M0
\\t");
550 return use_dot_p ? "b.%m0
\\t%l2" : "b%m0
\\t%l2";
552 [(set_attr "type" "branch")
554 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
555 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
558 (set (attr "far_branch")
559 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
560 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
565 ;; For a
24-bit immediate CST we can optimize the compare for equality
566 ;; and branch sequence from:
568 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
572 ;; sub x0, x1, #(CST &
0xfff000)
573 ;; subs x0, x0, #(CST &
0x000fff)
575 (define_insn_and_split "*compare_condjump<GPI:mode>"
576 [(set (pc) (if_then_else (EQL
577 (match_operand:GPI
0 "register_operand" "r")
578 (match_operand:GPI
1 "aarch64_imm24" "n"))
579 (label_ref:P (match_operand
2 "" ""))
581 "!aarch64_move_imm (INTVAL (operands[
1]), <GPI:MODE>mode)
582 && !aarch64_plus_operand (operands[
1], <GPI:MODE>mode)
583 && !reload_completed"
588 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
589 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
590 rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
591 emit_insn (gen_add<GPI:mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
592 emit_insn (gen_add<GPI:mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
593 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
594 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
596 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
601 (define_expand "casesi"
602 [(match_operand:SI
0 "register_operand") ; Index
603 (match_operand:SI
1 "const_int_operand") ; Lower bound
604 (match_operand:SI
2 "const_int_operand") ; Total range
605 (match_operand:DI
3 "" "") ; Table label
606 (match_operand:DI
4 "" "")] ; Out of range label
609 if (operands[
1] != const0_rtx)
611 rtx reg = gen_reg_rtx (SImode);
613 /* Canonical RTL says that if you have:
617 then this should be emitted as:
621 The use of trunc_int_for_mode ensures that the resulting
622 constant can be represented in SImode, this is important
623 for the corner case where operand[
1] is INT_MIN. */
625 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
627 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
628 (operands[
1], SImode))
629 operands[
1] = force_reg (SImode, operands[
1]);
630 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
634 if (!aarch64_plus_operand (operands[
2], SImode))
635 operands[
2] = force_reg (SImode, operands[
2]);
636 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
638 operands[
0], operands[
2], operands[
4]));
640 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
642 = gen_rtx_UNSPEC (Pmode, gen_rtvec (
2, operands[
2], operands[
0]),
644 operands[
2] = gen_rtx_MEM (DImode, operands[
2]);
645 MEM_READONLY_P (operands[
2]) =
1;
646 MEM_NOTRAP_P (operands[
2]) =
1;
647 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
3]));
652 (define_expand "casesi_dispatch"
654 [(set (pc) (match_operand:DI
0 ""))
655 (clobber (reg:CC CC_REGNUM))
656 (clobber (match_scratch:DI
2))
657 (clobber (match_scratch:DI
3))
658 (use (label_ref:DI (match_operand
1 "")))])]
661 (define_insn "*casesi_dispatch"
664 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
665 (match_operand:SI
1 "register_operand" "r")]
667 (clobber (reg:CC CC_REGNUM))
668 (clobber (match_scratch:DI
3 "=r"))
669 (clobber (match_scratch:DI
4 "=r"))
670 (use (label_ref:DI (match_operand
2 "" "")))])]
673 return aarch64_output_casesi (operands);
675 [(set_attr "length" "
16")
676 (set_attr "type" "branch")]
680 [(unspec[(const_int
0)] UNSPEC_NOP)]
683 [(set_attr "type" "no_insn")]
686 (define_insn "prefetch"
687 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
688 (match_operand:QI
1 "const_int_operand" "")
689 (match_operand:QI
2 "const_int_operand" ""))]
692 const char * pftype[
2][
4] =
694 {"prfm
\\tPLDL1STRM, %
0",
695 "prfm
\\tPLDL3KEEP, %
0",
696 "prfm
\\tPLDL2KEEP, %
0",
697 "prfm
\\tPLDL1KEEP, %
0"},
698 {"prfm
\\tPSTL1STRM, %
0",
699 "prfm
\\tPSTL3KEEP, %
0",
700 "prfm
\\tPSTL2KEEP, %
0",
701 "prfm
\\tPSTL1KEEP, %
0"},
704 int locality = INTVAL (operands[
2]);
706 gcc_assert (IN_RANGE (locality,
0,
3));
708 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
709 the address into a DImode MEM so that aarch64_print_operand knows
711 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
712 return pftype[INTVAL(operands[
1])][locality];
714 [(set_attr "type" "load_4")]
718 [(trap_if (const_int
1) (const_int
8))]
721 [(set_attr "type" "trap")])
723 (define_expand "prologue"
724 [(clobber (const_int
0))]
727 aarch64_expand_prologue ();
732 (define_expand "epilogue"
733 [(clobber (const_int
0))]
736 aarch64_expand_epilogue (false);
741 (define_expand "sibcall_epilogue"
742 [(clobber (const_int
0))]
745 aarch64_expand_epilogue (true);
750 (define_insn "*do_return"
754 if (aarch64_return_address_signing_enabled ()
756 && !crtl->calls_eh_return)
758 if (aarch64_ra_sign_key == AARCH64_KEY_B)
765 [(set_attr "type" "branch")]
768 (define_expand "return"
770 "aarch64_use_return_insn_p ()"
774 (define_insn "simple_return"
776 "aarch64_use_simple_return_insn_p ()"
778 [(set_attr "type" "branch")]
781 (define_insn "*cb<optab><mode>
1"
782 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
784 (label_ref (match_operand
1 "" ""))
786 "!aarch64_track_speculation"
788 if (get_attr_length (insn) ==
8)
789 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
791 return "<cbz>
\\t%<w>
0, %l1";
793 [(set_attr "type" "branch")
795 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
796 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
799 (set (attr "far_branch")
800 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
801 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
806 (define_insn "*tb<optab><mode>
1"
807 [(set (pc) (if_then_else
808 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
811 "aarch64_simd_shift_imm_<mode>" "n"))
813 (label_ref (match_operand
2 "" ""))
815 (clobber (reg:CC CC_REGNUM))]
816 "!aarch64_track_speculation"
818 if (get_attr_length (insn) ==
8)
820 if (get_attr_far_branch (insn) ==
1)
821 return aarch64_gen_far_branch (operands,
2, "Ltb",
822 "<inv_tb>
\\t%<w>
0, %
1, ");
825 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
826 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
830 return "<tbz>
\t%<w>
0, %
1, %l2";
832 [(set_attr "type" "branch")
834 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
835 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
838 (set (attr "far_branch")
839 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
840 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
846 (define_insn "*cb<optab><mode>
1"
847 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
849 (label_ref (match_operand
1 "" ""))
851 (clobber (reg:CC CC_REGNUM))]
852 "!aarch64_track_speculation"
854 if (get_attr_length (insn) ==
8)
856 if (get_attr_far_branch (insn) ==
1)
857 return aarch64_gen_far_branch (operands,
1, "Ltb",
858 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
862 uint64_t val = ((uint64_t)
1)
863 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
864 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
865 output_asm_insn (buf, operands);
866 return "<bcond>
\t%l1";
870 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
872 [(set_attr "type" "branch")
874 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
875 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
878 (set (attr "far_branch")
879 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
880 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
885 ;; -------------------------------------------------------------------
886 ;; Subroutine calls and sibcalls
887 ;; -------------------------------------------------------------------
889 (define_expand "call"
890 [(parallel [(call (match_operand
0 "memory_operand")
891 (match_operand
1 "general_operand"))
892 (use (match_operand
2 "" ""))
893 (clobber (reg:DI LR_REGNUM))])]
897 aarch64_expand_call (NULL_RTX, operands[
0], false);
902 (define_insn "*call_insn"
903 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
904 (match_operand
1 "" ""))
905 (clobber (reg:DI LR_REGNUM))]
910 [(set_attr "type" "call, call")]
913 (define_expand "call_value"
914 [(parallel [(set (match_operand
0 "" "")
915 (call (match_operand
1 "memory_operand")
916 (match_operand
2 "general_operand")))
917 (use (match_operand
3 "" ""))
918 (clobber (reg:DI LR_REGNUM))])]
922 aarch64_expand_call (operands[
0], operands[
1], false);
927 (define_insn "*call_value_insn"
928 [(set (match_operand
0 "" "")
929 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
930 (match_operand
2 "" "")))
931 (clobber (reg:DI LR_REGNUM))]
936 [(set_attr "type" "call, call")]
939 (define_expand "sibcall"
940 [(parallel [(call (match_operand
0 "memory_operand")
941 (match_operand
1 "general_operand"))
943 (use (match_operand
2 "" ""))])]
946 aarch64_expand_call (NULL_RTX, operands[
0], true);
951 (define_expand "sibcall_value"
952 [(parallel [(set (match_operand
0 "" "")
953 (call (match_operand
1 "memory_operand")
954 (match_operand
2 "general_operand")))
956 (use (match_operand
3 "" ""))])]
959 aarch64_expand_call (operands[
0], operands[
1], true);
964 (define_insn "*sibcall_insn"
965 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
966 (match_operand
1 "" ""))
968 "SIBLING_CALL_P (insn)"
972 [(set_attr "type" "branch, branch")]
975 (define_insn "*sibcall_value_insn"
976 [(set (match_operand
0 "" "")
978 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
979 (match_operand
2 "" "")))
981 "SIBLING_CALL_P (insn)"
985 [(set_attr "type" "branch, branch")]
988 ;; Call subroutine returning any type.
990 (define_expand "untyped_call"
991 [(parallel [(call (match_operand
0 "")
994 (match_operand
2 "")])]
999 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL));
1001 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
1003 rtx set = XVECEXP (operands[
2],
0, i);
1004 emit_move_insn (SET_DEST (set), SET_SRC (set));
1007 /* The optimizer does not know that the call sets the function value
1008 registers we stored in the result block. We avoid problems by
1009 claiming that all hard registers are used and clobbered at this
1011 emit_insn (gen_blockage ());
1015 ;; -------------------------------------------------------------------
1017 ;; -------------------------------------------------------------------
1019 (define_expand "mov<mode>"
1020 [(set (match_operand:SHORT
0 "nonimmediate_operand")
1021 (match_operand:SHORT
1 "general_operand"))]
1024 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1025 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1027 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1029 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1035 (define_insn "*mov<mode>_aarch64"
1036 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1037 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1038 "(register_operand (operands[
0], <MODE>mode)
1039 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
1041 switch (which_alternative)
1044 return "mov
\t%w0, %w1";
1046 return "mov
\t%w0, %
1";
1048 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
1051 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1053 return "ldr<size>
\t%w0, %
1";
1055 return "ldr
\t%<size>
0, %
1";
1057 return "str<size>
\t%w1, %
0";
1059 return "str
\t%<size>
1, %
0";
1061 return "umov
\t%w0, %
1.<v>[
0]";
1063 return "dup
\t%
0.<Vallxd>, %w1";
1065 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
1070 ;; The "mov_imm" type for CNT is just a placeholder.
1071 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1072 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1073 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1076 (define_expand "mov<mode>"
1077 [(set (match_operand:GPI
0 "nonimmediate_operand")
1078 (match_operand:GPI
1 "general_operand"))]
1081 if (MEM_P (operands[
0]) && CONST_INT_P (operands[
1])
1082 && <MODE>mode == DImode
1083 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
1086 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1087 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1089 /* FIXME: RR we still need to fix up what we are doing with
1090 symbol_refs and other types of constants. */
1091 if (CONSTANT_P (operands[
1])
1092 && !CONST_INT_P (operands[
1]))
1094 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1100 (define_insn_and_split "*movsi_aarch64"
1101 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1102 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1103 "(register_operand (operands[
0], SImode)
1104 || aarch64_reg_or_zero (operands[
1], SImode))"
1111 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1121 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1122 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1123 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1126 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1129 ;; The "mov_imm" type for CNT is just a placeholder.
1130 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1131 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1132 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1135 (define_insn_and_split "*movdi_aarch64"
1136 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1137 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1138 "(register_operand (operands[
0], DImode)
1139 || aarch64_reg_or_zero (operands[
1], DImode))"
1147 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1157 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1158 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1159 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1162 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1165 ;; The "mov_imm" type for CNTD is just a placeholder.
1166 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1167 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1169 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1172 (define_insn "insv_imm<mode>"
1173 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1175 (match_operand:GPI
1 "const_int_operand" "n"))
1176 (match_operand:GPI
2 "const_int_operand" "n"))]
1177 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1178 && UINTVAL (operands[
1]) %
16 ==
0"
1179 "movk
\\t%<w>
0, %X2, lsl %
1"
1180 [(set_attr "type" "mov_imm")]
1183 (define_expand "movti"
1184 [(set (match_operand:TI
0 "nonimmediate_operand")
1185 (match_operand:TI
1 "general_operand"))]
1188 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1189 operands[
1] = force_reg (TImode, operands[
1]);
1191 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1193 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1194 gen_lowpart (DImode, operands[
1]));
1195 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1201 (define_insn "*movti_aarch64"
1202 [(set (match_operand:TI
0
1203 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1205 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1206 "(register_operand (operands[
0], TImode)
1207 || aarch64_reg_or_zero (operands[
1], TImode))"
1212 mov
\\t%
0.16b, %
1.16b
1218 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1219 load_16,store_16,store_16,\
1221 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1222 (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
1225 ;; Split a TImode register-register or register-immediate move into
1226 ;; its component DImode pieces, taking care to handle overlapping
1227 ;; source and dest registers.
1229 [(set (match_operand:TI
0 "register_operand" "")
1230 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1231 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1234 aarch64_split_128bit_move (operands[
0], operands[
1]);
1238 (define_expand "mov<mode>"
1239 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand")
1240 (match_operand:GPF_TF_F16
1 "general_operand"))]
1245 aarch64_err_no_fpadvsimd (<MODE>mode);
1249 if (GET_CODE (operands[
0]) == MEM
1250 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1251 && aarch64_float_const_zero_rtx_p (operands[
1])))
1252 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1256 (define_insn "*movhf_aarch64"
1257 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1258 (match_operand:HF
1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1259 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1260 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1266 mov
\\t%
0.h[
0], %
1.h[
0]
1268 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1274 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1275 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1276 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1279 (define_insn "*movsf_aarch64"
1280 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1281 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1282 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1283 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1290 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1297 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1298 f_loads,f_stores,load_4,store_4,mov_reg,\
1300 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1303 (define_insn "*movdf_aarch64"
1304 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1305 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1306 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1307 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1314 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1321 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1322 f_loadd,f_stored,load_8,store_8,mov_reg,\
1324 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1328 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1329 (match_operand:GPF_HF
1 "general_operand"))]
1330 "can_create_pseudo_p ()
1331 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1332 && !aarch64_float_const_representable_p (operands[
1])
1333 && aarch64_float_const_rtx_p (operands[
1])"
1336 unsigned HOST_WIDE_INT ival;
1337 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1340 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1341 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1342 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1347 (define_insn "*movtf_aarch64"
1348 [(set (match_operand:TF
0
1349 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1351 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1352 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1353 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1355 mov
\\t%
0.16b, %
1.16b
1366 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1367 f_loadd,f_stored,load_16,store_16,store_16")
1368 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1369 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1373 [(set (match_operand:TF
0 "register_operand" "")
1374 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1375 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1378 aarch64_split_128bit_move (operands[
0], operands[
1]);
1385 ;;
2 is size of copy in bytes
1388 (define_expand "cpymemdi"
1389 [(match_operand:BLK
0 "memory_operand")
1390 (match_operand:BLK
1 "memory_operand")
1391 (match_operand:DI
2 "immediate_operand")
1392 (match_operand:DI
3 "immediate_operand")]
1395 if (aarch64_expand_cpymem (operands))
1401 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1402 ;; fairly lax checking on the second memory operation.
1403 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1404 [(set (match_operand:SX
0 "register_operand" "=r,w")
1405 (match_operand:SX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1406 (set (match_operand:SX2
2 "register_operand" "=r,w")
1407 (match_operand:SX2
3 "memory_operand" "m,m"))]
1408 "rtx_equal_p (XEXP (operands[
3],
0),
1409 plus_constant (Pmode,
1410 XEXP (operands[
1],
0),
1411 GET_MODE_SIZE (<SX:MODE>mode)))"
1415 [(set_attr "type" "load_8,neon_load1_2reg")
1416 (set_attr "arch" "*,fp")]
1419 ;; Storing different modes that can still be merged
1420 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1421 [(set (match_operand:DX
0 "register_operand" "=r,w")
1422 (match_operand:DX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1423 (set (match_operand:DX2
2 "register_operand" "=r,w")
1424 (match_operand:DX2
3 "memory_operand" "m,m"))]
1425 "rtx_equal_p (XEXP (operands[
3],
0),
1426 plus_constant (Pmode,
1427 XEXP (operands[
1],
0),
1428 GET_MODE_SIZE (<DX:MODE>mode)))"
1432 [(set_attr "type" "load_16,neon_load1_2reg")
1433 (set_attr "arch" "*,fp")]
1436 (define_insn "load_pair_dw_tftf"
1437 [(set (match_operand:TF
0 "register_operand" "=w")
1438 (match_operand:TF
1 "aarch64_mem_pair_operand" "Ump"))
1439 (set (match_operand:TF
2 "register_operand" "=w")
1440 (match_operand:TF
3 "memory_operand" "m"))]
1442 && rtx_equal_p (XEXP (operands[
3],
0),
1443 plus_constant (Pmode,
1444 XEXP (operands[
1],
0),
1445 GET_MODE_SIZE (TFmode)))"
1446 "ldp
\\t%q0, %q2, %
1"
1447 [(set_attr "type" "neon_ldp_q")
1448 (set_attr "fp" "yes")]
1451 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1452 ;; fairly lax checking on the second memory operation.
1453 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1454 [(set (match_operand:SX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1455 (match_operand:SX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1456 (set (match_operand:SX2
2 "memory_operand" "=m,m")
1457 (match_operand:SX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1458 "rtx_equal_p (XEXP (operands[
2],
0),
1459 plus_constant (Pmode,
1460 XEXP (operands[
0],
0),
1461 GET_MODE_SIZE (<SX:MODE>mode)))"
1465 [(set_attr "type" "store_8,neon_store1_2reg")
1466 (set_attr "arch" "*,fp")]
1469 ;; Storing different modes that can still be merged
1470 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1471 [(set (match_operand:DX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1472 (match_operand:DX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1473 (set (match_operand:DX2
2 "memory_operand" "=m,m")
1474 (match_operand:DX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1475 "rtx_equal_p (XEXP (operands[
2],
0),
1476 plus_constant (Pmode,
1477 XEXP (operands[
0],
0),
1478 GET_MODE_SIZE (<DX:MODE>mode)))"
1482 [(set_attr "type" "store_16,neon_store1_2reg")
1483 (set_attr "arch" "*,fp")]
1486 (define_insn "store_pair_dw_tftf"
1487 [(set (match_operand:TF
0 "aarch64_mem_pair_operand" "=Ump")
1488 (match_operand:TF
1 "register_operand" "w"))
1489 (set (match_operand:TF
2 "memory_operand" "=m")
1490 (match_operand:TF
3 "register_operand" "w"))]
1492 rtx_equal_p (XEXP (operands[
2],
0),
1493 plus_constant (Pmode,
1494 XEXP (operands[
0],
0),
1495 GET_MODE_SIZE (TFmode)))"
1496 "stp
\\t%q1, %q3, %
0"
1497 [(set_attr "type" "neon_stp_q")
1498 (set_attr "fp" "yes")]
1501 ;; Load pair with post-index writeback. This is primarily used in function
1503 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1505 [(set (match_operand:P
0 "register_operand" "=k")
1506 (plus:P (match_operand:P
1 "register_operand" "
0")
1507 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1508 (set (match_operand:GPI
2 "register_operand" "=r")
1509 (mem:GPI (match_dup
1)))
1510 (set (match_operand:GPI
3 "register_operand" "=r")
1511 (mem:GPI (plus:P (match_dup
1)
1512 (match_operand:P
5 "const_int_operand" "n"))))])]
1513 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1514 "ldp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
1], %
4"
1515 [(set_attr "type" "load_<GPI:ldpstp_sz>")]
1518 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1520 [(set (match_operand:P
0 "register_operand" "=k")
1521 (plus:P (match_operand:P
1 "register_operand" "
0")
1522 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1523 (set (match_operand:GPF
2 "register_operand" "=w")
1524 (mem:GPF (match_dup
1)))
1525 (set (match_operand:GPF
3 "register_operand" "=w")
1526 (mem:GPF (plus:P (match_dup
1)
1527 (match_operand:P
5 "const_int_operand" "n"))))])]
1528 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1529 "ldp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
1], %
4"
1530 [(set_attr "type" "neon_load1_2reg")]
1533 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1535 [(set (match_operand:P
0 "register_operand" "=k")
1536 (plus:P (match_operand:P
1 "register_operand" "
0")
1537 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1538 (set (match_operand:TX
2 "register_operand" "=w")
1539 (mem:TX (match_dup
1)))
1540 (set (match_operand:TX
3 "register_operand" "=w")
1541 (mem:TX (plus:P (match_dup
1)
1542 (match_operand:P
5 "const_int_operand" "n"))))])]
1543 "TARGET_SIMD && INTVAL (operands[
5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1544 "ldp
\\t%q2, %q3, [%
1], %
4"
1545 [(set_attr "type" "neon_ldp_q")]
1548 ;; Store pair with pre-index writeback. This is primarily used in function
1550 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1552 [(set (match_operand:P
0 "register_operand" "=&k")
1553 (plus:P (match_operand:P
1 "register_operand" "
0")
1554 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1555 (set (mem:GPI (plus:P (match_dup
0)
1557 (match_operand:GPI
2 "register_operand" "r"))
1558 (set (mem:GPI (plus:P (match_dup
0)
1559 (match_operand:P
5 "const_int_operand" "n")))
1560 (match_operand:GPI
3 "register_operand" "r"))])]
1561 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1562 "stp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
0, %
4]!"
1563 [(set_attr "type" "store_<GPI:ldpstp_sz>")]
1566 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1568 [(set (match_operand:P
0 "register_operand" "=&k")
1569 (plus:P (match_operand:P
1 "register_operand" "
0")
1570 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1571 (set (mem:GPF (plus:P (match_dup
0)
1573 (match_operand:GPF
2 "register_operand" "w"))
1574 (set (mem:GPF (plus:P (match_dup
0)
1575 (match_operand:P
5 "const_int_operand" "n")))
1576 (match_operand:GPF
3 "register_operand" "w"))])]
1577 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1578 "stp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
0, %
4]!"
1579 [(set_attr "type" "neon_store1_2reg<q>")]
1582 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1584 [(set (match_operand:P
0 "register_operand" "=&k")
1585 (plus:P (match_operand:P
1 "register_operand" "
0")
1586 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1587 (set (mem:TX (plus:P (match_dup
0)
1589 (match_operand:TX
2 "register_operand" "w"))
1590 (set (mem:TX (plus:P (match_dup
0)
1591 (match_operand:P
5 "const_int_operand" "n")))
1592 (match_operand:TX
3 "register_operand" "w"))])]
1594 && INTVAL (operands[
5])
1595 == INTVAL (operands[
4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1596 "stp
\\t%q2, %q3, [%
0, %
4]!"
1597 [(set_attr "type" "neon_stp_q")]
1600 ;; -------------------------------------------------------------------
1601 ;; Sign/Zero extension
1602 ;; -------------------------------------------------------------------
1604 (define_expand "<optab>sidi2"
1605 [(set (match_operand:DI
0 "register_operand")
1606 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1610 (define_insn "*extendsidi2_aarch64"
1611 [(set (match_operand:DI
0 "register_operand" "=r,r")
1612 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1617 [(set_attr "type" "extend,load_4")]
1620 (define_insn "*load_pair_extendsidi2_aarch64"
1621 [(set (match_operand:DI
0 "register_operand" "=r")
1622 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1623 (set (match_operand:DI
2 "register_operand" "=r")
1624 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1625 "rtx_equal_p (XEXP (operands[
3],
0),
1626 plus_constant (Pmode,
1627 XEXP (operands[
1],
0),
1628 GET_MODE_SIZE (SImode)))"
1629 "ldpsw
\\t%
0, %
2, %
1"
1630 [(set_attr "type" "load_8")]
1633 (define_insn "*zero_extendsidi2_aarch64"
1634 [(set (match_operand:DI
0 "register_operand" "=r,r,w,w,r,w")
1635 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1644 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1645 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1648 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1649 [(set (match_operand:DI
0 "register_operand" "=r,w")
1650 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump,Ump")))
1651 (set (match_operand:DI
2 "register_operand" "=r,w")
1652 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m,m")))]
1653 "rtx_equal_p (XEXP (operands[
3],
0),
1654 plus_constant (Pmode,
1655 XEXP (operands[
1],
0),
1656 GET_MODE_SIZE (SImode)))"
1660 [(set_attr "type" "load_8,neon_load1_2reg")
1661 (set_attr "arch" "*,fp")]
1664 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1665 [(set (match_operand:GPI
0 "register_operand")
1666 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1670 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1671 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1672 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1675 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1676 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1677 [(set_attr "type" "extend,load_4")]
1680 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1681 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1682 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1685 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1686 ldr<SHORT:size>
\t%w0, %
1
1687 ldr
\t%<SHORT:size>
0, %
1"
1688 [(set_attr "type" "logic_imm,load_4,f_loads")
1689 (set_attr "arch" "*,*,fp")]
1692 (define_expand "<optab>qihi2"
1693 [(set (match_operand:HI
0 "register_operand")
1694 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1698 (define_insn "*extendqihi2_aarch64"
1699 [(set (match_operand:HI
0 "register_operand" "=r,r")
1700 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1705 [(set_attr "type" "extend,load_4")]
1708 (define_insn "*zero_extendqihi2_aarch64"
1709 [(set (match_operand:HI
0 "register_operand" "=r,r")
1710 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1715 [(set_attr "type" "logic_imm,load_4")]
1718 ;; -------------------------------------------------------------------
1719 ;; Simple arithmetic
1720 ;; -------------------------------------------------------------------
1722 (define_expand "add<mode>
3"
1724 (match_operand:GPI
0 "register_operand")
1725 (plus:GPI (match_operand:GPI
1 "register_operand")
1726 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand")))]
1729 /* If operands[
1] is a subreg extract the inner RTX. */
1730 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1732 /* If the constant is too large for a single instruction and isn't frame
1733 based, split off the immediate so it is available for CSE. */
1734 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1735 && can_create_pseudo_p ()
1737 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1738 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1739 /* Expand polynomial additions now if the destination is the stack
1740 pointer, since we don't want to use that as a temporary. */
1741 else if (operands[
0] == stack_pointer_rtx
1742 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1744 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1745 operands[
2], NULL_RTX, NULL_RTX);
1750 (define_insn "*add<mode>
3_aarch64"
1752 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,rk")
1754 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,rk")
1755 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1758 add
\\t%<w>
0, %<w>
1, %
2
1759 add
\\t%<w>
0, %<w>
1, %<w>
2
1760 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1761 sub
\\t%<w>
0, %<w>
1, #%n2
1763 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);"
1764 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1765 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1766 (set_attr "arch" "*,*,simd,*,*,*")]
1769 ;; zero_extend version of above
1770 (define_insn "*addsi3_aarch64_uxtw"
1772 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1774 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1775 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1780 sub
\\t%w0, %w1, #%n2
1782 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1785 ;; If there's a free register, and we can load the constant with a
1786 ;; single instruction, do so. This has a chance to improve scheduling.
1788 [(match_scratch:GPI
3 "r")
1789 (set (match_operand:GPI
0 "register_operand")
1791 (match_operand:GPI
1 "register_operand")
1792 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1793 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1794 [(set (match_dup
3) (match_dup
2))
1795 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1799 [(match_scratch:SI
3 "r")
1800 (set (match_operand:DI
0 "register_operand")
1803 (match_operand:SI
1 "register_operand")
1804 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1805 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1806 [(set (match_dup
3) (match_dup
2))
1807 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1810 ;; After peephole2 has had a chance to run, split any remaining long
1811 ;; additions into two add immediates.
1813 [(set (match_operand:GPI
0 "register_operand")
1815 (match_operand:GPI
1 "register_operand")
1816 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1817 "epilogue_completed"
1818 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1819 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1821 HOST_WIDE_INT i = INTVAL (operands[
2]);
1822 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1823 operands[
3] = GEN_INT (i - s);
1824 operands[
4] = GEN_INT (s);
1828 ;; Match addition of polynomial offsets that require one temporary, for which
1829 ;; we can use the early-clobbered destination register. This is a separate
1830 ;; pattern so that the early clobber doesn't affect register allocation
1831 ;; for other forms of addition. However, we still need to provide an
1832 ;; all-register alternative, in case the offset goes out of range after
1833 ;; elimination. For completeness we might as well provide all GPR-based
1834 ;; alternatives from the main pattern.
1836 ;; We don't have a pattern for additions requiring two temporaries since at
1837 ;; present LRA doesn't allow new scratches to be added during elimination.
1838 ;; Such offsets should be rare anyway.
1840 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1841 ;; here would go away. We could just handle all polynomial constants in
1843 (define_insn_and_split "*add<mode>
3_poly_1"
1845 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,&r")
1847 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1848 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1849 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1851 add
\\t%<w>
0, %<w>
1, %
2
1852 add
\\t%<w>
0, %<w>
1, %<w>
2
1853 sub
\\t%<w>
0, %<w>
1, #%n2
1855 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);
1857 "&& epilogue_completed
1858 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1859 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1862 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1863 operands[
2], operands[
0], NULL_RTX);
1866 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1867 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1871 [(set (match_operand:DI
0 "register_operand")
1874 (match_operand:SI
1 "register_operand")
1875 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1876 "epilogue_completed"
1877 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1878 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1880 HOST_WIDE_INT i = INTVAL (operands[
2]);
1881 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1882 operands[
3] = GEN_INT (i - s);
1883 operands[
4] = GEN_INT (s);
1884 operands[
5] = gen_lowpart (SImode, operands[
0]);
1888 (define_expand "addv<mode>
4"
1889 [(match_operand:GPI
0 "register_operand")
1890 (match_operand:GPI
1 "register_operand")
1891 (match_operand:GPI
2 "aarch64_plus_operand")
1892 (label_ref (match_operand
3 "" ""))]
1895 if (CONST_INT_P (operands[
2]))
1896 emit_insn (gen_add<mode>
3_compareV_imm (operands[
0], operands[
1],
1899 emit_insn (gen_add<mode>
3_compareV (operands[
0], operands[
1], operands[
2]));
1900 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1905 (define_expand "uaddv<mode>
4"
1906 [(match_operand:GPI
0 "register_operand")
1907 (match_operand:GPI
1 "register_operand")
1908 (match_operand:GPI
2 "register_operand")
1909 (label_ref (match_operand
3 "" ""))]
1912 emit_insn (gen_add<mode>
3_compareC (operands[
0], operands[
1], operands[
2]));
1913 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[
3]);
1918 (define_expand "addti3"
1919 [(set (match_operand:TI
0 "register_operand")
1920 (plus:TI (match_operand:TI
1 "register_operand")
1921 (match_operand:TI
2 "aarch64_reg_or_imm")))]
1924 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1926 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1927 &low_dest, &op1_low, &op2_low,
1928 &high_dest, &op1_high, &op2_high);
1930 if (op2_low == const0_rtx)
1933 if (!aarch64_pluslong_operand (op2_high, DImode))
1934 op2_high = force_reg (DImode, op2_high);
1935 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
1939 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1940 force_reg (DImode, op2_low)));
1941 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
1942 force_reg (DImode, op2_high)));
1945 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1946 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1951 (define_expand "addvti4"
1952 [(match_operand:TI
0 "register_operand")
1953 (match_operand:TI
1 "register_operand")
1954 (match_operand:TI
2 "aarch64_reg_or_imm")
1955 (label_ref (match_operand
3 "" ""))]
1958 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1960 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1961 &low_dest, &op1_low, &op2_low,
1962 &high_dest, &op1_high, &op2_high);
1964 if (op2_low == const0_rtx)
1967 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
1968 force_reg (DImode, op2_high)));
1972 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1973 force_reg (DImode, op2_low)));
1974 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
1975 force_reg (DImode, op2_high)));
1978 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1979 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1981 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1985 (define_expand "uaddvti4"
1986 [(match_operand:TI
0 "register_operand")
1987 (match_operand:TI
1 "register_operand")
1988 (match_operand:TI
2 "aarch64_reg_or_imm")
1989 (label_ref (match_operand
3 "" ""))]
1992 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1994 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1995 &low_dest, &op1_low, &op2_low,
1996 &high_dest, &op1_high, &op2_high);
1998 if (op2_low == const0_rtx)
2001 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2002 force_reg (DImode, op2_high)));
2006 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2007 force_reg (DImode, op2_low)));
2008 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2009 force_reg (DImode, op2_high)));
2012 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2013 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2015 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[
3]);
2019 (define_insn "add<mode>
3_compare0"
2020 [(set (reg:CC_NZ CC_REGNUM)
2022 (plus:GPI (match_operand:GPI
1 "register_operand" "%rk,rk,rk")
2023 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2025 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2026 (plus:GPI (match_dup
1) (match_dup
2)))]
2029 adds
\\t%<w>
0, %<w>
1, %<w>
2
2030 adds
\\t%<w>
0, %<w>
1, %
2
2031 subs
\\t%<w>
0, %<w>
1, #%n2"
2032 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2035 ;; zero_extend version of above
2036 (define_insn "*addsi3_compare0_uxtw"
2037 [(set (reg:CC_NZ CC_REGNUM)
2039 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk")
2040 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
2042 (set (match_operand:DI
0 "register_operand" "=r,r,r")
2043 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
2046 adds
\\t%w0, %w1, %w2
2048 subs
\\t%w0, %w1, #%n2"
2049 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2052 (define_insn "*add<mode>
3_compareC_cconly"
2053 [(set (reg:CC_C CC_REGNUM)
2056 (match_operand:GPI
0 "register_operand" "r,r,r")
2057 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2064 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2067 (define_insn "add<mode>
3_compareC"
2068 [(set (reg:CC_C CC_REGNUM)
2071 (match_operand:GPI
1 "register_operand" "rk,rk,rk")
2072 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2074 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2075 (plus:GPI (match_dup
1) (match_dup
2)))]
2078 adds
\\t%<w>
0, %<w>
1, %<w>
2
2079 adds
\\t%<w>
0, %<w>
1, %
2
2080 subs
\\t%<w>
0, %<w>
1, #%n2"
2081 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2084 (define_insn "*add<mode>
3_compareV_cconly_imm"
2085 [(set (reg:CC_V CC_REGNUM)
2088 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
2089 (match_operand:<DWI>
1 "const_scalar_int_operand" ""))
2093 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))]
2094 "INTVAL (operands[
1]) == INTVAL (operands[
2])"
2098 [(set_attr "type" "alus_imm")]
2101 (define_insn "*add<mode>
3_compareV_cconly"
2102 [(set (reg:CC_V CC_REGNUM)
2105 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
2106 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2107 (sign_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
2109 "cmn
\\t%<w>
0, %<w>
1"
2110 [(set_attr "type" "alus_sreg")]
2113 (define_insn "add<mode>
3_compareV_imm"
2114 [(set (reg:CC_V CC_REGNUM)
2118 (match_operand:GPI
1 "register_operand" "rk,rk"))
2119 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J"))
2121 (plus:GPI (match_dup
1) (match_dup
2)))))
2122 (set (match_operand:GPI
0 "register_operand" "=r,r")
2123 (plus:GPI (match_dup
1) (match_dup
2)))]
2126 adds
\\t%<w>
0, %<w>
1, %<w>
2
2127 subs
\\t%<w>
0, %<w>
1, #%n2"
2128 [(set_attr "type" "alus_imm,alus_imm")]
2131 (define_insn "add<mode>
3_compareV"
2132 [(set (reg:CC_V CC_REGNUM)
2135 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "rk"))
2136 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2137 (sign_extend:<DWI> (plus:GPI (match_dup
1) (match_dup
2)))))
2138 (set (match_operand:GPI
0 "register_operand" "=r")
2139 (plus:GPI (match_dup
1) (match_dup
2)))]
2141 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
2142 [(set_attr "type" "alus_sreg")]
2145 (define_insn "*adds_shift_imm_<mode>"
2146 [(set (reg:CC_NZ CC_REGNUM)
2148 (plus:GPI (ASHIFT:GPI
2149 (match_operand:GPI
1 "register_operand" "r")
2150 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2151 (match_operand:GPI
3 "register_operand" "r"))
2153 (set (match_operand:GPI
0 "register_operand" "=r")
2154 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
2157 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2158 [(set_attr "type" "alus_shift_imm")]
2161 (define_insn "*subs_shift_imm_<mode>"
2162 [(set (reg:CC_NZ CC_REGNUM)
2164 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2166 (match_operand:GPI
2 "register_operand" "r")
2167 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
2169 (set (match_operand:GPI
0 "register_operand" "=r")
2170 (minus:GPI (match_dup
1)
2171 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
2173 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
2174 [(set_attr "type" "alus_shift_imm")]
2177 (define_insn "*adds_mul_imm_<mode>"
2178 [(set (reg:CC_NZ CC_REGNUM)
2181 (match_operand:GPI
1 "register_operand" "r")
2182 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2183 (match_operand:GPI
3 "register_operand" "r"))
2185 (set (match_operand:GPI
0 "register_operand" "=r")
2186 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
2189 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2190 [(set_attr "type" "alus_shift_imm")]
2193 (define_insn "*subs_mul_imm_<mode>"
2194 [(set (reg:CC_NZ CC_REGNUM)
2196 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2198 (match_operand:GPI
2 "register_operand" "r")
2199 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
2201 (set (match_operand:GPI
0 "register_operand" "=r")
2202 (minus:GPI (match_dup
1)
2203 (mult:GPI (match_dup
2) (match_dup
3))))]
2205 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
2206 [(set_attr "type" "alus_shift_imm")]
2209 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2210 [(set (reg:CC_NZ CC_REGNUM)
2213 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2214 (match_operand:GPI
2 "register_operand" "rk"))
2216 (set (match_operand:GPI
0 "register_operand" "=r")
2217 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
2219 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2220 [(set_attr "type" "alus_ext")]
2223 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2224 [(set (reg:CC_NZ CC_REGNUM)
2226 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2228 (match_operand:ALLX
2 "register_operand" "r")))
2230 (set (match_operand:GPI
0 "register_operand" "=r")
2231 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
2233 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2234 [(set_attr "type" "alus_ext")]
2237 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2238 [(set (reg:CC_NZ CC_REGNUM)
2240 (plus:GPI (ashift:GPI
2242 (match_operand:ALLX
1 "register_operand" "r"))
2243 (match_operand
2 "aarch64_imm3" "Ui3"))
2244 (match_operand:GPI
3 "register_operand" "rk"))
2246 (set (match_operand:GPI
0 "register_operand" "=rk")
2247 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2251 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2252 [(set_attr "type" "alus_ext")]
2255 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2256 [(set (reg:CC_NZ CC_REGNUM)
2258 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2261 (match_operand:ALLX
2 "register_operand" "r"))
2262 (match_operand
3 "aarch64_imm3" "Ui3")))
2264 (set (match_operand:GPI
0 "register_operand" "=rk")
2265 (minus:GPI (match_dup
1)
2266 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2269 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2270 [(set_attr "type" "alus_ext")]
2273 (define_insn "*adds_<optab><mode>_multp2"
2274 [(set (reg:CC_NZ CC_REGNUM)
2276 (plus:GPI (ANY_EXTRACT:GPI
2277 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2278 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2279 (match_operand
3 "const_int_operand" "n")
2281 (match_operand:GPI
4 "register_operand" "rk"))
2283 (set (match_operand:GPI
0 "register_operand" "=r")
2284 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2288 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2289 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2290 [(set_attr "type" "alus_ext")]
2293 (define_insn "*subs_<optab><mode>_multp2"
2294 [(set (reg:CC_NZ CC_REGNUM)
2296 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2298 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2299 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2300 (match_operand
3 "const_int_operand" "n")
2303 (set (match_operand:GPI
0 "register_operand" "=r")
2304 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2305 (mult:GPI (match_dup
1) (match_dup
2))
2308 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2309 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2310 [(set_attr "type" "alus_ext")]
2313 (define_insn "*add<mode>
3nr_compare0"
2314 [(set (reg:CC_NZ CC_REGNUM)
2316 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2317 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2324 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2327 (define_insn "aarch64_sub<mode>_compare0"
2328 [(set (reg:CC_NZ CC_REGNUM)
2330 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2331 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2334 "cmp
\\t%<w>
0, %<w>
1"
2335 [(set_attr "type" "alus_sreg")]
2338 (define_insn "*compare_neg<mode>"
2339 [(set (reg:CC_Z CC_REGNUM)
2341 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2342 (match_operand:GPI
1 "register_operand" "r")))]
2344 "cmn
\\t%<w>
1, %<w>
0"
2345 [(set_attr "type" "alus_sreg")]
2348 (define_insn "*add_<shift>_<mode>"
2349 [(set (match_operand:GPI
0 "register_operand" "=r")
2350 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2351 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2352 (match_operand:GPI
3 "register_operand" "r")))]
2354 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2355 [(set_attr "type" "alu_shift_imm")]
2358 ;; zero_extend version of above
2359 (define_insn "*add_<shift>_si_uxtw"
2360 [(set (match_operand:DI
0 "register_operand" "=r")
2362 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2363 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2364 (match_operand:SI
3 "register_operand" "r"))))]
2366 "add
\\t%w0, %w3, %w1, <shift> %
2"
2367 [(set_attr "type" "alu_shift_imm")]
2370 (define_insn "*add_mul_imm_<mode>"
2371 [(set (match_operand:GPI
0 "register_operand" "=r")
2372 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2373 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2374 (match_operand:GPI
3 "register_operand" "r")))]
2376 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2377 [(set_attr "type" "alu_shift_imm")]
2380 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2381 [(set (match_operand:GPI
0 "register_operand" "=rk")
2382 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2383 (match_operand:GPI
2 "register_operand" "r")))]
2385 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2386 [(set_attr "type" "alu_ext")]
2389 ;; zero_extend version of above
2390 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2391 [(set (match_operand:DI
0 "register_operand" "=rk")
2393 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2394 (match_operand:GPI
2 "register_operand" "r"))))]
2396 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2397 [(set_attr "type" "alu_ext")]
2400 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2401 [(set (match_operand:GPI
0 "register_operand" "=rk")
2402 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2403 (match_operand:ALLX
1 "register_operand" "r"))
2404 (match_operand
2 "aarch64_imm3" "Ui3"))
2405 (match_operand:GPI
3 "register_operand" "r")))]
2407 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2408 [(set_attr "type" "alu_ext")]
2411 ;; zero_extend version of above
2412 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2413 [(set (match_operand:DI
0 "register_operand" "=rk")
2415 (plus:SI (ashift:SI (ANY_EXTEND:SI
2416 (match_operand:SHORT
1 "register_operand" "r"))
2417 (match_operand
2 "aarch64_imm3" "Ui3"))
2418 (match_operand:SI
3 "register_operand" "r"))))]
2420 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2421 [(set_attr "type" "alu_ext")]
2424 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2425 [(set (match_operand:GPI
0 "register_operand" "=rk")
2426 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2427 (match_operand:ALLX
1 "register_operand" "r"))
2428 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2429 (match_operand:GPI
3 "register_operand" "r")))]
2431 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2432 [(set_attr "type" "alu_ext")]
2435 ;; zero_extend version of above
2436 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2437 [(set (match_operand:DI
0 "register_operand" "=rk")
2438 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2439 (match_operand:SHORT
1 "register_operand" "r"))
2440 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2441 (match_operand:SI
3 "register_operand" "r"))))]
2443 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2444 [(set_attr "type" "alu_ext")]
2447 (define_insn "*add_<optab><mode>_multp2"
2448 [(set (match_operand:GPI
0 "register_operand" "=rk")
2449 (plus:GPI (ANY_EXTRACT:GPI
2450 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2451 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2452 (match_operand
3 "const_int_operand" "n")
2454 (match_operand:GPI
4 "register_operand" "r")))]
2455 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2456 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2457 [(set_attr "type" "alu_ext")]
2460 ;; zero_extend version of above
2461 (define_insn "*add_<optab>si_multp2_uxtw"
2462 [(set (match_operand:DI
0 "register_operand" "=rk")
2464 (plus:SI (ANY_EXTRACT:SI
2465 (mult:SI (match_operand:SI
1 "register_operand" "r")
2466 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2467 (match_operand
3 "const_int_operand" "n")
2469 (match_operand:SI
4 "register_operand" "r"))))]
2470 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2471 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2472 [(set_attr "type" "alu_ext")]
2475 (define_expand "add<mode>
3_carryin"
2476 [(set (match_operand:GPI
0 "register_operand")
2479 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2480 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2481 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2486 ;; Note that add with carry with two zero inputs is matched by cset,
2487 ;; and that add with carry with one zero input is matched by cinc.
2489 (define_insn "*add<mode>
3_carryin"
2490 [(set (match_operand:GPI
0 "register_operand" "=r")
2493 (match_operand:GPI
3 "aarch64_carry_operation" "")
2494 (match_operand:GPI
1 "register_operand" "r"))
2495 (match_operand:GPI
2 "register_operand" "r")))]
2497 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2498 [(set_attr "type" "adc_reg")]
2501 ;; zero_extend version of above
2502 (define_insn "*addsi3_carryin_uxtw"
2503 [(set (match_operand:DI
0 "register_operand" "=r")
2507 (match_operand:SI
3 "aarch64_carry_operation" "")
2508 (match_operand:SI
1 "register_operand" "r"))
2509 (match_operand:SI
2 "register_operand" "r"))))]
2511 "adc
\\t%w0, %w1, %w2"
2512 [(set_attr "type" "adc_reg")]
2515 (define_expand "add<mode>
3_carryinC"
2523 (match_operand:GPI
1 "register_operand")))
2525 (match_operand:GPI
2 "register_operand")))
2527 (set (match_operand:GPI
0 "register_operand")
2529 (plus:GPI (match_dup
5) (match_dup
1))
2533 operands[
3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2534 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2535 operands[
4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2536 operands[
5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2537 operands[
6] = immed_wide_int_const (wi::shwi (
1, <DWI>mode)
2538 << GET_MODE_BITSIZE (<MODE>mode),
2542 (define_insn "*add<mode>
3_carryinC_zero"
2543 [(set (reg:CC_ADC CC_REGNUM)
2546 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2547 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2548 (match_operand
4 "const_scalar_int_operand" "")))
2549 (set (match_operand:GPI
0 "register_operand" "=r")
2550 (plus:GPI (match_operand:GPI
3 "aarch64_carry_operation" "")
2552 "rtx_mode_t (operands[
4], <DWI>mode)
2553 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2554 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2555 [(set_attr "type" "adc_reg")]
2558 (define_insn "*add<mode>
3_carryinC"
2559 [(set (reg:CC_ADC CC_REGNUM)
2563 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2564 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2565 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2566 (match_operand
5 "const_scalar_int_operand" "")))
2567 (set (match_operand:GPI
0 "register_operand" "=r")
2569 (plus:GPI (match_operand:GPI
4 "aarch64_carry_operation" "")
2572 "rtx_mode_t (operands[
5], <DWI>mode)
2573 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2574 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2575 [(set_attr "type" "adc_reg")]
2578 (define_expand "add<mode>
3_carryinV"
2580 [(set (reg:CC_V CC_REGNUM)
2586 (match_operand:GPI
1 "register_operand")))
2588 (match_operand:GPI
2 "register_operand")))
2591 (plus:GPI (match_dup
4) (match_dup
1))
2593 (set (match_operand:GPI
0 "register_operand")
2595 (plus:GPI (match_dup
4) (match_dup
1))
2599 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2600 operands[
3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2601 operands[
4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2604 (define_insn "*add<mode>
3_carryinV_zero"
2605 [(set (reg:CC_V CC_REGNUM)
2608 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2609 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2612 (match_operand:GPI
3 "aarch64_carry_operation" "")
2614 (set (match_operand:GPI
0 "register_operand" "=r")
2615 (plus:GPI (match_dup
3) (match_dup
1)))]
2617 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2618 [(set_attr "type" "adc_reg")]
2621 (define_insn "*add<mode>
3_carryinV"
2622 [(set (reg:CC_V CC_REGNUM)
2626 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2627 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2628 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2632 (match_operand:GPI
4 "aarch64_carry_operation" "")
2635 (set (match_operand:GPI
0 "register_operand" "=r")
2637 (plus:GPI (match_dup
4) (match_dup
1))
2640 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2641 [(set_attr "type" "adc_reg")]
2644 (define_insn "*add_uxt<mode>_shift2"
2645 [(set (match_operand:GPI
0 "register_operand" "=rk")
2647 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2648 (match_operand
2 "aarch64_imm3" "Ui3"))
2649 (match_operand
3 "const_int_operand" "n"))
2650 (match_operand:GPI
4 "register_operand" "r")))]
2651 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2653 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2654 INTVAL (operands[
3])));
2655 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2656 [(set_attr "type" "alu_ext")]
2659 ;; zero_extend version of above
2660 (define_insn "*add_uxtsi_shift2_uxtw"
2661 [(set (match_operand:DI
0 "register_operand" "=rk")
2664 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2665 (match_operand
2 "aarch64_imm3" "Ui3"))
2666 (match_operand
3 "const_int_operand" "n"))
2667 (match_operand:SI
4 "register_operand" "r"))))]
2668 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2670 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2671 INTVAL (operands[
3])));
2672 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2673 [(set_attr "type" "alu_ext")]
2676 (define_insn "*add_uxt<mode>_multp2"
2677 [(set (match_operand:GPI
0 "register_operand" "=rk")
2679 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2680 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2681 (match_operand
3 "const_int_operand" "n"))
2682 (match_operand:GPI
4 "register_operand" "r")))]
2683 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2685 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2686 INTVAL (operands[
3])));
2687 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2688 [(set_attr "type" "alu_ext")]
2691 ;; zero_extend version of above
2692 (define_insn "*add_uxtsi_multp2_uxtw"
2693 [(set (match_operand:DI
0 "register_operand" "=rk")
2696 (mult:SI (match_operand:SI
1 "register_operand" "r")
2697 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2698 (match_operand
3 "const_int_operand" "n"))
2699 (match_operand:SI
4 "register_operand" "r"))))]
2700 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2702 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2703 INTVAL (operands[
3])));
2704 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2705 [(set_attr "type" "alu_ext")]
2708 (define_insn "subsi3"
2709 [(set (match_operand:SI
0 "register_operand" "=rk")
2710 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2711 (match_operand:SI
2 "register_operand" "r")))]
2713 "sub
\\t%w0, %w1, %w2"
2714 [(set_attr "type" "alu_sreg")]
2717 ;; zero_extend version of above
2718 (define_insn "*subsi3_uxtw"
2719 [(set (match_operand:DI
0 "register_operand" "=rk")
2721 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2722 (match_operand:SI
2 "register_operand" "r"))))]
2724 "sub
\\t%w0, %w1, %w2"
2725 [(set_attr "type" "alu_sreg")]
2728 (define_insn "subdi3"
2729 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2730 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2731 (match_operand:DI
2 "register_operand" "r,w")))]
2735 sub
\\t%d0, %d1, %d2"
2736 [(set_attr "type" "alu_sreg, neon_sub")
2737 (set_attr "arch" "*,simd")]
2740 (define_expand "subv<GPI:mode>
4"
2741 [(match_operand:GPI
0 "register_operand")
2742 (match_operand:GPI
1 "register_operand")
2743 (match_operand:GPI
2 "aarch64_plus_operand")
2744 (label_ref (match_operand
3 "" ""))]
2747 if (CONST_INT_P (operands[
2]))
2748 emit_insn (gen_subv<mode>_imm (operands[
0], operands[
1], operands[
2]));
2750 emit_insn (gen_subv<mode>_insn (operands[
0], operands[
1], operands[
2]));
2751 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2756 (define_insn "subv<GPI:mode>_insn"
2757 [(set (reg:CC_V CC_REGNUM)
2761 (match_operand:GPI
1 "register_operand" "rk")
2762 (match_operand:GPI
2 "register_operand" "r")))
2763 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2764 (sign_extend:<DWI> (match_dup
2)))))
2765 (set (match_operand:GPI
0 "register_operand" "=r")
2766 (minus:GPI (match_dup
1) (match_dup
2)))]
2768 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2769 [(set_attr "type" "alus_sreg")]
2772 (define_insn "subv<GPI:mode>_imm"
2773 [(set (reg:CC_V CC_REGNUM)
2777 (match_operand:GPI
1 "register_operand" "rk,rk")
2778 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2779 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2781 (set (match_operand:GPI
0 "register_operand" "=r,r")
2782 (minus:GPI (match_dup
1) (match_dup
2)))]
2785 subs
\\t%<w>
0, %<w>
1, %
2
2786 adds
\\t%<w>
0, %<w>
1, #%n2"
2787 [(set_attr "type" "alus_sreg")]
2790 (define_expand "negv<GPI:mode>
3"
2791 [(match_operand:GPI
0 "register_operand")
2792 (match_operand:GPI
1 "register_operand")
2793 (label_ref (match_operand
2 "" ""))]
2796 emit_insn (gen_negv<mode>_insn (operands[
0], operands[
1]));
2797 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2803 (define_insn "negv<GPI:mode>_insn"
2804 [(set (reg:CC_V CC_REGNUM)
2807 (neg:GPI (match_operand:GPI
1 "register_operand" "r")))
2808 (neg:<DWI> (sign_extend:<DWI> (match_dup
1)))))
2809 (set (match_operand:GPI
0 "register_operand" "=r")
2810 (neg:GPI (match_dup
1)))]
2812 "negs
\\t%<w>
0, %<w>
1"
2813 [(set_attr "type" "alus_sreg")]
2816 (define_insn "negv<GPI:mode>_cmp_only"
2817 [(set (reg:CC_V CC_REGNUM)
2820 (neg:GPI (match_operand:GPI
0 "register_operand" "r")))
2821 (neg:<DWI> (sign_extend:<DWI> (match_dup
0)))))]
2823 "negs
\\t%<w>zr, %<w>
0"
2824 [(set_attr "type" "alus_sreg")]
2827 (define_insn "*cmpv<GPI:mode>_insn"
2828 [(set (reg:CC_V CC_REGNUM)
2831 (minus:GPI (match_operand:GPI
0 "register_operand" "r,r,r")
2832 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))
2833 (minus:<DWI> (sign_extend:<DWI> (match_dup
0))
2834 (sign_extend:<DWI> (match_dup
1)))))]
2840 [(set_attr "type" "alus_sreg")]
2843 (define_expand "usubv<mode>
4"
2844 [(match_operand:GPI
0 "register_operand")
2845 (match_operand:GPI
1 "aarch64_reg_or_zero")
2846 (match_operand:GPI
2 "aarch64_reg_or_zero")
2847 (label_ref (match_operand
3 "" ""))]
2850 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2851 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2856 (define_expand "subti3"
2857 [(set (match_operand:TI
0 "register_operand")
2858 (minus:TI (match_operand:TI
1 "aarch64_reg_or_zero")
2859 (match_operand:TI
2 "register_operand")))]
2862 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2864 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2865 &low_dest, &op1_low, &op2_low,
2866 &high_dest, &op1_high, &op2_high);
2868 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2869 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2871 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2872 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2876 (define_expand "subvti4"
2877 [(match_operand:TI
0 "register_operand")
2878 (match_operand:TI
1 "register_operand")
2879 (match_operand:TI
2 "aarch64_reg_or_imm")
2880 (label_ref (match_operand
3 "" ""))]
2883 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2885 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2886 &low_dest, &op1_low, &op2_low,
2887 &high_dest, &op1_high, &op2_high);
2888 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2889 high_dest, op1_high, op2_high, false);
2891 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2895 (define_expand "usubvti4"
2896 [(match_operand:TI
0 "register_operand")
2897 (match_operand:TI
1 "register_operand")
2898 (match_operand:TI
2 "aarch64_reg_or_imm")
2899 (label_ref (match_operand
3 "" ""))]
2902 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2904 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2905 &low_dest, &op1_low, &op2_low,
2906 &high_dest, &op1_high, &op2_high);
2907 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2908 high_dest, op1_high, op2_high, true);
2910 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2914 (define_expand "negvti3"
2915 [(match_operand:TI
0 "register_operand")
2916 (match_operand:TI
1 "register_operand")
2917 (label_ref (match_operand
2 "" ""))]
2920 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[
0]),
2921 gen_lowpart (DImode, operands[
1])));
2922 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[
0]),
2923 gen_highpart (DImode, operands[
1])));
2924 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2930 (define_insn "negdi_carryout"
2931 [(set (reg:CC CC_REGNUM)
2933 (const_int
0) (match_operand:DI
1 "register_operand" "r")))
2934 (set (match_operand:DI
0 "register_operand" "=r")
2935 (neg:DI (match_dup
1)))]
2938 [(set_attr "type" "alus_sreg")]
2941 (define_insn "negvdi_carryinV"
2942 [(set (reg:CC_V CC_REGNUM)
2945 (ltu:TI (reg:CC CC_REGNUM) (const_int
0))
2946 (sign_extend:TI (match_operand:DI
1 "register_operand" "r"))))
2948 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
2950 (set (match_operand:DI
0 "register_operand" "=r")
2951 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
2955 [(set_attr "type" "alus_sreg")]
2958 (define_insn "*sub<mode>
3_compare0"
2959 [(set (reg:CC_NZ CC_REGNUM)
2960 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2961 (match_operand:GPI
2 "register_operand" "r"))
2963 (set (match_operand:GPI
0 "register_operand" "=r")
2964 (minus:GPI (match_dup
1) (match_dup
2)))]
2966 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2967 [(set_attr "type" "alus_sreg")]
2970 ;; zero_extend version of above
2971 (define_insn "*subsi3_compare0_uxtw"
2972 [(set (reg:CC_NZ CC_REGNUM)
2973 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "rk")
2974 (match_operand:SI
2 "register_operand" "r"))
2976 (set (match_operand:DI
0 "register_operand" "=r")
2977 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
2979 "subs
\\t%w0, %w1, %w2"
2980 [(set_attr "type" "alus_sreg")]
2983 (define_insn "sub<mode>
3_compare1_imm"
2984 [(set (reg:CC CC_REGNUM)
2986 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ,rkZ")
2987 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2988 (set (match_operand:GPI
0 "register_operand" "=r,r")
2991 (match_operand:GPI
3 "aarch64_plus_immediate" "J,I")))]
2992 "UINTVAL (operands[
2]) == -UINTVAL (operands[
3])"
2994 subs
\\t%<w>
0, %<w>
1, %
2
2995 adds
\\t%<w>
0, %<w>
1, #%n2"
2996 [(set_attr "type" "alus_imm")]
2999 (define_insn "sub<mode>
3_compare1"
3000 [(set (reg:CC CC_REGNUM)
3002 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ")
3003 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
3004 (set (match_operand:GPI
0 "register_operand" "=r")
3005 (minus:GPI (match_dup
1) (match_dup
2)))]
3007 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
3008 [(set_attr "type" "alus_sreg")]
3012 [(set (match_operand:GPI
0 "aarch64_general_reg")
3013 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
3014 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3015 (set (reg:CC CC_REGNUM)
3019 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3020 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
3023 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3029 ;; Same as the above peephole but with the compare and minus in
3030 ;; swapped order. The restriction on overlap between operand
0
3031 ;; and operands
1 and
2 doesn't apply here.
3033 [(set (reg:CC CC_REGNUM)
3035 (match_operand:GPI
1 "aarch64_reg_or_zero")
3036 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3037 (set (match_operand:GPI
0 "aarch64_general_reg")
3038 (minus:GPI (match_dup
1)
3043 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3050 [(set (match_operand:GPI
0 "aarch64_general_reg")
3051 (plus:GPI (match_operand:GPI
1 "register_operand")
3052 (match_operand:GPI
2 "aarch64_plus_immediate")))
3053 (set (reg:CC CC_REGNUM)
3056 (match_operand:GPI
3 "const_int_operand")))]
3057 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3058 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3061 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3062 operands[
3], operands[
2]));
3067 ;; Same as the above peephole but with the compare and minus in
3068 ;; swapped order. The restriction on overlap between operand
0
3069 ;; and operands
1 doesn't apply here.
3071 [(set (reg:CC CC_REGNUM)
3073 (match_operand:GPI
1 "register_operand")
3074 (match_operand:GPI
3 "const_int_operand")))
3075 (set (match_operand:GPI
0 "aarch64_general_reg")
3076 (plus:GPI (match_dup
1)
3077 (match_operand:GPI
2 "aarch64_plus_immediate")))]
3078 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3081 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3082 operands[
3], operands[
2]));
3087 (define_insn "*sub_<shift>_<mode>"
3088 [(set (match_operand:GPI
0 "register_operand" "=r")
3089 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3091 (match_operand:GPI
1 "register_operand" "r")
3092 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3094 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
3095 [(set_attr "type" "alu_shift_imm")]
3098 ;; zero_extend version of above
3099 (define_insn "*sub_<shift>_si_uxtw"
3100 [(set (match_operand:DI
0 "register_operand" "=r")
3102 (minus:SI (match_operand:SI
3 "register_operand" "r")
3104 (match_operand:SI
1 "register_operand" "r")
3105 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3107 "sub
\\t%w0, %w3, %w1, <shift> %
2"
3108 [(set_attr "type" "alu_shift_imm")]
3111 (define_insn "*sub_mul_imm_<mode>"
3112 [(set (match_operand:GPI
0 "register_operand" "=r")
3113 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3115 (match_operand:GPI
1 "register_operand" "r")
3116 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3118 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
3119 [(set_attr "type" "alu_shift_imm")]
3122 ;; zero_extend version of above
3123 (define_insn "*sub_mul_imm_si_uxtw"
3124 [(set (match_operand:DI
0 "register_operand" "=r")
3126 (minus:SI (match_operand:SI
3 "register_operand" "r")
3128 (match_operand:SI
1 "register_operand" "r")
3129 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3131 "sub
\\t%w0, %w3, %w1, lsl %p2"
3132 [(set_attr "type" "alu_shift_imm")]
3135 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3136 [(set (match_operand:GPI
0 "register_operand" "=rk")
3137 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3139 (match_operand:ALLX
2 "register_operand" "r"))))]
3141 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
3142 [(set_attr "type" "alu_ext")]
3145 ;; zero_extend version of above
3146 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3147 [(set (match_operand:DI
0 "register_operand" "=rk")
3149 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3151 (match_operand:SHORT
2 "register_operand" "r")))))]
3153 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3154 [(set_attr "type" "alu_ext")]
3157 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3158 [(set (match_operand:GPI
0 "register_operand" "=rk")
3159 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3160 (ashift:GPI (ANY_EXTEND:GPI
3161 (match_operand:ALLX
2 "register_operand" "r"))
3162 (match_operand
3 "aarch64_imm3" "Ui3"))))]
3164 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
3165 [(set_attr "type" "alu_ext")]
3168 ;; zero_extend version of above
3169 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3170 [(set (match_operand:DI
0 "register_operand" "=rk")
3172 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3173 (ashift:SI (ANY_EXTEND:SI
3174 (match_operand:SHORT
2 "register_operand" "r"))
3175 (match_operand
3 "aarch64_imm3" "Ui3")))))]
3177 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
3178 [(set_attr "type" "alu_ext")]
3181 (define_insn "*sub_<optab><mode>_multp2"
3182 [(set (match_operand:GPI
0 "register_operand" "=rk")
3183 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3185 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3186 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3187 (match_operand
3 "const_int_operand" "n")
3189 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
3190 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
3191 [(set_attr "type" "alu_ext")]
3194 ;; zero_extend version of above
3195 (define_insn "*sub_<optab>si_multp2_uxtw"
3196 [(set (match_operand:DI
0 "register_operand" "=rk")
3198 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3200 (mult:SI (match_operand:SI
1 "register_operand" "r")
3201 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3202 (match_operand
3 "const_int_operand" "n")
3204 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
3205 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
3206 [(set_attr "type" "alu_ext")]
3209 ;; The hardware description is op1 + ~op2 + C.
3210 ;; = op1 + (-op2 +
1) + (
1 - !C)
3211 ;; = op1 - op2 -
1 +
1 - !C
3212 ;; = op1 - op2 - !C.
3213 ;; We describe the latter.
3215 (define_insn "*sub<mode>
3_carryin0"
3216 [(set (match_operand:GPI
0 "register_operand" "=r")
3218 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3219 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
3221 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
3222 [(set_attr "type" "adc_reg")]
3225 ;; zero_extend version of the above
3226 (define_insn "*subsi3_carryin_uxtw"
3227 [(set (match_operand:DI
0 "register_operand" "=r")
3230 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3231 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
3233 "sbc
\\t%w0, %w1, wzr"
3234 [(set_attr "type" "adc_reg")]
3237 (define_expand "sub<mode>
3_carryin"
3238 [(set (match_operand:GPI
0 "register_operand")
3241 (match_operand:GPI
1 "aarch64_reg_or_zero")
3242 (match_operand:GPI
2 "register_operand"))
3243 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
3248 (define_insn "*sub<mode>
3_carryin"
3249 [(set (match_operand:GPI
0 "register_operand" "=r")
3252 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3253 (match_operand:GPI
2 "register_operand" "r"))
3254 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3257 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3258 [(set_attr "type" "adc_reg")]
3261 ;; zero_extend version of the above
3262 (define_insn "*subsi3_carryin_uxtw"
3263 [(set (match_operand:DI
0 "register_operand" "=r")
3267 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3268 (match_operand:SI
2 "register_operand" "r"))
3269 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
3272 "sbc
\\t%w0, %w1, %w2"
3273 [(set_attr "type" "adc_reg")]
3276 (define_insn "*sub<mode>
3_carryin_alt"
3277 [(set (match_operand:GPI
0 "register_operand" "=r")
3280 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3281 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
3282 (match_operand:GPI
2 "register_operand" "r")))]
3284 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3285 [(set_attr "type" "adc_reg")]
3288 ;; zero_extend version of the above
3289 (define_insn "*subsi3_carryin_alt_uxtw"
3290 [(set (match_operand:DI
0 "register_operand" "=r")
3294 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3295 (match_operand:SI
3 "aarch64_borrow_operation" ""))
3296 (match_operand:SI
2 "register_operand" "r"))))]
3298 "sbc
\\t%w0, %w1, %w2"
3299 [(set_attr "type" "adc_reg")]
3302 (define_expand "usub<GPI:mode>
3_carryinC"
3304 [(set (reg:CC CC_REGNUM)
3307 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3310 (match_operand:GPI
2 "register_operand"))
3311 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0)))))
3312 (set (match_operand:GPI
0 "register_operand")
3314 (minus:GPI (match_dup
1) (match_dup
2))
3315 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3319 (define_insn "*usub<GPI:mode>
3_carryinC_z1"
3320 [(set (reg:CC CC_REGNUM)
3325 (match_operand:GPI
1 "register_operand" "r"))
3326 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))))
3327 (set (match_operand:GPI
0 "register_operand" "=r")
3329 (neg:GPI (match_dup
1))
3330 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3332 "sbcs
\\t%<w>
0, <w>zr, %<w>
1"
3333 [(set_attr "type" "adc_reg")]
3336 (define_insn "*usub<GPI:mode>
3_carryinC_z2"
3337 [(set (reg:CC CC_REGNUM)
3340 (match_operand:GPI
1 "register_operand" "r"))
3341 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3342 (set (match_operand:GPI
0 "register_operand" "=r")
3345 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3347 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3348 [(set_attr "type" "adc_reg")]
3351 (define_insn "*usub<GPI:mode>
3_carryinC"
3352 [(set (reg:CC CC_REGNUM)
3355 (match_operand:GPI
1 "register_operand" "r"))
3358 (match_operand:GPI
2 "register_operand" "r"))
3359 (match_operand:<DWI>
3 "aarch64_borrow_operation" ""))))
3360 (set (match_operand:GPI
0 "register_operand" "=r")
3362 (minus:GPI (match_dup
1) (match_dup
2))
3363 (match_operand:GPI
4 "aarch64_borrow_operation" "")))]
3365 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3366 [(set_attr "type" "adc_reg")]
3369 (define_expand "sub<GPI:mode>
3_carryinV"
3371 [(set (reg:CC_V CC_REGNUM)
3375 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3378 (match_operand:GPI
2 "register_operand"))
3379 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0))))
3381 (minus:GPI (match_dup
1)
3382 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))
3384 (set (match_operand:GPI
0 "register_operand")
3386 (minus:GPI (match_dup
1) (match_dup
2))
3387 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3391 (define_insn "*sub<mode>
3_carryinV_z2"
3392 [(set (reg:CC_V CC_REGNUM)
3395 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
3396 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))
3398 (minus:GPI (match_dup
1)
3399 (match_operand:GPI
3 "aarch64_borrow_operation" "")))))
3400 (set (match_operand:GPI
0 "register_operand" "=r")
3402 (match_dup
1) (match_dup
3)))]
3404 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3405 [(set_attr "type" "adc_reg")]
3408 (define_insn "*sub<mode>
3_carryinV"
3409 [(set (reg:CC_V CC_REGNUM)
3413 (match_operand:GPI
1 "register_operand" "r"))
3416 (match_operand:GPI
2 "register_operand" "r"))
3417 (match_operand:<DWI>
3 "aarch64_borrow_operation" "")))
3421 (plus:GPI (match_operand:GPI
4 "aarch64_borrow_operation" "")
3423 (set (match_operand:GPI
0 "register_operand" "=r")
3425 (minus:GPI (match_dup
1) (match_dup
2))
3428 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3429 [(set_attr "type" "adc_reg")]
3432 (define_insn "*sub_uxt<mode>_shift2"
3433 [(set (match_operand:GPI
0 "register_operand" "=rk")
3434 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3436 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
3437 (match_operand
2 "aarch64_imm3" "Ui3"))
3438 (match_operand
3 "const_int_operand" "n"))))]
3439 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3441 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3442 INTVAL (operands[
3])));
3443 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
3444 [(set_attr "type" "alu_ext")]
3447 ;; zero_extend version of above
3448 (define_insn "*sub_uxtsi_shift2_uxtw"
3449 [(set (match_operand:DI
0 "register_operand" "=rk")
3451 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3453 (ashift:SI (match_operand:SI
1 "register_operand" "r")
3454 (match_operand
2 "aarch64_imm3" "Ui3"))
3455 (match_operand
3 "const_int_operand" "n")))))]
3456 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3458 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3459 INTVAL (operands[
3])));
3460 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
3461 [(set_attr "type" "alu_ext")]
3464 (define_insn "*sub_uxt<mode>_multp2"
3465 [(set (match_operand:GPI
0 "register_operand" "=rk")
3466 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3468 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3469 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3470 (match_operand
3 "const_int_operand" "n"))))]
3471 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3473 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3474 INTVAL (operands[
3])));
3475 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
3476 [(set_attr "type" "alu_ext")]
3479 ;; zero_extend version of above
3480 (define_insn "*sub_uxtsi_multp2_uxtw"
3481 [(set (match_operand:DI
0 "register_operand" "=rk")
3483 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3485 (mult:SI (match_operand:SI
1 "register_operand" "r")
3486 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3487 (match_operand
3 "const_int_operand" "n")))))]
3488 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3490 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3491 INTVAL (operands[
3])));
3492 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
3493 [(set_attr "type" "alu_ext")]
3496 (define_expand "abs<mode>
2"
3497 [(match_operand:GPI
0 "register_operand")
3498 (match_operand:GPI
1 "register_operand")]
3501 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
3502 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3503 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
3508 (define_insn "neg<mode>
2"
3509 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3510 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3514 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
3515 [(set_attr "type" "alu_sreg, neon_neg<q>")
3516 (set_attr "arch" "*,simd")]
3519 ;; zero_extend version of above
3520 (define_insn "*negsi2_uxtw"
3521 [(set (match_operand:DI
0 "register_operand" "=r")
3522 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
3525 [(set_attr "type" "alu_sreg")]
3528 (define_insn "*ngc<mode>"
3529 [(set (match_operand:GPI
0 "register_operand" "=r")
3531 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
3532 (match_operand:GPI
1 "register_operand" "r")))]
3534 "ngc
\\t%<w>
0, %<w>
1"
3535 [(set_attr "type" "adc_reg")]
3538 (define_insn "*ngcsi_uxtw"
3539 [(set (match_operand:DI
0 "register_operand" "=r")
3542 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
3543 (match_operand:SI
1 "register_operand" "r"))))]
3546 [(set_attr "type" "adc_reg")]
3549 (define_insn "neg<mode>
2_compare0"
3550 [(set (reg:CC_NZ CC_REGNUM)
3551 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3553 (set (match_operand:GPI
0 "register_operand" "=r")
3554 (neg:GPI (match_dup
1)))]
3556 "negs
\\t%<w>
0, %<w>
1"
3557 [(set_attr "type" "alus_sreg")]
3560 ;; zero_extend version of above
3561 (define_insn "*negsi2_compare0_uxtw"
3562 [(set (reg:CC_NZ CC_REGNUM)
3563 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
3565 (set (match_operand:DI
0 "register_operand" "=r")
3566 (zero_extend:DI (neg:SI (match_dup
1))))]
3569 [(set_attr "type" "alus_sreg")]
3572 (define_insn "*neg_<shift><mode>
3_compare0"
3573 [(set (reg:CC_NZ CC_REGNUM)
3575 (neg:GPI (ASHIFT:GPI
3576 (match_operand:GPI
1 "register_operand" "r")
3577 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3579 (set (match_operand:GPI
0 "register_operand" "=r")
3580 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
3582 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
3583 [(set_attr "type" "alus_shift_imm")]
3586 (define_insn "*neg_<shift>_<mode>
2"
3587 [(set (match_operand:GPI
0 "register_operand" "=r")
3588 (neg:GPI (ASHIFT:GPI
3589 (match_operand:GPI
1 "register_operand" "r")
3590 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3592 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
3593 [(set_attr "type" "alu_shift_imm")]
3596 ;; zero_extend version of above
3597 (define_insn "*neg_<shift>_si2_uxtw"
3598 [(set (match_operand:DI
0 "register_operand" "=r")
3601 (match_operand:SI
1 "register_operand" "r")
3602 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3604 "neg
\\t%w0, %w1, <shift> %
2"
3605 [(set_attr "type" "alu_shift_imm")]
3608 (define_insn "*neg_mul_imm_<mode>
2"
3609 [(set (match_operand:GPI
0 "register_operand" "=r")
3611 (match_operand:GPI
1 "register_operand" "r")
3612 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3614 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
3615 [(set_attr "type" "alu_shift_imm")]
3618 ;; zero_extend version of above
3619 (define_insn "*neg_mul_imm_si2_uxtw"
3620 [(set (match_operand:DI
0 "register_operand" "=r")
3623 (match_operand:SI
1 "register_operand" "r")
3624 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3626 "neg
\\t%w0, %w1, lsl %p2"
3627 [(set_attr "type" "alu_shift_imm")]
3630 (define_insn "mul<mode>
3"
3631 [(set (match_operand:GPI
0 "register_operand" "=r")
3632 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3633 (match_operand:GPI
2 "register_operand" "r")))]
3635 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
3636 [(set_attr "type" "mul")]
3639 ;; zero_extend version of above
3640 (define_insn "*mulsi3_uxtw"
3641 [(set (match_operand:DI
0 "register_operand" "=r")
3643 (mult:SI (match_operand:SI
1 "register_operand" "r")
3644 (match_operand:SI
2 "register_operand" "r"))))]
3646 "mul
\\t%w0, %w1, %w2"
3647 [(set_attr "type" "mul")]
3650 (define_insn "madd<mode>"
3651 [(set (match_operand:GPI
0 "register_operand" "=r")
3652 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3653 (match_operand:GPI
2 "register_operand" "r"))
3654 (match_operand:GPI
3 "register_operand" "r")))]
3656 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3657 [(set_attr "type" "mla")]
3660 ;; zero_extend version of above
3661 (define_insn "*maddsi_uxtw"
3662 [(set (match_operand:DI
0 "register_operand" "=r")
3664 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
3665 (match_operand:SI
2 "register_operand" "r"))
3666 (match_operand:SI
3 "register_operand" "r"))))]
3668 "madd
\\t%w0, %w1, %w2, %w3"
3669 [(set_attr "type" "mla")]
3672 (define_insn "*msub<mode>"
3673 [(set (match_operand:GPI
0 "register_operand" "=r")
3674 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3675 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3676 (match_operand:GPI
2 "register_operand" "r"))))]
3679 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3680 [(set_attr "type" "mla")]
3683 ;; zero_extend version of above
3684 (define_insn "*msubsi_uxtw"
3685 [(set (match_operand:DI
0 "register_operand" "=r")
3687 (minus:SI (match_operand:SI
3 "register_operand" "r")
3688 (mult:SI (match_operand:SI
1 "register_operand" "r")
3689 (match_operand:SI
2 "register_operand" "r")))))]
3692 "msub
\\t%w0, %w1, %w2, %w3"
3693 [(set_attr "type" "mla")]
3696 (define_insn "*mul<mode>_neg"
3697 [(set (match_operand:GPI
0 "register_operand" "=r")
3698 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3699 (match_operand:GPI
2 "register_operand" "r")))]
3702 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3703 [(set_attr "type" "mul")]
3706 ;; zero_extend version of above
3707 (define_insn "*mulsi_neg_uxtw"
3708 [(set (match_operand:DI
0 "register_operand" "=r")
3710 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3711 (match_operand:SI
2 "register_operand" "r"))))]
3714 "mneg
\\t%w0, %w1, %w2"
3715 [(set_attr "type" "mul")]
3718 (define_insn "<su_optab>mulsidi3"
3719 [(set (match_operand:DI
0 "register_operand" "=r")
3720 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3721 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3723 "<su>mull
\\t%
0, %w1, %w2"
3724 [(set_attr "type" "<su>mull")]
3727 (define_insn "<su_optab>maddsidi4"
3728 [(set (match_operand:DI
0 "register_operand" "=r")
3730 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3731 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3732 (match_operand:DI
3 "register_operand" "r")))]
3734 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3735 [(set_attr "type" "<su>mlal")]
3738 (define_insn "<su_optab>msubsidi4"
3739 [(set (match_operand:DI
0 "register_operand" "=r")
3741 (match_operand:DI
3 "register_operand" "r")
3742 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3744 (match_operand:SI
2 "register_operand" "r")))))]
3746 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3747 [(set_attr "type" "<su>mlal")]
3750 (define_insn "*<su_optab>mulsidi_neg"
3751 [(set (match_operand:DI
0 "register_operand" "=r")
3753 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3754 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3756 "<su>mnegl
\\t%
0, %w1, %w2"
3757 [(set_attr "type" "<su>mull")]
3760 (define_expand "<su_optab>mulditi3"
3761 [(set (match_operand:TI
0 "register_operand")
3762 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3763 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3766 rtx low = gen_reg_rtx (DImode);
3767 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3769 rtx high = gen_reg_rtx (DImode);
3770 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3772 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3773 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3777 ;; The default expansion of multi3 using umuldi3_highpart will perform
3778 ;; the additions in an order that fails to combine into two madd insns.
3779 (define_expand "multi3"
3780 [(set (match_operand:TI
0 "register_operand")
3781 (mult:TI (match_operand:TI
1 "register_operand")
3782 (match_operand:TI
2 "register_operand")))]
3785 rtx l0 = gen_reg_rtx (DImode);
3786 rtx l1 = gen_lowpart (DImode, operands[
1]);
3787 rtx l2 = gen_lowpart (DImode, operands[
2]);
3788 rtx h0 = gen_reg_rtx (DImode);
3789 rtx h1 = gen_highpart (DImode, operands[
1]);
3790 rtx h2 = gen_highpart (DImode, operands[
2]);
3792 emit_insn (gen_muldi3 (l0, l1, l2));
3793 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3794 emit_insn (gen_madddi (h0, h1, l2, h0));
3795 emit_insn (gen_madddi (h0, l1, h2, h0));
3797 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3798 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3802 (define_insn "<su>muldi3_highpart"
3803 [(set (match_operand:DI
0 "register_operand" "=r")
3807 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3808 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3811 "<su>mulh
\\t%
0, %
1, %
2"
3812 [(set_attr "type" "<su>mull")]
3815 (define_insn "<su_optab>div<mode>
3"
3816 [(set (match_operand:GPI
0 "register_operand" "=r")
3817 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3818 (match_operand:GPI
2 "register_operand" "r")))]
3820 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3821 [(set_attr "type" "<su>div")]
3824 ;; zero_extend version of above
3825 (define_insn "*<su_optab>divsi3_uxtw"
3826 [(set (match_operand:DI
0 "register_operand" "=r")
3828 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3829 (match_operand:SI
2 "register_operand" "r"))))]
3831 "<su>div
\\t%w0, %w1, %w2"
3832 [(set_attr "type" "<su>div")]
3835 ;; -------------------------------------------------------------------
3837 ;; -------------------------------------------------------------------
3839 (define_insn "cmp<mode>"
3840 [(set (reg:CC CC_REGNUM)
3841 (compare:CC (match_operand:GPI
0 "register_operand" "rk,rk,rk")
3842 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3848 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3851 (define_insn "fcmp<mode>"
3852 [(set (reg:CCFP CC_REGNUM)
3853 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3854 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3858 fcmp
\\t%<s>
0, %<s>
1"
3859 [(set_attr "type" "fcmp<s>")]
3862 (define_insn "fcmpe<mode>"
3863 [(set (reg:CCFPE CC_REGNUM)
3864 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3865 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3869 fcmpe
\\t%<s>
0, %<s>
1"
3870 [(set_attr "type" "fcmp<s>")]
3873 (define_insn "*cmp_swp_<shift>_reg<mode>"
3874 [(set (reg:CC_SWP CC_REGNUM)
3875 (compare:CC_SWP (ASHIFT:GPI
3876 (match_operand:GPI
0 "register_operand" "r")
3877 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3878 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3880 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3881 [(set_attr "type" "alus_shift_imm")]
3884 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3885 [(set (reg:CC_SWP CC_REGNUM)
3886 (compare:CC_SWP (ANY_EXTEND:GPI
3887 (match_operand:ALLX
0 "register_operand" "r"))
3888 (match_operand:GPI
1 "register_operand" "r")))]
3890 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3891 [(set_attr "type" "alus_ext")]
3894 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3895 [(set (reg:CC_SWP CC_REGNUM)
3896 (compare:CC_SWP (ashift:GPI
3898 (match_operand:ALLX
0 "register_operand" "r"))
3899 (match_operand
1 "aarch64_imm3" "Ui3"))
3900 (match_operand:GPI
2 "register_operand" "r")))]
3902 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3903 [(set_attr "type" "alus_ext")]
3906 ;; -------------------------------------------------------------------
3907 ;; Store-flag and conditional select insns
3908 ;; -------------------------------------------------------------------
3910 (define_expand "cstore<mode>
4"
3911 [(set (match_operand:SI
0 "register_operand")
3912 (match_operator:SI
1 "aarch64_comparison_operator"
3913 [(match_operand:GPI
2 "register_operand")
3914 (match_operand:GPI
3 "aarch64_plus_operand")]))]
3917 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3919 operands[
3] = const0_rtx;
3923 (define_expand "cstorecc4"
3924 [(set (match_operand:SI
0 "register_operand")
3925 (match_operator
1 "aarch64_comparison_operator_mode"
3926 [(match_operand
2 "cc_register")
3927 (match_operand
3 "const0_operand")]))]
3930 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
3935 (define_expand "cstore<mode>
4"
3936 [(set (match_operand:SI
0 "register_operand")
3937 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3938 [(match_operand:GPF
2 "register_operand")
3939 (match_operand:GPF
3 "aarch64_fp_compare_operand")]))]
3942 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3944 operands[
3] = const0_rtx;
3948 (define_insn "aarch64_cstore<mode>"
3949 [(set (match_operand:ALLI
0 "register_operand" "=r")
3950 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3951 [(match_operand
2 "cc_register" "") (const_int
0)]))]
3954 [(set_attr "type" "csel")]
3957 ;; For a
24-bit immediate CST we can optimize the compare for equality
3958 ;; and branch sequence from:
3960 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
3963 ;; into the shorter:
3964 ;; sub x0, x1, #(CST &
0xfff000)
3965 ;; subs x0, x0, #(CST &
0x000fff)
3966 ;; cset x2, <ne, eq>.
3967 (define_insn_and_split "*compare_cstore<mode>_insn"
3968 [(set (match_operand:GPI
0 "register_operand" "=r")
3969 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
3970 (match_operand:GPI
2 "aarch64_imm24" "n")))
3971 (clobber (reg:CC CC_REGNUM))]
3972 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
3973 && !aarch64_plus_operand (operands[
2], <MODE>mode)
3974 && !reload_completed"
3979 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
3980 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
3981 rtx tmp = gen_reg_rtx (<MODE>mode);
3982 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
3983 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3984 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3985 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3986 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
3989 [(set_attr "type" "csel")]
3992 ;; zero_extend version of the above
3993 (define_insn "*cstoresi_insn_uxtw"
3994 [(set (match_operand:DI
0 "register_operand" "=r")
3996 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3997 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4000 [(set_attr "type" "csel")]
4003 (define_insn "cstore<mode>_neg"
4004 [(set (match_operand:ALLI
0 "register_operand" "=r")
4005 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
4006 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4008 "csetm
\\t%<w>
0, %m1"
4009 [(set_attr "type" "csel")]
4012 ;; zero_extend version of the above
4013 (define_insn "*cstoresi_neg_uxtw"
4014 [(set (match_operand:DI
0 "register_operand" "=r")
4016 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
4017 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
4020 [(set_attr "type" "csel")]
4023 (define_expand "cmov<mode>
6"
4024 [(set (match_operand:GPI
0 "register_operand")
4026 (match_operator
1 "aarch64_comparison_operator"
4027 [(match_operand:GPI
2 "register_operand")
4028 (match_operand:GPI
3 "aarch64_plus_operand")])
4029 (match_operand:GPI
4 "register_operand")
4030 (match_operand:GPI
5 "register_operand")))]
4033 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4035 operands[
3] = const0_rtx;
4039 (define_expand "cmov<mode>
6"
4040 [(set (match_operand:GPF
0 "register_operand")
4042 (match_operator
1 "aarch64_comparison_operator"
4043 [(match_operand:GPF
2 "register_operand")
4044 (match_operand:GPF
3 "aarch64_fp_compare_operand")])
4045 (match_operand:GPF
4 "register_operand")
4046 (match_operand:GPF
5 "register_operand")))]
4049 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4051 operands[
3] = const0_rtx;
4055 (define_insn "*cmov<mode>_insn"
4056 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
4058 (match_operator
1 "aarch64_comparison_operator"
4059 [(match_operand
2 "cc_register" "") (const_int
0)])
4060 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4061 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
4062 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4063 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4064 ;; Final two alternatives should be unreachable, but included for completeness
4066 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
4067 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
4068 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
4069 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
4070 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
4073 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4076 ;; zero_extend version of above
4077 (define_insn "*cmovsi_insn_uxtw"
4078 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
4081 (match_operator
1 "aarch64_comparison_operator"
4082 [(match_operand
2 "cc_register" "") (const_int
0)])
4083 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4084 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4085 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4086 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4087 ;; Final two alternatives should be unreachable, but included for completeness
4089 csel
\\t%w0, %w3, %w4, %m1
4090 csinv
\\t%w0, %w3, wzr, %m1
4091 csinv
\\t%w0, %w4, wzr, %M1
4092 csinc
\\t%w0, %w3, wzr, %m1
4093 csinc
\\t%w0, %w4, wzr, %M1
4096 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4099 (define_insn "*cmovdi_insn_uxtw"
4100 [(set (match_operand:DI
0 "register_operand" "=r")
4102 (match_operator
1 "aarch64_comparison_operator"
4103 [(match_operand
2 "cc_register" "") (const_int
0)])
4104 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
4105 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
4107 "csel
\\t%w0, %w3, %w4, %m1"
4108 [(set_attr "type" "csel")]
4111 (define_insn "*cmov<mode>_insn"
4112 [(set (match_operand:GPF
0 "register_operand" "=w")
4114 (match_operator
1 "aarch64_comparison_operator"
4115 [(match_operand
2 "cc_register" "") (const_int
0)])
4116 (match_operand:GPF
3 "register_operand" "w")
4117 (match_operand:GPF
4 "register_operand" "w")))]
4119 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
4120 [(set_attr "type" "fcsel")]
4123 (define_expand "mov<mode>cc"
4124 [(set (match_operand:ALLI
0 "register_operand")
4125 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator")
4126 (match_operand:ALLI
2 "register_operand")
4127 (match_operand:ALLI
3 "register_operand")))]
4131 enum rtx_code code = GET_CODE (operands[
1]);
4133 if (code == UNEQ || code == LTGT)
4136 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4137 XEXP (operands[
1],
1));
4138 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4142 (define_expand "mov<GPF:mode><GPI:mode>cc"
4143 [(set (match_operand:GPI
0 "register_operand")
4144 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4145 (match_operand:GPF
2 "register_operand")
4146 (match_operand:GPF
3 "register_operand")))]
4150 enum rtx_code code = GET_CODE (operands[
1]);
4152 if (code == UNEQ || code == LTGT)
4155 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4156 XEXP (operands[
1],
1));
4157 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4161 (define_expand "mov<mode>cc"
4162 [(set (match_operand:GPF
0 "register_operand")
4163 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator")
4164 (match_operand:GPF
2 "register_operand")
4165 (match_operand:GPF
3 "register_operand")))]
4169 enum rtx_code code = GET_CODE (operands[
1]);
4171 if (code == UNEQ || code == LTGT)
4174 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4175 XEXP (operands[
1],
1));
4176 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4180 (define_expand "<neg_not_op><mode>cc"
4181 [(set (match_operand:GPI
0 "register_operand")
4182 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4183 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand"))
4184 (match_operand:GPI
3 "register_operand")))]
4188 enum rtx_code code = GET_CODE (operands[
1]);
4190 if (code == UNEQ || code == LTGT)
4193 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4194 XEXP (operands[
1],
1));
4195 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4199 ;; CRC32 instructions.
4200 (define_insn "aarch64_<crc_variant>"
4201 [(set (match_operand:SI
0 "register_operand" "=r")
4202 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
4203 (match_operand:<crc_mode>
2 "register_operand" "r")]
4207 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
4208 return "<crc_variant>
\\t%w0, %w1, %x2";
4210 return "<crc_variant>
\\t%w0, %w1, %w2";
4212 [(set_attr "type" "crc")]
4215 (define_insn "*csinc2<mode>_insn"
4216 [(set (match_operand:GPI
0 "register_operand" "=r")
4217 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
4218 (match_operand:GPI
1 "register_operand" "r")))]
4220 "cinc
\\t%<w>
0, %<w>
1, %m2"
4221 [(set_attr "type" "csel")]
4224 (define_insn "csinc3<mode>_insn"
4225 [(set (match_operand:GPI
0 "register_operand" "=r")
4227 (match_operand
1 "aarch64_comparison_operation" "")
4228 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
4230 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4232 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4233 [(set_attr "type" "csel")]
4236 (define_insn "*csinv3<mode>_insn"
4237 [(set (match_operand:GPI
0 "register_operand" "=r")
4239 (match_operand
1 "aarch64_comparison_operation" "")
4240 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
4241 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4243 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4244 [(set_attr "type" "csel")]
4247 (define_insn "csneg3_uxtw_insn"
4248 [(set (match_operand:DI
0 "register_operand" "=r")
4251 (match_operand
1 "aarch64_comparison_operation" "")
4252 (neg:SI (match_operand:SI
2 "register_operand" "r"))
4253 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
4255 "csneg
\\t%w0, %w3, %w2, %M1"
4256 [(set_attr "type" "csel")]
4259 (define_insn "csneg3<mode>_insn"
4260 [(set (match_operand:GPI
0 "register_operand" "=r")
4262 (match_operand
1 "aarch64_comparison_operation" "")
4263 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
4264 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4266 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4267 [(set_attr "type" "csel")]
4270 ;; If X can be loaded by a single CNT[BHWD] instruction,
4274 ;; is equivalent to:
4276 ;; TMP = UQDEC[BHWD] (B, X)
4279 ;; Defining the pattern this way means that:
4281 ;; A = UMAX (B, X) - X
4285 ;; TMP1 = UQDEC[BHWD] (B, X)
4289 ;; which combine can optimize to:
4291 ;; A = UQDEC[BHWD] (B, X)
4293 ;; We don't use match_operand predicates because the order of the operands
4294 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4295 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4296 (define_expand "umax<mode>
3"
4297 [(set (match_operand:GPI
0 "register_operand")
4298 (umax:GPI (match_operand:GPI
1 "")
4299 (match_operand:GPI
2 "")))]
4302 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
4303 std::swap (operands[
1], operands[
2]);
4304 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
4306 rtx temp = gen_reg_rtx (<MODE>mode);
4307 operands[
1] = force_reg (<MODE>mode, operands[
1]);
4308 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
4309 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
4314 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4315 (define_insn "aarch64_uqdec<mode>"
4316 [(set (match_operand:GPI
0 "register_operand" "=r")
4318 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
4319 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
4323 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
4327 ;; -------------------------------------------------------------------
4328 ;; Logical operations
4329 ;; -------------------------------------------------------------------
4332 (define_insn_and_split "*aarch64_and<mode>_imm2"
4333 [(set (match_operand:GPI
0 "register_operand" "=rk")
4334 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
4335 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
4341 HOST_WIDE_INT val = INTVAL (operands[
2]);
4342 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4343 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4345 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
4346 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
4351 (define_insn "<optab><mode>
3"
4352 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
4353 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
4354 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
4357 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
4358 <logical>
\\t%<w>
0, %<w>
1, %
2
4359 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
4360 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4361 (set_attr "arch" "*,*,simd")]
4364 ;; zero_extend version of above
4365 (define_insn "*<optab>si3_uxtw"
4366 [(set (match_operand:DI
0 "register_operand" "=r,rk")
4368 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
4369 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
4372 <logical>
\\t%w0, %w1, %w2
4373 <logical>
\\t%w0, %w1, %
2"
4374 [(set_attr "type" "logic_reg,logic_imm")]
4377 (define_insn "*and<mode>
3_compare0"
4378 [(set (reg:CC_NZ CC_REGNUM)
4380 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
4381 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
4383 (set (match_operand:GPI
0 "register_operand" "=r,r")
4384 (and:GPI (match_dup
1) (match_dup
2)))]
4387 ands
\\t%<w>
0, %<w>
1, %<w>
2
4388 ands
\\t%<w>
0, %<w>
1, %
2"
4389 [(set_attr "type" "logics_reg,logics_imm")]
4392 ;; zero_extend version of above
4393 (define_insn "*andsi3_compare0_uxtw"
4394 [(set (reg:CC_NZ CC_REGNUM)
4396 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
4397 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
4399 (set (match_operand:DI
0 "register_operand" "=r,r")
4400 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
4403 ands
\\t%w0, %w1, %w2
4404 ands
\\t%w0, %w1, %
2"
4405 [(set_attr "type" "logics_reg,logics_imm")]
4408 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
4409 [(set (reg:CC_NZ CC_REGNUM)
4412 (match_operand:GPI
1 "register_operand" "r")
4413 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4414 (match_operand:GPI
3 "register_operand" "r"))
4416 (set (match_operand:GPI
0 "register_operand" "=r")
4417 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
4419 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4420 [(set_attr "type" "logics_shift_imm")]
4423 ;; zero_extend version of above
4424 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4425 [(set (reg:CC_NZ CC_REGNUM)
4428 (match_operand:SI
1 "register_operand" "r")
4429 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4430 (match_operand:SI
3 "register_operand" "r"))
4432 (set (match_operand:DI
0 "register_operand" "=r")
4433 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
4436 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4437 [(set_attr "type" "logics_shift_imm")]
4440 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
4441 [(set (match_operand:GPI
0 "register_operand" "=r")
4442 (LOGICAL:GPI (SHIFT:GPI
4443 (match_operand:GPI
1 "register_operand" "r")
4444 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4445 (match_operand:GPI
3 "register_operand" "r")))]
4447 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4448 [(set_attr "type" "logic_shift_imm")]
4451 (define_insn "*<optab>_rol<mode>
3"
4452 [(set (match_operand:GPI
0 "register_operand" "=r")
4453 (LOGICAL:GPI (rotate:GPI
4454 (match_operand:GPI
1 "register_operand" "r")
4455 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4456 (match_operand:GPI
3 "register_operand" "r")))]
4458 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
4459 [(set_attr "type" "logic_shift_imm")]
4462 ;; zero_extend versions of above
4463 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4464 [(set (match_operand:DI
0 "register_operand" "=r")
4466 (LOGICAL:SI (SHIFT:SI
4467 (match_operand:SI
1 "register_operand" "r")
4468 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4469 (match_operand:SI
3 "register_operand" "r"))))]
4471 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4472 [(set_attr "type" "logic_shift_imm")]
4475 (define_insn "*<optab>_rolsi3_uxtw"
4476 [(set (match_operand:DI
0 "register_operand" "=r")
4478 (LOGICAL:SI (rotate:SI
4479 (match_operand:SI
1 "register_operand" "r")
4480 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4481 (match_operand:SI
3 "register_operand" "r"))))]
4483 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
4484 [(set_attr "type" "logic_shift_imm")]
4487 (define_insn "one_cmpl<mode>
2"
4488 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4489 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
4494 [(set_attr "type" "logic_reg,neon_logic")
4495 (set_attr "arch" "*,simd")]
4498 (define_insn "*one_cmpl_<optab><mode>
2"
4499 [(set (match_operand:GPI
0 "register_operand" "=r")
4500 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
4501 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
4503 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
4504 [(set_attr "type" "logic_shift_imm")]
4507 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4509 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
4510 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4511 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
4512 (match_operand:GPI
2 "register_operand" "r,w")))]
4515 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
4516 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
4517 [(set_attr "type" "logic_reg,neon_logic")
4518 (set_attr "arch" "*,simd")]
4521 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4522 [(set (match_operand:DI
0 "register_operand" "=r")
4524 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
4525 (match_operand:SI
2 "register_operand" "r"))))]
4527 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
4528 [(set_attr "type" "logic_reg")]
4531 (define_insn "*xor_one_cmplsidi3_ze"
4532 [(set (match_operand:DI
0 "register_operand" "=r")
4534 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
4535 (match_operand:SI
2 "register_operand" "r")))))]
4537 "eon
\\t%w0, %w1, %w2"
4538 [(set_attr "type" "logic_reg")]
4541 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4542 ;; eon does not operate on SIMD registers so the vector variant must be split.
4543 (define_insn_and_split "*xor_one_cmpl<mode>
3"
4544 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4545 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
4546 (match_operand:GPI
2 "register_operand" "r,w"))))]
4549 eon
\\t%<w>
0, %<w>
1, %<w>
2
4551 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
4552 [(set (match_operand:GPI
0 "register_operand" "=w")
4553 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
4554 (match_operand:GPI
2 "register_operand" "w")))
4555 (set (match_dup
0) (not:GPI (match_dup
0)))]
4557 [(set_attr "type" "logic_reg,multiple")
4558 (set_attr "arch" "*,simd")]
4561 (define_insn "*and_one_cmpl<mode>
3_compare0"
4562 [(set (reg:CC_NZ CC_REGNUM)
4565 (match_operand:GPI
1 "register_operand" "r"))
4566 (match_operand:GPI
2 "register_operand" "r"))
4568 (set (match_operand:GPI
0 "register_operand" "=r")
4569 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
4571 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
4572 [(set_attr "type" "logics_reg")]
4575 ;; zero_extend version of above
4576 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4577 [(set (reg:CC_NZ CC_REGNUM)
4580 (match_operand:SI
1 "register_operand" "r"))
4581 (match_operand:SI
2 "register_operand" "r"))
4583 (set (match_operand:DI
0 "register_operand" "=r")
4584 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
4586 "bics
\\t%w0, %w2, %w1"
4587 [(set_attr "type" "logics_reg")]
4590 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
4591 [(set (reg:CC_NZ CC_REGNUM)
4594 (match_operand:GPI
0 "register_operand" "r"))
4595 (match_operand:GPI
1 "register_operand" "r"))
4598 "bics
\\t<w>zr, %<w>
1, %<w>
0"
4599 [(set_attr "type" "logics_reg")]
4602 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
4603 [(set (match_operand:GPI
0 "register_operand" "=r")
4604 (LOGICAL:GPI (not:GPI
4606 (match_operand:GPI
1 "register_operand" "r")
4607 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4608 (match_operand:GPI
3 "register_operand" "r")))]
4610 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4611 [(set_attr "type" "logic_shift_imm")]
4614 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
4615 [(set (match_operand:GPI
0 "register_operand" "=r")
4618 (match_operand:GPI
1 "register_operand" "r")
4619 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4620 (match_operand:GPI
3 "register_operand" "r"))))]
4622 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4623 [(set_attr "type" "logic_shift_imm")]
4626 ;; Zero-extend version of the above.
4627 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4628 [(set (match_operand:DI
0 "register_operand" "=r")
4632 (match_operand:SI
1 "register_operand" "r")
4633 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4634 (match_operand:SI
3 "register_operand" "r")))))]
4636 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4637 [(set_attr "type" "logic_shift_imm")]
4640 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
4641 [(set (reg:CC_NZ CC_REGNUM)
4645 (match_operand:GPI
1 "register_operand" "r")
4646 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4647 (match_operand:GPI
3 "register_operand" "r"))
4649 (set (match_operand:GPI
0 "register_operand" "=r")
4652 (match_dup
1) (match_dup
2))) (match_dup
3)))]
4654 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4655 [(set_attr "type" "logics_shift_imm")]
4658 ;; zero_extend version of above
4659 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4660 [(set (reg:CC_NZ CC_REGNUM)
4664 (match_operand:SI
1 "register_operand" "r")
4665 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
4666 (match_operand:SI
3 "register_operand" "r"))
4668 (set (match_operand:DI
0 "register_operand" "=r")
4669 (zero_extend:DI (and:SI
4671 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
4673 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4674 [(set_attr "type" "logics_shift_imm")]
4677 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
4678 [(set (reg:CC_NZ CC_REGNUM)
4682 (match_operand:GPI
0 "register_operand" "r")
4683 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
4684 (match_operand:GPI
2 "register_operand" "r"))
4687 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
4688 [(set_attr "type" "logics_shift_imm")]
4691 (define_insn "clz<mode>
2"
4692 [(set (match_operand:GPI
0 "register_operand" "=r")
4693 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4695 "clz
\\t%<w>
0, %<w>
1"
4696 [(set_attr "type" "clz")]
4699 (define_expand "ffs<mode>
2"
4700 [(match_operand:GPI
0 "register_operand")
4701 (match_operand:GPI
1 "register_operand")]
4704 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4705 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4707 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4708 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4709 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4714 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4721 (define_expand "popcount<mode>
2"
4722 [(match_operand:GPI
0 "register_operand")
4723 (match_operand:GPI
1 "register_operand")]
4726 rtx v = gen_reg_rtx (V8QImode);
4727 rtx v1 = gen_reg_rtx (V8QImode);
4728 rtx r = gen_reg_rtx (QImode);
4729 rtx in = operands[
1];
4730 rtx out = operands[
0];
4731 if(<MODE>mode == SImode)
4734 tmp = gen_reg_rtx (DImode);
4735 /* If we have SImode, zero extend to DImode, pop count does
4736 not change if we have extra zeros. */
4737 emit_insn (gen_zero_extendsidi2 (tmp, in));
4740 emit_move_insn (v, gen_lowpart (V8QImode, in));
4741 emit_insn (gen_popcountv8qi2 (v1, v));
4742 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4743 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4747 (define_insn "clrsb<mode>
2"
4748 [(set (match_operand:GPI
0 "register_operand" "=r")
4749 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4751 "cls
\\t%<w>
0, %<w>
1"
4752 [(set_attr "type" "clz")]
4755 (define_insn "rbit<mode>
2"
4756 [(set (match_operand:GPI
0 "register_operand" "=r")
4757 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4759 "rbit
\\t%<w>
0, %<w>
1"
4760 [(set_attr "type" "rbit")]
4763 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4764 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4765 ;; expression and split after reload to enable scheduling them apart if
4768 (define_insn_and_split "ctz<mode>
2"
4769 [(set (match_operand:GPI
0 "register_operand" "=r")
4770 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4776 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4777 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4781 (define_insn "*and<mode>_compare0"
4782 [(set (reg:CC_NZ CC_REGNUM)
4784 (match_operand:SHORT
0 "register_operand" "r")
4787 "tst
\\t%<w>
0, <short_mask>"
4788 [(set_attr "type" "alus_imm")]
4791 (define_insn "*ands<GPI:mode>_compare0"
4792 [(set (reg:CC_NZ CC_REGNUM)
4794 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4796 (set (match_operand:GPI
0 "register_operand" "=r")
4797 (zero_extend:GPI (match_dup
1)))]
4799 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4800 [(set_attr "type" "alus_imm")]
4803 (define_insn "*and<mode>
3nr_compare0"
4804 [(set (reg:CC_NZ CC_REGNUM)
4806 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4807 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4813 [(set_attr "type" "logics_reg,logics_imm")]
4817 [(set (reg:CC_NZ CC_REGNUM)
4819 (and:GPI (match_operand:GPI
0 "register_operand")
4820 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4822 (clobber (match_operand:SI
2 "register_operand"))]
4824 [(set (match_dup
2) (match_dup
1))
4825 (set (reg:CC_NZ CC_REGNUM)
4827 (and:GPI (match_dup
0)
4832 (define_insn "*and<mode>
3nr_compare0_zextract"
4833 [(set (reg:CC_NZ CC_REGNUM)
4835 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4836 (match_operand:GPI
1 "const_int_operand" "n")
4837 (match_operand:GPI
2 "const_int_operand" "n"))
4839 "INTVAL (operands[
1]) >
0
4840 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4841 <= GET_MODE_BITSIZE (<MODE>mode))
4842 && aarch64_bitmask_imm (
4843 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4848 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4849 return "tst
\\t%<w>
0, %
1";
4851 [(set_attr "type" "logics_shift_imm")]
4854 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4855 [(set (reg:CC_NZ CC_REGNUM)
4858 (match_operand:GPI
0 "register_operand" "r")
4859 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4860 (match_operand:GPI
2 "register_operand" "r"))
4863 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4864 [(set_attr "type" "logics_shift_imm")]
4868 [(set (reg:CC_NZ CC_REGNUM)
4871 (match_operand:GPI
0 "register_operand")
4872 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4873 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4875 (clobber (match_operand:SI
3 "register_operand"))]
4877 [(set (match_dup
3) (match_dup
2))
4878 (set (reg:CC_NZ CC_REGNUM)
4887 ;; -------------------------------------------------------------------
4889 ;; -------------------------------------------------------------------
4891 (define_expand "<optab><mode>
3"
4892 [(set (match_operand:GPI
0 "register_operand")
4893 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4894 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4897 if (CONST_INT_P (operands[
2]))
4899 operands[
2] = GEN_INT (INTVAL (operands[
2])
4900 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4902 if (operands[
2] == const0_rtx)
4904 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4911 (define_expand "ashl<mode>
3"
4912 [(set (match_operand:SHORT
0 "register_operand")
4913 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4914 (match_operand:QI
2 "const_int_operand")))]
4917 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4919 if (operands[
2] == const0_rtx)
4921 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4927 (define_expand "rotr<mode>
3"
4928 [(set (match_operand:GPI
0 "register_operand")
4929 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4930 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4933 if (CONST_INT_P (operands[
2]))
4935 operands[
2] = GEN_INT (INTVAL (operands[
2])
4936 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4938 if (operands[
2] == const0_rtx)
4940 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4947 (define_expand "rotl<mode>
3"
4948 [(set (match_operand:GPI
0 "register_operand")
4949 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4950 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4953 /* (SZ - cnt) % SZ == -cnt % SZ */
4954 if (CONST_INT_P (operands[
2]))
4956 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
4957 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4958 if (operands[
2] == const0_rtx)
4960 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4965 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
4970 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4971 ;; they truncate the shift/rotate amount by the size of the registers they
4972 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
4973 ;; such redundant masking instructions. GCC can do that automatically when
4974 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4975 ;; because some of the SISD shift alternatives don't perform this truncations.
4976 ;; So this pattern exists to catch such cases.
4978 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
4979 [(set (match_operand:GPI
0 "register_operand" "=r")
4981 (match_operand:GPI
1 "register_operand" "r")
4982 (match_operator
4 "subreg_lowpart_operator"
4983 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
4984 (match_operand
3 "const_int_operand" "n"))])))]
4985 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
4986 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
4987 [(set_attr "type" "shift_reg")]
4990 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
4991 [(set (match_operand:GPI
0 "register_operand" "=&r")
4993 (match_operand:GPI
1 "register_operand" "r")
4994 (match_operator
4 "subreg_lowpart_operator"
4995 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
4996 (match_operand
3 "const_int_operand" "n")))])))]
4997 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
5002 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5003 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
5004 emit_insn (gen_negsi2 (tmp, operands[
2]));
5006 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
5007 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
5008 SUBREG_BYTE (operands[
4]));
5009 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
5014 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
5015 [(set (match_operand:GPI
0 "register_operand" "=&r")
5017 (match_operand:GPI
1 "register_operand" "r")
5018 (minus:QI (match_operand
2 "const_int_operand" "n")
5019 (match_operator
5 "subreg_lowpart_operator"
5020 [(and:SI (match_operand:SI
3 "register_operand" "r")
5021 (match_operand
4 "const_int_operand" "n"))]))))]
5022 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
5023 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5028 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5031 emit_insn (gen_negsi2 (tmp, operands[
3]));
5033 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
5034 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
5035 SUBREG_BYTE (operands[
5]));
5037 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
5042 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5043 [(set (match_operand:DI
0 "register_operand" "=r")
5045 (match_operand:DI
1 "register_operand" "r")
5046 (match_operator
4 "subreg_lowpart_operator"
5047 [(and:SI (match_operand:SI
2 "register_operand" "r")
5048 (match_operand
3 "const_int_operand" "n"))])))]
5049 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
5052 xop[
0] = operands[
0];
5053 xop[
1] = operands[
1];
5054 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
5055 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
5058 [(set_attr "type" "shift_reg")]
5061 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
5062 [(set (match_operand:GPI
0 "register_operand" "=&r")
5064 (match_operand:GPI
1 "register_operand" "r")
5065 (minus:QI (match_operand
2 "const_int_operand" "n")
5066 (match_operand:QI
3 "register_operand" "r"))))]
5067 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5072 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
5074 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5075 : gen_lowpart (SImode, operands[
0]));
5077 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5079 rtx and_op = gen_rtx_AND (SImode, tmp,
5080 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
5082 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5084 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
5087 [(set_attr "length" "
8")]
5090 ;; Logical left shift using SISD or Integer instruction
5091 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
5092 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
5094 (match_operand:GPI
1 "register_operand" "r,r,w,w")
5095 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5098 lsl
\t%<w>
0, %<w>
1, %
2
5099 lsl
\t%<w>
0, %<w>
1, %<w>
2
5100 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5101 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
5102 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5103 (set_attr "arch" "*,*,simd,simd")]
5106 ;; Logical right shift using SISD or Integer instruction
5107 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
5108 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5110 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5111 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
5112 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5115 lsr
\t%<w>
0, %<w>
1, %
2
5116 lsr
\t%<w>
0, %<w>
1, %<w>
2
5117 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5120 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5121 (set_attr "arch" "*,*,simd,simd,simd")]
5125 [(set (match_operand:DI
0 "aarch64_simd_register")
5127 (match_operand:DI
1 "aarch64_simd_register")
5128 (match_operand:QI
2 "aarch64_simd_register")))]
5129 "TARGET_SIMD && reload_completed"
5131 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5133 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
5135 operands[
3] = gen_lowpart (QImode, operands[
0]);
5140 [(set (match_operand:SI
0 "aarch64_simd_register")
5142 (match_operand:SI
1 "aarch64_simd_register")
5143 (match_operand:QI
2 "aarch64_simd_register")))]
5144 "TARGET_SIMD && reload_completed"
5146 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5148 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
5150 operands[
3] = gen_lowpart (QImode, operands[
0]);
5154 ;; Arithmetic right shift using SISD or Integer instruction
5155 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
5156 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5158 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5159 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
5160 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5163 asr
\t%<w>
0, %<w>
1, %
2
5164 asr
\t%<w>
0, %<w>
1, %<w>
2
5165 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5168 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5169 (set_attr "arch" "*,*,simd,simd,simd")]
5173 [(set (match_operand:DI
0 "aarch64_simd_register")
5175 (match_operand:DI
1 "aarch64_simd_register")
5176 (match_operand:QI
2 "aarch64_simd_register")))]
5177 "TARGET_SIMD && reload_completed"
5179 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5181 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
5183 operands[
3] = gen_lowpart (QImode, operands[
0]);
5188 [(set (match_operand:SI
0 "aarch64_simd_register")
5190 (match_operand:SI
1 "aarch64_simd_register")
5191 (match_operand:QI
2 "aarch64_simd_register")))]
5192 "TARGET_SIMD && reload_completed"
5194 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5196 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
5198 operands[
3] = gen_lowpart (QImode, operands[
0]);
5202 (define_insn "*aarch64_sisd_ushl"
5203 [(set (match_operand:DI
0 "register_operand" "=w")
5204 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5205 (match_operand:QI
2 "register_operand" "w")]
5208 "ushl
\t%d0, %d1, %d2"
5209 [(set_attr "type" "neon_shift_reg")]
5212 (define_insn "*aarch64_ushl_2s"
5213 [(set (match_operand:SI
0 "register_operand" "=w")
5214 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5215 (match_operand:QI
2 "register_operand" "w")]
5218 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
5219 [(set_attr "type" "neon_shift_reg")]
5222 (define_insn "*aarch64_sisd_sshl"
5223 [(set (match_operand:DI
0 "register_operand" "=w")
5224 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5225 (match_operand:QI
2 "register_operand" "w")]
5228 "sshl
\t%d0, %d1, %d2"
5229 [(set_attr "type" "neon_shift_reg")]
5232 (define_insn "*aarch64_sshl_2s"
5233 [(set (match_operand:SI
0 "register_operand" "=w")
5234 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5235 (match_operand:QI
2 "register_operand" "w")]
5238 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
5239 [(set_attr "type" "neon_shift_reg")]
5242 (define_insn "*aarch64_sisd_neg_qi"
5243 [(set (match_operand:QI
0 "register_operand" "=w")
5244 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
5248 [(set_attr "type" "neon_neg")]
5252 (define_insn "*ror<mode>
3_insn"
5253 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5255 (match_operand:GPI
1 "register_operand" "r,r")
5256 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5259 ror
\\t%<w>
0, %<w>
1, %
2
5260 ror
\\t%<w>
0, %<w>
1, %<w>
2"
5261 [(set_attr "type" "rotate_imm,shift_reg")]
5264 ;; zero_extend version of above
5265 (define_insn "*<optab>si3_insn_uxtw"
5266 [(set (match_operand:DI
0 "register_operand" "=r,r")
5267 (zero_extend:DI (SHIFT:SI
5268 (match_operand:SI
1 "register_operand" "r,r")
5269 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5272 <shift>
\\t%w0, %w1, %
2
5273 <shift>
\\t%w0, %w1, %w2"
5274 [(set_attr "type" "bfx,shift_reg")]
5277 (define_insn "*<optab><mode>
3_insn"
5278 [(set (match_operand:SHORT
0 "register_operand" "=r")
5279 (ASHIFT:SHORT (match_operand:SHORT
1 "register_operand" "r")
5280 (match_operand
2 "const_int_operand" "n")))]
5281 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5283 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5284 return "<bfshift>
\t%w0, %w1, %
2, %
3";
5286 [(set_attr "type" "bfx")]
5289 (define_insn "*extr<mode>
5_insn"
5290 [(set (match_operand:GPI
0 "register_operand" "=r")
5291 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5292 (match_operand
3 "const_int_operand" "n"))
5293 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5294 (match_operand
4 "const_int_operand" "n"))))]
5295 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5296 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
5297 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5298 [(set_attr "type" "rotate_imm")]
5301 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5302 ;; so we have to match both orderings.
5303 (define_insn "*extr<mode>
5_insn_alt"
5304 [(set (match_operand:GPI
0 "register_operand" "=r")
5305 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5306 (match_operand
4 "const_int_operand" "n"))
5307 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5308 (match_operand
3 "const_int_operand" "n"))))]
5309 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
5310 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
5311 == GET_MODE_BITSIZE (<MODE>mode))"
5312 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5313 [(set_attr "type" "rotate_imm")]
5316 ;; zero_extend version of the above
5317 (define_insn "*extrsi5_insn_uxtw"
5318 [(set (match_operand:DI
0 "register_operand" "=r")
5320 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
5321 (match_operand
3 "const_int_operand" "n"))
5322 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5323 (match_operand
4 "const_int_operand" "n")))))]
5324 "UINTVAL (operands[
3]) <
32 &&
5325 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5326 "extr
\\t%w0, %w1, %w2, %
4"
5327 [(set_attr "type" "rotate_imm")]
5330 (define_insn "*extrsi5_insn_uxtw_alt"
5331 [(set (match_operand:DI
0 "register_operand" "=r")
5333 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5334 (match_operand
4 "const_int_operand" "n"))
5335 (ashift:SI (match_operand:SI
1 "register_operand" "r")
5336 (match_operand
3 "const_int_operand" "n")))))]
5337 "UINTVAL (operands[
3]) <
32 &&
5338 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5339 "extr
\\t%w0, %w1, %w2, %
4"
5340 [(set_attr "type" "rotate_imm")]
5343 (define_insn "*ror<mode>
3_insn"
5344 [(set (match_operand:GPI
0 "register_operand" "=r")
5345 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
5346 (match_operand
2 "const_int_operand" "n")))]
5347 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5349 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5350 return "ror
\\t%<w>
0, %<w>
1, %
3";
5352 [(set_attr "type" "rotate_imm")]
5355 ;; zero_extend version of the above
5356 (define_insn "*rorsi3_insn_uxtw"
5357 [(set (match_operand:DI
0 "register_operand" "=r")
5359 (rotate:SI (match_operand:SI
1 "register_operand" "r")
5360 (match_operand
2 "const_int_operand" "n"))))]
5361 "UINTVAL (operands[
2]) <
32"
5363 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
5364 return "ror
\\t%w0, %w1, %
3";
5366 [(set_attr "type" "rotate_imm")]
5369 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5370 [(set (match_operand:GPI
0 "register_operand" "=r")
5372 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
5373 (match_operand
2 "const_int_operand" "n"))))]
5374 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5376 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5377 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5379 [(set_attr "type" "bfx")]
5382 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5383 [(set (match_operand:GPI
0 "register_operand" "=r")
5385 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5386 (match_operand
2 "const_int_operand" "n"))))]
5387 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5389 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5390 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5392 [(set_attr "type" "bfx")]
5395 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5396 [(set (match_operand:GPI
0 "register_operand" "=r")
5398 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5399 (match_operand
2 "const_int_operand" "n"))))]
5400 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5402 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5403 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5405 [(set_attr "type" "bfx")]
5408 ;; -------------------------------------------------------------------
5410 ;; -------------------------------------------------------------------
5412 (define_expand "<optab>"
5413 [(set (match_operand:DI
0 "register_operand")
5414 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
5416 "aarch64_simd_shift_imm_offset_di")
5417 (match_operand
3 "aarch64_simd_shift_imm_di")))]
5420 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5421 1, GET_MODE_BITSIZE (DImode) -
1))
5427 (define_insn "*<optab><mode>"
5428 [(set (match_operand:GPI
0 "register_operand" "=r")
5429 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
5431 "aarch64_simd_shift_imm_offset_<mode>" "n")
5433 "aarch64_simd_shift_imm_<mode>" "n")))]
5434 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5435 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5436 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
5437 [(set_attr "type" "bfx")]
5440 ;; When the bit position and width add up to
32 we can use a W-reg LSR
5441 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5443 [(set (match_operand:DI
0 "register_operand")
5444 (zero_extract:DI (match_operand:DI
1 "register_operand")
5446 "aarch64_simd_shift_imm_offset_di")
5448 "aarch64_simd_shift_imm_di")))]
5449 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
5450 GET_MODE_BITSIZE (DImode) -
1)
5451 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
5452 == GET_MODE_BITSIZE (SImode)"
5454 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
5456 operands[
4] = gen_lowpart (SImode, operands[
1]);
5460 ;; Bitfield Insert (insv)
5461 (define_expand "insv<mode>"
5462 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
5463 (match_operand
1 "const_int_operand")
5464 (match_operand
2 "const_int_operand"))
5465 (match_operand:GPI
3 "general_operand"))]
5468 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
5469 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
5470 rtx value = operands[
3];
5472 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5475 if (CONST_INT_P (value))
5477 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
5479 /* Prefer AND/OR for inserting all zeros or all ones. */
5480 if ((UINTVAL (value) & mask) ==
0
5481 || (UINTVAL (value) & mask) == mask)
5484 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
5485 if (width ==
16 && (pos %
16) ==
0)
5488 operands[
3] = force_reg (<MODE>mode, value);
5491 (define_insn "*insv_reg<mode>"
5492 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5493 (match_operand
1 "const_int_operand" "n")
5494 (match_operand
2 "const_int_operand" "n"))
5495 (match_operand:GPI
3 "register_operand" "r"))]
5496 "!(UINTVAL (operands[
1]) ==
0
5497 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
5498 > GET_MODE_BITSIZE (<MODE>mode)))"
5499 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
5500 [(set_attr "type" "bfm")]
5503 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
5504 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5505 (match_operand
1 "const_int_operand" "n")
5506 (match_operand
2 "const_int_operand" "n"))
5507 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
5508 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
5509 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
5510 [(set_attr "type" "bfm")]
5513 ;; Match a bfi instruction where the shift of OP3 means that we are
5514 ;; actually copying the least significant bits of OP3 into OP0 by way
5515 ;; of the AND masks and the IOR instruction. A similar instruction
5516 ;; with the two parts of the IOR swapped around was never triggered
5517 ;; in a bootstrap build and test of GCC so it was not included.
5519 (define_insn "*aarch64_bfi<GPI:mode>
5_shift"
5520 [(set (match_operand:GPI
0 "register_operand" "=r")
5521 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5522 (match_operand:GPI
2 "const_int_operand" "n"))
5523 (and:GPI (ashift:GPI
5524 (match_operand:GPI
3 "register_operand" "r")
5525 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))
5526 (match_operand:GPI
5 "const_int_operand" "n"))))]
5527 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5528 UINTVAL (operands[
4]),
5529 UINTVAL(operands[
5]))"
5530 "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %P5"
5531 [(set_attr "type" "bfm")]
5534 (define_insn "*aarch64_bfi<GPI:mode>
5_shift_alt"
5535 [(set (match_operand:GPI
0 "register_operand" "=r")
5536 (ior:GPI (and:GPI (ashift:GPI
5537 (match_operand:GPI
1 "register_operand" "r")
5538 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5539 (match_operand:GPI
3 "const_int_operand" "n"))
5540 (and:GPI (match_operand:GPI
4 "register_operand" "
0")
5541 (match_operand:GPI
5 "const_int_operand" "n"))))]
5542 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
5]),
5543 UINTVAL (operands[
2]),
5544 UINTVAL(operands[
3]))"
5545 "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %P3"
5546 [(set_attr "type" "bfm")]
5549 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no and of the ashift because
5550 ;; the shift is large enough to remove the need for an AND instruction.
5552 (define_insn "*aarch64_bfi<GPI:mode>
4_noand"
5553 [(set (match_operand:GPI
0 "register_operand" "=r")
5554 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5555 (match_operand:GPI
2 "const_int_operand" "n"))
5557 (match_operand:GPI
3 "register_operand" "r")
5558 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5559 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5560 UINTVAL (operands[
4]),
5561 HOST_WIDE_INT_M1U << UINTVAL (operands[
4]) )"
5563 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
4]));
5564 return "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %
5";
5566 [(set_attr "type" "bfm")]
5569 (define_insn "*aarch64_bfi<GPI:mode>
4_noand_alt"
5570 [(set (match_operand:GPI
0 "register_operand" "=r")
5571 (ior:GPI (ashift:GPI
5572 (match_operand:GPI
1 "register_operand" "r")
5573 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5574 (and:GPI (match_operand:GPI
3 "register_operand" "
0")
5575 (match_operand:GPI
4 "const_int_operand" "n"))))]
5576 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
4]),
5577 UINTVAL (operands[
2]),
5578 HOST_WIDE_INT_M1U << UINTVAL (operands[
2]) )"
5580 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
2]));
5581 return "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
5";
5583 [(set_attr "type" "bfm")]
5586 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no shifting, we are just
5587 ;; copying the least significant bits of OP3 to OP0. We need two versions
5588 ;; of the instruction to handle different checks on the constant values.
5590 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift"
5591 [(set (match_operand:GPI
0 "register_operand" "=r")
5592 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5593 (match_operand:GPI
2 "const_int_operand" "n"))
5594 (and:GPI (match_operand:GPI
3 "register_operand" "r")
5595 (match_operand:GPI
4 "const_int_operand" "n"))))]
5596 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5597 UINTVAL (operands[
4]))"
5598 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5599 [(set_attr "type" "bfm")]
5602 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift_alt"
5603 [(set (match_operand:GPI
0 "register_operand" "=r")
5604 (ior:GPI (and:GPI (match_operand:GPI
3 "register_operand" "r")
5605 (match_operand:GPI
4 "const_int_operand" "n"))
5606 (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5607 (match_operand:GPI
2 "const_int_operand" "n"))))]
5608 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5609 UINTVAL (operands[
4]))"
5610 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5611 [(set_attr "type" "bfm")]
5614 (define_insn "*extr_insv_lower_reg<mode>"
5615 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5616 (match_operand
1 "const_int_operand" "n")
5618 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
5620 (match_operand
3 "const_int_operand" "n")))]
5621 "!(UINTVAL (operands[
1]) ==
0
5622 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
5623 > GET_MODE_BITSIZE (<MODE>mode)))"
5624 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
5625 [(set_attr "type" "bfm")]
5628 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5629 [(set (match_operand:GPI
0 "register_operand" "=r")
5630 (ashift:GPI (ANY_EXTEND:GPI
5631 (match_operand:ALLX
1 "register_operand" "r"))
5632 (match_operand
2 "const_int_operand" "n")))]
5633 "UINTVAL (operands[
2]) < <GPI:sizen>"
5635 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
5636 ? GEN_INT (<ALLX:sizen>)
5637 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
5638 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5640 [(set_attr "type" "bfx")]
5643 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5645 (define_insn "*andim_ashift<mode>_bfiz"
5646 [(set (match_operand:GPI
0 "register_operand" "=r")
5647 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5648 (match_operand
2 "const_int_operand" "n"))
5649 (match_operand
3 "const_int_operand" "n")))]
5650 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
5651 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
5652 [(set_attr "type" "bfx")]
5655 ;; Match sbfiz pattern in a shift left + shift right operation.
5657 (define_insn "*ashift<mode>_extv_bfiz"
5658 [(set (match_operand:GPI
0 "register_operand" "=r")
5659 (ashift:GPI (sign_extract:GPI (match_operand:GPI
1 "register_operand" "r")
5660 (match_operand
2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5662 (match_operand
3 "aarch64_simd_shift_imm_<mode>" "n")))]
5663 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5664 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5665 "sbfiz
\\t%<w>
0, %<w>
1, %
3, %
2"
5666 [(set_attr "type" "bfx")]
5669 ;; When the bit position and width of the equivalent extraction add up to
32
5670 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5671 ;; zero-extension of the X-reg.
5673 [(set (match_operand:DI
0 "register_operand")
5674 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
5675 (match_operand
2 "const_int_operand"))
5676 (match_operand
3 "const_int_operand")))]
5677 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
5678 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
5679 == GET_MODE_BITSIZE (SImode)"
5681 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
5683 operands[
4] = gen_lowpart (SImode, operands[
1]);
5687 (define_insn "bswap<mode>
2"
5688 [(set (match_operand:GPI
0 "register_operand" "=r")
5689 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
5691 "rev
\\t%<w>
0, %<w>
1"
5692 [(set_attr "type" "rev")]
5695 (define_insn "bswaphi2"
5696 [(set (match_operand:HI
0 "register_operand" "=r")
5697 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
5700 [(set_attr "type" "rev")]
5703 (define_insn "*aarch64_bfxil<mode>"
5704 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5705 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "r,
0")
5706 (match_operand:GPI
3 "const_int_operand" "n, Ulc"))
5707 (and:GPI (match_operand:GPI
2 "register_operand" "
0,r")
5708 (match_operand:GPI
4 "const_int_operand" "Ulc, n"))))]
5709 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5710 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5711 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5713 switch (which_alternative)
5716 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5717 return "bfxil
\\t%<w>
0, %<w>
1,
0, %
3";
5719 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5720 return "bfxil
\\t%<w>
0, %<w>
2,
0, %
3";
5725 [(set_attr "type" "bfm")]
5728 ; Zero-extended version of above (aarch64_bfxil)
5729 (define_insn "*aarch64_bfxilsi_uxtw"
5730 [(set (match_operand:DI
0 "register_operand" "=r,r")
5731 (zero_extend:DI (ior:SI (and:SI (match_operand:SI
1 "register_operand"
5733 (match_operand:SI
3 "const_int_operand" "n, Ulc"))
5734 (and:SI (match_operand:SI
2 "register_operand" "
0,r")
5735 (match_operand:SI
4 "const_int_operand" "Ulc, n")))))]
5736 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5737 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5738 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5740 switch (which_alternative)
5743 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5744 return "bfxil
\\t%
0, %
1,
0, %
3";
5746 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5747 return "bfxil
\\t%
0, %
2,
0, %
3";
5752 [(set_attr "type" "bfm")]
5755 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5756 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5757 ;; each valid permutation.
5759 (define_insn "rev16<mode>
2"
5760 [(set (match_operand:GPI
0 "register_operand" "=r")
5761 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5763 (match_operand:GPI
3 "const_int_operand" "n"))
5764 (and:GPI (lshiftrt:GPI (match_dup
1)
5766 (match_operand:GPI
2 "const_int_operand" "n"))))]
5767 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5768 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5769 "rev16
\\t%<w>
0, %<w>
1"
5770 [(set_attr "type" "rev")]
5773 (define_insn "rev16<mode>
2_alt"
5774 [(set (match_operand:GPI
0 "register_operand" "=r")
5775 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
5777 (match_operand:GPI
2 "const_int_operand" "n"))
5778 (and:GPI (ashift:GPI (match_dup
1)
5780 (match_operand:GPI
3 "const_int_operand" "n"))))]
5781 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5782 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5783 "rev16
\\t%<w>
0, %<w>
1"
5784 [(set_attr "type" "rev")]
5787 ;; zero_extend version of above
5788 (define_insn "*bswapsi2_uxtw"
5789 [(set (match_operand:DI
0 "register_operand" "=r")
5790 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
5793 [(set_attr "type" "rev")]
5796 ;; -------------------------------------------------------------------
5797 ;; Floating-point intrinsics
5798 ;; -------------------------------------------------------------------
5800 ;; frint floating-point round to integral standard patterns.
5801 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5803 (define_insn "<frint_pattern><mode>
2"
5804 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5805 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5808 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
5809 [(set_attr "type" "f_rint<stype>")]
5812 ;; frcvt floating-point round to integer and convert standard patterns.
5813 ;; Expands to lbtrunc, lceil, lfloor, lround.
5814 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
5815 [(set (match_operand:GPI
0 "register_operand" "=r")
5817 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5820 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
5821 [(set_attr "type" "f_cvtf2i")]
5824 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
5825 [(set (match_operand:GPI
0 "register_operand" "=r")
5828 (match_operand:GPF
1 "register_operand" "w")
5829 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
5831 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
5832 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5834 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
5836 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
5837 output_asm_insn (buf, operands);
5840 [(set_attr "type" "f_cvtf2i")]
5843 ;; fma - expand fma into patterns with the accumulator operand first since
5844 ;; reusing the accumulator results in better register allocation.
5845 ;; The register allocator considers copy preferences in operand order,
5846 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5848 (define_expand "fma<mode>
4"
5849 [(set (match_operand:GPF_F16
0 "register_operand")
5850 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
5851 (match_operand:GPF_F16
2 "register_operand")
5852 (match_operand:GPF_F16
3 "register_operand")))]
5856 (define_insn "*aarch64_fma<mode>
4"
5857 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5858 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
5859 (match_operand:GPF_F16
3 "register_operand" "w")
5860 (match_operand:GPF_F16
1 "register_operand" "w")))]
5862 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5863 [(set_attr "type" "fmac<stype>")]
5866 (define_expand "fnma<mode>
4"
5867 [(set (match_operand:GPF_F16
0 "register_operand")
5869 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5870 (match_operand:GPF_F16
2 "register_operand")
5871 (match_operand:GPF_F16
3 "register_operand")))]
5875 (define_insn "*aarch64_fnma<mode>
4"
5876 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5878 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5879 (match_operand:GPF_F16
3 "register_operand" "w")
5880 (match_operand:GPF_F16
1 "register_operand" "w")))]
5882 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5883 [(set_attr "type" "fmac<stype>")]
5887 (define_expand "fms<mode>
4"
5888 [(set (match_operand:GPF
0 "register_operand")
5889 (fma:GPF (match_operand:GPF
1 "register_operand")
5890 (match_operand:GPF
2 "register_operand")
5891 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5895 (define_insn "*aarch64_fms<mode>
4"
5896 [(set (match_operand:GPF
0 "register_operand" "=w")
5897 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5898 (match_operand:GPF
3 "register_operand" "w")
5899 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5901 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5902 [(set_attr "type" "fmac<s>")]
5905 (define_expand "fnms<mode>
4"
5906 [(set (match_operand:GPF
0 "register_operand")
5907 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5908 (match_operand:GPF
2 "register_operand")
5909 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5913 (define_insn "*aarch64_fnms<mode>
4"
5914 [(set (match_operand:GPF
0 "register_operand" "=w")
5915 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5916 (match_operand:GPF
3 "register_operand" "w")
5917 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5919 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5920 [(set_attr "type" "fmac<s>")]
5923 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5924 (define_insn "*aarch64_fnmadd<mode>
4"
5925 [(set (match_operand:GPF
0 "register_operand" "=w")
5926 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5927 (match_operand:GPF
3 "register_operand" "w")
5928 (match_operand:GPF
1 "register_operand" "w"))))]
5929 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5930 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5931 [(set_attr "type" "fmac<s>")]
5934 ;; -------------------------------------------------------------------
5935 ;; Floating-point conversions
5936 ;; -------------------------------------------------------------------
5938 (define_insn "extendsfdf2"
5939 [(set (match_operand:DF
0 "register_operand" "=w")
5940 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
5943 [(set_attr "type" "f_cvt")]
5946 (define_insn "extendhfsf2"
5947 [(set (match_operand:SF
0 "register_operand" "=w")
5948 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
5951 [(set_attr "type" "f_cvt")]
5954 (define_insn "extendhfdf2"
5955 [(set (match_operand:DF
0 "register_operand" "=w")
5956 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
5959 [(set_attr "type" "f_cvt")]
5962 (define_insn "truncdfsf2"
5963 [(set (match_operand:SF
0 "register_operand" "=w")
5964 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
5967 [(set_attr "type" "f_cvt")]
5970 (define_insn "truncsfhf2"
5971 [(set (match_operand:HF
0 "register_operand" "=w")
5972 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
5975 [(set_attr "type" "f_cvt")]
5978 (define_insn "truncdfhf2"
5979 [(set (match_operand:HF
0 "register_operand" "=w")
5980 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
5983 [(set_attr "type" "f_cvt")]
5986 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5987 ;; and making r = w more expensive
5989 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
5990 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
5991 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
5994 fcvtz<su>
\t%<s>
0, %<s>
1
5995 fcvtz<su>
\t%<w>
0, %<s>
1"
5996 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5999 ;; Convert HF -> SI or DI
6001 (define_insn "<optab>_trunchf<GPI:mode>
2"
6002 [(set (match_operand:GPI
0 "register_operand" "=r")
6003 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
6005 "fcvtz<su>
\t%<w>
0, %h1"
6006 [(set_attr "type" "f_cvtf2i")]
6009 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
6010 ;; input in a fp register and output in a integer register
6012 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
6013 [(set (match_operand:GPI
0 "register_operand" "=r")
6014 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
6016 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
6017 [(set_attr "type" "f_cvtf2i")]
6020 (define_insn "*fix_to_zero_extend<mode>di2"
6021 [(set (match_operand:DI
0 "register_operand" "=r")
6024 (match_operand:GPF
1 "register_operand" "w"))))]
6026 "fcvtzu
\t%w0, %<s>
1"
6027 [(set_attr "type" "f_cvtf2i")]
6030 (define_insn "<optab><fcvt_target><GPF:mode>
2"
6031 [(set (match_operand:GPF
0 "register_operand" "=w,w")
6032 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
6035 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
6036 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
6037 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6038 (set_attr "arch" "simd,fp")]
6041 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
6042 [(set (match_operand:GPF
0 "register_operand" "=w")
6043 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
6045 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
6046 [(set_attr "type" "f_cvti2f")]
6049 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
6050 ;; midend will arrange for an SImode conversion to HFmode to first go
6051 ;; through DFmode, then to HFmode. But first it will try converting
6052 ;; to DImode then down, which would match our DImode pattern below and
6053 ;; give very poor code-generation. So, we must provide our own emulation
6054 ;; of the mid-end logic.
6056 (define_insn "aarch64_fp16_<optab><mode>hf2"
6057 [(set (match_operand:HF
0 "register_operand" "=w")
6058 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
6060 "<su_optab>cvtf
\t%h0, %<w>
1"
6061 [(set_attr "type" "f_cvti2f")]
6064 (define_expand "<optab>sihf2"
6065 [(set (match_operand:HF
0 "register_operand")
6066 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
6069 if (TARGET_FP_F16INST)
6070 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
6073 rtx convert_target = gen_reg_rtx (DFmode);
6074 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
6075 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
6081 ;; For DImode there is no wide enough floating-point mode that we
6082 ;; can convert through natively (TFmode would work, but requires a library
6083 ;; call). However, we know that any value >=
65504 will be rounded
6084 ;; to infinity on conversion. This is well within the range of SImode, so
6086 ;; Saturate to SImode.
6087 ;; Convert from that to DFmode
6088 ;; Convert from that to HFmode (phew!).
6089 ;; Note that the saturation to SImode requires the SIMD extensions. If
6090 ;; we ever need to provide this pattern where the SIMD extensions are not
6091 ;; available, we would need a different approach.
6093 (define_expand "<optab>dihf2"
6094 [(set (match_operand:HF
0 "register_operand")
6095 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
6096 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6098 if (TARGET_FP_F16INST)
6099 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
6102 rtx sat_target = gen_reg_rtx (SImode);
6103 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
6104 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
6111 ;; Convert between fixed-point and floating-point (scalar modes)
6113 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
6114 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
6115 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
6116 (match_operand:SI
2 "immediate_operand" "i, i")]
6120 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
6121 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
6122 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6123 (set_attr "arch" "fp,simd")]
6126 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
6127 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
6128 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
6129 (match_operand:SI
2 "immediate_operand" "i, i")]
6133 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
6134 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
6135 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6136 (set_attr "arch" "fp,simd")]
6139 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
6140 [(set (match_operand:GPI
0 "register_operand" "=r")
6141 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
6142 (match_operand:SI
2 "immediate_operand" "i")]
6145 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
6146 [(set_attr "type" "f_cvtf2i")]
6149 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6150 [(set (match_operand:HF
0 "register_operand" "=w")
6151 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
6152 (match_operand:SI
2 "immediate_operand" "i")]
6155 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
6156 [(set_attr "type" "f_cvti2f")]
6159 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6160 [(set (match_operand:HI
0 "register_operand" "=w")
6161 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
6162 (match_operand:SI
2 "immediate_operand" "i")]
6165 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6166 [(set_attr "type" "neon_fp_to_int_s")]
6169 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6170 [(set (match_operand:HF
0 "register_operand" "=w")
6171 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
6172 (match_operand:SI
2 "immediate_operand" "i")]
6175 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6176 [(set_attr "type" "neon_int_to_fp_s")]
6179 ;; -------------------------------------------------------------------
6180 ;; Floating-point arithmetic
6181 ;; -------------------------------------------------------------------
6183 (define_insn "add<mode>
3"
6184 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6186 (match_operand:GPF_F16
1 "register_operand" "w")
6187 (match_operand:GPF_F16
2 "register_operand" "w")))]
6189 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
6190 [(set_attr "type" "fadd<stype>")]
6193 (define_insn "sub<mode>
3"
6194 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6196 (match_operand:GPF_F16
1 "register_operand" "w")
6197 (match_operand:GPF_F16
2 "register_operand" "w")))]
6199 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
6200 [(set_attr "type" "fadd<stype>")]
6203 (define_insn "mul<mode>
3"
6204 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6206 (match_operand:GPF_F16
1 "register_operand" "w")
6207 (match_operand:GPF_F16
2 "register_operand" "w")))]
6209 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
6210 [(set_attr "type" "fmul<stype>")]
6213 (define_insn "*fnmul<mode>
3"
6214 [(set (match_operand:GPF
0 "register_operand" "=w")
6216 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
6217 (match_operand:GPF
2 "register_operand" "w")))]
6218 "TARGET_FLOAT && !flag_rounding_math"
6219 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6220 [(set_attr "type" "fmul<s>")]
6223 (define_insn "*fnmul<mode>
3"
6224 [(set (match_operand:GPF
0 "register_operand" "=w")
6226 (match_operand:GPF
1 "register_operand" "w")
6227 (match_operand:GPF
2 "register_operand" "w"))))]
6229 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6230 [(set_attr "type" "fmul<s>")]
6233 (define_expand "div<mode>
3"
6234 [(set (match_operand:GPF_F16
0 "register_operand")
6235 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
6236 (match_operand:GPF_F16
2 "register_operand")))]
6239 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
6242 operands[
1] = force_reg (<MODE>mode, operands[
1]);
6245 (define_insn "*div<mode>
3"
6246 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6247 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
6248 (match_operand:GPF_F16
2 "register_operand" "w")))]
6250 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
6251 [(set_attr "type" "fdiv<stype>")]
6254 (define_insn "neg<mode>
2"
6255 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6256 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6258 "fneg
\\t%<s>
0, %<s>
1"
6259 [(set_attr "type" "ffarith<stype>")]
6262 (define_expand "sqrt<mode>
2"
6263 [(set (match_operand:GPF_F16
0 "register_operand")
6264 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand")))]
6267 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
6271 (define_insn "*sqrt<mode>
2"
6272 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6273 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6275 "fsqrt
\\t%<s>
0, %<s>
1"
6276 [(set_attr "type" "fsqrt<stype>")]
6279 (define_insn "abs<mode>
2"
6280 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6281 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6283 "fabs
\\t%<s>
0, %<s>
1"
6284 [(set_attr "type" "ffarith<stype>")]
6287 ;; Given that smax/smin do not specify the result when either input is NaN,
6288 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6291 (define_insn "smax<mode>
3"
6292 [(set (match_operand:GPF
0 "register_operand" "=w")
6293 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
6294 (match_operand:GPF
2 "register_operand" "w")))]
6296 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
6297 [(set_attr "type" "f_minmax<s>")]
6300 (define_insn "smin<mode>
3"
6301 [(set (match_operand:GPF
0 "register_operand" "=w")
6302 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
6303 (match_operand:GPF
2 "register_operand" "w")))]
6305 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
6306 [(set_attr "type" "f_minmax<s>")]
6309 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6310 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
6311 ;; which implement the IEEE fmax ()/fmin () functions.
6312 (define_insn "<maxmin_uns><mode>
3"
6313 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6314 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
6315 (match_operand:GPF_F16
2 "register_operand" "w")]
6318 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
6319 [(set_attr "type" "f_minmax<stype>")]
6322 (define_expand "lrint<GPF:mode><GPI:mode>
2"
6323 [(match_operand:GPI
0 "register_operand")
6324 (match_operand:GPF
1 "register_operand")]
6326 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
6327 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6329 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6330 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
6331 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
6336 ;; For copysign (x, y), we want to generate:
6338 ;; LDR d2, #(
1 <<
63)
6339 ;; BSL v2.8b, [y], [x]
6341 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6342 ;; we expect these operations to nearly always operate on
6343 ;; floating-point values, we do not want the operation to be
6344 ;; simplified into a bit-field insert operation that operates on the
6345 ;; integer side, since typically that would involve three inter-bank
6346 ;; register copies. As we do not expect copysign to be followed by
6347 ;; other logical operations on the result, it seems preferable to keep
6348 ;; this as an unspec operation, rather than exposing the underlying
6349 ;; logic to the compiler.
6351 (define_expand "copysign<GPF:mode>
3"
6352 [(match_operand:GPF
0 "register_operand")
6353 (match_operand:GPF
1 "register_operand")
6354 (match_operand:GPF
2 "register_operand")]
6355 "TARGET_FLOAT && TARGET_SIMD"
6357 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6358 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6359 << (GET_MODE_BITSIZE (<MODE>mode) -
1)));
6360 emit_insn (gen_copysign<mode>
3_insn (operands[
0], operands[
1], operands[
2],
6366 (define_insn "copysign<GPF:mode>
3_insn"
6367 [(set (match_operand:GPF
0 "register_operand" "=w,w,w,r")
6368 (unspec:GPF [(match_operand:GPF
1 "register_operand" "w,
0,w,r")
6369 (match_operand:GPF
2 "register_operand" "w,w,
0,
0")
6370 (match_operand:<V_INT_EQUIV>
3 "register_operand" "
0,w,w,X")]
6372 "TARGET_FLOAT && TARGET_SIMD"
6374 bsl
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>
6375 bit
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
3.<Vbtype>
6376 bif
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
3.<Vbtype>
6377 bfxil
\\t%<w1>
0, %<w1>
1, #
0, <sizem1>"
6378 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6382 ;; For xorsign (x, y), we want to generate:
6385 ;; AND v3.8B, v1.8B, v2.8B
6386 ;; EOR v0.8B, v0.8B, v3.8B
6389 (define_expand "xorsign<mode>
3"
6390 [(match_operand:GPF
0 "register_operand")
6391 (match_operand:GPF
1 "register_operand")
6392 (match_operand:GPF
2 "register_operand")]
6393 "TARGET_FLOAT && TARGET_SIMD"
6396 machine_mode imode = <V_INT_EQUIV>mode;
6397 rtx mask = gen_reg_rtx (imode);
6398 rtx op1x = gen_reg_rtx (imode);
6399 rtx op2x = gen_reg_rtx (imode);
6401 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
6402 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6405 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
6406 lowpart_subreg (imode, operands[
2],
6408 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
6409 lowpart_subreg (imode, operands[
1],
6412 emit_move_insn (operands[
0],
6413 lowpart_subreg (<MODE>mode, op1x, imode));
6418 ;; -------------------------------------------------------------------
6420 ;; -------------------------------------------------------------------
6421 ;; Reload Scalar Floating point modes from constant pool.
6422 ;; The AArch64 port doesn't have __int128 constant move support.
6423 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
6424 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6425 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
6426 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
6427 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6430 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6431 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
6436 ;; Reload Vector modes from constant pool.
6437 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6438 [(set (match_operand:VALL
0 "register_operand" "=w")
6439 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
6440 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6443 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6444 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
6449 (define_expand "@aarch64_reload_mov<mode>"
6450 [(set (match_operand:TX
0 "register_operand" "=w")
6451 (match_operand:TX
1 "register_operand" "w"))
6452 (clobber (match_operand:DI
2 "register_operand" "=&r"))
6456 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
6457 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
6458 gen_aarch64_movtilow_tilow (op0, op1);
6459 gen_aarch64_movdi_tihigh (operands[
2], op1);
6460 gen_aarch64_movtihigh_di (op0, operands[
2]);
6465 ;; The following secondary reload helpers patterns are invoked
6466 ;; after or during reload as we don't want these patterns to start
6467 ;; kicking in during the combiner.
6469 (define_insn "@aarch64_movdi_<mode>low"
6470 [(set (match_operand:DI
0 "register_operand" "=r")
6471 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6472 (const_int
64) (const_int
0)))]
6473 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6475 [(set_attr "type" "f_mrc")
6476 (set_attr "length" "
4")
6479 (define_insn "@aarch64_movdi_<mode>high"
6480 [(set (match_operand:DI
0 "register_operand" "=r")
6481 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6482 (const_int
64) (const_int
64)))]
6483 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6484 "fmov
\\t%x0, %
1.d[
1]"
6485 [(set_attr "type" "f_mrc")
6486 (set_attr "length" "
4")
6489 (define_insn "@aarch64_mov<mode>high_di"
6490 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
6491 (const_int
64) (const_int
64))
6492 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6493 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6494 "fmov
\\t%
0.d[
1], %x1"
6495 [(set_attr "type" "f_mcr")
6496 (set_attr "length" "
4")
6499 (define_insn "@aarch64_mov<mode>low_di"
6500 [(set (match_operand:TX
0 "register_operand" "=w")
6501 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6502 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6504 [(set_attr "type" "f_mcr")
6505 (set_attr "length" "
4")
6508 (define_insn "aarch64_movtilow_tilow"
6509 [(set (match_operand:TI
0 "register_operand" "=w")
6511 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
6512 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6514 [(set_attr "type" "fmov")
6515 (set_attr "length" "
4")
6518 ;; There is a deliberate reason why the parameters of high and lo_sum's
6519 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6520 ;; and lo_sum's to be used with the labels defining the jump tables in
6523 (define_expand "add_losym"
6524 [(set (match_operand
0 "register_operand")
6525 (lo_sum (match_operand
1 "register_operand")
6526 (match_operand
2 "aarch64_valid_symref")))]
6529 machine_mode mode = GET_MODE (operands[
0]);
6531 emit_insn ((mode == DImode
6533 : gen_add_losym_si) (operands[
0],
6539 (define_insn "add_losym_<mode>"
6540 [(set (match_operand:P
0 "register_operand" "=r")
6541 (lo_sum:P (match_operand:P
1 "register_operand" "r")
6542 (match_operand
2 "aarch64_valid_symref" "S")))]
6544 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
6545 [(set_attr "type" "alu_imm")]
6548 (define_insn "ldr_got_small_<mode>"
6549 [(set (match_operand:PTR
0 "register_operand" "=r")
6550 (unspec:PTR [(mem:PTR (lo_sum:PTR
6551 (match_operand:PTR
1 "register_operand" "r")
6552 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6553 UNSPEC_GOTSMALLPIC))]
6555 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
6556 [(set_attr "type" "load_<ldst_sz>")]
6559 (define_insn "ldr_got_small_sidi"
6560 [(set (match_operand:DI
0 "register_operand" "=r")
6562 (unspec:SI [(mem:SI (lo_sum:DI
6563 (match_operand:DI
1 "register_operand" "r")
6564 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6565 UNSPEC_GOTSMALLPIC)))]
6567 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
6568 [(set_attr "type" "load_4")]
6571 (define_insn "ldr_got_small_28k_<mode>"
6572 [(set (match_operand:PTR
0 "register_operand" "=r")
6573 (unspec:PTR [(mem:PTR (lo_sum:PTR
6574 (match_operand:PTR
1 "register_operand" "r")
6575 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6576 UNSPEC_GOTSMALLPIC28K))]
6578 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
6579 [(set_attr "type" "load_<ldst_sz>")]
6582 (define_insn "ldr_got_small_28k_sidi"
6583 [(set (match_operand:DI
0 "register_operand" "=r")
6585 (unspec:SI [(mem:SI (lo_sum:DI
6586 (match_operand:DI
1 "register_operand" "r")
6587 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6588 UNSPEC_GOTSMALLPIC28K)))]
6590 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
6591 [(set_attr "type" "load_4")]
6594 (define_insn "ldr_got_tiny"
6595 [(set (match_operand:DI
0 "register_operand" "=r")
6596 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
6597 UNSPEC_GOTTINYPIC))]
6600 [(set_attr "type" "load_8")]
6603 (define_insn "aarch64_load_tp_hard"
6604 [(set (match_operand:DI
0 "register_operand" "=r")
6605 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
6607 "mrs
\\t%
0, tpidr_el0"
6608 [(set_attr "type" "mrs")]
6611 ;; The TLS ABI specifically requires that the compiler does not schedule
6612 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6613 ;; Therefore we treat the stubs as an atomic sequence.
6614 (define_expand "tlsgd_small_<mode>"
6615 [(parallel [(set (match_operand
0 "register_operand")
6616 (call (mem:DI (match_dup
2)) (const_int
1)))
6617 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
6618 (clobber (reg:DI LR_REGNUM))])]
6621 operands[
2] = aarch64_tls_get_addr ();
6624 (define_insn "*tlsgd_small_<mode>"
6625 [(set (match_operand
0 "register_operand" "")
6626 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
6627 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6628 (clobber (reg:DI LR_REGNUM))
6631 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
6632 [(set_attr "type" "call")
6633 (set_attr "length" "
16")])
6635 (define_insn "tlsie_small_<mode>"
6636 [(set (match_operand:PTR
0 "register_operand" "=r")
6637 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6638 UNSPEC_GOTSMALLTLS))]
6640 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
6641 [(set_attr "type" "load_4")
6642 (set_attr "length" "
8")]
6645 (define_insn "tlsie_small_sidi"
6646 [(set (match_operand:DI
0 "register_operand" "=r")
6648 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6649 UNSPEC_GOTSMALLTLS)))]
6651 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
6652 [(set_attr "type" "load_4")
6653 (set_attr "length" "
8")]
6656 (define_insn "tlsie_tiny_<mode>"
6657 [(set (match_operand:PTR
0 "register_operand" "=&r")
6658 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
6659 (match_operand:PTR
2 "register_operand" "r")]
6660 UNSPEC_GOTTINYTLS))]
6662 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
6663 [(set_attr "type" "multiple")
6664 (set_attr "length" "
8")]
6667 (define_insn "tlsie_tiny_sidi"
6668 [(set (match_operand:DI
0 "register_operand" "=&r")
6670 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
6671 (match_operand:DI
2 "register_operand" "r")
6673 UNSPEC_GOTTINYTLS)))]
6675 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
6676 [(set_attr "type" "multiple")
6677 (set_attr "length" "
8")]
6680 (define_insn "tlsle12_<mode>"
6681 [(set (match_operand:P
0 "register_operand" "=r")
6682 (unspec:P [(match_operand:P
1 "register_operand" "r")
6683 (match_operand
2 "aarch64_tls_le_symref" "S")]
6686 "add
\\t%<w>
0, %<w>
1, #%L2";
6687 [(set_attr "type" "alu_sreg")
6688 (set_attr "length" "
4")]
6691 (define_insn "tlsle24_<mode>"
6692 [(set (match_operand:P
0 "register_operand" "=r")
6693 (unspec:P [(match_operand:P
1 "register_operand" "r")
6694 (match_operand
2 "aarch64_tls_le_symref" "S")]
6697 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
6698 [(set_attr "type" "multiple")
6699 (set_attr "length" "
8")]
6702 (define_insn "tlsle32_<mode>"
6703 [(set (match_operand:P
0 "register_operand" "=r")
6704 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6707 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6708 [(set_attr "type" "multiple")
6709 (set_attr "length" "
8")]
6712 (define_insn "tlsle48_<mode>"
6713 [(set (match_operand:P
0 "register_operand" "=r")
6714 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6717 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6718 [(set_attr "type" "multiple")
6719 (set_attr "length" "
12")]
6722 (define_expand "tlsdesc_small_<mode>"
6723 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6727 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[
0]));
6729 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
6734 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6736 (define_insn "tlsdesc_small_advsimd_<mode>"
6737 [(set (reg:PTR R0_REGNUM)
6738 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6740 (clobber (reg:DI LR_REGNUM))
6741 (clobber (reg:CC CC_REGNUM))
6742 (clobber (match_scratch:DI
1 "=r"))
6743 (use (reg:DI FP_REGNUM))]
6744 "TARGET_TLS_DESC && !TARGET_SVE"
6745 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6746 [(set_attr "type" "call")
6747 (set_attr "length" "
16")])
6749 ;; For SVE, model tlsdesc calls as clobbering the lower
128 bits of
6750 ;; all vector registers, and clobber all predicate registers, on
6751 ;; top of the usual R0 and LR.
6752 (define_insn "tlsdesc_small_sve_<mode>"
6753 [(set (reg:PTR R0_REGNUM)
6754 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6756 (clobber (reg:DI LR_REGNUM))
6757 (clobber (reg:CC CC_REGNUM))
6758 (clobber_high (reg:TI V0_REGNUM))
6759 (clobber_high (reg:TI V1_REGNUM))
6760 (clobber_high (reg:TI V2_REGNUM))
6761 (clobber_high (reg:TI V3_REGNUM))
6762 (clobber_high (reg:TI V4_REGNUM))
6763 (clobber_high (reg:TI V5_REGNUM))
6764 (clobber_high (reg:TI V6_REGNUM))
6765 (clobber_high (reg:TI V7_REGNUM))
6766 (clobber_high (reg:TI V8_REGNUM))
6767 (clobber_high (reg:TI V9_REGNUM))
6768 (clobber_high (reg:TI V10_REGNUM))
6769 (clobber_high (reg:TI V11_REGNUM))
6770 (clobber_high (reg:TI V12_REGNUM))
6771 (clobber_high (reg:TI V13_REGNUM))
6772 (clobber_high (reg:TI V14_REGNUM))
6773 (clobber_high (reg:TI V15_REGNUM))
6774 (clobber_high (reg:TI V16_REGNUM))
6775 (clobber_high (reg:TI V17_REGNUM))
6776 (clobber_high (reg:TI V18_REGNUM))
6777 (clobber_high (reg:TI V19_REGNUM))
6778 (clobber_high (reg:TI V20_REGNUM))
6779 (clobber_high (reg:TI V21_REGNUM))
6780 (clobber_high (reg:TI V22_REGNUM))
6781 (clobber_high (reg:TI V23_REGNUM))
6782 (clobber_high (reg:TI V24_REGNUM))
6783 (clobber_high (reg:TI V25_REGNUM))
6784 (clobber_high (reg:TI V26_REGNUM))
6785 (clobber_high (reg:TI V27_REGNUM))
6786 (clobber_high (reg:TI V28_REGNUM))
6787 (clobber_high (reg:TI V29_REGNUM))
6788 (clobber_high (reg:TI V30_REGNUM))
6789 (clobber_high (reg:TI V31_REGNUM))
6790 (clobber (reg:VNx2BI P0_REGNUM))
6791 (clobber (reg:VNx2BI P1_REGNUM))
6792 (clobber (reg:VNx2BI P2_REGNUM))
6793 (clobber (reg:VNx2BI P3_REGNUM))
6794 (clobber (reg:VNx2BI P4_REGNUM))
6795 (clobber (reg:VNx2BI P5_REGNUM))
6796 (clobber (reg:VNx2BI P6_REGNUM))
6797 (clobber (reg:VNx2BI P7_REGNUM))
6798 (clobber (reg:VNx2BI P8_REGNUM))
6799 (clobber (reg:VNx2BI P9_REGNUM))
6800 (clobber (reg:VNx2BI P10_REGNUM))
6801 (clobber (reg:VNx2BI P11_REGNUM))
6802 (clobber (reg:VNx2BI P12_REGNUM))
6803 (clobber (reg:VNx2BI P13_REGNUM))
6804 (clobber (reg:VNx2BI P14_REGNUM))
6805 (clobber (reg:VNx2BI P15_REGNUM))
6806 (clobber (match_scratch:DI
1 "=r"))
6807 (use (reg:DI FP_REGNUM))]
6808 "TARGET_TLS_DESC && TARGET_SVE"
6809 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6810 [(set_attr "type" "call")
6811 (set_attr "length" "
16")])
6813 (define_insn "stack_tie"
6814 [(set (mem:BLK (scratch))
6815 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
6816 (match_operand:DI
1 "register_operand" "rk")]
6820 [(set_attr "length" "
0")]
6823 ;; Pointer authentication patterns are always provided. In architecture
6824 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6825 ;; This lets the user write portable software which authenticates pointers
6826 ;; when run on something which implements ARMv8.3-A, and which runs
6827 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6830 ;; Signing/Authenticating R30 using SP as the salt.
6832 (define_insn "<pauth_mnem_prefix>sp"
6833 [(set (reg:DI R30_REGNUM)
6834 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6836 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6839 ;; Signing/Authenticating X17 using X16 as the salt.
6841 (define_insn "<pauth_mnem_prefix>
1716"
6842 [(set (reg:DI R17_REGNUM)
6843 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6845 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>
1716";
6848 ;; Stripping the signature in R30.
6850 (define_insn "xpaclri"
6851 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6853 "hint
\t7 // xpaclri"
6856 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6857 ;; all of memory. This blocks insns from being moved across this point.
6859 (define_insn "blockage"
6860 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
6863 [(set_attr "length" "
0")
6864 (set_attr "type" "block")]
6867 (define_insn "probe_stack_range"
6868 [(set (match_operand:DI
0 "register_operand" "=rk")
6869 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
6870 (match_operand:DI
2 "register_operand" "r")]
6871 UNSPECV_PROBE_STACK_RANGE))]
6874 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
6876 [(set_attr "length" "
32")]
6879 ;; This instruction is used to generate the stack clash stack adjustment and
6880 ;; probing loop. We can't change the control flow during prologue and epilogue
6881 ;; code generation. So we must emit a volatile unspec and expand it later on.
6883 (define_insn "@probe_sve_stack_clash_<mode>"
6884 [(set (match_operand:P
0 "register_operand" "=rk")
6885 (unspec_volatile:P [(match_operand:P
1 "register_operand" "
0")
6886 (match_operand:P
2 "register_operand" "r")
6887 (match_operand:P
3 "const_int_operand" "n")
6888 (match_operand:P
4 "aarch64_plus_immediate" "L")]
6889 UNSPECV_PROBE_STACK_RANGE))]
6892 return aarch64_output_probe_sve_stack_clash (operands[
0], operands[
2],
6893 operands[
3], operands[
4]);
6895 [(set_attr "length" "
28")]
6898 ;; Named pattern for expanding thread pointer reference.
6899 (define_expand "get_thread_pointerdi"
6900 [(match_operand:DI
0 "register_operand")]
6903 rtx tmp = aarch64_load_tp (operands[
0]);
6904 if (tmp != operands[
0])
6905 emit_move_insn (operands[
0], tmp);
6909 ;; Named patterns for stack smashing protection.
6910 (define_expand "stack_protect_set"
6911 [(match_operand
0 "memory_operand")
6912 (match_operand
1 "memory_operand")]
6915 machine_mode mode = GET_MODE (operands[
0]);
6916 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6918 /* Generate access through the system register. */
6919 rtx tmp_reg = gen_reg_rtx (mode);
6922 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6923 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6924 GEN_INT (aarch64_stack_protector_guard_offset)));
6928 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
6929 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
6930 GEN_INT (aarch64_stack_protector_guard_offset)));
6933 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
6936 emit_insn ((mode == DImode
6937 ? gen_stack_protect_set_di
6938 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
6942 (define_insn "reg_stack_protect_address_<mode>"
6943 [(set (match_operand:PTR
0 "register_operand" "=r")
6944 (unspec:PTR [(const_int
0)]
6945 UNSPEC_SSP_SYSREG))]
6946 "aarch64_stack_protector_guard != SSP_GLOBAL"
6949 snprintf (buf,
150, "mrs
\\t%%<w>
0, %s",
6950 aarch64_stack_protector_guard_reg_str);
6951 output_asm_insn (buf, operands);
6954 [(set_attr "type" "mrs")])
6956 (define_insn "stack_protect_set_<mode>"
6957 [(set (match_operand:PTR
0 "memory_operand" "=m")
6958 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
6960 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
6962 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
6963 [(set_attr "length" "
12")
6964 (set_attr "type" "multiple")])
6966 (define_expand "stack_protect_test"
6967 [(match_operand
0 "memory_operand")
6968 (match_operand
1 "memory_operand")
6973 machine_mode mode = GET_MODE (operands[
0]);
6975 result = gen_reg_rtx(mode);
6976 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6978 /* Generate access through the system register. The
6979 sequence we want here is the access
6980 of the stack offset to come with
6981 mrs scratch_reg, <system_register>
6982 add scratch_reg, scratch_reg, :lo12:offset. */
6983 rtx tmp_reg = gen_reg_rtx (mode);
6986 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6987 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6988 GEN_INT (aarch64_stack_protector_guard_offset)));
6992 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
6993 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
6994 GEN_INT (aarch64_stack_protector_guard_offset)));
6997 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
6999 emit_insn ((mode == DImode
7000 ? gen_stack_protect_test_di
7001 : gen_stack_protect_test_si) (result,
7006 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7007 result, const0_rtx, operands[
2]));
7009 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7010 result, const0_rtx, operands[
2]));
7014 (define_insn "stack_protect_test_<mode>"
7015 [(set (match_operand:PTR
0 "register_operand" "=r")
7016 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
7017 (match_operand:PTR
2 "memory_operand" "m")]
7019 (clobber (match_scratch:PTR
3 "=&r"))]
7021 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
7022 [(set_attr "length" "
12")
7023 (set_attr "type" "multiple")])
7025 ;; Write Floating-point Control Register.
7026 (define_insn "set_fpcr"
7027 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
7030 [(set_attr "type" "mrs")])
7032 ;; Read Floating-point Control Register.
7033 (define_insn "get_fpcr"
7034 [(set (match_operand:SI
0 "register_operand" "=r")
7035 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
7038 [(set_attr "type" "mrs")])
7040 ;; Write Floating-point Status Register.
7041 (define_insn "set_fpsr"
7042 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
7045 [(set_attr "type" "mrs")])
7047 ;; Read Floating-point Status Register.
7048 (define_insn "get_fpsr"
7049 [(set (match_operand:SI
0 "register_operand" "=r")
7050 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
7053 [(set_attr "type" "mrs")])
7056 ;; Define the subtract-one-and-jump insns so loop.c
7057 ;; knows what to generate.
7058 (define_expand "doloop_end"
7059 [(use (match_operand
0 "" "")) ; loop pseudo
7060 (use (match_operand
1 "" ""))] ; label
7061 "optimize >
0 && flag_modulo_sched"
7070 /* Currently SMS relies on the do-loop pattern to recognize loops
7071 where (
1) the control part consists of all insns defining and/or
7072 using a certain 'count' register and (
2) the loop count can be
7073 adjusted by modifying this register prior to the loop.
7074 ??? The possible introduction of a new block to initialize the
7075 new IV can potentially affect branch optimizations. */
7077 if (GET_MODE (operands[
0]) != DImode)
7081 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
7083 cmp = XVECEXP (PATTERN (insn),
0,
0);
7084 cc_reg = SET_DEST (cmp);
7085 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7086 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
7087 emit_jump_insn (gen_rtx_SET (pc_rtx,
7088 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7093 ;; Track speculation through conditional branches. We assume that
7094 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7095 (define_insn "speculation_tracker"
7096 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7097 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand
0)]
7098 UNSPEC_SPECULATION_TRACKER))]
7101 operands[
1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7102 output_asm_insn ("csel
\\t%
1, %
1, xzr, %m0", operands);
7105 [(set_attr "type" "csel")]
7108 ;; BTI <target> instructions
7109 (define_insn "bti_noarg"
7110 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_NOARG)]
7113 [(set_attr "type" "no_insn")]
7116 (define_insn "bti_c"
7117 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_C)]
7120 [(set_attr "type" "no_insn")]
7123 (define_insn "bti_j"
7124 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_J)]
7127 [(set_attr "type" "no_insn")]
7130 (define_insn "bti_jc"
7131 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_JC)]
7133 "hint
\t38 // bti jc"
7134 [(set_attr "type" "no_insn")]
7137 ;; Helper for aarch64.c code.
7138 (define_expand "set_clobber_cc_nzc"
7139 [(parallel [(set (match_operand
0)
7141 (clobber (reg:CC_NZC CC_REGNUM))])])
7143 ;; Hard speculation barrier.
7144 (define_insn "speculation_barrier"
7145 [(unspec_volatile [(const_int
0)] UNSPECV_SPECULATION_BARRIER)]
7148 [(set_attr "length" "
8")
7149 (set_attr "type" "block")
7150 (set_attr "speculation_barrier" "true")]
7153 ;; Support for __builtin_speculation_safe_value when we have speculation
7154 ;; tracking enabled. Use the speculation tracker to decide whether to
7155 ;; copy operand
1 to the target, or to copy the fail value (operand
2).
7156 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7157 [(set (match_operand:ALLI_TI
0 "register_operand")
7158 (unspec_volatile:ALLI_TI
7159 [(match_operand:ALLI_TI
1 "register_operand")
7160 (match_operand:ALLI_TI
2 "aarch64_reg_or_zero")
7161 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7162 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7166 if (operands[
2] == const0_rtx)
7169 if (<MODE>mode == TImode)
7170 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7172 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7174 emit_insn (gen_despeculate_simple<mode> (operands[
0], operands[
1],
7182 ;; Patterns to match despeculate_copy<mode>. Note that "hint
0x14" is the
7183 ;; encoding for CSDB, but will work in older versions of the assembler.
7184 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7185 [(set (match_operand:ALLI
0 "register_operand" "=r")
7186 (unspec_volatile:ALLI
7187 [(match_operand:ALLI
1 "register_operand" "r")
7188 (match_operand:ALLI
2 "aarch64_reg_or_zero" "rZ")
7189 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7190 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7193 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7194 output_asm_insn ("cmp
\\t%
3, #
0\;csel
\\t%<w>
0, %<w>
1, %<w>
2, ne\;hint
\t0x14 // csdb",
7198 [(set_attr "length" "
12")
7199 (set_attr "type" "block")
7200 (set_attr "speculation_barrier" "true")]
7203 ;; Pattern to match despeculate_copyti
7204 (define_insn "*despeculate_copyti_insn"
7205 [(set (match_operand:TI
0 "register_operand" "=r")
7207 [(match_operand:TI
1 "register_operand" "r")
7208 (match_operand:TI
2 "aarch64_reg_or_zero" "rZ")
7209 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7210 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7213 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7215 ("cmp
\\t%
3, #
0\;csel
\\t%
0, %
1, %
2, ne\;csel
\\t%H0, %H1, %H2, ne\;hint
\t0x14 // csdb",
7219 [(set_attr "length" "
16")
7220 (set_attr "type" "block")
7221 (set_attr "speculation_barrier" "true")]
7224 (define_insn "despeculate_simple<ALLI:mode>"
7225 [(set (match_operand:ALLI
0 "register_operand" "=r")
7226 (unspec_volatile:ALLI
7227 [(match_operand:ALLI
1 "register_operand" "r")
7228 (use (match_operand:ALLI
2 "register_operand" ""))]
7229 UNSPECV_SPECULATION_BARRIER))]
7231 "and
\\t%<w>
0, %<w>
1, %<w>
2\;hint
\t0x14 // csdb"
7232 [(set_attr "type" "block")
7233 (set_attr "length" "
8")
7234 (set_attr "speculation_barrier" "true")]
7237 (define_insn "despeculate_simpleti"
7238 [(set (match_operand:TI
0 "register_operand" "=r")
7240 [(match_operand:TI
1 "register_operand" "r")
7241 (use (match_operand:DI
2 "register_operand" ""))]
7242 UNSPECV_SPECULATION_BARRIER))]
7244 "and
\\t%
0, %
1, %
2\;and
\\t%H0, %H1, %
2\;hint
\t0x14 // csdb"
7245 [(set_attr "type" "block")
7246 (set_attr "length" "
12")
7247 (set_attr "speculation_barrier" "true")]
7250 ;; Transactional Memory Extension (TME) instructions.
7252 (define_insn "tstart"
7253 [(set (match_operand:DI
0 "register_operand" "=r")
7254 (unspec_volatile:DI [(const_int
0)] UNSPECV_TSTART))
7255 (clobber (mem:BLK (scratch)))]
7258 [(set_attr "type" "tme")]
7261 (define_insn "ttest"
7262 [(set (match_operand:DI
0 "register_operand" "=r")
7263 (unspec_volatile:DI [(const_int
0)] UNSPEC_TTEST))
7264 (clobber (mem:BLK (scratch)))]
7267 [(set_attr "type" "tme")]
7270 (define_insn "tcommit"
7271 [(unspec_volatile:BLK [(const_int
0)] UNSPECV_TCOMMIT)
7272 (clobber (mem:BLK (scratch)))]
7275 [(set_attr "type" "tme")]
7278 (define_insn "tcancel"
7279 [(unspec_volatile:BLK
7280 [(match_operand
0 "const_int_operand" "n")] UNSPECV_TCANCEL)
7281 (clobber (mem:BLK (scratch)))]
7282 "TARGET_TME && (UINTVAL (operands[
0]) <=
65535)"
7284 [(set_attr "type" "tme")]
7288 (include "aarch64-simd.md")
7290 ;; Atomic Operations
7291 (include "atomics.md")
7293 ;; ldp/stp peephole patterns
7294 (include "aarch64-ldpstp.md")
7297 (include "aarch64-sve.md")
7300 (include "aarch64-sve2.md")