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/>.
91 ;; Defined only to make the DWARF description simpler.
109 (LAST_SAVED_REGNUM
83)
111 ;; "FFR token": a fake register used for representing the scheduling
112 ;; restrictions on FFR-related operations.
114 ;; Scratch register used by stack clash protection to calculate
115 ;; SVE CFA offsets during probing.
116 (STACK_CLASH_SVE_CFA_REGNUM
11)
117 ;; Scratch registers for prologue/epilogue use.
120 ;; A couple of call-clobbered registers that we need to reserve when
121 ;; tracking speculation this is not ABI, so is subject to change.
122 (SPECULATION_SCRATCH_REGNUM
14)
123 (SPECULATION_TRACKER_REGNUM
15)
124 ;; Scratch registers used in frame layout.
132 (define_c_enum "unspec" [
166 UNSPEC_GOTSMALLPIC28K
256 UNSPEC_SPECULATION_TRACKER
258 UNSPEC_TTEST ; Represent transaction test.
263 ;; Represents an SVE-style lane index, in which the indexing applies
264 ;; within the containing
128-bit block.
265 UNSPEC_SVE_LANE_SELECT
268 UNSPEC_SVE_PREFETCH_GATHER
273 (define_c_enum "unspecv" [
274 UNSPECV_EH_RETURN ; Represent EH_RETURN
275 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
276 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
277 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
278 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
279 UNSPECV_BLOCKAGE ; Represent a blockage
280 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
281 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
282 UNSPECV_BTI_NOARG ; Represent BTI.
283 UNSPECV_BTI_C ; Represent BTI c.
284 UNSPECV_BTI_J ; Represent BTI j.
285 UNSPECV_BTI_JC ; Represent BTI jc.
286 UNSPECV_TSTART ; Represent transaction start.
287 UNSPECV_TCOMMIT ; Represent transaction commit.
288 UNSPECV_TCANCEL ; Represent transaction cancel.
289 UNSPEC_RNDR ; Represent RNDR
290 UNSPEC_RNDRRS ; Represent RNDRRS
294 ;; These constants are used as a const_int in various SVE unspecs
295 ;; to indicate whether the governing predicate is known to be a PTRUE.
297 [; Indicates that the predicate might not be a PTRUE.
298 (SVE_MAYBE_NOT_PTRUE
0)
300 ; Indicates that the predicate is known to be a PTRUE.
301 (SVE_KNOWN_PTRUE
1)])
303 ;; These constants are used as a const_int in predicated SVE FP arithmetic
304 ;; to indicate whether the operation is allowed to make additional lanes
305 ;; active without worrying about the effect on faulting behavior.
307 [; Indicates either that all lanes are active or that the instruction may
308 ; operate on inactive inputs even if doing so could induce a fault.
311 ; Indicates that some lanes might be inactive and that the instruction
312 ; must not operate on inactive inputs if doing so could induce a fault.
315 ;; If further include files are added the defintion of MD_INCLUDES
318 (include "constraints.md")
319 (include "predicates.md")
320 (include "iterators.md")
322 ;; -------------------------------------------------------------------
323 ;; Instruction types and attributes
324 ;; -------------------------------------------------------------------
326 ; The "type" attribute is included here from AArch32 backend to be able
327 ; to share pipeline descriptions.
328 (include "../arm/types.md")
330 ;; It is important to set the fp or simd attributes to yes when a pattern
331 ;; alternative uses the FP or SIMD register files, usually signified by use of
332 ;; the 'w' constraint. This will ensure that the alternative will be
333 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
334 ;; architecture extensions. If all the alternatives in a pattern use the
335 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
338 ;; Attributes of the architecture required to support the instruction (or
339 ;; alternative). This attribute is used to compute attribute "enabled", use type
340 ;; "any" to enable an alternative in all cases.
342 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
344 (define_enum_attr "arch" "arches" (const_string "any"))
346 ;; [For compatibility with Arm in pipeline models]
347 ;; Attribute that specifies whether or not the instruction touches fp
349 ;; Note that this attribute is not used anywhere in either the arm or aarch64
350 ;; backends except in the scheduling description for xgene1. In that
351 ;; scheduling description this attribute is used to subclass the load_4 and
353 (define_attr "fp" "no,yes"
355 (eq_attr "arch" "fp")
357 (const_string "no")))
359 (define_attr "arch_enabled" "no,yes"
362 (eq_attr "arch" "any")
364 (and (eq_attr "arch" "rcpc8_4")
365 (match_test "AARCH64_ISA_RCPC8_4"))
367 (and (eq_attr "arch" "fp")
368 (match_test "TARGET_FLOAT"))
370 (and (eq_attr "arch" "simd")
371 (match_test "TARGET_SIMD"))
373 (and (eq_attr "arch" "fp16")
374 (match_test "TARGET_FP_F16INST"))
376 (and (eq_attr "arch" "sve")
377 (match_test "TARGET_SVE")))
379 (const_string "no")))
381 ;; Attribute that controls whether an alternative is enabled or not.
382 ;; Currently it is only used to disable alternatives which touch fp or simd
383 ;; registers when -mgeneral-regs-only is specified or to require a special
384 ;; architecture support.
385 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
387 ;; Attribute that specifies whether we are dealing with a branch to a
388 ;; label that is far away, i.e. further away than the maximum/minimum
389 ;; representable in a signed
21-bits number.
392 (define_attr "far_branch" "" (const_int
0))
394 ;; Attribute that specifies whether the alternative uses MOVPRFX.
395 (define_attr "movprfx" "no,yes" (const_string "no"))
397 (define_attr "length" ""
398 (cond [(eq_attr "movprfx" "yes")
402 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
403 ;; no predicated insns.
404 (define_attr "predicated" "yes,no" (const_string "no"))
406 ;; Set to true on an insn that requires the speculation tracking state to be
407 ;; in the tracking register before the insn issues. Otherwise the compiler
408 ;; may chose to hold the tracking state encoded in SP.
409 (define_attr "speculation_barrier" "true,false" (const_string "false"))
411 ;; -------------------------------------------------------------------
412 ;; Pipeline descriptions and scheduling
413 ;; -------------------------------------------------------------------
416 (include "aarch64-tune.md")
419 (include "../arm/cortex-a53.md")
420 (include "../arm/cortex-a57.md")
421 (include "../arm/exynos-m1.md")
422 (include "falkor.md")
423 (include "saphira.md")
424 (include "thunderx.md")
425 (include "../arm/xgene1.md")
426 (include "thunderx2t99.md")
427 (include "tsv110.md")
429 ;; -------------------------------------------------------------------
430 ;; Jumps and other miscellaneous insns
431 ;; -------------------------------------------------------------------
433 (define_insn "indirect_jump"
434 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
437 [(set_attr "type" "branch")]
441 [(set (pc) (label_ref (match_operand
0 "" "")))]
444 [(set_attr "type" "branch")]
447 (define_expand "cbranch<mode>
4"
448 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
449 [(match_operand:GPI
1 "register_operand")
450 (match_operand:GPI
2 "aarch64_plus_operand")])
451 (label_ref (match_operand
3 "" ""))
455 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
457 operands[
2] = const0_rtx;
461 (define_expand "cbranch<mode>
4"
462 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
463 [(match_operand:GPF
1 "register_operand")
464 (match_operand:GPF
2 "aarch64_fp_compare_operand")])
465 (label_ref (match_operand
3 "" ""))
469 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
471 operands[
2] = const0_rtx;
475 (define_expand "cbranchcc4"
476 [(set (pc) (if_then_else
477 (match_operator
0 "aarch64_comparison_operator"
478 [(match_operand
1 "cc_register")
479 (match_operand
2 "const0_operand")])
480 (label_ref (match_operand
3 "" ""))
485 (define_insn "ccmp<mode>"
486 [(set (match_operand:CC
1 "cc_register" "")
488 (match_operator
4 "aarch64_comparison_operator"
489 [(match_operand
0 "cc_register" "")
492 (match_operand:GPI
2 "register_operand" "r,r,r")
493 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
494 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
497 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
498 ccmp
\\t%<w>
2, %
3, %k5, %m4
499 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
500 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
503 (define_insn "fccmp<mode>"
504 [(set (match_operand:CCFP
1 "cc_register" "")
506 (match_operator
4 "aarch64_comparison_operator"
507 [(match_operand
0 "cc_register" "")
510 (match_operand:GPF
2 "register_operand" "w")
511 (match_operand:GPF
3 "register_operand" "w"))
512 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
514 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
515 [(set_attr "type" "fccmp<s>")]
518 (define_insn "fccmpe<mode>"
519 [(set (match_operand:CCFPE
1 "cc_register" "")
521 (match_operator
4 "aarch64_comparison_operator"
522 [(match_operand
0 "cc_register" "")
525 (match_operand:GPF
2 "register_operand" "w")
526 (match_operand:GPF
3 "register_operand" "w"))
527 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
529 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
530 [(set_attr "type" "fccmp<s>")]
533 ;; Expansion of signed mod by a power of
2 using CSNEG.
534 ;; For x0 % n where n is a power of
2 produce:
536 ;; and x0, x0, #(n -
1)
537 ;; and x1, x1, #(n -
1)
538 ;; csneg x0, x0, x1, mi
540 (define_expand "mod<mode>
3"
541 [(match_operand:GPI
0 "register_operand")
542 (match_operand:GPI
1 "register_operand")
543 (match_operand:GPI
2 "const_int_operand")]
546 HOST_WIDE_INT val = INTVAL (operands[
2]);
549 || exact_log2 (val) <=
0
550 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
553 rtx mask = GEN_INT (val -
1);
555 /* In the special case of x0 %
2 we can do the even shorter:
561 rtx masked = gen_reg_rtx (<MODE>mode);
562 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
563 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
564 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
565 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
569 rtx neg_op = gen_reg_rtx (<MODE>mode);
570 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
572 /* Extract the condition register and mode. */
573 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
574 rtx cc_reg = SET_DEST (cmp);
575 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
577 rtx masked_pos = gen_reg_rtx (<MODE>mode);
578 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
580 rtx masked_neg = gen_reg_rtx (<MODE>mode);
581 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
583 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
584 masked_neg, masked_pos));
589 (define_insn "condjump"
590 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
591 [(match_operand
1 "cc_register" "") (const_int
0)])
592 (label_ref (match_operand
2 "" ""))
596 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
597 but the "." is required for SVE conditions. */
598 bool use_dot_p = GET_MODE (operands[
1]) == CC_NZCmode;
599 if (get_attr_length (insn) ==
8)
600 return aarch64_gen_far_branch (operands,
2, "Lbcond",
601 use_dot_p ? "b.%M0
\\t" : "b%M0
\\t");
603 return use_dot_p ? "b.%m0
\\t%l2" : "b%m0
\\t%l2";
605 [(set_attr "type" "branch")
607 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
608 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
611 (set (attr "far_branch")
612 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
613 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
618 ;; For a
24-bit immediate CST we can optimize the compare for equality
619 ;; and branch sequence from:
621 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
625 ;; sub x0, x1, #(CST &
0xfff000)
626 ;; subs x0, x0, #(CST &
0x000fff)
628 (define_insn_and_split "*compare_condjump<GPI:mode>"
629 [(set (pc) (if_then_else (EQL
630 (match_operand:GPI
0 "register_operand" "r")
631 (match_operand:GPI
1 "aarch64_imm24" "n"))
632 (label_ref:P (match_operand
2 "" ""))
634 "!aarch64_move_imm (INTVAL (operands[
1]), <GPI:MODE>mode)
635 && !aarch64_plus_operand (operands[
1], <GPI:MODE>mode)
636 && !reload_completed"
641 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
642 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
643 rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
644 emit_insn (gen_add<GPI:mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
645 emit_insn (gen_add<GPI:mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
646 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
647 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
649 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
654 (define_expand "casesi"
655 [(match_operand:SI
0 "register_operand") ; Index
656 (match_operand:SI
1 "const_int_operand") ; Lower bound
657 (match_operand:SI
2 "const_int_operand") ; Total range
658 (match_operand:DI
3 "" "") ; Table label
659 (match_operand:DI
4 "" "")] ; Out of range label
662 if (operands[
1] != const0_rtx)
664 rtx reg = gen_reg_rtx (SImode);
666 /* Canonical RTL says that if you have:
670 then this should be emitted as:
674 The use of trunc_int_for_mode ensures that the resulting
675 constant can be represented in SImode, this is important
676 for the corner case where operand[
1] is INT_MIN. */
678 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
680 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
681 (operands[
1], SImode))
682 operands[
1] = force_reg (SImode, operands[
1]);
683 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
687 if (!aarch64_plus_operand (operands[
2], SImode))
688 operands[
2] = force_reg (SImode, operands[
2]);
689 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
691 operands[
0], operands[
2], operands[
4]));
693 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
695 = gen_rtx_UNSPEC (Pmode, gen_rtvec (
2, operands[
2], operands[
0]),
697 operands[
2] = gen_rtx_MEM (DImode, operands[
2]);
698 MEM_READONLY_P (operands[
2]) =
1;
699 MEM_NOTRAP_P (operands[
2]) =
1;
700 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
3]));
705 (define_expand "casesi_dispatch"
707 [(set (pc) (match_operand:DI
0 ""))
708 (clobber (reg:CC CC_REGNUM))
709 (clobber (match_scratch:DI
2))
710 (clobber (match_scratch:DI
3))
711 (use (label_ref:DI (match_operand
1 "")))])]
714 (define_insn "*casesi_dispatch"
717 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
718 (match_operand:SI
1 "register_operand" "r")]
720 (clobber (reg:CC CC_REGNUM))
721 (clobber (match_scratch:DI
3 "=r"))
722 (clobber (match_scratch:DI
4 "=r"))
723 (use (label_ref:DI (match_operand
2 "" "")))])]
726 return aarch64_output_casesi (operands);
728 [(set_attr "length" "
16")
729 (set_attr "type" "branch")]
733 [(unspec[(const_int
0)] UNSPEC_NOP)]
736 [(set_attr "type" "no_insn")]
739 (define_insn "prefetch"
740 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
741 (match_operand:QI
1 "const_int_operand" "")
742 (match_operand:QI
2 "const_int_operand" ""))]
745 const char * pftype[
2][
4] =
747 {"prfm
\\tPLDL1STRM, %
0",
748 "prfm
\\tPLDL3KEEP, %
0",
749 "prfm
\\tPLDL2KEEP, %
0",
750 "prfm
\\tPLDL1KEEP, %
0"},
751 {"prfm
\\tPSTL1STRM, %
0",
752 "prfm
\\tPSTL3KEEP, %
0",
753 "prfm
\\tPSTL2KEEP, %
0",
754 "prfm
\\tPSTL1KEEP, %
0"},
757 int locality = INTVAL (operands[
2]);
759 gcc_assert (IN_RANGE (locality,
0,
3));
761 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
762 the address into a DImode MEM so that aarch64_print_operand knows
764 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
765 return pftype[INTVAL(operands[
1])][locality];
767 [(set_attr "type" "load_4")]
771 [(trap_if (const_int
1) (const_int
8))]
774 [(set_attr "type" "trap")])
776 (define_expand "prologue"
777 [(clobber (const_int
0))]
780 aarch64_expand_prologue ();
785 (define_expand "epilogue"
786 [(clobber (const_int
0))]
789 aarch64_expand_epilogue (false);
794 (define_expand "sibcall_epilogue"
795 [(clobber (const_int
0))]
798 aarch64_expand_epilogue (true);
803 (define_insn "*do_return"
807 if (aarch64_return_address_signing_enabled ()
809 && !crtl->calls_eh_return)
811 if (aarch64_ra_sign_key == AARCH64_KEY_B)
818 [(set_attr "type" "branch")]
821 (define_expand "return"
823 "aarch64_use_return_insn_p ()"
827 (define_insn "simple_return"
831 [(set_attr "type" "branch")]
834 (define_insn "*cb<optab><mode>
1"
835 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
837 (label_ref (match_operand
1 "" ""))
839 "!aarch64_track_speculation"
841 if (get_attr_length (insn) ==
8)
842 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
844 return "<cbz>
\\t%<w>
0, %l1";
846 [(set_attr "type" "branch")
848 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
849 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
852 (set (attr "far_branch")
853 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
854 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
859 (define_insn "*tb<optab><mode>
1"
860 [(set (pc) (if_then_else
861 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
864 "aarch64_simd_shift_imm_<mode>" "n"))
866 (label_ref (match_operand
2 "" ""))
868 (clobber (reg:CC CC_REGNUM))]
869 "!aarch64_track_speculation"
871 if (get_attr_length (insn) ==
8)
873 if (get_attr_far_branch (insn) ==
1)
874 return aarch64_gen_far_branch (operands,
2, "Ltb",
875 "<inv_tb>
\\t%<w>
0, %
1, ");
878 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
879 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
883 return "<tbz>
\t%<w>
0, %
1, %l2";
885 [(set_attr "type" "branch")
887 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
888 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
891 (set (attr "far_branch")
892 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
893 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
899 (define_insn "*cb<optab><mode>
1"
900 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
902 (label_ref (match_operand
1 "" ""))
904 (clobber (reg:CC CC_REGNUM))]
905 "!aarch64_track_speculation"
907 if (get_attr_length (insn) ==
8)
909 if (get_attr_far_branch (insn) ==
1)
910 return aarch64_gen_far_branch (operands,
1, "Ltb",
911 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
915 uint64_t val = ((uint64_t)
1)
916 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
917 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
918 output_asm_insn (buf, operands);
919 return "<bcond>
\t%l1";
923 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
925 [(set_attr "type" "branch")
927 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
928 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
931 (set (attr "far_branch")
932 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
933 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
938 ;; -------------------------------------------------------------------
939 ;; Subroutine calls and sibcalls
940 ;; -------------------------------------------------------------------
942 (define_expand "call"
944 [(call (match_operand
0 "memory_operand")
945 (match_operand
1 "general_operand"))
946 (unspec:DI [(match_operand
2 "const_int_operand")] UNSPEC_CALLEE_ABI)
947 (clobber (reg:DI LR_REGNUM))])]
951 aarch64_expand_call (NULL_RTX, operands[
0], operands[
2], false);
956 (define_insn "*call_insn"
957 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
958 (match_operand
1 "" ""))
959 (unspec:DI [(match_operand:DI
2 "const_int_operand")] UNSPEC_CALLEE_ABI)
960 (clobber (reg:DI LR_REGNUM))]
965 [(set_attr "type" "call, call")]
968 (define_expand "call_value"
970 [(set (match_operand
0 "")
971 (call (match_operand
1 "memory_operand")
972 (match_operand
2 "general_operand")))
973 (unspec:DI [(match_operand
3 "const_int_operand")] UNSPEC_CALLEE_ABI)
974 (clobber (reg:DI LR_REGNUM))])]
978 aarch64_expand_call (operands[
0], operands[
1], operands[
3], false);
983 (define_insn "*call_value_insn"
984 [(set (match_operand
0 "" "")
985 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
986 (match_operand
2 "" "")))
987 (unspec:DI [(match_operand:DI
3 "const_int_operand")] UNSPEC_CALLEE_ABI)
988 (clobber (reg:DI LR_REGNUM))]
993 [(set_attr "type" "call, call")]
996 (define_expand "sibcall"
998 [(call (match_operand
0 "memory_operand")
999 (match_operand
1 "general_operand"))
1000 (unspec:DI [(match_operand
2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1004 aarch64_expand_call (NULL_RTX, operands[
0], operands[
2], true);
1009 (define_expand "sibcall_value"
1011 [(set (match_operand
0 "")
1012 (call (match_operand
1 "memory_operand")
1013 (match_operand
2 "general_operand")))
1014 (unspec:DI [(match_operand
3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1018 aarch64_expand_call (operands[
0], operands[
1], operands[
3], true);
1023 (define_insn "*sibcall_insn"
1024 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
1025 (match_operand
1 ""))
1026 (unspec:DI [(match_operand:DI
2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1028 "SIBLING_CALL_P (insn)"
1032 [(set_attr "type" "branch, branch")]
1035 (define_insn "*sibcall_value_insn"
1036 [(set (match_operand
0 "")
1038 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
1039 (match_operand
2 "")))
1040 (unspec:DI [(match_operand:DI
3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1042 "SIBLING_CALL_P (insn)"
1046 [(set_attr "type" "branch, branch")]
1049 ;; Call subroutine returning any type.
1051 (define_expand "untyped_call"
1052 [(parallel [(call (match_operand
0 "")
1054 (match_operand
1 "")
1055 (match_operand
2 "")])]
1060 /* Untyped calls always use the default ABI. It's only possible to use
1061 ABI variants if we know the type of the target function. */
1062 emit_call_insn (gen_call (operands[
0], const0_rtx, const0_rtx));
1064 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
1066 rtx set = XVECEXP (operands[
2],
0, i);
1067 emit_move_insn (SET_DEST (set), SET_SRC (set));
1070 /* The optimizer does not know that the call sets the function value
1071 registers we stored in the result block. We avoid problems by
1072 claiming that all hard registers are used and clobbered at this
1074 emit_insn (gen_blockage ());
1078 ;; -------------------------------------------------------------------
1080 ;; -------------------------------------------------------------------
1082 (define_expand "mov<mode>"
1083 [(set (match_operand:SHORT
0 "nonimmediate_operand")
1084 (match_operand:SHORT
1 "general_operand"))]
1087 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1088 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1090 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1092 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1098 (define_insn "*mov<mode>_aarch64"
1099 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1100 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1101 "(register_operand (operands[
0], <MODE>mode)
1102 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
1104 switch (which_alternative)
1107 return "mov
\t%w0, %w1";
1109 return "mov
\t%w0, %
1";
1111 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
1114 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1116 return "ldr<size>
\t%w0, %
1";
1118 return "ldr
\t%<size>
0, %
1";
1120 return "str<size>
\t%w1, %
0";
1122 return "str
\t%<size>
1, %
0";
1124 return "umov
\t%w0, %
1.<v>[
0]";
1126 return "dup
\t%
0.<Vallxd>, %w1";
1128 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
1133 ;; The "mov_imm" type for CNT is just a placeholder.
1134 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1135 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1136 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1139 (define_expand "mov<mode>"
1140 [(set (match_operand:GPI
0 "nonimmediate_operand")
1141 (match_operand:GPI
1 "general_operand"))]
1144 if (MEM_P (operands[
0]) && !MEM_VOLATILE_P (operands[
0])
1145 && CONST_INT_P (operands[
1]) && <MODE>mode == DImode
1146 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
1149 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1150 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1152 /* FIXME: RR we still need to fix up what we are doing with
1153 symbol_refs and other types of constants. */
1154 if (CONSTANT_P (operands[
1])
1155 && !CONST_INT_P (operands[
1]))
1157 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1163 (define_insn_and_split "*movsi_aarch64"
1164 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1165 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1166 "(register_operand (operands[
0], SImode)
1167 || aarch64_reg_or_zero (operands[
1], SImode))"
1174 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1184 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1185 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1186 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1189 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1192 ;; The "mov_imm" type for CNT is just a placeholder.
1193 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1194 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1195 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1198 (define_insn_and_split "*movdi_aarch64"
1199 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1200 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1201 "(register_operand (operands[
0], DImode)
1202 || aarch64_reg_or_zero (operands[
1], DImode))"
1210 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1220 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1221 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1222 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1225 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1228 ;; The "mov_imm" type for CNTD is just a placeholder.
1229 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1230 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1232 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1235 (define_insn "insv_imm<mode>"
1236 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1238 (match_operand:GPI
1 "const_int_operand" "n"))
1239 (match_operand:GPI
2 "const_int_operand" "n"))]
1240 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1241 && UINTVAL (operands[
1]) %
16 ==
0"
1242 "movk
\\t%<w>
0, %X2, lsl %
1"
1243 [(set_attr "type" "mov_imm")]
1246 (define_expand "movti"
1247 [(set (match_operand:TI
0 "nonimmediate_operand")
1248 (match_operand:TI
1 "general_operand"))]
1251 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1252 operands[
1] = force_reg (TImode, operands[
1]);
1254 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1256 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1257 gen_lowpart (DImode, operands[
1]));
1258 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1264 (define_insn "*movti_aarch64"
1265 [(set (match_operand:TI
0
1266 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1268 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1269 "(register_operand (operands[
0], TImode)
1270 || aarch64_reg_or_zero (operands[
1], TImode))"
1275 mov
\\t%
0.16b, %
1.16b
1281 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1282 load_16,store_16,store_16,\
1284 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1285 (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
1288 ;; Split a TImode register-register or register-immediate move into
1289 ;; its component DImode pieces, taking care to handle overlapping
1290 ;; source and dest registers.
1292 [(set (match_operand:TI
0 "register_operand" "")
1293 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1294 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1297 aarch64_split_128bit_move (operands[
0], operands[
1]);
1301 (define_expand "mov<mode>"
1302 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand")
1303 (match_operand:GPF_TF_F16
1 "general_operand"))]
1308 aarch64_err_no_fpadvsimd (<MODE>mode);
1312 if (GET_CODE (operands[
0]) == MEM
1313 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1314 && aarch64_float_const_zero_rtx_p (operands[
1])))
1315 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1319 (define_insn "*movhf_aarch64"
1320 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1321 (match_operand:HF
1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1322 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1323 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1329 mov
\\t%
0.h[
0], %
1.h[
0]
1331 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1337 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1338 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1339 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1342 (define_insn "*movsf_aarch64"
1343 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1344 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1345 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1346 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1353 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1360 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1361 f_loads,f_stores,load_4,store_4,mov_reg,\
1363 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1366 (define_insn "*movdf_aarch64"
1367 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1368 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1369 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1370 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1377 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1384 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1385 f_loadd,f_stored,load_8,store_8,mov_reg,\
1387 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1391 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1392 (match_operand:GPF_HF
1 "general_operand"))]
1393 "can_create_pseudo_p ()
1394 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1395 && !aarch64_float_const_representable_p (operands[
1])
1396 && aarch64_float_const_rtx_p (operands[
1])"
1399 unsigned HOST_WIDE_INT ival;
1400 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1403 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1404 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1405 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1410 (define_insn "*movtf_aarch64"
1411 [(set (match_operand:TF
0
1412 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1414 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1415 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1416 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1418 mov
\\t%
0.16b, %
1.16b
1429 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1430 f_loadd,f_stored,load_16,store_16,store_16")
1431 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1432 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1436 [(set (match_operand:TF
0 "register_operand" "")
1437 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1438 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1441 aarch64_split_128bit_move (operands[
0], operands[
1]);
1448 ;;
2 is size of copy in bytes
1451 (define_expand "cpymemdi"
1452 [(match_operand:BLK
0 "memory_operand")
1453 (match_operand:BLK
1 "memory_operand")
1454 (match_operand:DI
2 "immediate_operand")
1455 (match_operand:DI
3 "immediate_operand")]
1458 if (aarch64_expand_cpymem (operands))
1464 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1465 ;; fairly lax checking on the second memory operation.
1466 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1467 [(set (match_operand:SX
0 "register_operand" "=r,w")
1468 (match_operand:SX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1469 (set (match_operand:SX2
2 "register_operand" "=r,w")
1470 (match_operand:SX2
3 "memory_operand" "m,m"))]
1471 "rtx_equal_p (XEXP (operands[
3],
0),
1472 plus_constant (Pmode,
1473 XEXP (operands[
1],
0),
1474 GET_MODE_SIZE (<SX:MODE>mode)))"
1478 [(set_attr "type" "load_8,neon_load1_2reg")
1479 (set_attr "arch" "*,fp")]
1482 ;; Storing different modes that can still be merged
1483 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1484 [(set (match_operand:DX
0 "register_operand" "=r,w")
1485 (match_operand:DX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1486 (set (match_operand:DX2
2 "register_operand" "=r,w")
1487 (match_operand:DX2
3 "memory_operand" "m,m"))]
1488 "rtx_equal_p (XEXP (operands[
3],
0),
1489 plus_constant (Pmode,
1490 XEXP (operands[
1],
0),
1491 GET_MODE_SIZE (<DX:MODE>mode)))"
1495 [(set_attr "type" "load_16,neon_load1_2reg")
1496 (set_attr "arch" "*,fp")]
1499 (define_insn "load_pair_dw_tftf"
1500 [(set (match_operand:TF
0 "register_operand" "=w")
1501 (match_operand:TF
1 "aarch64_mem_pair_operand" "Ump"))
1502 (set (match_operand:TF
2 "register_operand" "=w")
1503 (match_operand:TF
3 "memory_operand" "m"))]
1505 && rtx_equal_p (XEXP (operands[
3],
0),
1506 plus_constant (Pmode,
1507 XEXP (operands[
1],
0),
1508 GET_MODE_SIZE (TFmode)))"
1509 "ldp
\\t%q0, %q2, %
1"
1510 [(set_attr "type" "neon_ldp_q")
1511 (set_attr "fp" "yes")]
1514 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1515 ;; fairly lax checking on the second memory operation.
1516 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1517 [(set (match_operand:SX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1518 (match_operand:SX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1519 (set (match_operand:SX2
2 "memory_operand" "=m,m")
1520 (match_operand:SX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1521 "rtx_equal_p (XEXP (operands[
2],
0),
1522 plus_constant (Pmode,
1523 XEXP (operands[
0],
0),
1524 GET_MODE_SIZE (<SX:MODE>mode)))"
1528 [(set_attr "type" "store_8,neon_store1_2reg")
1529 (set_attr "arch" "*,fp")]
1532 ;; Storing different modes that can still be merged
1533 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1534 [(set (match_operand:DX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1535 (match_operand:DX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1536 (set (match_operand:DX2
2 "memory_operand" "=m,m")
1537 (match_operand:DX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1538 "rtx_equal_p (XEXP (operands[
2],
0),
1539 plus_constant (Pmode,
1540 XEXP (operands[
0],
0),
1541 GET_MODE_SIZE (<DX:MODE>mode)))"
1545 [(set_attr "type" "store_16,neon_store1_2reg")
1546 (set_attr "arch" "*,fp")]
1549 (define_insn "store_pair_dw_tftf"
1550 [(set (match_operand:TF
0 "aarch64_mem_pair_operand" "=Ump")
1551 (match_operand:TF
1 "register_operand" "w"))
1552 (set (match_operand:TF
2 "memory_operand" "=m")
1553 (match_operand:TF
3 "register_operand" "w"))]
1555 rtx_equal_p (XEXP (operands[
2],
0),
1556 plus_constant (Pmode,
1557 XEXP (operands[
0],
0),
1558 GET_MODE_SIZE (TFmode)))"
1559 "stp
\\t%q1, %q3, %
0"
1560 [(set_attr "type" "neon_stp_q")
1561 (set_attr "fp" "yes")]
1564 ;; Load pair with post-index writeback. This is primarily used in function
1566 (define_insn "loadwb_pair<GPI: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 (match_operand:GPI
2 "register_operand" "=r")
1572 (mem:GPI (match_dup
1)))
1573 (set (match_operand:GPI
3 "register_operand" "=r")
1574 (mem:GPI (plus:P (match_dup
1)
1575 (match_operand:P
5 "const_int_operand" "n"))))])]
1576 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1577 "ldp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
1], %
4"
1578 [(set_attr "type" "load_<GPI:ldpstp_sz>")]
1581 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1583 [(set (match_operand:P
0 "register_operand" "=k")
1584 (plus:P (match_operand:P
1 "register_operand" "
0")
1585 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1586 (set (match_operand:GPF
2 "register_operand" "=w")
1587 (mem:GPF (match_dup
1)))
1588 (set (match_operand:GPF
3 "register_operand" "=w")
1589 (mem:GPF (plus:P (match_dup
1)
1590 (match_operand:P
5 "const_int_operand" "n"))))])]
1591 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1592 "ldp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
1], %
4"
1593 [(set_attr "type" "neon_load1_2reg")]
1596 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1598 [(set (match_operand:P
0 "register_operand" "=k")
1599 (plus:P (match_operand:P
1 "register_operand" "
0")
1600 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1601 (set (match_operand:TX
2 "register_operand" "=w")
1602 (mem:TX (match_dup
1)))
1603 (set (match_operand:TX
3 "register_operand" "=w")
1604 (mem:TX (plus:P (match_dup
1)
1605 (match_operand:P
5 "const_int_operand" "n"))))])]
1606 "TARGET_SIMD && INTVAL (operands[
5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1607 "ldp
\\t%q2, %q3, [%
1], %
4"
1608 [(set_attr "type" "neon_ldp_q")]
1611 ;; Store pair with pre-index writeback. This is primarily used in function
1613 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1615 [(set (match_operand:P
0 "register_operand" "=&k")
1616 (plus:P (match_operand:P
1 "register_operand" "
0")
1617 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1618 (set (mem:GPI (plus:P (match_dup
0)
1620 (match_operand:GPI
2 "register_operand" "r"))
1621 (set (mem:GPI (plus:P (match_dup
0)
1622 (match_operand:P
5 "const_int_operand" "n")))
1623 (match_operand:GPI
3 "register_operand" "r"))])]
1624 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1625 "stp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
0, %
4]!"
1626 [(set_attr "type" "store_<GPI:ldpstp_sz>")]
1629 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1631 [(set (match_operand:P
0 "register_operand" "=&k")
1632 (plus:P (match_operand:P
1 "register_operand" "
0")
1633 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1634 (set (mem:GPF (plus:P (match_dup
0)
1636 (match_operand:GPF
2 "register_operand" "w"))
1637 (set (mem:GPF (plus:P (match_dup
0)
1638 (match_operand:P
5 "const_int_operand" "n")))
1639 (match_operand:GPF
3 "register_operand" "w"))])]
1640 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1641 "stp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
0, %
4]!"
1642 [(set_attr "type" "neon_store1_2reg<q>")]
1645 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1647 [(set (match_operand:P
0 "register_operand" "=&k")
1648 (plus:P (match_operand:P
1 "register_operand" "
0")
1649 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1650 (set (mem:TX (plus:P (match_dup
0)
1652 (match_operand:TX
2 "register_operand" "w"))
1653 (set (mem:TX (plus:P (match_dup
0)
1654 (match_operand:P
5 "const_int_operand" "n")))
1655 (match_operand:TX
3 "register_operand" "w"))])]
1657 && INTVAL (operands[
5])
1658 == INTVAL (operands[
4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1659 "stp
\\t%q2, %q3, [%
0, %
4]!"
1660 [(set_attr "type" "neon_stp_q")]
1663 ;; -------------------------------------------------------------------
1664 ;; Sign/Zero extension
1665 ;; -------------------------------------------------------------------
1667 (define_expand "<optab>sidi2"
1668 [(set (match_operand:DI
0 "register_operand")
1669 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1673 (define_insn "*extendsidi2_aarch64"
1674 [(set (match_operand:DI
0 "register_operand" "=r,r")
1675 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1680 [(set_attr "type" "extend,load_4")]
1683 (define_insn "*load_pair_extendsidi2_aarch64"
1684 [(set (match_operand:DI
0 "register_operand" "=r")
1685 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1686 (set (match_operand:DI
2 "register_operand" "=r")
1687 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1688 "rtx_equal_p (XEXP (operands[
3],
0),
1689 plus_constant (Pmode,
1690 XEXP (operands[
1],
0),
1691 GET_MODE_SIZE (SImode)))"
1692 "ldpsw
\\t%
0, %
2, %
1"
1693 [(set_attr "type" "load_8")]
1696 (define_insn "*zero_extendsidi2_aarch64"
1697 [(set (match_operand:DI
0 "register_operand" "=r,r,w,w,r,w")
1698 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1707 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1708 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1711 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1712 [(set (match_operand:DI
0 "register_operand" "=r,w")
1713 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump,Ump")))
1714 (set (match_operand:DI
2 "register_operand" "=r,w")
1715 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m,m")))]
1716 "rtx_equal_p (XEXP (operands[
3],
0),
1717 plus_constant (Pmode,
1718 XEXP (operands[
1],
0),
1719 GET_MODE_SIZE (SImode)))"
1723 [(set_attr "type" "load_8,neon_load1_2reg")
1724 (set_attr "arch" "*,fp")]
1727 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1728 [(set (match_operand:GPI
0 "register_operand")
1729 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1733 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1734 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1735 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1738 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1739 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1740 [(set_attr "type" "extend,load_4")]
1743 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1744 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1745 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1748 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1749 ldr<SHORT:size>
\t%w0, %
1
1750 ldr
\t%<SHORT:size>
0, %
1"
1751 [(set_attr "type" "logic_imm,load_4,f_loads")
1752 (set_attr "arch" "*,*,fp")]
1755 (define_expand "<optab>qihi2"
1756 [(set (match_operand:HI
0 "register_operand")
1757 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1761 (define_insn "*extendqihi2_aarch64"
1762 [(set (match_operand:HI
0 "register_operand" "=r,r")
1763 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1768 [(set_attr "type" "extend,load_4")]
1771 (define_insn "*zero_extendqihi2_aarch64"
1772 [(set (match_operand:HI
0 "register_operand" "=r,r")
1773 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1778 [(set_attr "type" "logic_imm,load_4")]
1781 ;; -------------------------------------------------------------------
1782 ;; Simple arithmetic
1783 ;; -------------------------------------------------------------------
1785 (define_expand "add<mode>
3"
1787 (match_operand:GPI
0 "register_operand")
1788 (plus:GPI (match_operand:GPI
1 "register_operand")
1789 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand")))]
1792 /* If operands[
1] is a subreg extract the inner RTX. */
1793 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1795 /* If the constant is too large for a single instruction and isn't frame
1796 based, split off the immediate so it is available for CSE. */
1797 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1798 && !(TARGET_SVE && aarch64_sve_plus_immediate (operands[
2], <MODE>mode))
1799 && can_create_pseudo_p ()
1801 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1802 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1803 /* Expand polynomial additions now if the destination is the stack
1804 pointer, since we don't want to use that as a temporary. */
1805 else if (operands[
0] == stack_pointer_rtx
1806 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1808 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1809 operands[
2], NULL_RTX, NULL_RTX);
1814 (define_insn "*add<mode>
3_aarch64"
1816 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,r,rk")
1818 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,
0,rk")
1819 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
1822 add
\\t%<w>
0, %<w>
1, %
2
1823 add
\\t%<w>
0, %<w>
1, %<w>
2
1824 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1825 sub
\\t%<w>
0, %<w>
1, #%n2
1827 * return aarch64_output_sve_scalar_inc_dec (operands[
2]);
1828 * return aarch64_output_sve_addvl_addpl (operands[
2]);"
1829 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1830 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm")
1831 (set_attr "arch" "*,*,simd,*,*,sve,sve")]
1834 ;; zero_extend version of above
1835 (define_insn "*addsi3_aarch64_uxtw"
1837 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1839 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1840 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1845 sub
\\t%w0, %w1, #%n2
1847 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1850 ;; If there's a free register, and we can load the constant with a
1851 ;; single instruction, do so. This has a chance to improve scheduling.
1853 [(match_scratch:GPI
3 "r")
1854 (set (match_operand:GPI
0 "register_operand")
1856 (match_operand:GPI
1 "register_operand")
1857 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1858 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1859 [(set (match_dup
3) (match_dup
2))
1860 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1864 [(match_scratch:SI
3 "r")
1865 (set (match_operand:DI
0 "register_operand")
1868 (match_operand:SI
1 "register_operand")
1869 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1870 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1871 [(set (match_dup
3) (match_dup
2))
1872 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1875 ;; After peephole2 has had a chance to run, split any remaining long
1876 ;; additions into two add immediates.
1878 [(set (match_operand:GPI
0 "register_operand")
1880 (match_operand:GPI
1 "register_operand")
1881 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1882 "epilogue_completed"
1883 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1884 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1886 HOST_WIDE_INT i = INTVAL (operands[
2]);
1887 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1888 operands[
3] = GEN_INT (i - s);
1889 operands[
4] = GEN_INT (s);
1893 ;; Match addition of polynomial offsets that require one temporary, for which
1894 ;; we can use the early-clobbered destination register. This is a separate
1895 ;; pattern so that the early clobber doesn't affect register allocation
1896 ;; for other forms of addition. However, we still need to provide an
1897 ;; all-register alternative, in case the offset goes out of range after
1898 ;; elimination. For completeness we might as well provide all GPR-based
1899 ;; alternatives from the main pattern.
1901 ;; We don't have a pattern for additions requiring two temporaries since at
1902 ;; present LRA doesn't allow new scratches to be added during elimination.
1903 ;; Such offsets should be rare anyway.
1905 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1906 ;; here would go away. We could just handle all polynomial constants in
1908 (define_insn_and_split "*add<mode>
3_poly_1"
1910 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,r,&r")
1912 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,
0,rk")
1913 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uai,Uat")))]
1914 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1916 add
\\t%<w>
0, %<w>
1, %
2
1917 add
\\t%<w>
0, %<w>
1, %<w>
2
1918 sub
\\t%<w>
0, %<w>
1, #%n2
1920 * return aarch64_output_sve_scalar_inc_dec (operands[
2]);
1921 * return aarch64_output_sve_addvl_addpl (operands[
2]);
1923 "&& epilogue_completed
1924 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1925 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1928 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1929 operands[
2], operands[
0], NULL_RTX);
1932 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1933 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,alu_imm,multiple")]
1937 [(set (match_operand:DI
0 "register_operand")
1940 (match_operand:SI
1 "register_operand")
1941 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1942 "epilogue_completed"
1943 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1944 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1946 HOST_WIDE_INT i = INTVAL (operands[
2]);
1947 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1948 operands[
3] = GEN_INT (i - s);
1949 operands[
4] = GEN_INT (s);
1950 operands[
5] = gen_lowpart (SImode, operands[
0]);
1954 (define_expand "addv<mode>
4"
1955 [(match_operand:GPI
0 "register_operand")
1956 (match_operand:GPI
1 "register_operand")
1957 (match_operand:GPI
2 "aarch64_plus_operand")
1958 (label_ref (match_operand
3 "" ""))]
1961 if (CONST_INT_P (operands[
2]))
1962 emit_insn (gen_add<mode>
3_compareV_imm (operands[
0], operands[
1],
1965 emit_insn (gen_add<mode>
3_compareV (operands[
0], operands[
1], operands[
2]));
1966 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1971 (define_expand "uaddv<mode>
4"
1972 [(match_operand:GPI
0 "register_operand")
1973 (match_operand:GPI
1 "register_operand")
1974 (match_operand:GPI
2 "register_operand")
1975 (label_ref (match_operand
3 "" ""))]
1978 emit_insn (gen_add<mode>
3_compareC (operands[
0], operands[
1], operands[
2]));
1979 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[
3]);
1984 (define_expand "addti3"
1985 [(set (match_operand:TI
0 "register_operand")
1986 (plus:TI (match_operand:TI
1 "register_operand")
1987 (match_operand:TI
2 "aarch64_reg_or_imm")))]
1990 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1992 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1993 &low_dest, &op1_low, &op2_low,
1994 &high_dest, &op1_high, &op2_high);
1996 if (op2_low == const0_rtx)
1999 if (!aarch64_pluslong_operand (op2_high, DImode))
2000 op2_high = force_reg (DImode, op2_high);
2001 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
2005 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2006 force_reg (DImode, op2_low)));
2007 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
2008 force_reg (DImode, op2_high)));
2011 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2012 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2017 (define_expand "addvti4"
2018 [(match_operand:TI
0 "register_operand")
2019 (match_operand:TI
1 "register_operand")
2020 (match_operand:TI
2 "aarch64_reg_or_imm")
2021 (label_ref (match_operand
3 "" ""))]
2024 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2026 aarch64_addti_scratch_regs (operands[
1], operands[
2],
2027 &low_dest, &op1_low, &op2_low,
2028 &high_dest, &op1_high, &op2_high);
2030 if (op2_low == const0_rtx)
2033 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
2034 force_reg (DImode, op2_high)));
2038 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2039 force_reg (DImode, op2_low)));
2040 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
2041 force_reg (DImode, op2_high)));
2044 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2045 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2047 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2051 (define_expand "uaddvti4"
2052 [(match_operand:TI
0 "register_operand")
2053 (match_operand:TI
1 "register_operand")
2054 (match_operand:TI
2 "aarch64_reg_or_imm")
2055 (label_ref (match_operand
3 "" ""))]
2058 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2060 aarch64_addti_scratch_regs (operands[
1], operands[
2],
2061 &low_dest, &op1_low, &op2_low,
2062 &high_dest, &op1_high, &op2_high);
2064 if (op2_low == const0_rtx)
2067 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2068 force_reg (DImode, op2_high)));
2072 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2073 force_reg (DImode, op2_low)));
2074 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2075 force_reg (DImode, op2_high)));
2078 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2079 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2081 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[
3]);
2085 (define_insn "add<mode>
3_compare0"
2086 [(set (reg:CC_NZ CC_REGNUM)
2088 (plus:GPI (match_operand:GPI
1 "register_operand" "%rk,rk,rk")
2089 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2091 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2092 (plus:GPI (match_dup
1) (match_dup
2)))]
2095 adds
\\t%<w>
0, %<w>
1, %<w>
2
2096 adds
\\t%<w>
0, %<w>
1, %
2
2097 subs
\\t%<w>
0, %<w>
1, #%n2"
2098 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2101 ;; zero_extend version of above
2102 (define_insn "*addsi3_compare0_uxtw"
2103 [(set (reg:CC_NZ CC_REGNUM)
2105 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk")
2106 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
2108 (set (match_operand:DI
0 "register_operand" "=r,r,r")
2109 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
2112 adds
\\t%w0, %w1, %w2
2114 subs
\\t%w0, %w1, #%n2"
2115 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2118 (define_insn "*add<mode>
3_compareC_cconly"
2119 [(set (reg:CC_C CC_REGNUM)
2122 (match_operand:GPI
0 "register_operand" "r,r,r")
2123 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2130 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2133 (define_insn "add<mode>
3_compareC"
2134 [(set (reg:CC_C CC_REGNUM)
2137 (match_operand:GPI
1 "register_operand" "rk,rk,rk")
2138 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2140 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2141 (plus:GPI (match_dup
1) (match_dup
2)))]
2144 adds
\\t%<w>
0, %<w>
1, %<w>
2
2145 adds
\\t%<w>
0, %<w>
1, %
2
2146 subs
\\t%<w>
0, %<w>
1, #%n2"
2147 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2150 (define_insn "*add<mode>
3_compareV_cconly_imm"
2151 [(set (reg:CC_V CC_REGNUM)
2154 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
2155 (match_operand:<DWI>
1 "const_scalar_int_operand" ""))
2159 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))]
2160 "INTVAL (operands[
1]) == INTVAL (operands[
2])"
2164 [(set_attr "type" "alus_imm")]
2167 (define_insn "*add<mode>
3_compareV_cconly"
2168 [(set (reg:CC_V CC_REGNUM)
2171 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
2172 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2173 (sign_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
2175 "cmn
\\t%<w>
0, %<w>
1"
2176 [(set_attr "type" "alus_sreg")]
2179 (define_insn "add<mode>
3_compareV_imm"
2180 [(set (reg:CC_V CC_REGNUM)
2184 (match_operand:GPI
1 "register_operand" "rk,rk"))
2185 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J"))
2187 (plus:GPI (match_dup
1) (match_dup
2)))))
2188 (set (match_operand:GPI
0 "register_operand" "=r,r")
2189 (plus:GPI (match_dup
1) (match_dup
2)))]
2192 adds
\\t%<w>
0, %<w>
1, %<w>
2
2193 subs
\\t%<w>
0, %<w>
1, #%n2"
2194 [(set_attr "type" "alus_imm,alus_imm")]
2197 (define_insn "add<mode>
3_compareV"
2198 [(set (reg:CC_V CC_REGNUM)
2201 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "rk"))
2202 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2203 (sign_extend:<DWI> (plus:GPI (match_dup
1) (match_dup
2)))))
2204 (set (match_operand:GPI
0 "register_operand" "=r")
2205 (plus:GPI (match_dup
1) (match_dup
2)))]
2207 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
2208 [(set_attr "type" "alus_sreg")]
2211 (define_insn "*adds_shift_imm_<mode>"
2212 [(set (reg:CC_NZ CC_REGNUM)
2214 (plus:GPI (ASHIFT:GPI
2215 (match_operand:GPI
1 "register_operand" "r")
2216 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2217 (match_operand:GPI
3 "register_operand" "r"))
2219 (set (match_operand:GPI
0 "register_operand" "=r")
2220 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
2223 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2224 [(set_attr "type" "alus_shift_imm")]
2227 (define_insn "*subs_shift_imm_<mode>"
2228 [(set (reg:CC_NZ CC_REGNUM)
2230 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2232 (match_operand:GPI
2 "register_operand" "r")
2233 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
2235 (set (match_operand:GPI
0 "register_operand" "=r")
2236 (minus:GPI (match_dup
1)
2237 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
2239 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
2240 [(set_attr "type" "alus_shift_imm")]
2243 (define_insn "*adds_mul_imm_<mode>"
2244 [(set (reg:CC_NZ CC_REGNUM)
2247 (match_operand:GPI
1 "register_operand" "r")
2248 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2249 (match_operand:GPI
3 "register_operand" "r"))
2251 (set (match_operand:GPI
0 "register_operand" "=r")
2252 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
2255 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2256 [(set_attr "type" "alus_shift_imm")]
2259 (define_insn "*subs_mul_imm_<mode>"
2260 [(set (reg:CC_NZ CC_REGNUM)
2262 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2264 (match_operand:GPI
2 "register_operand" "r")
2265 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
2267 (set (match_operand:GPI
0 "register_operand" "=r")
2268 (minus:GPI (match_dup
1)
2269 (mult:GPI (match_dup
2) (match_dup
3))))]
2271 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
2272 [(set_attr "type" "alus_shift_imm")]
2275 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2276 [(set (reg:CC_NZ CC_REGNUM)
2279 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2280 (match_operand:GPI
2 "register_operand" "rk"))
2282 (set (match_operand:GPI
0 "register_operand" "=r")
2283 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
2285 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2286 [(set_attr "type" "alus_ext")]
2289 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2290 [(set (reg:CC_NZ CC_REGNUM)
2292 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2294 (match_operand:ALLX
2 "register_operand" "r")))
2296 (set (match_operand:GPI
0 "register_operand" "=r")
2297 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
2299 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2300 [(set_attr "type" "alus_ext")]
2303 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2304 [(set (reg:CC_NZ CC_REGNUM)
2306 (plus:GPI (ashift:GPI
2308 (match_operand:ALLX
1 "register_operand" "r"))
2309 (match_operand
2 "aarch64_imm3" "Ui3"))
2310 (match_operand:GPI
3 "register_operand" "rk"))
2312 (set (match_operand:GPI
0 "register_operand" "=rk")
2313 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2317 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2318 [(set_attr "type" "alus_ext")]
2321 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2322 [(set (reg:CC_NZ CC_REGNUM)
2324 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2327 (match_operand:ALLX
2 "register_operand" "r"))
2328 (match_operand
3 "aarch64_imm3" "Ui3")))
2330 (set (match_operand:GPI
0 "register_operand" "=rk")
2331 (minus:GPI (match_dup
1)
2332 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2335 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2336 [(set_attr "type" "alus_ext")]
2339 (define_insn "*adds_<optab><mode>_multp2"
2340 [(set (reg:CC_NZ CC_REGNUM)
2342 (plus:GPI (ANY_EXTRACT:GPI
2343 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2344 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2345 (match_operand
3 "const_int_operand" "n")
2347 (match_operand:GPI
4 "register_operand" "rk"))
2349 (set (match_operand:GPI
0 "register_operand" "=r")
2350 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2354 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2355 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2356 [(set_attr "type" "alus_ext")]
2359 (define_insn "*subs_<optab><mode>_multp2"
2360 [(set (reg:CC_NZ CC_REGNUM)
2362 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2364 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2365 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2366 (match_operand
3 "const_int_operand" "n")
2369 (set (match_operand:GPI
0 "register_operand" "=r")
2370 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2371 (mult:GPI (match_dup
1) (match_dup
2))
2374 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2375 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2376 [(set_attr "type" "alus_ext")]
2379 (define_insn "*add<mode>
3nr_compare0"
2380 [(set (reg:CC_NZ CC_REGNUM)
2382 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2383 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2390 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2393 (define_insn "aarch64_sub<mode>_compare0"
2394 [(set (reg:CC_NZ CC_REGNUM)
2396 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2397 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2400 "cmp
\\t%<w>
0, %<w>
1"
2401 [(set_attr "type" "alus_sreg")]
2404 (define_insn "*compare_neg<mode>"
2405 [(set (reg:CC_Z CC_REGNUM)
2407 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2408 (match_operand:GPI
1 "register_operand" "r")))]
2410 "cmn
\\t%<w>
1, %<w>
0"
2411 [(set_attr "type" "alus_sreg")]
2414 (define_insn "*add_<shift>_<mode>"
2415 [(set (match_operand:GPI
0 "register_operand" "=r")
2416 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2417 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2418 (match_operand:GPI
3 "register_operand" "r")))]
2420 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2421 [(set_attr "type" "alu_shift_imm")]
2424 ;; zero_extend version of above
2425 (define_insn "*add_<shift>_si_uxtw"
2426 [(set (match_operand:DI
0 "register_operand" "=r")
2428 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2429 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2430 (match_operand:SI
3 "register_operand" "r"))))]
2432 "add
\\t%w0, %w3, %w1, <shift> %
2"
2433 [(set_attr "type" "alu_shift_imm")]
2436 (define_insn "*add_mul_imm_<mode>"
2437 [(set (match_operand:GPI
0 "register_operand" "=r")
2438 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2439 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2440 (match_operand:GPI
3 "register_operand" "r")))]
2442 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2443 [(set_attr "type" "alu_shift_imm")]
2446 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2447 [(set (match_operand:GPI
0 "register_operand" "=rk")
2448 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2449 (match_operand:GPI
2 "register_operand" "r")))]
2451 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2452 [(set_attr "type" "alu_ext")]
2455 ;; zero_extend version of above
2456 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2457 [(set (match_operand:DI
0 "register_operand" "=rk")
2459 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2460 (match_operand:GPI
2 "register_operand" "r"))))]
2462 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2463 [(set_attr "type" "alu_ext")]
2466 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2467 [(set (match_operand:GPI
0 "register_operand" "=rk")
2468 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2469 (match_operand:ALLX
1 "register_operand" "r"))
2470 (match_operand
2 "aarch64_imm3" "Ui3"))
2471 (match_operand:GPI
3 "register_operand" "r")))]
2473 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2474 [(set_attr "type" "alu_ext")]
2477 ;; zero_extend version of above
2478 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2479 [(set (match_operand:DI
0 "register_operand" "=rk")
2481 (plus:SI (ashift:SI (ANY_EXTEND:SI
2482 (match_operand:SHORT
1 "register_operand" "r"))
2483 (match_operand
2 "aarch64_imm3" "Ui3"))
2484 (match_operand:SI
3 "register_operand" "r"))))]
2486 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2487 [(set_attr "type" "alu_ext")]
2490 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2491 [(set (match_operand:GPI
0 "register_operand" "=rk")
2492 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2493 (match_operand:ALLX
1 "register_operand" "r"))
2494 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2495 (match_operand:GPI
3 "register_operand" "r")))]
2497 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2498 [(set_attr "type" "alu_ext")]
2501 ;; zero_extend version of above
2502 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2503 [(set (match_operand:DI
0 "register_operand" "=rk")
2504 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2505 (match_operand:SHORT
1 "register_operand" "r"))
2506 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2507 (match_operand:SI
3 "register_operand" "r"))))]
2509 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2510 [(set_attr "type" "alu_ext")]
2513 (define_insn "*add_<optab><mode>_multp2"
2514 [(set (match_operand:GPI
0 "register_operand" "=rk")
2515 (plus:GPI (ANY_EXTRACT:GPI
2516 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2517 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2518 (match_operand
3 "const_int_operand" "n")
2520 (match_operand:GPI
4 "register_operand" "r")))]
2521 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2522 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2523 [(set_attr "type" "alu_ext")]
2526 ;; zero_extend version of above
2527 (define_insn "*add_<optab>si_multp2_uxtw"
2528 [(set (match_operand:DI
0 "register_operand" "=rk")
2530 (plus:SI (ANY_EXTRACT:SI
2531 (mult:SI (match_operand:SI
1 "register_operand" "r")
2532 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2533 (match_operand
3 "const_int_operand" "n")
2535 (match_operand:SI
4 "register_operand" "r"))))]
2536 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2537 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2538 [(set_attr "type" "alu_ext")]
2541 (define_expand "add<mode>
3_carryin"
2542 [(set (match_operand:GPI
0 "register_operand")
2545 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2546 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2547 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2552 ;; Note that add with carry with two zero inputs is matched by cset,
2553 ;; and that add with carry with one zero input is matched by cinc.
2555 (define_insn "*add<mode>
3_carryin"
2556 [(set (match_operand:GPI
0 "register_operand" "=r")
2559 (match_operand:GPI
3 "aarch64_carry_operation" "")
2560 (match_operand:GPI
1 "register_operand" "r"))
2561 (match_operand:GPI
2 "register_operand" "r")))]
2563 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2564 [(set_attr "type" "adc_reg")]
2567 ;; zero_extend version of above
2568 (define_insn "*addsi3_carryin_uxtw"
2569 [(set (match_operand:DI
0 "register_operand" "=r")
2573 (match_operand:SI
3 "aarch64_carry_operation" "")
2574 (match_operand:SI
1 "register_operand" "r"))
2575 (match_operand:SI
2 "register_operand" "r"))))]
2577 "adc
\\t%w0, %w1, %w2"
2578 [(set_attr "type" "adc_reg")]
2581 (define_expand "add<mode>
3_carryinC"
2589 (match_operand:GPI
1 "register_operand")))
2591 (match_operand:GPI
2 "register_operand")))
2593 (set (match_operand:GPI
0 "register_operand")
2595 (plus:GPI (match_dup
5) (match_dup
1))
2599 operands[
3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2600 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2601 operands[
4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2602 operands[
5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2603 operands[
6] = immed_wide_int_const (wi::shwi (
1, <DWI>mode)
2604 << GET_MODE_BITSIZE (<MODE>mode),
2608 (define_insn "*add<mode>
3_carryinC_zero"
2609 [(set (reg:CC_ADC CC_REGNUM)
2612 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2613 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2614 (match_operand
4 "const_scalar_int_operand" "")))
2615 (set (match_operand:GPI
0 "register_operand" "=r")
2616 (plus:GPI (match_operand:GPI
3 "aarch64_carry_operation" "")
2618 "rtx_mode_t (operands[
4], <DWI>mode)
2619 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2620 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2621 [(set_attr "type" "adc_reg")]
2624 (define_insn "*add<mode>
3_carryinC"
2625 [(set (reg:CC_ADC CC_REGNUM)
2629 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2630 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2631 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2632 (match_operand
5 "const_scalar_int_operand" "")))
2633 (set (match_operand:GPI
0 "register_operand" "=r")
2635 (plus:GPI (match_operand:GPI
4 "aarch64_carry_operation" "")
2638 "rtx_mode_t (operands[
5], <DWI>mode)
2639 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2640 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2641 [(set_attr "type" "adc_reg")]
2644 (define_expand "add<mode>
3_carryinV"
2646 [(set (reg:CC_V CC_REGNUM)
2652 (match_operand:GPI
1 "register_operand")))
2654 (match_operand:GPI
2 "register_operand")))
2657 (plus:GPI (match_dup
4) (match_dup
1))
2659 (set (match_operand:GPI
0 "register_operand")
2661 (plus:GPI (match_dup
4) (match_dup
1))
2665 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2666 operands[
3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2667 operands[
4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2670 (define_insn "*add<mode>
3_carryinV_zero"
2671 [(set (reg:CC_V CC_REGNUM)
2674 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2675 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2678 (match_operand:GPI
3 "aarch64_carry_operation" "")
2680 (set (match_operand:GPI
0 "register_operand" "=r")
2681 (plus:GPI (match_dup
3) (match_dup
1)))]
2683 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2684 [(set_attr "type" "adc_reg")]
2687 (define_insn "*add<mode>
3_carryinV"
2688 [(set (reg:CC_V CC_REGNUM)
2692 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2693 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2694 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2698 (match_operand:GPI
4 "aarch64_carry_operation" "")
2701 (set (match_operand:GPI
0 "register_operand" "=r")
2703 (plus:GPI (match_dup
4) (match_dup
1))
2706 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2707 [(set_attr "type" "adc_reg")]
2710 (define_insn "*add_uxt<mode>_shift2"
2711 [(set (match_operand:GPI
0 "register_operand" "=rk")
2713 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2714 (match_operand
2 "aarch64_imm3" "Ui3"))
2715 (match_operand
3 "const_int_operand" "n"))
2716 (match_operand:GPI
4 "register_operand" "r")))]
2717 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2719 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2720 INTVAL (operands[
3])));
2721 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2722 [(set_attr "type" "alu_ext")]
2725 ;; zero_extend version of above
2726 (define_insn "*add_uxtsi_shift2_uxtw"
2727 [(set (match_operand:DI
0 "register_operand" "=rk")
2730 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2731 (match_operand
2 "aarch64_imm3" "Ui3"))
2732 (match_operand
3 "const_int_operand" "n"))
2733 (match_operand:SI
4 "register_operand" "r"))))]
2734 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2736 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2737 INTVAL (operands[
3])));
2738 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2739 [(set_attr "type" "alu_ext")]
2742 (define_insn "*add_uxt<mode>_multp2"
2743 [(set (match_operand:GPI
0 "register_operand" "=rk")
2745 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2746 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2747 (match_operand
3 "const_int_operand" "n"))
2748 (match_operand:GPI
4 "register_operand" "r")))]
2749 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2751 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2752 INTVAL (operands[
3])));
2753 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2754 [(set_attr "type" "alu_ext")]
2757 ;; zero_extend version of above
2758 (define_insn "*add_uxtsi_multp2_uxtw"
2759 [(set (match_operand:DI
0 "register_operand" "=rk")
2762 (mult:SI (match_operand:SI
1 "register_operand" "r")
2763 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2764 (match_operand
3 "const_int_operand" "n"))
2765 (match_operand:SI
4 "register_operand" "r"))))]
2766 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2768 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2769 INTVAL (operands[
3])));
2770 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2771 [(set_attr "type" "alu_ext")]
2774 (define_insn "subsi3"
2775 [(set (match_operand:SI
0 "register_operand" "=rk")
2776 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2777 (match_operand:SI
2 "register_operand" "r")))]
2779 "sub
\\t%w0, %w1, %w2"
2780 [(set_attr "type" "alu_sreg")]
2783 ;; zero_extend version of above
2784 (define_insn "*subsi3_uxtw"
2785 [(set (match_operand:DI
0 "register_operand" "=rk")
2787 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2788 (match_operand:SI
2 "register_operand" "r"))))]
2790 "sub
\\t%w0, %w1, %w2"
2791 [(set_attr "type" "alu_sreg")]
2794 (define_insn "subdi3"
2795 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2796 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2797 (match_operand:DI
2 "register_operand" "r,w")))]
2801 sub
\\t%d0, %d1, %d2"
2802 [(set_attr "type" "alu_sreg, neon_sub")
2803 (set_attr "arch" "*,simd")]
2806 (define_expand "subv<GPI:mode>
4"
2807 [(match_operand:GPI
0 "register_operand")
2808 (match_operand:GPI
1 "register_operand")
2809 (match_operand:GPI
2 "aarch64_plus_operand")
2810 (label_ref (match_operand
3 "" ""))]
2813 if (CONST_INT_P (operands[
2]))
2814 emit_insn (gen_subv<mode>_imm (operands[
0], operands[
1], operands[
2]));
2816 emit_insn (gen_subv<mode>_insn (operands[
0], operands[
1], operands[
2]));
2817 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2822 (define_insn "subv<GPI:mode>_insn"
2823 [(set (reg:CC_V CC_REGNUM)
2827 (match_operand:GPI
1 "register_operand" "rk")
2828 (match_operand:GPI
2 "register_operand" "r")))
2829 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2830 (sign_extend:<DWI> (match_dup
2)))))
2831 (set (match_operand:GPI
0 "register_operand" "=r")
2832 (minus:GPI (match_dup
1) (match_dup
2)))]
2834 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2835 [(set_attr "type" "alus_sreg")]
2838 (define_insn "subv<GPI:mode>_imm"
2839 [(set (reg:CC_V CC_REGNUM)
2843 (match_operand:GPI
1 "register_operand" "rk,rk")
2844 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2845 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2847 (set (match_operand:GPI
0 "register_operand" "=r,r")
2848 (minus:GPI (match_dup
1) (match_dup
2)))]
2851 subs
\\t%<w>
0, %<w>
1, %
2
2852 adds
\\t%<w>
0, %<w>
1, #%n2"
2853 [(set_attr "type" "alus_sreg")]
2856 (define_expand "negv<GPI:mode>
3"
2857 [(match_operand:GPI
0 "register_operand")
2858 (match_operand:GPI
1 "register_operand")
2859 (label_ref (match_operand
2 "" ""))]
2862 emit_insn (gen_negv<mode>_insn (operands[
0], operands[
1]));
2863 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2869 (define_insn "negv<GPI:mode>_insn"
2870 [(set (reg:CC_V CC_REGNUM)
2873 (neg:GPI (match_operand:GPI
1 "register_operand" "r")))
2874 (neg:<DWI> (sign_extend:<DWI> (match_dup
1)))))
2875 (set (match_operand:GPI
0 "register_operand" "=r")
2876 (neg:GPI (match_dup
1)))]
2878 "negs
\\t%<w>
0, %<w>
1"
2879 [(set_attr "type" "alus_sreg")]
2882 (define_insn "negv<GPI:mode>_cmp_only"
2883 [(set (reg:CC_V CC_REGNUM)
2886 (neg:GPI (match_operand:GPI
0 "register_operand" "r")))
2887 (neg:<DWI> (sign_extend:<DWI> (match_dup
0)))))]
2889 "negs
\\t%<w>zr, %<w>
0"
2890 [(set_attr "type" "alus_sreg")]
2893 (define_insn "*cmpv<GPI:mode>_insn"
2894 [(set (reg:CC_V CC_REGNUM)
2897 (minus:GPI (match_operand:GPI
0 "register_operand" "r,r,r")
2898 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))
2899 (minus:<DWI> (sign_extend:<DWI> (match_dup
0))
2900 (sign_extend:<DWI> (match_dup
1)))))]
2906 [(set_attr "type" "alus_sreg")]
2909 (define_expand "usubv<mode>
4"
2910 [(match_operand:GPI
0 "register_operand")
2911 (match_operand:GPI
1 "aarch64_reg_or_zero")
2912 (match_operand:GPI
2 "aarch64_reg_or_zero")
2913 (label_ref (match_operand
3 "" ""))]
2916 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2917 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2922 (define_expand "subti3"
2923 [(set (match_operand:TI
0 "register_operand")
2924 (minus:TI (match_operand:TI
1 "aarch64_reg_or_zero")
2925 (match_operand:TI
2 "register_operand")))]
2928 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2930 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2931 &low_dest, &op1_low, &op2_low,
2932 &high_dest, &op1_high, &op2_high);
2934 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2935 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2937 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2938 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2942 (define_expand "subvti4"
2943 [(match_operand:TI
0 "register_operand")
2944 (match_operand:TI
1 "register_operand")
2945 (match_operand:TI
2 "aarch64_reg_or_imm")
2946 (label_ref (match_operand
3 "" ""))]
2949 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2951 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2952 &low_dest, &op1_low, &op2_low,
2953 &high_dest, &op1_high, &op2_high);
2954 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2955 high_dest, op1_high, op2_high, false);
2957 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2961 (define_expand "usubvti4"
2962 [(match_operand:TI
0 "register_operand")
2963 (match_operand:TI
1 "register_operand")
2964 (match_operand:TI
2 "aarch64_reg_or_imm")
2965 (label_ref (match_operand
3 "" ""))]
2968 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2970 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2971 &low_dest, &op1_low, &op2_low,
2972 &high_dest, &op1_high, &op2_high);
2973 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2974 high_dest, op1_high, op2_high, true);
2976 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2980 (define_expand "negvti3"
2981 [(match_operand:TI
0 "register_operand")
2982 (match_operand:TI
1 "register_operand")
2983 (label_ref (match_operand
2 "" ""))]
2986 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[
0]),
2987 gen_lowpart (DImode, operands[
1])));
2988 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[
0]),
2989 gen_highpart (DImode, operands[
1])));
2990 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2996 (define_insn "negdi_carryout"
2997 [(set (reg:CC CC_REGNUM)
2999 (const_int
0) (match_operand:DI
1 "register_operand" "r")))
3000 (set (match_operand:DI
0 "register_operand" "=r")
3001 (neg:DI (match_dup
1)))]
3004 [(set_attr "type" "alus_sreg")]
3007 (define_insn "negvdi_carryinV"
3008 [(set (reg:CC_V CC_REGNUM)
3011 (ltu:TI (reg:CC CC_REGNUM) (const_int
0))
3012 (sign_extend:TI (match_operand:DI
1 "register_operand" "r"))))
3014 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
3016 (set (match_operand:DI
0 "register_operand" "=r")
3017 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
3021 [(set_attr "type" "alus_sreg")]
3024 (define_insn "*sub<mode>
3_compare0"
3025 [(set (reg:CC_NZ CC_REGNUM)
3026 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3027 (match_operand:GPI
2 "register_operand" "r"))
3029 (set (match_operand:GPI
0 "register_operand" "=r")
3030 (minus:GPI (match_dup
1) (match_dup
2)))]
3032 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
3033 [(set_attr "type" "alus_sreg")]
3036 ;; zero_extend version of above
3037 (define_insn "*subsi3_compare0_uxtw"
3038 [(set (reg:CC_NZ CC_REGNUM)
3039 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "rk")
3040 (match_operand:SI
2 "register_operand" "r"))
3042 (set (match_operand:DI
0 "register_operand" "=r")
3043 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
3045 "subs
\\t%w0, %w1, %w2"
3046 [(set_attr "type" "alus_sreg")]
3049 (define_insn "sub<mode>
3_compare1_imm"
3050 [(set (reg:CC CC_REGNUM)
3052 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ,rkZ")
3053 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
3054 (set (match_operand:GPI
0 "register_operand" "=r,r")
3057 (match_operand:GPI
3 "aarch64_plus_immediate" "J,I")))]
3058 "UINTVAL (operands[
2]) == -UINTVAL (operands[
3])"
3060 subs
\\t%<w>
0, %<w>
1, %
2
3061 adds
\\t%<w>
0, %<w>
1, #%n2"
3062 [(set_attr "type" "alus_imm")]
3065 (define_insn "sub<mode>
3_compare1"
3066 [(set (reg:CC CC_REGNUM)
3068 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ")
3069 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
3070 (set (match_operand:GPI
0 "register_operand" "=r")
3071 (minus:GPI (match_dup
1) (match_dup
2)))]
3073 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
3074 [(set_attr "type" "alus_sreg")]
3078 [(set (match_operand:GPI
0 "aarch64_general_reg")
3079 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
3080 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3081 (set (reg:CC CC_REGNUM)
3085 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3086 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
3089 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3095 ;; Same as the above peephole but with the compare and minus in
3096 ;; swapped order. The restriction on overlap between operand
0
3097 ;; and operands
1 and
2 doesn't apply here.
3099 [(set (reg:CC CC_REGNUM)
3101 (match_operand:GPI
1 "aarch64_reg_or_zero")
3102 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3103 (set (match_operand:GPI
0 "aarch64_general_reg")
3104 (minus:GPI (match_dup
1)
3109 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3116 [(set (match_operand:GPI
0 "aarch64_general_reg")
3117 (plus:GPI (match_operand:GPI
1 "register_operand")
3118 (match_operand:GPI
2 "aarch64_plus_immediate")))
3119 (set (reg:CC CC_REGNUM)
3122 (match_operand:GPI
3 "const_int_operand")))]
3123 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3124 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3127 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3128 operands[
3], operands[
2]));
3133 ;; Same as the above peephole but with the compare and minus in
3134 ;; swapped order. The restriction on overlap between operand
0
3135 ;; and operands
1 doesn't apply here.
3137 [(set (reg:CC CC_REGNUM)
3139 (match_operand:GPI
1 "register_operand")
3140 (match_operand:GPI
3 "const_int_operand")))
3141 (set (match_operand:GPI
0 "aarch64_general_reg")
3142 (plus:GPI (match_dup
1)
3143 (match_operand:GPI
2 "aarch64_plus_immediate")))]
3144 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3147 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3148 operands[
3], operands[
2]));
3153 (define_insn "*sub_<shift>_<mode>"
3154 [(set (match_operand:GPI
0 "register_operand" "=r")
3155 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3157 (match_operand:GPI
1 "register_operand" "r")
3158 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3160 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
3161 [(set_attr "type" "alu_shift_imm")]
3164 ;; zero_extend version of above
3165 (define_insn "*sub_<shift>_si_uxtw"
3166 [(set (match_operand:DI
0 "register_operand" "=r")
3168 (minus:SI (match_operand:SI
3 "register_operand" "r")
3170 (match_operand:SI
1 "register_operand" "r")
3171 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3173 "sub
\\t%w0, %w3, %w1, <shift> %
2"
3174 [(set_attr "type" "alu_shift_imm")]
3177 (define_insn "*sub_mul_imm_<mode>"
3178 [(set (match_operand:GPI
0 "register_operand" "=r")
3179 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3181 (match_operand:GPI
1 "register_operand" "r")
3182 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3184 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
3185 [(set_attr "type" "alu_shift_imm")]
3188 ;; zero_extend version of above
3189 (define_insn "*sub_mul_imm_si_uxtw"
3190 [(set (match_operand:DI
0 "register_operand" "=r")
3192 (minus:SI (match_operand:SI
3 "register_operand" "r")
3194 (match_operand:SI
1 "register_operand" "r")
3195 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3197 "sub
\\t%w0, %w3, %w1, lsl %p2"
3198 [(set_attr "type" "alu_shift_imm")]
3201 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3202 [(set (match_operand:GPI
0 "register_operand" "=rk")
3203 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3205 (match_operand:ALLX
2 "register_operand" "r"))))]
3207 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
3208 [(set_attr "type" "alu_ext")]
3211 ;; zero_extend version of above
3212 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3213 [(set (match_operand:DI
0 "register_operand" "=rk")
3215 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3217 (match_operand:SHORT
2 "register_operand" "r")))))]
3219 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3220 [(set_attr "type" "alu_ext")]
3223 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3224 [(set (match_operand:GPI
0 "register_operand" "=rk")
3225 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3226 (ashift:GPI (ANY_EXTEND:GPI
3227 (match_operand:ALLX
2 "register_operand" "r"))
3228 (match_operand
3 "aarch64_imm3" "Ui3"))))]
3230 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
3231 [(set_attr "type" "alu_ext")]
3234 ;; zero_extend version of above
3235 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3236 [(set (match_operand:DI
0 "register_operand" "=rk")
3238 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3239 (ashift:SI (ANY_EXTEND:SI
3240 (match_operand:SHORT
2 "register_operand" "r"))
3241 (match_operand
3 "aarch64_imm3" "Ui3")))))]
3243 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
3244 [(set_attr "type" "alu_ext")]
3247 (define_insn "*sub_<optab><mode>_multp2"
3248 [(set (match_operand:GPI
0 "register_operand" "=rk")
3249 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3251 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3252 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3253 (match_operand
3 "const_int_operand" "n")
3255 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
3256 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
3257 [(set_attr "type" "alu_ext")]
3260 ;; zero_extend version of above
3261 (define_insn "*sub_<optab>si_multp2_uxtw"
3262 [(set (match_operand:DI
0 "register_operand" "=rk")
3264 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3266 (mult:SI (match_operand:SI
1 "register_operand" "r")
3267 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3268 (match_operand
3 "const_int_operand" "n")
3270 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
3271 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
3272 [(set_attr "type" "alu_ext")]
3275 ;; The hardware description is op1 + ~op2 + C.
3276 ;; = op1 + (-op2 +
1) + (
1 - !C)
3277 ;; = op1 - op2 -
1 +
1 - !C
3278 ;; = op1 - op2 - !C.
3279 ;; We describe the latter.
3281 (define_insn "*sub<mode>
3_carryin0"
3282 [(set (match_operand:GPI
0 "register_operand" "=r")
3284 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3285 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
3287 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
3288 [(set_attr "type" "adc_reg")]
3291 ;; zero_extend version of the above
3292 (define_insn "*subsi3_carryin_uxtw"
3293 [(set (match_operand:DI
0 "register_operand" "=r")
3296 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3297 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
3299 "sbc
\\t%w0, %w1, wzr"
3300 [(set_attr "type" "adc_reg")]
3303 (define_expand "sub<mode>
3_carryin"
3304 [(set (match_operand:GPI
0 "register_operand")
3307 (match_operand:GPI
1 "aarch64_reg_or_zero")
3308 (match_operand:GPI
2 "register_operand"))
3309 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
3314 (define_insn "*sub<mode>
3_carryin"
3315 [(set (match_operand:GPI
0 "register_operand" "=r")
3318 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3319 (match_operand:GPI
2 "register_operand" "r"))
3320 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3323 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3324 [(set_attr "type" "adc_reg")]
3327 ;; zero_extend version of the above
3328 (define_insn "*subsi3_carryin_uxtw"
3329 [(set (match_operand:DI
0 "register_operand" "=r")
3333 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3334 (match_operand:SI
2 "register_operand" "r"))
3335 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
3338 "sbc
\\t%w0, %w1, %w2"
3339 [(set_attr "type" "adc_reg")]
3342 (define_insn "*sub<mode>
3_carryin_alt"
3343 [(set (match_operand:GPI
0 "register_operand" "=r")
3346 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3347 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
3348 (match_operand:GPI
2 "register_operand" "r")))]
3350 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3351 [(set_attr "type" "adc_reg")]
3354 ;; zero_extend version of the above
3355 (define_insn "*subsi3_carryin_alt_uxtw"
3356 [(set (match_operand:DI
0 "register_operand" "=r")
3360 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3361 (match_operand:SI
3 "aarch64_borrow_operation" ""))
3362 (match_operand:SI
2 "register_operand" "r"))))]
3364 "sbc
\\t%w0, %w1, %w2"
3365 [(set_attr "type" "adc_reg")]
3368 (define_expand "usub<GPI:mode>
3_carryinC"
3370 [(set (reg:CC CC_REGNUM)
3373 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3376 (match_operand:GPI
2 "register_operand"))
3377 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0)))))
3378 (set (match_operand:GPI
0 "register_operand")
3380 (minus:GPI (match_dup
1) (match_dup
2))
3381 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3385 (define_insn "*usub<GPI:mode>
3_carryinC_z1"
3386 [(set (reg:CC CC_REGNUM)
3391 (match_operand:GPI
1 "register_operand" "r"))
3392 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))))
3393 (set (match_operand:GPI
0 "register_operand" "=r")
3395 (neg:GPI (match_dup
1))
3396 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3398 "sbcs
\\t%<w>
0, <w>zr, %<w>
1"
3399 [(set_attr "type" "adc_reg")]
3402 (define_insn "*usub<GPI:mode>
3_carryinC_z2"
3403 [(set (reg:CC CC_REGNUM)
3406 (match_operand:GPI
1 "register_operand" "r"))
3407 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3408 (set (match_operand:GPI
0 "register_operand" "=r")
3411 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3413 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3414 [(set_attr "type" "adc_reg")]
3417 (define_insn "*usub<GPI:mode>
3_carryinC"
3418 [(set (reg:CC CC_REGNUM)
3421 (match_operand:GPI
1 "register_operand" "r"))
3424 (match_operand:GPI
2 "register_operand" "r"))
3425 (match_operand:<DWI>
3 "aarch64_borrow_operation" ""))))
3426 (set (match_operand:GPI
0 "register_operand" "=r")
3428 (minus:GPI (match_dup
1) (match_dup
2))
3429 (match_operand:GPI
4 "aarch64_borrow_operation" "")))]
3431 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3432 [(set_attr "type" "adc_reg")]
3435 (define_expand "sub<GPI:mode>
3_carryinV"
3437 [(set (reg:CC_V CC_REGNUM)
3441 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3444 (match_operand:GPI
2 "register_operand"))
3445 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0))))
3447 (minus:GPI (match_dup
1)
3448 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))
3450 (set (match_operand:GPI
0 "register_operand")
3452 (minus:GPI (match_dup
1) (match_dup
2))
3453 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3457 (define_insn "*sub<mode>
3_carryinV_z2"
3458 [(set (reg:CC_V CC_REGNUM)
3461 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
3462 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))
3464 (minus:GPI (match_dup
1)
3465 (match_operand:GPI
3 "aarch64_borrow_operation" "")))))
3466 (set (match_operand:GPI
0 "register_operand" "=r")
3468 (match_dup
1) (match_dup
3)))]
3470 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3471 [(set_attr "type" "adc_reg")]
3474 (define_insn "*sub<mode>
3_carryinV"
3475 [(set (reg:CC_V CC_REGNUM)
3479 (match_operand:GPI
1 "register_operand" "r"))
3482 (match_operand:GPI
2 "register_operand" "r"))
3483 (match_operand:<DWI>
3 "aarch64_borrow_operation" "")))
3487 (plus:GPI (match_operand:GPI
4 "aarch64_borrow_operation" "")
3489 (set (match_operand:GPI
0 "register_operand" "=r")
3491 (minus:GPI (match_dup
1) (match_dup
2))
3494 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3495 [(set_attr "type" "adc_reg")]
3498 (define_insn "*sub_uxt<mode>_shift2"
3499 [(set (match_operand:GPI
0 "register_operand" "=rk")
3500 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3502 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
3503 (match_operand
2 "aarch64_imm3" "Ui3"))
3504 (match_operand
3 "const_int_operand" "n"))))]
3505 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3507 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3508 INTVAL (operands[
3])));
3509 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
3510 [(set_attr "type" "alu_ext")]
3513 ;; zero_extend version of above
3514 (define_insn "*sub_uxtsi_shift2_uxtw"
3515 [(set (match_operand:DI
0 "register_operand" "=rk")
3517 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3519 (ashift:SI (match_operand:SI
1 "register_operand" "r")
3520 (match_operand
2 "aarch64_imm3" "Ui3"))
3521 (match_operand
3 "const_int_operand" "n")))))]
3522 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3524 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3525 INTVAL (operands[
3])));
3526 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
3527 [(set_attr "type" "alu_ext")]
3530 (define_insn "*sub_uxt<mode>_multp2"
3531 [(set (match_operand:GPI
0 "register_operand" "=rk")
3532 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3534 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3535 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3536 (match_operand
3 "const_int_operand" "n"))))]
3537 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3539 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3540 INTVAL (operands[
3])));
3541 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
3542 [(set_attr "type" "alu_ext")]
3545 ;; zero_extend version of above
3546 (define_insn "*sub_uxtsi_multp2_uxtw"
3547 [(set (match_operand:DI
0 "register_operand" "=rk")
3549 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3551 (mult:SI (match_operand:SI
1 "register_operand" "r")
3552 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3553 (match_operand
3 "const_int_operand" "n")))))]
3554 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3556 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3557 INTVAL (operands[
3])));
3558 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
3559 [(set_attr "type" "alu_ext")]
3562 (define_expand "abs<mode>
2"
3563 [(match_operand:GPI
0 "register_operand")
3564 (match_operand:GPI
1 "register_operand")]
3567 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
3568 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3569 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
3574 (define_insn "neg<mode>
2"
3575 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3576 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3580 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
3581 [(set_attr "type" "alu_sreg, neon_neg<q>")
3582 (set_attr "arch" "*,simd")]
3585 ;; zero_extend version of above
3586 (define_insn "*negsi2_uxtw"
3587 [(set (match_operand:DI
0 "register_operand" "=r")
3588 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
3591 [(set_attr "type" "alu_sreg")]
3594 (define_insn "*ngc<mode>"
3595 [(set (match_operand:GPI
0 "register_operand" "=r")
3597 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
3598 (match_operand:GPI
1 "register_operand" "r")))]
3600 "ngc
\\t%<w>
0, %<w>
1"
3601 [(set_attr "type" "adc_reg")]
3604 (define_insn "*ngcsi_uxtw"
3605 [(set (match_operand:DI
0 "register_operand" "=r")
3608 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
3609 (match_operand:SI
1 "register_operand" "r"))))]
3612 [(set_attr "type" "adc_reg")]
3615 (define_insn "neg<mode>
2_compare0"
3616 [(set (reg:CC_NZ CC_REGNUM)
3617 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3619 (set (match_operand:GPI
0 "register_operand" "=r")
3620 (neg:GPI (match_dup
1)))]
3622 "negs
\\t%<w>
0, %<w>
1"
3623 [(set_attr "type" "alus_sreg")]
3626 ;; zero_extend version of above
3627 (define_insn "*negsi2_compare0_uxtw"
3628 [(set (reg:CC_NZ CC_REGNUM)
3629 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
3631 (set (match_operand:DI
0 "register_operand" "=r")
3632 (zero_extend:DI (neg:SI (match_dup
1))))]
3635 [(set_attr "type" "alus_sreg")]
3638 (define_insn "*neg_<shift><mode>
3_compare0"
3639 [(set (reg:CC_NZ CC_REGNUM)
3641 (neg:GPI (ASHIFT:GPI
3642 (match_operand:GPI
1 "register_operand" "r")
3643 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3645 (set (match_operand:GPI
0 "register_operand" "=r")
3646 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
3648 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
3649 [(set_attr "type" "alus_shift_imm")]
3652 (define_insn "*neg_<shift>_<mode>
2"
3653 [(set (match_operand:GPI
0 "register_operand" "=r")
3654 (neg:GPI (ASHIFT:GPI
3655 (match_operand:GPI
1 "register_operand" "r")
3656 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3658 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
3659 [(set_attr "type" "alu_shift_imm")]
3662 ;; zero_extend version of above
3663 (define_insn "*neg_<shift>_si2_uxtw"
3664 [(set (match_operand:DI
0 "register_operand" "=r")
3667 (match_operand:SI
1 "register_operand" "r")
3668 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3670 "neg
\\t%w0, %w1, <shift> %
2"
3671 [(set_attr "type" "alu_shift_imm")]
3674 (define_insn "*neg_mul_imm_<mode>
2"
3675 [(set (match_operand:GPI
0 "register_operand" "=r")
3677 (match_operand:GPI
1 "register_operand" "r")
3678 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3680 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
3681 [(set_attr "type" "alu_shift_imm")]
3684 ;; zero_extend version of above
3685 (define_insn "*neg_mul_imm_si2_uxtw"
3686 [(set (match_operand:DI
0 "register_operand" "=r")
3689 (match_operand:SI
1 "register_operand" "r")
3690 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3692 "neg
\\t%w0, %w1, lsl %p2"
3693 [(set_attr "type" "alu_shift_imm")]
3696 (define_insn "mul<mode>
3"
3697 [(set (match_operand:GPI
0 "register_operand" "=r")
3698 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3699 (match_operand:GPI
2 "register_operand" "r")))]
3701 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
3702 [(set_attr "type" "mul")]
3705 ;; zero_extend version of above
3706 (define_insn "*mulsi3_uxtw"
3707 [(set (match_operand:DI
0 "register_operand" "=r")
3709 (mult:SI (match_operand:SI
1 "register_operand" "r")
3710 (match_operand:SI
2 "register_operand" "r"))))]
3712 "mul
\\t%w0, %w1, %w2"
3713 [(set_attr "type" "mul")]
3716 (define_insn "madd<mode>"
3717 [(set (match_operand:GPI
0 "register_operand" "=r")
3718 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3719 (match_operand:GPI
2 "register_operand" "r"))
3720 (match_operand:GPI
3 "register_operand" "r")))]
3722 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3723 [(set_attr "type" "mla")]
3726 ;; zero_extend version of above
3727 (define_insn "*maddsi_uxtw"
3728 [(set (match_operand:DI
0 "register_operand" "=r")
3730 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
3731 (match_operand:SI
2 "register_operand" "r"))
3732 (match_operand:SI
3 "register_operand" "r"))))]
3734 "madd
\\t%w0, %w1, %w2, %w3"
3735 [(set_attr "type" "mla")]
3738 (define_insn "*msub<mode>"
3739 [(set (match_operand:GPI
0 "register_operand" "=r")
3740 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3741 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3742 (match_operand:GPI
2 "register_operand" "r"))))]
3745 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3746 [(set_attr "type" "mla")]
3749 ;; zero_extend version of above
3750 (define_insn "*msubsi_uxtw"
3751 [(set (match_operand:DI
0 "register_operand" "=r")
3753 (minus:SI (match_operand:SI
3 "register_operand" "r")
3754 (mult:SI (match_operand:SI
1 "register_operand" "r")
3755 (match_operand:SI
2 "register_operand" "r")))))]
3758 "msub
\\t%w0, %w1, %w2, %w3"
3759 [(set_attr "type" "mla")]
3762 (define_insn "*mul<mode>_neg"
3763 [(set (match_operand:GPI
0 "register_operand" "=r")
3764 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3765 (match_operand:GPI
2 "register_operand" "r")))]
3768 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3769 [(set_attr "type" "mul")]
3772 ;; zero_extend version of above
3773 (define_insn "*mulsi_neg_uxtw"
3774 [(set (match_operand:DI
0 "register_operand" "=r")
3776 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3777 (match_operand:SI
2 "register_operand" "r"))))]
3780 "mneg
\\t%w0, %w1, %w2"
3781 [(set_attr "type" "mul")]
3784 (define_insn "<su_optab>mulsidi3"
3785 [(set (match_operand:DI
0 "register_operand" "=r")
3786 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3787 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3789 "<su>mull
\\t%
0, %w1, %w2"
3790 [(set_attr "type" "<su>mull")]
3793 (define_insn "<su_optab>maddsidi4"
3794 [(set (match_operand:DI
0 "register_operand" "=r")
3796 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3797 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3798 (match_operand:DI
3 "register_operand" "r")))]
3800 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3801 [(set_attr "type" "<su>mlal")]
3804 (define_insn "<su_optab>msubsidi4"
3805 [(set (match_operand:DI
0 "register_operand" "=r")
3807 (match_operand:DI
3 "register_operand" "r")
3808 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3810 (match_operand:SI
2 "register_operand" "r")))))]
3812 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3813 [(set_attr "type" "<su>mlal")]
3816 (define_insn "*<su_optab>mulsidi_neg"
3817 [(set (match_operand:DI
0 "register_operand" "=r")
3819 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3820 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3822 "<su>mnegl
\\t%
0, %w1, %w2"
3823 [(set_attr "type" "<su>mull")]
3826 (define_expand "<su_optab>mulditi3"
3827 [(set (match_operand:TI
0 "register_operand")
3828 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3829 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3832 rtx low = gen_reg_rtx (DImode);
3833 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3835 rtx high = gen_reg_rtx (DImode);
3836 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3838 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3839 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3843 ;; The default expansion of multi3 using umuldi3_highpart will perform
3844 ;; the additions in an order that fails to combine into two madd insns.
3845 (define_expand "multi3"
3846 [(set (match_operand:TI
0 "register_operand")
3847 (mult:TI (match_operand:TI
1 "register_operand")
3848 (match_operand:TI
2 "register_operand")))]
3851 rtx l0 = gen_reg_rtx (DImode);
3852 rtx l1 = gen_lowpart (DImode, operands[
1]);
3853 rtx l2 = gen_lowpart (DImode, operands[
2]);
3854 rtx h0 = gen_reg_rtx (DImode);
3855 rtx h1 = gen_highpart (DImode, operands[
1]);
3856 rtx h2 = gen_highpart (DImode, operands[
2]);
3858 emit_insn (gen_muldi3 (l0, l1, l2));
3859 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3860 emit_insn (gen_madddi (h0, h1, l2, h0));
3861 emit_insn (gen_madddi (h0, l1, h2, h0));
3863 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3864 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3868 (define_insn "<su>muldi3_highpart"
3869 [(set (match_operand:DI
0 "register_operand" "=r")
3873 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3874 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3877 "<su>mulh
\\t%
0, %
1, %
2"
3878 [(set_attr "type" "<su>mull")]
3881 (define_insn "<su_optab>div<mode>
3"
3882 [(set (match_operand:GPI
0 "register_operand" "=r")
3883 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3884 (match_operand:GPI
2 "register_operand" "r")))]
3886 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3887 [(set_attr "type" "<su>div")]
3890 ;; zero_extend version of above
3891 (define_insn "*<su_optab>divsi3_uxtw"
3892 [(set (match_operand:DI
0 "register_operand" "=r")
3894 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3895 (match_operand:SI
2 "register_operand" "r"))))]
3897 "<su>div
\\t%w0, %w1, %w2"
3898 [(set_attr "type" "<su>div")]
3901 ;; -------------------------------------------------------------------
3903 ;; -------------------------------------------------------------------
3905 (define_insn "cmp<mode>"
3906 [(set (reg:CC CC_REGNUM)
3907 (compare:CC (match_operand:GPI
0 "register_operand" "rk,rk,rk")
3908 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3914 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3917 (define_insn "fcmp<mode>"
3918 [(set (reg:CCFP CC_REGNUM)
3919 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3920 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3924 fcmp
\\t%<s>
0, %<s>
1"
3925 [(set_attr "type" "fcmp<s>")]
3928 (define_insn "fcmpe<mode>"
3929 [(set (reg:CCFPE CC_REGNUM)
3930 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3931 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3935 fcmpe
\\t%<s>
0, %<s>
1"
3936 [(set_attr "type" "fcmp<s>")]
3939 (define_insn "*cmp_swp_<shift>_reg<mode>"
3940 [(set (reg:CC_SWP CC_REGNUM)
3941 (compare:CC_SWP (ASHIFT:GPI
3942 (match_operand:GPI
0 "register_operand" "r")
3943 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3944 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3946 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3947 [(set_attr "type" "alus_shift_imm")]
3950 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3951 [(set (reg:CC_SWP CC_REGNUM)
3952 (compare:CC_SWP (ANY_EXTEND:GPI
3953 (match_operand:ALLX
0 "register_operand" "r"))
3954 (match_operand:GPI
1 "register_operand" "r")))]
3956 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3957 [(set_attr "type" "alus_ext")]
3960 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3961 [(set (reg:CC_SWP CC_REGNUM)
3962 (compare:CC_SWP (ashift:GPI
3964 (match_operand:ALLX
0 "register_operand" "r"))
3965 (match_operand
1 "aarch64_imm3" "Ui3"))
3966 (match_operand:GPI
2 "register_operand" "r")))]
3968 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3969 [(set_attr "type" "alus_ext")]
3972 ;; -------------------------------------------------------------------
3973 ;; Store-flag and conditional select insns
3974 ;; -------------------------------------------------------------------
3976 (define_expand "cstore<mode>
4"
3977 [(set (match_operand:SI
0 "register_operand")
3978 (match_operator:SI
1 "aarch64_comparison_operator"
3979 [(match_operand:GPI
2 "register_operand")
3980 (match_operand:GPI
3 "aarch64_plus_operand")]))]
3983 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3985 operands[
3] = const0_rtx;
3989 (define_expand "cstorecc4"
3990 [(set (match_operand:SI
0 "register_operand")
3991 (match_operator
1 "aarch64_comparison_operator_mode"
3992 [(match_operand
2 "cc_register")
3993 (match_operand
3 "const0_operand")]))]
3996 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
4001 (define_expand "cstore<mode>
4"
4002 [(set (match_operand:SI
0 "register_operand")
4003 (match_operator:SI
1 "aarch64_comparison_operator_mode"
4004 [(match_operand:GPF
2 "register_operand")
4005 (match_operand:GPF
3 "aarch64_fp_compare_operand")]))]
4008 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4010 operands[
3] = const0_rtx;
4014 (define_insn "aarch64_cstore<mode>"
4015 [(set (match_operand:ALLI
0 "register_operand" "=r")
4016 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
4017 [(match_operand
2 "cc_register" "") (const_int
0)]))]
4020 [(set_attr "type" "csel")]
4023 ;; For a
24-bit immediate CST we can optimize the compare for equality
4024 ;; and branch sequence from:
4026 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
4029 ;; into the shorter:
4030 ;; sub x0, x1, #(CST &
0xfff000)
4031 ;; subs x0, x0, #(CST &
0x000fff)
4032 ;; cset x2, <ne, eq>.
4033 (define_insn_and_split "*compare_cstore<mode>_insn"
4034 [(set (match_operand:GPI
0 "register_operand" "=r")
4035 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
4036 (match_operand:GPI
2 "aarch64_imm24" "n")))
4037 (clobber (reg:CC CC_REGNUM))]
4038 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
4039 && !aarch64_plus_operand (operands[
2], <MODE>mode)
4040 && !reload_completed"
4045 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
4046 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
4047 rtx tmp = gen_reg_rtx (<MODE>mode);
4048 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
4049 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
4050 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
4051 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
4052 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
4055 [(set_attr "type" "csel")]
4058 ;; zero_extend version of the above
4059 (define_insn "*cstoresi_insn_uxtw"
4060 [(set (match_operand:DI
0 "register_operand" "=r")
4062 (match_operator:SI
1 "aarch64_comparison_operator_mode"
4063 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4066 [(set_attr "type" "csel")]
4069 (define_insn "cstore<mode>_neg"
4070 [(set (match_operand:ALLI
0 "register_operand" "=r")
4071 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
4072 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4074 "csetm
\\t%<w>
0, %m1"
4075 [(set_attr "type" "csel")]
4078 ;; zero_extend version of the above
4079 (define_insn "*cstoresi_neg_uxtw"
4080 [(set (match_operand:DI
0 "register_operand" "=r")
4082 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
4083 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
4086 [(set_attr "type" "csel")]
4089 (define_expand "cmov<mode>
6"
4090 [(set (match_operand:GPI
0 "register_operand")
4092 (match_operator
1 "aarch64_comparison_operator"
4093 [(match_operand:GPI
2 "register_operand")
4094 (match_operand:GPI
3 "aarch64_plus_operand")])
4095 (match_operand:GPI
4 "register_operand")
4096 (match_operand:GPI
5 "register_operand")))]
4099 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4101 operands[
3] = const0_rtx;
4105 (define_expand "cmov<mode>
6"
4106 [(set (match_operand:GPF
0 "register_operand")
4108 (match_operator
1 "aarch64_comparison_operator"
4109 [(match_operand:GPF
2 "register_operand")
4110 (match_operand:GPF
3 "aarch64_fp_compare_operand")])
4111 (match_operand:GPF
4 "register_operand")
4112 (match_operand:GPF
5 "register_operand")))]
4115 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4117 operands[
3] = const0_rtx;
4121 (define_insn "*cmov<mode>_insn"
4122 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
4124 (match_operator
1 "aarch64_comparison_operator"
4125 [(match_operand
2 "cc_register" "") (const_int
0)])
4126 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4127 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
4128 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4129 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4130 ;; Final two alternatives should be unreachable, but included for completeness
4132 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
4133 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
4134 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
4135 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
4136 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
4139 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4142 ;; zero_extend version of above
4143 (define_insn "*cmovsi_insn_uxtw"
4144 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
4147 (match_operator
1 "aarch64_comparison_operator"
4148 [(match_operand
2 "cc_register" "") (const_int
0)])
4149 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4150 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4151 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4152 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4153 ;; Final two alternatives should be unreachable, but included for completeness
4155 csel
\\t%w0, %w3, %w4, %m1
4156 csinv
\\t%w0, %w3, wzr, %m1
4157 csinv
\\t%w0, %w4, wzr, %M1
4158 csinc
\\t%w0, %w3, wzr, %m1
4159 csinc
\\t%w0, %w4, wzr, %M1
4162 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4165 (define_insn "*cmovdi_insn_uxtw"
4166 [(set (match_operand:DI
0 "register_operand" "=r")
4168 (match_operator
1 "aarch64_comparison_operator"
4169 [(match_operand
2 "cc_register" "") (const_int
0)])
4170 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
4171 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
4173 "csel
\\t%w0, %w3, %w4, %m1"
4174 [(set_attr "type" "csel")]
4177 (define_insn "*cmov<mode>_insn"
4178 [(set (match_operand:GPF
0 "register_operand" "=w")
4180 (match_operator
1 "aarch64_comparison_operator"
4181 [(match_operand
2 "cc_register" "") (const_int
0)])
4182 (match_operand:GPF
3 "register_operand" "w")
4183 (match_operand:GPF
4 "register_operand" "w")))]
4185 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
4186 [(set_attr "type" "fcsel")]
4189 (define_expand "mov<mode>cc"
4190 [(set (match_operand:ALLI
0 "register_operand")
4191 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator")
4192 (match_operand:ALLI
2 "register_operand")
4193 (match_operand:ALLI
3 "register_operand")))]
4197 enum rtx_code code = GET_CODE (operands[
1]);
4199 if (code == UNEQ || code == LTGT)
4202 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4203 XEXP (operands[
1],
1));
4204 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4208 (define_expand "mov<GPF:mode><GPI:mode>cc"
4209 [(set (match_operand:GPI
0 "register_operand")
4210 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4211 (match_operand:GPF
2 "register_operand")
4212 (match_operand:GPF
3 "register_operand")))]
4216 enum rtx_code code = GET_CODE (operands[
1]);
4218 if (code == UNEQ || code == LTGT)
4221 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4222 XEXP (operands[
1],
1));
4223 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4227 (define_expand "mov<mode>cc"
4228 [(set (match_operand:GPF
0 "register_operand")
4229 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator")
4230 (match_operand:GPF
2 "register_operand")
4231 (match_operand:GPF
3 "register_operand")))]
4235 enum rtx_code code = GET_CODE (operands[
1]);
4237 if (code == UNEQ || code == LTGT)
4240 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4241 XEXP (operands[
1],
1));
4242 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4246 (define_expand "<neg_not_op><mode>cc"
4247 [(set (match_operand:GPI
0 "register_operand")
4248 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4249 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand"))
4250 (match_operand:GPI
3 "register_operand")))]
4254 enum rtx_code code = GET_CODE (operands[
1]);
4256 if (code == UNEQ || code == LTGT)
4259 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4260 XEXP (operands[
1],
1));
4261 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4265 ;; CRC32 instructions.
4266 (define_insn "aarch64_<crc_variant>"
4267 [(set (match_operand:SI
0 "register_operand" "=r")
4268 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
4269 (match_operand:<crc_mode>
2 "register_operand" "r")]
4273 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
4274 return "<crc_variant>
\\t%w0, %w1, %x2";
4276 return "<crc_variant>
\\t%w0, %w1, %w2";
4278 [(set_attr "type" "crc")]
4281 (define_insn "*csinc2<mode>_insn"
4282 [(set (match_operand:GPI
0 "register_operand" "=r")
4283 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
4284 (match_operand:GPI
1 "register_operand" "r")))]
4286 "cinc
\\t%<w>
0, %<w>
1, %m2"
4287 [(set_attr "type" "csel")]
4290 (define_insn "csinc3<mode>_insn"
4291 [(set (match_operand:GPI
0 "register_operand" "=r")
4293 (match_operand
1 "aarch64_comparison_operation" "")
4294 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
4296 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4298 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4299 [(set_attr "type" "csel")]
4302 (define_insn "*csinv3<mode>_insn"
4303 [(set (match_operand:GPI
0 "register_operand" "=r")
4305 (match_operand
1 "aarch64_comparison_operation" "")
4306 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
4307 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4309 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4310 [(set_attr "type" "csel")]
4313 (define_insn "csneg3_uxtw_insn"
4314 [(set (match_operand:DI
0 "register_operand" "=r")
4317 (match_operand
1 "aarch64_comparison_operation" "")
4318 (neg:SI (match_operand:SI
2 "register_operand" "r"))
4319 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
4321 "csneg
\\t%w0, %w3, %w2, %M1"
4322 [(set_attr "type" "csel")]
4325 (define_insn "csneg3<mode>_insn"
4326 [(set (match_operand:GPI
0 "register_operand" "=r")
4328 (match_operand
1 "aarch64_comparison_operation" "")
4329 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
4330 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4332 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4333 [(set_attr "type" "csel")]
4336 ;; If X can be loaded by a single CNT[BHWD] instruction,
4340 ;; is equivalent to:
4342 ;; TMP = UQDEC[BHWD] (B, X)
4345 ;; Defining the pattern this way means that:
4347 ;; A = UMAX (B, X) - X
4351 ;; TMP1 = UQDEC[BHWD] (B, X)
4355 ;; which combine can optimize to:
4357 ;; A = UQDEC[BHWD] (B, X)
4359 ;; We don't use match_operand predicates because the order of the operands
4360 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4361 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4362 (define_expand "umax<mode>
3"
4363 [(set (match_operand:GPI
0 "register_operand")
4364 (umax:GPI (match_operand:GPI
1 "")
4365 (match_operand:GPI
2 "")))]
4368 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
4369 std::swap (operands[
1], operands[
2]);
4370 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
4372 rtx temp = gen_reg_rtx (<MODE>mode);
4373 operands[
1] = force_reg (<MODE>mode, operands[
1]);
4374 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
4375 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
4380 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4381 (define_insn "aarch64_uqdec<mode>"
4382 [(set (match_operand:GPI
0 "register_operand" "=r")
4384 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
4385 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
4389 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
4393 ;; -------------------------------------------------------------------
4394 ;; Logical operations
4395 ;; -------------------------------------------------------------------
4398 (define_insn_and_split "*aarch64_and<mode>_imm2"
4399 [(set (match_operand:GPI
0 "register_operand" "=rk")
4400 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
4401 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
4407 HOST_WIDE_INT val = INTVAL (operands[
2]);
4408 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4409 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4411 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
4412 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
4417 (define_insn "<optab><mode>
3"
4418 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
4419 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
4420 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
4423 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
4424 <logical>
\\t%<w>
0, %<w>
1, %
2
4425 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
4426 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4427 (set_attr "arch" "*,*,simd")]
4430 ;; zero_extend version of above
4431 (define_insn "*<optab>si3_uxtw"
4432 [(set (match_operand:DI
0 "register_operand" "=r,rk")
4434 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
4435 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
4438 <logical>
\\t%w0, %w1, %w2
4439 <logical>
\\t%w0, %w1, %
2"
4440 [(set_attr "type" "logic_reg,logic_imm")]
4443 (define_insn "*and<mode>
3_compare0"
4444 [(set (reg:CC_NZ CC_REGNUM)
4446 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
4447 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
4449 (set (match_operand:GPI
0 "register_operand" "=r,r")
4450 (and:GPI (match_dup
1) (match_dup
2)))]
4453 ands
\\t%<w>
0, %<w>
1, %<w>
2
4454 ands
\\t%<w>
0, %<w>
1, %
2"
4455 [(set_attr "type" "logics_reg,logics_imm")]
4458 ;; zero_extend version of above
4459 (define_insn "*andsi3_compare0_uxtw"
4460 [(set (reg:CC_NZ CC_REGNUM)
4462 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
4463 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
4465 (set (match_operand:DI
0 "register_operand" "=r,r")
4466 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
4469 ands
\\t%w0, %w1, %w2
4470 ands
\\t%w0, %w1, %
2"
4471 [(set_attr "type" "logics_reg,logics_imm")]
4474 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
4475 [(set (reg:CC_NZ CC_REGNUM)
4478 (match_operand:GPI
1 "register_operand" "r")
4479 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4480 (match_operand:GPI
3 "register_operand" "r"))
4482 (set (match_operand:GPI
0 "register_operand" "=r")
4483 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
4485 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4486 [(set_attr "type" "logics_shift_imm")]
4489 ;; zero_extend version of above
4490 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4491 [(set (reg:CC_NZ CC_REGNUM)
4494 (match_operand:SI
1 "register_operand" "r")
4495 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4496 (match_operand:SI
3 "register_operand" "r"))
4498 (set (match_operand:DI
0 "register_operand" "=r")
4499 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
4502 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4503 [(set_attr "type" "logics_shift_imm")]
4506 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
4507 [(set (match_operand:GPI
0 "register_operand" "=r")
4508 (LOGICAL:GPI (SHIFT:GPI
4509 (match_operand:GPI
1 "register_operand" "r")
4510 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4511 (match_operand:GPI
3 "register_operand" "r")))]
4513 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4514 [(set_attr "type" "logic_shift_imm")]
4517 (define_insn "*<optab>_rol<mode>
3"
4518 [(set (match_operand:GPI
0 "register_operand" "=r")
4519 (LOGICAL:GPI (rotate:GPI
4520 (match_operand:GPI
1 "register_operand" "r")
4521 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4522 (match_operand:GPI
3 "register_operand" "r")))]
4524 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
4525 [(set_attr "type" "logic_shift_imm")]
4528 ;; zero_extend versions of above
4529 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4530 [(set (match_operand:DI
0 "register_operand" "=r")
4532 (LOGICAL:SI (SHIFT:SI
4533 (match_operand:SI
1 "register_operand" "r")
4534 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4535 (match_operand:SI
3 "register_operand" "r"))))]
4537 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4538 [(set_attr "type" "logic_shift_imm")]
4541 (define_insn "*<optab>_rolsi3_uxtw"
4542 [(set (match_operand:DI
0 "register_operand" "=r")
4544 (LOGICAL:SI (rotate:SI
4545 (match_operand:SI
1 "register_operand" "r")
4546 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4547 (match_operand:SI
3 "register_operand" "r"))))]
4549 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
4550 [(set_attr "type" "logic_shift_imm")]
4553 (define_insn "one_cmpl<mode>
2"
4554 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4555 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
4560 [(set_attr "type" "logic_reg,neon_logic")
4561 (set_attr "arch" "*,simd")]
4564 (define_insn "*one_cmpl_<optab><mode>
2"
4565 [(set (match_operand:GPI
0 "register_operand" "=r")
4566 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
4567 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
4569 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
4570 [(set_attr "type" "logic_shift_imm")]
4573 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4575 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
4576 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4577 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
4578 (match_operand:GPI
2 "register_operand" "r,w")))]
4581 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
4582 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
4583 [(set_attr "type" "logic_reg,neon_logic")
4584 (set_attr "arch" "*,simd")]
4587 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4588 [(set (match_operand:DI
0 "register_operand" "=r")
4590 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
4591 (match_operand:SI
2 "register_operand" "r"))))]
4593 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
4594 [(set_attr "type" "logic_reg")]
4597 (define_insn "*xor_one_cmplsidi3_ze"
4598 [(set (match_operand:DI
0 "register_operand" "=r")
4600 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
4601 (match_operand:SI
2 "register_operand" "r")))))]
4603 "eon
\\t%w0, %w1, %w2"
4604 [(set_attr "type" "logic_reg")]
4607 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4608 ;; eon does not operate on SIMD registers so the vector variant must be split.
4609 (define_insn_and_split "*xor_one_cmpl<mode>
3"
4610 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4611 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
4612 (match_operand:GPI
2 "register_operand" "r,w"))))]
4615 eon
\\t%<w>
0, %<w>
1, %<w>
2
4617 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
4618 [(set (match_operand:GPI
0 "register_operand" "=w")
4619 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
4620 (match_operand:GPI
2 "register_operand" "w")))
4621 (set (match_dup
0) (not:GPI (match_dup
0)))]
4623 [(set_attr "type" "logic_reg,multiple")
4624 (set_attr "arch" "*,simd")]
4627 (define_insn "*and_one_cmpl<mode>
3_compare0"
4628 [(set (reg:CC_NZ CC_REGNUM)
4631 (match_operand:GPI
1 "register_operand" "r"))
4632 (match_operand:GPI
2 "register_operand" "r"))
4634 (set (match_operand:GPI
0 "register_operand" "=r")
4635 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
4637 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
4638 [(set_attr "type" "logics_reg")]
4641 ;; zero_extend version of above
4642 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4643 [(set (reg:CC_NZ CC_REGNUM)
4646 (match_operand:SI
1 "register_operand" "r"))
4647 (match_operand:SI
2 "register_operand" "r"))
4649 (set (match_operand:DI
0 "register_operand" "=r")
4650 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
4652 "bics
\\t%w0, %w2, %w1"
4653 [(set_attr "type" "logics_reg")]
4656 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
4657 [(set (reg:CC_NZ CC_REGNUM)
4660 (match_operand:GPI
0 "register_operand" "r"))
4661 (match_operand:GPI
1 "register_operand" "r"))
4664 "bics
\\t<w>zr, %<w>
1, %<w>
0"
4665 [(set_attr "type" "logics_reg")]
4668 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
4669 [(set (match_operand:GPI
0 "register_operand" "=r")
4670 (LOGICAL:GPI (not:GPI
4672 (match_operand:GPI
1 "register_operand" "r")
4673 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4674 (match_operand:GPI
3 "register_operand" "r")))]
4676 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4677 [(set_attr "type" "logic_shift_imm")]
4680 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
4681 [(set (match_operand:GPI
0 "register_operand" "=r")
4684 (match_operand:GPI
1 "register_operand" "r")
4685 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4686 (match_operand:GPI
3 "register_operand" "r"))))]
4688 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4689 [(set_attr "type" "logic_shift_imm")]
4692 ;; Zero-extend version of the above.
4693 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4694 [(set (match_operand:DI
0 "register_operand" "=r")
4698 (match_operand:SI
1 "register_operand" "r")
4699 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4700 (match_operand:SI
3 "register_operand" "r")))))]
4702 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4703 [(set_attr "type" "logic_shift_imm")]
4706 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
4707 [(set (reg:CC_NZ CC_REGNUM)
4711 (match_operand:GPI
1 "register_operand" "r")
4712 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4713 (match_operand:GPI
3 "register_operand" "r"))
4715 (set (match_operand:GPI
0 "register_operand" "=r")
4718 (match_dup
1) (match_dup
2))) (match_dup
3)))]
4720 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4721 [(set_attr "type" "logics_shift_imm")]
4724 ;; zero_extend version of above
4725 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4726 [(set (reg:CC_NZ CC_REGNUM)
4730 (match_operand:SI
1 "register_operand" "r")
4731 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
4732 (match_operand:SI
3 "register_operand" "r"))
4734 (set (match_operand:DI
0 "register_operand" "=r")
4735 (zero_extend:DI (and:SI
4737 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
4739 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4740 [(set_attr "type" "logics_shift_imm")]
4743 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
4744 [(set (reg:CC_NZ CC_REGNUM)
4748 (match_operand:GPI
0 "register_operand" "r")
4749 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
4750 (match_operand:GPI
2 "register_operand" "r"))
4753 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
4754 [(set_attr "type" "logics_shift_imm")]
4757 (define_insn "clz<mode>
2"
4758 [(set (match_operand:GPI
0 "register_operand" "=r")
4759 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4761 "clz
\\t%<w>
0, %<w>
1"
4762 [(set_attr "type" "clz")]
4765 (define_expand "ffs<mode>
2"
4766 [(match_operand:GPI
0 "register_operand")
4767 (match_operand:GPI
1 "register_operand")]
4770 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4771 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4773 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4774 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4775 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4780 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4787 (define_expand "popcount<mode>
2"
4788 [(match_operand:GPI
0 "register_operand")
4789 (match_operand:GPI
1 "register_operand")]
4792 rtx v = gen_reg_rtx (V8QImode);
4793 rtx v1 = gen_reg_rtx (V8QImode);
4794 rtx r = gen_reg_rtx (QImode);
4795 rtx in = operands[
1];
4796 rtx out = operands[
0];
4797 if(<MODE>mode == SImode)
4800 tmp = gen_reg_rtx (DImode);
4801 /* If we have SImode, zero extend to DImode, pop count does
4802 not change if we have extra zeros. */
4803 emit_insn (gen_zero_extendsidi2 (tmp, in));
4806 emit_move_insn (v, gen_lowpart (V8QImode, in));
4807 emit_insn (gen_popcountv8qi2 (v1, v));
4808 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4809 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4813 (define_insn "clrsb<mode>
2"
4814 [(set (match_operand:GPI
0 "register_operand" "=r")
4815 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4817 "cls
\\t%<w>
0, %<w>
1"
4818 [(set_attr "type" "clz")]
4821 (define_insn "rbit<mode>
2"
4822 [(set (match_operand:GPI
0 "register_operand" "=r")
4823 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4825 "rbit
\\t%<w>
0, %<w>
1"
4826 [(set_attr "type" "rbit")]
4829 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4830 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4831 ;; expression and split after reload to enable scheduling them apart if
4834 (define_insn_and_split "ctz<mode>
2"
4835 [(set (match_operand:GPI
0 "register_operand" "=r")
4836 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4842 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4843 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4847 (define_insn "*and<mode>_compare0"
4848 [(set (reg:CC_NZ CC_REGNUM)
4850 (match_operand:SHORT
0 "register_operand" "r")
4853 "tst
\\t%<w>
0, <short_mask>"
4854 [(set_attr "type" "alus_imm")]
4857 (define_insn "*ands<GPI:mode>_compare0"
4858 [(set (reg:CC_NZ CC_REGNUM)
4860 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4862 (set (match_operand:GPI
0 "register_operand" "=r")
4863 (zero_extend:GPI (match_dup
1)))]
4865 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4866 [(set_attr "type" "alus_imm")]
4869 (define_insn "*and<mode>
3nr_compare0"
4870 [(set (reg:CC_NZ CC_REGNUM)
4872 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4873 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4879 [(set_attr "type" "logics_reg,logics_imm")]
4883 [(set (reg:CC_NZ CC_REGNUM)
4885 (and:GPI (match_operand:GPI
0 "register_operand")
4886 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4888 (clobber (match_operand:SI
2 "register_operand"))]
4890 [(set (match_dup
2) (match_dup
1))
4891 (set (reg:CC_NZ CC_REGNUM)
4893 (and:GPI (match_dup
0)
4898 (define_insn "*and<mode>
3nr_compare0_zextract"
4899 [(set (reg:CC_NZ CC_REGNUM)
4901 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4902 (match_operand:GPI
1 "const_int_operand" "n")
4903 (match_operand:GPI
2 "const_int_operand" "n"))
4905 "INTVAL (operands[
1]) >
0
4906 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4907 <= GET_MODE_BITSIZE (<MODE>mode))
4908 && aarch64_bitmask_imm (
4909 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4914 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4915 return "tst
\\t%<w>
0, %
1";
4917 [(set_attr "type" "logics_shift_imm")]
4920 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4921 [(set (reg:CC_NZ CC_REGNUM)
4924 (match_operand:GPI
0 "register_operand" "r")
4925 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4926 (match_operand:GPI
2 "register_operand" "r"))
4929 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4930 [(set_attr "type" "logics_shift_imm")]
4934 [(set (reg:CC_NZ CC_REGNUM)
4937 (match_operand:GPI
0 "register_operand")
4938 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4939 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4941 (clobber (match_operand:SI
3 "register_operand"))]
4943 [(set (match_dup
3) (match_dup
2))
4944 (set (reg:CC_NZ CC_REGNUM)
4953 ;; -------------------------------------------------------------------
4955 ;; -------------------------------------------------------------------
4957 (define_expand "<optab><mode>
3"
4958 [(set (match_operand:GPI
0 "register_operand")
4959 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4960 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4963 if (CONST_INT_P (operands[
2]))
4965 operands[
2] = GEN_INT (INTVAL (operands[
2])
4966 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4968 if (operands[
2] == const0_rtx)
4970 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4977 (define_expand "ashl<mode>
3"
4978 [(set (match_operand:SHORT
0 "register_operand")
4979 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4980 (match_operand:QI
2 "const_int_operand")))]
4983 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4985 if (operands[
2] == const0_rtx)
4987 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4993 (define_expand "rotr<mode>
3"
4994 [(set (match_operand:GPI
0 "register_operand")
4995 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4996 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4999 if (CONST_INT_P (operands[
2]))
5001 operands[
2] = GEN_INT (INTVAL (operands[
2])
5002 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
5004 if (operands[
2] == const0_rtx)
5006 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
5013 (define_expand "rotl<mode>
3"
5014 [(set (match_operand:GPI
0 "register_operand")
5015 (rotatert:GPI (match_operand:GPI
1 "register_operand")
5016 (match_operand:QI
2 "aarch64_reg_or_imm")))]
5019 /* (SZ - cnt) % SZ == -cnt % SZ */
5020 if (CONST_INT_P (operands[
2]))
5022 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
5023 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
5024 if (operands[
2] == const0_rtx)
5026 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
5031 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
5036 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
5037 ;; they truncate the shift/rotate amount by the size of the registers they
5038 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
5039 ;; such redundant masking instructions. GCC can do that automatically when
5040 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
5041 ;; because some of the SISD shift alternatives don't perform this truncations.
5042 ;; So this pattern exists to catch such cases.
5044 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
5045 [(set (match_operand:GPI
0 "register_operand" "=r")
5047 (match_operand:GPI
1 "register_operand" "r")
5048 (match_operator
4 "subreg_lowpart_operator"
5049 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
5050 (match_operand
3 "const_int_operand" "n"))])))]
5051 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
5052 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
5053 [(set_attr "type" "shift_reg")]
5056 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
5057 [(set (match_operand:GPI
0 "register_operand" "=&r")
5059 (match_operand:GPI
1 "register_operand" "r")
5060 (match_operator
4 "subreg_lowpart_operator"
5061 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
5062 (match_operand
3 "const_int_operand" "n")))])))]
5063 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
5068 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5069 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
5070 emit_insn (gen_negsi2 (tmp, operands[
2]));
5072 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
5073 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
5074 SUBREG_BYTE (operands[
4]));
5075 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
5080 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
5081 [(set (match_operand:GPI
0 "register_operand" "=&r")
5083 (match_operand:GPI
1 "register_operand" "r")
5084 (minus:QI (match_operand
2 "const_int_operand" "n")
5085 (match_operator
5 "subreg_lowpart_operator"
5086 [(and:SI (match_operand:SI
3 "register_operand" "r")
5087 (match_operand
4 "const_int_operand" "n"))]))))]
5088 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
5089 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5094 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5097 emit_insn (gen_negsi2 (tmp, operands[
3]));
5099 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
5100 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
5101 SUBREG_BYTE (operands[
5]));
5103 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
5108 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5109 [(set (match_operand:DI
0 "register_operand" "=r")
5111 (match_operand:DI
1 "register_operand" "r")
5112 (match_operator
4 "subreg_lowpart_operator"
5113 [(and:SI (match_operand:SI
2 "register_operand" "r")
5114 (match_operand
3 "const_int_operand" "n"))])))]
5115 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
5118 xop[
0] = operands[
0];
5119 xop[
1] = operands[
1];
5120 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
5121 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
5124 [(set_attr "type" "shift_reg")]
5127 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
5128 [(set (match_operand:GPI
0 "register_operand" "=&r")
5130 (match_operand:GPI
1 "register_operand" "r")
5131 (minus:QI (match_operand
2 "const_int_operand" "n")
5132 (match_operand:QI
3 "register_operand" "r"))))]
5133 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5138 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
5140 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5141 : gen_lowpart (SImode, operands[
0]));
5143 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5145 rtx and_op = gen_rtx_AND (SImode, tmp,
5146 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
5148 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5150 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
5153 [(set_attr "length" "
8")]
5156 ;; Logical left shift using SISD or Integer instruction
5157 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
5158 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
5160 (match_operand:GPI
1 "register_operand" "r,r,w,w")
5161 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5164 lsl
\t%<w>
0, %<w>
1, %
2
5165 lsl
\t%<w>
0, %<w>
1, %<w>
2
5166 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5167 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
5168 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5169 (set_attr "arch" "*,*,simd,simd")]
5172 ;; Logical right shift using SISD or Integer instruction
5173 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
5174 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5176 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5177 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
5178 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5181 lsr
\t%<w>
0, %<w>
1, %
2
5182 lsr
\t%<w>
0, %<w>
1, %<w>
2
5183 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5186 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5187 (set_attr "arch" "*,*,simd,simd,simd")]
5191 [(set (match_operand:DI
0 "aarch64_simd_register")
5193 (match_operand:DI
1 "aarch64_simd_register")
5194 (match_operand:QI
2 "aarch64_simd_register")))]
5195 "TARGET_SIMD && reload_completed"
5197 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5199 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
5201 operands[
3] = gen_lowpart (QImode, operands[
0]);
5206 [(set (match_operand:SI
0 "aarch64_simd_register")
5208 (match_operand:SI
1 "aarch64_simd_register")
5209 (match_operand:QI
2 "aarch64_simd_register")))]
5210 "TARGET_SIMD && reload_completed"
5212 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5214 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
5216 operands[
3] = gen_lowpart (QImode, operands[
0]);
5220 ;; Arithmetic right shift using SISD or Integer instruction
5221 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
5222 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5224 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5225 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
5226 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5229 asr
\t%<w>
0, %<w>
1, %
2
5230 asr
\t%<w>
0, %<w>
1, %<w>
2
5231 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5234 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5235 (set_attr "arch" "*,*,simd,simd,simd")]
5239 [(set (match_operand:DI
0 "aarch64_simd_register")
5241 (match_operand:DI
1 "aarch64_simd_register")
5242 (match_operand:QI
2 "aarch64_simd_register")))]
5243 "TARGET_SIMD && reload_completed"
5245 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5247 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
5249 operands[
3] = gen_lowpart (QImode, operands[
0]);
5254 [(set (match_operand:SI
0 "aarch64_simd_register")
5256 (match_operand:SI
1 "aarch64_simd_register")
5257 (match_operand:QI
2 "aarch64_simd_register")))]
5258 "TARGET_SIMD && reload_completed"
5260 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5262 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
5264 operands[
3] = gen_lowpart (QImode, operands[
0]);
5268 (define_insn "*aarch64_sisd_ushl"
5269 [(set (match_operand:DI
0 "register_operand" "=w")
5270 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5271 (match_operand:QI
2 "register_operand" "w")]
5274 "ushl
\t%d0, %d1, %d2"
5275 [(set_attr "type" "neon_shift_reg")]
5278 (define_insn "*aarch64_ushl_2s"
5279 [(set (match_operand:SI
0 "register_operand" "=w")
5280 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5281 (match_operand:QI
2 "register_operand" "w")]
5284 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
5285 [(set_attr "type" "neon_shift_reg")]
5288 (define_insn "*aarch64_sisd_sshl"
5289 [(set (match_operand:DI
0 "register_operand" "=w")
5290 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5291 (match_operand:QI
2 "register_operand" "w")]
5294 "sshl
\t%d0, %d1, %d2"
5295 [(set_attr "type" "neon_shift_reg")]
5298 (define_insn "*aarch64_sshl_2s"
5299 [(set (match_operand:SI
0 "register_operand" "=w")
5300 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5301 (match_operand:QI
2 "register_operand" "w")]
5304 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
5305 [(set_attr "type" "neon_shift_reg")]
5308 (define_insn "*aarch64_sisd_neg_qi"
5309 [(set (match_operand:QI
0 "register_operand" "=w")
5310 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
5314 [(set_attr "type" "neon_neg")]
5318 (define_insn "*ror<mode>
3_insn"
5319 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5321 (match_operand:GPI
1 "register_operand" "r,r")
5322 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5325 ror
\\t%<w>
0, %<w>
1, %
2
5326 ror
\\t%<w>
0, %<w>
1, %<w>
2"
5327 [(set_attr "type" "rotate_imm,shift_reg")]
5330 ;; zero_extend version of above
5331 (define_insn "*<optab>si3_insn_uxtw"
5332 [(set (match_operand:DI
0 "register_operand" "=r,r")
5333 (zero_extend:DI (SHIFT:SI
5334 (match_operand:SI
1 "register_operand" "r,r")
5335 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5338 <shift>
\\t%w0, %w1, %
2
5339 <shift>
\\t%w0, %w1, %w2"
5340 [(set_attr "type" "bfx,shift_reg")]
5343 (define_insn "*<optab><mode>
3_insn"
5344 [(set (match_operand:SHORT
0 "register_operand" "=r")
5345 (ASHIFT:SHORT (match_operand:SHORT
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 "<bfshift>
\t%w0, %w1, %
2, %
3";
5352 [(set_attr "type" "bfx")]
5355 (define_insn "*extr<mode>
5_insn"
5356 [(set (match_operand:GPI
0 "register_operand" "=r")
5357 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5358 (match_operand
3 "const_int_operand" "n"))
5359 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5360 (match_operand
4 "const_int_operand" "n"))))]
5361 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5362 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
5363 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5364 [(set_attr "type" "rotate_imm")]
5367 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5368 ;; so we have to match both orderings.
5369 (define_insn "*extr<mode>
5_insn_alt"
5370 [(set (match_operand:GPI
0 "register_operand" "=r")
5371 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5372 (match_operand
4 "const_int_operand" "n"))
5373 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5374 (match_operand
3 "const_int_operand" "n"))))]
5375 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
5376 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
5377 == GET_MODE_BITSIZE (<MODE>mode))"
5378 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5379 [(set_attr "type" "rotate_imm")]
5382 ;; zero_extend version of the above
5383 (define_insn "*extrsi5_insn_uxtw"
5384 [(set (match_operand:DI
0 "register_operand" "=r")
5386 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
5387 (match_operand
3 "const_int_operand" "n"))
5388 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5389 (match_operand
4 "const_int_operand" "n")))))]
5390 "UINTVAL (operands[
3]) <
32 &&
5391 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5392 "extr
\\t%w0, %w1, %w2, %
4"
5393 [(set_attr "type" "rotate_imm")]
5396 (define_insn "*extrsi5_insn_uxtw_alt"
5397 [(set (match_operand:DI
0 "register_operand" "=r")
5399 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5400 (match_operand
4 "const_int_operand" "n"))
5401 (ashift:SI (match_operand:SI
1 "register_operand" "r")
5402 (match_operand
3 "const_int_operand" "n")))))]
5403 "UINTVAL (operands[
3]) <
32 &&
5404 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5405 "extr
\\t%w0, %w1, %w2, %
4"
5406 [(set_attr "type" "rotate_imm")]
5409 (define_insn "*ror<mode>
3_insn"
5410 [(set (match_operand:GPI
0 "register_operand" "=r")
5411 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
5412 (match_operand
2 "const_int_operand" "n")))]
5413 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5415 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5416 return "ror
\\t%<w>
0, %<w>
1, %
3";
5418 [(set_attr "type" "rotate_imm")]
5421 ;; zero_extend version of the above
5422 (define_insn "*rorsi3_insn_uxtw"
5423 [(set (match_operand:DI
0 "register_operand" "=r")
5425 (rotate:SI (match_operand:SI
1 "register_operand" "r")
5426 (match_operand
2 "const_int_operand" "n"))))]
5427 "UINTVAL (operands[
2]) <
32"
5429 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
5430 return "ror
\\t%w0, %w1, %
3";
5432 [(set_attr "type" "rotate_imm")]
5435 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5436 [(set (match_operand:GPI
0 "register_operand" "=r")
5438 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
5439 (match_operand
2 "const_int_operand" "n"))))]
5440 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5442 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5443 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5445 [(set_attr "type" "bfx")]
5448 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5449 [(set (match_operand:GPI
0 "register_operand" "=r")
5451 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5452 (match_operand
2 "const_int_operand" "n"))))]
5453 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5455 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5456 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5458 [(set_attr "type" "bfx")]
5461 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5462 [(set (match_operand:GPI
0 "register_operand" "=r")
5464 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5465 (match_operand
2 "const_int_operand" "n"))))]
5466 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5468 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5469 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5471 [(set_attr "type" "bfx")]
5474 ;; -------------------------------------------------------------------
5476 ;; -------------------------------------------------------------------
5478 (define_expand "<optab>"
5479 [(set (match_operand:DI
0 "register_operand")
5480 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
5482 "aarch64_simd_shift_imm_offset_di")
5483 (match_operand
3 "aarch64_simd_shift_imm_di")))]
5486 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5487 1, GET_MODE_BITSIZE (DImode) -
1))
5493 (define_insn "*<optab><mode>"
5494 [(set (match_operand:GPI
0 "register_operand" "=r")
5495 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
5497 "aarch64_simd_shift_imm_offset_<mode>" "n")
5499 "aarch64_simd_shift_imm_<mode>" "n")))]
5500 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5501 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5502 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
5503 [(set_attr "type" "bfx")]
5506 ;; When the bit position and width add up to
32 we can use a W-reg LSR
5507 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5509 [(set (match_operand:DI
0 "register_operand")
5510 (zero_extract:DI (match_operand:DI
1 "register_operand")
5512 "aarch64_simd_shift_imm_offset_di")
5514 "aarch64_simd_shift_imm_di")))]
5515 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
5516 GET_MODE_BITSIZE (DImode) -
1)
5517 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
5518 == GET_MODE_BITSIZE (SImode)"
5520 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
5522 operands[
4] = gen_lowpart (SImode, operands[
1]);
5526 ;; Bitfield Insert (insv)
5527 (define_expand "insv<mode>"
5528 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
5529 (match_operand
1 "const_int_operand")
5530 (match_operand
2 "const_int_operand"))
5531 (match_operand:GPI
3 "general_operand"))]
5534 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
5535 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
5536 rtx value = operands[
3];
5538 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5541 if (CONST_INT_P (value))
5543 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
5545 /* Prefer AND/OR for inserting all zeros or all ones. */
5546 if ((UINTVAL (value) & mask) ==
0
5547 || (UINTVAL (value) & mask) == mask)
5550 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
5551 if (width ==
16 && (pos %
16) ==
0)
5554 operands[
3] = force_reg (<MODE>mode, value);
5557 (define_insn "*insv_reg<mode>"
5558 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5559 (match_operand
1 "const_int_operand" "n")
5560 (match_operand
2 "const_int_operand" "n"))
5561 (match_operand:GPI
3 "register_operand" "r"))]
5562 "!(UINTVAL (operands[
1]) ==
0
5563 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
5564 > GET_MODE_BITSIZE (<MODE>mode)))"
5565 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
5566 [(set_attr "type" "bfm")]
5569 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
5570 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5571 (match_operand
1 "const_int_operand" "n")
5572 (match_operand
2 "const_int_operand" "n"))
5573 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
5574 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
5575 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
5576 [(set_attr "type" "bfm")]
5579 ;; Match a bfi instruction where the shift of OP3 means that we are
5580 ;; actually copying the least significant bits of OP3 into OP0 by way
5581 ;; of the AND masks and the IOR instruction. A similar instruction
5582 ;; with the two parts of the IOR swapped around was never triggered
5583 ;; in a bootstrap build and test of GCC so it was not included.
5585 (define_insn "*aarch64_bfi<GPI:mode>
5_shift"
5586 [(set (match_operand:GPI
0 "register_operand" "=r")
5587 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5588 (match_operand:GPI
2 "const_int_operand" "n"))
5589 (and:GPI (ashift:GPI
5590 (match_operand:GPI
3 "register_operand" "r")
5591 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))
5592 (match_operand:GPI
5 "const_int_operand" "n"))))]
5593 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5594 UINTVAL (operands[
4]),
5595 UINTVAL(operands[
5]))"
5596 "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %P5"
5597 [(set_attr "type" "bfm")]
5600 (define_insn "*aarch64_bfi<GPI:mode>
5_shift_alt"
5601 [(set (match_operand:GPI
0 "register_operand" "=r")
5602 (ior:GPI (and:GPI (ashift:GPI
5603 (match_operand:GPI
1 "register_operand" "r")
5604 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5605 (match_operand:GPI
3 "const_int_operand" "n"))
5606 (and:GPI (match_operand:GPI
4 "register_operand" "
0")
5607 (match_operand:GPI
5 "const_int_operand" "n"))))]
5608 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
5]),
5609 UINTVAL (operands[
2]),
5610 UINTVAL(operands[
3]))"
5611 "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %P3"
5612 [(set_attr "type" "bfm")]
5615 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no and of the ashift because
5616 ;; the shift is large enough to remove the need for an AND instruction.
5618 (define_insn "*aarch64_bfi<GPI:mode>
4_noand"
5619 [(set (match_operand:GPI
0 "register_operand" "=r")
5620 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5621 (match_operand:GPI
2 "const_int_operand" "n"))
5623 (match_operand:GPI
3 "register_operand" "r")
5624 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5625 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5626 UINTVAL (operands[
4]),
5627 HOST_WIDE_INT_M1U << UINTVAL (operands[
4]) )"
5629 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
4]));
5630 return "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %
5";
5632 [(set_attr "type" "bfm")]
5635 (define_insn "*aarch64_bfi<GPI:mode>
4_noand_alt"
5636 [(set (match_operand:GPI
0 "register_operand" "=r")
5637 (ior:GPI (ashift:GPI
5638 (match_operand:GPI
1 "register_operand" "r")
5639 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5640 (and:GPI (match_operand:GPI
3 "register_operand" "
0")
5641 (match_operand:GPI
4 "const_int_operand" "n"))))]
5642 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
4]),
5643 UINTVAL (operands[
2]),
5644 HOST_WIDE_INT_M1U << UINTVAL (operands[
2]) )"
5646 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
2]));
5647 return "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
5";
5649 [(set_attr "type" "bfm")]
5652 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no shifting, we are just
5653 ;; copying the least significant bits of OP3 to OP0. We need two versions
5654 ;; of the instruction to handle different checks on the constant values.
5656 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift"
5657 [(set (match_operand:GPI
0 "register_operand" "=r")
5658 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5659 (match_operand:GPI
2 "const_int_operand" "n"))
5660 (and:GPI (match_operand:GPI
3 "register_operand" "r")
5661 (match_operand:GPI
4 "const_int_operand" "n"))))]
5662 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5663 UINTVAL (operands[
4]))"
5664 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5665 [(set_attr "type" "bfm")]
5668 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift_alt"
5669 [(set (match_operand:GPI
0 "register_operand" "=r")
5670 (ior:GPI (and:GPI (match_operand:GPI
3 "register_operand" "r")
5671 (match_operand:GPI
4 "const_int_operand" "n"))
5672 (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5673 (match_operand:GPI
2 "const_int_operand" "n"))))]
5674 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5675 UINTVAL (operands[
4]))"
5676 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5677 [(set_attr "type" "bfm")]
5680 (define_insn "*extr_insv_lower_reg<mode>"
5681 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5682 (match_operand
1 "const_int_operand" "n")
5684 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
5686 (match_operand
3 "const_int_operand" "n")))]
5687 "!(UINTVAL (operands[
1]) ==
0
5688 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
5689 > GET_MODE_BITSIZE (<MODE>mode)))"
5690 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
5691 [(set_attr "type" "bfm")]
5694 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5695 [(set (match_operand:GPI
0 "register_operand" "=r")
5696 (ashift:GPI (ANY_EXTEND:GPI
5697 (match_operand:ALLX
1 "register_operand" "r"))
5698 (match_operand
2 "const_int_operand" "n")))]
5699 "UINTVAL (operands[
2]) < <GPI:sizen>"
5701 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
5702 ? GEN_INT (<ALLX:sizen>)
5703 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
5704 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5706 [(set_attr "type" "bfx")]
5709 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5711 (define_insn "*andim_ashift<mode>_bfiz"
5712 [(set (match_operand:GPI
0 "register_operand" "=r")
5713 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5714 (match_operand
2 "const_int_operand" "n"))
5715 (match_operand
3 "const_int_operand" "n")))]
5716 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
5717 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
5718 [(set_attr "type" "bfx")]
5721 ;; Match sbfiz pattern in a shift left + shift right operation.
5723 (define_insn "*ashift<mode>_extv_bfiz"
5724 [(set (match_operand:GPI
0 "register_operand" "=r")
5725 (ashift:GPI (sign_extract:GPI (match_operand:GPI
1 "register_operand" "r")
5726 (match_operand
2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5728 (match_operand
3 "aarch64_simd_shift_imm_<mode>" "n")))]
5729 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5730 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5731 "sbfiz
\\t%<w>
0, %<w>
1, %
3, %
2"
5732 [(set_attr "type" "bfx")]
5735 ;; When the bit position and width of the equivalent extraction add up to
32
5736 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5737 ;; zero-extension of the X-reg.
5739 [(set (match_operand:DI
0 "register_operand")
5740 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
5741 (match_operand
2 "const_int_operand"))
5742 (match_operand
3 "const_int_operand")))]
5743 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
5744 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
5745 == GET_MODE_BITSIZE (SImode)"
5747 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
5749 operands[
4] = gen_lowpart (SImode, operands[
1]);
5753 (define_insn "bswap<mode>
2"
5754 [(set (match_operand:GPI
0 "register_operand" "=r")
5755 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
5757 "rev
\\t%<w>
0, %<w>
1"
5758 [(set_attr "type" "rev")]
5761 (define_insn "bswaphi2"
5762 [(set (match_operand:HI
0 "register_operand" "=r")
5763 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
5766 [(set_attr "type" "rev")]
5769 (define_insn "*aarch64_bfxil<mode>"
5770 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5771 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "r,
0")
5772 (match_operand:GPI
3 "const_int_operand" "n, Ulc"))
5773 (and:GPI (match_operand:GPI
2 "register_operand" "
0,r")
5774 (match_operand:GPI
4 "const_int_operand" "Ulc, n"))))]
5775 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5776 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5777 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5779 switch (which_alternative)
5782 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5783 return "bfxil
\\t%<w>
0, %<w>
1,
0, %
3";
5785 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5786 return "bfxil
\\t%<w>
0, %<w>
2,
0, %
3";
5791 [(set_attr "type" "bfm")]
5794 ; Zero-extended version of above (aarch64_bfxil)
5795 (define_insn "*aarch64_bfxilsi_uxtw"
5796 [(set (match_operand:DI
0 "register_operand" "=r,r")
5797 (zero_extend:DI (ior:SI (and:SI (match_operand:SI
1 "register_operand"
5799 (match_operand:SI
3 "const_int_operand" "n, Ulc"))
5800 (and:SI (match_operand:SI
2 "register_operand" "
0,r")
5801 (match_operand:SI
4 "const_int_operand" "Ulc, n")))))]
5802 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5803 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5804 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5806 switch (which_alternative)
5809 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5810 return "bfxil
\\t%
0, %
1,
0, %
3";
5812 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5813 return "bfxil
\\t%
0, %
2,
0, %
3";
5818 [(set_attr "type" "bfm")]
5821 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5822 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5823 ;; each valid permutation.
5825 (define_insn "rev16<mode>
2"
5826 [(set (match_operand:GPI
0 "register_operand" "=r")
5827 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5829 (match_operand:GPI
3 "const_int_operand" "n"))
5830 (and:GPI (lshiftrt:GPI (match_dup
1)
5832 (match_operand:GPI
2 "const_int_operand" "n"))))]
5833 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5834 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5835 "rev16
\\t%<w>
0, %<w>
1"
5836 [(set_attr "type" "rev")]
5839 (define_insn "rev16<mode>
2_alt"
5840 [(set (match_operand:GPI
0 "register_operand" "=r")
5841 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
5843 (match_operand:GPI
2 "const_int_operand" "n"))
5844 (and:GPI (ashift:GPI (match_dup
1)
5846 (match_operand:GPI
3 "const_int_operand" "n"))))]
5847 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5848 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5849 "rev16
\\t%<w>
0, %<w>
1"
5850 [(set_attr "type" "rev")]
5853 ;; zero_extend version of above
5854 (define_insn "*bswapsi2_uxtw"
5855 [(set (match_operand:DI
0 "register_operand" "=r")
5856 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
5859 [(set_attr "type" "rev")]
5862 ;; -------------------------------------------------------------------
5863 ;; Floating-point intrinsics
5864 ;; -------------------------------------------------------------------
5866 ;; frint floating-point round to integral standard patterns.
5867 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5869 (define_insn "<frint_pattern><mode>
2"
5870 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5871 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5874 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
5875 [(set_attr "type" "f_rint<stype>")]
5878 ;; frcvt floating-point round to integer and convert standard patterns.
5879 ;; Expands to lbtrunc, lceil, lfloor, lround.
5880 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
5881 [(set (match_operand:GPI
0 "register_operand" "=r")
5883 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5886 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
5887 [(set_attr "type" "f_cvtf2i")]
5890 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
5891 [(set (match_operand:GPI
0 "register_operand" "=r")
5894 (match_operand:GPF
1 "register_operand" "w")
5895 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
5897 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
5898 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5900 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
5902 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
5903 output_asm_insn (buf, operands);
5906 [(set_attr "type" "f_cvtf2i")]
5909 ;; fma - expand fma into patterns with the accumulator operand first since
5910 ;; reusing the accumulator results in better register allocation.
5911 ;; The register allocator considers copy preferences in operand order,
5912 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5914 (define_expand "fma<mode>
4"
5915 [(set (match_operand:GPF_F16
0 "register_operand")
5916 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
5917 (match_operand:GPF_F16
2 "register_operand")
5918 (match_operand:GPF_F16
3 "register_operand")))]
5922 (define_insn "*aarch64_fma<mode>
4"
5923 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5924 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
5925 (match_operand:GPF_F16
3 "register_operand" "w")
5926 (match_operand:GPF_F16
1 "register_operand" "w")))]
5928 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5929 [(set_attr "type" "fmac<stype>")]
5932 (define_expand "fnma<mode>
4"
5933 [(set (match_operand:GPF_F16
0 "register_operand")
5935 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5936 (match_operand:GPF_F16
2 "register_operand")
5937 (match_operand:GPF_F16
3 "register_operand")))]
5941 (define_insn "*aarch64_fnma<mode>
4"
5942 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5944 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5945 (match_operand:GPF_F16
3 "register_operand" "w")
5946 (match_operand:GPF_F16
1 "register_operand" "w")))]
5948 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5949 [(set_attr "type" "fmac<stype>")]
5953 (define_expand "fms<mode>
4"
5954 [(set (match_operand:GPF
0 "register_operand")
5955 (fma:GPF (match_operand:GPF
1 "register_operand")
5956 (match_operand:GPF
2 "register_operand")
5957 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5961 (define_insn "*aarch64_fms<mode>
4"
5962 [(set (match_operand:GPF
0 "register_operand" "=w")
5963 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5964 (match_operand:GPF
3 "register_operand" "w")
5965 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5967 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5968 [(set_attr "type" "fmac<s>")]
5971 (define_expand "fnms<mode>
4"
5972 [(set (match_operand:GPF
0 "register_operand")
5973 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5974 (match_operand:GPF
2 "register_operand")
5975 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5979 (define_insn "*aarch64_fnms<mode>
4"
5980 [(set (match_operand:GPF
0 "register_operand" "=w")
5981 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5982 (match_operand:GPF
3 "register_operand" "w")
5983 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5985 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5986 [(set_attr "type" "fmac<s>")]
5989 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5990 (define_insn "*aarch64_fnmadd<mode>
4"
5991 [(set (match_operand:GPF
0 "register_operand" "=w")
5992 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5993 (match_operand:GPF
3 "register_operand" "w")
5994 (match_operand:GPF
1 "register_operand" "w"))))]
5995 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5996 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5997 [(set_attr "type" "fmac<s>")]
6000 ;; -------------------------------------------------------------------
6001 ;; Floating-point conversions
6002 ;; -------------------------------------------------------------------
6004 (define_insn "extendsfdf2"
6005 [(set (match_operand:DF
0 "register_operand" "=w")
6006 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
6009 [(set_attr "type" "f_cvt")]
6012 (define_insn "extendhfsf2"
6013 [(set (match_operand:SF
0 "register_operand" "=w")
6014 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
6017 [(set_attr "type" "f_cvt")]
6020 (define_insn "extendhfdf2"
6021 [(set (match_operand:DF
0 "register_operand" "=w")
6022 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
6025 [(set_attr "type" "f_cvt")]
6028 (define_insn "truncdfsf2"
6029 [(set (match_operand:SF
0 "register_operand" "=w")
6030 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
6033 [(set_attr "type" "f_cvt")]
6036 (define_insn "truncsfhf2"
6037 [(set (match_operand:HF
0 "register_operand" "=w")
6038 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
6041 [(set_attr "type" "f_cvt")]
6044 (define_insn "truncdfhf2"
6045 [(set (match_operand:HF
0 "register_operand" "=w")
6046 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
6049 [(set_attr "type" "f_cvt")]
6052 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
6053 ;; and making r = w more expensive
6055 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
6056 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
6057 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
6060 fcvtz<su>
\t%<s>
0, %<s>
1
6061 fcvtz<su>
\t%<w>
0, %<s>
1"
6062 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
6065 ;; Convert HF -> SI or DI
6067 (define_insn "<optab>_trunchf<GPI:mode>
2"
6068 [(set (match_operand:GPI
0 "register_operand" "=r")
6069 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
6071 "fcvtz<su>
\t%<w>
0, %h1"
6072 [(set_attr "type" "f_cvtf2i")]
6075 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
6076 ;; input in a fp register and output in a integer register
6078 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
6079 [(set (match_operand:GPI
0 "register_operand" "=r")
6080 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
6082 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
6083 [(set_attr "type" "f_cvtf2i")]
6086 (define_insn "*fix_to_zero_extend<mode>di2"
6087 [(set (match_operand:DI
0 "register_operand" "=r")
6090 (match_operand:GPF
1 "register_operand" "w"))))]
6092 "fcvtzu
\t%w0, %<s>
1"
6093 [(set_attr "type" "f_cvtf2i")]
6096 ;; Equal width integer to fp and multiply combine.
6097 (define_insn "*aarch64_<su_optab>cvtf<fcvt_target><GPF:mode>
2_mult"
6098 [(set (match_operand:GPF
0 "register_operand" "=w,w")
6099 (mult:GPF (FLOATUORS:GPF
6100 (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r"))
6101 (match_operand:GPF
2 "aarch64_fp_pow2_recip" "Dt,Dt")))]
6104 operands[
2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[
2]));
6105 switch (which_alternative)
6108 return "<su_optab>cvtf
\t%<GPF:s>
0, %<s>
1, #%
2";
6110 return "<su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1, #%
2";
6115 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6116 (set_attr "arch" "simd,fp")]
6119 ;; Unequal width integer to fp and multiply combine.
6120 (define_insn "*aarch64_<su_optab>cvtf<fcvt_iesize><GPF:mode>
2_mult"
6121 [(set (match_operand:GPF
0 "register_operand" "=w")
6122 (mult:GPF (FLOATUORS:GPF
6123 (match_operand:<FCVT_IESIZE>
1 "register_operand" "r"))
6124 (match_operand:GPF
2 "aarch64_fp_pow2_recip" "Dt")))]
6127 operands[
2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[
2]));
6128 return "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1, #%
2";
6130 [(set_attr "type" "f_cvti2f")]
6133 ;; Equal width integer to fp conversion.
6134 (define_insn "<optab><fcvt_target><GPF:mode>
2"
6135 [(set (match_operand:GPF
0 "register_operand" "=w,w")
6136 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
6139 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
6140 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
6141 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6142 (set_attr "arch" "simd,fp")]
6145 ;; Unequal width integer to fp conversions.
6146 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
6147 [(set (match_operand:GPF
0 "register_operand" "=w")
6148 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
6150 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
6151 [(set_attr "type" "f_cvti2f")]
6154 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
6155 ;; midend will arrange for an SImode conversion to HFmode to first go
6156 ;; through DFmode, then to HFmode. But first it will try converting
6157 ;; to DImode then down, which would match our DImode pattern below and
6158 ;; give very poor code-generation. So, we must provide our own emulation
6159 ;; of the mid-end logic.
6161 (define_insn "aarch64_fp16_<optab><mode>hf2"
6162 [(set (match_operand:HF
0 "register_operand" "=w")
6163 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
6165 "<su_optab>cvtf
\t%h0, %<w>
1"
6166 [(set_attr "type" "f_cvti2f")]
6169 (define_expand "<optab>sihf2"
6170 [(set (match_operand:HF
0 "register_operand")
6171 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
6174 if (TARGET_FP_F16INST)
6175 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
6178 rtx convert_target = gen_reg_rtx (DFmode);
6179 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
6180 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
6186 ;; For DImode there is no wide enough floating-point mode that we
6187 ;; can convert through natively (TFmode would work, but requires a library
6188 ;; call). However, we know that any value >=
65504 will be rounded
6189 ;; to infinity on conversion. This is well within the range of SImode, so
6191 ;; Saturate to SImode.
6192 ;; Convert from that to DFmode
6193 ;; Convert from that to HFmode (phew!).
6194 ;; Note that the saturation to SImode requires the SIMD extensions. If
6195 ;; we ever need to provide this pattern where the SIMD extensions are not
6196 ;; available, we would need a different approach.
6198 (define_expand "<optab>dihf2"
6199 [(set (match_operand:HF
0 "register_operand")
6200 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
6201 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6203 if (TARGET_FP_F16INST)
6204 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
6207 rtx sat_target = gen_reg_rtx (SImode);
6208 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
6209 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
6216 ;; Convert between fixed-point and floating-point (scalar modes)
6218 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
6219 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
6220 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
6221 (match_operand:SI
2 "immediate_operand" "i, i")]
6225 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
6226 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
6227 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6228 (set_attr "arch" "fp,simd")]
6231 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
6232 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
6233 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
6234 (match_operand:SI
2 "immediate_operand" "i, i")]
6238 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
6239 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
6240 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6241 (set_attr "arch" "fp,simd")]
6244 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
6245 [(set (match_operand:GPI
0 "register_operand" "=r")
6246 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
6247 (match_operand:SI
2 "immediate_operand" "i")]
6250 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
6251 [(set_attr "type" "f_cvtf2i")]
6254 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6255 [(set (match_operand:HF
0 "register_operand" "=w")
6256 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
6257 (match_operand:SI
2 "immediate_operand" "i")]
6260 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
6261 [(set_attr "type" "f_cvti2f")]
6264 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6265 [(set (match_operand:HI
0 "register_operand" "=w")
6266 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
6267 (match_operand:SI
2 "immediate_operand" "i")]
6270 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6271 [(set_attr "type" "neon_fp_to_int_s")]
6274 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6275 [(set (match_operand:HF
0 "register_operand" "=w")
6276 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
6277 (match_operand:SI
2 "immediate_operand" "i")]
6280 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6281 [(set_attr "type" "neon_int_to_fp_s")]
6284 ;; -------------------------------------------------------------------
6285 ;; Floating-point arithmetic
6286 ;; -------------------------------------------------------------------
6288 (define_insn "add<mode>
3"
6289 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6291 (match_operand:GPF_F16
1 "register_operand" "w")
6292 (match_operand:GPF_F16
2 "register_operand" "w")))]
6294 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
6295 [(set_attr "type" "fadd<stype>")]
6298 (define_insn "sub<mode>
3"
6299 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6301 (match_operand:GPF_F16
1 "register_operand" "w")
6302 (match_operand:GPF_F16
2 "register_operand" "w")))]
6304 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
6305 [(set_attr "type" "fadd<stype>")]
6308 (define_insn "mul<mode>
3"
6309 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6311 (match_operand:GPF_F16
1 "register_operand" "w")
6312 (match_operand:GPF_F16
2 "register_operand" "w")))]
6314 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
6315 [(set_attr "type" "fmul<stype>")]
6318 (define_insn "*fnmul<mode>
3"
6319 [(set (match_operand:GPF
0 "register_operand" "=w")
6321 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
6322 (match_operand:GPF
2 "register_operand" "w")))]
6323 "TARGET_FLOAT && !flag_rounding_math"
6324 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6325 [(set_attr "type" "fmul<s>")]
6328 (define_insn "*fnmul<mode>
3"
6329 [(set (match_operand:GPF
0 "register_operand" "=w")
6331 (match_operand:GPF
1 "register_operand" "w")
6332 (match_operand:GPF
2 "register_operand" "w"))))]
6334 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6335 [(set_attr "type" "fmul<s>")]
6338 (define_expand "div<mode>
3"
6339 [(set (match_operand:GPF_F16
0 "register_operand")
6340 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
6341 (match_operand:GPF_F16
2 "register_operand")))]
6344 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
6347 operands[
1] = force_reg (<MODE>mode, operands[
1]);
6350 (define_insn "*div<mode>
3"
6351 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6352 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
6353 (match_operand:GPF_F16
2 "register_operand" "w")))]
6355 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
6356 [(set_attr "type" "fdiv<stype>")]
6359 (define_insn "neg<mode>
2"
6360 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6361 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6363 "fneg
\\t%<s>
0, %<s>
1"
6364 [(set_attr "type" "ffarith<stype>")]
6367 (define_expand "sqrt<mode>
2"
6368 [(set (match_operand:GPF_F16
0 "register_operand")
6369 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand")))]
6372 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
6376 (define_insn "*sqrt<mode>
2"
6377 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6378 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6380 "fsqrt
\\t%<s>
0, %<s>
1"
6381 [(set_attr "type" "fsqrt<stype>")]
6384 (define_insn "abs<mode>
2"
6385 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6386 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6388 "fabs
\\t%<s>
0, %<s>
1"
6389 [(set_attr "type" "ffarith<stype>")]
6392 ;; Given that smax/smin do not specify the result when either input is NaN,
6393 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6396 (define_insn "smax<mode>
3"
6397 [(set (match_operand:GPF
0 "register_operand" "=w")
6398 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
6399 (match_operand:GPF
2 "register_operand" "w")))]
6401 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
6402 [(set_attr "type" "f_minmax<s>")]
6405 (define_insn "smin<mode>
3"
6406 [(set (match_operand:GPF
0 "register_operand" "=w")
6407 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
6408 (match_operand:GPF
2 "register_operand" "w")))]
6410 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
6411 [(set_attr "type" "f_minmax<s>")]
6414 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6415 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
6416 ;; which implement the IEEE fmax ()/fmin () functions.
6417 (define_insn "<maxmin_uns><mode>
3"
6418 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6419 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
6420 (match_operand:GPF_F16
2 "register_operand" "w")]
6423 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
6424 [(set_attr "type" "f_minmax<stype>")]
6427 (define_expand "lrint<GPF:mode><GPI:mode>
2"
6428 [(match_operand:GPI
0 "register_operand")
6429 (match_operand:GPF
1 "register_operand")]
6431 && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE)
6432 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6434 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6435 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
6436 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
6441 ;; For copysign (x, y), we want to generate:
6443 ;; LDR d2, #(
1 <<
63)
6444 ;; BSL v2.8b, [y], [x]
6446 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6447 ;; we expect these operations to nearly always operate on
6448 ;; floating-point values, we do not want the operation to be
6449 ;; simplified into a bit-field insert operation that operates on the
6450 ;; integer side, since typically that would involve three inter-bank
6451 ;; register copies. As we do not expect copysign to be followed by
6452 ;; other logical operations on the result, it seems preferable to keep
6453 ;; this as an unspec operation, rather than exposing the underlying
6454 ;; logic to the compiler.
6456 (define_expand "copysign<GPF:mode>
3"
6457 [(match_operand:GPF
0 "register_operand")
6458 (match_operand:GPF
1 "register_operand")
6459 (match_operand:GPF
2 "register_operand")]
6460 "TARGET_FLOAT && TARGET_SIMD"
6462 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6463 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6464 << (GET_MODE_BITSIZE (<MODE>mode) -
1)));
6465 emit_insn (gen_copysign<mode>
3_insn (operands[
0], operands[
1], operands[
2],
6471 (define_insn "copysign<GPF:mode>
3_insn"
6472 [(set (match_operand:GPF
0 "register_operand" "=w,w,w,r")
6473 (unspec:GPF [(match_operand:GPF
1 "register_operand" "w,
0,w,r")
6474 (match_operand:GPF
2 "register_operand" "w,w,
0,
0")
6475 (match_operand:<V_INT_EQUIV>
3 "register_operand" "
0,w,w,X")]
6477 "TARGET_FLOAT && TARGET_SIMD"
6479 bsl
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>
6480 bit
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
3.<Vbtype>
6481 bif
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
3.<Vbtype>
6482 bfxil
\\t%<w1>
0, %<w1>
1, #
0, <sizem1>"
6483 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6487 ;; For xorsign (x, y), we want to generate:
6490 ;; AND v3.8B, v1.8B, v2.8B
6491 ;; EOR v0.8B, v0.8B, v3.8B
6494 (define_expand "xorsign<mode>
3"
6495 [(match_operand:GPF
0 "register_operand")
6496 (match_operand:GPF
1 "register_operand")
6497 (match_operand:GPF
2 "register_operand")]
6498 "TARGET_FLOAT && TARGET_SIMD"
6501 machine_mode imode = <V_INT_EQUIV>mode;
6502 rtx mask = gen_reg_rtx (imode);
6503 rtx op1x = gen_reg_rtx (imode);
6504 rtx op2x = gen_reg_rtx (imode);
6506 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
6507 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6510 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
6511 lowpart_subreg (imode, operands[
2],
6513 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
6514 lowpart_subreg (imode, operands[
1],
6517 emit_move_insn (operands[
0],
6518 lowpart_subreg (<MODE>mode, op1x, imode));
6523 ;; -------------------------------------------------------------------
6525 ;; -------------------------------------------------------------------
6526 ;; Reload Scalar Floating point modes from constant pool.
6527 ;; The AArch64 port doesn't have __int128 constant move support.
6528 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
6529 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6530 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
6531 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
6532 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6535 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6536 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
6541 ;; Reload Vector modes from constant pool.
6542 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6543 [(set (match_operand:VALL
0 "register_operand" "=w")
6544 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
6545 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6548 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6549 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
6554 (define_expand "@aarch64_reload_mov<mode>"
6555 [(set (match_operand:TX
0 "register_operand" "=w")
6556 (match_operand:TX
1 "register_operand" "w"))
6557 (clobber (match_operand:DI
2 "register_operand" "=&r"))
6561 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
6562 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
6563 gen_aarch64_movtilow_tilow (op0, op1);
6564 gen_aarch64_movdi_tihigh (operands[
2], op1);
6565 gen_aarch64_movtihigh_di (op0, operands[
2]);
6570 ;; The following secondary reload helpers patterns are invoked
6571 ;; after or during reload as we don't want these patterns to start
6572 ;; kicking in during the combiner.
6574 (define_insn "@aarch64_movdi_<mode>low"
6575 [(set (match_operand:DI
0 "register_operand" "=r")
6576 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6577 (const_int
64) (const_int
0)))]
6578 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6580 [(set_attr "type" "f_mrc")
6581 (set_attr "length" "
4")
6584 (define_insn "@aarch64_movdi_<mode>high"
6585 [(set (match_operand:DI
0 "register_operand" "=r")
6586 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6587 (const_int
64) (const_int
64)))]
6588 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6589 "fmov
\\t%x0, %
1.d[
1]"
6590 [(set_attr "type" "f_mrc")
6591 (set_attr "length" "
4")
6594 (define_insn "@aarch64_mov<mode>high_di"
6595 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
6596 (const_int
64) (const_int
64))
6597 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6598 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6599 "fmov
\\t%
0.d[
1], %x1"
6600 [(set_attr "type" "f_mcr")
6601 (set_attr "length" "
4")
6604 (define_insn "@aarch64_mov<mode>low_di"
6605 [(set (match_operand:TX
0 "register_operand" "=w")
6606 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6607 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6609 [(set_attr "type" "f_mcr")
6610 (set_attr "length" "
4")
6613 (define_insn "aarch64_movtilow_tilow"
6614 [(set (match_operand:TI
0 "register_operand" "=w")
6616 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
6617 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6619 [(set_attr "type" "fmov")
6620 (set_attr "length" "
4")
6623 ;; There is a deliberate reason why the parameters of high and lo_sum's
6624 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6625 ;; and lo_sum's to be used with the labels defining the jump tables in
6628 (define_expand "add_losym"
6629 [(set (match_operand
0 "register_operand")
6630 (lo_sum (match_operand
1 "register_operand")
6631 (match_operand
2 "aarch64_valid_symref")))]
6634 machine_mode mode = GET_MODE (operands[
0]);
6636 emit_insn ((mode == DImode
6638 : gen_add_losym_si) (operands[
0],
6644 (define_insn "add_losym_<mode>"
6645 [(set (match_operand:P
0 "register_operand" "=r")
6646 (lo_sum:P (match_operand:P
1 "register_operand" "r")
6647 (match_operand
2 "aarch64_valid_symref" "S")))]
6649 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
6650 [(set_attr "type" "alu_imm")]
6653 (define_insn "ldr_got_small_<mode>"
6654 [(set (match_operand:PTR
0 "register_operand" "=r")
6655 (unspec:PTR [(mem:PTR (lo_sum:PTR
6656 (match_operand:PTR
1 "register_operand" "r")
6657 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6658 UNSPEC_GOTSMALLPIC))]
6660 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
6661 [(set_attr "type" "load_<ldst_sz>")]
6664 (define_insn "ldr_got_small_sidi"
6665 [(set (match_operand:DI
0 "register_operand" "=r")
6667 (unspec:SI [(mem:SI (lo_sum:DI
6668 (match_operand:DI
1 "register_operand" "r")
6669 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6670 UNSPEC_GOTSMALLPIC)))]
6672 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
6673 [(set_attr "type" "load_4")]
6676 (define_insn "ldr_got_small_28k_<mode>"
6677 [(set (match_operand:PTR
0 "register_operand" "=r")
6678 (unspec:PTR [(mem:PTR (lo_sum:PTR
6679 (match_operand:PTR
1 "register_operand" "r")
6680 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6681 UNSPEC_GOTSMALLPIC28K))]
6683 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
6684 [(set_attr "type" "load_<ldst_sz>")]
6687 (define_insn "ldr_got_small_28k_sidi"
6688 [(set (match_operand:DI
0 "register_operand" "=r")
6690 (unspec:SI [(mem:SI (lo_sum:DI
6691 (match_operand:DI
1 "register_operand" "r")
6692 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6693 UNSPEC_GOTSMALLPIC28K)))]
6695 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
6696 [(set_attr "type" "load_4")]
6699 (define_insn "ldr_got_tiny"
6700 [(set (match_operand:DI
0 "register_operand" "=r")
6701 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
6702 UNSPEC_GOTTINYPIC))]
6705 [(set_attr "type" "load_8")]
6708 (define_insn "aarch64_load_tp_hard"
6709 [(set (match_operand:DI
0 "register_operand" "=r")
6710 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
6712 "mrs
\\t%
0, tpidr_el0"
6713 [(set_attr "type" "mrs")]
6716 ;; The TLS ABI specifically requires that the compiler does not schedule
6717 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6718 ;; Therefore we treat the stubs as an atomic sequence.
6719 (define_expand "tlsgd_small_<mode>"
6720 [(parallel [(set (match_operand
0 "register_operand")
6721 (call (mem:DI (match_dup
2)) (const_int
1)))
6722 (unspec:DI [(const_int
0)] UNSPEC_CALLEE_ABI)
6723 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
6724 (clobber (reg:DI LR_REGNUM))])]
6727 operands[
2] = aarch64_tls_get_addr ();
6730 (define_insn "*tlsgd_small_<mode>"
6731 [(set (match_operand
0 "register_operand" "")
6732 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
6733 (unspec:DI [(const_int
0)] UNSPEC_CALLEE_ABI)
6734 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6735 (clobber (reg:DI LR_REGNUM))
6738 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
6739 [(set_attr "type" "call")
6740 (set_attr "length" "
16")])
6742 (define_insn "tlsie_small_<mode>"
6743 [(set (match_operand:PTR
0 "register_operand" "=r")
6744 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6745 UNSPEC_GOTSMALLTLS))]
6747 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
6748 [(set_attr "type" "load_4")
6749 (set_attr "length" "
8")]
6752 (define_insn "tlsie_small_sidi"
6753 [(set (match_operand:DI
0 "register_operand" "=r")
6755 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6756 UNSPEC_GOTSMALLTLS)))]
6758 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
6759 [(set_attr "type" "load_4")
6760 (set_attr "length" "
8")]
6763 (define_insn "tlsie_tiny_<mode>"
6764 [(set (match_operand:PTR
0 "register_operand" "=&r")
6765 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
6766 (match_operand:PTR
2 "register_operand" "r")]
6767 UNSPEC_GOTTINYTLS))]
6769 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
6770 [(set_attr "type" "multiple")
6771 (set_attr "length" "
8")]
6774 (define_insn "tlsie_tiny_sidi"
6775 [(set (match_operand:DI
0 "register_operand" "=&r")
6777 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
6778 (match_operand:DI
2 "register_operand" "r")
6780 UNSPEC_GOTTINYTLS)))]
6782 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
6783 [(set_attr "type" "multiple")
6784 (set_attr "length" "
8")]
6787 (define_insn "tlsle12_<mode>"
6788 [(set (match_operand:P
0 "register_operand" "=r")
6789 (unspec:P [(match_operand:P
1 "register_operand" "r")
6790 (match_operand
2 "aarch64_tls_le_symref" "S")]
6793 "add
\\t%<w>
0, %<w>
1, #%L2";
6794 [(set_attr "type" "alu_sreg")
6795 (set_attr "length" "
4")]
6798 (define_insn "tlsle24_<mode>"
6799 [(set (match_operand:P
0 "register_operand" "=r")
6800 (unspec:P [(match_operand:P
1 "register_operand" "r")
6801 (match_operand
2 "aarch64_tls_le_symref" "S")]
6804 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
6805 [(set_attr "type" "multiple")
6806 (set_attr "length" "
8")]
6809 (define_insn "tlsle32_<mode>"
6810 [(set (match_operand:P
0 "register_operand" "=r")
6811 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6814 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6815 [(set_attr "type" "multiple")
6816 (set_attr "length" "
8")]
6819 (define_insn "tlsle48_<mode>"
6820 [(set (match_operand:P
0 "register_operand" "=r")
6821 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6824 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6825 [(set_attr "type" "multiple")
6826 (set_attr "length" "
12")]
6829 (define_expand "tlsdesc_small_<mode>"
6830 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6835 rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
6837 = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[
0], abi));
6838 RTL_CONST_CALL_P (call) =
1;
6841 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
6846 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6848 (define_insn "tlsdesc_small_advsimd_<mode>"
6849 [(set (reg:PTR R0_REGNUM)
6850 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6852 (clobber (reg:DI LR_REGNUM))
6853 (clobber (reg:CC CC_REGNUM))
6854 (clobber (match_scratch:DI
1 "=r"))
6855 (use (reg:DI FP_REGNUM))]
6856 "TARGET_TLS_DESC && !TARGET_SVE"
6857 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6858 [(set_attr "type" "call")
6859 (set_attr "length" "
16")])
6861 ;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
6862 ;; describing the extra call-preserved guarantees. This would work
6863 ;; for non-SVE too, but avoiding a call is probably better if we can.
6864 (define_insn "tlsdesc_small_sve_<mode>"
6865 [(set (reg:PTR R0_REGNUM)
6866 (call (mem:DI (unspec:PTR
6867 [(match_operand
0 "aarch64_valid_symref")]
6870 (unspec:DI [(match_operand:DI
1 "const_int_operand")] UNSPEC_CALLEE_ABI)
6871 (clobber (reg:DI LR_REGNUM))
6872 (clobber (match_scratch:DI
2 "=r"))]
6873 "TARGET_TLS_DESC && TARGET_SVE"
6874 "adrp
\\tx0, %A0\;ldr
\\t%<w>
2, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
2"
6875 [(set_attr "type" "call")
6876 (set_attr "length" "
16")])
6878 (define_insn "stack_tie"
6879 [(set (mem:BLK (scratch))
6880 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
6881 (match_operand:DI
1 "register_operand" "rk")]
6885 [(set_attr "length" "
0")]
6888 (define_insn "aarch64_fjcvtzs"
6889 [(set (match_operand:SI
0 "register_operand" "=r")
6890 (unspec:SI [(match_operand:DF
1 "register_operand" "w")]
6893 "fjcvtzs
\\t%w0, %d1"
6894 [(set_attr "type" "f_cvtf2i")]
6897 ;; Pointer authentication patterns are always provided. In architecture
6898 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6899 ;; This lets the user write portable software which authenticates pointers
6900 ;; when run on something which implements ARMv8.3-A, and which runs
6901 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6904 ;; Signing/Authenticating R30 using SP as the salt.
6906 (define_insn "<pauth_mnem_prefix>sp"
6907 [(set (reg:DI R30_REGNUM)
6908 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6910 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6913 ;; Signing/Authenticating X17 using X16 as the salt.
6915 (define_insn "<pauth_mnem_prefix>
1716"
6916 [(set (reg:DI R17_REGNUM)
6917 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6919 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>
1716";
6922 ;; Stripping the signature in R30.
6924 (define_insn "xpaclri"
6925 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6927 "hint
\t7 // xpaclri"
6930 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6931 ;; all of memory. This blocks insns from being moved across this point.
6933 (define_insn "blockage"
6934 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
6937 [(set_attr "length" "
0")
6938 (set_attr "type" "block")]
6941 (define_insn "probe_stack_range"
6942 [(set (match_operand:DI
0 "register_operand" "=rk")
6943 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
6944 (match_operand:DI
2 "register_operand" "r")]
6945 UNSPECV_PROBE_STACK_RANGE))]
6948 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
6950 [(set_attr "length" "
32")]
6953 ;; This instruction is used to generate the stack clash stack adjustment and
6954 ;; probing loop. We can't change the control flow during prologue and epilogue
6955 ;; code generation. So we must emit a volatile unspec and expand it later on.
6957 (define_insn "@probe_sve_stack_clash_<mode>"
6958 [(set (match_operand:P
0 "register_operand" "=rk")
6959 (unspec_volatile:P [(match_operand:P
1 "register_operand" "
0")
6960 (match_operand:P
2 "register_operand" "r")
6961 (match_operand:P
3 "const_int_operand" "n")
6962 (match_operand:P
4 "aarch64_plus_immediate" "L")]
6963 UNSPECV_PROBE_STACK_RANGE))]
6966 return aarch64_output_probe_sve_stack_clash (operands[
0], operands[
2],
6967 operands[
3], operands[
4]);
6969 [(set_attr "length" "
28")]
6972 ;; Named pattern for expanding thread pointer reference.
6973 (define_expand "get_thread_pointerdi"
6974 [(match_operand:DI
0 "register_operand")]
6977 rtx tmp = aarch64_load_tp (operands[
0]);
6978 if (tmp != operands[
0])
6979 emit_move_insn (operands[
0], tmp);
6983 ;; Named patterns for stack smashing protection.
6984 (define_expand "stack_protect_set"
6985 [(match_operand
0 "memory_operand")
6986 (match_operand
1 "memory_operand")]
6989 machine_mode mode = GET_MODE (operands[
0]);
6990 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6992 /* Generate access through the system register. */
6993 rtx tmp_reg = gen_reg_rtx (mode);
6996 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6997 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6998 GEN_INT (aarch64_stack_protector_guard_offset)));
7002 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
7003 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
7004 GEN_INT (aarch64_stack_protector_guard_offset)));
7007 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
7010 emit_insn ((mode == DImode
7011 ? gen_stack_protect_set_di
7012 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
7016 (define_insn "reg_stack_protect_address_<mode>"
7017 [(set (match_operand:PTR
0 "register_operand" "=r")
7018 (unspec:PTR [(const_int
0)]
7019 UNSPEC_SSP_SYSREG))]
7020 "aarch64_stack_protector_guard != SSP_GLOBAL"
7023 snprintf (buf,
150, "mrs
\\t%%<w>
0, %s",
7024 aarch64_stack_protector_guard_reg_str);
7025 output_asm_insn (buf, operands);
7028 [(set_attr "type" "mrs")])
7030 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
7031 ;; canary value does not live beyond the life of this sequence.
7032 (define_insn "stack_protect_set_<mode>"
7033 [(set (match_operand:PTR
0 "memory_operand" "=m")
7034 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
7036 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
7038 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
7039 [(set_attr "length" "
12")
7040 (set_attr "type" "multiple")])
7042 (define_expand "stack_protect_test"
7043 [(match_operand
0 "memory_operand")
7044 (match_operand
1 "memory_operand")
7049 machine_mode mode = GET_MODE (operands[
0]);
7051 result = gen_reg_rtx(mode);
7052 if (aarch64_stack_protector_guard != SSP_GLOBAL)
7054 /* Generate access through the system register. The
7055 sequence we want here is the access
7056 of the stack offset to come with
7057 mrs scratch_reg, <system_register>
7058 add scratch_reg, scratch_reg, :lo12:offset. */
7059 rtx tmp_reg = gen_reg_rtx (mode);
7062 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
7063 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
7064 GEN_INT (aarch64_stack_protector_guard_offset)));
7068 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
7069 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
7070 GEN_INT (aarch64_stack_protector_guard_offset)));
7073 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
7075 emit_insn ((mode == DImode
7076 ? gen_stack_protect_test_di
7077 : gen_stack_protect_test_si) (result,
7082 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7083 result, const0_rtx, operands[
2]));
7085 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7086 result, const0_rtx, operands[
2]));
7090 (define_insn "stack_protect_test_<mode>"
7091 [(set (match_operand:PTR
0 "register_operand" "=r")
7092 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
7093 (match_operand:PTR
2 "memory_operand" "m")]
7095 (clobber (match_scratch:PTR
3 "=&r"))]
7097 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
7098 [(set_attr "length" "
12")
7099 (set_attr "type" "multiple")])
7101 ;; Write Floating-point Control Register.
7102 (define_insn "set_fpcr"
7103 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
7106 [(set_attr "type" "mrs")])
7108 ;; Read Floating-point Control Register.
7109 (define_insn "get_fpcr"
7110 [(set (match_operand:SI
0 "register_operand" "=r")
7111 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
7114 [(set_attr "type" "mrs")])
7116 ;; Write Floating-point Status Register.
7117 (define_insn "set_fpsr"
7118 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
7121 [(set_attr "type" "mrs")])
7123 ;; Read Floating-point Status Register.
7124 (define_insn "get_fpsr"
7125 [(set (match_operand:SI
0 "register_operand" "=r")
7126 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
7129 [(set_attr "type" "mrs")])
7132 ;; Define the subtract-one-and-jump insns so loop.c
7133 ;; knows what to generate.
7134 (define_expand "doloop_end"
7135 [(use (match_operand
0 "" "")) ; loop pseudo
7136 (use (match_operand
1 "" ""))] ; label
7137 "optimize >
0 && flag_modulo_sched"
7146 /* Currently SMS relies on the do-loop pattern to recognize loops
7147 where (
1) the control part consists of all insns defining and/or
7148 using a certain 'count' register and (
2) the loop count can be
7149 adjusted by modifying this register prior to the loop.
7150 ??? The possible introduction of a new block to initialize the
7151 new IV can potentially affect branch optimizations. */
7153 if (GET_MODE (operands[
0]) != DImode)
7157 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
7159 cmp = XVECEXP (PATTERN (insn),
0,
0);
7160 cc_reg = SET_DEST (cmp);
7161 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7162 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
7163 emit_jump_insn (gen_rtx_SET (pc_rtx,
7164 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7169 ;; Track speculation through conditional branches. We assume that
7170 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7171 (define_insn "speculation_tracker"
7172 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7173 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand
0)]
7174 UNSPEC_SPECULATION_TRACKER))]
7177 operands[
1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7178 output_asm_insn ("csel
\\t%
1, %
1, xzr, %m0", operands);
7181 [(set_attr "type" "csel")]
7184 ;; BTI <target> instructions
7185 (define_insn "bti_noarg"
7186 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_NOARG)]
7189 [(set_attr "type" "no_insn")]
7192 (define_insn "bti_c"
7193 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_C)]
7196 [(set_attr "type" "no_insn")]
7199 (define_insn "bti_j"
7200 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_J)]
7203 [(set_attr "type" "no_insn")]
7206 (define_insn "bti_jc"
7207 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_JC)]
7209 "hint
\t38 // bti jc"
7210 [(set_attr "type" "no_insn")]
7213 ;; Hard speculation barrier.
7214 (define_insn "speculation_barrier"
7215 [(unspec_volatile [(const_int
0)] UNSPECV_SPECULATION_BARRIER)]
7218 [(set_attr "length" "
8")
7219 (set_attr "type" "block")
7220 (set_attr "speculation_barrier" "true")]
7223 ;; Support for __builtin_speculation_safe_value when we have speculation
7224 ;; tracking enabled. Use the speculation tracker to decide whether to
7225 ;; copy operand
1 to the target, or to copy the fail value (operand
2).
7226 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7227 [(set (match_operand:ALLI_TI
0 "register_operand")
7228 (unspec_volatile:ALLI_TI
7229 [(match_operand:ALLI_TI
1 "register_operand")
7230 (match_operand:ALLI_TI
2 "aarch64_reg_or_zero")
7231 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7232 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7236 if (operands[
2] == const0_rtx)
7239 if (<MODE>mode == TImode)
7240 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7242 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7244 emit_insn (gen_despeculate_simple<mode> (operands[
0], operands[
1],
7252 ;; Patterns to match despeculate_copy<mode>. Note that "hint
0x14" is the
7253 ;; encoding for CSDB, but will work in older versions of the assembler.
7254 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7255 [(set (match_operand:ALLI
0 "register_operand" "=r")
7256 (unspec_volatile:ALLI
7257 [(match_operand:ALLI
1 "register_operand" "r")
7258 (match_operand:ALLI
2 "aarch64_reg_or_zero" "rZ")
7259 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7260 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7263 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7264 output_asm_insn ("cmp
\\t%
3, #
0\;csel
\\t%<w>
0, %<w>
1, %<w>
2, ne\;hint
\t0x14 // csdb",
7268 [(set_attr "length" "
12")
7269 (set_attr "type" "block")
7270 (set_attr "speculation_barrier" "true")]
7273 ;; Pattern to match despeculate_copyti
7274 (define_insn "*despeculate_copyti_insn"
7275 [(set (match_operand:TI
0 "register_operand" "=r")
7277 [(match_operand:TI
1 "register_operand" "r")
7278 (match_operand:TI
2 "aarch64_reg_or_zero" "rZ")
7279 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7280 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7283 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7285 ("cmp
\\t%
3, #
0\;csel
\\t%
0, %
1, %
2, ne\;csel
\\t%H0, %H1, %H2, ne\;hint
\t0x14 // csdb",
7289 [(set_attr "length" "
16")
7290 (set_attr "type" "block")
7291 (set_attr "speculation_barrier" "true")]
7294 (define_insn "despeculate_simple<ALLI:mode>"
7295 [(set (match_operand:ALLI
0 "register_operand" "=r")
7296 (unspec_volatile:ALLI
7297 [(match_operand:ALLI
1 "register_operand" "r")
7298 (use (match_operand:ALLI
2 "register_operand" ""))]
7299 UNSPECV_SPECULATION_BARRIER))]
7301 "and
\\t%<w>
0, %<w>
1, %<w>
2\;hint
\t0x14 // csdb"
7302 [(set_attr "type" "block")
7303 (set_attr "length" "
8")
7304 (set_attr "speculation_barrier" "true")]
7307 (define_insn "despeculate_simpleti"
7308 [(set (match_operand:TI
0 "register_operand" "=r")
7310 [(match_operand:TI
1 "register_operand" "r")
7311 (use (match_operand:DI
2 "register_operand" ""))]
7312 UNSPECV_SPECULATION_BARRIER))]
7314 "and
\\t%
0, %
1, %
2\;and
\\t%H0, %H1, %
2\;hint
\t0x14 // csdb"
7315 [(set_attr "type" "block")
7316 (set_attr "length" "
12")
7317 (set_attr "speculation_barrier" "true")]
7320 (define_insn "aarch64_<frintnzs_op><mode>"
7321 [(set (match_operand:VSFDF
0 "register_operand" "=w")
7322 (unspec:VSFDF [(match_operand:VSFDF
1 "register_operand" "w")]
7324 "TARGET_FRINT && TARGET_FLOAT
7325 && !(VECTOR_MODE_P (<MODE>mode) && !TARGET_SIMD)"
7326 "<frintnzs_op>
\\t%<v>
0<Vmtype>, %<v>
1<Vmtype>"
7327 [(set_attr "type" "f_rint<stype>")]
7330 ;; Transactional Memory Extension (TME) instructions.
7332 (define_insn "tstart"
7333 [(set (match_operand:DI
0 "register_operand" "=r")
7334 (unspec_volatile:DI [(const_int
0)] UNSPECV_TSTART))
7335 (clobber (mem:BLK (scratch)))]
7338 [(set_attr "type" "tme")]
7341 (define_insn "ttest"
7342 [(set (match_operand:DI
0 "register_operand" "=r")
7343 (unspec_volatile:DI [(const_int
0)] UNSPEC_TTEST))
7344 (clobber (mem:BLK (scratch)))]
7347 [(set_attr "type" "tme")]
7350 (define_insn "tcommit"
7351 [(unspec_volatile:BLK [(const_int
0)] UNSPECV_TCOMMIT)
7352 (clobber (mem:BLK (scratch)))]
7355 [(set_attr "type" "tme")]
7358 (define_insn "tcancel"
7359 [(unspec_volatile:BLK
7360 [(match_operand
0 "const_int_operand" "n")] UNSPECV_TCANCEL)
7361 (clobber (mem:BLK (scratch)))]
7362 "TARGET_TME && (UINTVAL (operands[
0]) <=
65535)"
7364 [(set_attr "type" "tme")]
7367 (define_insn "aarch64_rndr"
7368 [(set (match_operand:DI
0 "register_operand" "=r")
7369 (unspec_volatile:DI [(const_int
0)] UNSPEC_RNDR))
7370 (set (reg:CC_Z CC_REGNUM)
7371 (unspec_volatile:CC_Z [(const_int
0)] UNSPEC_RNDR))]
7374 [(set_attr "type" "mrs")]
7377 (define_insn "aarch64_rndrrs"
7378 [(set (match_operand:DI
0 "register_operand" "=r")
7379 (unspec_volatile:DI [(const_int
0)] UNSPEC_RNDRRS))
7380 (set (reg:CC_Z CC_REGNUM)
7381 (unspec_volatile:CC_Z [(const_int
0)] UNSPEC_RNDRRS))]
7384 [(set_attr "type" "mrs")]
7388 (include "aarch64-simd.md")
7390 ;; Atomic Operations
7391 (include "atomics.md")
7393 ;; ldp/stp peephole patterns
7394 (include "aarch64-ldpstp.md")
7397 (include "aarch64-sve.md")
7400 (include "aarch64-sve2.md")