1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C)
2009-
2019 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version
3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
88 (LAST_SAVED_REGNUM
63)
92 ;; Defined only to make the DWARF description simpler.
110 ;; Scratch register used by stack clash protection to calculate
111 ;; SVE CFA offsets during probing.
112 (STACK_CLASH_SVE_CFA_REGNUM
11)
113 ;; Scratch registers for prologue/epilogue use.
116 ;; A couple of call-clobbered registers that we need to reserve when
117 ;; tracking speculation this is not ABI, so is subject to change.
118 (SPECULATION_SCRATCH_REGNUM
14)
119 (SPECULATION_TRACKER_REGNUM
15)
120 ;; Scratch registers used in frame layout.
128 (define_c_enum "unspec" [
160 UNSPEC_GOTSMALLPIC28K
242 UNSPEC_SPECULATION_TRACKER
244 UNSPEC_TTEST ; Represent transaction test.
247 (define_c_enum "unspecv" [
248 UNSPECV_EH_RETURN ; Represent EH_RETURN
249 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
250 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
251 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
252 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
253 UNSPECV_BLOCKAGE ; Represent a blockage
254 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
255 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
256 UNSPECV_BTI_NOARG ; Represent BTI.
257 UNSPECV_BTI_C ; Represent BTI c.
258 UNSPECV_BTI_J ; Represent BTI j.
259 UNSPECV_BTI_JC ; Represent BTI jc.
260 UNSPECV_TSTART ; Represent transaction start.
261 UNSPECV_TCOMMIT ; Represent transaction commit.
262 UNSPECV_TCANCEL ; Represent transaction cancel.
266 ;; These constants are used as a const_int in various SVE unspecs
267 ;; to indicate whether the governing predicate is known to be a PTRUE.
269 [; Indicates that the predicate might not be a PTRUE.
270 (SVE_MAYBE_NOT_PTRUE
0)
272 ; Indicates that the predicate is known to be a PTRUE.
273 (SVE_KNOWN_PTRUE
1)])
275 ;; These constants are used as a const_int in predicated SVE FP arithmetic
276 ;; to indicate whether the operation is allowed to make additional lanes
277 ;; active without worrying about the effect on faulting behavior.
279 [; Indicates either that all lanes are active or that the instruction may
280 ; operate on inactive inputs even if doing so could induce a fault.
283 ; Indicates that some lanes might be inactive and that the instruction
284 ; must not operate on inactive inputs if doing so could induce a fault.
287 ;; If further include files are added the defintion of MD_INCLUDES
290 (include "constraints.md")
291 (include "predicates.md")
292 (include "iterators.md")
294 ;; -------------------------------------------------------------------
295 ;; Instruction types and attributes
296 ;; -------------------------------------------------------------------
298 ; The "type" attribute is included here from AArch32 backend to be able
299 ; to share pipeline descriptions.
300 (include "../arm/types.md")
302 ;; It is important to set the fp or simd attributes to yes when a pattern
303 ;; alternative uses the FP or SIMD register files, usually signified by use of
304 ;; the 'w' constraint. This will ensure that the alternative will be
305 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
306 ;; architecture extensions. If all the alternatives in a pattern use the
307 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
310 ;; Attributes of the architecture required to support the instruction (or
311 ;; alternative). This attribute is used to compute attribute "enabled", use type
312 ;; "any" to enable an alternative in all cases.
314 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
316 (define_enum_attr "arch" "arches" (const_string "any"))
318 ;; [For compatibility with Arm in pipeline models]
319 ;; Attribute that specifies whether or not the instruction touches fp
321 ;; Note that this attribute is not used anywhere in either the arm or aarch64
322 ;; backends except in the scheduling description for xgene1. In that
323 ;; scheduling description this attribute is used to subclass the load_4 and
325 (define_attr "fp" "no,yes"
327 (eq_attr "arch" "fp")
329 (const_string "no")))
331 (define_attr "arch_enabled" "no,yes"
334 (eq_attr "arch" "any")
336 (and (eq_attr "arch" "rcpc8_4")
337 (match_test "AARCH64_ISA_RCPC8_4"))
339 (and (eq_attr "arch" "fp")
340 (match_test "TARGET_FLOAT"))
342 (and (eq_attr "arch" "simd")
343 (match_test "TARGET_SIMD"))
345 (and (eq_attr "arch" "fp16")
346 (match_test "TARGET_FP_F16INST"))
348 (and (eq_attr "arch" "sve")
349 (match_test "TARGET_SVE")))
351 (const_string "no")))
353 ;; Attribute that controls whether an alternative is enabled or not.
354 ;; Currently it is only used to disable alternatives which touch fp or simd
355 ;; registers when -mgeneral-regs-only is specified or to require a special
356 ;; architecture support.
357 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
359 ;; Attribute that specifies whether we are dealing with a branch to a
360 ;; label that is far away, i.e. further away than the maximum/minimum
361 ;; representable in a signed
21-bits number.
364 (define_attr "far_branch" "" (const_int
0))
366 ;; Attribute that specifies whether the alternative uses MOVPRFX.
367 (define_attr "movprfx" "no,yes" (const_string "no"))
369 (define_attr "length" ""
370 (cond [(eq_attr "movprfx" "yes")
374 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
375 ;; no predicated insns.
376 (define_attr "predicated" "yes,no" (const_string "no"))
378 ;; Set to true on an insn that requires the speculation tracking state to be
379 ;; in the tracking register before the insn issues. Otherwise the compiler
380 ;; may chose to hold the tracking state encoded in SP.
381 (define_attr "speculation_barrier" "true,false" (const_string "false"))
383 ;; -------------------------------------------------------------------
384 ;; Pipeline descriptions and scheduling
385 ;; -------------------------------------------------------------------
388 (include "aarch64-tune.md")
391 (include "../arm/cortex-a53.md")
392 (include "../arm/cortex-a57.md")
393 (include "../arm/exynos-m1.md")
394 (include "falkor.md")
395 (include "saphira.md")
396 (include "thunderx.md")
397 (include "../arm/xgene1.md")
398 (include "thunderx2t99.md")
399 (include "tsv110.md")
401 ;; -------------------------------------------------------------------
402 ;; Jumps and other miscellaneous insns
403 ;; -------------------------------------------------------------------
405 (define_insn "indirect_jump"
406 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
409 [(set_attr "type" "branch")]
413 [(set (pc) (label_ref (match_operand
0 "" "")))]
416 [(set_attr "type" "branch")]
419 (define_expand "cbranch<mode>
4"
420 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
421 [(match_operand:GPI
1 "register_operand")
422 (match_operand:GPI
2 "aarch64_plus_operand")])
423 (label_ref (match_operand
3 "" ""))
427 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
429 operands[
2] = const0_rtx;
433 (define_expand "cbranch<mode>
4"
434 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
435 [(match_operand:GPF
1 "register_operand")
436 (match_operand:GPF
2 "aarch64_fp_compare_operand")])
437 (label_ref (match_operand
3 "" ""))
441 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
443 operands[
2] = const0_rtx;
447 (define_expand "cbranchcc4"
448 [(set (pc) (if_then_else
449 (match_operator
0 "aarch64_comparison_operator"
450 [(match_operand
1 "cc_register")
451 (match_operand
2 "const0_operand")])
452 (label_ref (match_operand
3 "" ""))
457 (define_insn "ccmp<mode>"
458 [(set (match_operand:CC
1 "cc_register" "")
460 (match_operator
4 "aarch64_comparison_operator"
461 [(match_operand
0 "cc_register" "")
464 (match_operand:GPI
2 "register_operand" "r,r,r")
465 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
466 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
469 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
470 ccmp
\\t%<w>
2, %
3, %k5, %m4
471 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
472 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
475 (define_insn "fccmp<mode>"
476 [(set (match_operand:CCFP
1 "cc_register" "")
478 (match_operator
4 "aarch64_comparison_operator"
479 [(match_operand
0 "cc_register" "")
482 (match_operand:GPF
2 "register_operand" "w")
483 (match_operand:GPF
3 "register_operand" "w"))
484 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
486 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
487 [(set_attr "type" "fccmp<s>")]
490 (define_insn "fccmpe<mode>"
491 [(set (match_operand:CCFPE
1 "cc_register" "")
493 (match_operator
4 "aarch64_comparison_operator"
494 [(match_operand
0 "cc_register" "")
497 (match_operand:GPF
2 "register_operand" "w")
498 (match_operand:GPF
3 "register_operand" "w"))
499 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
501 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
502 [(set_attr "type" "fccmp<s>")]
505 ;; Expansion of signed mod by a power of
2 using CSNEG.
506 ;; For x0 % n where n is a power of
2 produce:
508 ;; and x0, x0, #(n -
1)
509 ;; and x1, x1, #(n -
1)
510 ;; csneg x0, x0, x1, mi
512 (define_expand "mod<mode>
3"
513 [(match_operand:GPI
0 "register_operand")
514 (match_operand:GPI
1 "register_operand")
515 (match_operand:GPI
2 "const_int_operand")]
518 HOST_WIDE_INT val = INTVAL (operands[
2]);
521 || exact_log2 (val) <=
0
522 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
525 rtx mask = GEN_INT (val -
1);
527 /* In the special case of x0 %
2 we can do the even shorter:
533 rtx masked = gen_reg_rtx (<MODE>mode);
534 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
535 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
536 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
537 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
541 rtx neg_op = gen_reg_rtx (<MODE>mode);
542 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
544 /* Extract the condition register and mode. */
545 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
546 rtx cc_reg = SET_DEST (cmp);
547 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
549 rtx masked_pos = gen_reg_rtx (<MODE>mode);
550 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
552 rtx masked_neg = gen_reg_rtx (<MODE>mode);
553 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
555 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
556 masked_neg, masked_pos));
561 (define_insn "condjump"
562 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
563 [(match_operand
1 "cc_register" "") (const_int
0)])
564 (label_ref (match_operand
2 "" ""))
568 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
569 but the "." is required for SVE conditions. */
570 bool use_dot_p = GET_MODE (operands[
1]) == CC_NZCmode;
571 if (get_attr_length (insn) ==
8)
572 return aarch64_gen_far_branch (operands,
2, "Lbcond",
573 use_dot_p ? "b.%M0
\\t" : "b%M0
\\t");
575 return use_dot_p ? "b.%m0
\\t%l2" : "b%m0
\\t%l2";
577 [(set_attr "type" "branch")
579 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
580 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
583 (set (attr "far_branch")
584 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
585 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
590 ;; For a
24-bit immediate CST we can optimize the compare for equality
591 ;; and branch sequence from:
593 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
597 ;; sub x0, x1, #(CST &
0xfff000)
598 ;; subs x0, x0, #(CST &
0x000fff)
600 (define_insn_and_split "*compare_condjump<GPI:mode>"
601 [(set (pc) (if_then_else (EQL
602 (match_operand:GPI
0 "register_operand" "r")
603 (match_operand:GPI
1 "aarch64_imm24" "n"))
604 (label_ref:P (match_operand
2 "" ""))
606 "!aarch64_move_imm (INTVAL (operands[
1]), <GPI:MODE>mode)
607 && !aarch64_plus_operand (operands[
1], <GPI:MODE>mode)
608 && !reload_completed"
613 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
614 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
615 rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
616 emit_insn (gen_add<GPI:mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
617 emit_insn (gen_add<GPI:mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
618 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
619 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
621 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
626 (define_expand "casesi"
627 [(match_operand:SI
0 "register_operand") ; Index
628 (match_operand:SI
1 "const_int_operand") ; Lower bound
629 (match_operand:SI
2 "const_int_operand") ; Total range
630 (match_operand:DI
3 "" "") ; Table label
631 (match_operand:DI
4 "" "")] ; Out of range label
634 if (operands[
1] != const0_rtx)
636 rtx reg = gen_reg_rtx (SImode);
638 /* Canonical RTL says that if you have:
642 then this should be emitted as:
646 The use of trunc_int_for_mode ensures that the resulting
647 constant can be represented in SImode, this is important
648 for the corner case where operand[
1] is INT_MIN. */
650 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
652 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
653 (operands[
1], SImode))
654 operands[
1] = force_reg (SImode, operands[
1]);
655 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
659 if (!aarch64_plus_operand (operands[
2], SImode))
660 operands[
2] = force_reg (SImode, operands[
2]);
661 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
663 operands[
0], operands[
2], operands[
4]));
665 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
667 = gen_rtx_UNSPEC (Pmode, gen_rtvec (
2, operands[
2], operands[
0]),
669 operands[
2] = gen_rtx_MEM (DImode, operands[
2]);
670 MEM_READONLY_P (operands[
2]) =
1;
671 MEM_NOTRAP_P (operands[
2]) =
1;
672 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
3]));
677 (define_expand "casesi_dispatch"
679 [(set (pc) (match_operand:DI
0 ""))
680 (clobber (reg:CC CC_REGNUM))
681 (clobber (match_scratch:DI
2))
682 (clobber (match_scratch:DI
3))
683 (use (label_ref:DI (match_operand
1 "")))])]
686 (define_insn "*casesi_dispatch"
689 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
690 (match_operand:SI
1 "register_operand" "r")]
692 (clobber (reg:CC CC_REGNUM))
693 (clobber (match_scratch:DI
3 "=r"))
694 (clobber (match_scratch:DI
4 "=r"))
695 (use (label_ref:DI (match_operand
2 "" "")))])]
698 return aarch64_output_casesi (operands);
700 [(set_attr "length" "
16")
701 (set_attr "type" "branch")]
705 [(unspec[(const_int
0)] UNSPEC_NOP)]
708 [(set_attr "type" "no_insn")]
711 (define_insn "prefetch"
712 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
713 (match_operand:QI
1 "const_int_operand" "")
714 (match_operand:QI
2 "const_int_operand" ""))]
717 const char * pftype[
2][
4] =
719 {"prfm
\\tPLDL1STRM, %
0",
720 "prfm
\\tPLDL3KEEP, %
0",
721 "prfm
\\tPLDL2KEEP, %
0",
722 "prfm
\\tPLDL1KEEP, %
0"},
723 {"prfm
\\tPSTL1STRM, %
0",
724 "prfm
\\tPSTL3KEEP, %
0",
725 "prfm
\\tPSTL2KEEP, %
0",
726 "prfm
\\tPSTL1KEEP, %
0"},
729 int locality = INTVAL (operands[
2]);
731 gcc_assert (IN_RANGE (locality,
0,
3));
733 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
734 the address into a DImode MEM so that aarch64_print_operand knows
736 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
737 return pftype[INTVAL(operands[
1])][locality];
739 [(set_attr "type" "load_4")]
743 [(trap_if (const_int
1) (const_int
8))]
746 [(set_attr "type" "trap")])
748 (define_expand "prologue"
749 [(clobber (const_int
0))]
752 aarch64_expand_prologue ();
757 (define_expand "epilogue"
758 [(clobber (const_int
0))]
761 aarch64_expand_epilogue (false);
766 (define_expand "sibcall_epilogue"
767 [(clobber (const_int
0))]
770 aarch64_expand_epilogue (true);
775 (define_insn "*do_return"
779 if (aarch64_return_address_signing_enabled ()
781 && !crtl->calls_eh_return)
783 if (aarch64_ra_sign_key == AARCH64_KEY_B)
790 [(set_attr "type" "branch")]
793 (define_expand "return"
795 "aarch64_use_return_insn_p ()"
799 (define_insn "simple_return"
801 "aarch64_use_simple_return_insn_p ()"
803 [(set_attr "type" "branch")]
806 (define_insn "*cb<optab><mode>
1"
807 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
809 (label_ref (match_operand
1 "" ""))
811 "!aarch64_track_speculation"
813 if (get_attr_length (insn) ==
8)
814 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
816 return "<cbz>
\\t%<w>
0, %l1";
818 [(set_attr "type" "branch")
820 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
821 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
824 (set (attr "far_branch")
825 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
826 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
831 (define_insn "*tb<optab><mode>
1"
832 [(set (pc) (if_then_else
833 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
836 "aarch64_simd_shift_imm_<mode>" "n"))
838 (label_ref (match_operand
2 "" ""))
840 (clobber (reg:CC CC_REGNUM))]
841 "!aarch64_track_speculation"
843 if (get_attr_length (insn) ==
8)
845 if (get_attr_far_branch (insn) ==
1)
846 return aarch64_gen_far_branch (operands,
2, "Ltb",
847 "<inv_tb>
\\t%<w>
0, %
1, ");
850 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
851 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
855 return "<tbz>
\t%<w>
0, %
1, %l2";
857 [(set_attr "type" "branch")
859 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
860 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
863 (set (attr "far_branch")
864 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
865 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
871 (define_insn "*cb<optab><mode>
1"
872 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
874 (label_ref (match_operand
1 "" ""))
876 (clobber (reg:CC CC_REGNUM))]
877 "!aarch64_track_speculation"
879 if (get_attr_length (insn) ==
8)
881 if (get_attr_far_branch (insn) ==
1)
882 return aarch64_gen_far_branch (operands,
1, "Ltb",
883 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
887 uint64_t val = ((uint64_t)
1)
888 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
889 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
890 output_asm_insn (buf, operands);
891 return "<bcond>
\t%l1";
895 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
897 [(set_attr "type" "branch")
899 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
900 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
903 (set (attr "far_branch")
904 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
905 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
910 ;; -------------------------------------------------------------------
911 ;; Subroutine calls and sibcalls
912 ;; -------------------------------------------------------------------
914 (define_expand "call"
915 [(parallel [(call (match_operand
0 "memory_operand")
916 (match_operand
1 "general_operand"))
917 (use (match_operand
2 "" ""))
918 (clobber (reg:DI LR_REGNUM))])]
922 aarch64_expand_call (NULL_RTX, operands[
0], false);
927 (define_insn "*call_insn"
928 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
929 (match_operand
1 "" ""))
930 (clobber (reg:DI LR_REGNUM))]
935 [(set_attr "type" "call, call")]
938 (define_expand "call_value"
939 [(parallel [(set (match_operand
0 "" "")
940 (call (match_operand
1 "memory_operand")
941 (match_operand
2 "general_operand")))
942 (use (match_operand
3 "" ""))
943 (clobber (reg:DI LR_REGNUM))])]
947 aarch64_expand_call (operands[
0], operands[
1], false);
952 (define_insn "*call_value_insn"
953 [(set (match_operand
0 "" "")
954 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
955 (match_operand
2 "" "")))
956 (clobber (reg:DI LR_REGNUM))]
961 [(set_attr "type" "call, call")]
964 (define_expand "sibcall"
965 [(parallel [(call (match_operand
0 "memory_operand")
966 (match_operand
1 "general_operand"))
968 (use (match_operand
2 "" ""))])]
971 aarch64_expand_call (NULL_RTX, operands[
0], true);
976 (define_expand "sibcall_value"
977 [(parallel [(set (match_operand
0 "" "")
978 (call (match_operand
1 "memory_operand")
979 (match_operand
2 "general_operand")))
981 (use (match_operand
3 "" ""))])]
984 aarch64_expand_call (operands[
0], operands[
1], true);
989 (define_insn "*sibcall_insn"
990 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
991 (match_operand
1 "" ""))
993 "SIBLING_CALL_P (insn)"
997 [(set_attr "type" "branch, branch")]
1000 (define_insn "*sibcall_value_insn"
1001 [(set (match_operand
0 "" "")
1003 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
1004 (match_operand
2 "" "")))
1006 "SIBLING_CALL_P (insn)"
1010 [(set_attr "type" "branch, branch")]
1013 ;; Call subroutine returning any type.
1015 (define_expand "untyped_call"
1016 [(parallel [(call (match_operand
0 "")
1018 (match_operand
1 "")
1019 (match_operand
2 "")])]
1024 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL));
1026 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
1028 rtx set = XVECEXP (operands[
2],
0, i);
1029 emit_move_insn (SET_DEST (set), SET_SRC (set));
1032 /* The optimizer does not know that the call sets the function value
1033 registers we stored in the result block. We avoid problems by
1034 claiming that all hard registers are used and clobbered at this
1036 emit_insn (gen_blockage ());
1040 ;; -------------------------------------------------------------------
1042 ;; -------------------------------------------------------------------
1044 (define_expand "mov<mode>"
1045 [(set (match_operand:SHORT
0 "nonimmediate_operand")
1046 (match_operand:SHORT
1 "general_operand"))]
1049 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1050 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1052 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1054 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1060 (define_insn "*mov<mode>_aarch64"
1061 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1062 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1063 "(register_operand (operands[
0], <MODE>mode)
1064 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
1066 switch (which_alternative)
1069 return "mov
\t%w0, %w1";
1071 return "mov
\t%w0, %
1";
1073 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
1076 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1078 return "ldr<size>
\t%w0, %
1";
1080 return "ldr
\t%<size>
0, %
1";
1082 return "str<size>
\t%w1, %
0";
1084 return "str
\t%<size>
1, %
0";
1086 return "umov
\t%w0, %
1.<v>[
0]";
1088 return "dup
\t%
0.<Vallxd>, %w1";
1090 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
1095 ;; The "mov_imm" type for CNT is just a placeholder.
1096 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1097 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1098 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1101 (define_expand "mov<mode>"
1102 [(set (match_operand:GPI
0 "nonimmediate_operand")
1103 (match_operand:GPI
1 "general_operand"))]
1106 if (MEM_P (operands[
0]) && CONST_INT_P (operands[
1])
1107 && <MODE>mode == DImode
1108 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
1111 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1112 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1114 /* FIXME: RR we still need to fix up what we are doing with
1115 symbol_refs and other types of constants. */
1116 if (CONSTANT_P (operands[
1])
1117 && !CONST_INT_P (operands[
1]))
1119 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1125 (define_insn_and_split "*movsi_aarch64"
1126 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1127 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1128 "(register_operand (operands[
0], SImode)
1129 || aarch64_reg_or_zero (operands[
1], SImode))"
1136 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1146 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1147 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1148 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1151 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1154 ;; The "mov_imm" type for CNT is just a placeholder.
1155 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1156 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1157 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1160 (define_insn_and_split "*movdi_aarch64"
1161 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1162 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1163 "(register_operand (operands[
0], DImode)
1164 || aarch64_reg_or_zero (operands[
1], DImode))"
1172 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1182 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1183 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1184 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1187 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1190 ;; The "mov_imm" type for CNTD is just a placeholder.
1191 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1192 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1194 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1197 (define_insn "insv_imm<mode>"
1198 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1200 (match_operand:GPI
1 "const_int_operand" "n"))
1201 (match_operand:GPI
2 "const_int_operand" "n"))]
1202 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1203 && UINTVAL (operands[
1]) %
16 ==
0"
1204 "movk
\\t%<w>
0, %X2, lsl %
1"
1205 [(set_attr "type" "mov_imm")]
1208 (define_expand "movti"
1209 [(set (match_operand:TI
0 "nonimmediate_operand")
1210 (match_operand:TI
1 "general_operand"))]
1213 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1214 operands[
1] = force_reg (TImode, operands[
1]);
1216 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1218 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1219 gen_lowpart (DImode, operands[
1]));
1220 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1226 (define_insn "*movti_aarch64"
1227 [(set (match_operand:TI
0
1228 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1230 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1231 "(register_operand (operands[
0], TImode)
1232 || aarch64_reg_or_zero (operands[
1], TImode))"
1237 mov
\\t%
0.16b, %
1.16b
1243 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1244 load_16,store_16,store_16,\
1246 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1247 (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
1250 ;; Split a TImode register-register or register-immediate move into
1251 ;; its component DImode pieces, taking care to handle overlapping
1252 ;; source and dest registers.
1254 [(set (match_operand:TI
0 "register_operand" "")
1255 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1256 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1259 aarch64_split_128bit_move (operands[
0], operands[
1]);
1263 (define_expand "mov<mode>"
1264 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand")
1265 (match_operand:GPF_TF_F16
1 "general_operand"))]
1270 aarch64_err_no_fpadvsimd (<MODE>mode);
1274 if (GET_CODE (operands[
0]) == MEM
1275 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1276 && aarch64_float_const_zero_rtx_p (operands[
1])))
1277 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1281 (define_insn "*movhf_aarch64"
1282 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1283 (match_operand:HF
1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1284 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1285 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1291 mov
\\t%
0.h[
0], %
1.h[
0]
1293 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1299 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1300 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1301 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1304 (define_insn "*movsf_aarch64"
1305 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1306 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1307 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1308 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1315 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1322 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1323 f_loads,f_stores,load_4,store_4,mov_reg,\
1325 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1328 (define_insn "*movdf_aarch64"
1329 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1330 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1331 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1332 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1339 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1346 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1347 f_loadd,f_stored,load_8,store_8,mov_reg,\
1349 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1353 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1354 (match_operand:GPF_HF
1 "general_operand"))]
1355 "can_create_pseudo_p ()
1356 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1357 && !aarch64_float_const_representable_p (operands[
1])
1358 && aarch64_float_const_rtx_p (operands[
1])"
1361 unsigned HOST_WIDE_INT ival;
1362 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1365 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1366 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1367 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1372 (define_insn "*movtf_aarch64"
1373 [(set (match_operand:TF
0
1374 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1376 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1377 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1378 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1380 mov
\\t%
0.16b, %
1.16b
1391 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1392 f_loadd,f_stored,load_16,store_16,store_16")
1393 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1394 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1398 [(set (match_operand:TF
0 "register_operand" "")
1399 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1400 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1403 aarch64_split_128bit_move (operands[
0], operands[
1]);
1410 ;;
2 is size of copy in bytes
1413 (define_expand "cpymemdi"
1414 [(match_operand:BLK
0 "memory_operand")
1415 (match_operand:BLK
1 "memory_operand")
1416 (match_operand:DI
2 "immediate_operand")
1417 (match_operand:DI
3 "immediate_operand")]
1420 if (aarch64_expand_cpymem (operands))
1426 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1427 ;; fairly lax checking on the second memory operation.
1428 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1429 [(set (match_operand:SX
0 "register_operand" "=r,w")
1430 (match_operand:SX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1431 (set (match_operand:SX2
2 "register_operand" "=r,w")
1432 (match_operand:SX2
3 "memory_operand" "m,m"))]
1433 "rtx_equal_p (XEXP (operands[
3],
0),
1434 plus_constant (Pmode,
1435 XEXP (operands[
1],
0),
1436 GET_MODE_SIZE (<SX:MODE>mode)))"
1440 [(set_attr "type" "load_8,neon_load1_2reg")
1441 (set_attr "arch" "*,fp")]
1444 ;; Storing different modes that can still be merged
1445 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1446 [(set (match_operand:DX
0 "register_operand" "=r,w")
1447 (match_operand:DX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1448 (set (match_operand:DX2
2 "register_operand" "=r,w")
1449 (match_operand:DX2
3 "memory_operand" "m,m"))]
1450 "rtx_equal_p (XEXP (operands[
3],
0),
1451 plus_constant (Pmode,
1452 XEXP (operands[
1],
0),
1453 GET_MODE_SIZE (<DX:MODE>mode)))"
1457 [(set_attr "type" "load_16,neon_load1_2reg")
1458 (set_attr "arch" "*,fp")]
1461 (define_insn "load_pair_dw_tftf"
1462 [(set (match_operand:TF
0 "register_operand" "=w")
1463 (match_operand:TF
1 "aarch64_mem_pair_operand" "Ump"))
1464 (set (match_operand:TF
2 "register_operand" "=w")
1465 (match_operand:TF
3 "memory_operand" "m"))]
1467 && rtx_equal_p (XEXP (operands[
3],
0),
1468 plus_constant (Pmode,
1469 XEXP (operands[
1],
0),
1470 GET_MODE_SIZE (TFmode)))"
1471 "ldp
\\t%q0, %q2, %
1"
1472 [(set_attr "type" "neon_ldp_q")
1473 (set_attr "fp" "yes")]
1476 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1477 ;; fairly lax checking on the second memory operation.
1478 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1479 [(set (match_operand:SX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1480 (match_operand:SX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1481 (set (match_operand:SX2
2 "memory_operand" "=m,m")
1482 (match_operand:SX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1483 "rtx_equal_p (XEXP (operands[
2],
0),
1484 plus_constant (Pmode,
1485 XEXP (operands[
0],
0),
1486 GET_MODE_SIZE (<SX:MODE>mode)))"
1490 [(set_attr "type" "store_8,neon_store1_2reg")
1491 (set_attr "arch" "*,fp")]
1494 ;; Storing different modes that can still be merged
1495 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1496 [(set (match_operand:DX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1497 (match_operand:DX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1498 (set (match_operand:DX2
2 "memory_operand" "=m,m")
1499 (match_operand:DX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1500 "rtx_equal_p (XEXP (operands[
2],
0),
1501 plus_constant (Pmode,
1502 XEXP (operands[
0],
0),
1503 GET_MODE_SIZE (<DX:MODE>mode)))"
1507 [(set_attr "type" "store_16,neon_store1_2reg")
1508 (set_attr "arch" "*,fp")]
1511 (define_insn "store_pair_dw_tftf"
1512 [(set (match_operand:TF
0 "aarch64_mem_pair_operand" "=Ump")
1513 (match_operand:TF
1 "register_operand" "w"))
1514 (set (match_operand:TF
2 "memory_operand" "=m")
1515 (match_operand:TF
3 "register_operand" "w"))]
1517 rtx_equal_p (XEXP (operands[
2],
0),
1518 plus_constant (Pmode,
1519 XEXP (operands[
0],
0),
1520 GET_MODE_SIZE (TFmode)))"
1521 "stp
\\t%q1, %q3, %
0"
1522 [(set_attr "type" "neon_stp_q")
1523 (set_attr "fp" "yes")]
1526 ;; Load pair with post-index writeback. This is primarily used in function
1528 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1530 [(set (match_operand:P
0 "register_operand" "=k")
1531 (plus:P (match_operand:P
1 "register_operand" "
0")
1532 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1533 (set (match_operand:GPI
2 "register_operand" "=r")
1534 (mem:GPI (match_dup
1)))
1535 (set (match_operand:GPI
3 "register_operand" "=r")
1536 (mem:GPI (plus:P (match_dup
1)
1537 (match_operand:P
5 "const_int_operand" "n"))))])]
1538 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1539 "ldp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
1], %
4"
1540 [(set_attr "type" "load_<GPI:ldpstp_sz>")]
1543 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1545 [(set (match_operand:P
0 "register_operand" "=k")
1546 (plus:P (match_operand:P
1 "register_operand" "
0")
1547 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1548 (set (match_operand:GPF
2 "register_operand" "=w")
1549 (mem:GPF (match_dup
1)))
1550 (set (match_operand:GPF
3 "register_operand" "=w")
1551 (mem:GPF (plus:P (match_dup
1)
1552 (match_operand:P
5 "const_int_operand" "n"))))])]
1553 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1554 "ldp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
1], %
4"
1555 [(set_attr "type" "neon_load1_2reg")]
1558 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1560 [(set (match_operand:P
0 "register_operand" "=k")
1561 (plus:P (match_operand:P
1 "register_operand" "
0")
1562 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1563 (set (match_operand:TX
2 "register_operand" "=w")
1564 (mem:TX (match_dup
1)))
1565 (set (match_operand:TX
3 "register_operand" "=w")
1566 (mem:TX (plus:P (match_dup
1)
1567 (match_operand:P
5 "const_int_operand" "n"))))])]
1568 "TARGET_SIMD && INTVAL (operands[
5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1569 "ldp
\\t%q2, %q3, [%
1], %
4"
1570 [(set_attr "type" "neon_ldp_q")]
1573 ;; Store pair with pre-index writeback. This is primarily used in function
1575 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1577 [(set (match_operand:P
0 "register_operand" "=&k")
1578 (plus:P (match_operand:P
1 "register_operand" "
0")
1579 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1580 (set (mem:GPI (plus:P (match_dup
0)
1582 (match_operand:GPI
2 "register_operand" "r"))
1583 (set (mem:GPI (plus:P (match_dup
0)
1584 (match_operand:P
5 "const_int_operand" "n")))
1585 (match_operand:GPI
3 "register_operand" "r"))])]
1586 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1587 "stp
\\t%<GPI:w>
2, %<GPI:w>
3, [%
0, %
4]!"
1588 [(set_attr "type" "store_<GPI:ldpstp_sz>")]
1591 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1593 [(set (match_operand:P
0 "register_operand" "=&k")
1594 (plus:P (match_operand:P
1 "register_operand" "
0")
1595 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1596 (set (mem:GPF (plus:P (match_dup
0)
1598 (match_operand:GPF
2 "register_operand" "w"))
1599 (set (mem:GPF (plus:P (match_dup
0)
1600 (match_operand:P
5 "const_int_operand" "n")))
1601 (match_operand:GPF
3 "register_operand" "w"))])]
1602 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1603 "stp
\\t%<GPF:w>
2, %<GPF:w>
3, [%
0, %
4]!"
1604 [(set_attr "type" "neon_store1_2reg<q>")]
1607 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1609 [(set (match_operand:P
0 "register_operand" "=&k")
1610 (plus:P (match_operand:P
1 "register_operand" "
0")
1611 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1612 (set (mem:TX (plus:P (match_dup
0)
1614 (match_operand:TX
2 "register_operand" "w"))
1615 (set (mem:TX (plus:P (match_dup
0)
1616 (match_operand:P
5 "const_int_operand" "n")))
1617 (match_operand:TX
3 "register_operand" "w"))])]
1619 && INTVAL (operands[
5])
1620 == INTVAL (operands[
4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1621 "stp
\\t%q2, %q3, [%
0, %
4]!"
1622 [(set_attr "type" "neon_stp_q")]
1625 ;; -------------------------------------------------------------------
1626 ;; Sign/Zero extension
1627 ;; -------------------------------------------------------------------
1629 (define_expand "<optab>sidi2"
1630 [(set (match_operand:DI
0 "register_operand")
1631 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1635 (define_insn "*extendsidi2_aarch64"
1636 [(set (match_operand:DI
0 "register_operand" "=r,r")
1637 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1642 [(set_attr "type" "extend,load_4")]
1645 (define_insn "*load_pair_extendsidi2_aarch64"
1646 [(set (match_operand:DI
0 "register_operand" "=r")
1647 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1648 (set (match_operand:DI
2 "register_operand" "=r")
1649 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1650 "rtx_equal_p (XEXP (operands[
3],
0),
1651 plus_constant (Pmode,
1652 XEXP (operands[
1],
0),
1653 GET_MODE_SIZE (SImode)))"
1654 "ldpsw
\\t%
0, %
2, %
1"
1655 [(set_attr "type" "load_8")]
1658 (define_insn "*zero_extendsidi2_aarch64"
1659 [(set (match_operand:DI
0 "register_operand" "=r,r,w,w,r,w")
1660 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1669 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1670 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1673 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1674 [(set (match_operand:DI
0 "register_operand" "=r,w")
1675 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump,Ump")))
1676 (set (match_operand:DI
2 "register_operand" "=r,w")
1677 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m,m")))]
1678 "rtx_equal_p (XEXP (operands[
3],
0),
1679 plus_constant (Pmode,
1680 XEXP (operands[
1],
0),
1681 GET_MODE_SIZE (SImode)))"
1685 [(set_attr "type" "load_8,neon_load1_2reg")
1686 (set_attr "arch" "*,fp")]
1689 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1690 [(set (match_operand:GPI
0 "register_operand")
1691 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1695 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1696 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1697 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1700 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1701 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1702 [(set_attr "type" "extend,load_4")]
1705 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1706 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1707 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1710 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1711 ldr<SHORT:size>
\t%w0, %
1
1712 ldr
\t%<SHORT:size>
0, %
1"
1713 [(set_attr "type" "logic_imm,load_4,f_loads")
1714 (set_attr "arch" "*,*,fp")]
1717 (define_expand "<optab>qihi2"
1718 [(set (match_operand:HI
0 "register_operand")
1719 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1723 (define_insn "*extendqihi2_aarch64"
1724 [(set (match_operand:HI
0 "register_operand" "=r,r")
1725 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1730 [(set_attr "type" "extend,load_4")]
1733 (define_insn "*zero_extendqihi2_aarch64"
1734 [(set (match_operand:HI
0 "register_operand" "=r,r")
1735 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1740 [(set_attr "type" "logic_imm,load_4")]
1743 ;; -------------------------------------------------------------------
1744 ;; Simple arithmetic
1745 ;; -------------------------------------------------------------------
1747 (define_expand "add<mode>
3"
1749 (match_operand:GPI
0 "register_operand")
1750 (plus:GPI (match_operand:GPI
1 "register_operand")
1751 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand")))]
1754 /* If operands[
1] is a subreg extract the inner RTX. */
1755 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1757 /* If the constant is too large for a single instruction and isn't frame
1758 based, split off the immediate so it is available for CSE. */
1759 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1760 && !(TARGET_SVE && aarch64_sve_plus_immediate (operands[
2], <MODE>mode))
1761 && can_create_pseudo_p ()
1763 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1764 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1765 /* Expand polynomial additions now if the destination is the stack
1766 pointer, since we don't want to use that as a temporary. */
1767 else if (operands[
0] == stack_pointer_rtx
1768 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1770 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1771 operands[
2], NULL_RTX, NULL_RTX);
1776 (define_insn "*add<mode>
3_aarch64"
1778 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,r,rk")
1780 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,
0,rk")
1781 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
1784 add
\\t%<w>
0, %<w>
1, %
2
1785 add
\\t%<w>
0, %<w>
1, %<w>
2
1786 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1787 sub
\\t%<w>
0, %<w>
1, #%n2
1789 * return aarch64_output_sve_scalar_inc_dec (operands[
2]);
1790 * return aarch64_output_sve_addvl_addpl (operands[
2]);"
1791 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1792 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm")
1793 (set_attr "arch" "*,*,simd,*,*,sve,sve")]
1796 ;; zero_extend version of above
1797 (define_insn "*addsi3_aarch64_uxtw"
1799 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1801 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1802 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1807 sub
\\t%w0, %w1, #%n2
1809 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1812 ;; If there's a free register, and we can load the constant with a
1813 ;; single instruction, do so. This has a chance to improve scheduling.
1815 [(match_scratch:GPI
3 "r")
1816 (set (match_operand:GPI
0 "register_operand")
1818 (match_operand:GPI
1 "register_operand")
1819 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1820 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1821 [(set (match_dup
3) (match_dup
2))
1822 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1826 [(match_scratch:SI
3 "r")
1827 (set (match_operand:DI
0 "register_operand")
1830 (match_operand:SI
1 "register_operand")
1831 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1832 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1833 [(set (match_dup
3) (match_dup
2))
1834 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1837 ;; After peephole2 has had a chance to run, split any remaining long
1838 ;; additions into two add immediates.
1840 [(set (match_operand:GPI
0 "register_operand")
1842 (match_operand:GPI
1 "register_operand")
1843 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1844 "epilogue_completed"
1845 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1846 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1848 HOST_WIDE_INT i = INTVAL (operands[
2]);
1849 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1850 operands[
3] = GEN_INT (i - s);
1851 operands[
4] = GEN_INT (s);
1855 ;; Match addition of polynomial offsets that require one temporary, for which
1856 ;; we can use the early-clobbered destination register. This is a separate
1857 ;; pattern so that the early clobber doesn't affect register allocation
1858 ;; for other forms of addition. However, we still need to provide an
1859 ;; all-register alternative, in case the offset goes out of range after
1860 ;; elimination. For completeness we might as well provide all GPR-based
1861 ;; alternatives from the main pattern.
1863 ;; We don't have a pattern for additions requiring two temporaries since at
1864 ;; present LRA doesn't allow new scratches to be added during elimination.
1865 ;; Such offsets should be rare anyway.
1867 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1868 ;; here would go away. We could just handle all polynomial constants in
1870 (define_insn_and_split "*add<mode>
3_poly_1"
1872 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,r,&r")
1874 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,
0,rk")
1875 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uai,Uat")))]
1876 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1878 add
\\t%<w>
0, %<w>
1, %
2
1879 add
\\t%<w>
0, %<w>
1, %<w>
2
1880 sub
\\t%<w>
0, %<w>
1, #%n2
1882 * return aarch64_output_sve_scalar_inc_dec (operands[
2]);
1883 * return aarch64_output_sve_addvl_addpl (operands[
2]);
1885 "&& epilogue_completed
1886 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1887 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1890 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1891 operands[
2], operands[
0], NULL_RTX);
1894 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1895 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,alu_imm,multiple")]
1899 [(set (match_operand:DI
0 "register_operand")
1902 (match_operand:SI
1 "register_operand")
1903 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1904 "epilogue_completed"
1905 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1906 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1908 HOST_WIDE_INT i = INTVAL (operands[
2]);
1909 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1910 operands[
3] = GEN_INT (i - s);
1911 operands[
4] = GEN_INT (s);
1912 operands[
5] = gen_lowpart (SImode, operands[
0]);
1916 (define_expand "addv<mode>
4"
1917 [(match_operand:GPI
0 "register_operand")
1918 (match_operand:GPI
1 "register_operand")
1919 (match_operand:GPI
2 "aarch64_plus_operand")
1920 (label_ref (match_operand
3 "" ""))]
1923 if (CONST_INT_P (operands[
2]))
1924 emit_insn (gen_add<mode>
3_compareV_imm (operands[
0], operands[
1],
1927 emit_insn (gen_add<mode>
3_compareV (operands[
0], operands[
1], operands[
2]));
1928 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1933 (define_expand "uaddv<mode>
4"
1934 [(match_operand:GPI
0 "register_operand")
1935 (match_operand:GPI
1 "register_operand")
1936 (match_operand:GPI
2 "register_operand")
1937 (label_ref (match_operand
3 "" ""))]
1940 emit_insn (gen_add<mode>
3_compareC (operands[
0], operands[
1], operands[
2]));
1941 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[
3]);
1946 (define_expand "addti3"
1947 [(set (match_operand:TI
0 "register_operand")
1948 (plus:TI (match_operand:TI
1 "register_operand")
1949 (match_operand:TI
2 "aarch64_reg_or_imm")))]
1952 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1954 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1955 &low_dest, &op1_low, &op2_low,
1956 &high_dest, &op1_high, &op2_high);
1958 if (op2_low == const0_rtx)
1961 if (!aarch64_pluslong_operand (op2_high, DImode))
1962 op2_high = force_reg (DImode, op2_high);
1963 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
1967 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1968 force_reg (DImode, op2_low)));
1969 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
1970 force_reg (DImode, op2_high)));
1973 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1974 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1979 (define_expand "addvti4"
1980 [(match_operand:TI
0 "register_operand")
1981 (match_operand:TI
1 "register_operand")
1982 (match_operand:TI
2 "aarch64_reg_or_imm")
1983 (label_ref (match_operand
3 "" ""))]
1986 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1988 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1989 &low_dest, &op1_low, &op2_low,
1990 &high_dest, &op1_high, &op2_high);
1992 if (op2_low == const0_rtx)
1995 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
1996 force_reg (DImode, op2_high)));
2000 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2001 force_reg (DImode, op2_low)));
2002 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
2003 force_reg (DImode, op2_high)));
2006 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2007 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2009 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2013 (define_expand "uaddvti4"
2014 [(match_operand:TI
0 "register_operand")
2015 (match_operand:TI
1 "register_operand")
2016 (match_operand:TI
2 "aarch64_reg_or_imm")
2017 (label_ref (match_operand
3 "" ""))]
2020 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2022 aarch64_addti_scratch_regs (operands[
1], operands[
2],
2023 &low_dest, &op1_low, &op2_low,
2024 &high_dest, &op1_high, &op2_high);
2026 if (op2_low == const0_rtx)
2029 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2030 force_reg (DImode, op2_high)));
2034 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2035 force_reg (DImode, op2_low)));
2036 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2037 force_reg (DImode, op2_high)));
2040 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2041 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2043 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[
3]);
2047 (define_insn "add<mode>
3_compare0"
2048 [(set (reg:CC_NZ CC_REGNUM)
2050 (plus:GPI (match_operand:GPI
1 "register_operand" "%rk,rk,rk")
2051 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2053 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2054 (plus:GPI (match_dup
1) (match_dup
2)))]
2057 adds
\\t%<w>
0, %<w>
1, %<w>
2
2058 adds
\\t%<w>
0, %<w>
1, %
2
2059 subs
\\t%<w>
0, %<w>
1, #%n2"
2060 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2063 ;; zero_extend version of above
2064 (define_insn "*addsi3_compare0_uxtw"
2065 [(set (reg:CC_NZ CC_REGNUM)
2067 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk")
2068 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
2070 (set (match_operand:DI
0 "register_operand" "=r,r,r")
2071 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
2074 adds
\\t%w0, %w1, %w2
2076 subs
\\t%w0, %w1, #%n2"
2077 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2080 (define_insn "*add<mode>
3_compareC_cconly"
2081 [(set (reg:CC_C CC_REGNUM)
2084 (match_operand:GPI
0 "register_operand" "r,r,r")
2085 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2092 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2095 (define_insn "add<mode>
3_compareC"
2096 [(set (reg:CC_C CC_REGNUM)
2099 (match_operand:GPI
1 "register_operand" "rk,rk,rk")
2100 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
2102 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
2103 (plus:GPI (match_dup
1) (match_dup
2)))]
2106 adds
\\t%<w>
0, %<w>
1, %<w>
2
2107 adds
\\t%<w>
0, %<w>
1, %
2
2108 subs
\\t%<w>
0, %<w>
1, #%n2"
2109 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2112 (define_insn "*add<mode>
3_compareV_cconly_imm"
2113 [(set (reg:CC_V CC_REGNUM)
2116 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
2117 (match_operand:<DWI>
1 "const_scalar_int_operand" ""))
2121 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))]
2122 "INTVAL (operands[
1]) == INTVAL (operands[
2])"
2126 [(set_attr "type" "alus_imm")]
2129 (define_insn "*add<mode>
3_compareV_cconly"
2130 [(set (reg:CC_V CC_REGNUM)
2133 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
2134 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2135 (sign_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
2137 "cmn
\\t%<w>
0, %<w>
1"
2138 [(set_attr "type" "alus_sreg")]
2141 (define_insn "add<mode>
3_compareV_imm"
2142 [(set (reg:CC_V CC_REGNUM)
2146 (match_operand:GPI
1 "register_operand" "rk,rk"))
2147 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J"))
2149 (plus:GPI (match_dup
1) (match_dup
2)))))
2150 (set (match_operand:GPI
0 "register_operand" "=r,r")
2151 (plus:GPI (match_dup
1) (match_dup
2)))]
2154 adds
\\t%<w>
0, %<w>
1, %<w>
2
2155 subs
\\t%<w>
0, %<w>
1, #%n2"
2156 [(set_attr "type" "alus_imm,alus_imm")]
2159 (define_insn "add<mode>
3_compareV"
2160 [(set (reg:CC_V CC_REGNUM)
2163 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "rk"))
2164 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2165 (sign_extend:<DWI> (plus:GPI (match_dup
1) (match_dup
2)))))
2166 (set (match_operand:GPI
0 "register_operand" "=r")
2167 (plus:GPI (match_dup
1) (match_dup
2)))]
2169 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
2170 [(set_attr "type" "alus_sreg")]
2173 (define_insn "*adds_shift_imm_<mode>"
2174 [(set (reg:CC_NZ CC_REGNUM)
2176 (plus:GPI (ASHIFT:GPI
2177 (match_operand:GPI
1 "register_operand" "r")
2178 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2179 (match_operand:GPI
3 "register_operand" "r"))
2181 (set (match_operand:GPI
0 "register_operand" "=r")
2182 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
2185 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2186 [(set_attr "type" "alus_shift_imm")]
2189 (define_insn "*subs_shift_imm_<mode>"
2190 [(set (reg:CC_NZ CC_REGNUM)
2192 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2194 (match_operand:GPI
2 "register_operand" "r")
2195 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
2197 (set (match_operand:GPI
0 "register_operand" "=r")
2198 (minus:GPI (match_dup
1)
2199 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
2201 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
2202 [(set_attr "type" "alus_shift_imm")]
2205 (define_insn "*adds_mul_imm_<mode>"
2206 [(set (reg:CC_NZ CC_REGNUM)
2209 (match_operand:GPI
1 "register_operand" "r")
2210 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2211 (match_operand:GPI
3 "register_operand" "r"))
2213 (set (match_operand:GPI
0 "register_operand" "=r")
2214 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
2217 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2218 [(set_attr "type" "alus_shift_imm")]
2221 (define_insn "*subs_mul_imm_<mode>"
2222 [(set (reg:CC_NZ CC_REGNUM)
2224 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2226 (match_operand:GPI
2 "register_operand" "r")
2227 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
2229 (set (match_operand:GPI
0 "register_operand" "=r")
2230 (minus:GPI (match_dup
1)
2231 (mult:GPI (match_dup
2) (match_dup
3))))]
2233 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
2234 [(set_attr "type" "alus_shift_imm")]
2237 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2238 [(set (reg:CC_NZ CC_REGNUM)
2241 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2242 (match_operand:GPI
2 "register_operand" "rk"))
2244 (set (match_operand:GPI
0 "register_operand" "=r")
2245 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
2247 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2248 [(set_attr "type" "alus_ext")]
2251 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2252 [(set (reg:CC_NZ CC_REGNUM)
2254 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2256 (match_operand:ALLX
2 "register_operand" "r")))
2258 (set (match_operand:GPI
0 "register_operand" "=r")
2259 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
2261 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2262 [(set_attr "type" "alus_ext")]
2265 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2266 [(set (reg:CC_NZ CC_REGNUM)
2268 (plus:GPI (ashift:GPI
2270 (match_operand:ALLX
1 "register_operand" "r"))
2271 (match_operand
2 "aarch64_imm3" "Ui3"))
2272 (match_operand:GPI
3 "register_operand" "rk"))
2274 (set (match_operand:GPI
0 "register_operand" "=rk")
2275 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2279 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2280 [(set_attr "type" "alus_ext")]
2283 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2284 [(set (reg:CC_NZ CC_REGNUM)
2286 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2289 (match_operand:ALLX
2 "register_operand" "r"))
2290 (match_operand
3 "aarch64_imm3" "Ui3")))
2292 (set (match_operand:GPI
0 "register_operand" "=rk")
2293 (minus:GPI (match_dup
1)
2294 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2297 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2298 [(set_attr "type" "alus_ext")]
2301 (define_insn "*adds_<optab><mode>_multp2"
2302 [(set (reg:CC_NZ CC_REGNUM)
2304 (plus:GPI (ANY_EXTRACT:GPI
2305 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2306 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2307 (match_operand
3 "const_int_operand" "n")
2309 (match_operand:GPI
4 "register_operand" "rk"))
2311 (set (match_operand:GPI
0 "register_operand" "=r")
2312 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2316 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2317 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2318 [(set_attr "type" "alus_ext")]
2321 (define_insn "*subs_<optab><mode>_multp2"
2322 [(set (reg:CC_NZ CC_REGNUM)
2324 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2326 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2327 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2328 (match_operand
3 "const_int_operand" "n")
2331 (set (match_operand:GPI
0 "register_operand" "=r")
2332 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2333 (mult:GPI (match_dup
1) (match_dup
2))
2336 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2337 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2338 [(set_attr "type" "alus_ext")]
2341 (define_insn "*add<mode>
3nr_compare0"
2342 [(set (reg:CC_NZ CC_REGNUM)
2344 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2345 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2352 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2355 (define_insn "aarch64_sub<mode>_compare0"
2356 [(set (reg:CC_NZ CC_REGNUM)
2358 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2359 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2362 "cmp
\\t%<w>
0, %<w>
1"
2363 [(set_attr "type" "alus_sreg")]
2366 (define_insn "*compare_neg<mode>"
2367 [(set (reg:CC_Z CC_REGNUM)
2369 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2370 (match_operand:GPI
1 "register_operand" "r")))]
2372 "cmn
\\t%<w>
1, %<w>
0"
2373 [(set_attr "type" "alus_sreg")]
2376 (define_insn "*add_<shift>_<mode>"
2377 [(set (match_operand:GPI
0 "register_operand" "=r")
2378 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2379 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2380 (match_operand:GPI
3 "register_operand" "r")))]
2382 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2383 [(set_attr "type" "alu_shift_imm")]
2386 ;; zero_extend version of above
2387 (define_insn "*add_<shift>_si_uxtw"
2388 [(set (match_operand:DI
0 "register_operand" "=r")
2390 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2391 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2392 (match_operand:SI
3 "register_operand" "r"))))]
2394 "add
\\t%w0, %w3, %w1, <shift> %
2"
2395 [(set_attr "type" "alu_shift_imm")]
2398 (define_insn "*add_mul_imm_<mode>"
2399 [(set (match_operand:GPI
0 "register_operand" "=r")
2400 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2401 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2402 (match_operand:GPI
3 "register_operand" "r")))]
2404 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2405 [(set_attr "type" "alu_shift_imm")]
2408 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2409 [(set (match_operand:GPI
0 "register_operand" "=rk")
2410 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2411 (match_operand:GPI
2 "register_operand" "r")))]
2413 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2414 [(set_attr "type" "alu_ext")]
2417 ;; zero_extend version of above
2418 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2419 [(set (match_operand:DI
0 "register_operand" "=rk")
2421 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2422 (match_operand:GPI
2 "register_operand" "r"))))]
2424 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2425 [(set_attr "type" "alu_ext")]
2428 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2429 [(set (match_operand:GPI
0 "register_operand" "=rk")
2430 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2431 (match_operand:ALLX
1 "register_operand" "r"))
2432 (match_operand
2 "aarch64_imm3" "Ui3"))
2433 (match_operand:GPI
3 "register_operand" "r")))]
2435 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2436 [(set_attr "type" "alu_ext")]
2439 ;; zero_extend version of above
2440 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2441 [(set (match_operand:DI
0 "register_operand" "=rk")
2443 (plus:SI (ashift:SI (ANY_EXTEND:SI
2444 (match_operand:SHORT
1 "register_operand" "r"))
2445 (match_operand
2 "aarch64_imm3" "Ui3"))
2446 (match_operand:SI
3 "register_operand" "r"))))]
2448 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2449 [(set_attr "type" "alu_ext")]
2452 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2453 [(set (match_operand:GPI
0 "register_operand" "=rk")
2454 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2455 (match_operand:ALLX
1 "register_operand" "r"))
2456 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2457 (match_operand:GPI
3 "register_operand" "r")))]
2459 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2460 [(set_attr "type" "alu_ext")]
2463 ;; zero_extend version of above
2464 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2465 [(set (match_operand:DI
0 "register_operand" "=rk")
2466 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2467 (match_operand:SHORT
1 "register_operand" "r"))
2468 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2469 (match_operand:SI
3 "register_operand" "r"))))]
2471 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2472 [(set_attr "type" "alu_ext")]
2475 (define_insn "*add_<optab><mode>_multp2"
2476 [(set (match_operand:GPI
0 "register_operand" "=rk")
2477 (plus:GPI (ANY_EXTRACT:GPI
2478 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2479 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2480 (match_operand
3 "const_int_operand" "n")
2482 (match_operand:GPI
4 "register_operand" "r")))]
2483 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2484 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2485 [(set_attr "type" "alu_ext")]
2488 ;; zero_extend version of above
2489 (define_insn "*add_<optab>si_multp2_uxtw"
2490 [(set (match_operand:DI
0 "register_operand" "=rk")
2492 (plus:SI (ANY_EXTRACT:SI
2493 (mult:SI (match_operand:SI
1 "register_operand" "r")
2494 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2495 (match_operand
3 "const_int_operand" "n")
2497 (match_operand:SI
4 "register_operand" "r"))))]
2498 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2499 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2500 [(set_attr "type" "alu_ext")]
2503 (define_expand "add<mode>
3_carryin"
2504 [(set (match_operand:GPI
0 "register_operand")
2507 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2508 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2509 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2514 ;; Note that add with carry with two zero inputs is matched by cset,
2515 ;; and that add with carry with one zero input is matched by cinc.
2517 (define_insn "*add<mode>
3_carryin"
2518 [(set (match_operand:GPI
0 "register_operand" "=r")
2521 (match_operand:GPI
3 "aarch64_carry_operation" "")
2522 (match_operand:GPI
1 "register_operand" "r"))
2523 (match_operand:GPI
2 "register_operand" "r")))]
2525 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2526 [(set_attr "type" "adc_reg")]
2529 ;; zero_extend version of above
2530 (define_insn "*addsi3_carryin_uxtw"
2531 [(set (match_operand:DI
0 "register_operand" "=r")
2535 (match_operand:SI
3 "aarch64_carry_operation" "")
2536 (match_operand:SI
1 "register_operand" "r"))
2537 (match_operand:SI
2 "register_operand" "r"))))]
2539 "adc
\\t%w0, %w1, %w2"
2540 [(set_attr "type" "adc_reg")]
2543 (define_expand "add<mode>
3_carryinC"
2551 (match_operand:GPI
1 "register_operand")))
2553 (match_operand:GPI
2 "register_operand")))
2555 (set (match_operand:GPI
0 "register_operand")
2557 (plus:GPI (match_dup
5) (match_dup
1))
2561 operands[
3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2562 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2563 operands[
4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2564 operands[
5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2565 operands[
6] = immed_wide_int_const (wi::shwi (
1, <DWI>mode)
2566 << GET_MODE_BITSIZE (<MODE>mode),
2570 (define_insn "*add<mode>
3_carryinC_zero"
2571 [(set (reg:CC_ADC CC_REGNUM)
2574 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2575 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2576 (match_operand
4 "const_scalar_int_operand" "")))
2577 (set (match_operand:GPI
0 "register_operand" "=r")
2578 (plus:GPI (match_operand:GPI
3 "aarch64_carry_operation" "")
2580 "rtx_mode_t (operands[
4], <DWI>mode)
2581 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2582 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2583 [(set_attr "type" "adc_reg")]
2586 (define_insn "*add<mode>
3_carryinC"
2587 [(set (reg:CC_ADC CC_REGNUM)
2591 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2592 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2593 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2594 (match_operand
5 "const_scalar_int_operand" "")))
2595 (set (match_operand:GPI
0 "register_operand" "=r")
2597 (plus:GPI (match_operand:GPI
4 "aarch64_carry_operation" "")
2600 "rtx_mode_t (operands[
5], <DWI>mode)
2601 == (wi::shwi (
1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2602 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2603 [(set_attr "type" "adc_reg")]
2606 (define_expand "add<mode>
3_carryinV"
2608 [(set (reg:CC_V CC_REGNUM)
2614 (match_operand:GPI
1 "register_operand")))
2616 (match_operand:GPI
2 "register_operand")))
2619 (plus:GPI (match_dup
4) (match_dup
1))
2621 (set (match_operand:GPI
0 "register_operand")
2623 (plus:GPI (match_dup
4) (match_dup
1))
2627 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2628 operands[
3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2629 operands[
4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2632 (define_insn "*add<mode>
3_carryinV_zero"
2633 [(set (reg:CC_V CC_REGNUM)
2636 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2637 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2640 (match_operand:GPI
3 "aarch64_carry_operation" "")
2642 (set (match_operand:GPI
0 "register_operand" "=r")
2643 (plus:GPI (match_dup
3) (match_dup
1)))]
2645 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2646 [(set_attr "type" "adc_reg")]
2649 (define_insn "*add<mode>
3_carryinV"
2650 [(set (reg:CC_V CC_REGNUM)
2654 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2655 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2656 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2660 (match_operand:GPI
4 "aarch64_carry_operation" "")
2663 (set (match_operand:GPI
0 "register_operand" "=r")
2665 (plus:GPI (match_dup
4) (match_dup
1))
2668 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2669 [(set_attr "type" "adc_reg")]
2672 (define_insn "*add_uxt<mode>_shift2"
2673 [(set (match_operand:GPI
0 "register_operand" "=rk")
2675 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2676 (match_operand
2 "aarch64_imm3" "Ui3"))
2677 (match_operand
3 "const_int_operand" "n"))
2678 (match_operand:GPI
4 "register_operand" "r")))]
2679 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2681 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2682 INTVAL (operands[
3])));
2683 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2684 [(set_attr "type" "alu_ext")]
2687 ;; zero_extend version of above
2688 (define_insn "*add_uxtsi_shift2_uxtw"
2689 [(set (match_operand:DI
0 "register_operand" "=rk")
2692 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2693 (match_operand
2 "aarch64_imm3" "Ui3"))
2694 (match_operand
3 "const_int_operand" "n"))
2695 (match_operand:SI
4 "register_operand" "r"))))]
2696 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2698 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2699 INTVAL (operands[
3])));
2700 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2701 [(set_attr "type" "alu_ext")]
2704 (define_insn "*add_uxt<mode>_multp2"
2705 [(set (match_operand:GPI
0 "register_operand" "=rk")
2707 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2708 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2709 (match_operand
3 "const_int_operand" "n"))
2710 (match_operand:GPI
4 "register_operand" "r")))]
2711 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2713 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2714 INTVAL (operands[
3])));
2715 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2716 [(set_attr "type" "alu_ext")]
2719 ;; zero_extend version of above
2720 (define_insn "*add_uxtsi_multp2_uxtw"
2721 [(set (match_operand:DI
0 "register_operand" "=rk")
2724 (mult:SI (match_operand:SI
1 "register_operand" "r")
2725 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2726 (match_operand
3 "const_int_operand" "n"))
2727 (match_operand:SI
4 "register_operand" "r"))))]
2728 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2730 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2731 INTVAL (operands[
3])));
2732 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2733 [(set_attr "type" "alu_ext")]
2736 (define_insn "subsi3"
2737 [(set (match_operand:SI
0 "register_operand" "=rk")
2738 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2739 (match_operand:SI
2 "register_operand" "r")))]
2741 "sub
\\t%w0, %w1, %w2"
2742 [(set_attr "type" "alu_sreg")]
2745 ;; zero_extend version of above
2746 (define_insn "*subsi3_uxtw"
2747 [(set (match_operand:DI
0 "register_operand" "=rk")
2749 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2750 (match_operand:SI
2 "register_operand" "r"))))]
2752 "sub
\\t%w0, %w1, %w2"
2753 [(set_attr "type" "alu_sreg")]
2756 (define_insn "subdi3"
2757 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2758 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2759 (match_operand:DI
2 "register_operand" "r,w")))]
2763 sub
\\t%d0, %d1, %d2"
2764 [(set_attr "type" "alu_sreg, neon_sub")
2765 (set_attr "arch" "*,simd")]
2768 (define_expand "subv<GPI:mode>
4"
2769 [(match_operand:GPI
0 "register_operand")
2770 (match_operand:GPI
1 "register_operand")
2771 (match_operand:GPI
2 "aarch64_plus_operand")
2772 (label_ref (match_operand
3 "" ""))]
2775 if (CONST_INT_P (operands[
2]))
2776 emit_insn (gen_subv<mode>_imm (operands[
0], operands[
1], operands[
2]));
2778 emit_insn (gen_subv<mode>_insn (operands[
0], operands[
1], operands[
2]));
2779 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2784 (define_insn "subv<GPI:mode>_insn"
2785 [(set (reg:CC_V CC_REGNUM)
2789 (match_operand:GPI
1 "register_operand" "rk")
2790 (match_operand:GPI
2 "register_operand" "r")))
2791 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2792 (sign_extend:<DWI> (match_dup
2)))))
2793 (set (match_operand:GPI
0 "register_operand" "=r")
2794 (minus:GPI (match_dup
1) (match_dup
2)))]
2796 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2797 [(set_attr "type" "alus_sreg")]
2800 (define_insn "subv<GPI:mode>_imm"
2801 [(set (reg:CC_V CC_REGNUM)
2805 (match_operand:GPI
1 "register_operand" "rk,rk")
2806 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2807 (minus:<DWI> (sign_extend:<DWI> (match_dup
1))
2809 (set (match_operand:GPI
0 "register_operand" "=r,r")
2810 (minus:GPI (match_dup
1) (match_dup
2)))]
2813 subs
\\t%<w>
0, %<w>
1, %
2
2814 adds
\\t%<w>
0, %<w>
1, #%n2"
2815 [(set_attr "type" "alus_sreg")]
2818 (define_expand "negv<GPI:mode>
3"
2819 [(match_operand:GPI
0 "register_operand")
2820 (match_operand:GPI
1 "register_operand")
2821 (label_ref (match_operand
2 "" ""))]
2824 emit_insn (gen_negv<mode>_insn (operands[
0], operands[
1]));
2825 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2831 (define_insn "negv<GPI:mode>_insn"
2832 [(set (reg:CC_V CC_REGNUM)
2835 (neg:GPI (match_operand:GPI
1 "register_operand" "r")))
2836 (neg:<DWI> (sign_extend:<DWI> (match_dup
1)))))
2837 (set (match_operand:GPI
0 "register_operand" "=r")
2838 (neg:GPI (match_dup
1)))]
2840 "negs
\\t%<w>
0, %<w>
1"
2841 [(set_attr "type" "alus_sreg")]
2844 (define_insn "negv<GPI:mode>_cmp_only"
2845 [(set (reg:CC_V CC_REGNUM)
2848 (neg:GPI (match_operand:GPI
0 "register_operand" "r")))
2849 (neg:<DWI> (sign_extend:<DWI> (match_dup
0)))))]
2851 "negs
\\t%<w>zr, %<w>
0"
2852 [(set_attr "type" "alus_sreg")]
2855 (define_insn "*cmpv<GPI:mode>_insn"
2856 [(set (reg:CC_V CC_REGNUM)
2859 (minus:GPI (match_operand:GPI
0 "register_operand" "r,r,r")
2860 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))
2861 (minus:<DWI> (sign_extend:<DWI> (match_dup
0))
2862 (sign_extend:<DWI> (match_dup
1)))))]
2868 [(set_attr "type" "alus_sreg")]
2871 (define_expand "usubv<mode>
4"
2872 [(match_operand:GPI
0 "register_operand")
2873 (match_operand:GPI
1 "aarch64_reg_or_zero")
2874 (match_operand:GPI
2 "aarch64_reg_or_zero")
2875 (label_ref (match_operand
3 "" ""))]
2878 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2879 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2884 (define_expand "subti3"
2885 [(set (match_operand:TI
0 "register_operand")
2886 (minus:TI (match_operand:TI
1 "aarch64_reg_or_zero")
2887 (match_operand:TI
2 "register_operand")))]
2890 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2892 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2893 &low_dest, &op1_low, &op2_low,
2894 &high_dest, &op1_high, &op2_high);
2896 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2897 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2899 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2900 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2904 (define_expand "subvti4"
2905 [(match_operand:TI
0 "register_operand")
2906 (match_operand:TI
1 "register_operand")
2907 (match_operand:TI
2 "aarch64_reg_or_imm")
2908 (label_ref (match_operand
3 "" ""))]
2911 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2913 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2914 &low_dest, &op1_low, &op2_low,
2915 &high_dest, &op1_high, &op2_high);
2916 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2917 high_dest, op1_high, op2_high, false);
2919 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2923 (define_expand "usubvti4"
2924 [(match_operand:TI
0 "register_operand")
2925 (match_operand:TI
1 "register_operand")
2926 (match_operand:TI
2 "aarch64_reg_or_imm")
2927 (label_ref (match_operand
3 "" ""))]
2930 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2932 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2933 &low_dest, &op1_low, &op2_low,
2934 &high_dest, &op1_high, &op2_high);
2935 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2936 high_dest, op1_high, op2_high, true);
2938 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2942 (define_expand "negvti3"
2943 [(match_operand:TI
0 "register_operand")
2944 (match_operand:TI
1 "register_operand")
2945 (label_ref (match_operand
2 "" ""))]
2948 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[
0]),
2949 gen_lowpart (DImode, operands[
1])));
2950 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[
0]),
2951 gen_highpart (DImode, operands[
1])));
2952 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
2]);
2958 (define_insn "negdi_carryout"
2959 [(set (reg:CC CC_REGNUM)
2961 (const_int
0) (match_operand:DI
1 "register_operand" "r")))
2962 (set (match_operand:DI
0 "register_operand" "=r")
2963 (neg:DI (match_dup
1)))]
2966 [(set_attr "type" "alus_sreg")]
2969 (define_insn "negvdi_carryinV"
2970 [(set (reg:CC_V CC_REGNUM)
2973 (ltu:TI (reg:CC CC_REGNUM) (const_int
0))
2974 (sign_extend:TI (match_operand:DI
1 "register_operand" "r"))))
2976 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
2978 (set (match_operand:DI
0 "register_operand" "=r")
2979 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int
0))
2983 [(set_attr "type" "alus_sreg")]
2986 (define_insn "*sub<mode>
3_compare0"
2987 [(set (reg:CC_NZ CC_REGNUM)
2988 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2989 (match_operand:GPI
2 "register_operand" "r"))
2991 (set (match_operand:GPI
0 "register_operand" "=r")
2992 (minus:GPI (match_dup
1) (match_dup
2)))]
2994 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2995 [(set_attr "type" "alus_sreg")]
2998 ;; zero_extend version of above
2999 (define_insn "*subsi3_compare0_uxtw"
3000 [(set (reg:CC_NZ CC_REGNUM)
3001 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "rk")
3002 (match_operand:SI
2 "register_operand" "r"))
3004 (set (match_operand:DI
0 "register_operand" "=r")
3005 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
3007 "subs
\\t%w0, %w1, %w2"
3008 [(set_attr "type" "alus_sreg")]
3011 (define_insn "sub<mode>
3_compare1_imm"
3012 [(set (reg:CC CC_REGNUM)
3014 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ,rkZ")
3015 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
3016 (set (match_operand:GPI
0 "register_operand" "=r,r")
3019 (match_operand:GPI
3 "aarch64_plus_immediate" "J,I")))]
3020 "UINTVAL (operands[
2]) == -UINTVAL (operands[
3])"
3022 subs
\\t%<w>
0, %<w>
1, %
2
3023 adds
\\t%<w>
0, %<w>
1, #%n2"
3024 [(set_attr "type" "alus_imm")]
3027 (define_insn "sub<mode>
3_compare1"
3028 [(set (reg:CC CC_REGNUM)
3030 (match_operand:GPI
1 "aarch64_reg_or_zero" "rkZ")
3031 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
3032 (set (match_operand:GPI
0 "register_operand" "=r")
3033 (minus:GPI (match_dup
1) (match_dup
2)))]
3035 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
3036 [(set_attr "type" "alus_sreg")]
3040 [(set (match_operand:GPI
0 "aarch64_general_reg")
3041 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
3042 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3043 (set (reg:CC CC_REGNUM)
3047 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3048 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
3051 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3057 ;; Same as the above peephole but with the compare and minus in
3058 ;; swapped order. The restriction on overlap between operand
0
3059 ;; and operands
1 and
2 doesn't apply here.
3061 [(set (reg:CC CC_REGNUM)
3063 (match_operand:GPI
1 "aarch64_reg_or_zero")
3064 (match_operand:GPI
2 "aarch64_reg_or_zero")))
3065 (set (match_operand:GPI
0 "aarch64_general_reg")
3066 (minus:GPI (match_dup
1)
3071 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
3078 [(set (match_operand:GPI
0 "aarch64_general_reg")
3079 (plus:GPI (match_operand:GPI
1 "register_operand")
3080 (match_operand:GPI
2 "aarch64_plus_immediate")))
3081 (set (reg:CC CC_REGNUM)
3084 (match_operand:GPI
3 "const_int_operand")))]
3085 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
3086 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3089 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3090 operands[
3], operands[
2]));
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 doesn't apply here.
3099 [(set (reg:CC CC_REGNUM)
3101 (match_operand:GPI
1 "register_operand")
3102 (match_operand:GPI
3 "const_int_operand")))
3103 (set (match_operand:GPI
0 "aarch64_general_reg")
3104 (plus:GPI (match_dup
1)
3105 (match_operand:GPI
2 "aarch64_plus_immediate")))]
3106 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
3109 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
3110 operands[
3], operands[
2]));
3115 (define_insn "*sub_<shift>_<mode>"
3116 [(set (match_operand:GPI
0 "register_operand" "=r")
3117 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3119 (match_operand:GPI
1 "register_operand" "r")
3120 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3122 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
3123 [(set_attr "type" "alu_shift_imm")]
3126 ;; zero_extend version of above
3127 (define_insn "*sub_<shift>_si_uxtw"
3128 [(set (match_operand:DI
0 "register_operand" "=r")
3130 (minus:SI (match_operand:SI
3 "register_operand" "r")
3132 (match_operand:SI
1 "register_operand" "r")
3133 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3135 "sub
\\t%w0, %w3, %w1, <shift> %
2"
3136 [(set_attr "type" "alu_shift_imm")]
3139 (define_insn "*sub_mul_imm_<mode>"
3140 [(set (match_operand:GPI
0 "register_operand" "=r")
3141 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3143 (match_operand:GPI
1 "register_operand" "r")
3144 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3146 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
3147 [(set_attr "type" "alu_shift_imm")]
3150 ;; zero_extend version of above
3151 (define_insn "*sub_mul_imm_si_uxtw"
3152 [(set (match_operand:DI
0 "register_operand" "=r")
3154 (minus:SI (match_operand:SI
3 "register_operand" "r")
3156 (match_operand:SI
1 "register_operand" "r")
3157 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3159 "sub
\\t%w0, %w3, %w1, lsl %p2"
3160 [(set_attr "type" "alu_shift_imm")]
3163 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3164 [(set (match_operand:GPI
0 "register_operand" "=rk")
3165 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3167 (match_operand:ALLX
2 "register_operand" "r"))))]
3169 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
3170 [(set_attr "type" "alu_ext")]
3173 ;; zero_extend version of above
3174 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3175 [(set (match_operand:DI
0 "register_operand" "=rk")
3177 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3179 (match_operand:SHORT
2 "register_operand" "r")))))]
3181 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3182 [(set_attr "type" "alu_ext")]
3185 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3186 [(set (match_operand:GPI
0 "register_operand" "=rk")
3187 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
3188 (ashift:GPI (ANY_EXTEND:GPI
3189 (match_operand:ALLX
2 "register_operand" "r"))
3190 (match_operand
3 "aarch64_imm3" "Ui3"))))]
3192 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
3193 [(set_attr "type" "alu_ext")]
3196 ;; zero_extend version of above
3197 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3198 [(set (match_operand:DI
0 "register_operand" "=rk")
3200 (minus:SI (match_operand:SI
1 "register_operand" "rk")
3201 (ashift:SI (ANY_EXTEND:SI
3202 (match_operand:SHORT
2 "register_operand" "r"))
3203 (match_operand
3 "aarch64_imm3" "Ui3")))))]
3205 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
3206 [(set_attr "type" "alu_ext")]
3209 (define_insn "*sub_<optab><mode>_multp2"
3210 [(set (match_operand:GPI
0 "register_operand" "=rk")
3211 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3213 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3214 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3215 (match_operand
3 "const_int_operand" "n")
3217 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
3218 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
3219 [(set_attr "type" "alu_ext")]
3222 ;; zero_extend version of above
3223 (define_insn "*sub_<optab>si_multp2_uxtw"
3224 [(set (match_operand:DI
0 "register_operand" "=rk")
3226 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3228 (mult:SI (match_operand:SI
1 "register_operand" "r")
3229 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3230 (match_operand
3 "const_int_operand" "n")
3232 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
3233 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
3234 [(set_attr "type" "alu_ext")]
3237 ;; The hardware description is op1 + ~op2 + C.
3238 ;; = op1 + (-op2 +
1) + (
1 - !C)
3239 ;; = op1 - op2 -
1 +
1 - !C
3240 ;; = op1 - op2 - !C.
3241 ;; We describe the latter.
3243 (define_insn "*sub<mode>
3_carryin0"
3244 [(set (match_operand:GPI
0 "register_operand" "=r")
3246 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3247 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
3249 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
3250 [(set_attr "type" "adc_reg")]
3253 ;; zero_extend version of the above
3254 (define_insn "*subsi3_carryin_uxtw"
3255 [(set (match_operand:DI
0 "register_operand" "=r")
3258 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3259 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
3261 "sbc
\\t%w0, %w1, wzr"
3262 [(set_attr "type" "adc_reg")]
3265 (define_expand "sub<mode>
3_carryin"
3266 [(set (match_operand:GPI
0 "register_operand")
3269 (match_operand:GPI
1 "aarch64_reg_or_zero")
3270 (match_operand:GPI
2 "register_operand"))
3271 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
3276 (define_insn "*sub<mode>
3_carryin"
3277 [(set (match_operand:GPI
0 "register_operand" "=r")
3280 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3281 (match_operand:GPI
2 "register_operand" "r"))
3282 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3285 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3286 [(set_attr "type" "adc_reg")]
3289 ;; zero_extend version of the above
3290 (define_insn "*subsi3_carryin_uxtw"
3291 [(set (match_operand:DI
0 "register_operand" "=r")
3295 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3296 (match_operand:SI
2 "register_operand" "r"))
3297 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
3300 "sbc
\\t%w0, %w1, %w2"
3301 [(set_attr "type" "adc_reg")]
3304 (define_insn "*sub<mode>
3_carryin_alt"
3305 [(set (match_operand:GPI
0 "register_operand" "=r")
3308 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3309 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
3310 (match_operand:GPI
2 "register_operand" "r")))]
3312 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3313 [(set_attr "type" "adc_reg")]
3316 ;; zero_extend version of the above
3317 (define_insn "*subsi3_carryin_alt_uxtw"
3318 [(set (match_operand:DI
0 "register_operand" "=r")
3322 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3323 (match_operand:SI
3 "aarch64_borrow_operation" ""))
3324 (match_operand:SI
2 "register_operand" "r"))))]
3326 "sbc
\\t%w0, %w1, %w2"
3327 [(set_attr "type" "adc_reg")]
3330 (define_expand "usub<GPI:mode>
3_carryinC"
3332 [(set (reg:CC CC_REGNUM)
3335 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3338 (match_operand:GPI
2 "register_operand"))
3339 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0)))))
3340 (set (match_operand:GPI
0 "register_operand")
3342 (minus:GPI (match_dup
1) (match_dup
2))
3343 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3347 (define_insn "*usub<GPI:mode>
3_carryinC_z1"
3348 [(set (reg:CC CC_REGNUM)
3353 (match_operand:GPI
1 "register_operand" "r"))
3354 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))))
3355 (set (match_operand:GPI
0 "register_operand" "=r")
3357 (neg:GPI (match_dup
1))
3358 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3360 "sbcs
\\t%<w>
0, <w>zr, %<w>
1"
3361 [(set_attr "type" "adc_reg")]
3364 (define_insn "*usub<GPI:mode>
3_carryinC_z2"
3365 [(set (reg:CC CC_REGNUM)
3368 (match_operand:GPI
1 "register_operand" "r"))
3369 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3370 (set (match_operand:GPI
0 "register_operand" "=r")
3373 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3375 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3376 [(set_attr "type" "adc_reg")]
3379 (define_insn "*usub<GPI:mode>
3_carryinC"
3380 [(set (reg:CC CC_REGNUM)
3383 (match_operand:GPI
1 "register_operand" "r"))
3386 (match_operand:GPI
2 "register_operand" "r"))
3387 (match_operand:<DWI>
3 "aarch64_borrow_operation" ""))))
3388 (set (match_operand:GPI
0 "register_operand" "=r")
3390 (minus:GPI (match_dup
1) (match_dup
2))
3391 (match_operand:GPI
4 "aarch64_borrow_operation" "")))]
3393 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3394 [(set_attr "type" "adc_reg")]
3397 (define_expand "sub<GPI:mode>
3_carryinV"
3399 [(set (reg:CC_V CC_REGNUM)
3403 (match_operand:GPI
1 "aarch64_reg_or_zero"))
3406 (match_operand:GPI
2 "register_operand"))
3407 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0))))
3409 (minus:GPI (match_dup
1)
3410 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))
3412 (set (match_operand:GPI
0 "register_operand")
3414 (minus:GPI (match_dup
1) (match_dup
2))
3415 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3419 (define_insn "*sub<mode>
3_carryinV_z2"
3420 [(set (reg:CC_V CC_REGNUM)
3423 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
3424 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))
3426 (minus:GPI (match_dup
1)
3427 (match_operand:GPI
3 "aarch64_borrow_operation" "")))))
3428 (set (match_operand:GPI
0 "register_operand" "=r")
3430 (match_dup
1) (match_dup
3)))]
3432 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3433 [(set_attr "type" "adc_reg")]
3436 (define_insn "*sub<mode>
3_carryinV"
3437 [(set (reg:CC_V CC_REGNUM)
3441 (match_operand:GPI
1 "register_operand" "r"))
3444 (match_operand:GPI
2 "register_operand" "r"))
3445 (match_operand:<DWI>
3 "aarch64_borrow_operation" "")))
3449 (plus:GPI (match_operand:GPI
4 "aarch64_borrow_operation" "")
3451 (set (match_operand:GPI
0 "register_operand" "=r")
3453 (minus:GPI (match_dup
1) (match_dup
2))
3456 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3457 [(set_attr "type" "adc_reg")]
3460 (define_insn "*sub_uxt<mode>_shift2"
3461 [(set (match_operand:GPI
0 "register_operand" "=rk")
3462 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3464 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
3465 (match_operand
2 "aarch64_imm3" "Ui3"))
3466 (match_operand
3 "const_int_operand" "n"))))]
3467 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3469 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3470 INTVAL (operands[
3])));
3471 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
3472 [(set_attr "type" "alu_ext")]
3475 ;; zero_extend version of above
3476 (define_insn "*sub_uxtsi_shift2_uxtw"
3477 [(set (match_operand:DI
0 "register_operand" "=rk")
3479 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3481 (ashift:SI (match_operand:SI
1 "register_operand" "r")
3482 (match_operand
2 "aarch64_imm3" "Ui3"))
3483 (match_operand
3 "const_int_operand" "n")))))]
3484 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3486 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3487 INTVAL (operands[
3])));
3488 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
3489 [(set_attr "type" "alu_ext")]
3492 (define_insn "*sub_uxt<mode>_multp2"
3493 [(set (match_operand:GPI
0 "register_operand" "=rk")
3494 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3496 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3497 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3498 (match_operand
3 "const_int_operand" "n"))))]
3499 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3501 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3502 INTVAL (operands[
3])));
3503 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
3504 [(set_attr "type" "alu_ext")]
3507 ;; zero_extend version of above
3508 (define_insn "*sub_uxtsi_multp2_uxtw"
3509 [(set (match_operand:DI
0 "register_operand" "=rk")
3511 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3513 (mult:SI (match_operand:SI
1 "register_operand" "r")
3514 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3515 (match_operand
3 "const_int_operand" "n")))))]
3516 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3518 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3519 INTVAL (operands[
3])));
3520 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
3521 [(set_attr "type" "alu_ext")]
3524 (define_expand "abs<mode>
2"
3525 [(match_operand:GPI
0 "register_operand")
3526 (match_operand:GPI
1 "register_operand")]
3529 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
3530 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3531 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
3536 (define_insn "neg<mode>
2"
3537 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3538 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3542 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
3543 [(set_attr "type" "alu_sreg, neon_neg<q>")
3544 (set_attr "arch" "*,simd")]
3547 ;; zero_extend version of above
3548 (define_insn "*negsi2_uxtw"
3549 [(set (match_operand:DI
0 "register_operand" "=r")
3550 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
3553 [(set_attr "type" "alu_sreg")]
3556 (define_insn "*ngc<mode>"
3557 [(set (match_operand:GPI
0 "register_operand" "=r")
3559 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
3560 (match_operand:GPI
1 "register_operand" "r")))]
3562 "ngc
\\t%<w>
0, %<w>
1"
3563 [(set_attr "type" "adc_reg")]
3566 (define_insn "*ngcsi_uxtw"
3567 [(set (match_operand:DI
0 "register_operand" "=r")
3570 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
3571 (match_operand:SI
1 "register_operand" "r"))))]
3574 [(set_attr "type" "adc_reg")]
3577 (define_insn "neg<mode>
2_compare0"
3578 [(set (reg:CC_NZ CC_REGNUM)
3579 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3581 (set (match_operand:GPI
0 "register_operand" "=r")
3582 (neg:GPI (match_dup
1)))]
3584 "negs
\\t%<w>
0, %<w>
1"
3585 [(set_attr "type" "alus_sreg")]
3588 ;; zero_extend version of above
3589 (define_insn "*negsi2_compare0_uxtw"
3590 [(set (reg:CC_NZ CC_REGNUM)
3591 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
3593 (set (match_operand:DI
0 "register_operand" "=r")
3594 (zero_extend:DI (neg:SI (match_dup
1))))]
3597 [(set_attr "type" "alus_sreg")]
3600 (define_insn "*neg_<shift><mode>
3_compare0"
3601 [(set (reg:CC_NZ CC_REGNUM)
3603 (neg:GPI (ASHIFT:GPI
3604 (match_operand:GPI
1 "register_operand" "r")
3605 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3607 (set (match_operand:GPI
0 "register_operand" "=r")
3608 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
3610 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
3611 [(set_attr "type" "alus_shift_imm")]
3614 (define_insn "*neg_<shift>_<mode>
2"
3615 [(set (match_operand:GPI
0 "register_operand" "=r")
3616 (neg:GPI (ASHIFT:GPI
3617 (match_operand:GPI
1 "register_operand" "r")
3618 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3620 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
3621 [(set_attr "type" "alu_shift_imm")]
3624 ;; zero_extend version of above
3625 (define_insn "*neg_<shift>_si2_uxtw"
3626 [(set (match_operand:DI
0 "register_operand" "=r")
3629 (match_operand:SI
1 "register_operand" "r")
3630 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3632 "neg
\\t%w0, %w1, <shift> %
2"
3633 [(set_attr "type" "alu_shift_imm")]
3636 (define_insn "*neg_mul_imm_<mode>
2"
3637 [(set (match_operand:GPI
0 "register_operand" "=r")
3639 (match_operand:GPI
1 "register_operand" "r")
3640 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3642 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
3643 [(set_attr "type" "alu_shift_imm")]
3646 ;; zero_extend version of above
3647 (define_insn "*neg_mul_imm_si2_uxtw"
3648 [(set (match_operand:DI
0 "register_operand" "=r")
3651 (match_operand:SI
1 "register_operand" "r")
3652 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3654 "neg
\\t%w0, %w1, lsl %p2"
3655 [(set_attr "type" "alu_shift_imm")]
3658 (define_insn "mul<mode>
3"
3659 [(set (match_operand:GPI
0 "register_operand" "=r")
3660 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3661 (match_operand:GPI
2 "register_operand" "r")))]
3663 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
3664 [(set_attr "type" "mul")]
3667 ;; zero_extend version of above
3668 (define_insn "*mulsi3_uxtw"
3669 [(set (match_operand:DI
0 "register_operand" "=r")
3671 (mult:SI (match_operand:SI
1 "register_operand" "r")
3672 (match_operand:SI
2 "register_operand" "r"))))]
3674 "mul
\\t%w0, %w1, %w2"
3675 [(set_attr "type" "mul")]
3678 (define_insn "madd<mode>"
3679 [(set (match_operand:GPI
0 "register_operand" "=r")
3680 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3681 (match_operand:GPI
2 "register_operand" "r"))
3682 (match_operand:GPI
3 "register_operand" "r")))]
3684 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3685 [(set_attr "type" "mla")]
3688 ;; zero_extend version of above
3689 (define_insn "*maddsi_uxtw"
3690 [(set (match_operand:DI
0 "register_operand" "=r")
3692 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
3693 (match_operand:SI
2 "register_operand" "r"))
3694 (match_operand:SI
3 "register_operand" "r"))))]
3696 "madd
\\t%w0, %w1, %w2, %w3"
3697 [(set_attr "type" "mla")]
3700 (define_insn "*msub<mode>"
3701 [(set (match_operand:GPI
0 "register_operand" "=r")
3702 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3703 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3704 (match_operand:GPI
2 "register_operand" "r"))))]
3707 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3708 [(set_attr "type" "mla")]
3711 ;; zero_extend version of above
3712 (define_insn "*msubsi_uxtw"
3713 [(set (match_operand:DI
0 "register_operand" "=r")
3715 (minus:SI (match_operand:SI
3 "register_operand" "r")
3716 (mult:SI (match_operand:SI
1 "register_operand" "r")
3717 (match_operand:SI
2 "register_operand" "r")))))]
3720 "msub
\\t%w0, %w1, %w2, %w3"
3721 [(set_attr "type" "mla")]
3724 (define_insn "*mul<mode>_neg"
3725 [(set (match_operand:GPI
0 "register_operand" "=r")
3726 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3727 (match_operand:GPI
2 "register_operand" "r")))]
3730 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3731 [(set_attr "type" "mul")]
3734 ;; zero_extend version of above
3735 (define_insn "*mulsi_neg_uxtw"
3736 [(set (match_operand:DI
0 "register_operand" "=r")
3738 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3739 (match_operand:SI
2 "register_operand" "r"))))]
3742 "mneg
\\t%w0, %w1, %w2"
3743 [(set_attr "type" "mul")]
3746 (define_insn "<su_optab>mulsidi3"
3747 [(set (match_operand:DI
0 "register_operand" "=r")
3748 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3749 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3751 "<su>mull
\\t%
0, %w1, %w2"
3752 [(set_attr "type" "<su>mull")]
3755 (define_insn "<su_optab>maddsidi4"
3756 [(set (match_operand:DI
0 "register_operand" "=r")
3758 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3759 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3760 (match_operand:DI
3 "register_operand" "r")))]
3762 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3763 [(set_attr "type" "<su>mlal")]
3766 (define_insn "<su_optab>msubsidi4"
3767 [(set (match_operand:DI
0 "register_operand" "=r")
3769 (match_operand:DI
3 "register_operand" "r")
3770 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3772 (match_operand:SI
2 "register_operand" "r")))))]
3774 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3775 [(set_attr "type" "<su>mlal")]
3778 (define_insn "*<su_optab>mulsidi_neg"
3779 [(set (match_operand:DI
0 "register_operand" "=r")
3781 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3782 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3784 "<su>mnegl
\\t%
0, %w1, %w2"
3785 [(set_attr "type" "<su>mull")]
3788 (define_expand "<su_optab>mulditi3"
3789 [(set (match_operand:TI
0 "register_operand")
3790 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3791 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3794 rtx low = gen_reg_rtx (DImode);
3795 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3797 rtx high = gen_reg_rtx (DImode);
3798 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3800 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3801 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3805 ;; The default expansion of multi3 using umuldi3_highpart will perform
3806 ;; the additions in an order that fails to combine into two madd insns.
3807 (define_expand "multi3"
3808 [(set (match_operand:TI
0 "register_operand")
3809 (mult:TI (match_operand:TI
1 "register_operand")
3810 (match_operand:TI
2 "register_operand")))]
3813 rtx l0 = gen_reg_rtx (DImode);
3814 rtx l1 = gen_lowpart (DImode, operands[
1]);
3815 rtx l2 = gen_lowpart (DImode, operands[
2]);
3816 rtx h0 = gen_reg_rtx (DImode);
3817 rtx h1 = gen_highpart (DImode, operands[
1]);
3818 rtx h2 = gen_highpart (DImode, operands[
2]);
3820 emit_insn (gen_muldi3 (l0, l1, l2));
3821 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3822 emit_insn (gen_madddi (h0, h1, l2, h0));
3823 emit_insn (gen_madddi (h0, l1, h2, h0));
3825 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3826 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3830 (define_insn "<su>muldi3_highpart"
3831 [(set (match_operand:DI
0 "register_operand" "=r")
3835 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3836 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3839 "<su>mulh
\\t%
0, %
1, %
2"
3840 [(set_attr "type" "<su>mull")]
3843 (define_insn "<su_optab>div<mode>
3"
3844 [(set (match_operand:GPI
0 "register_operand" "=r")
3845 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3846 (match_operand:GPI
2 "register_operand" "r")))]
3848 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3849 [(set_attr "type" "<su>div")]
3852 ;; zero_extend version of above
3853 (define_insn "*<su_optab>divsi3_uxtw"
3854 [(set (match_operand:DI
0 "register_operand" "=r")
3856 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3857 (match_operand:SI
2 "register_operand" "r"))))]
3859 "<su>div
\\t%w0, %w1, %w2"
3860 [(set_attr "type" "<su>div")]
3863 ;; -------------------------------------------------------------------
3865 ;; -------------------------------------------------------------------
3867 (define_insn "cmp<mode>"
3868 [(set (reg:CC CC_REGNUM)
3869 (compare:CC (match_operand:GPI
0 "register_operand" "rk,rk,rk")
3870 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3876 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3879 (define_insn "fcmp<mode>"
3880 [(set (reg:CCFP CC_REGNUM)
3881 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3882 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3886 fcmp
\\t%<s>
0, %<s>
1"
3887 [(set_attr "type" "fcmp<s>")]
3890 (define_insn "fcmpe<mode>"
3891 [(set (reg:CCFPE CC_REGNUM)
3892 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3893 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3897 fcmpe
\\t%<s>
0, %<s>
1"
3898 [(set_attr "type" "fcmp<s>")]
3901 (define_insn "*cmp_swp_<shift>_reg<mode>"
3902 [(set (reg:CC_SWP CC_REGNUM)
3903 (compare:CC_SWP (ASHIFT:GPI
3904 (match_operand:GPI
0 "register_operand" "r")
3905 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3906 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3908 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3909 [(set_attr "type" "alus_shift_imm")]
3912 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3913 [(set (reg:CC_SWP CC_REGNUM)
3914 (compare:CC_SWP (ANY_EXTEND:GPI
3915 (match_operand:ALLX
0 "register_operand" "r"))
3916 (match_operand:GPI
1 "register_operand" "r")))]
3918 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3919 [(set_attr "type" "alus_ext")]
3922 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3923 [(set (reg:CC_SWP CC_REGNUM)
3924 (compare:CC_SWP (ashift:GPI
3926 (match_operand:ALLX
0 "register_operand" "r"))
3927 (match_operand
1 "aarch64_imm3" "Ui3"))
3928 (match_operand:GPI
2 "register_operand" "r")))]
3930 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3931 [(set_attr "type" "alus_ext")]
3934 ;; -------------------------------------------------------------------
3935 ;; Store-flag and conditional select insns
3936 ;; -------------------------------------------------------------------
3938 (define_expand "cstore<mode>
4"
3939 [(set (match_operand:SI
0 "register_operand")
3940 (match_operator:SI
1 "aarch64_comparison_operator"
3941 [(match_operand:GPI
2 "register_operand")
3942 (match_operand:GPI
3 "aarch64_plus_operand")]))]
3945 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3947 operands[
3] = const0_rtx;
3951 (define_expand "cstorecc4"
3952 [(set (match_operand:SI
0 "register_operand")
3953 (match_operator
1 "aarch64_comparison_operator_mode"
3954 [(match_operand
2 "cc_register")
3955 (match_operand
3 "const0_operand")]))]
3958 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
3963 (define_expand "cstore<mode>
4"
3964 [(set (match_operand:SI
0 "register_operand")
3965 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3966 [(match_operand:GPF
2 "register_operand")
3967 (match_operand:GPF
3 "aarch64_fp_compare_operand")]))]
3970 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3972 operands[
3] = const0_rtx;
3976 (define_insn "aarch64_cstore<mode>"
3977 [(set (match_operand:ALLI
0 "register_operand" "=r")
3978 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3979 [(match_operand
2 "cc_register" "") (const_int
0)]))]
3982 [(set_attr "type" "csel")]
3985 ;; For a
24-bit immediate CST we can optimize the compare for equality
3986 ;; and branch sequence from:
3988 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
3991 ;; into the shorter:
3992 ;; sub x0, x1, #(CST &
0xfff000)
3993 ;; subs x0, x0, #(CST &
0x000fff)
3994 ;; cset x2, <ne, eq>.
3995 (define_insn_and_split "*compare_cstore<mode>_insn"
3996 [(set (match_operand:GPI
0 "register_operand" "=r")
3997 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
3998 (match_operand:GPI
2 "aarch64_imm24" "n")))
3999 (clobber (reg:CC CC_REGNUM))]
4000 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
4001 && !aarch64_plus_operand (operands[
2], <MODE>mode)
4002 && !reload_completed"
4007 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
4008 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
4009 rtx tmp = gen_reg_rtx (<MODE>mode);
4010 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
4011 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
4012 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
4013 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
4014 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
4017 [(set_attr "type" "csel")]
4020 ;; zero_extend version of the above
4021 (define_insn "*cstoresi_insn_uxtw"
4022 [(set (match_operand:DI
0 "register_operand" "=r")
4024 (match_operator:SI
1 "aarch64_comparison_operator_mode"
4025 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4028 [(set_attr "type" "csel")]
4031 (define_insn "cstore<mode>_neg"
4032 [(set (match_operand:ALLI
0 "register_operand" "=r")
4033 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
4034 [(match_operand
2 "cc_register" "") (const_int
0)])))]
4036 "csetm
\\t%<w>
0, %m1"
4037 [(set_attr "type" "csel")]
4040 ;; zero_extend version of the above
4041 (define_insn "*cstoresi_neg_uxtw"
4042 [(set (match_operand:DI
0 "register_operand" "=r")
4044 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
4045 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
4048 [(set_attr "type" "csel")]
4051 (define_expand "cmov<mode>
6"
4052 [(set (match_operand:GPI
0 "register_operand")
4054 (match_operator
1 "aarch64_comparison_operator"
4055 [(match_operand:GPI
2 "register_operand")
4056 (match_operand:GPI
3 "aarch64_plus_operand")])
4057 (match_operand:GPI
4 "register_operand")
4058 (match_operand:GPI
5 "register_operand")))]
4061 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4063 operands[
3] = const0_rtx;
4067 (define_expand "cmov<mode>
6"
4068 [(set (match_operand:GPF
0 "register_operand")
4070 (match_operator
1 "aarch64_comparison_operator"
4071 [(match_operand:GPF
2 "register_operand")
4072 (match_operand:GPF
3 "aarch64_fp_compare_operand")])
4073 (match_operand:GPF
4 "register_operand")
4074 (match_operand:GPF
5 "register_operand")))]
4077 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
4079 operands[
3] = const0_rtx;
4083 (define_insn "*cmov<mode>_insn"
4084 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
4086 (match_operator
1 "aarch64_comparison_operator"
4087 [(match_operand
2 "cc_register" "") (const_int
0)])
4088 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4089 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
4090 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4091 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4092 ;; Final two alternatives should be unreachable, but included for completeness
4094 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
4095 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
4096 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
4097 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
4098 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
4101 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4104 ;; zero_extend version of above
4105 (define_insn "*cmovsi_insn_uxtw"
4106 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
4109 (match_operator
1 "aarch64_comparison_operator"
4110 [(match_operand
2 "cc_register" "") (const_int
0)])
4111 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4112 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4113 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
4114 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
4115 ;; Final two alternatives should be unreachable, but included for completeness
4117 csel
\\t%w0, %w3, %w4, %m1
4118 csinv
\\t%w0, %w3, wzr, %m1
4119 csinv
\\t%w0, %w4, wzr, %M1
4120 csinc
\\t%w0, %w3, wzr, %m1
4121 csinc
\\t%w0, %w4, wzr, %M1
4124 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4127 (define_insn "*cmovdi_insn_uxtw"
4128 [(set (match_operand:DI
0 "register_operand" "=r")
4130 (match_operator
1 "aarch64_comparison_operator"
4131 [(match_operand
2 "cc_register" "") (const_int
0)])
4132 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
4133 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
4135 "csel
\\t%w0, %w3, %w4, %m1"
4136 [(set_attr "type" "csel")]
4139 (define_insn "*cmov<mode>_insn"
4140 [(set (match_operand:GPF
0 "register_operand" "=w")
4142 (match_operator
1 "aarch64_comparison_operator"
4143 [(match_operand
2 "cc_register" "") (const_int
0)])
4144 (match_operand:GPF
3 "register_operand" "w")
4145 (match_operand:GPF
4 "register_operand" "w")))]
4147 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
4148 [(set_attr "type" "fcsel")]
4151 (define_expand "mov<mode>cc"
4152 [(set (match_operand:ALLI
0 "register_operand")
4153 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator")
4154 (match_operand:ALLI
2 "register_operand")
4155 (match_operand:ALLI
3 "register_operand")))]
4159 enum rtx_code code = GET_CODE (operands[
1]);
4161 if (code == UNEQ || code == LTGT)
4164 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4165 XEXP (operands[
1],
1));
4166 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4170 (define_expand "mov<GPF:mode><GPI:mode>cc"
4171 [(set (match_operand:GPI
0 "register_operand")
4172 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4173 (match_operand:GPF
2 "register_operand")
4174 (match_operand:GPF
3 "register_operand")))]
4178 enum rtx_code code = GET_CODE (operands[
1]);
4180 if (code == UNEQ || code == LTGT)
4183 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
4184 XEXP (operands[
1],
1));
4185 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4189 (define_expand "mov<mode>cc"
4190 [(set (match_operand:GPF
0 "register_operand")
4191 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator")
4192 (match_operand:GPF
2 "register_operand")
4193 (match_operand:GPF
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 "<neg_not_op><mode>cc"
4209 [(set (match_operand:GPI
0 "register_operand")
4210 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator")
4211 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand"))
4212 (match_operand:GPI
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 ;; CRC32 instructions.
4228 (define_insn "aarch64_<crc_variant>"
4229 [(set (match_operand:SI
0 "register_operand" "=r")
4230 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
4231 (match_operand:<crc_mode>
2 "register_operand" "r")]
4235 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
4236 return "<crc_variant>
\\t%w0, %w1, %x2";
4238 return "<crc_variant>
\\t%w0, %w1, %w2";
4240 [(set_attr "type" "crc")]
4243 (define_insn "*csinc2<mode>_insn"
4244 [(set (match_operand:GPI
0 "register_operand" "=r")
4245 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
4246 (match_operand:GPI
1 "register_operand" "r")))]
4248 "cinc
\\t%<w>
0, %<w>
1, %m2"
4249 [(set_attr "type" "csel")]
4252 (define_insn "csinc3<mode>_insn"
4253 [(set (match_operand:GPI
0 "register_operand" "=r")
4255 (match_operand
1 "aarch64_comparison_operation" "")
4256 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
4258 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4260 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4261 [(set_attr "type" "csel")]
4264 (define_insn "*csinv3<mode>_insn"
4265 [(set (match_operand:GPI
0 "register_operand" "=r")
4267 (match_operand
1 "aarch64_comparison_operation" "")
4268 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
4269 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4271 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4272 [(set_attr "type" "csel")]
4275 (define_insn "csneg3_uxtw_insn"
4276 [(set (match_operand:DI
0 "register_operand" "=r")
4279 (match_operand
1 "aarch64_comparison_operation" "")
4280 (neg:SI (match_operand:SI
2 "register_operand" "r"))
4281 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
4283 "csneg
\\t%w0, %w3, %w2, %M1"
4284 [(set_attr "type" "csel")]
4287 (define_insn "csneg3<mode>_insn"
4288 [(set (match_operand:GPI
0 "register_operand" "=r")
4290 (match_operand
1 "aarch64_comparison_operation" "")
4291 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
4292 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4294 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4295 [(set_attr "type" "csel")]
4298 ;; If X can be loaded by a single CNT[BHWD] instruction,
4302 ;; is equivalent to:
4304 ;; TMP = UQDEC[BHWD] (B, X)
4307 ;; Defining the pattern this way means that:
4309 ;; A = UMAX (B, X) - X
4313 ;; TMP1 = UQDEC[BHWD] (B, X)
4317 ;; which combine can optimize to:
4319 ;; A = UQDEC[BHWD] (B, X)
4321 ;; We don't use match_operand predicates because the order of the operands
4322 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4323 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4324 (define_expand "umax<mode>
3"
4325 [(set (match_operand:GPI
0 "register_operand")
4326 (umax:GPI (match_operand:GPI
1 "")
4327 (match_operand:GPI
2 "")))]
4330 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
4331 std::swap (operands[
1], operands[
2]);
4332 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
4334 rtx temp = gen_reg_rtx (<MODE>mode);
4335 operands[
1] = force_reg (<MODE>mode, operands[
1]);
4336 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
4337 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
4342 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4343 (define_insn "aarch64_uqdec<mode>"
4344 [(set (match_operand:GPI
0 "register_operand" "=r")
4346 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
4347 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
4351 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
4355 ;; -------------------------------------------------------------------
4356 ;; Logical operations
4357 ;; -------------------------------------------------------------------
4360 (define_insn_and_split "*aarch64_and<mode>_imm2"
4361 [(set (match_operand:GPI
0 "register_operand" "=rk")
4362 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
4363 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
4369 HOST_WIDE_INT val = INTVAL (operands[
2]);
4370 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4371 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4373 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
4374 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
4379 (define_insn "<optab><mode>
3"
4380 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
4381 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
4382 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
4385 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
4386 <logical>
\\t%<w>
0, %<w>
1, %
2
4387 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
4388 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4389 (set_attr "arch" "*,*,simd")]
4392 ;; zero_extend version of above
4393 (define_insn "*<optab>si3_uxtw"
4394 [(set (match_operand:DI
0 "register_operand" "=r,rk")
4396 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
4397 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
4400 <logical>
\\t%w0, %w1, %w2
4401 <logical>
\\t%w0, %w1, %
2"
4402 [(set_attr "type" "logic_reg,logic_imm")]
4405 (define_insn "*and<mode>
3_compare0"
4406 [(set (reg:CC_NZ CC_REGNUM)
4408 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
4409 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
4411 (set (match_operand:GPI
0 "register_operand" "=r,r")
4412 (and:GPI (match_dup
1) (match_dup
2)))]
4415 ands
\\t%<w>
0, %<w>
1, %<w>
2
4416 ands
\\t%<w>
0, %<w>
1, %
2"
4417 [(set_attr "type" "logics_reg,logics_imm")]
4420 ;; zero_extend version of above
4421 (define_insn "*andsi3_compare0_uxtw"
4422 [(set (reg:CC_NZ CC_REGNUM)
4424 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
4425 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
4427 (set (match_operand:DI
0 "register_operand" "=r,r")
4428 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
4431 ands
\\t%w0, %w1, %w2
4432 ands
\\t%w0, %w1, %
2"
4433 [(set_attr "type" "logics_reg,logics_imm")]
4436 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
4437 [(set (reg:CC_NZ CC_REGNUM)
4440 (match_operand:GPI
1 "register_operand" "r")
4441 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4442 (match_operand:GPI
3 "register_operand" "r"))
4444 (set (match_operand:GPI
0 "register_operand" "=r")
4445 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
4447 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4448 [(set_attr "type" "logics_shift_imm")]
4451 ;; zero_extend version of above
4452 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4453 [(set (reg:CC_NZ CC_REGNUM)
4456 (match_operand:SI
1 "register_operand" "r")
4457 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4458 (match_operand:SI
3 "register_operand" "r"))
4460 (set (match_operand:DI
0 "register_operand" "=r")
4461 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
4464 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4465 [(set_attr "type" "logics_shift_imm")]
4468 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
4469 [(set (match_operand:GPI
0 "register_operand" "=r")
4470 (LOGICAL:GPI (SHIFT:GPI
4471 (match_operand:GPI
1 "register_operand" "r")
4472 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4473 (match_operand:GPI
3 "register_operand" "r")))]
4475 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4476 [(set_attr "type" "logic_shift_imm")]
4479 (define_insn "*<optab>_rol<mode>
3"
4480 [(set (match_operand:GPI
0 "register_operand" "=r")
4481 (LOGICAL:GPI (rotate:GPI
4482 (match_operand:GPI
1 "register_operand" "r")
4483 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4484 (match_operand:GPI
3 "register_operand" "r")))]
4486 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
4487 [(set_attr "type" "logic_shift_imm")]
4490 ;; zero_extend versions of above
4491 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4492 [(set (match_operand:DI
0 "register_operand" "=r")
4494 (LOGICAL:SI (SHIFT:SI
4495 (match_operand:SI
1 "register_operand" "r")
4496 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4497 (match_operand:SI
3 "register_operand" "r"))))]
4499 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4500 [(set_attr "type" "logic_shift_imm")]
4503 (define_insn "*<optab>_rolsi3_uxtw"
4504 [(set (match_operand:DI
0 "register_operand" "=r")
4506 (LOGICAL:SI (rotate:SI
4507 (match_operand:SI
1 "register_operand" "r")
4508 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4509 (match_operand:SI
3 "register_operand" "r"))))]
4511 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
4512 [(set_attr "type" "logic_shift_imm")]
4515 (define_insn "one_cmpl<mode>
2"
4516 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4517 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
4522 [(set_attr "type" "logic_reg,neon_logic")
4523 (set_attr "arch" "*,simd")]
4526 (define_insn "*one_cmpl_<optab><mode>
2"
4527 [(set (match_operand:GPI
0 "register_operand" "=r")
4528 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
4529 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
4531 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
4532 [(set_attr "type" "logic_shift_imm")]
4535 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4537 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
4538 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4539 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
4540 (match_operand:GPI
2 "register_operand" "r,w")))]
4543 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
4544 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
4545 [(set_attr "type" "logic_reg,neon_logic")
4546 (set_attr "arch" "*,simd")]
4549 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4550 [(set (match_operand:DI
0 "register_operand" "=r")
4552 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
4553 (match_operand:SI
2 "register_operand" "r"))))]
4555 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
4556 [(set_attr "type" "logic_reg")]
4559 (define_insn "*xor_one_cmplsidi3_ze"
4560 [(set (match_operand:DI
0 "register_operand" "=r")
4562 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
4563 (match_operand:SI
2 "register_operand" "r")))))]
4565 "eon
\\t%w0, %w1, %w2"
4566 [(set_attr "type" "logic_reg")]
4569 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4570 ;; eon does not operate on SIMD registers so the vector variant must be split.
4571 (define_insn_and_split "*xor_one_cmpl<mode>
3"
4572 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4573 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
4574 (match_operand:GPI
2 "register_operand" "r,w"))))]
4577 eon
\\t%<w>
0, %<w>
1, %<w>
2
4579 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
4580 [(set (match_operand:GPI
0 "register_operand" "=w")
4581 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
4582 (match_operand:GPI
2 "register_operand" "w")))
4583 (set (match_dup
0) (not:GPI (match_dup
0)))]
4585 [(set_attr "type" "logic_reg,multiple")
4586 (set_attr "arch" "*,simd")]
4589 (define_insn "*and_one_cmpl<mode>
3_compare0"
4590 [(set (reg:CC_NZ CC_REGNUM)
4593 (match_operand:GPI
1 "register_operand" "r"))
4594 (match_operand:GPI
2 "register_operand" "r"))
4596 (set (match_operand:GPI
0 "register_operand" "=r")
4597 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
4599 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
4600 [(set_attr "type" "logics_reg")]
4603 ;; zero_extend version of above
4604 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4605 [(set (reg:CC_NZ CC_REGNUM)
4608 (match_operand:SI
1 "register_operand" "r"))
4609 (match_operand:SI
2 "register_operand" "r"))
4611 (set (match_operand:DI
0 "register_operand" "=r")
4612 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
4614 "bics
\\t%w0, %w2, %w1"
4615 [(set_attr "type" "logics_reg")]
4618 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
4619 [(set (reg:CC_NZ CC_REGNUM)
4622 (match_operand:GPI
0 "register_operand" "r"))
4623 (match_operand:GPI
1 "register_operand" "r"))
4626 "bics
\\t<w>zr, %<w>
1, %<w>
0"
4627 [(set_attr "type" "logics_reg")]
4630 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
4631 [(set (match_operand:GPI
0 "register_operand" "=r")
4632 (LOGICAL:GPI (not:GPI
4634 (match_operand:GPI
1 "register_operand" "r")
4635 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4636 (match_operand:GPI
3 "register_operand" "r")))]
4638 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4639 [(set_attr "type" "logic_shift_imm")]
4642 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
4643 [(set (match_operand:GPI
0 "register_operand" "=r")
4646 (match_operand:GPI
1 "register_operand" "r")
4647 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4648 (match_operand:GPI
3 "register_operand" "r"))))]
4650 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4651 [(set_attr "type" "logic_shift_imm")]
4654 ;; Zero-extend version of the above.
4655 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4656 [(set (match_operand:DI
0 "register_operand" "=r")
4660 (match_operand:SI
1 "register_operand" "r")
4661 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4662 (match_operand:SI
3 "register_operand" "r")))))]
4664 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4665 [(set_attr "type" "logic_shift_imm")]
4668 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
4669 [(set (reg:CC_NZ CC_REGNUM)
4673 (match_operand:GPI
1 "register_operand" "r")
4674 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4675 (match_operand:GPI
3 "register_operand" "r"))
4677 (set (match_operand:GPI
0 "register_operand" "=r")
4680 (match_dup
1) (match_dup
2))) (match_dup
3)))]
4682 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4683 [(set_attr "type" "logics_shift_imm")]
4686 ;; zero_extend version of above
4687 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4688 [(set (reg:CC_NZ CC_REGNUM)
4692 (match_operand:SI
1 "register_operand" "r")
4693 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
4694 (match_operand:SI
3 "register_operand" "r"))
4696 (set (match_operand:DI
0 "register_operand" "=r")
4697 (zero_extend:DI (and:SI
4699 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
4701 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4702 [(set_attr "type" "logics_shift_imm")]
4705 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
4706 [(set (reg:CC_NZ CC_REGNUM)
4710 (match_operand:GPI
0 "register_operand" "r")
4711 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
4712 (match_operand:GPI
2 "register_operand" "r"))
4715 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
4716 [(set_attr "type" "logics_shift_imm")]
4719 (define_insn "clz<mode>
2"
4720 [(set (match_operand:GPI
0 "register_operand" "=r")
4721 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4723 "clz
\\t%<w>
0, %<w>
1"
4724 [(set_attr "type" "clz")]
4727 (define_expand "ffs<mode>
2"
4728 [(match_operand:GPI
0 "register_operand")
4729 (match_operand:GPI
1 "register_operand")]
4732 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4733 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4735 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4736 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4737 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4742 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4749 (define_expand "popcount<mode>
2"
4750 [(match_operand:GPI
0 "register_operand")
4751 (match_operand:GPI
1 "register_operand")]
4754 rtx v = gen_reg_rtx (V8QImode);
4755 rtx v1 = gen_reg_rtx (V8QImode);
4756 rtx r = gen_reg_rtx (QImode);
4757 rtx in = operands[
1];
4758 rtx out = operands[
0];
4759 if(<MODE>mode == SImode)
4762 tmp = gen_reg_rtx (DImode);
4763 /* If we have SImode, zero extend to DImode, pop count does
4764 not change if we have extra zeros. */
4765 emit_insn (gen_zero_extendsidi2 (tmp, in));
4768 emit_move_insn (v, gen_lowpart (V8QImode, in));
4769 emit_insn (gen_popcountv8qi2 (v1, v));
4770 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4771 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4775 (define_insn "clrsb<mode>
2"
4776 [(set (match_operand:GPI
0 "register_operand" "=r")
4777 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4779 "cls
\\t%<w>
0, %<w>
1"
4780 [(set_attr "type" "clz")]
4783 (define_insn "rbit<mode>
2"
4784 [(set (match_operand:GPI
0 "register_operand" "=r")
4785 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4787 "rbit
\\t%<w>
0, %<w>
1"
4788 [(set_attr "type" "rbit")]
4791 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4792 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4793 ;; expression and split after reload to enable scheduling them apart if
4796 (define_insn_and_split "ctz<mode>
2"
4797 [(set (match_operand:GPI
0 "register_operand" "=r")
4798 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4804 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4805 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4809 (define_insn "*and<mode>_compare0"
4810 [(set (reg:CC_NZ CC_REGNUM)
4812 (match_operand:SHORT
0 "register_operand" "r")
4815 "tst
\\t%<w>
0, <short_mask>"
4816 [(set_attr "type" "alus_imm")]
4819 (define_insn "*ands<GPI:mode>_compare0"
4820 [(set (reg:CC_NZ CC_REGNUM)
4822 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4824 (set (match_operand:GPI
0 "register_operand" "=r")
4825 (zero_extend:GPI (match_dup
1)))]
4827 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4828 [(set_attr "type" "alus_imm")]
4831 (define_insn "*and<mode>
3nr_compare0"
4832 [(set (reg:CC_NZ CC_REGNUM)
4834 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4835 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4841 [(set_attr "type" "logics_reg,logics_imm")]
4845 [(set (reg:CC_NZ CC_REGNUM)
4847 (and:GPI (match_operand:GPI
0 "register_operand")
4848 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4850 (clobber (match_operand:SI
2 "register_operand"))]
4852 [(set (match_dup
2) (match_dup
1))
4853 (set (reg:CC_NZ CC_REGNUM)
4855 (and:GPI (match_dup
0)
4860 (define_insn "*and<mode>
3nr_compare0_zextract"
4861 [(set (reg:CC_NZ CC_REGNUM)
4863 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4864 (match_operand:GPI
1 "const_int_operand" "n")
4865 (match_operand:GPI
2 "const_int_operand" "n"))
4867 "INTVAL (operands[
1]) >
0
4868 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4869 <= GET_MODE_BITSIZE (<MODE>mode))
4870 && aarch64_bitmask_imm (
4871 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4876 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4877 return "tst
\\t%<w>
0, %
1";
4879 [(set_attr "type" "logics_shift_imm")]
4882 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4883 [(set (reg:CC_NZ CC_REGNUM)
4886 (match_operand:GPI
0 "register_operand" "r")
4887 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4888 (match_operand:GPI
2 "register_operand" "r"))
4891 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4892 [(set_attr "type" "logics_shift_imm")]
4896 [(set (reg:CC_NZ CC_REGNUM)
4899 (match_operand:GPI
0 "register_operand")
4900 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4901 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4903 (clobber (match_operand:SI
3 "register_operand"))]
4905 [(set (match_dup
3) (match_dup
2))
4906 (set (reg:CC_NZ CC_REGNUM)
4915 ;; -------------------------------------------------------------------
4917 ;; -------------------------------------------------------------------
4919 (define_expand "<optab><mode>
3"
4920 [(set (match_operand:GPI
0 "register_operand")
4921 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4922 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4925 if (CONST_INT_P (operands[
2]))
4927 operands[
2] = GEN_INT (INTVAL (operands[
2])
4928 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4930 if (operands[
2] == const0_rtx)
4932 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4939 (define_expand "ashl<mode>
3"
4940 [(set (match_operand:SHORT
0 "register_operand")
4941 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4942 (match_operand:QI
2 "const_int_operand")))]
4945 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4947 if (operands[
2] == const0_rtx)
4949 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4955 (define_expand "rotr<mode>
3"
4956 [(set (match_operand:GPI
0 "register_operand")
4957 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4958 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4961 if (CONST_INT_P (operands[
2]))
4963 operands[
2] = GEN_INT (INTVAL (operands[
2])
4964 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4966 if (operands[
2] == const0_rtx)
4968 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4975 (define_expand "rotl<mode>
3"
4976 [(set (match_operand:GPI
0 "register_operand")
4977 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4978 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4981 /* (SZ - cnt) % SZ == -cnt % SZ */
4982 if (CONST_INT_P (operands[
2]))
4984 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
4985 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4986 if (operands[
2] == const0_rtx)
4988 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4993 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
4998 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4999 ;; they truncate the shift/rotate amount by the size of the registers they
5000 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
5001 ;; such redundant masking instructions. GCC can do that automatically when
5002 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
5003 ;; because some of the SISD shift alternatives don't perform this truncations.
5004 ;; So this pattern exists to catch such cases.
5006 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
5007 [(set (match_operand:GPI
0 "register_operand" "=r")
5009 (match_operand:GPI
1 "register_operand" "r")
5010 (match_operator
4 "subreg_lowpart_operator"
5011 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
5012 (match_operand
3 "const_int_operand" "n"))])))]
5013 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
5014 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
5015 [(set_attr "type" "shift_reg")]
5018 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
5019 [(set (match_operand:GPI
0 "register_operand" "=&r")
5021 (match_operand:GPI
1 "register_operand" "r")
5022 (match_operator
4 "subreg_lowpart_operator"
5023 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
5024 (match_operand
3 "const_int_operand" "n")))])))]
5025 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
5030 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5031 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
5032 emit_insn (gen_negsi2 (tmp, operands[
2]));
5034 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
5035 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
5036 SUBREG_BYTE (operands[
4]));
5037 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
5042 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
5043 [(set (match_operand:GPI
0 "register_operand" "=&r")
5045 (match_operand:GPI
1 "register_operand" "r")
5046 (minus:QI (match_operand
2 "const_int_operand" "n")
5047 (match_operator
5 "subreg_lowpart_operator"
5048 [(and:SI (match_operand:SI
3 "register_operand" "r")
5049 (match_operand
4 "const_int_operand" "n"))]))))]
5050 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
5051 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5056 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5059 emit_insn (gen_negsi2 (tmp, operands[
3]));
5061 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
5062 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
5063 SUBREG_BYTE (operands[
5]));
5065 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
5070 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5071 [(set (match_operand:DI
0 "register_operand" "=r")
5073 (match_operand:DI
1 "register_operand" "r")
5074 (match_operator
4 "subreg_lowpart_operator"
5075 [(and:SI (match_operand:SI
2 "register_operand" "r")
5076 (match_operand
3 "const_int_operand" "n"))])))]
5077 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
5080 xop[
0] = operands[
0];
5081 xop[
1] = operands[
1];
5082 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
5083 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
5086 [(set_attr "type" "shift_reg")]
5089 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
5090 [(set (match_operand:GPI
0 "register_operand" "=&r")
5092 (match_operand:GPI
1 "register_operand" "r")
5093 (minus:QI (match_operand
2 "const_int_operand" "n")
5094 (match_operand:QI
3 "register_operand" "r"))))]
5095 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
5100 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
5102 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5103 : gen_lowpart (SImode, operands[
0]));
5105 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5107 rtx and_op = gen_rtx_AND (SImode, tmp,
5108 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
5110 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5112 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
5115 [(set_attr "length" "
8")]
5118 ;; Logical left shift using SISD or Integer instruction
5119 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
5120 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
5122 (match_operand:GPI
1 "register_operand" "r,r,w,w")
5123 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5126 lsl
\t%<w>
0, %<w>
1, %
2
5127 lsl
\t%<w>
0, %<w>
1, %<w>
2
5128 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5129 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
5130 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5131 (set_attr "arch" "*,*,simd,simd")]
5134 ;; Logical right shift using SISD or Integer instruction
5135 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
5136 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5138 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5139 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
5140 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5143 lsr
\t%<w>
0, %<w>
1, %
2
5144 lsr
\t%<w>
0, %<w>
1, %<w>
2
5145 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5148 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5149 (set_attr "arch" "*,*,simd,simd,simd")]
5153 [(set (match_operand:DI
0 "aarch64_simd_register")
5155 (match_operand:DI
1 "aarch64_simd_register")
5156 (match_operand:QI
2 "aarch64_simd_register")))]
5157 "TARGET_SIMD && reload_completed"
5159 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5161 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
5163 operands[
3] = gen_lowpart (QImode, operands[
0]);
5168 [(set (match_operand:SI
0 "aarch64_simd_register")
5170 (match_operand:SI
1 "aarch64_simd_register")
5171 (match_operand:QI
2 "aarch64_simd_register")))]
5172 "TARGET_SIMD && reload_completed"
5174 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5176 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
5178 operands[
3] = gen_lowpart (QImode, operands[
0]);
5182 ;; Arithmetic right shift using SISD or Integer instruction
5183 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
5184 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
5186 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
5187 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
5188 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
5191 asr
\t%<w>
0, %<w>
1, %
2
5192 asr
\t%<w>
0, %<w>
1, %<w>
2
5193 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
5196 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5197 (set_attr "arch" "*,*,simd,simd,simd")]
5201 [(set (match_operand:DI
0 "aarch64_simd_register")
5203 (match_operand:DI
1 "aarch64_simd_register")
5204 (match_operand:QI
2 "aarch64_simd_register")))]
5205 "TARGET_SIMD && reload_completed"
5207 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5209 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
5211 operands[
3] = gen_lowpart (QImode, operands[
0]);
5216 [(set (match_operand:SI
0 "aarch64_simd_register")
5218 (match_operand:SI
1 "aarch64_simd_register")
5219 (match_operand:QI
2 "aarch64_simd_register")))]
5220 "TARGET_SIMD && reload_completed"
5222 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
5224 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
5226 operands[
3] = gen_lowpart (QImode, operands[
0]);
5230 (define_insn "*aarch64_sisd_ushl"
5231 [(set (match_operand:DI
0 "register_operand" "=w")
5232 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5233 (match_operand:QI
2 "register_operand" "w")]
5236 "ushl
\t%d0, %d1, %d2"
5237 [(set_attr "type" "neon_shift_reg")]
5240 (define_insn "*aarch64_ushl_2s"
5241 [(set (match_operand:SI
0 "register_operand" "=w")
5242 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5243 (match_operand:QI
2 "register_operand" "w")]
5246 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
5247 [(set_attr "type" "neon_shift_reg")]
5250 (define_insn "*aarch64_sisd_sshl"
5251 [(set (match_operand:DI
0 "register_operand" "=w")
5252 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
5253 (match_operand:QI
2 "register_operand" "w")]
5256 "sshl
\t%d0, %d1, %d2"
5257 [(set_attr "type" "neon_shift_reg")]
5260 (define_insn "*aarch64_sshl_2s"
5261 [(set (match_operand:SI
0 "register_operand" "=w")
5262 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
5263 (match_operand:QI
2 "register_operand" "w")]
5266 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
5267 [(set_attr "type" "neon_shift_reg")]
5270 (define_insn "*aarch64_sisd_neg_qi"
5271 [(set (match_operand:QI
0 "register_operand" "=w")
5272 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
5276 [(set_attr "type" "neon_neg")]
5280 (define_insn "*ror<mode>
3_insn"
5281 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5283 (match_operand:GPI
1 "register_operand" "r,r")
5284 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5287 ror
\\t%<w>
0, %<w>
1, %
2
5288 ror
\\t%<w>
0, %<w>
1, %<w>
2"
5289 [(set_attr "type" "rotate_imm,shift_reg")]
5292 ;; zero_extend version of above
5293 (define_insn "*<optab>si3_insn_uxtw"
5294 [(set (match_operand:DI
0 "register_operand" "=r,r")
5295 (zero_extend:DI (SHIFT:SI
5296 (match_operand:SI
1 "register_operand" "r,r")
5297 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5300 <shift>
\\t%w0, %w1, %
2
5301 <shift>
\\t%w0, %w1, %w2"
5302 [(set_attr "type" "bfx,shift_reg")]
5305 (define_insn "*<optab><mode>
3_insn"
5306 [(set (match_operand:SHORT
0 "register_operand" "=r")
5307 (ASHIFT:SHORT (match_operand:SHORT
1 "register_operand" "r")
5308 (match_operand
2 "const_int_operand" "n")))]
5309 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5311 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5312 return "<bfshift>
\t%w0, %w1, %
2, %
3";
5314 [(set_attr "type" "bfx")]
5317 (define_insn "*extr<mode>
5_insn"
5318 [(set (match_operand:GPI
0 "register_operand" "=r")
5319 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5320 (match_operand
3 "const_int_operand" "n"))
5321 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5322 (match_operand
4 "const_int_operand" "n"))))]
5323 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5324 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
5325 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5326 [(set_attr "type" "rotate_imm")]
5329 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5330 ;; so we have to match both orderings.
5331 (define_insn "*extr<mode>
5_insn_alt"
5332 [(set (match_operand:GPI
0 "register_operand" "=r")
5333 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5334 (match_operand
4 "const_int_operand" "n"))
5335 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5336 (match_operand
3 "const_int_operand" "n"))))]
5337 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
5338 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
5339 == GET_MODE_BITSIZE (<MODE>mode))"
5340 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5341 [(set_attr "type" "rotate_imm")]
5344 ;; zero_extend version of the above
5345 (define_insn "*extrsi5_insn_uxtw"
5346 [(set (match_operand:DI
0 "register_operand" "=r")
5348 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
5349 (match_operand
3 "const_int_operand" "n"))
5350 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5351 (match_operand
4 "const_int_operand" "n")))))]
5352 "UINTVAL (operands[
3]) <
32 &&
5353 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5354 "extr
\\t%w0, %w1, %w2, %
4"
5355 [(set_attr "type" "rotate_imm")]
5358 (define_insn "*extrsi5_insn_uxtw_alt"
5359 [(set (match_operand:DI
0 "register_operand" "=r")
5361 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5362 (match_operand
4 "const_int_operand" "n"))
5363 (ashift:SI (match_operand:SI
1 "register_operand" "r")
5364 (match_operand
3 "const_int_operand" "n")))))]
5365 "UINTVAL (operands[
3]) <
32 &&
5366 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5367 "extr
\\t%w0, %w1, %w2, %
4"
5368 [(set_attr "type" "rotate_imm")]
5371 (define_insn "*ror<mode>
3_insn"
5372 [(set (match_operand:GPI
0 "register_operand" "=r")
5373 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
5374 (match_operand
2 "const_int_operand" "n")))]
5375 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5377 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5378 return "ror
\\t%<w>
0, %<w>
1, %
3";
5380 [(set_attr "type" "rotate_imm")]
5383 ;; zero_extend version of the above
5384 (define_insn "*rorsi3_insn_uxtw"
5385 [(set (match_operand:DI
0 "register_operand" "=r")
5387 (rotate:SI (match_operand:SI
1 "register_operand" "r")
5388 (match_operand
2 "const_int_operand" "n"))))]
5389 "UINTVAL (operands[
2]) <
32"
5391 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
5392 return "ror
\\t%w0, %w1, %
3";
5394 [(set_attr "type" "rotate_imm")]
5397 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5398 [(set (match_operand:GPI
0 "register_operand" "=r")
5400 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
5401 (match_operand
2 "const_int_operand" "n"))))]
5402 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5404 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5405 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5407 [(set_attr "type" "bfx")]
5410 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5411 [(set (match_operand:GPI
0 "register_operand" "=r")
5413 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5414 (match_operand
2 "const_int_operand" "n"))))]
5415 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5417 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5418 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5420 [(set_attr "type" "bfx")]
5423 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5424 [(set (match_operand:GPI
0 "register_operand" "=r")
5426 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5427 (match_operand
2 "const_int_operand" "n"))))]
5428 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5430 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5431 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5433 [(set_attr "type" "bfx")]
5436 ;; -------------------------------------------------------------------
5438 ;; -------------------------------------------------------------------
5440 (define_expand "<optab>"
5441 [(set (match_operand:DI
0 "register_operand")
5442 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
5444 "aarch64_simd_shift_imm_offset_di")
5445 (match_operand
3 "aarch64_simd_shift_imm_di")))]
5448 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5449 1, GET_MODE_BITSIZE (DImode) -
1))
5455 (define_insn "*<optab><mode>"
5456 [(set (match_operand:GPI
0 "register_operand" "=r")
5457 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
5459 "aarch64_simd_shift_imm_offset_<mode>" "n")
5461 "aarch64_simd_shift_imm_<mode>" "n")))]
5462 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5463 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5464 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
5465 [(set_attr "type" "bfx")]
5468 ;; When the bit position and width add up to
32 we can use a W-reg LSR
5469 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5471 [(set (match_operand:DI
0 "register_operand")
5472 (zero_extract:DI (match_operand:DI
1 "register_operand")
5474 "aarch64_simd_shift_imm_offset_di")
5476 "aarch64_simd_shift_imm_di")))]
5477 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
5478 GET_MODE_BITSIZE (DImode) -
1)
5479 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
5480 == GET_MODE_BITSIZE (SImode)"
5482 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
5484 operands[
4] = gen_lowpart (SImode, operands[
1]);
5488 ;; Bitfield Insert (insv)
5489 (define_expand "insv<mode>"
5490 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
5491 (match_operand
1 "const_int_operand")
5492 (match_operand
2 "const_int_operand"))
5493 (match_operand:GPI
3 "general_operand"))]
5496 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
5497 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
5498 rtx value = operands[
3];
5500 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5503 if (CONST_INT_P (value))
5505 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
5507 /* Prefer AND/OR for inserting all zeros or all ones. */
5508 if ((UINTVAL (value) & mask) ==
0
5509 || (UINTVAL (value) & mask) == mask)
5512 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
5513 if (width ==
16 && (pos %
16) ==
0)
5516 operands[
3] = force_reg (<MODE>mode, value);
5519 (define_insn "*insv_reg<mode>"
5520 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5521 (match_operand
1 "const_int_operand" "n")
5522 (match_operand
2 "const_int_operand" "n"))
5523 (match_operand:GPI
3 "register_operand" "r"))]
5524 "!(UINTVAL (operands[
1]) ==
0
5525 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
5526 > GET_MODE_BITSIZE (<MODE>mode)))"
5527 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
5528 [(set_attr "type" "bfm")]
5531 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
5532 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5533 (match_operand
1 "const_int_operand" "n")
5534 (match_operand
2 "const_int_operand" "n"))
5535 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
5536 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
5537 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
5538 [(set_attr "type" "bfm")]
5541 ;; Match a bfi instruction where the shift of OP3 means that we are
5542 ;; actually copying the least significant bits of OP3 into OP0 by way
5543 ;; of the AND masks and the IOR instruction. A similar instruction
5544 ;; with the two parts of the IOR swapped around was never triggered
5545 ;; in a bootstrap build and test of GCC so it was not included.
5547 (define_insn "*aarch64_bfi<GPI:mode>
5_shift"
5548 [(set (match_operand:GPI
0 "register_operand" "=r")
5549 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5550 (match_operand:GPI
2 "const_int_operand" "n"))
5551 (and:GPI (ashift:GPI
5552 (match_operand:GPI
3 "register_operand" "r")
5553 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))
5554 (match_operand:GPI
5 "const_int_operand" "n"))))]
5555 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5556 UINTVAL (operands[
4]),
5557 UINTVAL(operands[
5]))"
5558 "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %P5"
5559 [(set_attr "type" "bfm")]
5562 (define_insn "*aarch64_bfi<GPI:mode>
5_shift_alt"
5563 [(set (match_operand:GPI
0 "register_operand" "=r")
5564 (ior:GPI (and:GPI (ashift:GPI
5565 (match_operand:GPI
1 "register_operand" "r")
5566 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5567 (match_operand:GPI
3 "const_int_operand" "n"))
5568 (and:GPI (match_operand:GPI
4 "register_operand" "
0")
5569 (match_operand:GPI
5 "const_int_operand" "n"))))]
5570 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
5]),
5571 UINTVAL (operands[
2]),
5572 UINTVAL(operands[
3]))"
5573 "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %P3"
5574 [(set_attr "type" "bfm")]
5577 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no and of the ashift because
5578 ;; the shift is large enough to remove the need for an AND instruction.
5580 (define_insn "*aarch64_bfi<GPI:mode>
4_noand"
5581 [(set (match_operand:GPI
0 "register_operand" "=r")
5582 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5583 (match_operand:GPI
2 "const_int_operand" "n"))
5585 (match_operand:GPI
3 "register_operand" "r")
5586 (match_operand:GPI
4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5587 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
5588 UINTVAL (operands[
4]),
5589 HOST_WIDE_INT_M1U << UINTVAL (operands[
4]) )"
5591 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
4]));
5592 return "bfi
\t%<GPI:w>
0, %<GPI:w>
3, %
4, %
5";
5594 [(set_attr "type" "bfm")]
5597 (define_insn "*aarch64_bfi<GPI:mode>
4_noand_alt"
5598 [(set (match_operand:GPI
0 "register_operand" "=r")
5599 (ior:GPI (ashift:GPI
5600 (match_operand:GPI
1 "register_operand" "r")
5601 (match_operand:GPI
2 "aarch64_simd_shift_imm_<mode>" "n"))
5602 (and:GPI (match_operand:GPI
3 "register_operand" "
0")
5603 (match_operand:GPI
4 "const_int_operand" "n"))))]
5604 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
4]),
5605 UINTVAL (operands[
2]),
5606 HOST_WIDE_INT_M1U << UINTVAL (operands[
2]) )"
5608 operands[
5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[
2]));
5609 return "bfi
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
5";
5611 [(set_attr "type" "bfm")]
5614 ;; Like *aarch64_bfi<GPI:mode>
5_shift but with no shifting, we are just
5615 ;; copying the least significant bits of OP3 to OP0. We need two versions
5616 ;; of the instruction to handle different checks on the constant values.
5618 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift"
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"))
5622 (and:GPI (match_operand:GPI
3 "register_operand" "r")
5623 (match_operand:GPI
4 "const_int_operand" "n"))))]
5624 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5625 UINTVAL (operands[
4]))"
5626 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5627 [(set_attr "type" "bfm")]
5630 (define_insn "*aarch64_bfi<GPI:mode>
4_noshift_alt"
5631 [(set (match_operand:GPI
0 "register_operand" "=r")
5632 (ior:GPI (and:GPI (match_operand:GPI
3 "register_operand" "r")
5633 (match_operand:GPI
4 "const_int_operand" "n"))
5634 (and:GPI (match_operand:GPI
1 "register_operand" "
0")
5635 (match_operand:GPI
2 "const_int_operand" "n"))))]
5636 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[
2]),
0,
5637 UINTVAL (operands[
4]))"
5638 "bfi
\t%<GPI:w>
0, %<GPI:w>
3,
0, %P4"
5639 [(set_attr "type" "bfm")]
5642 (define_insn "*extr_insv_lower_reg<mode>"
5643 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5644 (match_operand
1 "const_int_operand" "n")
5646 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
5648 (match_operand
3 "const_int_operand" "n")))]
5649 "!(UINTVAL (operands[
1]) ==
0
5650 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
5651 > GET_MODE_BITSIZE (<MODE>mode)))"
5652 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
5653 [(set_attr "type" "bfm")]
5656 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5657 [(set (match_operand:GPI
0 "register_operand" "=r")
5658 (ashift:GPI (ANY_EXTEND:GPI
5659 (match_operand:ALLX
1 "register_operand" "r"))
5660 (match_operand
2 "const_int_operand" "n")))]
5661 "UINTVAL (operands[
2]) < <GPI:sizen>"
5663 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
5664 ? GEN_INT (<ALLX:sizen>)
5665 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
5666 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5668 [(set_attr "type" "bfx")]
5671 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5673 (define_insn "*andim_ashift<mode>_bfiz"
5674 [(set (match_operand:GPI
0 "register_operand" "=r")
5675 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5676 (match_operand
2 "const_int_operand" "n"))
5677 (match_operand
3 "const_int_operand" "n")))]
5678 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
5679 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
5680 [(set_attr "type" "bfx")]
5683 ;; Match sbfiz pattern in a shift left + shift right operation.
5685 (define_insn "*ashift<mode>_extv_bfiz"
5686 [(set (match_operand:GPI
0 "register_operand" "=r")
5687 (ashift:GPI (sign_extract:GPI (match_operand:GPI
1 "register_operand" "r")
5688 (match_operand
2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5690 (match_operand
3 "aarch64_simd_shift_imm_<mode>" "n")))]
5691 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5692 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5693 "sbfiz
\\t%<w>
0, %<w>
1, %
3, %
2"
5694 [(set_attr "type" "bfx")]
5697 ;; When the bit position and width of the equivalent extraction add up to
32
5698 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5699 ;; zero-extension of the X-reg.
5701 [(set (match_operand:DI
0 "register_operand")
5702 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
5703 (match_operand
2 "const_int_operand"))
5704 (match_operand
3 "const_int_operand")))]
5705 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
5706 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
5707 == GET_MODE_BITSIZE (SImode)"
5709 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
5711 operands[
4] = gen_lowpart (SImode, operands[
1]);
5715 (define_insn "bswap<mode>
2"
5716 [(set (match_operand:GPI
0 "register_operand" "=r")
5717 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
5719 "rev
\\t%<w>
0, %<w>
1"
5720 [(set_attr "type" "rev")]
5723 (define_insn "bswaphi2"
5724 [(set (match_operand:HI
0 "register_operand" "=r")
5725 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
5728 [(set_attr "type" "rev")]
5731 (define_insn "*aarch64_bfxil<mode>"
5732 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5733 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "r,
0")
5734 (match_operand:GPI
3 "const_int_operand" "n, Ulc"))
5735 (and:GPI (match_operand:GPI
2 "register_operand" "
0,r")
5736 (match_operand:GPI
4 "const_int_operand" "Ulc, n"))))]
5737 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5738 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5739 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5741 switch (which_alternative)
5744 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5745 return "bfxil
\\t%<w>
0, %<w>
1,
0, %
3";
5747 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5748 return "bfxil
\\t%<w>
0, %<w>
2,
0, %
3";
5753 [(set_attr "type" "bfm")]
5756 ; Zero-extended version of above (aarch64_bfxil)
5757 (define_insn "*aarch64_bfxilsi_uxtw"
5758 [(set (match_operand:DI
0 "register_operand" "=r,r")
5759 (zero_extend:DI (ior:SI (and:SI (match_operand:SI
1 "register_operand"
5761 (match_operand:SI
3 "const_int_operand" "n, Ulc"))
5762 (and:SI (match_operand:SI
2 "register_operand" "
0,r")
5763 (match_operand:SI
4 "const_int_operand" "Ulc, n")))))]
5764 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5765 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5766 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5768 switch (which_alternative)
5771 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5772 return "bfxil
\\t%
0, %
1,
0, %
3";
5774 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5775 return "bfxil
\\t%
0, %
2,
0, %
3";
5780 [(set_attr "type" "bfm")]
5783 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5784 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5785 ;; each valid permutation.
5787 (define_insn "rev16<mode>
2"
5788 [(set (match_operand:GPI
0 "register_operand" "=r")
5789 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5791 (match_operand:GPI
3 "const_int_operand" "n"))
5792 (and:GPI (lshiftrt:GPI (match_dup
1)
5794 (match_operand:GPI
2 "const_int_operand" "n"))))]
5795 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5796 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5797 "rev16
\\t%<w>
0, %<w>
1"
5798 [(set_attr "type" "rev")]
5801 (define_insn "rev16<mode>
2_alt"
5802 [(set (match_operand:GPI
0 "register_operand" "=r")
5803 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
5805 (match_operand:GPI
2 "const_int_operand" "n"))
5806 (and:GPI (ashift:GPI (match_dup
1)
5808 (match_operand:GPI
3 "const_int_operand" "n"))))]
5809 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5810 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5811 "rev16
\\t%<w>
0, %<w>
1"
5812 [(set_attr "type" "rev")]
5815 ;; zero_extend version of above
5816 (define_insn "*bswapsi2_uxtw"
5817 [(set (match_operand:DI
0 "register_operand" "=r")
5818 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
5821 [(set_attr "type" "rev")]
5824 ;; -------------------------------------------------------------------
5825 ;; Floating-point intrinsics
5826 ;; -------------------------------------------------------------------
5828 ;; frint floating-point round to integral standard patterns.
5829 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5831 (define_insn "<frint_pattern><mode>
2"
5832 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5833 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5836 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
5837 [(set_attr "type" "f_rint<stype>")]
5840 ;; frcvt floating-point round to integer and convert standard patterns.
5841 ;; Expands to lbtrunc, lceil, lfloor, lround.
5842 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
5843 [(set (match_operand:GPI
0 "register_operand" "=r")
5845 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5848 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
5849 [(set_attr "type" "f_cvtf2i")]
5852 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
5853 [(set (match_operand:GPI
0 "register_operand" "=r")
5856 (match_operand:GPF
1 "register_operand" "w")
5857 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
5859 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
5860 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5862 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
5864 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
5865 output_asm_insn (buf, operands);
5868 [(set_attr "type" "f_cvtf2i")]
5871 ;; fma - expand fma into patterns with the accumulator operand first since
5872 ;; reusing the accumulator results in better register allocation.
5873 ;; The register allocator considers copy preferences in operand order,
5874 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5876 (define_expand "fma<mode>
4"
5877 [(set (match_operand:GPF_F16
0 "register_operand")
5878 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
5879 (match_operand:GPF_F16
2 "register_operand")
5880 (match_operand:GPF_F16
3 "register_operand")))]
5884 (define_insn "*aarch64_fma<mode>
4"
5885 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5886 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
5887 (match_operand:GPF_F16
3 "register_operand" "w")
5888 (match_operand:GPF_F16
1 "register_operand" "w")))]
5890 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5891 [(set_attr "type" "fmac<stype>")]
5894 (define_expand "fnma<mode>
4"
5895 [(set (match_operand:GPF_F16
0 "register_operand")
5897 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5898 (match_operand:GPF_F16
2 "register_operand")
5899 (match_operand:GPF_F16
3 "register_operand")))]
5903 (define_insn "*aarch64_fnma<mode>
4"
5904 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5906 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5907 (match_operand:GPF_F16
3 "register_operand" "w")
5908 (match_operand:GPF_F16
1 "register_operand" "w")))]
5910 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5911 [(set_attr "type" "fmac<stype>")]
5915 (define_expand "fms<mode>
4"
5916 [(set (match_operand:GPF
0 "register_operand")
5917 (fma:GPF (match_operand:GPF
1 "register_operand")
5918 (match_operand:GPF
2 "register_operand")
5919 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5923 (define_insn "*aarch64_fms<mode>
4"
5924 [(set (match_operand:GPF
0 "register_operand" "=w")
5925 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5926 (match_operand:GPF
3 "register_operand" "w")
5927 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5929 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5930 [(set_attr "type" "fmac<s>")]
5933 (define_expand "fnms<mode>
4"
5934 [(set (match_operand:GPF
0 "register_operand")
5935 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5936 (match_operand:GPF
2 "register_operand")
5937 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5941 (define_insn "*aarch64_fnms<mode>
4"
5942 [(set (match_operand:GPF
0 "register_operand" "=w")
5943 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5944 (match_operand:GPF
3 "register_operand" "w")
5945 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5947 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5948 [(set_attr "type" "fmac<s>")]
5951 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5952 (define_insn "*aarch64_fnmadd<mode>
4"
5953 [(set (match_operand:GPF
0 "register_operand" "=w")
5954 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5955 (match_operand:GPF
3 "register_operand" "w")
5956 (match_operand:GPF
1 "register_operand" "w"))))]
5957 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5958 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5959 [(set_attr "type" "fmac<s>")]
5962 ;; -------------------------------------------------------------------
5963 ;; Floating-point conversions
5964 ;; -------------------------------------------------------------------
5966 (define_insn "extendsfdf2"
5967 [(set (match_operand:DF
0 "register_operand" "=w")
5968 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
5971 [(set_attr "type" "f_cvt")]
5974 (define_insn "extendhfsf2"
5975 [(set (match_operand:SF
0 "register_operand" "=w")
5976 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
5979 [(set_attr "type" "f_cvt")]
5982 (define_insn "extendhfdf2"
5983 [(set (match_operand:DF
0 "register_operand" "=w")
5984 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
5987 [(set_attr "type" "f_cvt")]
5990 (define_insn "truncdfsf2"
5991 [(set (match_operand:SF
0 "register_operand" "=w")
5992 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
5995 [(set_attr "type" "f_cvt")]
5998 (define_insn "truncsfhf2"
5999 [(set (match_operand:HF
0 "register_operand" "=w")
6000 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
6003 [(set_attr "type" "f_cvt")]
6006 (define_insn "truncdfhf2"
6007 [(set (match_operand:HF
0 "register_operand" "=w")
6008 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
6011 [(set_attr "type" "f_cvt")]
6014 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
6015 ;; and making r = w more expensive
6017 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
6018 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
6019 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
6022 fcvtz<su>
\t%<s>
0, %<s>
1
6023 fcvtz<su>
\t%<w>
0, %<s>
1"
6024 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
6027 ;; Convert HF -> SI or DI
6029 (define_insn "<optab>_trunchf<GPI:mode>
2"
6030 [(set (match_operand:GPI
0 "register_operand" "=r")
6031 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
6033 "fcvtz<su>
\t%<w>
0, %h1"
6034 [(set_attr "type" "f_cvtf2i")]
6037 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
6038 ;; input in a fp register and output in a integer register
6040 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
6041 [(set (match_operand:GPI
0 "register_operand" "=r")
6042 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
6044 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
6045 [(set_attr "type" "f_cvtf2i")]
6048 (define_insn "*fix_to_zero_extend<mode>di2"
6049 [(set (match_operand:DI
0 "register_operand" "=r")
6052 (match_operand:GPF
1 "register_operand" "w"))))]
6054 "fcvtzu
\t%w0, %<s>
1"
6055 [(set_attr "type" "f_cvtf2i")]
6058 ;; Equal width integer to fp and multiply combine.
6059 (define_insn "*aarch64_<su_optab>cvtf<fcvt_target><GPF:mode>
2_mult"
6060 [(set (match_operand:GPF
0 "register_operand" "=w,w")
6061 (mult:GPF (FLOATUORS:GPF
6062 (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r"))
6063 (match_operand:GPF
2 "aarch64_fp_pow2_recip" "Dt,Dt")))]
6066 operands[
2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[
2]));
6067 switch (which_alternative)
6070 return "<su_optab>cvtf
\t%<GPF:s>
0, %<s>
1, #%
2";
6072 return "<su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1, #%
2";
6077 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6078 (set_attr "arch" "simd,fp")]
6081 ;; Unequal width integer to fp and multiply combine.
6082 (define_insn "*aarch64_<su_optab>cvtf<fcvt_iesize><GPF:mode>
2_mult"
6083 [(set (match_operand:GPF
0 "register_operand" "=w")
6084 (mult:GPF (FLOATUORS:GPF
6085 (match_operand:<FCVT_IESIZE>
1 "register_operand" "r"))
6086 (match_operand:GPF
2 "aarch64_fp_pow2_recip" "Dt")))]
6089 operands[
2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[
2]));
6090 return "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1, #%
2";
6092 [(set_attr "type" "f_cvti2f")]
6095 ;; Equal width integer to fp conversion.
6096 (define_insn "<optab><fcvt_target><GPF:mode>
2"
6097 [(set (match_operand:GPF
0 "register_operand" "=w,w")
6098 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
6101 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
6102 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
6103 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6104 (set_attr "arch" "simd,fp")]
6107 ;; Unequal width integer to fp conversions.
6108 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
6109 [(set (match_operand:GPF
0 "register_operand" "=w")
6110 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
6112 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
6113 [(set_attr "type" "f_cvti2f")]
6116 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
6117 ;; midend will arrange for an SImode conversion to HFmode to first go
6118 ;; through DFmode, then to HFmode. But first it will try converting
6119 ;; to DImode then down, which would match our DImode pattern below and
6120 ;; give very poor code-generation. So, we must provide our own emulation
6121 ;; of the mid-end logic.
6123 (define_insn "aarch64_fp16_<optab><mode>hf2"
6124 [(set (match_operand:HF
0 "register_operand" "=w")
6125 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
6127 "<su_optab>cvtf
\t%h0, %<w>
1"
6128 [(set_attr "type" "f_cvti2f")]
6131 (define_expand "<optab>sihf2"
6132 [(set (match_operand:HF
0 "register_operand")
6133 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
6136 if (TARGET_FP_F16INST)
6137 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
6140 rtx convert_target = gen_reg_rtx (DFmode);
6141 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
6142 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
6148 ;; For DImode there is no wide enough floating-point mode that we
6149 ;; can convert through natively (TFmode would work, but requires a library
6150 ;; call). However, we know that any value >=
65504 will be rounded
6151 ;; to infinity on conversion. This is well within the range of SImode, so
6153 ;; Saturate to SImode.
6154 ;; Convert from that to DFmode
6155 ;; Convert from that to HFmode (phew!).
6156 ;; Note that the saturation to SImode requires the SIMD extensions. If
6157 ;; we ever need to provide this pattern where the SIMD extensions are not
6158 ;; available, we would need a different approach.
6160 (define_expand "<optab>dihf2"
6161 [(set (match_operand:HF
0 "register_operand")
6162 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
6163 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6165 if (TARGET_FP_F16INST)
6166 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
6169 rtx sat_target = gen_reg_rtx (SImode);
6170 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
6171 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
6178 ;; Convert between fixed-point and floating-point (scalar modes)
6180 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
6181 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
6182 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
6183 (match_operand:SI
2 "immediate_operand" "i, i")]
6187 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
6188 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
6189 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6190 (set_attr "arch" "fp,simd")]
6193 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
6194 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
6195 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
6196 (match_operand:SI
2 "immediate_operand" "i, i")]
6200 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
6201 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
6202 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6203 (set_attr "arch" "fp,simd")]
6206 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
6207 [(set (match_operand:GPI
0 "register_operand" "=r")
6208 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
6209 (match_operand:SI
2 "immediate_operand" "i")]
6212 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
6213 [(set_attr "type" "f_cvtf2i")]
6216 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6217 [(set (match_operand:HF
0 "register_operand" "=w")
6218 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
6219 (match_operand:SI
2 "immediate_operand" "i")]
6222 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
6223 [(set_attr "type" "f_cvti2f")]
6226 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6227 [(set (match_operand:HI
0 "register_operand" "=w")
6228 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
6229 (match_operand:SI
2 "immediate_operand" "i")]
6232 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6233 [(set_attr "type" "neon_fp_to_int_s")]
6236 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6237 [(set (match_operand:HF
0 "register_operand" "=w")
6238 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
6239 (match_operand:SI
2 "immediate_operand" "i")]
6242 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
6243 [(set_attr "type" "neon_int_to_fp_s")]
6246 ;; -------------------------------------------------------------------
6247 ;; Floating-point arithmetic
6248 ;; -------------------------------------------------------------------
6250 (define_insn "add<mode>
3"
6251 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6253 (match_operand:GPF_F16
1 "register_operand" "w")
6254 (match_operand:GPF_F16
2 "register_operand" "w")))]
6256 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
6257 [(set_attr "type" "fadd<stype>")]
6260 (define_insn "sub<mode>
3"
6261 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6263 (match_operand:GPF_F16
1 "register_operand" "w")
6264 (match_operand:GPF_F16
2 "register_operand" "w")))]
6266 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
6267 [(set_attr "type" "fadd<stype>")]
6270 (define_insn "mul<mode>
3"
6271 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6273 (match_operand:GPF_F16
1 "register_operand" "w")
6274 (match_operand:GPF_F16
2 "register_operand" "w")))]
6276 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
6277 [(set_attr "type" "fmul<stype>")]
6280 (define_insn "*fnmul<mode>
3"
6281 [(set (match_operand:GPF
0 "register_operand" "=w")
6283 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
6284 (match_operand:GPF
2 "register_operand" "w")))]
6285 "TARGET_FLOAT && !flag_rounding_math"
6286 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6287 [(set_attr "type" "fmul<s>")]
6290 (define_insn "*fnmul<mode>
3"
6291 [(set (match_operand:GPF
0 "register_operand" "=w")
6293 (match_operand:GPF
1 "register_operand" "w")
6294 (match_operand:GPF
2 "register_operand" "w"))))]
6296 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
6297 [(set_attr "type" "fmul<s>")]
6300 (define_expand "div<mode>
3"
6301 [(set (match_operand:GPF_F16
0 "register_operand")
6302 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
6303 (match_operand:GPF_F16
2 "register_operand")))]
6306 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
6309 operands[
1] = force_reg (<MODE>mode, operands[
1]);
6312 (define_insn "*div<mode>
3"
6313 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6314 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
6315 (match_operand:GPF_F16
2 "register_operand" "w")))]
6317 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
6318 [(set_attr "type" "fdiv<stype>")]
6321 (define_insn "neg<mode>
2"
6322 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6323 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6325 "fneg
\\t%<s>
0, %<s>
1"
6326 [(set_attr "type" "ffarith<stype>")]
6329 (define_expand "sqrt<mode>
2"
6330 [(set (match_operand:GPF_F16
0 "register_operand")
6331 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand")))]
6334 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
6338 (define_insn "*sqrt<mode>
2"
6339 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6340 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6342 "fsqrt
\\t%<s>
0, %<s>
1"
6343 [(set_attr "type" "fsqrt<stype>")]
6346 (define_insn "abs<mode>
2"
6347 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6348 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
6350 "fabs
\\t%<s>
0, %<s>
1"
6351 [(set_attr "type" "ffarith<stype>")]
6354 ;; Given that smax/smin do not specify the result when either input is NaN,
6355 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6358 (define_insn "smax<mode>
3"
6359 [(set (match_operand:GPF
0 "register_operand" "=w")
6360 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
6361 (match_operand:GPF
2 "register_operand" "w")))]
6363 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
6364 [(set_attr "type" "f_minmax<s>")]
6367 (define_insn "smin<mode>
3"
6368 [(set (match_operand:GPF
0 "register_operand" "=w")
6369 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
6370 (match_operand:GPF
2 "register_operand" "w")))]
6372 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
6373 [(set_attr "type" "f_minmax<s>")]
6376 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6377 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
6378 ;; which implement the IEEE fmax ()/fmin () functions.
6379 (define_insn "<maxmin_uns><mode>
3"
6380 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
6381 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
6382 (match_operand:GPF_F16
2 "register_operand" "w")]
6385 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
6386 [(set_attr "type" "f_minmax<stype>")]
6389 (define_expand "lrint<GPF:mode><GPI:mode>
2"
6390 [(match_operand:GPI
0 "register_operand")
6391 (match_operand:GPF
1 "register_operand")]
6393 && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE)
6394 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6396 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6397 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
6398 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
6403 ;; For copysign (x, y), we want to generate:
6405 ;; LDR d2, #(
1 <<
63)
6406 ;; BSL v2.8b, [y], [x]
6408 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6409 ;; we expect these operations to nearly always operate on
6410 ;; floating-point values, we do not want the operation to be
6411 ;; simplified into a bit-field insert operation that operates on the
6412 ;; integer side, since typically that would involve three inter-bank
6413 ;; register copies. As we do not expect copysign to be followed by
6414 ;; other logical operations on the result, it seems preferable to keep
6415 ;; this as an unspec operation, rather than exposing the underlying
6416 ;; logic to the compiler.
6418 (define_expand "copysign<GPF:mode>
3"
6419 [(match_operand:GPF
0 "register_operand")
6420 (match_operand:GPF
1 "register_operand")
6421 (match_operand:GPF
2 "register_operand")]
6422 "TARGET_FLOAT && TARGET_SIMD"
6424 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6425 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6426 << (GET_MODE_BITSIZE (<MODE>mode) -
1)));
6427 emit_insn (gen_copysign<mode>
3_insn (operands[
0], operands[
1], operands[
2],
6433 (define_insn "copysign<GPF:mode>
3_insn"
6434 [(set (match_operand:GPF
0 "register_operand" "=w,w,w,r")
6435 (unspec:GPF [(match_operand:GPF
1 "register_operand" "w,
0,w,r")
6436 (match_operand:GPF
2 "register_operand" "w,w,
0,
0")
6437 (match_operand:<V_INT_EQUIV>
3 "register_operand" "
0,w,w,X")]
6439 "TARGET_FLOAT && TARGET_SIMD"
6441 bsl
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>
6442 bit
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
3.<Vbtype>
6443 bif
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
3.<Vbtype>
6444 bfxil
\\t%<w1>
0, %<w1>
1, #
0, <sizem1>"
6445 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6449 ;; For xorsign (x, y), we want to generate:
6452 ;; AND v3.8B, v1.8B, v2.8B
6453 ;; EOR v0.8B, v0.8B, v3.8B
6456 (define_expand "xorsign<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"
6463 machine_mode imode = <V_INT_EQUIV>mode;
6464 rtx mask = gen_reg_rtx (imode);
6465 rtx op1x = gen_reg_rtx (imode);
6466 rtx op2x = gen_reg_rtx (imode);
6468 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
6469 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6472 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
6473 lowpart_subreg (imode, operands[
2],
6475 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
6476 lowpart_subreg (imode, operands[
1],
6479 emit_move_insn (operands[
0],
6480 lowpart_subreg (<MODE>mode, op1x, imode));
6485 ;; -------------------------------------------------------------------
6487 ;; -------------------------------------------------------------------
6488 ;; Reload Scalar Floating point modes from constant pool.
6489 ;; The AArch64 port doesn't have __int128 constant move support.
6490 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
6491 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6492 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
6493 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
6494 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6497 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6498 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
6503 ;; Reload Vector modes from constant pool.
6504 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6505 [(set (match_operand:VALL
0 "register_operand" "=w")
6506 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
6507 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6510 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6511 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
6516 (define_expand "@aarch64_reload_mov<mode>"
6517 [(set (match_operand:TX
0 "register_operand" "=w")
6518 (match_operand:TX
1 "register_operand" "w"))
6519 (clobber (match_operand:DI
2 "register_operand" "=&r"))
6523 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
6524 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
6525 gen_aarch64_movtilow_tilow (op0, op1);
6526 gen_aarch64_movdi_tihigh (operands[
2], op1);
6527 gen_aarch64_movtihigh_di (op0, operands[
2]);
6532 ;; The following secondary reload helpers patterns are invoked
6533 ;; after or during reload as we don't want these patterns to start
6534 ;; kicking in during the combiner.
6536 (define_insn "@aarch64_movdi_<mode>low"
6537 [(set (match_operand:DI
0 "register_operand" "=r")
6538 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6539 (const_int
64) (const_int
0)))]
6540 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6542 [(set_attr "type" "f_mrc")
6543 (set_attr "length" "
4")
6546 (define_insn "@aarch64_movdi_<mode>high"
6547 [(set (match_operand:DI
0 "register_operand" "=r")
6548 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6549 (const_int
64) (const_int
64)))]
6550 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6551 "fmov
\\t%x0, %
1.d[
1]"
6552 [(set_attr "type" "f_mrc")
6553 (set_attr "length" "
4")
6556 (define_insn "@aarch64_mov<mode>high_di"
6557 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
6558 (const_int
64) (const_int
64))
6559 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6560 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6561 "fmov
\\t%
0.d[
1], %x1"
6562 [(set_attr "type" "f_mcr")
6563 (set_attr "length" "
4")
6566 (define_insn "@aarch64_mov<mode>low_di"
6567 [(set (match_operand:TX
0 "register_operand" "=w")
6568 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6569 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6571 [(set_attr "type" "f_mcr")
6572 (set_attr "length" "
4")
6575 (define_insn "aarch64_movtilow_tilow"
6576 [(set (match_operand:TI
0 "register_operand" "=w")
6578 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
6579 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6581 [(set_attr "type" "fmov")
6582 (set_attr "length" "
4")
6585 ;; There is a deliberate reason why the parameters of high and lo_sum's
6586 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6587 ;; and lo_sum's to be used with the labels defining the jump tables in
6590 (define_expand "add_losym"
6591 [(set (match_operand
0 "register_operand")
6592 (lo_sum (match_operand
1 "register_operand")
6593 (match_operand
2 "aarch64_valid_symref")))]
6596 machine_mode mode = GET_MODE (operands[
0]);
6598 emit_insn ((mode == DImode
6600 : gen_add_losym_si) (operands[
0],
6606 (define_insn "add_losym_<mode>"
6607 [(set (match_operand:P
0 "register_operand" "=r")
6608 (lo_sum:P (match_operand:P
1 "register_operand" "r")
6609 (match_operand
2 "aarch64_valid_symref" "S")))]
6611 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
6612 [(set_attr "type" "alu_imm")]
6615 (define_insn "ldr_got_small_<mode>"
6616 [(set (match_operand:PTR
0 "register_operand" "=r")
6617 (unspec:PTR [(mem:PTR (lo_sum:PTR
6618 (match_operand:PTR
1 "register_operand" "r")
6619 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6620 UNSPEC_GOTSMALLPIC))]
6622 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
6623 [(set_attr "type" "load_<ldst_sz>")]
6626 (define_insn "ldr_got_small_sidi"
6627 [(set (match_operand:DI
0 "register_operand" "=r")
6629 (unspec:SI [(mem:SI (lo_sum:DI
6630 (match_operand:DI
1 "register_operand" "r")
6631 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6632 UNSPEC_GOTSMALLPIC)))]
6634 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
6635 [(set_attr "type" "load_4")]
6638 (define_insn "ldr_got_small_28k_<mode>"
6639 [(set (match_operand:PTR
0 "register_operand" "=r")
6640 (unspec:PTR [(mem:PTR (lo_sum:PTR
6641 (match_operand:PTR
1 "register_operand" "r")
6642 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6643 UNSPEC_GOTSMALLPIC28K))]
6645 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
6646 [(set_attr "type" "load_<ldst_sz>")]
6649 (define_insn "ldr_got_small_28k_sidi"
6650 [(set (match_operand:DI
0 "register_operand" "=r")
6652 (unspec:SI [(mem:SI (lo_sum:DI
6653 (match_operand:DI
1 "register_operand" "r")
6654 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6655 UNSPEC_GOTSMALLPIC28K)))]
6657 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
6658 [(set_attr "type" "load_4")]
6661 (define_insn "ldr_got_tiny"
6662 [(set (match_operand:DI
0 "register_operand" "=r")
6663 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
6664 UNSPEC_GOTTINYPIC))]
6667 [(set_attr "type" "load_8")]
6670 (define_insn "aarch64_load_tp_hard"
6671 [(set (match_operand:DI
0 "register_operand" "=r")
6672 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
6674 "mrs
\\t%
0, tpidr_el0"
6675 [(set_attr "type" "mrs")]
6678 ;; The TLS ABI specifically requires that the compiler does not schedule
6679 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6680 ;; Therefore we treat the stubs as an atomic sequence.
6681 (define_expand "tlsgd_small_<mode>"
6682 [(parallel [(set (match_operand
0 "register_operand")
6683 (call (mem:DI (match_dup
2)) (const_int
1)))
6684 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
6685 (clobber (reg:DI LR_REGNUM))])]
6688 operands[
2] = aarch64_tls_get_addr ();
6691 (define_insn "*tlsgd_small_<mode>"
6692 [(set (match_operand
0 "register_operand" "")
6693 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
6694 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6695 (clobber (reg:DI LR_REGNUM))
6698 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
6699 [(set_attr "type" "call")
6700 (set_attr "length" "
16")])
6702 (define_insn "tlsie_small_<mode>"
6703 [(set (match_operand:PTR
0 "register_operand" "=r")
6704 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6705 UNSPEC_GOTSMALLTLS))]
6707 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
6708 [(set_attr "type" "load_4")
6709 (set_attr "length" "
8")]
6712 (define_insn "tlsie_small_sidi"
6713 [(set (match_operand:DI
0 "register_operand" "=r")
6715 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6716 UNSPEC_GOTSMALLTLS)))]
6718 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
6719 [(set_attr "type" "load_4")
6720 (set_attr "length" "
8")]
6723 (define_insn "tlsie_tiny_<mode>"
6724 [(set (match_operand:PTR
0 "register_operand" "=&r")
6725 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
6726 (match_operand:PTR
2 "register_operand" "r")]
6727 UNSPEC_GOTTINYTLS))]
6729 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
6730 [(set_attr "type" "multiple")
6731 (set_attr "length" "
8")]
6734 (define_insn "tlsie_tiny_sidi"
6735 [(set (match_operand:DI
0 "register_operand" "=&r")
6737 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
6738 (match_operand:DI
2 "register_operand" "r")
6740 UNSPEC_GOTTINYTLS)))]
6742 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
6743 [(set_attr "type" "multiple")
6744 (set_attr "length" "
8")]
6747 (define_insn "tlsle12_<mode>"
6748 [(set (match_operand:P
0 "register_operand" "=r")
6749 (unspec:P [(match_operand:P
1 "register_operand" "r")
6750 (match_operand
2 "aarch64_tls_le_symref" "S")]
6753 "add
\\t%<w>
0, %<w>
1, #%L2";
6754 [(set_attr "type" "alu_sreg")
6755 (set_attr "length" "
4")]
6758 (define_insn "tlsle24_<mode>"
6759 [(set (match_operand:P
0 "register_operand" "=r")
6760 (unspec:P [(match_operand:P
1 "register_operand" "r")
6761 (match_operand
2 "aarch64_tls_le_symref" "S")]
6764 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
6765 [(set_attr "type" "multiple")
6766 (set_attr "length" "
8")]
6769 (define_insn "tlsle32_<mode>"
6770 [(set (match_operand:P
0 "register_operand" "=r")
6771 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6774 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6775 [(set_attr "type" "multiple")
6776 (set_attr "length" "
8")]
6779 (define_insn "tlsle48_<mode>"
6780 [(set (match_operand:P
0 "register_operand" "=r")
6781 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6784 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6785 [(set_attr "type" "multiple")
6786 (set_attr "length" "
12")]
6789 (define_expand "tlsdesc_small_<mode>"
6790 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6794 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[
0]));
6796 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
6801 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6803 (define_insn "tlsdesc_small_advsimd_<mode>"
6804 [(set (reg:PTR R0_REGNUM)
6805 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6807 (clobber (reg:DI LR_REGNUM))
6808 (clobber (reg:CC CC_REGNUM))
6809 (clobber (match_scratch:DI
1 "=r"))
6810 (use (reg:DI FP_REGNUM))]
6811 "TARGET_TLS_DESC && !TARGET_SVE"
6812 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6813 [(set_attr "type" "call")
6814 (set_attr "length" "
16")])
6816 ;; For SVE, model tlsdesc calls as clobbering the lower
128 bits of
6817 ;; all vector registers, and clobber all predicate registers, on
6818 ;; top of the usual R0 and LR.
6819 (define_insn "tlsdesc_small_sve_<mode>"
6820 [(set (reg:PTR R0_REGNUM)
6821 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6823 (clobber (reg:DI LR_REGNUM))
6824 (clobber (reg:CC CC_REGNUM))
6825 (clobber_high (reg:TI V0_REGNUM))
6826 (clobber_high (reg:TI V1_REGNUM))
6827 (clobber_high (reg:TI V2_REGNUM))
6828 (clobber_high (reg:TI V3_REGNUM))
6829 (clobber_high (reg:TI V4_REGNUM))
6830 (clobber_high (reg:TI V5_REGNUM))
6831 (clobber_high (reg:TI V6_REGNUM))
6832 (clobber_high (reg:TI V7_REGNUM))
6833 (clobber_high (reg:TI V8_REGNUM))
6834 (clobber_high (reg:TI V9_REGNUM))
6835 (clobber_high (reg:TI V10_REGNUM))
6836 (clobber_high (reg:TI V11_REGNUM))
6837 (clobber_high (reg:TI V12_REGNUM))
6838 (clobber_high (reg:TI V13_REGNUM))
6839 (clobber_high (reg:TI V14_REGNUM))
6840 (clobber_high (reg:TI V15_REGNUM))
6841 (clobber_high (reg:TI V16_REGNUM))
6842 (clobber_high (reg:TI V17_REGNUM))
6843 (clobber_high (reg:TI V18_REGNUM))
6844 (clobber_high (reg:TI V19_REGNUM))
6845 (clobber_high (reg:TI V20_REGNUM))
6846 (clobber_high (reg:TI V21_REGNUM))
6847 (clobber_high (reg:TI V22_REGNUM))
6848 (clobber_high (reg:TI V23_REGNUM))
6849 (clobber_high (reg:TI V24_REGNUM))
6850 (clobber_high (reg:TI V25_REGNUM))
6851 (clobber_high (reg:TI V26_REGNUM))
6852 (clobber_high (reg:TI V27_REGNUM))
6853 (clobber_high (reg:TI V28_REGNUM))
6854 (clobber_high (reg:TI V29_REGNUM))
6855 (clobber_high (reg:TI V30_REGNUM))
6856 (clobber_high (reg:TI V31_REGNUM))
6857 (clobber (reg:VNx2BI P0_REGNUM))
6858 (clobber (reg:VNx2BI P1_REGNUM))
6859 (clobber (reg:VNx2BI P2_REGNUM))
6860 (clobber (reg:VNx2BI P3_REGNUM))
6861 (clobber (reg:VNx2BI P4_REGNUM))
6862 (clobber (reg:VNx2BI P5_REGNUM))
6863 (clobber (reg:VNx2BI P6_REGNUM))
6864 (clobber (reg:VNx2BI P7_REGNUM))
6865 (clobber (reg:VNx2BI P8_REGNUM))
6866 (clobber (reg:VNx2BI P9_REGNUM))
6867 (clobber (reg:VNx2BI P10_REGNUM))
6868 (clobber (reg:VNx2BI P11_REGNUM))
6869 (clobber (reg:VNx2BI P12_REGNUM))
6870 (clobber (reg:VNx2BI P13_REGNUM))
6871 (clobber (reg:VNx2BI P14_REGNUM))
6872 (clobber (reg:VNx2BI P15_REGNUM))
6873 (clobber (match_scratch:DI
1 "=r"))
6874 (use (reg:DI FP_REGNUM))]
6875 "TARGET_TLS_DESC && TARGET_SVE"
6876 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6877 [(set_attr "type" "call")
6878 (set_attr "length" "
16")])
6880 (define_insn "stack_tie"
6881 [(set (mem:BLK (scratch))
6882 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
6883 (match_operand:DI
1 "register_operand" "rk")]
6887 [(set_attr "length" "
0")]
6890 ;; Pointer authentication patterns are always provided. In architecture
6891 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6892 ;; This lets the user write portable software which authenticates pointers
6893 ;; when run on something which implements ARMv8.3-A, and which runs
6894 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6897 ;; Signing/Authenticating R30 using SP as the salt.
6899 (define_insn "<pauth_mnem_prefix>sp"
6900 [(set (reg:DI R30_REGNUM)
6901 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6903 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6906 ;; Signing/Authenticating X17 using X16 as the salt.
6908 (define_insn "<pauth_mnem_prefix>
1716"
6909 [(set (reg:DI R17_REGNUM)
6910 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6912 "hint
\t<pauth_hint_num> // <pauth_mnem_prefix>
1716";
6915 ;; Stripping the signature in R30.
6917 (define_insn "xpaclri"
6918 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6920 "hint
\t7 // xpaclri"
6923 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6924 ;; all of memory. This blocks insns from being moved across this point.
6926 (define_insn "blockage"
6927 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
6930 [(set_attr "length" "
0")
6931 (set_attr "type" "block")]
6934 (define_insn "probe_stack_range"
6935 [(set (match_operand:DI
0 "register_operand" "=rk")
6936 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
6937 (match_operand:DI
2 "register_operand" "r")]
6938 UNSPECV_PROBE_STACK_RANGE))]
6941 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
6943 [(set_attr "length" "
32")]
6946 ;; This instruction is used to generate the stack clash stack adjustment and
6947 ;; probing loop. We can't change the control flow during prologue and epilogue
6948 ;; code generation. So we must emit a volatile unspec and expand it later on.
6950 (define_insn "@probe_sve_stack_clash_<mode>"
6951 [(set (match_operand:P
0 "register_operand" "=rk")
6952 (unspec_volatile:P [(match_operand:P
1 "register_operand" "
0")
6953 (match_operand:P
2 "register_operand" "r")
6954 (match_operand:P
3 "const_int_operand" "n")
6955 (match_operand:P
4 "aarch64_plus_immediate" "L")]
6956 UNSPECV_PROBE_STACK_RANGE))]
6959 return aarch64_output_probe_sve_stack_clash (operands[
0], operands[
2],
6960 operands[
3], operands[
4]);
6962 [(set_attr "length" "
28")]
6965 ;; Named pattern for expanding thread pointer reference.
6966 (define_expand "get_thread_pointerdi"
6967 [(match_operand:DI
0 "register_operand")]
6970 rtx tmp = aarch64_load_tp (operands[
0]);
6971 if (tmp != operands[
0])
6972 emit_move_insn (operands[
0], tmp);
6976 ;; Named patterns for stack smashing protection.
6977 (define_expand "stack_protect_set"
6978 [(match_operand
0 "memory_operand")
6979 (match_operand
1 "memory_operand")]
6982 machine_mode mode = GET_MODE (operands[
0]);
6983 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6985 /* Generate access through the system register. */
6986 rtx tmp_reg = gen_reg_rtx (mode);
6989 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6990 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6991 GEN_INT (aarch64_stack_protector_guard_offset)));
6995 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
6996 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
6997 GEN_INT (aarch64_stack_protector_guard_offset)));
7000 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
7003 emit_insn ((mode == DImode
7004 ? gen_stack_protect_set_di
7005 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
7009 (define_insn "reg_stack_protect_address_<mode>"
7010 [(set (match_operand:PTR
0 "register_operand" "=r")
7011 (unspec:PTR [(const_int
0)]
7012 UNSPEC_SSP_SYSREG))]
7013 "aarch64_stack_protector_guard != SSP_GLOBAL"
7016 snprintf (buf,
150, "mrs
\\t%%<w>
0, %s",
7017 aarch64_stack_protector_guard_reg_str);
7018 output_asm_insn (buf, operands);
7021 [(set_attr "type" "mrs")])
7023 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
7024 ;; canary value does not live beyond the life of this sequence.
7025 (define_insn "stack_protect_set_<mode>"
7026 [(set (match_operand:PTR
0 "memory_operand" "=m")
7027 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
7029 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
7031 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
7032 [(set_attr "length" "
12")
7033 (set_attr "type" "multiple")])
7035 (define_expand "stack_protect_test"
7036 [(match_operand
0 "memory_operand")
7037 (match_operand
1 "memory_operand")
7042 machine_mode mode = GET_MODE (operands[
0]);
7044 result = gen_reg_rtx(mode);
7045 if (aarch64_stack_protector_guard != SSP_GLOBAL)
7047 /* Generate access through the system register. The
7048 sequence we want here is the access
7049 of the stack offset to come with
7050 mrs scratch_reg, <system_register>
7051 add scratch_reg, scratch_reg, :lo12:offset. */
7052 rtx tmp_reg = gen_reg_rtx (mode);
7055 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
7056 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
7057 GEN_INT (aarch64_stack_protector_guard_offset)));
7061 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
7062 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
7063 GEN_INT (aarch64_stack_protector_guard_offset)));
7066 operands[
1] = gen_rtx_MEM (mode, tmp_reg);
7068 emit_insn ((mode == DImode
7069 ? gen_stack_protect_test_di
7070 : gen_stack_protect_test_si) (result,
7075 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7076 result, const0_rtx, operands[
2]));
7078 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7079 result, const0_rtx, operands[
2]));
7083 (define_insn "stack_protect_test_<mode>"
7084 [(set (match_operand:PTR
0 "register_operand" "=r")
7085 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
7086 (match_operand:PTR
2 "memory_operand" "m")]
7088 (clobber (match_scratch:PTR
3 "=&r"))]
7090 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
7091 [(set_attr "length" "
12")
7092 (set_attr "type" "multiple")])
7094 ;; Write Floating-point Control Register.
7095 (define_insn "set_fpcr"
7096 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
7099 [(set_attr "type" "mrs")])
7101 ;; Read Floating-point Control Register.
7102 (define_insn "get_fpcr"
7103 [(set (match_operand:SI
0 "register_operand" "=r")
7104 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
7107 [(set_attr "type" "mrs")])
7109 ;; Write Floating-point Status Register.
7110 (define_insn "set_fpsr"
7111 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
7114 [(set_attr "type" "mrs")])
7116 ;; Read Floating-point Status Register.
7117 (define_insn "get_fpsr"
7118 [(set (match_operand:SI
0 "register_operand" "=r")
7119 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
7122 [(set_attr "type" "mrs")])
7125 ;; Define the subtract-one-and-jump insns so loop.c
7126 ;; knows what to generate.
7127 (define_expand "doloop_end"
7128 [(use (match_operand
0 "" "")) ; loop pseudo
7129 (use (match_operand
1 "" ""))] ; label
7130 "optimize >
0 && flag_modulo_sched"
7139 /* Currently SMS relies on the do-loop pattern to recognize loops
7140 where (
1) the control part consists of all insns defining and/or
7141 using a certain 'count' register and (
2) the loop count can be
7142 adjusted by modifying this register prior to the loop.
7143 ??? The possible introduction of a new block to initialize the
7144 new IV can potentially affect branch optimizations. */
7146 if (GET_MODE (operands[
0]) != DImode)
7150 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
7152 cmp = XVECEXP (PATTERN (insn),
0,
0);
7153 cc_reg = SET_DEST (cmp);
7154 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7155 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
7156 emit_jump_insn (gen_rtx_SET (pc_rtx,
7157 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7162 ;; Track speculation through conditional branches. We assume that
7163 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7164 (define_insn "speculation_tracker"
7165 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7166 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand
0)]
7167 UNSPEC_SPECULATION_TRACKER))]
7170 operands[
1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7171 output_asm_insn ("csel
\\t%
1, %
1, xzr, %m0", operands);
7174 [(set_attr "type" "csel")]
7177 ;; BTI <target> instructions
7178 (define_insn "bti_noarg"
7179 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_NOARG)]
7182 [(set_attr "type" "no_insn")]
7185 (define_insn "bti_c"
7186 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_C)]
7189 [(set_attr "type" "no_insn")]
7192 (define_insn "bti_j"
7193 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_J)]
7196 [(set_attr "type" "no_insn")]
7199 (define_insn "bti_jc"
7200 [(unspec_volatile [(const_int
0)] UNSPECV_BTI_JC)]
7202 "hint
\t38 // bti jc"
7203 [(set_attr "type" "no_insn")]
7206 ;; Hard speculation barrier.
7207 (define_insn "speculation_barrier"
7208 [(unspec_volatile [(const_int
0)] UNSPECV_SPECULATION_BARRIER)]
7211 [(set_attr "length" "
8")
7212 (set_attr "type" "block")
7213 (set_attr "speculation_barrier" "true")]
7216 ;; Support for __builtin_speculation_safe_value when we have speculation
7217 ;; tracking enabled. Use the speculation tracker to decide whether to
7218 ;; copy operand
1 to the target, or to copy the fail value (operand
2).
7219 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7220 [(set (match_operand:ALLI_TI
0 "register_operand")
7221 (unspec_volatile:ALLI_TI
7222 [(match_operand:ALLI_TI
1 "register_operand")
7223 (match_operand:ALLI_TI
2 "aarch64_reg_or_zero")
7224 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7225 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7229 if (operands[
2] == const0_rtx)
7232 if (<MODE>mode == TImode)
7233 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7235 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7237 emit_insn (gen_despeculate_simple<mode> (operands[
0], operands[
1],
7245 ;; Patterns to match despeculate_copy<mode>. Note that "hint
0x14" is the
7246 ;; encoding for CSDB, but will work in older versions of the assembler.
7247 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7248 [(set (match_operand:ALLI
0 "register_operand" "=r")
7249 (unspec_volatile:ALLI
7250 [(match_operand:ALLI
1 "register_operand" "r")
7251 (match_operand:ALLI
2 "aarch64_reg_or_zero" "rZ")
7252 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7253 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7256 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7257 output_asm_insn ("cmp
\\t%
3, #
0\;csel
\\t%<w>
0, %<w>
1, %<w>
2, ne\;hint
\t0x14 // csdb",
7261 [(set_attr "length" "
12")
7262 (set_attr "type" "block")
7263 (set_attr "speculation_barrier" "true")]
7266 ;; Pattern to match despeculate_copyti
7267 (define_insn "*despeculate_copyti_insn"
7268 [(set (match_operand:TI
0 "register_operand" "=r")
7270 [(match_operand:TI
1 "register_operand" "r")
7271 (match_operand:TI
2 "aarch64_reg_or_zero" "rZ")
7272 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7273 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7276 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7278 ("cmp
\\t%
3, #
0\;csel
\\t%
0, %
1, %
2, ne\;csel
\\t%H0, %H1, %H2, ne\;hint
\t0x14 // csdb",
7282 [(set_attr "length" "
16")
7283 (set_attr "type" "block")
7284 (set_attr "speculation_barrier" "true")]
7287 (define_insn "despeculate_simple<ALLI:mode>"
7288 [(set (match_operand:ALLI
0 "register_operand" "=r")
7289 (unspec_volatile:ALLI
7290 [(match_operand:ALLI
1 "register_operand" "r")
7291 (use (match_operand:ALLI
2 "register_operand" ""))]
7292 UNSPECV_SPECULATION_BARRIER))]
7294 "and
\\t%<w>
0, %<w>
1, %<w>
2\;hint
\t0x14 // csdb"
7295 [(set_attr "type" "block")
7296 (set_attr "length" "
8")
7297 (set_attr "speculation_barrier" "true")]
7300 (define_insn "despeculate_simpleti"
7301 [(set (match_operand:TI
0 "register_operand" "=r")
7303 [(match_operand:TI
1 "register_operand" "r")
7304 (use (match_operand:DI
2 "register_operand" ""))]
7305 UNSPECV_SPECULATION_BARRIER))]
7307 "and
\\t%
0, %
1, %
2\;and
\\t%H0, %H1, %
2\;hint
\t0x14 // csdb"
7308 [(set_attr "type" "block")
7309 (set_attr "length" "
12")
7310 (set_attr "speculation_barrier" "true")]
7313 (define_insn "aarch64_<frintnzs_op><mode>"
7314 [(set (match_operand:VSFDF
0 "register_operand" "=w")
7315 (unspec:VSFDF [(match_operand:VSFDF
1 "register_operand" "w")]
7317 "TARGET_FRINT && TARGET_FLOAT
7318 && !(VECTOR_MODE_P (<MODE>mode) && !TARGET_SIMD)"
7319 "<frintnzs_op>
\\t%<v>
0<Vmtype>, %<v>
1<Vmtype>"
7320 [(set_attr "type" "f_rint<stype>")]
7323 ;; Transactional Memory Extension (TME) instructions.
7325 (define_insn "tstart"
7326 [(set (match_operand:DI
0 "register_operand" "=r")
7327 (unspec_volatile:DI [(const_int
0)] UNSPECV_TSTART))
7328 (clobber (mem:BLK (scratch)))]
7331 [(set_attr "type" "tme")]
7334 (define_insn "ttest"
7335 [(set (match_operand:DI
0 "register_operand" "=r")
7336 (unspec_volatile:DI [(const_int
0)] UNSPEC_TTEST))
7337 (clobber (mem:BLK (scratch)))]
7340 [(set_attr "type" "tme")]
7343 (define_insn "tcommit"
7344 [(unspec_volatile:BLK [(const_int
0)] UNSPECV_TCOMMIT)
7345 (clobber (mem:BLK (scratch)))]
7348 [(set_attr "type" "tme")]
7351 (define_insn "tcancel"
7352 [(unspec_volatile:BLK
7353 [(match_operand
0 "const_int_operand" "n")] UNSPECV_TCANCEL)
7354 (clobber (mem:BLK (scratch)))]
7355 "TARGET_TME && (UINTVAL (operands[
0]) <=
65535)"
7357 [(set_attr "type" "tme")]
7361 (include "aarch64-simd.md")
7363 ;; Atomic Operations
7364 (include "atomics.md")
7366 ;; ldp/stp peephole patterns
7367 (include "aarch64-ldpstp.md")
7370 (include "aarch64-sve.md")
7373 (include "aarch64-sve2.md")