1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C)
2009-
2018 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version
3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
91 (LAST_SAVED_REGNUM
63)
95 ;; Defined only to make the DWARF description simpler.
113 ;; A couple of call-clobbered registers that we need to reserve when
114 ;; tracking speculation this is not ABI, so is subject to change.
115 (SPECULATION_TRACKER_REGNUM
15)
116 (SPECULATION_SCRATCH_REGNUM
14)
120 (define_c_enum "unspec" [
146 UNSPEC_GOTSMALLPIC28K
224 UNSPEC_SPECULATION_TRACKER
227 (define_c_enum "unspecv" [
228 UNSPECV_EH_RETURN ; Represent EH_RETURN
229 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
230 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
231 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
232 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
233 UNSPECV_BLOCKAGE ; Represent a blockage
234 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
235 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
239 ;; If further include files are added the defintion of MD_INCLUDES
242 (include "constraints.md")
243 (include "predicates.md")
244 (include "iterators.md")
246 ;; -------------------------------------------------------------------
247 ;; Instruction types and attributes
248 ;; -------------------------------------------------------------------
250 ; The "type" attribute is included here from AArch32 backend to be able
251 ; to share pipeline descriptions.
252 (include "../arm/types.md")
254 ;; It is important to set the fp or simd attributes to yes when a pattern
255 ;; alternative uses the FP or SIMD register files, usually signified by use of
256 ;; the 'w' constraint. This will ensure that the alternative will be
257 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
258 ;; architecture extensions. If all the alternatives in a pattern use the
259 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
262 ;; Attributes of the architecture required to support the instruction (or
263 ;; alternative). This attribute is used to compute attribute "enabled", use type
264 ;; "any" to enable an alternative in all cases.
266 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
268 (define_enum_attr "arch" "arches" (const_string "any"))
270 ;; [For compatibility with Arm in pipeline models]
271 ;; Attribute that specifies whether or not the instruction touches fp
273 ;; Note that this attribute is not used anywhere in either the arm or aarch64
274 ;; backends except in the scheduling description for xgene1. In that
275 ;; scheduling description this attribute is used to subclass the load_4 and
277 (define_attr "fp" "no,yes"
279 (eq_attr "arch" "fp")
281 (const_string "no")))
283 (define_attr "arch_enabled" "no,yes"
286 (eq_attr "arch" "any")
288 (and (eq_attr "arch" "rcpc8_4")
289 (match_test "AARCH64_ISA_RCPC8_4"))
291 (and (eq_attr "arch" "fp")
292 (match_test "TARGET_FLOAT"))
294 (and (eq_attr "arch" "simd")
295 (match_test "TARGET_SIMD"))
297 (and (eq_attr "arch" "fp16")
298 (match_test "TARGET_FP_F16INST"))
300 (and (eq_attr "arch" "sve")
301 (match_test "TARGET_SVE")))
303 (const_string "no")))
305 ;; Attribute that controls whether an alternative is enabled or not.
306 ;; Currently it is only used to disable alternatives which touch fp or simd
307 ;; registers when -mgeneral-regs-only is specified or to require a special
308 ;; architecture support.
309 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
311 ;; Attribute that specifies whether we are dealing with a branch to a
312 ;; label that is far away, i.e. further away than the maximum/minimum
313 ;; representable in a signed
21-bits number.
316 (define_attr "far_branch" "" (const_int
0))
318 ;; Attribute that specifies whether the alternative uses MOVPRFX.
319 (define_attr "movprfx" "no,yes" (const_string "no"))
321 (define_attr "length" ""
322 (cond [(eq_attr "movprfx" "yes")
326 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
327 ;; no predicated insns.
328 (define_attr "predicated" "yes,no" (const_string "no"))
330 ;; Set to true on an insn that requires the speculation tracking state to be
331 ;; in the tracking register before the insn issues. Otherwise the compiler
332 ;; may chose to hold the tracking state encoded in SP.
333 (define_attr "speculation_barrier" "true,false" (const_string "false"))
335 ;; -------------------------------------------------------------------
336 ;; Pipeline descriptions and scheduling
337 ;; -------------------------------------------------------------------
340 (include "aarch64-tune.md")
343 (include "../arm/cortex-a53.md")
344 (include "../arm/cortex-a57.md")
345 (include "../arm/exynos-m1.md")
346 (include "falkor.md")
347 (include "thunderx.md")
348 (include "../arm/xgene1.md")
349 (include "thunderx2t99.md")
351 ;; -------------------------------------------------------------------
352 ;; Jumps and other miscellaneous insns
353 ;; -------------------------------------------------------------------
355 (define_insn "indirect_jump"
356 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
359 [(set_attr "type" "branch")]
363 [(set (pc) (label_ref (match_operand
0 "" "")))]
366 [(set_attr "type" "branch")]
369 (define_expand "cbranch<mode>
4"
370 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
371 [(match_operand:GPI
1 "register_operand" "")
372 (match_operand:GPI
2 "aarch64_plus_operand" "")])
373 (label_ref (match_operand
3 "" ""))
377 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
379 operands[
2] = const0_rtx;
383 (define_expand "cbranch<mode>
4"
384 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
385 [(match_operand:GPF
1 "register_operand" "")
386 (match_operand:GPF
2 "aarch64_fp_compare_operand" "")])
387 (label_ref (match_operand
3 "" ""))
391 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
393 operands[
2] = const0_rtx;
397 (define_expand "cbranchcc4"
398 [(set (pc) (if_then_else
399 (match_operator
0 "aarch64_comparison_operator"
400 [(match_operand
1 "cc_register" "")
401 (match_operand
2 "const0_operand")])
402 (label_ref (match_operand
3 "" ""))
407 (define_insn "ccmp<mode>"
408 [(set (match_operand:CC
1 "cc_register" "")
410 (match_operator
4 "aarch64_comparison_operator"
411 [(match_operand
0 "cc_register" "")
414 (match_operand:GPI
2 "register_operand" "r,r,r")
415 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
416 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
419 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
420 ccmp
\\t%<w>
2, %
3, %k5, %m4
421 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
422 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
425 (define_insn "fccmp<mode>"
426 [(set (match_operand:CCFP
1 "cc_register" "")
428 (match_operator
4 "aarch64_comparison_operator"
429 [(match_operand
0 "cc_register" "")
432 (match_operand:GPF
2 "register_operand" "w")
433 (match_operand:GPF
3 "register_operand" "w"))
434 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
436 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
437 [(set_attr "type" "fccmp<s>")]
440 (define_insn "fccmpe<mode>"
441 [(set (match_operand:CCFPE
1 "cc_register" "")
443 (match_operator
4 "aarch64_comparison_operator"
444 [(match_operand
0 "cc_register" "")
447 (match_operand:GPF
2 "register_operand" "w")
448 (match_operand:GPF
3 "register_operand" "w"))
449 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
451 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
452 [(set_attr "type" "fccmp<s>")]
455 ;; Expansion of signed mod by a power of
2 using CSNEG.
456 ;; For x0 % n where n is a power of
2 produce:
458 ;; and x0, x0, #(n -
1)
459 ;; and x1, x1, #(n -
1)
460 ;; csneg x0, x0, x1, mi
462 (define_expand "mod<mode>
3"
463 [(match_operand:GPI
0 "register_operand" "")
464 (match_operand:GPI
1 "register_operand" "")
465 (match_operand:GPI
2 "const_int_operand" "")]
468 HOST_WIDE_INT val = INTVAL (operands[
2]);
471 || exact_log2 (val) <=
0
472 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
475 rtx mask = GEN_INT (val -
1);
477 /* In the special case of x0 %
2 we can do the even shorter:
483 rtx masked = gen_reg_rtx (<MODE>mode);
484 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
485 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
486 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
487 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
491 rtx neg_op = gen_reg_rtx (<MODE>mode);
492 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
494 /* Extract the condition register and mode. */
495 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
496 rtx cc_reg = SET_DEST (cmp);
497 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
499 rtx masked_pos = gen_reg_rtx (<MODE>mode);
500 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
502 rtx masked_neg = gen_reg_rtx (<MODE>mode);
503 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
505 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
506 masked_neg, masked_pos));
511 (define_insn "condjump"
512 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
513 [(match_operand
1 "cc_register" "") (const_int
0)])
514 (label_ref (match_operand
2 "" ""))
518 if (get_attr_length (insn) ==
8)
519 return aarch64_gen_far_branch (operands,
2, "Lbcond", "b%M0
\\t");
523 [(set_attr "type" "branch")
525 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
526 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
529 (set (attr "far_branch")
530 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
531 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
536 ;; For a
24-bit immediate CST we can optimize the compare for equality
537 ;; and branch sequence from:
539 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
543 ;; sub x0, x1, #(CST &
0xfff000)
544 ;; subs x0, x0, #(CST &
0x000fff)
546 (define_insn_and_split "*compare_condjump<mode>"
547 [(set (pc) (if_then_else (EQL
548 (match_operand:GPI
0 "register_operand" "r")
549 (match_operand:GPI
1 "aarch64_imm24" "n"))
550 (label_ref:P (match_operand
2 "" ""))
552 "!aarch64_move_imm (INTVAL (operands[
1]), <MODE>mode)
553 && !aarch64_plus_operand (operands[
1], <MODE>mode)
554 && !reload_completed"
559 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
560 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
561 rtx tmp = gen_reg_rtx (<MODE>mode);
562 emit_insn (gen_add<mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
563 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
564 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
565 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
566 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
571 (define_expand "casesi"
572 [(match_operand:SI
0 "register_operand" "") ; Index
573 (match_operand:SI
1 "const_int_operand" "") ; Lower bound
574 (match_operand:SI
2 "const_int_operand" "") ; Total range
575 (match_operand:DI
3 "" "") ; Table label
576 (match_operand:DI
4 "" "")] ; Out of range label
579 if (operands[
1] != const0_rtx)
581 rtx reg = gen_reg_rtx (SImode);
583 /* Canonical RTL says that if you have:
587 then this should be emitted as:
591 The use of trunc_int_for_mode ensures that the resulting
592 constant can be represented in SImode, this is important
593 for the corner case where operand[
1] is INT_MIN. */
595 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
597 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
598 (operands[
1], SImode))
599 operands[
1] = force_reg (SImode, operands[
1]);
600 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
604 if (!aarch64_plus_operand (operands[
2], SImode))
605 operands[
2] = force_reg (SImode, operands[
2]);
606 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
608 operands[
0], operands[
2], operands[
4]));
610 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
611 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
0],
617 (define_insn "casesi_dispatch"
620 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
621 (match_operand:SI
1 "register_operand" "r")]
623 (clobber (reg:CC CC_REGNUM))
624 (clobber (match_scratch:DI
3 "=r"))
625 (clobber (match_scratch:DI
4 "=r"))
626 (use (label_ref (match_operand
2 "" "")))])]
629 return aarch64_output_casesi (operands);
631 [(set_attr "length" "
16")
632 (set_attr "type" "branch")]
636 [(unspec[(const_int
0)] UNSPEC_NOP)]
639 [(set_attr "type" "no_insn")]
642 (define_insn "prefetch"
643 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
644 (match_operand:QI
1 "const_int_operand" "")
645 (match_operand:QI
2 "const_int_operand" ""))]
648 const char * pftype[
2][
4] =
650 {"prfm
\\tPLDL1STRM, %
0",
651 "prfm
\\tPLDL3KEEP, %
0",
652 "prfm
\\tPLDL2KEEP, %
0",
653 "prfm
\\tPLDL1KEEP, %
0"},
654 {"prfm
\\tPSTL1STRM, %
0",
655 "prfm
\\tPSTL3KEEP, %
0",
656 "prfm
\\tPSTL2KEEP, %
0",
657 "prfm
\\tPSTL1KEEP, %
0"},
660 int locality = INTVAL (operands[
2]);
662 gcc_assert (IN_RANGE (locality,
0,
3));
664 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
665 the address into a DImode MEM so that aarch64_print_operand knows
667 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
668 return pftype[INTVAL(operands[
1])][locality];
670 [(set_attr "type" "load_4")]
674 [(trap_if (const_int
1) (const_int
8))]
677 [(set_attr "type" "trap")])
679 (define_expand "prologue"
680 [(clobber (const_int
0))]
683 aarch64_expand_prologue ();
688 (define_expand "epilogue"
689 [(clobber (const_int
0))]
692 aarch64_expand_epilogue (false);
697 (define_expand "sibcall_epilogue"
698 [(clobber (const_int
0))]
701 aarch64_expand_epilogue (true);
706 (define_insn "*do_return"
710 if (aarch64_return_address_signing_enabled ()
712 && !crtl->calls_eh_return)
717 [(set_attr "type" "branch")]
720 (define_expand "return"
722 "aarch64_use_return_insn_p ()"
726 (define_insn "simple_return"
730 [(set_attr "type" "branch")]
733 (define_insn "*cb<optab><mode>
1"
734 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
736 (label_ref (match_operand
1 "" ""))
738 "!aarch64_track_speculation"
740 if (get_attr_length (insn) ==
8)
741 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
743 return "<cbz>
\\t%<w>
0, %l1";
745 [(set_attr "type" "branch")
747 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
748 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
751 (set (attr "far_branch")
752 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
753 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
758 (define_insn "*tb<optab><mode>
1"
759 [(set (pc) (if_then_else
760 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
763 "aarch64_simd_shift_imm_<mode>" "n"))
765 (label_ref (match_operand
2 "" ""))
767 (clobber (reg:CC CC_REGNUM))]
768 "!aarch64_track_speculation"
770 if (get_attr_length (insn) ==
8)
772 if (get_attr_far_branch (insn) ==
1)
773 return aarch64_gen_far_branch (operands,
2, "Ltb",
774 "<inv_tb>
\\t%<w>
0, %
1, ");
777 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
778 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
782 return "<tbz>
\t%<w>
0, %
1, %l2";
784 [(set_attr "type" "branch")
786 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
787 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
790 (set (attr "far_branch")
791 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
792 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
798 (define_insn "*cb<optab><mode>
1"
799 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
801 (label_ref (match_operand
1 "" ""))
803 (clobber (reg:CC CC_REGNUM))]
804 "!aarch64_track_speculation"
806 if (get_attr_length (insn) ==
8)
808 if (get_attr_far_branch (insn) ==
1)
809 return aarch64_gen_far_branch (operands,
1, "Ltb",
810 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
814 uint64_t val = ((uint64_t)
1)
815 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
816 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
817 output_asm_insn (buf, operands);
818 return "<bcond>
\t%l1";
822 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
824 [(set_attr "type" "branch")
826 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
827 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
830 (set (attr "far_branch")
831 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
832 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
837 ;; -------------------------------------------------------------------
838 ;; Subroutine calls and sibcalls
839 ;; -------------------------------------------------------------------
841 (define_expand "call"
842 [(parallel [(call (match_operand
0 "memory_operand" "")
843 (match_operand
1 "general_operand" ""))
844 (use (match_operand
2 "" ""))
845 (clobber (reg:DI LR_REGNUM))])]
849 aarch64_expand_call (NULL_RTX, operands[
0], false);
854 (define_insn "*call_insn"
855 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
856 (match_operand
1 "" ""))
857 (clobber (reg:DI LR_REGNUM))]
862 [(set_attr "type" "call, call")]
865 (define_expand "call_value"
866 [(parallel [(set (match_operand
0 "" "")
867 (call (match_operand
1 "memory_operand" "")
868 (match_operand
2 "general_operand" "")))
869 (use (match_operand
3 "" ""))
870 (clobber (reg:DI LR_REGNUM))])]
874 aarch64_expand_call (operands[
0], operands[
1], false);
879 (define_insn "*call_value_insn"
880 [(set (match_operand
0 "" "")
881 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
882 (match_operand
2 "" "")))
883 (clobber (reg:DI LR_REGNUM))]
888 [(set_attr "type" "call, call")]
891 (define_expand "sibcall"
892 [(parallel [(call (match_operand
0 "memory_operand" "")
893 (match_operand
1 "general_operand" ""))
895 (use (match_operand
2 "" ""))])]
898 aarch64_expand_call (NULL_RTX, operands[
0], true);
903 (define_expand "sibcall_value"
904 [(parallel [(set (match_operand
0 "" "")
905 (call (match_operand
1 "memory_operand" "")
906 (match_operand
2 "general_operand" "")))
908 (use (match_operand
3 "" ""))])]
911 aarch64_expand_call (operands[
0], operands[
1], true);
916 (define_insn "*sibcall_insn"
917 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
918 (match_operand
1 "" ""))
920 "SIBLING_CALL_P (insn)"
924 [(set_attr "type" "branch, branch")]
927 (define_insn "*sibcall_value_insn"
928 [(set (match_operand
0 "" "")
930 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
931 (match_operand
2 "" "")))
933 "SIBLING_CALL_P (insn)"
937 [(set_attr "type" "branch, branch")]
940 ;; Call subroutine returning any type.
942 (define_expand "untyped_call"
943 [(parallel [(call (match_operand
0 "")
946 (match_operand
2 "")])]
951 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL));
953 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
955 rtx set = XVECEXP (operands[
2],
0, i);
956 emit_move_insn (SET_DEST (set), SET_SRC (set));
959 /* The optimizer does not know that the call sets the function value
960 registers we stored in the result block. We avoid problems by
961 claiming that all hard registers are used and clobbered at this
963 emit_insn (gen_blockage ());
967 ;; -------------------------------------------------------------------
969 ;; -------------------------------------------------------------------
971 (define_expand "mov<mode>"
972 [(set (match_operand:SHORT
0 "nonimmediate_operand" "")
973 (match_operand:SHORT
1 "general_operand" ""))]
976 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
977 operands[
1] = force_reg (<MODE>mode, operands[
1]);
979 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
981 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
987 (define_insn "*mov<mode>_aarch64"
988 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
989 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
990 "(register_operand (operands[
0], <MODE>mode)
991 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
993 switch (which_alternative)
996 return "mov
\t%w0, %w1";
998 return "mov
\t%w0, %
1";
1000 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
1003 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1005 return "ldr<size>
\t%w0, %
1";
1007 return "ldr
\t%<size>
0, %
1";
1009 return "str<size>
\t%w1, %
0";
1011 return "str
\t%<size>
1, %
0";
1013 return "umov
\t%w0, %
1.<v>[
0]";
1015 return "dup
\t%
0.<Vallxd>, %w1";
1017 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
1022 ;; The "mov_imm" type for CNT is just a placeholder.
1023 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1024 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1025 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1028 (define_expand "mov<mode>"
1029 [(set (match_operand:GPI
0 "nonimmediate_operand" "")
1030 (match_operand:GPI
1 "general_operand" ""))]
1033 if (MEM_P (operands[
0]) && CONST_INT_P (operands[
1])
1034 && <MODE>mode == DImode
1035 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
1038 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1039 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1041 /* FIXME: RR we still need to fix up what we are doing with
1042 symbol_refs and other types of constants. */
1043 if (CONSTANT_P (operands[
1])
1044 && !CONST_INT_P (operands[
1]))
1046 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1052 (define_insn_and_split "*movsi_aarch64"
1053 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1054 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1055 "(register_operand (operands[
0], SImode)
1056 || aarch64_reg_or_zero (operands[
1], SImode))"
1063 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1073 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1074 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1075 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1078 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1081 ;; The "mov_imm" type for CNT is just a placeholder.
1082 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1083 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1084 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1087 (define_insn_and_split "*movdi_aarch64"
1088 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1089 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1090 "(register_operand (operands[
0], DImode)
1091 || aarch64_reg_or_zero (operands[
1], DImode))"
1099 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1109 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1110 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1111 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1114 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1117 ;; The "mov_imm" type for CNTD is just a placeholder.
1118 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1119 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1121 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1124 (define_insn "insv_imm<mode>"
1125 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1127 (match_operand:GPI
1 "const_int_operand" "n"))
1128 (match_operand:GPI
2 "const_int_operand" "n"))]
1129 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1130 && UINTVAL (operands[
1]) %
16 ==
0"
1131 "movk
\\t%<w>
0, %X2, lsl %
1"
1132 [(set_attr "type" "mov_imm")]
1135 (define_expand "movti"
1136 [(set (match_operand:TI
0 "nonimmediate_operand" "")
1137 (match_operand:TI
1 "general_operand" ""))]
1140 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1141 operands[
1] = force_reg (TImode, operands[
1]);
1143 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1145 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1146 gen_lowpart (DImode, operands[
1]));
1147 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1153 (define_insn "*movti_aarch64"
1154 [(set (match_operand:TI
0
1155 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1157 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1158 "(register_operand (operands[
0], TImode)
1159 || aarch64_reg_or_zero (operands[
1], TImode))"
1164 mov
\\t%
0.16b, %
1.16b
1170 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1171 load_16,store_16,store_16,\
1173 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1174 (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
1177 ;; Split a TImode register-register or register-immediate move into
1178 ;; its component DImode pieces, taking care to handle overlapping
1179 ;; source and dest registers.
1181 [(set (match_operand:TI
0 "register_operand" "")
1182 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1183 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1186 aarch64_split_128bit_move (operands[
0], operands[
1]);
1190 (define_expand "mov<mode>"
1191 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand" "")
1192 (match_operand:GPF_TF_F16
1 "general_operand" ""))]
1197 aarch64_err_no_fpadvsimd (<MODE>mode);
1201 if (GET_CODE (operands[
0]) == MEM
1202 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1203 && aarch64_float_const_zero_rtx_p (operands[
1])))
1204 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1208 (define_insn "*movhf_aarch64"
1209 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1210 (match_operand:HF
1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1211 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1212 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1218 mov
\\t%
0.h[
0], %
1.h[
0]
1220 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1226 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1227 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1228 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1231 (define_insn "*movsf_aarch64"
1232 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1233 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1234 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1235 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1242 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1249 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1250 f_loads,f_stores,load_4,store_4,mov_reg,\
1252 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1255 (define_insn "*movdf_aarch64"
1256 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1257 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1258 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1259 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1266 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1273 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1274 f_loadd,f_stored,load_8,store_8,mov_reg,\
1276 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1280 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1281 (match_operand:GPF_HF
1 "general_operand"))]
1282 "can_create_pseudo_p ()
1283 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1284 && !aarch64_float_const_representable_p (operands[
1])
1285 && aarch64_float_const_rtx_p (operands[
1])"
1288 unsigned HOST_WIDE_INT ival;
1289 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1292 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1293 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1294 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1299 (define_insn "*movtf_aarch64"
1300 [(set (match_operand:TF
0
1301 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1303 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1304 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1305 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1307 mov
\\t%
0.16b, %
1.16b
1318 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1319 f_loadd,f_stored,load_16,store_16,store_16")
1320 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1321 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1325 [(set (match_operand:TF
0 "register_operand" "")
1326 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1327 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1330 aarch64_split_128bit_move (operands[
0], operands[
1]);
1337 ;;
2 is size of move in bytes
1340 (define_expand "movmemdi"
1341 [(match_operand:BLK
0 "memory_operand")
1342 (match_operand:BLK
1 "memory_operand")
1343 (match_operand:DI
2 "immediate_operand")
1344 (match_operand:DI
3 "immediate_operand")]
1347 if (aarch64_expand_movmem (operands))
1353 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1354 ;; fairly lax checking on the second memory operation.
1355 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1356 [(set (match_operand:SX
0 "register_operand" "=r,w")
1357 (match_operand:SX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1358 (set (match_operand:SX2
2 "register_operand" "=r,w")
1359 (match_operand:SX2
3 "memory_operand" "m,m"))]
1360 "rtx_equal_p (XEXP (operands[
3],
0),
1361 plus_constant (Pmode,
1362 XEXP (operands[
1],
0),
1363 GET_MODE_SIZE (<SX:MODE>mode)))"
1367 [(set_attr "type" "load_8,neon_load1_2reg")
1368 (set_attr "arch" "*,fp")]
1371 ;; Storing different modes that can still be merged
1372 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1373 [(set (match_operand:DX
0 "register_operand" "=r,w")
1374 (match_operand:DX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1375 (set (match_operand:DX2
2 "register_operand" "=r,w")
1376 (match_operand:DX2
3 "memory_operand" "m,m"))]
1377 "rtx_equal_p (XEXP (operands[
3],
0),
1378 plus_constant (Pmode,
1379 XEXP (operands[
1],
0),
1380 GET_MODE_SIZE (<DX:MODE>mode)))"
1384 [(set_attr "type" "load_16,neon_load1_2reg")
1385 (set_attr "arch" "*,fp")]
1388 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1389 ;; fairly lax checking on the second memory operation.
1390 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1391 [(set (match_operand:SX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1392 (match_operand:SX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1393 (set (match_operand:SX2
2 "memory_operand" "=m,m")
1394 (match_operand:SX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1395 "rtx_equal_p (XEXP (operands[
2],
0),
1396 plus_constant (Pmode,
1397 XEXP (operands[
0],
0),
1398 GET_MODE_SIZE (<SX:MODE>mode)))"
1402 [(set_attr "type" "store_8,neon_store1_2reg")
1403 (set_attr "arch" "*,fp")]
1406 ;; Storing different modes that can still be merged
1407 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1408 [(set (match_operand:DX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1409 (match_operand:DX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1410 (set (match_operand:DX2
2 "memory_operand" "=m,m")
1411 (match_operand:DX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1412 "rtx_equal_p (XEXP (operands[
2],
0),
1413 plus_constant (Pmode,
1414 XEXP (operands[
0],
0),
1415 GET_MODE_SIZE (<DX:MODE>mode)))"
1419 [(set_attr "type" "store_16,neon_store1_2reg")
1420 (set_attr "arch" "*,fp")]
1423 ;; Load pair with post-index writeback. This is primarily used in function
1425 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1427 [(set (match_operand:P
0 "register_operand" "=k")
1428 (plus:P (match_operand:P
1 "register_operand" "
0")
1429 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1430 (set (match_operand:GPI
2 "register_operand" "=r")
1431 (mem:GPI (match_dup
1)))
1432 (set (match_operand:GPI
3 "register_operand" "=r")
1433 (mem:GPI (plus:P (match_dup
1)
1434 (match_operand:P
5 "const_int_operand" "n"))))])]
1435 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1436 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1437 [(set_attr "type" "load_<ldpstp_sz>")]
1440 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1442 [(set (match_operand:P
0 "register_operand" "=k")
1443 (plus:P (match_operand:P
1 "register_operand" "
0")
1444 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1445 (set (match_operand:GPF
2 "register_operand" "=w")
1446 (mem:GPF (match_dup
1)))
1447 (set (match_operand:GPF
3 "register_operand" "=w")
1448 (mem:GPF (plus:P (match_dup
1)
1449 (match_operand:P
5 "const_int_operand" "n"))))])]
1450 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1451 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1452 [(set_attr "type" "neon_load1_2reg")]
1455 ;; Store pair with pre-index writeback. This is primarily used in function
1457 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1459 [(set (match_operand:P
0 "register_operand" "=&k")
1460 (plus:P (match_operand:P
1 "register_operand" "
0")
1461 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1462 (set (mem:GPI (plus:P (match_dup
0)
1464 (match_operand:GPI
2 "register_operand" "r"))
1465 (set (mem:GPI (plus:P (match_dup
0)
1466 (match_operand:P
5 "const_int_operand" "n")))
1467 (match_operand:GPI
3 "register_operand" "r"))])]
1468 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1469 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1470 [(set_attr "type" "store_<ldpstp_sz>")]
1473 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1475 [(set (match_operand:P
0 "register_operand" "=&k")
1476 (plus:P (match_operand:P
1 "register_operand" "
0")
1477 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1478 (set (mem:GPF (plus:P (match_dup
0)
1480 (match_operand:GPF
2 "register_operand" "w"))
1481 (set (mem:GPF (plus:P (match_dup
0)
1482 (match_operand:P
5 "const_int_operand" "n")))
1483 (match_operand:GPF
3 "register_operand" "w"))])]
1484 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1485 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1486 [(set_attr "type" "neon_store1_2reg<q>")]
1489 ;; -------------------------------------------------------------------
1490 ;; Sign/Zero extension
1491 ;; -------------------------------------------------------------------
1493 (define_expand "<optab>sidi2"
1494 [(set (match_operand:DI
0 "register_operand")
1495 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1499 (define_insn "*extendsidi2_aarch64"
1500 [(set (match_operand:DI
0 "register_operand" "=r,r")
1501 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1506 [(set_attr "type" "extend,load_4")]
1509 (define_insn "*load_pair_extendsidi2_aarch64"
1510 [(set (match_operand:DI
0 "register_operand" "=r")
1511 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1512 (set (match_operand:DI
2 "register_operand" "=r")
1513 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1514 "rtx_equal_p (XEXP (operands[
3],
0),
1515 plus_constant (Pmode,
1516 XEXP (operands[
1],
0),
1517 GET_MODE_SIZE (SImode)))"
1518 "ldpsw
\\t%
0, %
2, %
1"
1519 [(set_attr "type" "load_8")]
1522 (define_insn "*zero_extendsidi2_aarch64"
1523 [(set (match_operand:DI
0 "register_operand" "=r,r,w,w,r,w")
1524 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1533 [(set_attr "type" "extend,load_4,f_mcr,f_loads,f_mrc,fmov")
1534 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1537 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1538 [(set (match_operand:DI
0 "register_operand" "=r,w")
1539 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump,Ump")))
1540 (set (match_operand:DI
2 "register_operand" "=r,w")
1541 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m,m")))]
1542 "rtx_equal_p (XEXP (operands[
3],
0),
1543 plus_constant (Pmode,
1544 XEXP (operands[
1],
0),
1545 GET_MODE_SIZE (SImode)))"
1549 [(set_attr "type" "load_8,neon_load1_2reg")
1550 (set_attr "arch" "*,fp")]
1553 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1554 [(set (match_operand:GPI
0 "register_operand")
1555 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1559 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1560 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1561 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1564 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1565 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1566 [(set_attr "type" "extend,load_4")]
1569 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1570 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1571 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1574 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1575 ldr<SHORT:size>
\t%w0, %
1
1576 ldr
\t%<SHORT:size>
0, %
1"
1577 [(set_attr "type" "logic_imm,load_4,f_loads")
1578 (set_attr "arch" "*,*,fp")]
1581 (define_expand "<optab>qihi2"
1582 [(set (match_operand:HI
0 "register_operand")
1583 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1587 (define_insn "*extendqihi2_aarch64"
1588 [(set (match_operand:HI
0 "register_operand" "=r,r")
1589 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1594 [(set_attr "type" "extend,load_4")]
1597 (define_insn "*zero_extendqihi2_aarch64"
1598 [(set (match_operand:HI
0 "register_operand" "=r,r")
1599 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1604 [(set_attr "type" "logic_imm,load_4")]
1607 ;; -------------------------------------------------------------------
1608 ;; Simple arithmetic
1609 ;; -------------------------------------------------------------------
1611 (define_expand "add<mode>
3"
1613 (match_operand:GPI
0 "register_operand" "")
1614 (plus:GPI (match_operand:GPI
1 "register_operand" "")
1615 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "")))]
1618 /* If operands[
1] is a subreg extract the inner RTX. */
1619 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1621 /* If the constant is too large for a single instruction and isn't frame
1622 based, split off the immediate so it is available for CSE. */
1623 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1624 && can_create_pseudo_p ()
1626 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1627 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1628 /* Expand polynomial additions now if the destination is the stack
1629 pointer, since we don't want to use that as a temporary. */
1630 else if (operands[
0] == stack_pointer_rtx
1631 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1633 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1634 operands[
2], NULL_RTX, NULL_RTX);
1639 (define_insn "*add<mode>
3_aarch64"
1641 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,rk")
1643 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,rk")
1644 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1647 add
\\t%<w>
0, %<w>
1, %
2
1648 add
\\t%<w>
0, %<w>
1, %<w>
2
1649 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1650 sub
\\t%<w>
0, %<w>
1, #%n2
1652 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);"
1653 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1654 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1655 (set_attr "arch" "*,*,simd,*,*,*")]
1658 ;; zero_extend version of above
1659 (define_insn "*addsi3_aarch64_uxtw"
1661 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1663 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1664 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1669 sub
\\t%w0, %w1, #%n2
1671 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1674 ;; If there's a free register, and we can load the constant with a
1675 ;; single instruction, do so. This has a chance to improve scheduling.
1677 [(match_scratch:GPI
3 "r")
1678 (set (match_operand:GPI
0 "register_operand")
1680 (match_operand:GPI
1 "register_operand")
1681 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1682 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1683 [(set (match_dup
3) (match_dup
2))
1684 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1688 [(match_scratch:SI
3 "r")
1689 (set (match_operand:DI
0 "register_operand")
1692 (match_operand:SI
1 "register_operand")
1693 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1694 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1695 [(set (match_dup
3) (match_dup
2))
1696 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1699 ;; After peephole2 has had a chance to run, split any remaining long
1700 ;; additions into two add immediates.
1702 [(set (match_operand:GPI
0 "register_operand")
1704 (match_operand:GPI
1 "register_operand")
1705 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1706 "epilogue_completed"
1707 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1708 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1710 HOST_WIDE_INT i = INTVAL (operands[
2]);
1711 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1712 operands[
3] = GEN_INT (i - s);
1713 operands[
4] = GEN_INT (s);
1717 ;; Match addition of polynomial offsets that require one temporary, for which
1718 ;; we can use the early-clobbered destination register. This is a separate
1719 ;; pattern so that the early clobber doesn't affect register allocation
1720 ;; for other forms of addition. However, we still need to provide an
1721 ;; all-register alternative, in case the offset goes out of range after
1722 ;; elimination. For completeness we might as well provide all GPR-based
1723 ;; alternatives from the main pattern.
1725 ;; We don't have a pattern for additions requiring two temporaries since at
1726 ;; present LRA doesn't allow new scratches to be added during elimination.
1727 ;; Such offsets should be rare anyway.
1729 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1730 ;; here would go away. We could just handle all polynomial constants in
1732 (define_insn_and_split "*add<mode>
3_poly_1"
1734 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,&r")
1736 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1737 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1738 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1740 add
\\t%<w>
0, %<w>
1, %
2
1741 add
\\t%<w>
0, %<w>
1, %<w>
2
1742 sub
\\t%<w>
0, %<w>
1, #%n2
1744 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);
1746 "&& epilogue_completed
1747 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1748 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1751 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1752 operands[
2], operands[
0], NULL_RTX);
1755 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1756 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1760 [(set (match_operand:DI
0 "register_operand")
1763 (match_operand:SI
1 "register_operand")
1764 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1765 "epilogue_completed"
1766 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1767 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1769 HOST_WIDE_INT i = INTVAL (operands[
2]);
1770 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1771 operands[
3] = GEN_INT (i - s);
1772 operands[
4] = GEN_INT (s);
1773 operands[
5] = gen_lowpart (SImode, operands[
0]);
1777 (define_expand "addv<mode>
4"
1778 [(match_operand:GPI
0 "register_operand")
1779 (match_operand:GPI
1 "register_operand")
1780 (match_operand:GPI
2 "register_operand")
1781 (label_ref (match_operand
3 "" ""))]
1784 emit_insn (gen_add<mode>
3_compareV (operands[
0], operands[
1], operands[
2]));
1785 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1790 (define_expand "uaddv<mode>
4"
1791 [(match_operand:GPI
0 "register_operand")
1792 (match_operand:GPI
1 "register_operand")
1793 (match_operand:GPI
2 "register_operand")
1794 (label_ref (match_operand
3 "" ""))]
1797 emit_insn (gen_add<mode>
3_compareC (operands[
0], operands[
1], operands[
2]));
1798 aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[
3]);
1803 (define_expand "addti3"
1804 [(set (match_operand:TI
0 "register_operand" "")
1805 (plus:TI (match_operand:TI
1 "register_operand" "")
1806 (match_operand:TI
2 "aarch64_reg_or_imm" "")))]
1809 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1811 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1812 &low_dest, &op1_low, &op2_low,
1813 &high_dest, &op1_high, &op2_high);
1815 if (op2_low == const0_rtx)
1818 if (!aarch64_pluslong_operand (op2_high, DImode))
1819 op2_high = force_reg (DImode, op2_high);
1820 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
1824 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1825 force_reg (DImode, op2_low)));
1826 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
1827 force_reg (DImode, op2_high)));
1830 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1831 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1836 (define_expand "addvti4"
1837 [(match_operand:TI
0 "register_operand" "")
1838 (match_operand:TI
1 "register_operand" "")
1839 (match_operand:TI
2 "aarch64_reg_or_imm" "")
1840 (label_ref (match_operand
3 "" ""))]
1843 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1845 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1846 &low_dest, &op1_low, &op2_low,
1847 &high_dest, &op1_high, &op2_high);
1849 if (op2_low == const0_rtx)
1852 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
1853 force_reg (DImode, op2_high)));
1857 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1858 force_reg (DImode, op2_low)));
1859 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
1860 force_reg (DImode, op2_high)));
1863 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1864 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1866 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1870 (define_expand "uaddvti4"
1871 [(match_operand:TI
0 "register_operand" "")
1872 (match_operand:TI
1 "register_operand" "")
1873 (match_operand:TI
2 "aarch64_reg_or_imm" "")
1874 (label_ref (match_operand
3 "" ""))]
1877 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1879 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1880 &low_dest, &op1_low, &op2_low,
1881 &high_dest, &op1_high, &op2_high);
1883 if (op2_low == const0_rtx)
1886 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
1887 force_reg (DImode, op2_high)));
1891 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1892 force_reg (DImode, op2_low)));
1893 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
1894 force_reg (DImode, op2_high)));
1897 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1898 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1900 aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[
3]);
1904 (define_insn "add<mode>
3_compare0"
1905 [(set (reg:CC_NZ CC_REGNUM)
1907 (plus:GPI (match_operand:GPI
1 "register_operand" "%r,r,r")
1908 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
1910 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
1911 (plus:GPI (match_dup
1) (match_dup
2)))]
1914 adds
\\t%<w>
0, %<w>
1, %<w>
2
1915 adds
\\t%<w>
0, %<w>
1, %
2
1916 subs
\\t%<w>
0, %<w>
1, #%n2"
1917 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1920 ;; zero_extend version of above
1921 (define_insn "*addsi3_compare0_uxtw"
1922 [(set (reg:CC_NZ CC_REGNUM)
1924 (plus:SI (match_operand:SI
1 "register_operand" "%r,r,r")
1925 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
1927 (set (match_operand:DI
0 "register_operand" "=r,r,r")
1928 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
1931 adds
\\t%w0, %w1, %w2
1933 subs
\\t%w0, %w1, #%n2"
1934 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1937 (define_insn "*add<mode>
3_compareC_cconly_imm"
1938 [(set (reg:CC_C CC_REGNUM)
1941 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
1942 (match_operand:<DWI>
2 "const_scalar_int_operand" ""))
1946 (match_operand:GPI
1 "aarch64_plus_immediate" "I,J")))))]
1947 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
2],
1948 <MODE>mode, operands[
1])"
1952 [(set_attr "type" "alus_imm")]
1955 (define_insn "*add<mode>
3_compareC_cconly"
1956 [(set (reg:CC_C CC_REGNUM)
1959 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
1960 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
1961 (zero_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
1963 "cmn
\\t%<w>
0, %<w>
1"
1964 [(set_attr "type" "alus_sreg")]
1967 (define_insn "*add<mode>
3_compareC_imm"
1968 [(set (reg:CC_C CC_REGNUM)
1971 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r,r"))
1972 (match_operand:<DWI>
3 "const_scalar_int_operand" ""))
1976 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))
1977 (set (match_operand:GPI
0 "register_operand" "=r,r")
1978 (plus:GPI (match_dup
1) (match_dup
2)))]
1979 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
3],
1980 <MODE>mode, operands[
2])"
1982 adds
\\t%<w>
0, %<w>
1, %
2
1983 subs
\\t%<w>
0, %<w>
1, #%n2"
1984 [(set_attr "type" "alus_imm")]
1987 (define_insn "add<mode>
3_compareC"
1988 [(set (reg:CC_C CC_REGNUM)
1991 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
1992 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
1994 (plus:GPI (match_dup
1) (match_dup
2)))))
1995 (set (match_operand:GPI
0 "register_operand" "=r")
1996 (plus:GPI (match_dup
1) (match_dup
2)))]
1998 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
1999 [(set_attr "type" "alus_sreg")]
2002 (define_insn "*add<mode>
3_compareV_cconly_imm"
2003 [(set (reg:CC_V CC_REGNUM)
2006 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
2007 (match_operand:<DWI>
1 "const_scalar_int_operand" ""))
2011 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))]
2012 "INTVAL (operands[
1]) == INTVAL (operands[
2])"
2016 [(set_attr "type" "alus_imm")]
2019 (define_insn "*add<mode>
3_compareV_cconly"
2020 [(set (reg:CC_V CC_REGNUM)
2023 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
2024 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2025 (sign_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
2027 "cmn
\\t%<w>
0, %<w>
1"
2028 [(set_attr "type" "alus_sreg")]
2031 (define_insn "*add<mode>
3_compareV_imm"
2032 [(set (reg:CC_V CC_REGNUM)
2036 (match_operand:GPI
1 "register_operand" "r,r"))
2037 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J"))
2039 (plus:GPI (match_dup
1) (match_dup
2)))))
2040 (set (match_operand:GPI
0 "register_operand" "=r,r")
2041 (plus:GPI (match_dup
1) (match_dup
2)))]
2044 adds
\\t%<w>
0, %<w>
1, %<w>
2
2045 subs
\\t%<w>
0, %<w>
1, #%n2"
2046 [(set_attr "type" "alus_imm,alus_imm")]
2049 (define_insn "add<mode>
3_compareV"
2050 [(set (reg:CC_V CC_REGNUM)
2053 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
2054 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2055 (sign_extend:<DWI> (plus:GPI (match_dup
1) (match_dup
2)))))
2056 (set (match_operand:GPI
0 "register_operand" "=r")
2057 (plus:GPI (match_dup
1) (match_dup
2)))]
2059 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
2060 [(set_attr "type" "alus_sreg")]
2063 (define_insn "*adds_shift_imm_<mode>"
2064 [(set (reg:CC_NZ CC_REGNUM)
2066 (plus:GPI (ASHIFT:GPI
2067 (match_operand:GPI
1 "register_operand" "r")
2068 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2069 (match_operand:GPI
3 "register_operand" "r"))
2071 (set (match_operand:GPI
0 "register_operand" "=r")
2072 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
2075 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2076 [(set_attr "type" "alus_shift_imm")]
2079 (define_insn "*subs_shift_imm_<mode>"
2080 [(set (reg:CC_NZ CC_REGNUM)
2082 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2084 (match_operand:GPI
2 "register_operand" "r")
2085 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
2087 (set (match_operand:GPI
0 "register_operand" "=r")
2088 (minus:GPI (match_dup
1)
2089 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
2091 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
2092 [(set_attr "type" "alus_shift_imm")]
2095 (define_insn "*adds_mul_imm_<mode>"
2096 [(set (reg:CC_NZ CC_REGNUM)
2099 (match_operand:GPI
1 "register_operand" "r")
2100 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2101 (match_operand:GPI
3 "register_operand" "r"))
2103 (set (match_operand:GPI
0 "register_operand" "=r")
2104 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
2107 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2108 [(set_attr "type" "alus_shift_imm")]
2111 (define_insn "*subs_mul_imm_<mode>"
2112 [(set (reg:CC_NZ CC_REGNUM)
2114 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2116 (match_operand:GPI
2 "register_operand" "r")
2117 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
2119 (set (match_operand:GPI
0 "register_operand" "=r")
2120 (minus:GPI (match_dup
1)
2121 (mult:GPI (match_dup
2) (match_dup
3))))]
2123 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
2124 [(set_attr "type" "alus_shift_imm")]
2127 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2128 [(set (reg:CC_NZ CC_REGNUM)
2131 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2132 (match_operand:GPI
2 "register_operand" "r"))
2134 (set (match_operand:GPI
0 "register_operand" "=r")
2135 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
2137 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2138 [(set_attr "type" "alus_ext")]
2141 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2142 [(set (reg:CC_NZ CC_REGNUM)
2144 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2146 (match_operand:ALLX
2 "register_operand" "r")))
2148 (set (match_operand:GPI
0 "register_operand" "=r")
2149 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
2151 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2152 [(set_attr "type" "alus_ext")]
2155 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2156 [(set (reg:CC_NZ CC_REGNUM)
2158 (plus:GPI (ashift:GPI
2160 (match_operand:ALLX
1 "register_operand" "r"))
2161 (match_operand
2 "aarch64_imm3" "Ui3"))
2162 (match_operand:GPI
3 "register_operand" "r"))
2164 (set (match_operand:GPI
0 "register_operand" "=rk")
2165 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2169 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2170 [(set_attr "type" "alus_ext")]
2173 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2174 [(set (reg:CC_NZ CC_REGNUM)
2176 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2179 (match_operand:ALLX
2 "register_operand" "r"))
2180 (match_operand
3 "aarch64_imm3" "Ui3")))
2182 (set (match_operand:GPI
0 "register_operand" "=rk")
2183 (minus:GPI (match_dup
1)
2184 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2187 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2188 [(set_attr "type" "alus_ext")]
2191 (define_insn "*adds_<optab><mode>_multp2"
2192 [(set (reg:CC_NZ CC_REGNUM)
2194 (plus:GPI (ANY_EXTRACT:GPI
2195 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2196 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2197 (match_operand
3 "const_int_operand" "n")
2199 (match_operand:GPI
4 "register_operand" "r"))
2201 (set (match_operand:GPI
0 "register_operand" "=r")
2202 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2206 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2207 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2208 [(set_attr "type" "alus_ext")]
2211 (define_insn "*subs_<optab><mode>_multp2"
2212 [(set (reg:CC_NZ CC_REGNUM)
2214 (minus:GPI (match_operand:GPI
4 "register_operand" "r")
2216 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2217 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2218 (match_operand
3 "const_int_operand" "n")
2221 (set (match_operand:GPI
0 "register_operand" "=r")
2222 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2223 (mult:GPI (match_dup
1) (match_dup
2))
2226 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2227 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2228 [(set_attr "type" "alus_ext")]
2231 (define_insn "*add<mode>
3nr_compare0"
2232 [(set (reg:CC_NZ CC_REGNUM)
2234 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2235 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2242 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2245 (define_insn "aarch64_sub<mode>_compare0"
2246 [(set (reg:CC_NZ CC_REGNUM)
2248 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2249 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2252 "cmp
\\t%<w>
0, %<w>
1"
2253 [(set_attr "type" "alus_sreg")]
2256 (define_insn "*compare_neg<mode>"
2257 [(set (reg:CC_Z CC_REGNUM)
2259 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2260 (match_operand:GPI
1 "register_operand" "r")))]
2262 "cmn
\\t%<w>
1, %<w>
0"
2263 [(set_attr "type" "alus_sreg")]
2266 (define_insn "*add_<shift>_<mode>"
2267 [(set (match_operand:GPI
0 "register_operand" "=r")
2268 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2269 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2270 (match_operand:GPI
3 "register_operand" "r")))]
2272 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2273 [(set_attr "type" "alu_shift_imm")]
2276 ;; zero_extend version of above
2277 (define_insn "*add_<shift>_si_uxtw"
2278 [(set (match_operand:DI
0 "register_operand" "=r")
2280 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2281 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2282 (match_operand:SI
3 "register_operand" "r"))))]
2284 "add
\\t%w0, %w3, %w1, <shift> %
2"
2285 [(set_attr "type" "alu_shift_imm")]
2288 (define_insn "*add_mul_imm_<mode>"
2289 [(set (match_operand:GPI
0 "register_operand" "=r")
2290 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2291 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2292 (match_operand:GPI
3 "register_operand" "r")))]
2294 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2295 [(set_attr "type" "alu_shift_imm")]
2298 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2299 [(set (match_operand:GPI
0 "register_operand" "=rk")
2300 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2301 (match_operand:GPI
2 "register_operand" "r")))]
2303 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2304 [(set_attr "type" "alu_ext")]
2307 ;; zero_extend version of above
2308 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2309 [(set (match_operand:DI
0 "register_operand" "=rk")
2311 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2312 (match_operand:GPI
2 "register_operand" "r"))))]
2314 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2315 [(set_attr "type" "alu_ext")]
2318 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2319 [(set (match_operand:GPI
0 "register_operand" "=rk")
2320 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2321 (match_operand:ALLX
1 "register_operand" "r"))
2322 (match_operand
2 "aarch64_imm3" "Ui3"))
2323 (match_operand:GPI
3 "register_operand" "r")))]
2325 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2326 [(set_attr "type" "alu_ext")]
2329 ;; zero_extend version of above
2330 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2331 [(set (match_operand:DI
0 "register_operand" "=rk")
2333 (plus:SI (ashift:SI (ANY_EXTEND:SI
2334 (match_operand:SHORT
1 "register_operand" "r"))
2335 (match_operand
2 "aarch64_imm3" "Ui3"))
2336 (match_operand:SI
3 "register_operand" "r"))))]
2338 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2339 [(set_attr "type" "alu_ext")]
2342 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2343 [(set (match_operand:GPI
0 "register_operand" "=rk")
2344 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2345 (match_operand:ALLX
1 "register_operand" "r"))
2346 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2347 (match_operand:GPI
3 "register_operand" "r")))]
2349 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2350 [(set_attr "type" "alu_ext")]
2353 ;; zero_extend version of above
2354 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2355 [(set (match_operand:DI
0 "register_operand" "=rk")
2356 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2357 (match_operand:SHORT
1 "register_operand" "r"))
2358 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2359 (match_operand:SI
3 "register_operand" "r"))))]
2361 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2362 [(set_attr "type" "alu_ext")]
2365 (define_insn "*add_<optab><mode>_multp2"
2366 [(set (match_operand:GPI
0 "register_operand" "=rk")
2367 (plus:GPI (ANY_EXTRACT:GPI
2368 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2369 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2370 (match_operand
3 "const_int_operand" "n")
2372 (match_operand:GPI
4 "register_operand" "r")))]
2373 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2374 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2375 [(set_attr "type" "alu_ext")]
2378 ;; zero_extend version of above
2379 (define_insn "*add_<optab>si_multp2_uxtw"
2380 [(set (match_operand:DI
0 "register_operand" "=rk")
2382 (plus:SI (ANY_EXTRACT:SI
2383 (mult:SI (match_operand:SI
1 "register_operand" "r")
2384 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2385 (match_operand
3 "const_int_operand" "n")
2387 (match_operand:SI
4 "register_operand" "r"))))]
2388 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2389 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2390 [(set_attr "type" "alu_ext")]
2393 (define_expand "add<mode>
3_carryin"
2394 [(set (match_operand:GPI
0 "register_operand")
2397 (ne:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2398 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2399 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2404 ;; Note that add with carry with two zero inputs is matched by cset,
2405 ;; and that add with carry with one zero input is matched by cinc.
2407 (define_insn "*add<mode>
3_carryin"
2408 [(set (match_operand:GPI
0 "register_operand" "=r")
2411 (match_operand:GPI
3 "aarch64_carry_operation" "")
2412 (match_operand:GPI
1 "register_operand" "r"))
2413 (match_operand:GPI
2 "register_operand" "r")))]
2415 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2416 [(set_attr "type" "adc_reg")]
2419 ;; zero_extend version of above
2420 (define_insn "*addsi3_carryin_uxtw"
2421 [(set (match_operand:DI
0 "register_operand" "=r")
2425 (match_operand:SI
3 "aarch64_carry_operation" "")
2426 (match_operand:SI
1 "register_operand" "r"))
2427 (match_operand:SI
2 "register_operand" "r"))))]
2429 "adc
\\t%w0, %w1, %w2"
2430 [(set_attr "type" "adc_reg")]
2433 (define_expand "add<mode>
3_carryinC"
2441 (match_operand:GPI
1 "register_operand" "")))
2443 (match_operand:GPI
2 "register_operand" "")))
2446 (plus:GPI (match_dup
5) (match_dup
1))
2448 (set (match_operand:GPI
0 "register_operand")
2450 (plus:GPI (match_dup
5) (match_dup
1))
2454 operands[
3] = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2455 operands[
4] = gen_rtx_NE (<DWI>mode, operands[
3], const0_rtx);
2456 operands[
5] = gen_rtx_NE (<MODE>mode, operands[
3], const0_rtx);
2459 (define_insn "*add<mode>
3_carryinC_zero"
2460 [(set (reg:CC_C CC_REGNUM)
2463 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2464 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2467 (match_operand:GPI
3 "aarch64_carry_operation" "")
2469 (set (match_operand:GPI
0 "register_operand" "=r")
2470 (plus:GPI (match_dup
3) (match_dup
1)))]
2472 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2473 [(set_attr "type" "adc_reg")]
2476 (define_insn "*add<mode>
3_carryinC"
2477 [(set (reg:CC_C CC_REGNUM)
2481 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2482 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2483 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2487 (match_operand:GPI
4 "aarch64_carry_operation" "")
2490 (set (match_operand:GPI
0 "register_operand" "=r")
2492 (plus:GPI (match_dup
4) (match_dup
1))
2495 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2496 [(set_attr "type" "adc_reg")]
2499 (define_expand "add<mode>
3_carryinV"
2501 [(set (reg:CC_V CC_REGNUM)
2507 (match_operand:GPI
1 "register_operand" "")))
2509 (match_operand:GPI
2 "register_operand" "")))
2512 (plus:GPI (match_dup
4) (match_dup
1))
2514 (set (match_operand:GPI
0 "register_operand")
2516 (plus:GPI (match_dup
4) (match_dup
1))
2520 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2521 operands[
3] = gen_rtx_NE (<DWI>mode, cc, const0_rtx);
2522 operands[
4] = gen_rtx_NE (<MODE>mode, cc, const0_rtx);
2525 (define_insn "*add<mode>
3_carryinV_zero"
2526 [(set (reg:CC_V CC_REGNUM)
2529 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2530 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2533 (match_operand:GPI
3 "aarch64_carry_operation" "")
2535 (set (match_operand:GPI
0 "register_operand" "=r")
2536 (plus:GPI (match_dup
3) (match_dup
1)))]
2538 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2539 [(set_attr "type" "adc_reg")]
2542 (define_insn "*add<mode>
3_carryinV"
2543 [(set (reg:CC_V CC_REGNUM)
2547 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2548 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2549 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2553 (match_operand:GPI
4 "aarch64_carry_operation" "")
2556 (set (match_operand:GPI
0 "register_operand" "=r")
2558 (plus:GPI (match_dup
4) (match_dup
1))
2561 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2562 [(set_attr "type" "adc_reg")]
2565 (define_insn "*add_uxt<mode>_shift2"
2566 [(set (match_operand:GPI
0 "register_operand" "=rk")
2568 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2569 (match_operand
2 "aarch64_imm3" "Ui3"))
2570 (match_operand
3 "const_int_operand" "n"))
2571 (match_operand:GPI
4 "register_operand" "r")))]
2572 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2574 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2575 INTVAL (operands[
3])));
2576 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2577 [(set_attr "type" "alu_ext")]
2580 ;; zero_extend version of above
2581 (define_insn "*add_uxtsi_shift2_uxtw"
2582 [(set (match_operand:DI
0 "register_operand" "=rk")
2585 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2586 (match_operand
2 "aarch64_imm3" "Ui3"))
2587 (match_operand
3 "const_int_operand" "n"))
2588 (match_operand:SI
4 "register_operand" "r"))))]
2589 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2591 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2592 INTVAL (operands[
3])));
2593 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2594 [(set_attr "type" "alu_ext")]
2597 (define_insn "*add_uxt<mode>_multp2"
2598 [(set (match_operand:GPI
0 "register_operand" "=rk")
2600 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2601 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2602 (match_operand
3 "const_int_operand" "n"))
2603 (match_operand:GPI
4 "register_operand" "r")))]
2604 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2606 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2607 INTVAL (operands[
3])));
2608 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2609 [(set_attr "type" "alu_ext")]
2612 ;; zero_extend version of above
2613 (define_insn "*add_uxtsi_multp2_uxtw"
2614 [(set (match_operand:DI
0 "register_operand" "=rk")
2617 (mult:SI (match_operand:SI
1 "register_operand" "r")
2618 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2619 (match_operand
3 "const_int_operand" "n"))
2620 (match_operand:SI
4 "register_operand" "r"))))]
2621 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2623 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2624 INTVAL (operands[
3])));
2625 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2626 [(set_attr "type" "alu_ext")]
2629 (define_insn "subsi3"
2630 [(set (match_operand:SI
0 "register_operand" "=rk")
2631 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2632 (match_operand:SI
2 "register_operand" "r")))]
2634 "sub
\\t%w0, %w1, %w2"
2635 [(set_attr "type" "alu_sreg")]
2638 ;; zero_extend version of above
2639 (define_insn "*subsi3_uxtw"
2640 [(set (match_operand:DI
0 "register_operand" "=rk")
2642 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2643 (match_operand:SI
2 "register_operand" "r"))))]
2645 "sub
\\t%w0, %w1, %w2"
2646 [(set_attr "type" "alu_sreg")]
2649 (define_insn "subdi3"
2650 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2651 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2652 (match_operand:DI
2 "register_operand" "r,w")))]
2656 sub
\\t%d0, %d1, %d2"
2657 [(set_attr "type" "alu_sreg, neon_sub")
2658 (set_attr "arch" "*,simd")]
2661 (define_expand "subv<mode>
4"
2662 [(match_operand:GPI
0 "register_operand")
2663 (match_operand:GPI
1 "aarch64_reg_or_zero")
2664 (match_operand:GPI
2 "aarch64_reg_or_zero")
2665 (label_ref (match_operand
3 "" ""))]
2668 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2669 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2674 (define_expand "usubv<mode>
4"
2675 [(match_operand:GPI
0 "register_operand")
2676 (match_operand:GPI
1 "aarch64_reg_or_zero")
2677 (match_operand:GPI
2 "aarch64_reg_or_zero")
2678 (label_ref (match_operand
3 "" ""))]
2681 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2682 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2687 (define_expand "subti3"
2688 [(set (match_operand:TI
0 "register_operand" "")
2689 (minus:TI (match_operand:TI
1 "aarch64_reg_or_zero" "")
2690 (match_operand:TI
2 "register_operand" "")))]
2693 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2695 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2696 &low_dest, &op1_low, &op2_low,
2697 &high_dest, &op1_high, &op2_high);
2699 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2700 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2702 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2703 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2707 (define_expand "subvti4"
2708 [(match_operand:TI
0 "register_operand")
2709 (match_operand:TI
1 "aarch64_reg_or_zero")
2710 (match_operand:TI
2 "aarch64_reg_or_imm")
2711 (label_ref (match_operand
3 "" ""))]
2714 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2716 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2717 &low_dest, &op1_low, &op2_low,
2718 &high_dest, &op1_high, &op2_high);
2719 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2720 high_dest, op1_high, op2_high);
2722 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2726 (define_expand "usubvti4"
2727 [(match_operand:TI
0 "register_operand")
2728 (match_operand:TI
1 "aarch64_reg_or_zero")
2729 (match_operand:TI
2 "aarch64_reg_or_imm")
2730 (label_ref (match_operand
3 "" ""))]
2733 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2735 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2736 &low_dest, &op1_low, &op2_low,
2737 &high_dest, &op1_high, &op2_high);
2738 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2739 high_dest, op1_high, op2_high);
2741 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2745 (define_insn "*sub<mode>
3_compare0"
2746 [(set (reg:CC_NZ CC_REGNUM)
2747 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2748 (match_operand:GPI
2 "register_operand" "r"))
2750 (set (match_operand:GPI
0 "register_operand" "=r")
2751 (minus:GPI (match_dup
1) (match_dup
2)))]
2753 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2754 [(set_attr "type" "alus_sreg")]
2757 ;; zero_extend version of above
2758 (define_insn "*subsi3_compare0_uxtw"
2759 [(set (reg:CC_NZ CC_REGNUM)
2760 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "r")
2761 (match_operand:SI
2 "register_operand" "r"))
2763 (set (match_operand:DI
0 "register_operand" "=r")
2764 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
2766 "subs
\\t%w0, %w1, %w2"
2767 [(set_attr "type" "alus_sreg")]
2770 (define_insn "*sub<mode>
3_compare1_imm"
2771 [(set (reg:CC CC_REGNUM)
2773 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ,rZ")
2774 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2775 (set (match_operand:GPI
0 "register_operand" "=r,r")
2778 (match_operand:GPI
3 "aarch64_plus_immediate" "J,I")))]
2779 "UINTVAL (operands[
2]) == -UINTVAL (operands[
3])"
2781 subs
\\t%<w>
0, %<w>
1, #%n3
2782 adds
\\t%<w>
0, %<w>
1, %
3"
2783 [(set_attr "type" "alus_imm")]
2786 (define_insn "sub<mode>
3_compare1"
2787 [(set (reg:CC CC_REGNUM)
2789 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2790 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
2791 (set (match_operand:GPI
0 "register_operand" "=r")
2792 (minus:GPI (match_dup
1) (match_dup
2)))]
2794 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2795 [(set_attr "type" "alus_sreg")]
2798 (define_insn "sub<mode>
3_compare1_imm"
2799 [(set (reg:CC CC_REGNUM)
2801 (match_operand:GPI
1 "register_operand" "r")
2802 (match_operand:GPI
3 "const_int_operand" "n")))
2803 (set (match_operand:GPI
0 "register_operand" "=r")
2804 (plus:GPI (match_dup
1)
2805 (match_operand:GPI
2 "aarch64_sub_immediate" "J")))]
2806 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2807 "subs
\\t%<w>
0, %<w>
1, #%n2"
2808 [(set_attr "type" "alus_sreg")]
2812 [(set (match_operand:GPI
0 "register_operand")
2813 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
2814 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2815 (set (reg:CC CC_REGNUM)
2819 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2820 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
2823 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2829 ;; Same as the above peephole but with the compare and minus in
2830 ;; swapped order. The restriction on overlap between operand
0
2831 ;; and operands
1 and
2 doesn't apply here.
2833 [(set (reg:CC CC_REGNUM)
2835 (match_operand:GPI
1 "aarch64_reg_or_zero")
2836 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2837 (set (match_operand:GPI
0 "register_operand")
2838 (minus:GPI (match_dup
1)
2843 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2850 [(set (match_operand:GPI
0 "register_operand")
2851 (plus:GPI (match_operand:GPI
1 "register_operand")
2852 (match_operand:GPI
2 "aarch64_sub_immediate")))
2853 (set (reg:CC CC_REGNUM)
2856 (match_operand:GPI
3 "const_int_operand")))]
2857 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2858 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2861 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2862 operands[
2], operands[
3]));
2867 ;; Same as the above peephole but with the compare and minus in
2868 ;; swapped order. The restriction on overlap between operand
0
2869 ;; and operands
1 doesn't apply here.
2871 [(set (reg:CC CC_REGNUM)
2873 (match_operand:GPI
1 "register_operand")
2874 (match_operand:GPI
3 "const_int_operand")))
2875 (set (match_operand:GPI
0 "register_operand")
2876 (plus:GPI (match_dup
1)
2877 (match_operand:GPI
2 "aarch64_sub_immediate")))]
2878 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2881 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2882 operands[
2], operands[
3]));
2887 (define_insn "*sub_<shift>_<mode>"
2888 [(set (match_operand:GPI
0 "register_operand" "=r")
2889 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2891 (match_operand:GPI
1 "register_operand" "r")
2892 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
2894 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2895 [(set_attr "type" "alu_shift_imm")]
2898 ;; zero_extend version of above
2899 (define_insn "*sub_<shift>_si_uxtw"
2900 [(set (match_operand:DI
0 "register_operand" "=r")
2902 (minus:SI (match_operand:SI
3 "register_operand" "r")
2904 (match_operand:SI
1 "register_operand" "r")
2905 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
2907 "sub
\\t%w0, %w3, %w1, <shift> %
2"
2908 [(set_attr "type" "alu_shift_imm")]
2911 (define_insn "*sub_mul_imm_<mode>"
2912 [(set (match_operand:GPI
0 "register_operand" "=r")
2913 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2915 (match_operand:GPI
1 "register_operand" "r")
2916 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
2918 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2919 [(set_attr "type" "alu_shift_imm")]
2922 ;; zero_extend version of above
2923 (define_insn "*sub_mul_imm_si_uxtw"
2924 [(set (match_operand:DI
0 "register_operand" "=r")
2926 (minus:SI (match_operand:SI
3 "register_operand" "r")
2928 (match_operand:SI
1 "register_operand" "r")
2929 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
2931 "sub
\\t%w0, %w3, %w1, lsl %p2"
2932 [(set_attr "type" "alu_shift_imm")]
2935 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2936 [(set (match_operand:GPI
0 "register_operand" "=rk")
2937 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2939 (match_operand:ALLX
2 "register_operand" "r"))))]
2941 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2942 [(set_attr "type" "alu_ext")]
2945 ;; zero_extend version of above
2946 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2947 [(set (match_operand:DI
0 "register_operand" "=rk")
2949 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2951 (match_operand:SHORT
2 "register_operand" "r")))))]
2953 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2954 [(set_attr "type" "alu_ext")]
2957 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2958 [(set (match_operand:GPI
0 "register_operand" "=rk")
2959 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2960 (ashift:GPI (ANY_EXTEND:GPI
2961 (match_operand:ALLX
2 "register_operand" "r"))
2962 (match_operand
3 "aarch64_imm3" "Ui3"))))]
2964 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2965 [(set_attr "type" "alu_ext")]
2968 ;; zero_extend version of above
2969 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2970 [(set (match_operand:DI
0 "register_operand" "=rk")
2972 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2973 (ashift:SI (ANY_EXTEND:SI
2974 (match_operand:SHORT
2 "register_operand" "r"))
2975 (match_operand
3 "aarch64_imm3" "Ui3")))))]
2977 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
2978 [(set_attr "type" "alu_ext")]
2981 (define_insn "*sub_<optab><mode>_multp2"
2982 [(set (match_operand:GPI
0 "register_operand" "=rk")
2983 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2985 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2986 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2987 (match_operand
3 "const_int_operand" "n")
2989 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2990 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2991 [(set_attr "type" "alu_ext")]
2994 ;; zero_extend version of above
2995 (define_insn "*sub_<optab>si_multp2_uxtw"
2996 [(set (match_operand:DI
0 "register_operand" "=rk")
2998 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3000 (mult:SI (match_operand:SI
1 "register_operand" "r")
3001 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3002 (match_operand
3 "const_int_operand" "n")
3004 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
3005 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
3006 [(set_attr "type" "alu_ext")]
3009 ;; The hardware description is op1 + ~op2 + C.
3010 ;; = op1 + (-op2 +
1) + (
1 - !C)
3011 ;; = op1 - op2 -
1 +
1 - !C
3012 ;; = op1 - op2 - !C.
3013 ;; We describe the latter.
3015 (define_insn "*sub<mode>
3_carryin0"
3016 [(set (match_operand:GPI
0 "register_operand" "=r")
3018 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3019 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
3021 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
3022 [(set_attr "type" "adc_reg")]
3025 ;; zero_extend version of the above
3026 (define_insn "*subsi3_carryin_uxtw"
3027 [(set (match_operand:DI
0 "register_operand" "=r")
3030 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3031 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
3033 "sbc
\\t%w0, %w1, wzr"
3034 [(set_attr "type" "adc_reg")]
3037 (define_expand "sub<mode>
3_carryin"
3038 [(set (match_operand:GPI
0 "register_operand")
3041 (match_operand:GPI
1 "aarch64_reg_or_zero")
3042 (match_operand:GPI
2 "register_operand"))
3043 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
3048 (define_insn "*sub<mode>
3_carryin"
3049 [(set (match_operand:GPI
0 "register_operand" "=r")
3052 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3053 (match_operand:GPI
2 "register_operand" "r"))
3054 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3057 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3058 [(set_attr "type" "adc_reg")]
3061 ;; zero_extend version of the above
3062 (define_insn "*subsi3_carryin_uxtw"
3063 [(set (match_operand:DI
0 "register_operand" "=r")
3067 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3068 (match_operand:SI
2 "register_operand" "r"))
3069 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
3072 "sbc
\\t%w0, %w1, %w2"
3073 [(set_attr "type" "adc_reg")]
3076 (define_insn "*sub<mode>
3_carryin_alt"
3077 [(set (match_operand:GPI
0 "register_operand" "=r")
3080 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3081 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
3082 (match_operand:GPI
2 "register_operand" "r")))]
3084 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3085 [(set_attr "type" "adc_reg")]
3088 ;; zero_extend version of the above
3089 (define_insn "*subsi3_carryin_alt_uxtw"
3090 [(set (match_operand:DI
0 "register_operand" "=r")
3094 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3095 (match_operand:SI
3 "aarch64_borrow_operation" ""))
3096 (match_operand:SI
2 "register_operand" "r"))))]
3098 "sbc
\\t%w0, %w1, %w2"
3099 [(set_attr "type" "adc_reg")]
3102 (define_expand "sub<mode>
3_carryinCV"
3104 [(set (reg:CC CC_REGNUM)
3107 (match_operand:GPI
1 "aarch64_reg_or_zero" ""))
3110 (match_operand:GPI
2 "register_operand" ""))
3111 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0)))))
3112 (set (match_operand:GPI
0 "register_operand" "")
3114 (minus:GPI (match_dup
1) (match_dup
2))
3115 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3119 (define_insn "*sub<mode>
3_carryinCV_z1_z2"
3120 [(set (reg:CC CC_REGNUM)
3123 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3124 (set (match_operand:GPI
0 "register_operand" "=r")
3125 (neg:GPI (match_operand:GPI
1 "aarch64_borrow_operation" "")))]
3127 "sbcs
\\t%<w>
0, <w>zr, <w>zr"
3128 [(set_attr "type" "adc_reg")]
3131 (define_insn "*sub<mode>
3_carryinCV_z1"
3132 [(set (reg:CC CC_REGNUM)
3137 (match_operand:GPI
1 "register_operand" "r"))
3138 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))))
3139 (set (match_operand:GPI
0 "register_operand" "=r")
3141 (neg:GPI (match_dup
1))
3142 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3144 "sbcs
\\t%<w>
0, <w>zr, %<w>
1"
3145 [(set_attr "type" "adc_reg")]
3148 (define_insn "*sub<mode>
3_carryinCV_z2"
3149 [(set (reg:CC CC_REGNUM)
3152 (match_operand:GPI
1 "register_operand" "r"))
3153 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3154 (set (match_operand:GPI
0 "register_operand" "=r")
3157 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3159 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3160 [(set_attr "type" "adc_reg")]
3163 (define_insn "*sub<mode>
3_carryinCV"
3164 [(set (reg:CC CC_REGNUM)
3167 (match_operand:GPI
1 "register_operand" "r"))
3170 (match_operand:GPI
2 "register_operand" "r"))
3171 (match_operand:<DWI>
3 "aarch64_borrow_operation" ""))))
3172 (set (match_operand:GPI
0 "register_operand" "=r")
3174 (minus:GPI (match_dup
1) (match_dup
2))
3175 (match_operand:GPI
4 "aarch64_borrow_operation" "")))]
3177 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3178 [(set_attr "type" "adc_reg")]
3181 (define_insn "*sub_uxt<mode>_shift2"
3182 [(set (match_operand:GPI
0 "register_operand" "=rk")
3183 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3185 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
3186 (match_operand
2 "aarch64_imm3" "Ui3"))
3187 (match_operand
3 "const_int_operand" "n"))))]
3188 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3190 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3191 INTVAL (operands[
3])));
3192 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
3193 [(set_attr "type" "alu_ext")]
3196 ;; zero_extend version of above
3197 (define_insn "*sub_uxtsi_shift2_uxtw"
3198 [(set (match_operand:DI
0 "register_operand" "=rk")
3200 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3202 (ashift:SI (match_operand:SI
1 "register_operand" "r")
3203 (match_operand
2 "aarch64_imm3" "Ui3"))
3204 (match_operand
3 "const_int_operand" "n")))))]
3205 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3207 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3208 INTVAL (operands[
3])));
3209 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
3210 [(set_attr "type" "alu_ext")]
3213 (define_insn "*sub_uxt<mode>_multp2"
3214 [(set (match_operand:GPI
0 "register_operand" "=rk")
3215 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3217 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3218 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3219 (match_operand
3 "const_int_operand" "n"))))]
3220 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3222 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3223 INTVAL (operands[
3])));
3224 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
3225 [(set_attr "type" "alu_ext")]
3228 ;; zero_extend version of above
3229 (define_insn "*sub_uxtsi_multp2_uxtw"
3230 [(set (match_operand:DI
0 "register_operand" "=rk")
3232 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3234 (mult:SI (match_operand:SI
1 "register_operand" "r")
3235 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3236 (match_operand
3 "const_int_operand" "n")))))]
3237 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3239 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3240 INTVAL (operands[
3])));
3241 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
3242 [(set_attr "type" "alu_ext")]
3245 (define_expand "abs<mode>
2"
3246 [(match_operand:GPI
0 "register_operand" "")
3247 (match_operand:GPI
1 "register_operand" "")]
3250 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
3251 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3252 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
3257 (define_insn "neg<mode>
2"
3258 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3259 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3263 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
3264 [(set_attr "type" "alu_sreg, neon_neg<q>")
3265 (set_attr "arch" "*,simd")]
3268 ;; zero_extend version of above
3269 (define_insn "*negsi2_uxtw"
3270 [(set (match_operand:DI
0 "register_operand" "=r")
3271 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
3274 [(set_attr "type" "alu_sreg")]
3277 (define_insn "*ngc<mode>"
3278 [(set (match_operand:GPI
0 "register_operand" "=r")
3280 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
3281 (match_operand:GPI
1 "register_operand" "r")))]
3283 "ngc
\\t%<w>
0, %<w>
1"
3284 [(set_attr "type" "adc_reg")]
3287 (define_insn "*ngcsi_uxtw"
3288 [(set (match_operand:DI
0 "register_operand" "=r")
3291 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
3292 (match_operand:SI
1 "register_operand" "r"))))]
3295 [(set_attr "type" "adc_reg")]
3298 (define_insn "neg<mode>
2_compare0"
3299 [(set (reg:CC_NZ CC_REGNUM)
3300 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3302 (set (match_operand:GPI
0 "register_operand" "=r")
3303 (neg:GPI (match_dup
1)))]
3305 "negs
\\t%<w>
0, %<w>
1"
3306 [(set_attr "type" "alus_sreg")]
3309 ;; zero_extend version of above
3310 (define_insn "*negsi2_compare0_uxtw"
3311 [(set (reg:CC_NZ CC_REGNUM)
3312 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
3314 (set (match_operand:DI
0 "register_operand" "=r")
3315 (zero_extend:DI (neg:SI (match_dup
1))))]
3318 [(set_attr "type" "alus_sreg")]
3321 (define_insn "*neg_<shift><mode>
3_compare0"
3322 [(set (reg:CC_NZ CC_REGNUM)
3324 (neg:GPI (ASHIFT:GPI
3325 (match_operand:GPI
1 "register_operand" "r")
3326 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3328 (set (match_operand:GPI
0 "register_operand" "=r")
3329 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
3331 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
3332 [(set_attr "type" "alus_shift_imm")]
3335 (define_insn "*neg_<shift>_<mode>
2"
3336 [(set (match_operand:GPI
0 "register_operand" "=r")
3337 (neg:GPI (ASHIFT:GPI
3338 (match_operand:GPI
1 "register_operand" "r")
3339 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3341 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
3342 [(set_attr "type" "alu_shift_imm")]
3345 ;; zero_extend version of above
3346 (define_insn "*neg_<shift>_si2_uxtw"
3347 [(set (match_operand:DI
0 "register_operand" "=r")
3350 (match_operand:SI
1 "register_operand" "r")
3351 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3353 "neg
\\t%w0, %w1, <shift> %
2"
3354 [(set_attr "type" "alu_shift_imm")]
3357 (define_insn "*neg_mul_imm_<mode>
2"
3358 [(set (match_operand:GPI
0 "register_operand" "=r")
3360 (match_operand:GPI
1 "register_operand" "r")
3361 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3363 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
3364 [(set_attr "type" "alu_shift_imm")]
3367 ;; zero_extend version of above
3368 (define_insn "*neg_mul_imm_si2_uxtw"
3369 [(set (match_operand:DI
0 "register_operand" "=r")
3372 (match_operand:SI
1 "register_operand" "r")
3373 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3375 "neg
\\t%w0, %w1, lsl %p2"
3376 [(set_attr "type" "alu_shift_imm")]
3379 (define_insn "mul<mode>
3"
3380 [(set (match_operand:GPI
0 "register_operand" "=r")
3381 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3382 (match_operand:GPI
2 "register_operand" "r")))]
3384 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
3385 [(set_attr "type" "mul")]
3388 ;; zero_extend version of above
3389 (define_insn "*mulsi3_uxtw"
3390 [(set (match_operand:DI
0 "register_operand" "=r")
3392 (mult:SI (match_operand:SI
1 "register_operand" "r")
3393 (match_operand:SI
2 "register_operand" "r"))))]
3395 "mul
\\t%w0, %w1, %w2"
3396 [(set_attr "type" "mul")]
3399 (define_insn "madd<mode>"
3400 [(set (match_operand:GPI
0 "register_operand" "=r")
3401 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3402 (match_operand:GPI
2 "register_operand" "r"))
3403 (match_operand:GPI
3 "register_operand" "r")))]
3405 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3406 [(set_attr "type" "mla")]
3409 ;; zero_extend version of above
3410 (define_insn "*maddsi_uxtw"
3411 [(set (match_operand:DI
0 "register_operand" "=r")
3413 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
3414 (match_operand:SI
2 "register_operand" "r"))
3415 (match_operand:SI
3 "register_operand" "r"))))]
3417 "madd
\\t%w0, %w1, %w2, %w3"
3418 [(set_attr "type" "mla")]
3421 (define_insn "*msub<mode>"
3422 [(set (match_operand:GPI
0 "register_operand" "=r")
3423 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3424 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3425 (match_operand:GPI
2 "register_operand" "r"))))]
3428 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3429 [(set_attr "type" "mla")]
3432 ;; zero_extend version of above
3433 (define_insn "*msubsi_uxtw"
3434 [(set (match_operand:DI
0 "register_operand" "=r")
3436 (minus:SI (match_operand:SI
3 "register_operand" "r")
3437 (mult:SI (match_operand:SI
1 "register_operand" "r")
3438 (match_operand:SI
2 "register_operand" "r")))))]
3441 "msub
\\t%w0, %w1, %w2, %w3"
3442 [(set_attr "type" "mla")]
3445 (define_insn "*mul<mode>_neg"
3446 [(set (match_operand:GPI
0 "register_operand" "=r")
3447 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3448 (match_operand:GPI
2 "register_operand" "r")))]
3451 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3452 [(set_attr "type" "mul")]
3455 ;; zero_extend version of above
3456 (define_insn "*mulsi_neg_uxtw"
3457 [(set (match_operand:DI
0 "register_operand" "=r")
3459 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3460 (match_operand:SI
2 "register_operand" "r"))))]
3463 "mneg
\\t%w0, %w1, %w2"
3464 [(set_attr "type" "mul")]
3467 (define_insn "<su_optab>mulsidi3"
3468 [(set (match_operand:DI
0 "register_operand" "=r")
3469 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3470 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3472 "<su>mull
\\t%
0, %w1, %w2"
3473 [(set_attr "type" "<su>mull")]
3476 (define_insn "<su_optab>maddsidi4"
3477 [(set (match_operand:DI
0 "register_operand" "=r")
3479 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3480 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3481 (match_operand:DI
3 "register_operand" "r")))]
3483 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3484 [(set_attr "type" "<su>mlal")]
3487 (define_insn "<su_optab>msubsidi4"
3488 [(set (match_operand:DI
0 "register_operand" "=r")
3490 (match_operand:DI
3 "register_operand" "r")
3491 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3493 (match_operand:SI
2 "register_operand" "r")))))]
3495 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3496 [(set_attr "type" "<su>mlal")]
3499 (define_insn "*<su_optab>mulsidi_neg"
3500 [(set (match_operand:DI
0 "register_operand" "=r")
3502 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3503 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3505 "<su>mnegl
\\t%
0, %w1, %w2"
3506 [(set_attr "type" "<su>mull")]
3509 (define_expand "<su_optab>mulditi3"
3510 [(set (match_operand:TI
0 "register_operand")
3511 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3512 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3515 rtx low = gen_reg_rtx (DImode);
3516 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3518 rtx high = gen_reg_rtx (DImode);
3519 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3521 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3522 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3526 ;; The default expansion of multi3 using umuldi3_highpart will perform
3527 ;; the additions in an order that fails to combine into two madd insns.
3528 (define_expand "multi3"
3529 [(set (match_operand:TI
0 "register_operand")
3530 (mult:TI (match_operand:TI
1 "register_operand")
3531 (match_operand:TI
2 "register_operand")))]
3534 rtx l0 = gen_reg_rtx (DImode);
3535 rtx l1 = gen_lowpart (DImode, operands[
1]);
3536 rtx l2 = gen_lowpart (DImode, operands[
2]);
3537 rtx h0 = gen_reg_rtx (DImode);
3538 rtx h1 = gen_highpart (DImode, operands[
1]);
3539 rtx h2 = gen_highpart (DImode, operands[
2]);
3541 emit_insn (gen_muldi3 (l0, l1, l2));
3542 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3543 emit_insn (gen_madddi (h0, h1, l2, h0));
3544 emit_insn (gen_madddi (h0, l1, h2, h0));
3546 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3547 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3551 (define_insn "<su>muldi3_highpart"
3552 [(set (match_operand:DI
0 "register_operand" "=r")
3556 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3557 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3560 "<su>mulh
\\t%
0, %
1, %
2"
3561 [(set_attr "type" "<su>mull")]
3564 (define_insn "<su_optab>div<mode>
3"
3565 [(set (match_operand:GPI
0 "register_operand" "=r")
3566 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3567 (match_operand:GPI
2 "register_operand" "r")))]
3569 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3570 [(set_attr "type" "<su>div")]
3573 ;; zero_extend version of above
3574 (define_insn "*<su_optab>divsi3_uxtw"
3575 [(set (match_operand:DI
0 "register_operand" "=r")
3577 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3578 (match_operand:SI
2 "register_operand" "r"))))]
3580 "<su>div
\\t%w0, %w1, %w2"
3581 [(set_attr "type" "<su>div")]
3584 ;; -------------------------------------------------------------------
3586 ;; -------------------------------------------------------------------
3588 (define_insn "cmp<mode>"
3589 [(set (reg:CC CC_REGNUM)
3590 (compare:CC (match_operand:GPI
0 "register_operand" "rk,rk,rk")
3591 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3597 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3600 (define_insn "fcmp<mode>"
3601 [(set (reg:CCFP CC_REGNUM)
3602 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3603 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3607 fcmp
\\t%<s>
0, %<s>
1"
3608 [(set_attr "type" "fcmp<s>")]
3611 (define_insn "fcmpe<mode>"
3612 [(set (reg:CCFPE CC_REGNUM)
3613 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3614 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3618 fcmpe
\\t%<s>
0, %<s>
1"
3619 [(set_attr "type" "fcmp<s>")]
3622 (define_insn "*cmp_swp_<shift>_reg<mode>"
3623 [(set (reg:CC_SWP CC_REGNUM)
3624 (compare:CC_SWP (ASHIFT:GPI
3625 (match_operand:GPI
0 "register_operand" "r")
3626 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3627 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3629 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3630 [(set_attr "type" "alus_shift_imm")]
3633 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3634 [(set (reg:CC_SWP CC_REGNUM)
3635 (compare:CC_SWP (ANY_EXTEND:GPI
3636 (match_operand:ALLX
0 "register_operand" "r"))
3637 (match_operand:GPI
1 "register_operand" "r")))]
3639 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3640 [(set_attr "type" "alus_ext")]
3643 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3644 [(set (reg:CC_SWP CC_REGNUM)
3645 (compare:CC_SWP (ashift:GPI
3647 (match_operand:ALLX
0 "register_operand" "r"))
3648 (match_operand
1 "aarch64_imm3" "Ui3"))
3649 (match_operand:GPI
2 "register_operand" "r")))]
3651 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3652 [(set_attr "type" "alus_ext")]
3655 ;; -------------------------------------------------------------------
3656 ;; Store-flag and conditional select insns
3657 ;; -------------------------------------------------------------------
3659 (define_expand "cstore<mode>
4"
3660 [(set (match_operand:SI
0 "register_operand" "")
3661 (match_operator:SI
1 "aarch64_comparison_operator"
3662 [(match_operand:GPI
2 "register_operand" "")
3663 (match_operand:GPI
3 "aarch64_plus_operand" "")]))]
3666 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3668 operands[
3] = const0_rtx;
3672 (define_expand "cstorecc4"
3673 [(set (match_operand:SI
0 "register_operand")
3674 (match_operator
1 "aarch64_comparison_operator_mode"
3675 [(match_operand
2 "cc_register")
3676 (match_operand
3 "const0_operand")]))]
3679 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
3684 (define_expand "cstore<mode>
4"
3685 [(set (match_operand:SI
0 "register_operand" "")
3686 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3687 [(match_operand:GPF
2 "register_operand" "")
3688 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")]))]
3691 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3693 operands[
3] = const0_rtx;
3697 (define_insn "aarch64_cstore<mode>"
3698 [(set (match_operand:ALLI
0 "register_operand" "=r")
3699 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3700 [(match_operand
2 "cc_register" "") (const_int
0)]))]
3703 [(set_attr "type" "csel")]
3706 ;; For a
24-bit immediate CST we can optimize the compare for equality
3707 ;; and branch sequence from:
3709 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
3712 ;; into the shorter:
3713 ;; sub x0, x1, #(CST &
0xfff000)
3714 ;; subs x0, x0, #(CST &
0x000fff)
3715 ;; cset x2, <ne, eq>.
3716 (define_insn_and_split "*compare_cstore<mode>_insn"
3717 [(set (match_operand:GPI
0 "register_operand" "=r")
3718 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
3719 (match_operand:GPI
2 "aarch64_imm24" "n")))
3720 (clobber (reg:CC CC_REGNUM))]
3721 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
3722 && !aarch64_plus_operand (operands[
2], <MODE>mode)
3723 && !reload_completed"
3728 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
3729 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
3730 rtx tmp = gen_reg_rtx (<MODE>mode);
3731 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
3732 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3733 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3734 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3735 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
3738 [(set_attr "type" "csel")]
3741 ;; zero_extend version of the above
3742 (define_insn "*cstoresi_insn_uxtw"
3743 [(set (match_operand:DI
0 "register_operand" "=r")
3745 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3746 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3749 [(set_attr "type" "csel")]
3752 (define_insn "cstore<mode>_neg"
3753 [(set (match_operand:ALLI
0 "register_operand" "=r")
3754 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3755 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3757 "csetm
\\t%<w>
0, %m1"
3758 [(set_attr "type" "csel")]
3761 ;; zero_extend version of the above
3762 (define_insn "*cstoresi_neg_uxtw"
3763 [(set (match_operand:DI
0 "register_operand" "=r")
3765 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
3766 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
3769 [(set_attr "type" "csel")]
3772 (define_expand "cmov<mode>
6"
3773 [(set (match_operand:GPI
0 "register_operand" "")
3775 (match_operator
1 "aarch64_comparison_operator"
3776 [(match_operand:GPI
2 "register_operand" "")
3777 (match_operand:GPI
3 "aarch64_plus_operand" "")])
3778 (match_operand:GPI
4 "register_operand" "")
3779 (match_operand:GPI
5 "register_operand" "")))]
3782 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3784 operands[
3] = const0_rtx;
3788 (define_expand "cmov<mode>
6"
3789 [(set (match_operand:GPF
0 "register_operand" "")
3791 (match_operator
1 "aarch64_comparison_operator"
3792 [(match_operand:GPF
2 "register_operand" "")
3793 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")])
3794 (match_operand:GPF
4 "register_operand" "")
3795 (match_operand:GPF
5 "register_operand" "")))]
3798 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3800 operands[
3] = const0_rtx;
3804 (define_insn "*cmov<mode>_insn"
3805 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
3807 (match_operator
1 "aarch64_comparison_operator"
3808 [(match_operand
2 "cc_register" "") (const_int
0)])
3809 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3810 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3811 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3812 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3813 ;; Final two alternatives should be unreachable, but included for completeness
3815 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
3816 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
3817 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
3818 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
3819 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
3822 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3825 ;; zero_extend version of above
3826 (define_insn "*cmovsi_insn_uxtw"
3827 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
3830 (match_operator
1 "aarch64_comparison_operator"
3831 [(match_operand
2 "cc_register" "") (const_int
0)])
3832 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3833 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3834 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3835 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3836 ;; Final two alternatives should be unreachable, but included for completeness
3838 csel
\\t%w0, %w3, %w4, %m1
3839 csinv
\\t%w0, %w3, wzr, %m1
3840 csinv
\\t%w0, %w4, wzr, %M1
3841 csinc
\\t%w0, %w3, wzr, %m1
3842 csinc
\\t%w0, %w4, wzr, %M1
3845 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3848 (define_insn "*cmovdi_insn_uxtw"
3849 [(set (match_operand:DI
0 "register_operand" "=r")
3851 (match_operator
1 "aarch64_comparison_operator"
3852 [(match_operand
2 "cc_register" "") (const_int
0)])
3853 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
3854 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
3856 "csel
\\t%w0, %w3, %w4, %m1"
3857 [(set_attr "type" "csel")]
3860 (define_insn "*cmov<mode>_insn"
3861 [(set (match_operand:GPF
0 "register_operand" "=w")
3863 (match_operator
1 "aarch64_comparison_operator"
3864 [(match_operand
2 "cc_register" "") (const_int
0)])
3865 (match_operand:GPF
3 "register_operand" "w")
3866 (match_operand:GPF
4 "register_operand" "w")))]
3868 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
3869 [(set_attr "type" "fcsel")]
3872 (define_expand "mov<mode>cc"
3873 [(set (match_operand:ALLI
0 "register_operand" "")
3874 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator" "")
3875 (match_operand:ALLI
2 "register_operand" "")
3876 (match_operand:ALLI
3 "register_operand" "")))]
3880 enum rtx_code code = GET_CODE (operands[
1]);
3882 if (code == UNEQ || code == LTGT)
3885 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3886 XEXP (operands[
1],
1));
3887 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3891 (define_expand "mov<GPF:mode><GPI:mode>cc"
3892 [(set (match_operand:GPI
0 "register_operand" "")
3893 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3894 (match_operand:GPF
2 "register_operand" "")
3895 (match_operand:GPF
3 "register_operand" "")))]
3899 enum rtx_code code = GET_CODE (operands[
1]);
3901 if (code == UNEQ || code == LTGT)
3904 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3905 XEXP (operands[
1],
1));
3906 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3910 (define_expand "mov<mode>cc"
3911 [(set (match_operand:GPF
0 "register_operand" "")
3912 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator" "")
3913 (match_operand:GPF
2 "register_operand" "")
3914 (match_operand:GPF
3 "register_operand" "")))]
3918 enum rtx_code code = GET_CODE (operands[
1]);
3920 if (code == UNEQ || code == LTGT)
3923 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3924 XEXP (operands[
1],
1));
3925 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3929 (define_expand "<neg_not_op><mode>cc"
3930 [(set (match_operand:GPI
0 "register_operand" "")
3931 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3932 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand" ""))
3933 (match_operand:GPI
3 "register_operand" "")))]
3937 enum rtx_code code = GET_CODE (operands[
1]);
3939 if (code == UNEQ || code == LTGT)
3942 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3943 XEXP (operands[
1],
1));
3944 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3948 ;; CRC32 instructions.
3949 (define_insn "aarch64_<crc_variant>"
3950 [(set (match_operand:SI
0 "register_operand" "=r")
3951 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
3952 (match_operand:<crc_mode>
2 "register_operand" "r")]
3956 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
3957 return "<crc_variant>
\\t%w0, %w1, %x2";
3959 return "<crc_variant>
\\t%w0, %w1, %w2";
3961 [(set_attr "type" "crc")]
3964 (define_insn "*csinc2<mode>_insn"
3965 [(set (match_operand:GPI
0 "register_operand" "=r")
3966 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
3967 (match_operand:GPI
1 "register_operand" "r")))]
3969 "cinc
\\t%<w>
0, %<w>
1, %m2"
3970 [(set_attr "type" "csel")]
3973 (define_insn "csinc3<mode>_insn"
3974 [(set (match_operand:GPI
0 "register_operand" "=r")
3976 (match_operand
1 "aarch64_comparison_operation" "")
3977 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
3979 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3981 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3982 [(set_attr "type" "csel")]
3985 (define_insn "*csinv3<mode>_insn"
3986 [(set (match_operand:GPI
0 "register_operand" "=r")
3988 (match_operand
1 "aarch64_comparison_operation" "")
3989 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
3990 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3992 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3993 [(set_attr "type" "csel")]
3996 (define_insn "csneg3_uxtw_insn"
3997 [(set (match_operand:DI
0 "register_operand" "=r")
4000 (match_operand
1 "aarch64_comparison_operation" "")
4001 (neg:SI (match_operand:SI
2 "register_operand" "r"))
4002 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
4004 "csneg
\\t%w0, %w3, %w2, %M1"
4005 [(set_attr "type" "csel")]
4008 (define_insn "csneg3<mode>_insn"
4009 [(set (match_operand:GPI
0 "register_operand" "=r")
4011 (match_operand
1 "aarch64_comparison_operation" "")
4012 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
4013 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
4015 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
4016 [(set_attr "type" "csel")]
4019 ;; If X can be loaded by a single CNT[BHWD] instruction,
4023 ;; is equivalent to:
4025 ;; TMP = UQDEC[BHWD] (B, X)
4028 ;; Defining the pattern this way means that:
4030 ;; A = UMAX (B, X) - X
4034 ;; TMP1 = UQDEC[BHWD] (B, X)
4038 ;; which combine can optimize to:
4040 ;; A = UQDEC[BHWD] (B, X)
4042 ;; We don't use match_operand predicates because the order of the operands
4043 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4044 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4045 (define_expand "umax<mode>
3"
4046 [(set (match_operand:GPI
0 "register_operand")
4047 (umax:GPI (match_operand:GPI
1 "")
4048 (match_operand:GPI
2 "")))]
4051 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
4052 std::swap (operands[
1], operands[
2]);
4053 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
4055 rtx temp = gen_reg_rtx (<MODE>mode);
4056 operands[
1] = force_reg (<MODE>mode, operands[
1]);
4057 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
4058 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
4063 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4064 (define_insn "aarch64_uqdec<mode>"
4065 [(set (match_operand:GPI
0 "register_operand" "=r")
4067 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
4068 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
4072 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
4076 ;; -------------------------------------------------------------------
4077 ;; Logical operations
4078 ;; -------------------------------------------------------------------
4081 (define_insn_and_split "*aarch64_and<mode>_imm2"
4082 [(set (match_operand:GPI
0 "register_operand" "=rk")
4083 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
4084 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
4090 HOST_WIDE_INT val = INTVAL (operands[
2]);
4091 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4092 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4094 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
4095 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
4100 (define_insn "<optab><mode>
3"
4101 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
4102 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
4103 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
4106 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
4107 <logical>
\\t%<w>
0, %<w>
1, %
2
4108 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
4109 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4110 (set_attr "arch" "*,*,simd")]
4113 ;; zero_extend version of above
4114 (define_insn "*<optab>si3_uxtw"
4115 [(set (match_operand:DI
0 "register_operand" "=r,rk")
4117 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
4118 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
4121 <logical>
\\t%w0, %w1, %w2
4122 <logical>
\\t%w0, %w1, %
2"
4123 [(set_attr "type" "logic_reg,logic_imm")]
4126 (define_insn "*and<mode>
3_compare0"
4127 [(set (reg:CC_NZ CC_REGNUM)
4129 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
4130 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
4132 (set (match_operand:GPI
0 "register_operand" "=r,r")
4133 (and:GPI (match_dup
1) (match_dup
2)))]
4136 ands
\\t%<w>
0, %<w>
1, %<w>
2
4137 ands
\\t%<w>
0, %<w>
1, %
2"
4138 [(set_attr "type" "logics_reg,logics_imm")]
4141 ;; zero_extend version of above
4142 (define_insn "*andsi3_compare0_uxtw"
4143 [(set (reg:CC_NZ CC_REGNUM)
4145 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
4146 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
4148 (set (match_operand:DI
0 "register_operand" "=r,r")
4149 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
4152 ands
\\t%w0, %w1, %w2
4153 ands
\\t%w0, %w1, %
2"
4154 [(set_attr "type" "logics_reg,logics_imm")]
4157 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
4158 [(set (reg:CC_NZ CC_REGNUM)
4161 (match_operand:GPI
1 "register_operand" "r")
4162 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4163 (match_operand:GPI
3 "register_operand" "r"))
4165 (set (match_operand:GPI
0 "register_operand" "=r")
4166 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
4168 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4169 [(set_attr "type" "logics_shift_imm")]
4172 ;; zero_extend version of above
4173 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4174 [(set (reg:CC_NZ CC_REGNUM)
4177 (match_operand:SI
1 "register_operand" "r")
4178 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4179 (match_operand:SI
3 "register_operand" "r"))
4181 (set (match_operand:DI
0 "register_operand" "=r")
4182 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
4185 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4186 [(set_attr "type" "logics_shift_imm")]
4189 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
4190 [(set (match_operand:GPI
0 "register_operand" "=r")
4191 (LOGICAL:GPI (SHIFT:GPI
4192 (match_operand:GPI
1 "register_operand" "r")
4193 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4194 (match_operand:GPI
3 "register_operand" "r")))]
4196 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4197 [(set_attr "type" "logic_shift_imm")]
4200 (define_insn "*<optab>_rol<mode>
3"
4201 [(set (match_operand:GPI
0 "register_operand" "=r")
4202 (LOGICAL:GPI (rotate:GPI
4203 (match_operand:GPI
1 "register_operand" "r")
4204 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4205 (match_operand:GPI
3 "register_operand" "r")))]
4207 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
4208 [(set_attr "type" "logic_shift_imm")]
4211 ;; zero_extend versions of above
4212 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4213 [(set (match_operand:DI
0 "register_operand" "=r")
4215 (LOGICAL:SI (SHIFT:SI
4216 (match_operand:SI
1 "register_operand" "r")
4217 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4218 (match_operand:SI
3 "register_operand" "r"))))]
4220 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4221 [(set_attr "type" "logic_shift_imm")]
4224 (define_insn "*<optab>_rolsi3_uxtw"
4225 [(set (match_operand:DI
0 "register_operand" "=r")
4227 (LOGICAL:SI (rotate:SI
4228 (match_operand:SI
1 "register_operand" "r")
4229 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4230 (match_operand:SI
3 "register_operand" "r"))))]
4232 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
4233 [(set_attr "type" "logic_shift_imm")]
4236 (define_insn "one_cmpl<mode>
2"
4237 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4238 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
4243 [(set_attr "type" "logic_reg,neon_logic")
4244 (set_attr "arch" "*,simd")]
4247 (define_insn "*one_cmpl_<optab><mode>
2"
4248 [(set (match_operand:GPI
0 "register_operand" "=r")
4249 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
4250 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
4252 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
4253 [(set_attr "type" "logic_shift_imm")]
4256 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4258 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
4259 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4260 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
4261 (match_operand:GPI
2 "register_operand" "r,w")))]
4264 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
4265 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
4266 [(set_attr "type" "logic_reg,neon_logic")
4267 (set_attr "arch" "*,simd")]
4270 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4271 [(set (match_operand:DI
0 "register_operand" "=r")
4273 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
4274 (match_operand:SI
2 "register_operand" "r"))))]
4276 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
4277 [(set_attr "type" "logic_reg")]
4280 (define_insn "*xor_one_cmplsidi3_ze"
4281 [(set (match_operand:DI
0 "register_operand" "=r")
4283 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
4284 (match_operand:SI
2 "register_operand" "r")))))]
4286 "eon
\\t%w0, %w1, %w2"
4287 [(set_attr "type" "logic_reg")]
4290 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4291 ;; eon does not operate on SIMD registers so the vector variant must be split.
4292 (define_insn_and_split "*xor_one_cmpl<mode>
3"
4293 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4294 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
4295 (match_operand:GPI
2 "register_operand" "r,w"))))]
4298 eon
\\t%<w>
0, %<w>
1, %<w>
2
4300 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
4301 [(set (match_operand:GPI
0 "register_operand" "=w")
4302 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
4303 (match_operand:GPI
2 "register_operand" "w")))
4304 (set (match_dup
0) (not:GPI (match_dup
0)))]
4306 [(set_attr "type" "logic_reg,multiple")
4307 (set_attr "arch" "*,simd")]
4310 (define_insn "*and_one_cmpl<mode>
3_compare0"
4311 [(set (reg:CC_NZ CC_REGNUM)
4314 (match_operand:GPI
1 "register_operand" "r"))
4315 (match_operand:GPI
2 "register_operand" "r"))
4317 (set (match_operand:GPI
0 "register_operand" "=r")
4318 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
4320 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
4321 [(set_attr "type" "logics_reg")]
4324 ;; zero_extend version of above
4325 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4326 [(set (reg:CC_NZ CC_REGNUM)
4329 (match_operand:SI
1 "register_operand" "r"))
4330 (match_operand:SI
2 "register_operand" "r"))
4332 (set (match_operand:DI
0 "register_operand" "=r")
4333 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
4335 "bics
\\t%w0, %w2, %w1"
4336 [(set_attr "type" "logics_reg")]
4339 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
4340 [(set (reg:CC_NZ CC_REGNUM)
4343 (match_operand:GPI
0 "register_operand" "r"))
4344 (match_operand:GPI
1 "register_operand" "r"))
4347 "bics
\\t<w>zr, %<w>
1, %<w>
0"
4348 [(set_attr "type" "logics_reg")]
4351 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
4352 [(set (match_operand:GPI
0 "register_operand" "=r")
4353 (LOGICAL:GPI (not:GPI
4355 (match_operand:GPI
1 "register_operand" "r")
4356 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4357 (match_operand:GPI
3 "register_operand" "r")))]
4359 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4360 [(set_attr "type" "logic_shift_imm")]
4363 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
4364 [(set (match_operand:GPI
0 "register_operand" "=r")
4367 (match_operand:GPI
1 "register_operand" "r")
4368 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4369 (match_operand:GPI
3 "register_operand" "r"))))]
4371 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4372 [(set_attr "type" "logic_shift_imm")]
4375 ;; Zero-extend version of the above.
4376 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4377 [(set (match_operand:DI
0 "register_operand" "=r")
4381 (match_operand:SI
1 "register_operand" "r")
4382 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4383 (match_operand:SI
3 "register_operand" "r")))))]
4385 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4386 [(set_attr "type" "logic_shift_imm")]
4389 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
4390 [(set (reg:CC_NZ CC_REGNUM)
4394 (match_operand:GPI
1 "register_operand" "r")
4395 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4396 (match_operand:GPI
3 "register_operand" "r"))
4398 (set (match_operand:GPI
0 "register_operand" "=r")
4401 (match_dup
1) (match_dup
2))) (match_dup
3)))]
4403 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4404 [(set_attr "type" "logics_shift_imm")]
4407 ;; zero_extend version of above
4408 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4409 [(set (reg:CC_NZ CC_REGNUM)
4413 (match_operand:SI
1 "register_operand" "r")
4414 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
4415 (match_operand:SI
3 "register_operand" "r"))
4417 (set (match_operand:DI
0 "register_operand" "=r")
4418 (zero_extend:DI (and:SI
4420 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
4422 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4423 [(set_attr "type" "logics_shift_imm")]
4426 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
4427 [(set (reg:CC_NZ CC_REGNUM)
4431 (match_operand:GPI
0 "register_operand" "r")
4432 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
4433 (match_operand:GPI
2 "register_operand" "r"))
4436 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
4437 [(set_attr "type" "logics_shift_imm")]
4440 (define_insn "clz<mode>
2"
4441 [(set (match_operand:GPI
0 "register_operand" "=r")
4442 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4444 "clz
\\t%<w>
0, %<w>
1"
4445 [(set_attr "type" "clz")]
4448 (define_expand "ffs<mode>
2"
4449 [(match_operand:GPI
0 "register_operand")
4450 (match_operand:GPI
1 "register_operand")]
4453 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4454 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4456 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4457 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4458 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4463 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4470 (define_expand "popcount<mode>
2"
4471 [(match_operand:GPI
0 "register_operand")
4472 (match_operand:GPI
1 "register_operand")]
4475 rtx v = gen_reg_rtx (V8QImode);
4476 rtx v1 = gen_reg_rtx (V8QImode);
4477 rtx r = gen_reg_rtx (QImode);
4478 rtx in = operands[
1];
4479 rtx out = operands[
0];
4480 if(<MODE>mode == SImode)
4483 tmp = gen_reg_rtx (DImode);
4484 /* If we have SImode, zero extend to DImode, pop count does
4485 not change if we have extra zeros. */
4486 emit_insn (gen_zero_extendsidi2 (tmp, in));
4489 emit_move_insn (v, gen_lowpart (V8QImode, in));
4490 emit_insn (gen_popcountv8qi2 (v1, v));
4491 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4492 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4496 (define_insn "clrsb<mode>
2"
4497 [(set (match_operand:GPI
0 "register_operand" "=r")
4498 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4500 "cls
\\t%<w>
0, %<w>
1"
4501 [(set_attr "type" "clz")]
4504 (define_insn "rbit<mode>
2"
4505 [(set (match_operand:GPI
0 "register_operand" "=r")
4506 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4508 "rbit
\\t%<w>
0, %<w>
1"
4509 [(set_attr "type" "rbit")]
4512 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4513 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4514 ;; expression and split after reload to enable scheduling them apart if
4517 (define_insn_and_split "ctz<mode>
2"
4518 [(set (match_operand:GPI
0 "register_operand" "=r")
4519 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4525 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4526 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4530 (define_insn "*and<mode>_compare0"
4531 [(set (reg:CC_NZ CC_REGNUM)
4533 (match_operand:SHORT
0 "register_operand" "r")
4536 "tst
\\t%<w>
0, <short_mask>"
4537 [(set_attr "type" "alus_imm")]
4540 (define_insn "*ands<mode>_compare0"
4541 [(set (reg:CC_NZ CC_REGNUM)
4543 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4545 (set (match_operand:GPI
0 "register_operand" "=r")
4546 (zero_extend:GPI (match_dup
1)))]
4548 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4549 [(set_attr "type" "alus_imm")]
4552 (define_insn "*and<mode>
3nr_compare0"
4553 [(set (reg:CC_NZ CC_REGNUM)
4555 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4556 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4562 [(set_attr "type" "logics_reg,logics_imm")]
4566 [(set (reg:CC_NZ CC_REGNUM)
4568 (and:GPI (match_operand:GPI
0 "register_operand")
4569 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4571 (clobber (match_operand:SI
2 "register_operand"))]
4573 [(set (match_dup
2) (match_dup
1))
4574 (set (reg:CC_NZ CC_REGNUM)
4576 (and:GPI (match_dup
0)
4581 (define_insn "*and<mode>
3nr_compare0_zextract"
4582 [(set (reg:CC_NZ CC_REGNUM)
4584 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4585 (match_operand:GPI
1 "const_int_operand" "n")
4586 (match_operand:GPI
2 "const_int_operand" "n"))
4588 "INTVAL (operands[
1]) >
0
4589 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4590 <= GET_MODE_BITSIZE (<MODE>mode))
4591 && aarch64_bitmask_imm (
4592 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4597 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4598 return "tst
\\t%<w>
0, %
1";
4600 [(set_attr "type" "logics_shift_imm")]
4603 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4604 [(set (reg:CC_NZ CC_REGNUM)
4607 (match_operand:GPI
0 "register_operand" "r")
4608 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4609 (match_operand:GPI
2 "register_operand" "r"))
4612 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4613 [(set_attr "type" "logics_shift_imm")]
4617 [(set (reg:CC_NZ CC_REGNUM)
4620 (match_operand:GPI
0 "register_operand")
4621 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4622 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4624 (clobber (match_operand:SI
3 "register_operand"))]
4626 [(set (match_dup
3) (match_dup
2))
4627 (set (reg:CC_NZ CC_REGNUM)
4636 ;; -------------------------------------------------------------------
4638 ;; -------------------------------------------------------------------
4640 (define_expand "<optab><mode>
3"
4641 [(set (match_operand:GPI
0 "register_operand")
4642 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4643 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4646 if (CONST_INT_P (operands[
2]))
4648 operands[
2] = GEN_INT (INTVAL (operands[
2])
4649 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4651 if (operands[
2] == const0_rtx)
4653 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4660 (define_expand "ashl<mode>
3"
4661 [(set (match_operand:SHORT
0 "register_operand")
4662 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4663 (match_operand:QI
2 "const_int_operand")))]
4666 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4668 if (operands[
2] == const0_rtx)
4670 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4676 (define_expand "rotr<mode>
3"
4677 [(set (match_operand:GPI
0 "register_operand")
4678 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4679 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4682 if (CONST_INT_P (operands[
2]))
4684 operands[
2] = GEN_INT (INTVAL (operands[
2])
4685 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4687 if (operands[
2] == const0_rtx)
4689 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4696 (define_expand "rotl<mode>
3"
4697 [(set (match_operand:GPI
0 "register_operand")
4698 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4699 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4702 /* (SZ - cnt) % SZ == -cnt % SZ */
4703 if (CONST_INT_P (operands[
2]))
4705 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
4706 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4707 if (operands[
2] == const0_rtx)
4709 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4714 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
4719 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4720 ;; they truncate the shift/rotate amount by the size of the registers they
4721 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
4722 ;; such redundant masking instructions. GCC can do that automatically when
4723 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4724 ;; because some of the SISD shift alternatives don't perform this truncations.
4725 ;; So this pattern exists to catch such cases.
4727 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
4728 [(set (match_operand:GPI
0 "register_operand" "=r")
4730 (match_operand:GPI
1 "register_operand" "r")
4731 (match_operator
4 "subreg_lowpart_operator"
4732 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
4733 (match_operand
3 "const_int_operand" "n"))])))]
4734 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
4735 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
4736 [(set_attr "type" "shift_reg")]
4739 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
4740 [(set (match_operand:GPI
0 "register_operand" "=&r")
4742 (match_operand:GPI
1 "register_operand" "r")
4743 (match_operator
4 "subreg_lowpart_operator"
4744 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
4745 (match_operand
3 "const_int_operand" "n")))])))]
4746 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
4751 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4752 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
4753 emit_insn (gen_negsi2 (tmp, operands[
2]));
4755 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
4756 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
4757 SUBREG_BYTE (operands[
4]));
4758 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
4763 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
4764 [(set (match_operand:GPI
0 "register_operand" "=&r")
4766 (match_operand:GPI
1 "register_operand" "r")
4767 (minus:QI (match_operand
2 "const_int_operand" "n")
4768 (match_operator
5 "subreg_lowpart_operator"
4769 [(and:SI (match_operand:SI
3 "register_operand" "r")
4770 (match_operand
4 "const_int_operand" "n"))]))))]
4771 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
4772 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4777 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4780 emit_insn (gen_negsi2 (tmp, operands[
3]));
4782 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
4783 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
4784 SUBREG_BYTE (operands[
5]));
4786 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
4791 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4792 [(set (match_operand:DI
0 "register_operand" "=r")
4794 (match_operand:DI
1 "register_operand" "r")
4795 (match_operator
4 "subreg_lowpart_operator"
4796 [(and:SI (match_operand:SI
2 "register_operand" "r")
4797 (match_operand
3 "const_int_operand" "n"))])))]
4798 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
4801 xop[
0] = operands[
0];
4802 xop[
1] = operands[
1];
4803 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
4804 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
4807 [(set_attr "type" "shift_reg")]
4810 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
4811 [(set (match_operand:GPI
0 "register_operand" "=&r")
4813 (match_operand:GPI
1 "register_operand" "r")
4814 (minus:QI (match_operand
2 "const_int_operand" "n")
4815 (match_operand:QI
3 "register_operand" "r"))))]
4816 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4821 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
4823 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4824 : gen_lowpart (SImode, operands[
0]));
4826 emit_insn (gen_negsi2 (tmp, subreg_tmp));
4828 rtx and_op = gen_rtx_AND (SImode, tmp,
4829 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
4831 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
4833 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
4836 [(set_attr "length" "
8")]
4839 ;; Logical left shift using SISD or Integer instruction
4840 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
4841 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
4843 (match_operand:GPI
1 "register_operand" "r,r,w,w")
4844 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4847 lsl
\t%<w>
0, %<w>
1, %
2
4848 lsl
\t%<w>
0, %<w>
1, %<w>
2
4849 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4850 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
4851 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
4852 (set_attr "arch" "*,*,simd,simd")]
4855 ;; Logical right shift using SISD or Integer instruction
4856 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
4857 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4859 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4860 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
4861 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4864 lsr
\t%<w>
0, %<w>
1, %
2
4865 lsr
\t%<w>
0, %<w>
1, %<w>
2
4866 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4869 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
4870 (set_attr "arch" "*,*,simd,simd,simd")]
4874 [(set (match_operand:DI
0 "aarch64_simd_register")
4876 (match_operand:DI
1 "aarch64_simd_register")
4877 (match_operand:QI
2 "aarch64_simd_register")))]
4878 "TARGET_SIMD && reload_completed"
4880 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4882 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
4884 operands[
3] = gen_lowpart (QImode, operands[
0]);
4889 [(set (match_operand:SI
0 "aarch64_simd_register")
4891 (match_operand:SI
1 "aarch64_simd_register")
4892 (match_operand:QI
2 "aarch64_simd_register")))]
4893 "TARGET_SIMD && reload_completed"
4895 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4897 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
4899 operands[
3] = gen_lowpart (QImode, operands[
0]);
4903 ;; Arithmetic right shift using SISD or Integer instruction
4904 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
4905 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4907 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4908 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
4909 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4912 asr
\t%<w>
0, %<w>
1, %
2
4913 asr
\t%<w>
0, %<w>
1, %<w>
2
4914 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4917 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
4918 (set_attr "arch" "*,*,simd,simd,simd")]
4922 [(set (match_operand:DI
0 "aarch64_simd_register")
4924 (match_operand:DI
1 "aarch64_simd_register")
4925 (match_operand:QI
2 "aarch64_simd_register")))]
4926 "TARGET_SIMD && reload_completed"
4928 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4930 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
4932 operands[
3] = gen_lowpart (QImode, operands[
0]);
4937 [(set (match_operand:SI
0 "aarch64_simd_register")
4939 (match_operand:SI
1 "aarch64_simd_register")
4940 (match_operand:QI
2 "aarch64_simd_register")))]
4941 "TARGET_SIMD && reload_completed"
4943 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4945 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
4947 operands[
3] = gen_lowpart (QImode, operands[
0]);
4951 (define_insn "*aarch64_sisd_ushl"
4952 [(set (match_operand:DI
0 "register_operand" "=w")
4953 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4954 (match_operand:QI
2 "register_operand" "w")]
4957 "ushl
\t%d0, %d1, %d2"
4958 [(set_attr "type" "neon_shift_reg")]
4961 (define_insn "*aarch64_ushl_2s"
4962 [(set (match_operand:SI
0 "register_operand" "=w")
4963 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4964 (match_operand:QI
2 "register_operand" "w")]
4967 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
4968 [(set_attr "type" "neon_shift_reg")]
4971 (define_insn "*aarch64_sisd_sshl"
4972 [(set (match_operand:DI
0 "register_operand" "=w")
4973 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4974 (match_operand:QI
2 "register_operand" "w")]
4977 "sshl
\t%d0, %d1, %d2"
4978 [(set_attr "type" "neon_shift_reg")]
4981 (define_insn "*aarch64_sshl_2s"
4982 [(set (match_operand:SI
0 "register_operand" "=w")
4983 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4984 (match_operand:QI
2 "register_operand" "w")]
4987 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
4988 [(set_attr "type" "neon_shift_reg")]
4991 (define_insn "*aarch64_sisd_neg_qi"
4992 [(set (match_operand:QI
0 "register_operand" "=w")
4993 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
4997 [(set_attr "type" "neon_neg")]
5001 (define_insn "*ror<mode>
3_insn"
5002 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5004 (match_operand:GPI
1 "register_operand" "r,r")
5005 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5008 ror
\\t%<w>
0, %<w>
1, %
2
5009 ror
\\t%<w>
0, %<w>
1, %<w>
2"
5010 [(set_attr "type" "rotate_imm,shift_reg")]
5013 ;; zero_extend version of above
5014 (define_insn "*<optab>si3_insn_uxtw"
5015 [(set (match_operand:DI
0 "register_operand" "=r,r")
5016 (zero_extend:DI (SHIFT:SI
5017 (match_operand:SI
1 "register_operand" "r,r")
5018 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5021 <shift>
\\t%w0, %w1, %
2
5022 <shift>
\\t%w0, %w1, %w2"
5023 [(set_attr "type" "bfx,shift_reg")]
5026 (define_insn "*<optab><mode>
3_insn"
5027 [(set (match_operand:SHORT
0 "register_operand" "=r")
5028 (ASHIFT:SHORT (match_operand:SHORT
1 "register_operand" "r")
5029 (match_operand
2 "const_int_operand" "n")))]
5030 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5032 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5033 return "<bfshift>
\t%w0, %w1, %
2, %
3";
5035 [(set_attr "type" "bfx")]
5038 (define_insn "*extr<mode>
5_insn"
5039 [(set (match_operand:GPI
0 "register_operand" "=r")
5040 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5041 (match_operand
3 "const_int_operand" "n"))
5042 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5043 (match_operand
4 "const_int_operand" "n"))))]
5044 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5045 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
5046 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5047 [(set_attr "type" "rotate_imm")]
5050 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5051 ;; so we have to match both orderings.
5052 (define_insn "*extr<mode>
5_insn_alt"
5053 [(set (match_operand:GPI
0 "register_operand" "=r")
5054 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5055 (match_operand
4 "const_int_operand" "n"))
5056 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5057 (match_operand
3 "const_int_operand" "n"))))]
5058 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
5059 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
5060 == GET_MODE_BITSIZE (<MODE>mode))"
5061 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5062 [(set_attr "type" "rotate_imm")]
5065 ;; zero_extend version of the above
5066 (define_insn "*extrsi5_insn_uxtw"
5067 [(set (match_operand:DI
0 "register_operand" "=r")
5069 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
5070 (match_operand
3 "const_int_operand" "n"))
5071 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5072 (match_operand
4 "const_int_operand" "n")))))]
5073 "UINTVAL (operands[
3]) <
32 &&
5074 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5075 "extr
\\t%w0, %w1, %w2, %
4"
5076 [(set_attr "type" "rotate_imm")]
5079 (define_insn "*extrsi5_insn_uxtw_alt"
5080 [(set (match_operand:DI
0 "register_operand" "=r")
5082 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5083 (match_operand
4 "const_int_operand" "n"))
5084 (ashift:SI (match_operand:SI
1 "register_operand" "r")
5085 (match_operand
3 "const_int_operand" "n")))))]
5086 "UINTVAL (operands[
3]) <
32 &&
5087 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5088 "extr
\\t%w0, %w1, %w2, %
4"
5089 [(set_attr "type" "rotate_imm")]
5092 (define_insn "*ror<mode>
3_insn"
5093 [(set (match_operand:GPI
0 "register_operand" "=r")
5094 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
5095 (match_operand
2 "const_int_operand" "n")))]
5096 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5098 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5099 return "ror
\\t%<w>
0, %<w>
1, %
3";
5101 [(set_attr "type" "rotate_imm")]
5104 ;; zero_extend version of the above
5105 (define_insn "*rorsi3_insn_uxtw"
5106 [(set (match_operand:DI
0 "register_operand" "=r")
5108 (rotate:SI (match_operand:SI
1 "register_operand" "r")
5109 (match_operand
2 "const_int_operand" "n"))))]
5110 "UINTVAL (operands[
2]) <
32"
5112 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
5113 return "ror
\\t%w0, %w1, %
3";
5115 [(set_attr "type" "rotate_imm")]
5118 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5119 [(set (match_operand:GPI
0 "register_operand" "=r")
5121 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
5122 (match_operand
2 "const_int_operand" "n"))))]
5123 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5125 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5126 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5128 [(set_attr "type" "bfx")]
5131 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5132 [(set (match_operand:GPI
0 "register_operand" "=r")
5134 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5135 (match_operand
2 "const_int_operand" "n"))))]
5136 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5138 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5139 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5141 [(set_attr "type" "bfx")]
5144 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5145 [(set (match_operand:GPI
0 "register_operand" "=r")
5147 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5148 (match_operand
2 "const_int_operand" "n"))))]
5149 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5151 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5152 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5154 [(set_attr "type" "bfx")]
5157 ;; -------------------------------------------------------------------
5159 ;; -------------------------------------------------------------------
5161 (define_expand "<optab>"
5162 [(set (match_operand:DI
0 "register_operand" "=r")
5163 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
5165 "aarch64_simd_shift_imm_offset_di")
5166 (match_operand
3 "aarch64_simd_shift_imm_di")))]
5169 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5170 1, GET_MODE_BITSIZE (DImode) -
1))
5176 (define_insn "*<optab><mode>"
5177 [(set (match_operand:GPI
0 "register_operand" "=r")
5178 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
5180 "aarch64_simd_shift_imm_offset_<mode>" "n")
5182 "aarch64_simd_shift_imm_<mode>" "n")))]
5183 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5184 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5185 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
5186 [(set_attr "type" "bfx")]
5189 ;; When the bit position and width add up to
32 we can use a W-reg LSR
5190 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5192 [(set (match_operand:DI
0 "register_operand")
5193 (zero_extract:DI (match_operand:DI
1 "register_operand")
5195 "aarch64_simd_shift_imm_offset_di")
5197 "aarch64_simd_shift_imm_di")))]
5198 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
5199 GET_MODE_BITSIZE (DImode) -
1)
5200 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
5201 == GET_MODE_BITSIZE (SImode)"
5203 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
5205 operands[
4] = gen_lowpart (SImode, operands[
1]);
5209 ;; Bitfield Insert (insv)
5210 (define_expand "insv<mode>"
5211 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
5212 (match_operand
1 "const_int_operand")
5213 (match_operand
2 "const_int_operand"))
5214 (match_operand:GPI
3 "general_operand"))]
5217 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
5218 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
5219 rtx value = operands[
3];
5221 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5224 if (CONST_INT_P (value))
5226 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
5228 /* Prefer AND/OR for inserting all zeros or all ones. */
5229 if ((UINTVAL (value) & mask) ==
0
5230 || (UINTVAL (value) & mask) == mask)
5233 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
5234 if (width ==
16 && (pos %
16) ==
0)
5237 operands[
3] = force_reg (<MODE>mode, value);
5240 (define_insn "*insv_reg<mode>"
5241 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5242 (match_operand
1 "const_int_operand" "n")
5243 (match_operand
2 "const_int_operand" "n"))
5244 (match_operand:GPI
3 "register_operand" "r"))]
5245 "!(UINTVAL (operands[
1]) ==
0
5246 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
5247 > GET_MODE_BITSIZE (<MODE>mode)))"
5248 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
5249 [(set_attr "type" "bfm")]
5252 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
5253 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5254 (match_operand
1 "const_int_operand" "n")
5255 (match_operand
2 "const_int_operand" "n"))
5256 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
5257 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
5258 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
5259 [(set_attr "type" "bfm")]
5262 (define_insn "*extr_insv_lower_reg<mode>"
5263 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5264 (match_operand
1 "const_int_operand" "n")
5266 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
5268 (match_operand
3 "const_int_operand" "n")))]
5269 "!(UINTVAL (operands[
1]) ==
0
5270 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
5271 > GET_MODE_BITSIZE (<MODE>mode)))"
5272 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
5273 [(set_attr "type" "bfm")]
5276 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5277 [(set (match_operand:GPI
0 "register_operand" "=r")
5278 (ashift:GPI (ANY_EXTEND:GPI
5279 (match_operand:ALLX
1 "register_operand" "r"))
5280 (match_operand
2 "const_int_operand" "n")))]
5281 "UINTVAL (operands[
2]) < <GPI:sizen>"
5283 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
5284 ? GEN_INT (<ALLX:sizen>)
5285 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
5286 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5288 [(set_attr "type" "bfx")]
5291 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5293 (define_insn "*andim_ashift<mode>_bfiz"
5294 [(set (match_operand:GPI
0 "register_operand" "=r")
5295 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5296 (match_operand
2 "const_int_operand" "n"))
5297 (match_operand
3 "const_int_operand" "n")))]
5298 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
5299 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
5300 [(set_attr "type" "bfx")]
5303 ;; Match sbfiz pattern in a shift left + shift right operation.
5305 (define_insn "*ashift<mode>_extv_bfiz"
5306 [(set (match_operand:GPI
0 "register_operand" "=r")
5307 (ashift:GPI (sign_extract:GPI (match_operand:GPI
1 "register_operand" "r")
5308 (match_operand
2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5310 (match_operand
3 "aarch64_simd_shift_imm_<mode>" "n")))]
5311 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5312 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5313 "sbfiz
\\t%<w>
0, %<w>
1, %
3, %
2"
5314 [(set_attr "type" "bfx")]
5317 ;; When the bit position and width of the equivalent extraction add up to
32
5318 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5319 ;; zero-extension of the X-reg.
5321 [(set (match_operand:DI
0 "register_operand")
5322 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
5323 (match_operand
2 "const_int_operand"))
5324 (match_operand
3 "const_int_operand")))]
5325 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
5326 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
5327 == GET_MODE_BITSIZE (SImode)"
5329 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
5331 operands[
4] = gen_lowpart (SImode, operands[
1]);
5335 (define_insn "bswap<mode>
2"
5336 [(set (match_operand:GPI
0 "register_operand" "=r")
5337 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
5339 "rev
\\t%<w>
0, %<w>
1"
5340 [(set_attr "type" "rev")]
5343 (define_insn "bswaphi2"
5344 [(set (match_operand:HI
0 "register_operand" "=r")
5345 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
5348 [(set_attr "type" "rev")]
5351 (define_insn "*aarch64_bfxil<mode>"
5352 [(set (match_operand:GPI
0 "register_operand" "=r,r")
5353 (ior:GPI (and:GPI (match_operand:GPI
1 "register_operand" "r,
0")
5354 (match_operand:GPI
3 "const_int_operand" "n, Ulc"))
5355 (and:GPI (match_operand:GPI
2 "register_operand" "
0,r")
5356 (match_operand:GPI
4 "const_int_operand" "Ulc, n"))))]
5357 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5358 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5359 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5361 switch (which_alternative)
5364 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5365 return "bfxil
\\t%<w>
0, %<w>
1,
0, %
3";
5367 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5368 return "bfxil
\\t%<w>
0, %<w>
2,
0, %
3";
5373 [(set_attr "type" "bfm")]
5376 ; Zero-extended version of above (aarch64_bfxil)
5377 (define_insn "*aarch64_bfxilsi_uxtw"
5378 [(set (match_operand:DI
0 "register_operand" "=r,r")
5379 (zero_extend:DI (ior:SI (and:SI (match_operand:SI
1 "register_operand"
5381 (match_operand:SI
3 "const_int_operand" "n, Ulc"))
5382 (and:SI (match_operand:SI
2 "register_operand" "
0,r")
5383 (match_operand:SI
4 "const_int_operand" "Ulc, n")))))]
5384 "(INTVAL (operands[
3]) == ~INTVAL (operands[
4]))
5385 && (aarch64_high_bits_all_ones_p (INTVAL (operands[
3]))
5386 || aarch64_high_bits_all_ones_p (INTVAL (operands[
4])))"
5388 switch (which_alternative)
5391 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
3])));
5392 return "bfxil
\\t%
0, %
1,
0, %
3";
5394 operands[
3] = GEN_INT (ctz_hwi (~INTVAL (operands[
4])));
5395 return "bfxil
\\t%
0, %
2,
0, %
3";
5400 [(set_attr "type" "bfm")]
5403 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5404 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5405 ;; each valid permutation.
5407 (define_insn "rev16<mode>
2"
5408 [(set (match_operand:GPI
0 "register_operand" "=r")
5409 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5411 (match_operand:GPI
3 "const_int_operand" "n"))
5412 (and:GPI (lshiftrt:GPI (match_dup
1)
5414 (match_operand:GPI
2 "const_int_operand" "n"))))]
5415 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5416 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5417 "rev16
\\t%<w>
0, %<w>
1"
5418 [(set_attr "type" "rev")]
5421 (define_insn "rev16<mode>
2_alt"
5422 [(set (match_operand:GPI
0 "register_operand" "=r")
5423 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
5425 (match_operand:GPI
2 "const_int_operand" "n"))
5426 (and:GPI (ashift:GPI (match_dup
1)
5428 (match_operand:GPI
3 "const_int_operand" "n"))))]
5429 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5430 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5431 "rev16
\\t%<w>
0, %<w>
1"
5432 [(set_attr "type" "rev")]
5435 ;; zero_extend version of above
5436 (define_insn "*bswapsi2_uxtw"
5437 [(set (match_operand:DI
0 "register_operand" "=r")
5438 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
5441 [(set_attr "type" "rev")]
5444 ;; -------------------------------------------------------------------
5445 ;; Floating-point intrinsics
5446 ;; -------------------------------------------------------------------
5448 ;; frint floating-point round to integral standard patterns.
5449 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5451 (define_insn "<frint_pattern><mode>
2"
5452 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5453 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5456 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
5457 [(set_attr "type" "f_rint<stype>")]
5460 ;; frcvt floating-point round to integer and convert standard patterns.
5461 ;; Expands to lbtrunc, lceil, lfloor, lround.
5462 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
5463 [(set (match_operand:GPI
0 "register_operand" "=r")
5465 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5468 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
5469 [(set_attr "type" "f_cvtf2i")]
5472 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
5473 [(set (match_operand:GPI
0 "register_operand" "=r")
5476 (match_operand:GPF
1 "register_operand" "w")
5477 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
5479 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
5480 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5482 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
5484 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
5485 output_asm_insn (buf, operands);
5488 [(set_attr "type" "f_cvtf2i")]
5491 ;; fma - expand fma into patterns with the accumulator operand first since
5492 ;; reusing the accumulator results in better register allocation.
5493 ;; The register allocator considers copy preferences in operand order,
5494 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5496 (define_expand "fma<mode>
4"
5497 [(set (match_operand:GPF_F16
0 "register_operand")
5498 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
5499 (match_operand:GPF_F16
2 "register_operand")
5500 (match_operand:GPF_F16
3 "register_operand")))]
5504 (define_insn "*aarch64_fma<mode>
4"
5505 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5506 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
5507 (match_operand:GPF_F16
3 "register_operand" "w")
5508 (match_operand:GPF_F16
1 "register_operand" "w")))]
5510 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5511 [(set_attr "type" "fmac<stype>")]
5514 (define_expand "fnma<mode>
4"
5515 [(set (match_operand:GPF_F16
0 "register_operand")
5517 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5518 (match_operand:GPF_F16
2 "register_operand")
5519 (match_operand:GPF_F16
3 "register_operand")))]
5523 (define_insn "*aarch64_fnma<mode>
4"
5524 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5526 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5527 (match_operand:GPF_F16
3 "register_operand" "w")
5528 (match_operand:GPF_F16
1 "register_operand" "w")))]
5530 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5531 [(set_attr "type" "fmac<stype>")]
5535 (define_expand "fms<mode>
4"
5536 [(set (match_operand:GPF
0 "register_operand")
5537 (fma:GPF (match_operand:GPF
1 "register_operand")
5538 (match_operand:GPF
2 "register_operand")
5539 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5543 (define_insn "*aarch64_fms<mode>
4"
5544 [(set (match_operand:GPF
0 "register_operand" "=w")
5545 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5546 (match_operand:GPF
3 "register_operand" "w")
5547 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5549 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5550 [(set_attr "type" "fmac<s>")]
5553 (define_expand "fnms<mode>
4"
5554 [(set (match_operand:GPF
0 "register_operand")
5555 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5556 (match_operand:GPF
2 "register_operand")
5557 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5561 (define_insn "*aarch64_fnms<mode>
4"
5562 [(set (match_operand:GPF
0 "register_operand" "=w")
5563 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5564 (match_operand:GPF
3 "register_operand" "w")
5565 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5567 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5568 [(set_attr "type" "fmac<s>")]
5571 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5572 (define_insn "*aarch64_fnmadd<mode>
4"
5573 [(set (match_operand:GPF
0 "register_operand" "=w")
5574 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5575 (match_operand:GPF
3 "register_operand" "w")
5576 (match_operand:GPF
1 "register_operand" "w"))))]
5577 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5578 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5579 [(set_attr "type" "fmac<s>")]
5582 ;; -------------------------------------------------------------------
5583 ;; Floating-point conversions
5584 ;; -------------------------------------------------------------------
5586 (define_insn "extendsfdf2"
5587 [(set (match_operand:DF
0 "register_operand" "=w")
5588 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
5591 [(set_attr "type" "f_cvt")]
5594 (define_insn "extendhfsf2"
5595 [(set (match_operand:SF
0 "register_operand" "=w")
5596 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
5599 [(set_attr "type" "f_cvt")]
5602 (define_insn "extendhfdf2"
5603 [(set (match_operand:DF
0 "register_operand" "=w")
5604 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
5607 [(set_attr "type" "f_cvt")]
5610 (define_insn "truncdfsf2"
5611 [(set (match_operand:SF
0 "register_operand" "=w")
5612 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
5615 [(set_attr "type" "f_cvt")]
5618 (define_insn "truncsfhf2"
5619 [(set (match_operand:HF
0 "register_operand" "=w")
5620 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
5623 [(set_attr "type" "f_cvt")]
5626 (define_insn "truncdfhf2"
5627 [(set (match_operand:HF
0 "register_operand" "=w")
5628 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
5631 [(set_attr "type" "f_cvt")]
5634 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5635 ;; and making r = w more expensive
5637 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
5638 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
5639 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
5642 fcvtz<su>
\t%<s>
0, %<s>
1
5643 fcvtz<su>
\t%<w>
0, %<s>
1"
5644 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5647 ;; Convert HF -> SI or DI
5649 (define_insn "<optab>_trunchf<GPI:mode>
2"
5650 [(set (match_operand:GPI
0 "register_operand" "=r")
5651 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
5653 "fcvtz<su>
\t%<w>
0, %h1"
5654 [(set_attr "type" "f_cvtf2i")]
5657 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5658 ;; input in a fp register and output in a integer register
5660 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
5661 [(set (match_operand:GPI
0 "register_operand" "=r")
5662 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
5664 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
5665 [(set_attr "type" "f_cvtf2i")]
5668 (define_insn "*fix_to_zero_extend<mode>di2"
5669 [(set (match_operand:DI
0 "register_operand" "=r")
5672 (match_operand:GPF
1 "register_operand" "w"))))]
5674 "fcvtzu
\t%w0, %<s>
1"
5675 [(set_attr "type" "f_cvtf2i")]
5678 (define_insn "<optab><fcvt_target><GPF:mode>
2"
5679 [(set (match_operand:GPF
0 "register_operand" "=w,w")
5680 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
5683 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
5684 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
5685 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
5686 (set_attr "arch" "simd,fp")]
5689 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
5690 [(set (match_operand:GPF
0 "register_operand" "=w")
5691 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
5693 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
5694 [(set_attr "type" "f_cvti2f")]
5697 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
5698 ;; midend will arrange for an SImode conversion to HFmode to first go
5699 ;; through DFmode, then to HFmode. But first it will try converting
5700 ;; to DImode then down, which would match our DImode pattern below and
5701 ;; give very poor code-generation. So, we must provide our own emulation
5702 ;; of the mid-end logic.
5704 (define_insn "aarch64_fp16_<optab><mode>hf2"
5705 [(set (match_operand:HF
0 "register_operand" "=w")
5706 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
5708 "<su_optab>cvtf
\t%h0, %<w>
1"
5709 [(set_attr "type" "f_cvti2f")]
5712 (define_expand "<optab>sihf2"
5713 [(set (match_operand:HF
0 "register_operand")
5714 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
5717 if (TARGET_FP_F16INST)
5718 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
5721 rtx convert_target = gen_reg_rtx (DFmode);
5722 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
5723 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
5729 ;; For DImode there is no wide enough floating-point mode that we
5730 ;; can convert through natively (TFmode would work, but requires a library
5731 ;; call). However, we know that any value >=
65504 will be rounded
5732 ;; to infinity on conversion. This is well within the range of SImode, so
5734 ;; Saturate to SImode.
5735 ;; Convert from that to DFmode
5736 ;; Convert from that to HFmode (phew!).
5737 ;; Note that the saturation to SImode requires the SIMD extensions. If
5738 ;; we ever need to provide this pattern where the SIMD extensions are not
5739 ;; available, we would need a different approach.
5741 (define_expand "<optab>dihf2"
5742 [(set (match_operand:HF
0 "register_operand")
5743 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
5744 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
5746 if (TARGET_FP_F16INST)
5747 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
5750 rtx sat_target = gen_reg_rtx (SImode);
5751 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
5752 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
5759 ;; Convert between fixed-point and floating-point (scalar modes)
5761 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
5762 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
5763 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
5764 (match_operand:SI
2 "immediate_operand" "i, i")]
5768 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
5769 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
5770 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
5771 (set_attr "arch" "fp,simd")]
5774 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
5775 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
5776 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
5777 (match_operand:SI
2 "immediate_operand" "i, i")]
5781 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
5782 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
5783 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
5784 (set_attr "arch" "fp,simd")]
5787 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
5788 [(set (match_operand:GPI
0 "register_operand" "=r")
5789 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
5790 (match_operand:SI
2 "immediate_operand" "i")]
5793 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
5794 [(set_attr "type" "f_cvtf2i")]
5797 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
5798 [(set (match_operand:HF
0 "register_operand" "=w")
5799 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
5800 (match_operand:SI
2 "immediate_operand" "i")]
5803 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
5804 [(set_attr "type" "f_cvti2f")]
5807 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
5808 [(set (match_operand:HI
0 "register_operand" "=w")
5809 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
5810 (match_operand:SI
2 "immediate_operand" "i")]
5813 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5814 [(set_attr "type" "neon_fp_to_int_s")]
5817 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
5818 [(set (match_operand:HF
0 "register_operand" "=w")
5819 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
5820 (match_operand:SI
2 "immediate_operand" "i")]
5823 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5824 [(set_attr "type" "neon_int_to_fp_s")]
5827 ;; -------------------------------------------------------------------
5828 ;; Floating-point arithmetic
5829 ;; -------------------------------------------------------------------
5831 (define_insn "add<mode>
3"
5832 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5834 (match_operand:GPF_F16
1 "register_operand" "w")
5835 (match_operand:GPF_F16
2 "register_operand" "w")))]
5837 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
5838 [(set_attr "type" "fadd<stype>")]
5841 (define_insn "sub<mode>
3"
5842 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5844 (match_operand:GPF_F16
1 "register_operand" "w")
5845 (match_operand:GPF_F16
2 "register_operand" "w")))]
5847 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
5848 [(set_attr "type" "fadd<stype>")]
5851 (define_insn "mul<mode>
3"
5852 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5854 (match_operand:GPF_F16
1 "register_operand" "w")
5855 (match_operand:GPF_F16
2 "register_operand" "w")))]
5857 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
5858 [(set_attr "type" "fmul<stype>")]
5861 (define_insn "*fnmul<mode>
3"
5862 [(set (match_operand:GPF
0 "register_operand" "=w")
5864 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
5865 (match_operand:GPF
2 "register_operand" "w")))]
5866 "TARGET_FLOAT && !flag_rounding_math"
5867 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5868 [(set_attr "type" "fmul<s>")]
5871 (define_insn "*fnmul<mode>
3"
5872 [(set (match_operand:GPF
0 "register_operand" "=w")
5874 (match_operand:GPF
1 "register_operand" "w")
5875 (match_operand:GPF
2 "register_operand" "w"))))]
5877 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5878 [(set_attr "type" "fmul<s>")]
5881 (define_expand "div<mode>
3"
5882 [(set (match_operand:GPF_F16
0 "register_operand")
5883 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
5884 (match_operand:GPF_F16
2 "register_operand")))]
5887 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
5890 operands[
1] = force_reg (<MODE>mode, operands[
1]);
5893 (define_insn "*div<mode>
3"
5894 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5895 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
5896 (match_operand:GPF_F16
2 "register_operand" "w")))]
5898 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
5899 [(set_attr "type" "fdiv<stype>")]
5902 (define_insn "neg<mode>
2"
5903 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5904 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5906 "fneg
\\t%<s>
0, %<s>
1"
5907 [(set_attr "type" "ffarith<stype>")]
5910 (define_expand "sqrt<mode>
2"
5911 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5912 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5915 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
5919 (define_insn "*sqrt<mode>
2"
5920 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5921 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5923 "fsqrt
\\t%<s>
0, %<s>
1"
5924 [(set_attr "type" "fsqrt<stype>")]
5927 (define_insn "abs<mode>
2"
5928 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5929 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5931 "fabs
\\t%<s>
0, %<s>
1"
5932 [(set_attr "type" "ffarith<stype>")]
5935 ;; Given that smax/smin do not specify the result when either input is NaN,
5936 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5939 (define_insn "smax<mode>
3"
5940 [(set (match_operand:GPF
0 "register_operand" "=w")
5941 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
5942 (match_operand:GPF
2 "register_operand" "w")))]
5944 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
5945 [(set_attr "type" "f_minmax<s>")]
5948 (define_insn "smin<mode>
3"
5949 [(set (match_operand:GPF
0 "register_operand" "=w")
5950 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
5951 (match_operand:GPF
2 "register_operand" "w")))]
5953 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
5954 [(set_attr "type" "f_minmax<s>")]
5957 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5958 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
5959 ;; which implement the IEEE fmax ()/fmin () functions.
5960 (define_insn "<maxmin_uns><mode>
3"
5961 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5962 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
5963 (match_operand:GPF_F16
2 "register_operand" "w")]
5966 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
5967 [(set_attr "type" "f_minmax<stype>")]
5970 (define_expand "lrint<GPF:mode><GPI:mode>
2"
5971 [(match_operand:GPI
0 "register_operand")
5972 (match_operand:GPF
1 "register_operand")]
5974 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
5975 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
5977 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5978 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
5979 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
5984 ;; For copysign (x, y), we want to generate:
5986 ;; LDR d2, #(
1 <<
63)
5987 ;; BSL v2.8b, [y], [x]
5989 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5990 ;; aarch64_simd_bsldf will select the best suited of these instructions
5991 ;; to generate based on register allocation, and knows how to partially
5992 ;; constant fold based on the values of X and Y, so expand through that.
5994 (define_expand "copysigndf3"
5995 [(match_operand:DF
0 "register_operand")
5996 (match_operand:DF
1 "register_operand")
5997 (match_operand:DF
2 "register_operand")]
5998 "TARGET_FLOAT && TARGET_SIMD"
6000 rtx mask = gen_reg_rtx (DImode);
6001 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U <<
63));
6002 emit_insn (gen_aarch64_simd_bsldf (operands[
0], mask,
6003 operands[
2], operands[
1]));
6008 ;; As above, but we must first get to a
64-bit value if we wish to use
6009 ;; aarch64_simd_bslv2sf.
6011 (define_expand "copysignsf3"
6012 [(match_operand:SF
0 "register_operand")
6013 (match_operand:SF
1 "register_operand")
6014 (match_operand:SF
2 "register_operand")]
6015 "TARGET_FLOAT && TARGET_SIMD"
6017 rtx v_bitmask = gen_reg_rtx (V2SImode);
6019 /* Juggle modes to get us in to a vector mode for BSL. */
6020 rtx op1 = lowpart_subreg (DImode, operands[
1], SFmode);
6021 rtx op2 = lowpart_subreg (V2SFmode, operands[
2], SFmode);
6022 rtx tmp = gen_reg_rtx (V2SFmode);
6023 emit_move_insn (v_bitmask,
6024 aarch64_simd_gen_const_vector_dup (V2SImode,
6025 HOST_WIDE_INT_M1U <<
31));
6026 emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
6027 emit_move_insn (operands[
0], lowpart_subreg (SFmode, tmp, V2SFmode));
6032 ;; For xorsign (x, y), we want to generate:
6035 ;; AND v3.8B, v1.8B, v2.8B
6036 ;; EOR v0.8B, v0.8B, v3.8B
6039 (define_expand "xorsign<mode>
3"
6040 [(match_operand:GPF
0 "register_operand")
6041 (match_operand:GPF
1 "register_operand")
6042 (match_operand:GPF
2 "register_operand")]
6043 "TARGET_FLOAT && TARGET_SIMD"
6046 machine_mode imode = <V_INT_EQUIV>mode;
6047 rtx mask = gen_reg_rtx (imode);
6048 rtx op1x = gen_reg_rtx (imode);
6049 rtx op2x = gen_reg_rtx (imode);
6051 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
6052 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6055 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
6056 lowpart_subreg (imode, operands[
2],
6058 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
6059 lowpart_subreg (imode, operands[
1],
6062 emit_move_insn (operands[
0],
6063 lowpart_subreg (<MODE>mode, op1x, imode));
6068 ;; -------------------------------------------------------------------
6070 ;; -------------------------------------------------------------------
6071 ;; Reload Scalar Floating point modes from constant pool.
6072 ;; The AArch64 port doesn't have __int128 constant move support.
6073 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6074 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
6075 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
6076 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6079 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6080 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
6085 ;; Reload Vector modes from constant pool.
6086 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6087 [(set (match_operand:VALL
0 "register_operand" "=w")
6088 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
6089 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6092 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6093 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
6098 (define_expand "@aarch64_reload_mov<mode>"
6099 [(set (match_operand:TX
0 "register_operand" "=w")
6100 (match_operand:TX
1 "register_operand" "w"))
6101 (clobber (match_operand:DI
2 "register_operand" "=&r"))
6105 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
6106 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
6107 gen_aarch64_movtilow_tilow (op0, op1);
6108 gen_aarch64_movdi_tihigh (operands[
2], op1);
6109 gen_aarch64_movtihigh_di (op0, operands[
2]);
6114 ;; The following secondary reload helpers patterns are invoked
6115 ;; after or during reload as we don't want these patterns to start
6116 ;; kicking in during the combiner.
6118 (define_insn "@aarch64_movdi_<mode>low"
6119 [(set (match_operand:DI
0 "register_operand" "=r")
6120 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6121 (const_int
64) (const_int
0)))]
6122 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6124 [(set_attr "type" "f_mrc")
6125 (set_attr "length" "
4")
6128 (define_insn "@aarch64_movdi_<mode>high"
6129 [(set (match_operand:DI
0 "register_operand" "=r")
6130 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6131 (const_int
64) (const_int
64)))]
6132 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6133 "fmov
\\t%x0, %
1.d[
1]"
6134 [(set_attr "type" "f_mrc")
6135 (set_attr "length" "
4")
6138 (define_insn "@aarch64_mov<mode>high_di"
6139 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
6140 (const_int
64) (const_int
64))
6141 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6142 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6143 "fmov
\\t%
0.d[
1], %x1"
6144 [(set_attr "type" "f_mcr")
6145 (set_attr "length" "
4")
6148 (define_insn "@aarch64_mov<mode>low_di"
6149 [(set (match_operand:TX
0 "register_operand" "=w")
6150 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6151 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6153 [(set_attr "type" "f_mcr")
6154 (set_attr "length" "
4")
6157 (define_insn "aarch64_movtilow_tilow"
6158 [(set (match_operand:TI
0 "register_operand" "=w")
6160 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
6161 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6163 [(set_attr "type" "fmov")
6164 (set_attr "length" "
4")
6167 ;; There is a deliberate reason why the parameters of high and lo_sum's
6168 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6169 ;; and lo_sum's to be used with the labels defining the jump tables in
6172 (define_expand "add_losym"
6173 [(set (match_operand
0 "register_operand" "=r")
6174 (lo_sum (match_operand
1 "register_operand" "r")
6175 (match_operand
2 "aarch64_valid_symref" "S")))]
6178 machine_mode mode = GET_MODE (operands[
0]);
6180 emit_insn ((mode == DImode
6182 : gen_add_losym_si) (operands[
0],
6188 (define_insn "add_losym_<mode>"
6189 [(set (match_operand:P
0 "register_operand" "=r")
6190 (lo_sum:P (match_operand:P
1 "register_operand" "r")
6191 (match_operand
2 "aarch64_valid_symref" "S")))]
6193 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
6194 [(set_attr "type" "alu_imm")]
6197 (define_insn "ldr_got_small_<mode>"
6198 [(set (match_operand:PTR
0 "register_operand" "=r")
6199 (unspec:PTR [(mem:PTR (lo_sum:PTR
6200 (match_operand:PTR
1 "register_operand" "r")
6201 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6202 UNSPEC_GOTSMALLPIC))]
6204 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
6205 [(set_attr "type" "load_<ldst_sz>")]
6208 (define_insn "ldr_got_small_sidi"
6209 [(set (match_operand:DI
0 "register_operand" "=r")
6211 (unspec:SI [(mem:SI (lo_sum:DI
6212 (match_operand:DI
1 "register_operand" "r")
6213 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6214 UNSPEC_GOTSMALLPIC)))]
6216 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
6217 [(set_attr "type" "load_4")]
6220 (define_insn "ldr_got_small_28k_<mode>"
6221 [(set (match_operand:PTR
0 "register_operand" "=r")
6222 (unspec:PTR [(mem:PTR (lo_sum:PTR
6223 (match_operand:PTR
1 "register_operand" "r")
6224 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6225 UNSPEC_GOTSMALLPIC28K))]
6227 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
6228 [(set_attr "type" "load_<ldst_sz>")]
6231 (define_insn "ldr_got_small_28k_sidi"
6232 [(set (match_operand:DI
0 "register_operand" "=r")
6234 (unspec:SI [(mem:SI (lo_sum:DI
6235 (match_operand:DI
1 "register_operand" "r")
6236 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6237 UNSPEC_GOTSMALLPIC28K)))]
6239 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
6240 [(set_attr "type" "load_4")]
6243 (define_insn "ldr_got_tiny"
6244 [(set (match_operand:DI
0 "register_operand" "=r")
6245 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
6246 UNSPEC_GOTTINYPIC))]
6249 [(set_attr "type" "load_8")]
6252 (define_insn "aarch64_load_tp_hard"
6253 [(set (match_operand:DI
0 "register_operand" "=r")
6254 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
6256 "mrs
\\t%
0, tpidr_el0"
6257 [(set_attr "type" "mrs")]
6260 ;; The TLS ABI specifically requires that the compiler does not schedule
6261 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6262 ;; Therefore we treat the stubs as an atomic sequence.
6263 (define_expand "tlsgd_small_<mode>"
6264 [(parallel [(set (match_operand
0 "register_operand" "")
6265 (call (mem:DI (match_dup
2)) (const_int
1)))
6266 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
6267 (clobber (reg:DI LR_REGNUM))])]
6270 operands[
2] = aarch64_tls_get_addr ();
6273 (define_insn "*tlsgd_small_<mode>"
6274 [(set (match_operand
0 "register_operand" "")
6275 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
6276 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6277 (clobber (reg:DI LR_REGNUM))
6280 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
6281 [(set_attr "type" "call")
6282 (set_attr "length" "
16")])
6284 (define_insn "tlsie_small_<mode>"
6285 [(set (match_operand:PTR
0 "register_operand" "=r")
6286 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6287 UNSPEC_GOTSMALLTLS))]
6289 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
6290 [(set_attr "type" "load_4")
6291 (set_attr "length" "
8")]
6294 (define_insn "tlsie_small_sidi"
6295 [(set (match_operand:DI
0 "register_operand" "=r")
6297 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6298 UNSPEC_GOTSMALLTLS)))]
6300 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
6301 [(set_attr "type" "load_4")
6302 (set_attr "length" "
8")]
6305 (define_insn "tlsie_tiny_<mode>"
6306 [(set (match_operand:PTR
0 "register_operand" "=&r")
6307 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
6308 (match_operand:PTR
2 "register_operand" "r")]
6309 UNSPEC_GOTTINYTLS))]
6311 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
6312 [(set_attr "type" "multiple")
6313 (set_attr "length" "
8")]
6316 (define_insn "tlsie_tiny_sidi"
6317 [(set (match_operand:DI
0 "register_operand" "=&r")
6319 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
6320 (match_operand:DI
2 "register_operand" "r")
6322 UNSPEC_GOTTINYTLS)))]
6324 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
6325 [(set_attr "type" "multiple")
6326 (set_attr "length" "
8")]
6329 (define_insn "tlsle12_<mode>"
6330 [(set (match_operand:P
0 "register_operand" "=r")
6331 (unspec:P [(match_operand:P
1 "register_operand" "r")
6332 (match_operand
2 "aarch64_tls_le_symref" "S")]
6335 "add
\\t%<w>
0, %<w>
1, #%L2";
6336 [(set_attr "type" "alu_sreg")
6337 (set_attr "length" "
4")]
6340 (define_insn "tlsle24_<mode>"
6341 [(set (match_operand:P
0 "register_operand" "=r")
6342 (unspec:P [(match_operand:P
1 "register_operand" "r")
6343 (match_operand
2 "aarch64_tls_le_symref" "S")]
6346 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
6347 [(set_attr "type" "multiple")
6348 (set_attr "length" "
8")]
6351 (define_insn "tlsle32_<mode>"
6352 [(set (match_operand:P
0 "register_operand" "=r")
6353 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6356 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6357 [(set_attr "type" "multiple")
6358 (set_attr "length" "
8")]
6361 (define_insn "tlsle48_<mode>"
6362 [(set (match_operand:P
0 "register_operand" "=r")
6363 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6366 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6367 [(set_attr "type" "multiple")
6368 (set_attr "length" "
12")]
6371 (define_expand "tlsdesc_small_<mode>"
6372 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6376 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[
0]));
6378 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
6383 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6385 (define_insn "tlsdesc_small_advsimd_<mode>"
6386 [(set (reg:PTR R0_REGNUM)
6387 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6389 (clobber (reg:DI LR_REGNUM))
6390 (clobber (reg:CC CC_REGNUM))
6391 (clobber (match_scratch:DI
1 "=r"))]
6392 "TARGET_TLS_DESC && !TARGET_SVE"
6393 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6394 [(set_attr "type" "call")
6395 (set_attr "length" "
16")])
6397 ;; For SVE, model tlsdesc calls as clobbering the lower
128 bits of
6398 ;; all vector registers, and clobber all predicate registers, on
6399 ;; top of the usual R0 and LR.
6400 (define_insn "tlsdesc_small_sve_<mode>"
6401 [(set (reg:PTR R0_REGNUM)
6402 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6404 (clobber (reg:DI LR_REGNUM))
6405 (clobber (reg:CC CC_REGNUM))
6406 (clobber_high (reg:TI V0_REGNUM))
6407 (clobber_high (reg:TI V1_REGNUM))
6408 (clobber_high (reg:TI V2_REGNUM))
6409 (clobber_high (reg:TI V3_REGNUM))
6410 (clobber_high (reg:TI V4_REGNUM))
6411 (clobber_high (reg:TI V5_REGNUM))
6412 (clobber_high (reg:TI V6_REGNUM))
6413 (clobber_high (reg:TI V7_REGNUM))
6414 (clobber_high (reg:TI V8_REGNUM))
6415 (clobber_high (reg:TI V9_REGNUM))
6416 (clobber_high (reg:TI V10_REGNUM))
6417 (clobber_high (reg:TI V11_REGNUM))
6418 (clobber_high (reg:TI V12_REGNUM))
6419 (clobber_high (reg:TI V13_REGNUM))
6420 (clobber_high (reg:TI V14_REGNUM))
6421 (clobber_high (reg:TI V15_REGNUM))
6422 (clobber_high (reg:TI V16_REGNUM))
6423 (clobber_high (reg:TI V17_REGNUM))
6424 (clobber_high (reg:TI V18_REGNUM))
6425 (clobber_high (reg:TI V19_REGNUM))
6426 (clobber_high (reg:TI V20_REGNUM))
6427 (clobber_high (reg:TI V21_REGNUM))
6428 (clobber_high (reg:TI V22_REGNUM))
6429 (clobber_high (reg:TI V23_REGNUM))
6430 (clobber_high (reg:TI V24_REGNUM))
6431 (clobber_high (reg:TI V25_REGNUM))
6432 (clobber_high (reg:TI V26_REGNUM))
6433 (clobber_high (reg:TI V27_REGNUM))
6434 (clobber_high (reg:TI V28_REGNUM))
6435 (clobber_high (reg:TI V29_REGNUM))
6436 (clobber_high (reg:TI V30_REGNUM))
6437 (clobber_high (reg:TI V31_REGNUM))
6438 (clobber (reg:VNx2BI P0_REGNUM))
6439 (clobber (reg:VNx2BI P1_REGNUM))
6440 (clobber (reg:VNx2BI P2_REGNUM))
6441 (clobber (reg:VNx2BI P3_REGNUM))
6442 (clobber (reg:VNx2BI P4_REGNUM))
6443 (clobber (reg:VNx2BI P5_REGNUM))
6444 (clobber (reg:VNx2BI P6_REGNUM))
6445 (clobber (reg:VNx2BI P7_REGNUM))
6446 (clobber (reg:VNx2BI P8_REGNUM))
6447 (clobber (reg:VNx2BI P9_REGNUM))
6448 (clobber (reg:VNx2BI P10_REGNUM))
6449 (clobber (reg:VNx2BI P11_REGNUM))
6450 (clobber (reg:VNx2BI P12_REGNUM))
6451 (clobber (reg:VNx2BI P13_REGNUM))
6452 (clobber (reg:VNx2BI P14_REGNUM))
6453 (clobber (reg:VNx2BI P15_REGNUM))
6454 (clobber (match_scratch:DI
1 "=r"))]
6455 "TARGET_TLS_DESC && TARGET_SVE"
6456 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6457 [(set_attr "type" "call")
6458 (set_attr "length" "
16")])
6460 (define_insn "stack_tie"
6461 [(set (mem:BLK (scratch))
6462 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
6463 (match_operand:DI
1 "register_operand" "rk")]
6467 [(set_attr "length" "
0")]
6470 ;; Pointer authentication patterns are always provided. In architecture
6471 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6472 ;; This lets the user write portable software which authenticates pointers
6473 ;; when run on something which implements ARMv8.3-A, and which runs
6474 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6477 ;; Signing/Authenticating R30 using SP as the salt.
6479 (define_insn "<pauth_mnem_prefix>sp"
6480 [(set (reg:DI R30_REGNUM)
6481 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6483 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
6486 ;; Signing/Authenticating X17 using X16 as the salt.
6488 (define_insn "<pauth_mnem_prefix>
1716"
6489 [(set (reg:DI R17_REGNUM)
6490 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6492 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
6495 ;; Stripping the signature in R30.
6497 (define_insn "xpaclri"
6498 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6500 "hint
\t7 // xpaclri"
6503 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6504 ;; all of memory. This blocks insns from being moved across this point.
6506 (define_insn "blockage"
6507 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
6510 [(set_attr "length" "
0")
6511 (set_attr "type" "block")]
6514 (define_insn "probe_stack_range"
6515 [(set (match_operand:DI
0 "register_operand" "=rk")
6516 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
6517 (match_operand:DI
2 "register_operand" "r")]
6518 UNSPECV_PROBE_STACK_RANGE))]
6521 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
6523 [(set_attr "length" "
32")]
6526 ;; This instruction is used to generate the stack clash stack adjustment and
6527 ;; probing loop. We can't change the control flow during prologue and epilogue
6528 ;; code generation. So we must emit a volatile unspec and expand it later on.
6530 (define_insn "@probe_sve_stack_clash_<mode>"
6531 [(set (match_operand:P
0 "register_operand" "=rk")
6532 (unspec_volatile:P [(match_operand:P
1 "register_operand" "
0")
6533 (match_operand:P
2 "register_operand" "r")
6534 (match_operand:P
3 "const_int_operand" "n")
6535 (match_operand:P
4 "aarch64_plus_immediate" "L")]
6536 UNSPECV_PROBE_STACK_RANGE))]
6539 return aarch64_output_probe_sve_stack_clash (operands[
0], operands[
2],
6540 operands[
3], operands[
4]);
6542 [(set_attr "length" "
28")]
6545 ;; Named pattern for expanding thread pointer reference.
6546 (define_expand "get_thread_pointerdi"
6547 [(match_operand:DI
0 "register_operand" "=r")]
6550 rtx tmp = aarch64_load_tp (operands[
0]);
6551 if (tmp != operands[
0])
6552 emit_move_insn (operands[
0], tmp);
6556 ;; Named patterns for stack smashing protection.
6557 (define_expand "stack_protect_set"
6558 [(match_operand
0 "memory_operand")
6559 (match_operand
1 "memory_operand")]
6562 machine_mode mode = GET_MODE (operands[
0]);
6564 emit_insn ((mode == DImode
6565 ? gen_stack_protect_set_di
6566 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
6570 (define_insn "stack_protect_set_<mode>"
6571 [(set (match_operand:PTR
0 "memory_operand" "=m")
6572 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
6574 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
6576 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
6577 [(set_attr "length" "
12")
6578 (set_attr "type" "multiple")])
6580 (define_expand "stack_protect_test"
6581 [(match_operand
0 "memory_operand")
6582 (match_operand
1 "memory_operand")
6587 machine_mode mode = GET_MODE (operands[
0]);
6589 result = gen_reg_rtx(mode);
6591 emit_insn ((mode == DImode
6592 ? gen_stack_protect_test_di
6593 : gen_stack_protect_test_si) (result,
6598 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6599 result, const0_rtx, operands[
2]));
6601 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6602 result, const0_rtx, operands[
2]));
6606 (define_insn "stack_protect_test_<mode>"
6607 [(set (match_operand:PTR
0 "register_operand" "=r")
6608 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
6609 (match_operand:PTR
2 "memory_operand" "m")]
6611 (clobber (match_scratch:PTR
3 "=&r"))]
6613 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
6614 [(set_attr "length" "
12")
6615 (set_attr "type" "multiple")])
6617 ;; Write Floating-point Control Register.
6618 (define_insn "set_fpcr"
6619 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
6622 [(set_attr "type" "mrs")])
6624 ;; Read Floating-point Control Register.
6625 (define_insn "get_fpcr"
6626 [(set (match_operand:SI
0 "register_operand" "=r")
6627 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
6630 [(set_attr "type" "mrs")])
6632 ;; Write Floating-point Status Register.
6633 (define_insn "set_fpsr"
6634 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
6637 [(set_attr "type" "mrs")])
6639 ;; Read Floating-point Status Register.
6640 (define_insn "get_fpsr"
6641 [(set (match_operand:SI
0 "register_operand" "=r")
6642 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
6645 [(set_attr "type" "mrs")])
6648 ;; Define the subtract-one-and-jump insns so loop.c
6649 ;; knows what to generate.
6650 (define_expand "doloop_end"
6651 [(use (match_operand
0 "" "")) ; loop pseudo
6652 (use (match_operand
1 "" ""))] ; label
6653 "optimize >
0 && flag_modulo_sched"
6662 /* Currently SMS relies on the do-loop pattern to recognize loops
6663 where (
1) the control part consists of all insns defining and/or
6664 using a certain 'count' register and (
2) the loop count can be
6665 adjusted by modifying this register prior to the loop.
6666 ??? The possible introduction of a new block to initialize the
6667 new IV can potentially affect branch optimizations. */
6669 if (GET_MODE (operands[
0]) != DImode)
6673 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
6675 cmp = XVECEXP (PATTERN (insn),
0,
0);
6676 cc_reg = SET_DEST (cmp);
6677 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
6678 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
6679 emit_jump_insn (gen_rtx_SET (pc_rtx,
6680 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
6685 ;; Track speculation through conditional branches. We assume that
6686 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
6687 (define_insn "speculation_tracker"
6688 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
6689 (unspec [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand
0)]
6690 UNSPEC_SPECULATION_TRACKER))]
6693 operands[
1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
6694 output_asm_insn ("csel
\\t%
1, %
1, xzr, %m0", operands);
6697 [(set_attr "type" "csel")]
6700 ;; Helper for aarch64.c code.
6701 (define_expand "set_clobber_cc"
6702 [(parallel [(set (match_operand
0)
6704 (clobber (reg:CC CC_REGNUM))])])
6706 ;; Hard speculation barrier.
6707 (define_insn "speculation_barrier"
6708 [(unspec_volatile [(const_int
0)] UNSPECV_SPECULATION_BARRIER)]
6711 [(set_attr "length" "
8")
6712 (set_attr "type" "block")
6713 (set_attr "speculation_barrier" "true")]
6716 ;; Support for __builtin_speculation_safe_value when we have speculation
6717 ;; tracking enabled. Use the speculation tracker to decide whether to
6718 ;; copy operand
1 to the target, or to copy the fail value (operand
2).
6719 (define_expand "@despeculate_copy<ALLI_TI:mode>"
6720 [(set (match_operand:ALLI_TI
0 "register_operand" "=r")
6721 (unspec_volatile:ALLI_TI
6722 [(match_operand:ALLI_TI
1 "register_operand" "r")
6723 (match_operand:ALLI_TI
2 "aarch64_reg_or_zero" "rZ")
6724 (use (reg:DI SPECULATION_TRACKER_REGNUM))
6725 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
6729 if (operands[
2] == const0_rtx)
6732 if (<MODE>mode == TImode)
6733 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
6735 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
6737 emit_insn (gen_despeculate_simple<mode> (operands[
0], operands[
1],
6745 ;; Patterns to match despeculate_copy<mode>. Note that "hint
0x14" is the
6746 ;; encoding for CSDB, but will work in older versions of the assembler.
6747 (define_insn "*despeculate_copy<ALLI:mode>_insn"
6748 [(set (match_operand:ALLI
0 "register_operand" "=r")
6749 (unspec_volatile:ALLI
6750 [(match_operand:ALLI
1 "register_operand" "r")
6751 (match_operand:ALLI
2 "aarch64_reg_or_zero" "rZ")
6752 (use (reg:DI SPECULATION_TRACKER_REGNUM))
6753 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
6756 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
6757 output_asm_insn ("cmp
\\t%
3, #
0\;csel
\\t%<w>
0, %<w>
1, %<w>
2, ne\;hint
\t0x14 // csdb",
6761 [(set_attr "length" "
12")
6762 (set_attr "type" "block")
6763 (set_attr "speculation_barrier" "true")]
6766 ;; Pattern to match despeculate_copyti
6767 (define_insn "*despeculate_copyti_insn"
6768 [(set (match_operand:TI
0 "register_operand" "=r")
6770 [(match_operand:TI
1 "register_operand" "r")
6771 (match_operand:TI
2 "aarch64_reg_or_zero" "rZ")
6772 (use (reg:DI SPECULATION_TRACKER_REGNUM))
6773 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
6776 operands[
3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
6778 ("cmp
\\t%
3, #
0\;csel
\\t%
0, %
1, %
2, ne\;csel
\\t%H0, %H1, %H2, ne\;hint
\t0x14 // csdb",
6782 [(set_attr "length" "
16")
6783 (set_attr "type" "block")
6784 (set_attr "speculation_barrier" "true")]
6787 (define_insn "despeculate_simple<ALLI:mode>"
6788 [(set (match_operand:ALLI
0 "register_operand" "=r")
6789 (unspec_volatile:ALLI
6790 [(match_operand:ALLI
1 "register_operand" "r")
6791 (use (match_operand:ALLI
2 "register_operand" ""))]
6792 UNSPECV_SPECULATION_BARRIER))]
6794 "and
\\t%<w>
0, %<w>
1, %<w>
2\;hint
\t0x14 // csdb"
6795 [(set_attr "type" "block")
6796 (set_attr "length" "
8")
6797 (set_attr "speculation_barrier" "true")]
6800 (define_insn "despeculate_simpleti"
6801 [(set (match_operand:TI
0 "register_operand" "=r")
6803 [(match_operand:TI
1 "register_operand" "r")
6804 (use (match_operand:DI
2 "register_operand" ""))]
6805 UNSPECV_SPECULATION_BARRIER))]
6807 "and
\\t%
0, %
1, %
2\;and
\\t%H0, %H1, %
2\;hint
\t0x14 // csdb"
6808 [(set_attr "type" "block")
6809 (set_attr "length" "
12")
6810 (set_attr "speculation_barrier" "true")]
6814 (include "aarch64-simd.md")
6816 ;; Atomic Operations
6817 (include "atomics.md")
6819 ;; ldp/stp peephole patterns
6820 (include "aarch64-ldpstp.md")
6823 (include "aarch64-sve.md")