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/>.
69 (LAST_SAVED_REGNUM
63)
73 ;; Defined only to make the DWARF description simpler.
94 (define_c_enum "unspec" [
120 UNSPEC_GOTSMALLPIC28K
200 (define_c_enum "unspecv" [
201 UNSPECV_EH_RETURN ; Represent EH_RETURN
202 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
203 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
204 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
205 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
206 UNSPECV_BLOCKAGE ; Represent a blockage
207 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
211 ;; If further include files are added the defintion of MD_INCLUDES
214 (include "constraints.md")
215 (include "predicates.md")
216 (include "iterators.md")
218 ;; -------------------------------------------------------------------
219 ;; Instruction types and attributes
220 ;; -------------------------------------------------------------------
222 ; The "type" attribute is included here from AArch32 backend to be able
223 ; to share pipeline descriptions.
224 (include "../arm/types.md")
226 ;; It is important to set the fp or simd attributes to yes when a pattern
227 ;; alternative uses the FP or SIMD register files, usually signified by use of
228 ;; the 'w' constraint. This will ensure that the alternative will be
229 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
230 ;; architecture extensions. If all the alternatives in a pattern use the
231 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
234 ;; Attribute that specifies whether or not the instruction touches fp
235 ;; registers. When this is set to yes for an alternative, that alternative
236 ;; will be disabled when !TARGET_FLOAT.
237 (define_attr "fp" "no,yes" (const_string "no"))
239 ;; Attribute that specifies whether or not the instruction touches half
240 ;; precision fp registers. When this is set to yes for an alternative,
241 ;; that alternative will be disabled when !TARGET_FP_F16INST.
242 (define_attr "fp16" "no,yes" (const_string "no"))
244 ;; Attribute that specifies whether or not the instruction touches simd
245 ;; registers. When this is set to yes for an alternative, that alternative
246 ;; will be disabled when !TARGET_SIMD.
247 (define_attr "simd" "no,yes" (const_string "no"))
249 ;; Attribute that specifies whether or not the instruction uses SVE.
250 ;; When this is set to yes for an alternative, that alternative
251 ;; will be disabled when !TARGET_SVE.
252 (define_attr "sve" "no,yes" (const_string "no"))
254 (define_attr "length" ""
257 ;; Attribute that controls whether an alternative is enabled or not.
258 ;; Currently it is only used to disable alternatives which touch fp or simd
259 ;; registers when -mgeneral-regs-only is specified.
260 (define_attr "enabled" "no,yes"
262 (and (eq_attr "fp" "yes")
263 (eq (symbol_ref "TARGET_FLOAT") (const_int
0)))
264 (and (eq_attr "simd" "yes")
265 (eq (symbol_ref "TARGET_SIMD") (const_int
0)))
266 (and (eq_attr "fp16" "yes")
267 (eq (symbol_ref "TARGET_FP_F16INST") (const_int
0)))
268 (and (eq_attr "sve" "yes")
269 (eq (symbol_ref "TARGET_SVE") (const_int
0))))
271 ] (const_string "yes")))
273 ;; Attribute that specifies whether we are dealing with a branch to a
274 ;; label that is far away, i.e. further away than the maximum/minimum
275 ;; representable in a signed
21-bits number.
278 (define_attr "far_branch" "" (const_int
0))
280 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
281 ;; no predicated insns.
282 (define_attr "predicated" "yes,no" (const_string "no"))
284 ;; -------------------------------------------------------------------
285 ;; Pipeline descriptions and scheduling
286 ;; -------------------------------------------------------------------
289 (include "aarch64-tune.md")
292 (include "../arm/cortex-a53.md")
293 (include "../arm/cortex-a57.md")
294 (include "../arm/exynos-m1.md")
295 (include "falkor.md")
296 (include "thunderx.md")
297 (include "../arm/xgene1.md")
298 (include "thunderx2t99.md")
300 ;; -------------------------------------------------------------------
301 ;; Jumps and other miscellaneous insns
302 ;; -------------------------------------------------------------------
304 (define_insn "indirect_jump"
305 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
308 [(set_attr "type" "branch")]
312 [(set (pc) (label_ref (match_operand
0 "" "")))]
315 [(set_attr "type" "branch")]
318 (define_expand "cbranch<mode>
4"
319 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
320 [(match_operand:GPI
1 "register_operand" "")
321 (match_operand:GPI
2 "aarch64_plus_operand" "")])
322 (label_ref (match_operand
3 "" ""))
326 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
328 operands[
2] = const0_rtx;
332 (define_expand "cbranch<mode>
4"
333 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
334 [(match_operand:GPF
1 "register_operand" "")
335 (match_operand:GPF
2 "aarch64_fp_compare_operand" "")])
336 (label_ref (match_operand
3 "" ""))
340 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
342 operands[
2] = const0_rtx;
346 (define_expand "cbranchcc4"
347 [(set (pc) (if_then_else
348 (match_operator
0 "aarch64_comparison_operator"
349 [(match_operand
1 "cc_register" "")
350 (match_operand
2 "const0_operand")])
351 (label_ref (match_operand
3 "" ""))
356 (define_insn "ccmp<mode>"
357 [(set (match_operand:CC
1 "cc_register" "")
359 (match_operator
4 "aarch64_comparison_operator"
360 [(match_operand
0 "cc_register" "")
363 (match_operand:GPI
2 "register_operand" "r,r,r")
364 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
365 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
368 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
369 ccmp
\\t%<w>
2, %
3, %k5, %m4
370 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
371 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
374 (define_insn "fccmp<mode>"
375 [(set (match_operand:CCFP
1 "cc_register" "")
377 (match_operator
4 "aarch64_comparison_operator"
378 [(match_operand
0 "cc_register" "")
381 (match_operand:GPF
2 "register_operand" "w")
382 (match_operand:GPF
3 "register_operand" "w"))
383 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
385 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
386 [(set_attr "type" "fccmp<s>")]
389 (define_insn "fccmpe<mode>"
390 [(set (match_operand:CCFPE
1 "cc_register" "")
392 (match_operator
4 "aarch64_comparison_operator"
393 [(match_operand
0 "cc_register" "")
396 (match_operand:GPF
2 "register_operand" "w")
397 (match_operand:GPF
3 "register_operand" "w"))
398 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
400 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
401 [(set_attr "type" "fccmp<s>")]
404 ;; Expansion of signed mod by a power of
2 using CSNEG.
405 ;; For x0 % n where n is a power of
2 produce:
407 ;; and x0, x0, #(n -
1)
408 ;; and x1, x1, #(n -
1)
409 ;; csneg x0, x0, x1, mi
411 (define_expand "mod<mode>
3"
412 [(match_operand:GPI
0 "register_operand" "")
413 (match_operand:GPI
1 "register_operand" "")
414 (match_operand:GPI
2 "const_int_operand" "")]
417 HOST_WIDE_INT val = INTVAL (operands[
2]);
420 || exact_log2 (val) <=
0
421 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
424 rtx mask = GEN_INT (val -
1);
426 /* In the special case of x0 %
2 we can do the even shorter:
432 rtx masked = gen_reg_rtx (<MODE>mode);
433 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
434 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
435 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
436 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
440 rtx neg_op = gen_reg_rtx (<MODE>mode);
441 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
443 /* Extract the condition register and mode. */
444 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
445 rtx cc_reg = SET_DEST (cmp);
446 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
448 rtx masked_pos = gen_reg_rtx (<MODE>mode);
449 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
451 rtx masked_neg = gen_reg_rtx (<MODE>mode);
452 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
454 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
455 masked_neg, masked_pos));
460 (define_insn "condjump"
461 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
462 [(match_operand
1 "cc_register" "") (const_int
0)])
463 (label_ref (match_operand
2 "" ""))
467 if (get_attr_length (insn) ==
8)
468 return aarch64_gen_far_branch (operands,
2, "Lbcond", "b%M0
\\t");
472 [(set_attr "type" "branch")
474 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
475 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
478 (set (attr "far_branch")
479 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
480 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
485 ;; For a
24-bit immediate CST we can optimize the compare for equality
486 ;; and branch sequence from:
488 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
492 ;; sub x0, x1, #(CST &
0xfff000)
493 ;; subs x0, x0, #(CST &
0x000fff)
495 (define_insn_and_split "*compare_condjump<mode>"
496 [(set (pc) (if_then_else (EQL
497 (match_operand:GPI
0 "register_operand" "r")
498 (match_operand:GPI
1 "aarch64_imm24" "n"))
499 (label_ref:P (match_operand
2 "" ""))
501 "!aarch64_move_imm (INTVAL (operands[
1]), <MODE>mode)
502 && !aarch64_plus_operand (operands[
1], <MODE>mode)
503 && !reload_completed"
508 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
509 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
510 rtx tmp = gen_reg_rtx (<MODE>mode);
511 emit_insn (gen_add<mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
512 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
513 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
514 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
515 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
520 (define_expand "casesi"
521 [(match_operand:SI
0 "register_operand" "") ; Index
522 (match_operand:SI
1 "const_int_operand" "") ; Lower bound
523 (match_operand:SI
2 "const_int_operand" "") ; Total range
524 (match_operand:DI
3 "" "") ; Table label
525 (match_operand:DI
4 "" "")] ; Out of range label
528 if (operands[
1] != const0_rtx)
530 rtx reg = gen_reg_rtx (SImode);
532 /* Canonical RTL says that if you have:
536 then this should be emitted as:
540 The use of trunc_int_for_mode ensures that the resulting
541 constant can be represented in SImode, this is important
542 for the corner case where operand[
1] is INT_MIN. */
544 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
546 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
547 (operands[
1], SImode))
548 operands[
1] = force_reg (SImode, operands[
1]);
549 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
553 if (!aarch64_plus_operand (operands[
2], SImode))
554 operands[
2] = force_reg (SImode, operands[
2]);
555 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
557 operands[
0], operands[
2], operands[
4]));
559 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
560 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
0],
566 (define_insn "casesi_dispatch"
569 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
570 (match_operand:SI
1 "register_operand" "r")]
572 (clobber (reg:CC CC_REGNUM))
573 (clobber (match_scratch:DI
3 "=r"))
574 (clobber (match_scratch:DI
4 "=r"))
575 (use (label_ref (match_operand
2 "" "")))])]
578 return aarch64_output_casesi (operands);
580 [(set_attr "length" "
16")
581 (set_attr "type" "branch")]
585 [(unspec[(const_int
0)] UNSPEC_NOP)]
588 [(set_attr "type" "no_insn")]
591 (define_insn "prefetch"
592 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
593 (match_operand:QI
1 "const_int_operand" "")
594 (match_operand:QI
2 "const_int_operand" ""))]
597 const char * pftype[
2][
4] =
599 {"prfm
\\tPLDL1STRM, %
0",
600 "prfm
\\tPLDL3KEEP, %
0",
601 "prfm
\\tPLDL2KEEP, %
0",
602 "prfm
\\tPLDL1KEEP, %
0"},
603 {"prfm
\\tPSTL1STRM, %
0",
604 "prfm
\\tPSTL3KEEP, %
0",
605 "prfm
\\tPSTL2KEEP, %
0",
606 "prfm
\\tPSTL1KEEP, %
0"},
609 int locality = INTVAL (operands[
2]);
611 gcc_assert (IN_RANGE (locality,
0,
3));
613 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
614 the address into a DImode MEM so that aarch64_print_operand knows
616 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
617 return pftype[INTVAL(operands[
1])][locality];
619 [(set_attr "type" "load_4")]
623 [(trap_if (const_int
1) (const_int
8))]
626 [(set_attr "type" "trap")])
628 (define_expand "prologue"
629 [(clobber (const_int
0))]
632 aarch64_expand_prologue ();
637 (define_expand "epilogue"
638 [(clobber (const_int
0))]
641 aarch64_expand_epilogue (false);
646 (define_expand "sibcall_epilogue"
647 [(clobber (const_int
0))]
650 aarch64_expand_epilogue (true);
655 (define_insn "*do_return"
659 if (aarch64_return_address_signing_enabled ()
661 && !crtl->calls_eh_return)
666 [(set_attr "type" "branch")]
669 (define_expand "return"
671 "aarch64_use_return_insn_p ()"
675 (define_insn "simple_return"
679 [(set_attr "type" "branch")]
682 (define_insn "*cb<optab><mode>
1"
683 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
685 (label_ref (match_operand
1 "" ""))
689 if (get_attr_length (insn) ==
8)
690 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
692 return "<cbz>
\\t%<w>
0, %l1";
694 [(set_attr "type" "branch")
696 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
697 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
700 (set (attr "far_branch")
701 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
702 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
707 (define_insn "*tb<optab><mode>
1"
708 [(set (pc) (if_then_else
709 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
712 "aarch64_simd_shift_imm_<mode>" "n"))
714 (label_ref (match_operand
2 "" ""))
716 (clobber (reg:CC CC_REGNUM))]
719 if (get_attr_length (insn) ==
8)
721 if (get_attr_far_branch (insn) ==
1)
722 return aarch64_gen_far_branch (operands,
2, "Ltb",
723 "<inv_tb>
\\t%<w>
0, %
1, ");
726 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
727 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
731 return "<tbz>
\t%<w>
0, %
1, %l2";
733 [(set_attr "type" "branch")
735 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
736 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
739 (set (attr "far_branch")
740 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
741 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
747 (define_insn "*cb<optab><mode>
1"
748 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
750 (label_ref (match_operand
1 "" ""))
752 (clobber (reg:CC CC_REGNUM))]
755 if (get_attr_length (insn) ==
8)
757 if (get_attr_far_branch (insn) ==
1)
758 return aarch64_gen_far_branch (operands,
1, "Ltb",
759 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
763 uint64_t val = ((uint64_t)
1)
764 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
765 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
766 output_asm_insn (buf, operands);
767 return "<bcond>
\t%l1";
771 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
773 [(set_attr "type" "branch")
775 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
776 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
779 (set (attr "far_branch")
780 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
781 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
786 ;; -------------------------------------------------------------------
787 ;; Subroutine calls and sibcalls
788 ;; -------------------------------------------------------------------
790 (define_expand "call"
791 [(parallel [(call (match_operand
0 "memory_operand" "")
792 (match_operand
1 "general_operand" ""))
793 (use (match_operand
2 "" ""))
794 (clobber (reg:DI LR_REGNUM))])]
798 aarch64_expand_call (NULL_RTX, operands[
0], false);
803 (define_insn "*call_insn"
804 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
805 (match_operand
1 "" ""))
806 (clobber (reg:DI LR_REGNUM))]
811 [(set_attr "type" "call, call")]
814 (define_expand "call_value"
815 [(parallel [(set (match_operand
0 "" "")
816 (call (match_operand
1 "memory_operand" "")
817 (match_operand
2 "general_operand" "")))
818 (use (match_operand
3 "" ""))
819 (clobber (reg:DI LR_REGNUM))])]
823 aarch64_expand_call (operands[
0], operands[
1], false);
828 (define_insn "*call_value_insn"
829 [(set (match_operand
0 "" "")
830 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
831 (match_operand
2 "" "")))
832 (clobber (reg:DI LR_REGNUM))]
837 [(set_attr "type" "call, call")]
840 (define_expand "sibcall"
841 [(parallel [(call (match_operand
0 "memory_operand" "")
842 (match_operand
1 "general_operand" ""))
844 (use (match_operand
2 "" ""))])]
847 aarch64_expand_call (NULL_RTX, operands[
0], true);
852 (define_expand "sibcall_value"
853 [(parallel [(set (match_operand
0 "" "")
854 (call (match_operand
1 "memory_operand" "")
855 (match_operand
2 "general_operand" "")))
857 (use (match_operand
3 "" ""))])]
860 aarch64_expand_call (operands[
0], operands[
1], true);
865 (define_insn "*sibcall_insn"
866 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
867 (match_operand
1 "" ""))
869 "SIBLING_CALL_P (insn)"
873 [(set_attr "type" "branch, branch")]
876 (define_insn "*sibcall_value_insn"
877 [(set (match_operand
0 "" "")
879 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
880 (match_operand
2 "" "")))
882 "SIBLING_CALL_P (insn)"
886 [(set_attr "type" "branch, branch")]
889 ;; Call subroutine returning any type.
891 (define_expand "untyped_call"
892 [(parallel [(call (match_operand
0 "")
895 (match_operand
2 "")])]
900 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL));
902 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
904 rtx set = XVECEXP (operands[
2],
0, i);
905 emit_move_insn (SET_DEST (set), SET_SRC (set));
908 /* The optimizer does not know that the call sets the function value
909 registers we stored in the result block. We avoid problems by
910 claiming that all hard registers are used and clobbered at this
912 emit_insn (gen_blockage ());
916 ;; -------------------------------------------------------------------
918 ;; -------------------------------------------------------------------
920 (define_expand "mov<mode>"
921 [(set (match_operand:SHORT
0 "nonimmediate_operand" "")
922 (match_operand:SHORT
1 "general_operand" ""))]
925 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
926 operands[
1] = force_reg (<MODE>mode, operands[
1]);
928 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
930 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
936 (define_insn "*mov<mode>_aarch64"
937 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
938 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
939 "(register_operand (operands[
0], <MODE>mode)
940 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
942 switch (which_alternative)
945 return "mov
\t%w0, %w1";
947 return "mov
\t%w0, %
1";
949 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
952 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
954 return "ldr<size>
\t%w0, %
1";
956 return "ldr
\t%<size>
0, %
1";
958 return "str<size>
\t%w1, %
0";
960 return "str
\t%<size>
1, %
0";
962 return "umov
\t%w0, %
1.<v>[
0]";
964 return "dup
\t%
0.<Vallxd>, %w1";
966 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
971 ;; The "mov_imm" type for CNT is just a placeholder.
972 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
973 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
974 (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes")
975 (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")]
978 (define_expand "mov<mode>"
979 [(set (match_operand:GPI
0 "nonimmediate_operand" "")
980 (match_operand:GPI
1 "general_operand" ""))]
983 if (MEM_P (operands[
0]) && CONST_INT_P (operands[
1])
984 && <MODE>mode == DImode
985 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
988 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
989 operands[
1] = force_reg (<MODE>mode, operands[
1]);
991 /* FIXME: RR we still need to fix up what we are doing with
992 symbol_refs and other types of constants. */
993 if (CONSTANT_P (operands[
1])
994 && !CONST_INT_P (operands[
1]))
996 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1002 (define_insn_and_split "*movsi_aarch64"
1003 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1004 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1005 "(register_operand (operands[
0], SImode)
1006 || aarch64_reg_or_zero (operands[
1], SImode))"
1013 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1023 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1024 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1025 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1028 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1031 ;; The "mov_imm" type for CNT is just a placeholder.
1032 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1033 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1034 (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1035 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1036 (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1039 (define_insn_and_split "*movdi_aarch64"
1040 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1041 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1042 "(register_operand (operands[
0], DImode)
1043 || aarch64_reg_or_zero (operands[
1], DImode))"
1051 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1061 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1062 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1063 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1066 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1069 ;; The "mov_imm" type for CNTD is just a placeholder.
1070 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1071 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1073 (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1074 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1075 (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1078 (define_insn "insv_imm<mode>"
1079 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1081 (match_operand:GPI
1 "const_int_operand" "n"))
1082 (match_operand:GPI
2 "const_int_operand" "n"))]
1083 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1084 && UINTVAL (operands[
1]) %
16 ==
0"
1085 "movk
\\t%<w>
0, %X2, lsl %
1"
1086 [(set_attr "type" "mov_imm")]
1089 (define_expand "movti"
1090 [(set (match_operand:TI
0 "nonimmediate_operand" "")
1091 (match_operand:TI
1 "general_operand" ""))]
1094 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1095 operands[
1] = force_reg (TImode, operands[
1]);
1097 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1099 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1100 gen_lowpart (DImode, operands[
1]));
1101 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1107 (define_insn "*movti_aarch64"
1108 [(set (match_operand:TI
0
1109 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1111 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1112 "(register_operand (operands[
0], TImode)
1113 || aarch64_reg_or_zero (operands[
1], TImode))"
1118 mov
\\t%
0.16b, %
1.16b
1124 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1125 load_16,store_16,store_16,\
1127 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1128 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1129 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1132 ;; Split a TImode register-register or register-immediate move into
1133 ;; its component DImode pieces, taking care to handle overlapping
1134 ;; source and dest registers.
1136 [(set (match_operand:TI
0 "register_operand" "")
1137 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1138 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1141 aarch64_split_128bit_move (operands[
0], operands[
1]);
1145 (define_expand "mov<mode>"
1146 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand" "")
1147 (match_operand:GPF_TF_F16
1 "general_operand" ""))]
1152 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1156 if (GET_CODE (operands[
0]) == MEM
1157 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1158 && aarch64_float_const_zero_rtx_p (operands[
1])))
1159 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1163 (define_insn "*movhf_aarch64"
1164 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r")
1165 (match_operand:HF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1166 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1167 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1172 mov
\\t%
0.h[
0], %
1.h[
0]
1174 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1180 [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
1181 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1182 (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
1183 (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")]
1186 (define_insn "*movsf_aarch64"
1187 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1188 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1189 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1190 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1197 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1204 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1205 f_loads,f_stores,load_4,store_4,mov_reg,\
1207 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1210 (define_insn "*movdf_aarch64"
1211 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1212 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1213 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1214 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1221 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1228 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1229 f_loadd,f_stored,load_8,store_8,mov_reg,\
1231 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1235 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1236 (match_operand:GPF_HF
1 "general_operand"))]
1237 "can_create_pseudo_p ()
1238 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1239 && !aarch64_float_const_representable_p (operands[
1])
1240 && aarch64_float_const_rtx_p (operands[
1])"
1243 unsigned HOST_WIDE_INT ival;
1244 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1247 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1248 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1249 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1254 (define_insn "*movtf_aarch64"
1255 [(set (match_operand:TF
0
1256 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1258 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1259 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1260 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1262 mov
\\t%
0.16b, %
1.16b
1273 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1274 f_loadd,f_stored,load_16,store_16,store_16")
1275 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1276 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1280 [(set (match_operand:TF
0 "register_operand" "")
1281 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1282 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1285 aarch64_split_128bit_move (operands[
0], operands[
1]);
1292 ;;
2 is size of move in bytes
1295 (define_expand "movmemdi"
1296 [(match_operand:BLK
0 "memory_operand")
1297 (match_operand:BLK
1 "memory_operand")
1298 (match_operand:DI
2 "immediate_operand")
1299 (match_operand:DI
3 "immediate_operand")]
1302 if (aarch64_expand_movmem (operands))
1308 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1309 ;; fairly lax checking on the second memory operation.
1310 (define_insn "load_pairsi"
1311 [(set (match_operand:SI
0 "register_operand" "=r,w")
1312 (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1313 (set (match_operand:SI
2 "register_operand" "=r,w")
1314 (match_operand:SI
3 "memory_operand" "m,m"))]
1315 "rtx_equal_p (XEXP (operands[
3],
0),
1316 plus_constant (Pmode,
1317 XEXP (operands[
1],
0),
1318 GET_MODE_SIZE (SImode)))"
1322 [(set_attr "type" "load_8,neon_load1_2reg")
1323 (set_attr "fp" "*,yes")]
1326 (define_insn "load_pairdi"
1327 [(set (match_operand:DI
0 "register_operand" "=r,w")
1328 (match_operand:DI
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1329 (set (match_operand:DI
2 "register_operand" "=r,w")
1330 (match_operand:DI
3 "memory_operand" "m,m"))]
1331 "rtx_equal_p (XEXP (operands[
3],
0),
1332 plus_constant (Pmode,
1333 XEXP (operands[
1],
0),
1334 GET_MODE_SIZE (DImode)))"
1338 [(set_attr "type" "load_16,neon_load1_2reg")
1339 (set_attr "fp" "*,yes")]
1343 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1344 ;; fairly lax checking on the second memory operation.
1345 (define_insn "store_pairsi"
1346 [(set (match_operand:SI
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1347 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ,w"))
1348 (set (match_operand:SI
2 "memory_operand" "=m,m")
1349 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ,w"))]
1350 "rtx_equal_p (XEXP (operands[
2],
0),
1351 plus_constant (Pmode,
1352 XEXP (operands[
0],
0),
1353 GET_MODE_SIZE (SImode)))"
1357 [(set_attr "type" "store_8,neon_store1_2reg")
1358 (set_attr "fp" "*,yes")]
1361 (define_insn "store_pairdi"
1362 [(set (match_operand:DI
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1363 (match_operand:DI
1 "aarch64_reg_or_zero" "rZ,w"))
1364 (set (match_operand:DI
2 "memory_operand" "=m,m")
1365 (match_operand:DI
3 "aarch64_reg_or_zero" "rZ,w"))]
1366 "rtx_equal_p (XEXP (operands[
2],
0),
1367 plus_constant (Pmode,
1368 XEXP (operands[
0],
0),
1369 GET_MODE_SIZE (DImode)))"
1373 [(set_attr "type" "store_16,neon_store1_2reg")
1374 (set_attr "fp" "*,yes")]
1377 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1378 ;; fairly lax checking on the second memory operation.
1379 (define_insn "load_pairsf"
1380 [(set (match_operand:SF
0 "register_operand" "=w,r")
1381 (match_operand:SF
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1382 (set (match_operand:SF
2 "register_operand" "=w,r")
1383 (match_operand:SF
3 "memory_operand" "m,m"))]
1384 "rtx_equal_p (XEXP (operands[
3],
0),
1385 plus_constant (Pmode,
1386 XEXP (operands[
1],
0),
1387 GET_MODE_SIZE (SFmode)))"
1391 [(set_attr "type" "neon_load1_2reg,load_8")
1392 (set_attr "fp" "yes,*")]
1395 (define_insn "load_pairdf"
1396 [(set (match_operand:DF
0 "register_operand" "=w,r")
1397 (match_operand:DF
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1398 (set (match_operand:DF
2 "register_operand" "=w,r")
1399 (match_operand:DF
3 "memory_operand" "m,m"))]
1400 "rtx_equal_p (XEXP (operands[
3],
0),
1401 plus_constant (Pmode,
1402 XEXP (operands[
1],
0),
1403 GET_MODE_SIZE (DFmode)))"
1407 [(set_attr "type" "neon_load1_2reg,load_16")
1408 (set_attr "fp" "yes,*")]
1411 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1412 ;; fairly lax checking on the second memory operation.
1413 (define_insn "store_pairsf"
1414 [(set (match_operand:SF
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1415 (match_operand:SF
1 "aarch64_reg_or_fp_zero" "w,rY"))
1416 (set (match_operand:SF
2 "memory_operand" "=m,m")
1417 (match_operand:SF
3 "aarch64_reg_or_fp_zero" "w,rY"))]
1418 "rtx_equal_p (XEXP (operands[
2],
0),
1419 plus_constant (Pmode,
1420 XEXP (operands[
0],
0),
1421 GET_MODE_SIZE (SFmode)))"
1425 [(set_attr "type" "neon_store1_2reg,store_8")
1426 (set_attr "fp" "yes,*")]
1429 (define_insn "store_pairdf"
1430 [(set (match_operand:DF
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1431 (match_operand:DF
1 "aarch64_reg_or_fp_zero" "w,rY"))
1432 (set (match_operand:DF
2 "memory_operand" "=m,m")
1433 (match_operand:DF
3 "aarch64_reg_or_fp_zero" "w,rY"))]
1434 "rtx_equal_p (XEXP (operands[
2],
0),
1435 plus_constant (Pmode,
1436 XEXP (operands[
0],
0),
1437 GET_MODE_SIZE (DFmode)))"
1441 [(set_attr "type" "neon_store1_2reg,store_16")
1442 (set_attr "fp" "yes,*")]
1445 ;; Load pair with post-index writeback. This is primarily used in function
1447 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1449 [(set (match_operand:P
0 "register_operand" "=k")
1450 (plus:P (match_operand:P
1 "register_operand" "
0")
1451 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1452 (set (match_operand:GPI
2 "register_operand" "=r")
1453 (mem:GPI (match_dup
1)))
1454 (set (match_operand:GPI
3 "register_operand" "=r")
1455 (mem:GPI (plus:P (match_dup
1)
1456 (match_operand:P
5 "const_int_operand" "n"))))])]
1457 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1458 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1459 [(set_attr "type" "load_<ldpstp_sz>")]
1462 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1464 [(set (match_operand:P
0 "register_operand" "=k")
1465 (plus:P (match_operand:P
1 "register_operand" "
0")
1466 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1467 (set (match_operand:GPF
2 "register_operand" "=w")
1468 (mem:GPF (match_dup
1)))
1469 (set (match_operand:GPF
3 "register_operand" "=w")
1470 (mem:GPF (plus:P (match_dup
1)
1471 (match_operand:P
5 "const_int_operand" "n"))))])]
1472 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1473 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1474 [(set_attr "type" "neon_load1_2reg")]
1477 ;; Store pair with pre-index writeback. This is primarily used in function
1479 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1481 [(set (match_operand:P
0 "register_operand" "=&k")
1482 (plus:P (match_operand:P
1 "register_operand" "
0")
1483 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1484 (set (mem:GPI (plus:P (match_dup
0)
1486 (match_operand:GPI
2 "register_operand" "r"))
1487 (set (mem:GPI (plus:P (match_dup
0)
1488 (match_operand:P
5 "const_int_operand" "n")))
1489 (match_operand:GPI
3 "register_operand" "r"))])]
1490 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1491 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1492 [(set_attr "type" "store_<ldpstp_sz>")]
1495 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1497 [(set (match_operand:P
0 "register_operand" "=&k")
1498 (plus:P (match_operand:P
1 "register_operand" "
0")
1499 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1500 (set (mem:GPF (plus:P (match_dup
0)
1502 (match_operand:GPF
2 "register_operand" "w"))
1503 (set (mem:GPF (plus:P (match_dup
0)
1504 (match_operand:P
5 "const_int_operand" "n")))
1505 (match_operand:GPF
3 "register_operand" "w"))])]
1506 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1507 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1508 [(set_attr "type" "neon_store1_2reg<q>")]
1511 ;; -------------------------------------------------------------------
1512 ;; Sign/Zero extension
1513 ;; -------------------------------------------------------------------
1515 (define_expand "<optab>sidi2"
1516 [(set (match_operand:DI
0 "register_operand")
1517 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1521 (define_insn "*extendsidi2_aarch64"
1522 [(set (match_operand:DI
0 "register_operand" "=r,r")
1523 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1528 [(set_attr "type" "extend,load_4")]
1531 (define_insn "*load_pair_extendsidi2_aarch64"
1532 [(set (match_operand:DI
0 "register_operand" "=r")
1533 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1534 (set (match_operand:DI
2 "register_operand" "=r")
1535 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1536 "rtx_equal_p (XEXP (operands[
3],
0),
1537 plus_constant (Pmode,
1538 XEXP (operands[
1],
0),
1539 GET_MODE_SIZE (SImode)))"
1540 "ldpsw
\\t%
0, %
2, %
1"
1541 [(set_attr "type" "load_8")]
1544 (define_insn "*zero_extendsidi2_aarch64"
1545 [(set (match_operand:DI
0 "register_operand" "=r,r")
1546 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1551 [(set_attr "type" "extend,load_4")]
1554 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1555 [(set (match_operand:DI
0 "register_operand" "=r")
1556 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1557 (set (match_operand:DI
2 "register_operand" "=r")
1558 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1559 "rtx_equal_p (XEXP (operands[
3],
0),
1560 plus_constant (Pmode,
1561 XEXP (operands[
1],
0),
1562 GET_MODE_SIZE (SImode)))"
1563 "ldp
\\t%w0, %w2, %
1"
1564 [(set_attr "type" "load_8")]
1567 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1568 [(set (match_operand:GPI
0 "register_operand")
1569 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1573 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1574 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1575 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1578 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1579 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1580 [(set_attr "type" "extend,load_4")]
1583 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1584 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1585 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1588 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1589 ldr<SHORT:size>
\t%w0, %
1
1590 ldr
\t%<SHORT:size>
0, %
1"
1591 [(set_attr "type" "logic_imm,load_4,load_4")]
1594 (define_expand "<optab>qihi2"
1595 [(set (match_operand:HI
0 "register_operand")
1596 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1600 (define_insn "*extendqihi2_aarch64"
1601 [(set (match_operand:HI
0 "register_operand" "=r,r")
1602 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1607 [(set_attr "type" "extend,load_4")]
1610 (define_insn "*zero_extendqihi2_aarch64"
1611 [(set (match_operand:HI
0 "register_operand" "=r,r")
1612 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1617 [(set_attr "type" "logic_imm,load_4")]
1620 ;; -------------------------------------------------------------------
1621 ;; Simple arithmetic
1622 ;; -------------------------------------------------------------------
1624 (define_expand "add<mode>
3"
1626 (match_operand:GPI
0 "register_operand" "")
1627 (plus:GPI (match_operand:GPI
1 "register_operand" "")
1628 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "")))]
1631 /* If operands[
1] is a subreg extract the inner RTX. */
1632 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1634 /* If the constant is too large for a single instruction and isn't frame
1635 based, split off the immediate so it is available for CSE. */
1636 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1637 && can_create_pseudo_p ()
1639 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1640 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1641 /* Expand polynomial additions now if the destination is the stack
1642 pointer, since we don't want to use that as a temporary. */
1643 else if (operands[
0] == stack_pointer_rtx
1644 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1646 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1647 operands[
2], NULL_RTX, NULL_RTX);
1652 (define_insn "*add<mode>
3_aarch64"
1654 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,rk")
1656 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,rk")
1657 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1660 add
\\t%<w>
0, %<w>
1, %
2
1661 add
\\t%<w>
0, %<w>
1, %<w>
2
1662 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1663 sub
\\t%<w>
0, %<w>
1, #%n2
1665 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);"
1666 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1667 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1668 (set_attr "simd" "*,*,yes,*,*,*")]
1671 ;; zero_extend version of above
1672 (define_insn "*addsi3_aarch64_uxtw"
1674 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1676 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1677 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1682 sub
\\t%w0, %w1, #%n2
1684 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1687 ;; If there's a free register, and we can load the constant with a
1688 ;; single instruction, do so. This has a chance to improve scheduling.
1690 [(match_scratch:GPI
3 "r")
1691 (set (match_operand:GPI
0 "register_operand")
1693 (match_operand:GPI
1 "register_operand")
1694 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1695 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1696 [(set (match_dup
3) (match_dup
2))
1697 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1701 [(match_scratch:SI
3 "r")
1702 (set (match_operand:DI
0 "register_operand")
1705 (match_operand:SI
1 "register_operand")
1706 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1707 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1708 [(set (match_dup
3) (match_dup
2))
1709 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1712 ;; After peephole2 has had a chance to run, split any remaining long
1713 ;; additions into two add immediates.
1715 [(set (match_operand:GPI
0 "register_operand")
1717 (match_operand:GPI
1 "register_operand")
1718 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1719 "epilogue_completed"
1720 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1721 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1723 HOST_WIDE_INT i = INTVAL (operands[
2]);
1724 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1725 operands[
3] = GEN_INT (i - s);
1726 operands[
4] = GEN_INT (s);
1730 ;; Match addition of polynomial offsets that require one temporary, for which
1731 ;; we can use the early-clobbered destination register. This is a separate
1732 ;; pattern so that the early clobber doesn't affect register allocation
1733 ;; for other forms of addition. However, we still need to provide an
1734 ;; all-register alternative, in case the offset goes out of range after
1735 ;; elimination. For completeness we might as well provide all GPR-based
1736 ;; alternatives from the main pattern.
1738 ;; We don't have a pattern for additions requiring two temporaries since at
1739 ;; present LRA doesn't allow new scratches to be added during elimination.
1740 ;; Such offsets should be rare anyway.
1742 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1743 ;; here would go away. We could just handle all polynomial constants in
1745 (define_insn_and_split "*add<mode>
3_poly_1"
1747 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,&r")
1749 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1750 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1751 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1753 add
\\t%<w>
0, %<w>
1, %
2
1754 add
\\t%<w>
0, %<w>
1, %<w>
2
1755 sub
\\t%<w>
0, %<w>
1, #%n2
1757 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);
1759 "&& epilogue_completed
1760 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1761 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1764 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1765 operands[
2], operands[
0], NULL_RTX);
1768 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1769 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1773 [(set (match_operand:DI
0 "register_operand")
1776 (match_operand:SI
1 "register_operand")
1777 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1778 "epilogue_completed"
1779 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1780 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1782 HOST_WIDE_INT i = INTVAL (operands[
2]);
1783 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1784 operands[
3] = GEN_INT (i - s);
1785 operands[
4] = GEN_INT (s);
1786 operands[
5] = gen_lowpart (SImode, operands[
0]);
1790 (define_expand "addti3"
1791 [(set (match_operand:TI
0 "register_operand" "")
1792 (plus:TI (match_operand:TI
1 "register_operand" "")
1793 (match_operand:TI
2 "register_operand" "")))]
1796 rtx low = gen_reg_rtx (DImode);
1797 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[
1]),
1798 gen_lowpart (DImode, operands[
2])));
1800 rtx high = gen_reg_rtx (DImode);
1801 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[
1]),
1802 gen_highpart (DImode, operands[
2])));
1804 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
1805 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
1809 (define_insn "add<mode>
3_compare0"
1810 [(set (reg:CC_NZ CC_REGNUM)
1812 (plus:GPI (match_operand:GPI
1 "register_operand" "%r,r,r")
1813 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
1815 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
1816 (plus:GPI (match_dup
1) (match_dup
2)))]
1819 adds
\\t%<w>
0, %<w>
1, %<w>
2
1820 adds
\\t%<w>
0, %<w>
1, %
2
1821 subs
\\t%<w>
0, %<w>
1, #%n2"
1822 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1825 ;; zero_extend version of above
1826 (define_insn "*addsi3_compare0_uxtw"
1827 [(set (reg:CC_NZ CC_REGNUM)
1829 (plus:SI (match_operand:SI
1 "register_operand" "%r,r,r")
1830 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
1832 (set (match_operand:DI
0 "register_operand" "=r,r,r")
1833 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
1836 adds
\\t%w0, %w1, %w2
1838 subs
\\t%w0, %w1, #%n2"
1839 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1842 (define_insn "*add<mode>
3_compareC_cconly_imm"
1843 [(set (reg:CC_C CC_REGNUM)
1846 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
1847 (match_operand:<DWI>
2 "const_scalar_int_operand" ""))
1851 (match_operand:GPI
1 "aarch64_plus_immediate" "I,J")))))]
1852 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
2],
1853 <MODE>mode, operands[
1])"
1857 [(set_attr "type" "alus_imm")]
1860 (define_insn "*add<mode>
3_compareC_cconly"
1861 [(set (reg:CC_C CC_REGNUM)
1864 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
1865 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
1866 (zero_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
1868 "cmn
\\t%<w>
0, %<w>
1"
1869 [(set_attr "type" "alus_sreg")]
1872 (define_insn "*add<mode>
3_compareC_imm"
1873 [(set (reg:CC_C CC_REGNUM)
1876 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r,r"))
1877 (match_operand:<DWI>
3 "const_scalar_int_operand" ""))
1881 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))
1882 (set (match_operand:GPI
0 "register_operand" "=r,r")
1883 (plus:GPI (match_dup
1) (match_dup
2)))]
1884 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
3],
1885 <MODE>mode, operands[
2])"
1887 adds
\\t%<w>
0, %<w>
1, %
2
1888 subs
\\t%<w>
0, %<w>
1, #%n2"
1889 [(set_attr "type" "alus_imm")]
1892 (define_insn "add<mode>
3_compareC"
1893 [(set (reg:CC_C CC_REGNUM)
1896 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
1897 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
1899 (plus:GPI (match_dup
1) (match_dup
2)))))
1900 (set (match_operand:GPI
0 "register_operand" "=r")
1901 (plus:GPI (match_dup
1) (match_dup
2)))]
1903 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
1904 [(set_attr "type" "alus_sreg")]
1907 (define_insn "*adds_shift_imm_<mode>"
1908 [(set (reg:CC_NZ CC_REGNUM)
1910 (plus:GPI (ASHIFT:GPI
1911 (match_operand:GPI
1 "register_operand" "r")
1912 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
1913 (match_operand:GPI
3 "register_operand" "r"))
1915 (set (match_operand:GPI
0 "register_operand" "=r")
1916 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
1919 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
1920 [(set_attr "type" "alus_shift_imm")]
1923 (define_insn "*subs_shift_imm_<mode>"
1924 [(set (reg:CC_NZ CC_REGNUM)
1926 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
1928 (match_operand:GPI
2 "register_operand" "r")
1929 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
1931 (set (match_operand:GPI
0 "register_operand" "=r")
1932 (minus:GPI (match_dup
1)
1933 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
1935 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
1936 [(set_attr "type" "alus_shift_imm")]
1939 (define_insn "*adds_mul_imm_<mode>"
1940 [(set (reg:CC_NZ CC_REGNUM)
1943 (match_operand:GPI
1 "register_operand" "r")
1944 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
1945 (match_operand:GPI
3 "register_operand" "r"))
1947 (set (match_operand:GPI
0 "register_operand" "=r")
1948 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
1951 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
1952 [(set_attr "type" "alus_shift_imm")]
1955 (define_insn "*subs_mul_imm_<mode>"
1956 [(set (reg:CC_NZ CC_REGNUM)
1958 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
1960 (match_operand:GPI
2 "register_operand" "r")
1961 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
1963 (set (match_operand:GPI
0 "register_operand" "=r")
1964 (minus:GPI (match_dup
1)
1965 (mult:GPI (match_dup
2) (match_dup
3))))]
1967 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
1968 [(set_attr "type" "alus_shift_imm")]
1971 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1972 [(set (reg:CC_NZ CC_REGNUM)
1975 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
1976 (match_operand:GPI
2 "register_operand" "r"))
1978 (set (match_operand:GPI
0 "register_operand" "=r")
1979 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
1981 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
1982 [(set_attr "type" "alus_ext")]
1985 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1986 [(set (reg:CC_NZ CC_REGNUM)
1988 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
1990 (match_operand:ALLX
2 "register_operand" "r")))
1992 (set (match_operand:GPI
0 "register_operand" "=r")
1993 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
1995 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
1996 [(set_attr "type" "alus_ext")]
1999 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2000 [(set (reg:CC_NZ CC_REGNUM)
2002 (plus:GPI (ashift:GPI
2004 (match_operand:ALLX
1 "register_operand" "r"))
2005 (match_operand
2 "aarch64_imm3" "Ui3"))
2006 (match_operand:GPI
3 "register_operand" "r"))
2008 (set (match_operand:GPI
0 "register_operand" "=rk")
2009 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2013 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2014 [(set_attr "type" "alus_ext")]
2017 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2018 [(set (reg:CC_NZ CC_REGNUM)
2020 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2023 (match_operand:ALLX
2 "register_operand" "r"))
2024 (match_operand
3 "aarch64_imm3" "Ui3")))
2026 (set (match_operand:GPI
0 "register_operand" "=rk")
2027 (minus:GPI (match_dup
1)
2028 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2031 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2032 [(set_attr "type" "alus_ext")]
2035 (define_insn "*adds_<optab><mode>_multp2"
2036 [(set (reg:CC_NZ CC_REGNUM)
2038 (plus:GPI (ANY_EXTRACT:GPI
2039 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2040 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2041 (match_operand
3 "const_int_operand" "n")
2043 (match_operand:GPI
4 "register_operand" "r"))
2045 (set (match_operand:GPI
0 "register_operand" "=r")
2046 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2050 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2051 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2052 [(set_attr "type" "alus_ext")]
2055 (define_insn "*subs_<optab><mode>_multp2"
2056 [(set (reg:CC_NZ CC_REGNUM)
2058 (minus:GPI (match_operand:GPI
4 "register_operand" "r")
2060 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2061 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2062 (match_operand
3 "const_int_operand" "n")
2065 (set (match_operand:GPI
0 "register_operand" "=r")
2066 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2067 (mult:GPI (match_dup
1) (match_dup
2))
2070 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2071 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2072 [(set_attr "type" "alus_ext")]
2075 (define_insn "*add<mode>
3nr_compare0"
2076 [(set (reg:CC_NZ CC_REGNUM)
2078 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2079 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2086 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2089 (define_insn "aarch64_sub<mode>_compare0"
2090 [(set (reg:CC_NZ CC_REGNUM)
2092 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2093 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2096 "cmp
\\t%<w>
0, %<w>
1"
2097 [(set_attr "type" "alus_sreg")]
2100 (define_insn "*compare_neg<mode>"
2101 [(set (reg:CC_Z CC_REGNUM)
2103 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2104 (match_operand:GPI
1 "register_operand" "r")))]
2106 "cmn
\\t%<w>
1, %<w>
0"
2107 [(set_attr "type" "alus_sreg")]
2110 (define_insn "*add_<shift>_<mode>"
2111 [(set (match_operand:GPI
0 "register_operand" "=r")
2112 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2113 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2114 (match_operand:GPI
3 "register_operand" "r")))]
2116 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2117 [(set_attr "type" "alu_shift_imm")]
2120 ;; zero_extend version of above
2121 (define_insn "*add_<shift>_si_uxtw"
2122 [(set (match_operand:DI
0 "register_operand" "=r")
2124 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2125 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2126 (match_operand:SI
3 "register_operand" "r"))))]
2128 "add
\\t%w0, %w3, %w1, <shift> %
2"
2129 [(set_attr "type" "alu_shift_imm")]
2132 (define_insn "*add_mul_imm_<mode>"
2133 [(set (match_operand:GPI
0 "register_operand" "=r")
2134 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2135 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2136 (match_operand:GPI
3 "register_operand" "r")))]
2138 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2139 [(set_attr "type" "alu_shift_imm")]
2142 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2143 [(set (match_operand:GPI
0 "register_operand" "=rk")
2144 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2145 (match_operand:GPI
2 "register_operand" "r")))]
2147 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2148 [(set_attr "type" "alu_ext")]
2151 ;; zero_extend version of above
2152 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2153 [(set (match_operand:DI
0 "register_operand" "=rk")
2155 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2156 (match_operand:GPI
2 "register_operand" "r"))))]
2158 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2159 [(set_attr "type" "alu_ext")]
2162 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2163 [(set (match_operand:GPI
0 "register_operand" "=rk")
2164 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2165 (match_operand:ALLX
1 "register_operand" "r"))
2166 (match_operand
2 "aarch64_imm3" "Ui3"))
2167 (match_operand:GPI
3 "register_operand" "r")))]
2169 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2170 [(set_attr "type" "alu_ext")]
2173 ;; zero_extend version of above
2174 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2175 [(set (match_operand:DI
0 "register_operand" "=rk")
2177 (plus:SI (ashift:SI (ANY_EXTEND:SI
2178 (match_operand:SHORT
1 "register_operand" "r"))
2179 (match_operand
2 "aarch64_imm3" "Ui3"))
2180 (match_operand:SI
3 "register_operand" "r"))))]
2182 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2183 [(set_attr "type" "alu_ext")]
2186 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2187 [(set (match_operand:GPI
0 "register_operand" "=rk")
2188 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2189 (match_operand:ALLX
1 "register_operand" "r"))
2190 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2191 (match_operand:GPI
3 "register_operand" "r")))]
2193 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2194 [(set_attr "type" "alu_ext")]
2197 ;; zero_extend version of above
2198 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2199 [(set (match_operand:DI
0 "register_operand" "=rk")
2200 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2201 (match_operand:SHORT
1 "register_operand" "r"))
2202 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2203 (match_operand:SI
3 "register_operand" "r"))))]
2205 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2206 [(set_attr "type" "alu_ext")]
2209 (define_insn "*add_<optab><mode>_multp2"
2210 [(set (match_operand:GPI
0 "register_operand" "=rk")
2211 (plus:GPI (ANY_EXTRACT:GPI
2212 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2213 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2214 (match_operand
3 "const_int_operand" "n")
2216 (match_operand:GPI
4 "register_operand" "r")))]
2217 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2218 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2219 [(set_attr "type" "alu_ext")]
2222 ;; zero_extend version of above
2223 (define_insn "*add_<optab>si_multp2_uxtw"
2224 [(set (match_operand:DI
0 "register_operand" "=rk")
2226 (plus:SI (ANY_EXTRACT:SI
2227 (mult:SI (match_operand:SI
1 "register_operand" "r")
2228 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2229 (match_operand
3 "const_int_operand" "n")
2231 (match_operand:SI
4 "register_operand" "r"))))]
2232 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2233 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2234 [(set_attr "type" "alu_ext")]
2237 (define_expand "add<mode>
3_carryin"
2238 [(set (match_operand:GPI
0 "register_operand")
2241 (ne:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2242 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2243 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2248 ;; Note that add with carry with two zero inputs is matched by cset,
2249 ;; and that add with carry with one zero input is matched by cinc.
2251 (define_insn "*add<mode>
3_carryin"
2252 [(set (match_operand:GPI
0 "register_operand" "=r")
2255 (match_operand:GPI
3 "aarch64_carry_operation" "")
2256 (match_operand:GPI
1 "register_operand" "r"))
2257 (match_operand:GPI
2 "register_operand" "r")))]
2259 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2260 [(set_attr "type" "adc_reg")]
2263 ;; zero_extend version of above
2264 (define_insn "*addsi3_carryin_uxtw"
2265 [(set (match_operand:DI
0 "register_operand" "=r")
2269 (match_operand:SI
3 "aarch64_carry_operation" "")
2270 (match_operand:SI
1 "register_operand" "r"))
2271 (match_operand:SI
2 "register_operand" "r"))))]
2273 "adc
\\t%w0, %w1, %w2"
2274 [(set_attr "type" "adc_reg")]
2277 (define_insn "*add_uxt<mode>_shift2"
2278 [(set (match_operand:GPI
0 "register_operand" "=rk")
2280 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2281 (match_operand
2 "aarch64_imm3" "Ui3"))
2282 (match_operand
3 "const_int_operand" "n"))
2283 (match_operand:GPI
4 "register_operand" "r")))]
2284 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2286 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2287 INTVAL (operands[
3])));
2288 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2289 [(set_attr "type" "alu_ext")]
2292 ;; zero_extend version of above
2293 (define_insn "*add_uxtsi_shift2_uxtw"
2294 [(set (match_operand:DI
0 "register_operand" "=rk")
2297 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2298 (match_operand
2 "aarch64_imm3" "Ui3"))
2299 (match_operand
3 "const_int_operand" "n"))
2300 (match_operand:SI
4 "register_operand" "r"))))]
2301 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2303 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2304 INTVAL (operands[
3])));
2305 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2306 [(set_attr "type" "alu_ext")]
2309 (define_insn "*add_uxt<mode>_multp2"
2310 [(set (match_operand:GPI
0 "register_operand" "=rk")
2312 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2313 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2314 (match_operand
3 "const_int_operand" "n"))
2315 (match_operand:GPI
4 "register_operand" "r")))]
2316 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2318 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2319 INTVAL (operands[
3])));
2320 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2321 [(set_attr "type" "alu_ext")]
2324 ;; zero_extend version of above
2325 (define_insn "*add_uxtsi_multp2_uxtw"
2326 [(set (match_operand:DI
0 "register_operand" "=rk")
2329 (mult:SI (match_operand:SI
1 "register_operand" "r")
2330 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2331 (match_operand
3 "const_int_operand" "n"))
2332 (match_operand:SI
4 "register_operand" "r"))))]
2333 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2335 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2336 INTVAL (operands[
3])));
2337 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2338 [(set_attr "type" "alu_ext")]
2341 (define_insn "subsi3"
2342 [(set (match_operand:SI
0 "register_operand" "=rk")
2343 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2344 (match_operand:SI
2 "register_operand" "r")))]
2346 "sub
\\t%w0, %w1, %w2"
2347 [(set_attr "type" "alu_sreg")]
2350 ;; zero_extend version of above
2351 (define_insn "*subsi3_uxtw"
2352 [(set (match_operand:DI
0 "register_operand" "=rk")
2354 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2355 (match_operand:SI
2 "register_operand" "r"))))]
2357 "sub
\\t%w0, %w1, %w2"
2358 [(set_attr "type" "alu_sreg")]
2361 (define_insn "subdi3"
2362 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2363 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2364 (match_operand:DI
2 "register_operand" "r,w")))]
2368 sub
\\t%d0, %d1, %d2"
2369 [(set_attr "type" "alu_sreg, neon_sub")
2370 (set_attr "simd" "*,yes")]
2373 (define_expand "subti3"
2374 [(set (match_operand:TI
0 "register_operand" "")
2375 (minus:TI (match_operand:TI
1 "register_operand" "")
2376 (match_operand:TI
2 "register_operand" "")))]
2379 rtx low = gen_reg_rtx (DImode);
2380 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[
1]),
2381 gen_lowpart (DImode, operands[
2])));
2383 rtx high = gen_reg_rtx (DImode);
2384 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[
1]),
2385 gen_highpart (DImode, operands[
2])));
2387 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
2388 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
2392 (define_insn "*sub<mode>
3_compare0"
2393 [(set (reg:CC_NZ CC_REGNUM)
2394 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2395 (match_operand:GPI
2 "register_operand" "r"))
2397 (set (match_operand:GPI
0 "register_operand" "=r")
2398 (minus:GPI (match_dup
1) (match_dup
2)))]
2400 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2401 [(set_attr "type" "alus_sreg")]
2404 ;; zero_extend version of above
2405 (define_insn "*subsi3_compare0_uxtw"
2406 [(set (reg:CC_NZ CC_REGNUM)
2407 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "r")
2408 (match_operand:SI
2 "register_operand" "r"))
2410 (set (match_operand:DI
0 "register_operand" "=r")
2411 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
2413 "subs
\\t%w0, %w1, %w2"
2414 [(set_attr "type" "alus_sreg")]
2417 (define_insn "sub<mode>
3_compare1"
2418 [(set (reg:CC CC_REGNUM)
2420 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2421 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
2422 (set (match_operand:GPI
0 "register_operand" "=r")
2423 (minus:GPI (match_dup
1) (match_dup
2)))]
2425 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2426 [(set_attr "type" "alus_sreg")]
2429 (define_insn "sub<mode>
3_compare1_imm"
2430 [(set (reg:CC CC_REGNUM)
2432 (match_operand:GPI
1 "register_operand" "r")
2433 (match_operand:GPI
3 "const_int_operand" "n")))
2434 (set (match_operand:GPI
0 "register_operand" "=r")
2435 (plus:GPI (match_dup
1)
2436 (match_operand:GPI
2 "aarch64_sub_immediate" "J")))]
2437 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2438 "subs
\\t%<w>
0, %<w>
1, #%n2"
2439 [(set_attr "type" "alus_sreg")]
2443 [(set (match_operand:GPI
0 "register_operand")
2444 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
2445 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2446 (set (reg:CC CC_REGNUM)
2450 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2451 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
2454 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2460 ;; Same as the above peephole but with the compare and minus in
2461 ;; swapped order. The restriction on overlap between operand
0
2462 ;; and operands
1 and
2 doesn't apply here.
2464 [(set (reg:CC CC_REGNUM)
2466 (match_operand:GPI
1 "aarch64_reg_or_zero")
2467 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2468 (set (match_operand:GPI
0 "register_operand")
2469 (minus:GPI (match_dup
1)
2474 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2481 [(set (match_operand:GPI
0 "register_operand")
2482 (plus:GPI (match_operand:GPI
1 "register_operand")
2483 (match_operand:GPI
2 "aarch64_sub_immediate")))
2484 (set (reg:CC CC_REGNUM)
2487 (match_operand:GPI
3 "const_int_operand")))]
2488 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2489 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2492 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2493 operands[
2], operands[
3]));
2498 ;; Same as the above peephole but with the compare and minus in
2499 ;; swapped order. The restriction on overlap between operand
0
2500 ;; and operands
1 doesn't apply here.
2502 [(set (reg:CC CC_REGNUM)
2504 (match_operand:GPI
1 "register_operand")
2505 (match_operand:GPI
3 "const_int_operand")))
2506 (set (match_operand:GPI
0 "register_operand")
2507 (plus:GPI (match_dup
1)
2508 (match_operand:GPI
2 "aarch64_sub_immediate")))]
2509 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2512 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2513 operands[
2], operands[
3]));
2518 (define_insn "*sub_<shift>_<mode>"
2519 [(set (match_operand:GPI
0 "register_operand" "=r")
2520 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2522 (match_operand:GPI
1 "register_operand" "r")
2523 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
2525 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2526 [(set_attr "type" "alu_shift_imm")]
2529 ;; zero_extend version of above
2530 (define_insn "*sub_<shift>_si_uxtw"
2531 [(set (match_operand:DI
0 "register_operand" "=r")
2533 (minus:SI (match_operand:SI
3 "register_operand" "r")
2535 (match_operand:SI
1 "register_operand" "r")
2536 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
2538 "sub
\\t%w0, %w3, %w1, <shift> %
2"
2539 [(set_attr "type" "alu_shift_imm")]
2542 (define_insn "*sub_mul_imm_<mode>"
2543 [(set (match_operand:GPI
0 "register_operand" "=r")
2544 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2546 (match_operand:GPI
1 "register_operand" "r")
2547 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
2549 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2550 [(set_attr "type" "alu_shift_imm")]
2553 ;; zero_extend version of above
2554 (define_insn "*sub_mul_imm_si_uxtw"
2555 [(set (match_operand:DI
0 "register_operand" "=r")
2557 (minus:SI (match_operand:SI
3 "register_operand" "r")
2559 (match_operand:SI
1 "register_operand" "r")
2560 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
2562 "sub
\\t%w0, %w3, %w1, lsl %p2"
2563 [(set_attr "type" "alu_shift_imm")]
2566 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2567 [(set (match_operand:GPI
0 "register_operand" "=rk")
2568 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2570 (match_operand:ALLX
2 "register_operand" "r"))))]
2572 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2573 [(set_attr "type" "alu_ext")]
2576 ;; zero_extend version of above
2577 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2578 [(set (match_operand:DI
0 "register_operand" "=rk")
2580 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2582 (match_operand:SHORT
2 "register_operand" "r")))))]
2584 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2585 [(set_attr "type" "alu_ext")]
2588 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2589 [(set (match_operand:GPI
0 "register_operand" "=rk")
2590 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2591 (ashift:GPI (ANY_EXTEND:GPI
2592 (match_operand:ALLX
2 "register_operand" "r"))
2593 (match_operand
3 "aarch64_imm3" "Ui3"))))]
2595 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2596 [(set_attr "type" "alu_ext")]
2599 ;; zero_extend version of above
2600 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2601 [(set (match_operand:DI
0 "register_operand" "=rk")
2603 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2604 (ashift:SI (ANY_EXTEND:SI
2605 (match_operand:SHORT
2 "register_operand" "r"))
2606 (match_operand
3 "aarch64_imm3" "Ui3")))))]
2608 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
2609 [(set_attr "type" "alu_ext")]
2612 (define_insn "*sub_<optab><mode>_multp2"
2613 [(set (match_operand:GPI
0 "register_operand" "=rk")
2614 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2616 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2617 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2618 (match_operand
3 "const_int_operand" "n")
2620 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2621 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2622 [(set_attr "type" "alu_ext")]
2625 ;; zero_extend version of above
2626 (define_insn "*sub_<optab>si_multp2_uxtw"
2627 [(set (match_operand:DI
0 "register_operand" "=rk")
2629 (minus:SI (match_operand:SI
4 "register_operand" "rk")
2631 (mult:SI (match_operand:SI
1 "register_operand" "r")
2632 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2633 (match_operand
3 "const_int_operand" "n")
2635 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2636 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2637 [(set_attr "type" "alu_ext")]
2640 ;; The hardware description is op1 + ~op2 + C.
2641 ;; = op1 + (-op2 +
1) + (
1 - !C)
2642 ;; = op1 - op2 -
1 +
1 - !C
2643 ;; = op1 - op2 - !C.
2644 ;; We describe the latter.
2646 (define_insn "*sub<mode>
3_carryin0"
2647 [(set (match_operand:GPI
0 "register_operand" "=r")
2649 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2650 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
2652 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
2653 [(set_attr "type" "adc_reg")]
2656 ;; zero_extend version of the above
2657 (define_insn "*subsi3_carryin_uxtw"
2658 [(set (match_operand:DI
0 "register_operand" "=r")
2661 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
2662 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
2664 "sbc
\\t%w0, %w1, wzr"
2665 [(set_attr "type" "adc_reg")]
2668 (define_expand "sub<mode>
3_carryin"
2669 [(set (match_operand:GPI
0 "register_operand")
2672 (match_operand:GPI
1 "aarch64_reg_or_zero")
2673 (match_operand:GPI
2 "register_operand"))
2674 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
2679 (define_insn "*sub<mode>
3_carryin"
2680 [(set (match_operand:GPI
0 "register_operand" "=r")
2683 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2684 (match_operand:GPI
2 "register_operand" "r"))
2685 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
2688 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
2689 [(set_attr "type" "adc_reg")]
2692 ;; zero_extend version of the above
2693 (define_insn "*subsi3_carryin_uxtw"
2694 [(set (match_operand:DI
0 "register_operand" "=r")
2698 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
2699 (match_operand:SI
2 "register_operand" "r"))
2700 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
2703 "sbc
\\t%w0, %w1, %w2"
2704 [(set_attr "type" "adc_reg")]
2707 (define_insn "*sub<mode>
3_carryin_alt"
2708 [(set (match_operand:GPI
0 "register_operand" "=r")
2711 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2712 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
2713 (match_operand:GPI
2 "register_operand" "r")))]
2715 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
2716 [(set_attr "type" "adc_reg")]
2719 ;; zero_extend version of the above
2720 (define_insn "*subsi3_carryin_alt_uxtw"
2721 [(set (match_operand:DI
0 "register_operand" "=r")
2725 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
2726 (match_operand:SI
3 "aarch64_borrow_operation" ""))
2727 (match_operand:SI
2 "register_operand" "r"))))]
2729 "sbc
\\t%w0, %w1, %w2"
2730 [(set_attr "type" "adc_reg")]
2733 (define_insn "*sub_uxt<mode>_shift2"
2734 [(set (match_operand:GPI
0 "register_operand" "=rk")
2735 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2737 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2738 (match_operand
2 "aarch64_imm3" "Ui3"))
2739 (match_operand
3 "const_int_operand" "n"))))]
2740 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
2742 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2743 INTVAL (operands[
3])));
2744 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2745 [(set_attr "type" "alu_ext")]
2748 ;; zero_extend version of above
2749 (define_insn "*sub_uxtsi_shift2_uxtw"
2750 [(set (match_operand:DI
0 "register_operand" "=rk")
2752 (minus:SI (match_operand:SI
4 "register_operand" "rk")
2754 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2755 (match_operand
2 "aarch64_imm3" "Ui3"))
2756 (match_operand
3 "const_int_operand" "n")))))]
2757 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
2759 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2760 INTVAL (operands[
3])));
2761 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2762 [(set_attr "type" "alu_ext")]
2765 (define_insn "*sub_uxt<mode>_multp2"
2766 [(set (match_operand:GPI
0 "register_operand" "=rk")
2767 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2769 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2770 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2771 (match_operand
3 "const_int_operand" "n"))))]
2772 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
2774 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2775 INTVAL (operands[
3])));
2776 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2777 [(set_attr "type" "alu_ext")]
2780 ;; zero_extend version of above
2781 (define_insn "*sub_uxtsi_multp2_uxtw"
2782 [(set (match_operand:DI
0 "register_operand" "=rk")
2784 (minus:SI (match_operand:SI
4 "register_operand" "rk")
2786 (mult:SI (match_operand:SI
1 "register_operand" "r")
2787 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2788 (match_operand
3 "const_int_operand" "n")))))]
2789 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
2791 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2792 INTVAL (operands[
3])));
2793 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2794 [(set_attr "type" "alu_ext")]
2797 (define_expand "abs<mode>
2"
2798 [(match_operand:GPI
0 "register_operand" "")
2799 (match_operand:GPI
1 "register_operand" "")]
2802 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
2803 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2804 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
2809 (define_insn "neg<mode>
2"
2810 [(set (match_operand:GPI
0 "register_operand" "=r,w")
2811 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
2815 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
2816 [(set_attr "type" "alu_sreg, neon_neg<q>")
2817 (set_attr "simd" "*,yes")]
2820 ;; zero_extend version of above
2821 (define_insn "*negsi2_uxtw"
2822 [(set (match_operand:DI
0 "register_operand" "=r")
2823 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
2826 [(set_attr "type" "alu_sreg")]
2829 (define_insn "*ngc<mode>"
2830 [(set (match_operand:GPI
0 "register_operand" "=r")
2832 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
2833 (match_operand:GPI
1 "register_operand" "r")))]
2835 "ngc
\\t%<w>
0, %<w>
1"
2836 [(set_attr "type" "adc_reg")]
2839 (define_insn "*ngcsi_uxtw"
2840 [(set (match_operand:DI
0 "register_operand" "=r")
2843 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
2844 (match_operand:SI
1 "register_operand" "r"))))]
2847 [(set_attr "type" "adc_reg")]
2850 (define_insn "neg<mode>
2_compare0"
2851 [(set (reg:CC_NZ CC_REGNUM)
2852 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
2854 (set (match_operand:GPI
0 "register_operand" "=r")
2855 (neg:GPI (match_dup
1)))]
2857 "negs
\\t%<w>
0, %<w>
1"
2858 [(set_attr "type" "alus_sreg")]
2861 ;; zero_extend version of above
2862 (define_insn "*negsi2_compare0_uxtw"
2863 [(set (reg:CC_NZ CC_REGNUM)
2864 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
2866 (set (match_operand:DI
0 "register_operand" "=r")
2867 (zero_extend:DI (neg:SI (match_dup
1))))]
2870 [(set_attr "type" "alus_sreg")]
2873 (define_insn "*neg_<shift><mode>
3_compare0"
2874 [(set (reg:CC_NZ CC_REGNUM)
2876 (neg:GPI (ASHIFT:GPI
2877 (match_operand:GPI
1 "register_operand" "r")
2878 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
2880 (set (match_operand:GPI
0 "register_operand" "=r")
2881 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
2883 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
2884 [(set_attr "type" "alus_shift_imm")]
2887 (define_insn "*neg_<shift>_<mode>
2"
2888 [(set (match_operand:GPI
0 "register_operand" "=r")
2889 (neg:GPI (ASHIFT:GPI
2890 (match_operand:GPI
1 "register_operand" "r")
2891 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
2893 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
2894 [(set_attr "type" "alu_shift_imm")]
2897 ;; zero_extend version of above
2898 (define_insn "*neg_<shift>_si2_uxtw"
2899 [(set (match_operand:DI
0 "register_operand" "=r")
2902 (match_operand:SI
1 "register_operand" "r")
2903 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
2905 "neg
\\t%w0, %w1, <shift> %
2"
2906 [(set_attr "type" "alu_shift_imm")]
2909 (define_insn "*neg_mul_imm_<mode>
2"
2910 [(set (match_operand:GPI
0 "register_operand" "=r")
2912 (match_operand:GPI
1 "register_operand" "r")
2913 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
2915 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
2916 [(set_attr "type" "alu_shift_imm")]
2919 ;; zero_extend version of above
2920 (define_insn "*neg_mul_imm_si2_uxtw"
2921 [(set (match_operand:DI
0 "register_operand" "=r")
2924 (match_operand:SI
1 "register_operand" "r")
2925 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
2927 "neg
\\t%w0, %w1, lsl %p2"
2928 [(set_attr "type" "alu_shift_imm")]
2931 (define_insn "mul<mode>
3"
2932 [(set (match_operand:GPI
0 "register_operand" "=r")
2933 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2934 (match_operand:GPI
2 "register_operand" "r")))]
2936 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
2937 [(set_attr "type" "mul")]
2940 ;; zero_extend version of above
2941 (define_insn "*mulsi3_uxtw"
2942 [(set (match_operand:DI
0 "register_operand" "=r")
2944 (mult:SI (match_operand:SI
1 "register_operand" "r")
2945 (match_operand:SI
2 "register_operand" "r"))))]
2947 "mul
\\t%w0, %w1, %w2"
2948 [(set_attr "type" "mul")]
2951 (define_insn "madd<mode>"
2952 [(set (match_operand:GPI
0 "register_operand" "=r")
2953 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2954 (match_operand:GPI
2 "register_operand" "r"))
2955 (match_operand:GPI
3 "register_operand" "r")))]
2957 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
2958 [(set_attr "type" "mla")]
2961 ;; zero_extend version of above
2962 (define_insn "*maddsi_uxtw"
2963 [(set (match_operand:DI
0 "register_operand" "=r")
2965 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
2966 (match_operand:SI
2 "register_operand" "r"))
2967 (match_operand:SI
3 "register_operand" "r"))))]
2969 "madd
\\t%w0, %w1, %w2, %w3"
2970 [(set_attr "type" "mla")]
2973 (define_insn "*msub<mode>"
2974 [(set (match_operand:GPI
0 "register_operand" "=r")
2975 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2976 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2977 (match_operand:GPI
2 "register_operand" "r"))))]
2980 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
2981 [(set_attr "type" "mla")]
2984 ;; zero_extend version of above
2985 (define_insn "*msubsi_uxtw"
2986 [(set (match_operand:DI
0 "register_operand" "=r")
2988 (minus:SI (match_operand:SI
3 "register_operand" "r")
2989 (mult:SI (match_operand:SI
1 "register_operand" "r")
2990 (match_operand:SI
2 "register_operand" "r")))))]
2993 "msub
\\t%w0, %w1, %w2, %w3"
2994 [(set_attr "type" "mla")]
2997 (define_insn "*mul<mode>_neg"
2998 [(set (match_operand:GPI
0 "register_operand" "=r")
2999 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3000 (match_operand:GPI
2 "register_operand" "r")))]
3003 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3004 [(set_attr "type" "mul")]
3007 ;; zero_extend version of above
3008 (define_insn "*mulsi_neg_uxtw"
3009 [(set (match_operand:DI
0 "register_operand" "=r")
3011 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3012 (match_operand:SI
2 "register_operand" "r"))))]
3015 "mneg
\\t%w0, %w1, %w2"
3016 [(set_attr "type" "mul")]
3019 (define_insn "<su_optab>mulsidi3"
3020 [(set (match_operand:DI
0 "register_operand" "=r")
3021 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3022 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3024 "<su>mull
\\t%
0, %w1, %w2"
3025 [(set_attr "type" "<su>mull")]
3028 (define_insn "<su_optab>maddsidi4"
3029 [(set (match_operand:DI
0 "register_operand" "=r")
3031 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3032 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3033 (match_operand:DI
3 "register_operand" "r")))]
3035 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3036 [(set_attr "type" "<su>mlal")]
3039 (define_insn "<su_optab>msubsidi4"
3040 [(set (match_operand:DI
0 "register_operand" "=r")
3042 (match_operand:DI
3 "register_operand" "r")
3043 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3045 (match_operand:SI
2 "register_operand" "r")))))]
3047 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3048 [(set_attr "type" "<su>mlal")]
3051 (define_insn "*<su_optab>mulsidi_neg"
3052 [(set (match_operand:DI
0 "register_operand" "=r")
3054 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3055 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3057 "<su>mnegl
\\t%
0, %w1, %w2"
3058 [(set_attr "type" "<su>mull")]
3061 (define_expand "<su_optab>mulditi3"
3062 [(set (match_operand:TI
0 "register_operand")
3063 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3064 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3067 rtx low = gen_reg_rtx (DImode);
3068 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3070 rtx high = gen_reg_rtx (DImode);
3071 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3073 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3074 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3078 ;; The default expansion of multi3 using umuldi3_highpart will perform
3079 ;; the additions in an order that fails to combine into two madd insns.
3080 (define_expand "multi3"
3081 [(set (match_operand:TI
0 "register_operand")
3082 (mult:TI (match_operand:TI
1 "register_operand")
3083 (match_operand:TI
2 "register_operand")))]
3086 rtx l0 = gen_reg_rtx (DImode);
3087 rtx l1 = gen_lowpart (DImode, operands[
1]);
3088 rtx l2 = gen_lowpart (DImode, operands[
2]);
3089 rtx h0 = gen_reg_rtx (DImode);
3090 rtx h1 = gen_highpart (DImode, operands[
1]);
3091 rtx h2 = gen_highpart (DImode, operands[
2]);
3093 emit_insn (gen_muldi3 (l0, l1, l2));
3094 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3095 emit_insn (gen_madddi (h0, h1, l2, h0));
3096 emit_insn (gen_madddi (h0, l1, h2, h0));
3098 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3099 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3103 (define_insn "<su>muldi3_highpart"
3104 [(set (match_operand:DI
0 "register_operand" "=r")
3108 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3109 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3112 "<su>mulh
\\t%
0, %
1, %
2"
3113 [(set_attr "type" "<su>mull")]
3116 (define_insn "<su_optab>div<mode>
3"
3117 [(set (match_operand:GPI
0 "register_operand" "=r")
3118 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3119 (match_operand:GPI
2 "register_operand" "r")))]
3121 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3122 [(set_attr "type" "<su>div")]
3125 ;; zero_extend version of above
3126 (define_insn "*<su_optab>divsi3_uxtw"
3127 [(set (match_operand:DI
0 "register_operand" "=r")
3129 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3130 (match_operand:SI
2 "register_operand" "r"))))]
3132 "<su>div
\\t%w0, %w1, %w2"
3133 [(set_attr "type" "<su>div")]
3136 ;; -------------------------------------------------------------------
3138 ;; -------------------------------------------------------------------
3140 (define_insn "cmp<mode>"
3141 [(set (reg:CC CC_REGNUM)
3142 (compare:CC (match_operand:GPI
0 "register_operand" "r,r,r")
3143 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3149 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3152 (define_insn "fcmp<mode>"
3153 [(set (reg:CCFP CC_REGNUM)
3154 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3155 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3159 fcmp
\\t%<s>
0, %<s>
1"
3160 [(set_attr "type" "fcmp<s>")]
3163 (define_insn "fcmpe<mode>"
3164 [(set (reg:CCFPE CC_REGNUM)
3165 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3166 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3170 fcmpe
\\t%<s>
0, %<s>
1"
3171 [(set_attr "type" "fcmp<s>")]
3174 (define_insn "*cmp_swp_<shift>_reg<mode>"
3175 [(set (reg:CC_SWP CC_REGNUM)
3176 (compare:CC_SWP (ASHIFT:GPI
3177 (match_operand:GPI
0 "register_operand" "r")
3178 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3179 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3181 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3182 [(set_attr "type" "alus_shift_imm")]
3185 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3186 [(set (reg:CC_SWP CC_REGNUM)
3187 (compare:CC_SWP (ANY_EXTEND:GPI
3188 (match_operand:ALLX
0 "register_operand" "r"))
3189 (match_operand:GPI
1 "register_operand" "r")))]
3191 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3192 [(set_attr "type" "alus_ext")]
3195 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3196 [(set (reg:CC_SWP CC_REGNUM)
3197 (compare:CC_SWP (ashift:GPI
3199 (match_operand:ALLX
0 "register_operand" "r"))
3200 (match_operand
1 "aarch64_imm3" "Ui3"))
3201 (match_operand:GPI
2 "register_operand" "r")))]
3203 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3204 [(set_attr "type" "alus_ext")]
3207 ;; -------------------------------------------------------------------
3208 ;; Store-flag and conditional select insns
3209 ;; -------------------------------------------------------------------
3211 (define_expand "cstore<mode>
4"
3212 [(set (match_operand:SI
0 "register_operand" "")
3213 (match_operator:SI
1 "aarch64_comparison_operator"
3214 [(match_operand:GPI
2 "register_operand" "")
3215 (match_operand:GPI
3 "aarch64_plus_operand" "")]))]
3218 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3220 operands[
3] = const0_rtx;
3224 (define_expand "cstorecc4"
3225 [(set (match_operand:SI
0 "register_operand")
3226 (match_operator
1 "aarch64_comparison_operator_mode"
3227 [(match_operand
2 "cc_register")
3228 (match_operand
3 "const0_operand")]))]
3231 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
3236 (define_expand "cstore<mode>
4"
3237 [(set (match_operand:SI
0 "register_operand" "")
3238 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3239 [(match_operand:GPF
2 "register_operand" "")
3240 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")]))]
3243 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3245 operands[
3] = const0_rtx;
3249 (define_insn "aarch64_cstore<mode>"
3250 [(set (match_operand:ALLI
0 "register_operand" "=r")
3251 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3252 [(match_operand
2 "cc_register" "") (const_int
0)]))]
3255 [(set_attr "type" "csel")]
3258 ;; For a
24-bit immediate CST we can optimize the compare for equality
3259 ;; and branch sequence from:
3261 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
3264 ;; into the shorter:
3265 ;; sub x0, x1, #(CST &
0xfff000)
3266 ;; subs x0, x0, #(CST &
0x000fff)
3267 ;; cset x2, <ne, eq>.
3268 (define_insn_and_split "*compare_cstore<mode>_insn"
3269 [(set (match_operand:GPI
0 "register_operand" "=r")
3270 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
3271 (match_operand:GPI
2 "aarch64_imm24" "n")))
3272 (clobber (reg:CC CC_REGNUM))]
3273 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
3274 && !aarch64_plus_operand (operands[
2], <MODE>mode)
3275 && !reload_completed"
3280 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
3281 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
3282 rtx tmp = gen_reg_rtx (<MODE>mode);
3283 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
3284 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3285 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3286 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3287 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
3290 [(set_attr "type" "csel")]
3293 ;; zero_extend version of the above
3294 (define_insn "*cstoresi_insn_uxtw"
3295 [(set (match_operand:DI
0 "register_operand" "=r")
3297 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3298 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3301 [(set_attr "type" "csel")]
3304 (define_insn "cstore<mode>_neg"
3305 [(set (match_operand:ALLI
0 "register_operand" "=r")
3306 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3307 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3309 "csetm
\\t%<w>
0, %m1"
3310 [(set_attr "type" "csel")]
3313 ;; zero_extend version of the above
3314 (define_insn "*cstoresi_neg_uxtw"
3315 [(set (match_operand:DI
0 "register_operand" "=r")
3317 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
3318 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
3321 [(set_attr "type" "csel")]
3324 (define_expand "cmov<mode>
6"
3325 [(set (match_operand:GPI
0 "register_operand" "")
3327 (match_operator
1 "aarch64_comparison_operator"
3328 [(match_operand:GPI
2 "register_operand" "")
3329 (match_operand:GPI
3 "aarch64_plus_operand" "")])
3330 (match_operand:GPI
4 "register_operand" "")
3331 (match_operand:GPI
5 "register_operand" "")))]
3334 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3336 operands[
3] = const0_rtx;
3340 (define_expand "cmov<mode>
6"
3341 [(set (match_operand:GPF
0 "register_operand" "")
3343 (match_operator
1 "aarch64_comparison_operator"
3344 [(match_operand:GPF
2 "register_operand" "")
3345 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")])
3346 (match_operand:GPF
4 "register_operand" "")
3347 (match_operand:GPF
5 "register_operand" "")))]
3350 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3352 operands[
3] = const0_rtx;
3356 (define_insn "*cmov<mode>_insn"
3357 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
3359 (match_operator
1 "aarch64_comparison_operator"
3360 [(match_operand
2 "cc_register" "") (const_int
0)])
3361 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3362 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3363 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3364 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3365 ;; Final two alternatives should be unreachable, but included for completeness
3367 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
3368 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
3369 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
3370 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
3371 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
3374 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3377 ;; zero_extend version of above
3378 (define_insn "*cmovsi_insn_uxtw"
3379 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
3382 (match_operator
1 "aarch64_comparison_operator"
3383 [(match_operand
2 "cc_register" "") (const_int
0)])
3384 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3385 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3386 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3387 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3388 ;; Final two alternatives should be unreachable, but included for completeness
3390 csel
\\t%w0, %w3, %w4, %m1
3391 csinv
\\t%w0, %w3, wzr, %m1
3392 csinv
\\t%w0, %w4, wzr, %M1
3393 csinc
\\t%w0, %w3, wzr, %m1
3394 csinc
\\t%w0, %w4, wzr, %M1
3397 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3400 (define_insn "*cmovdi_insn_uxtw"
3401 [(set (match_operand:DI
0 "register_operand" "=r")
3403 (match_operator
1 "aarch64_comparison_operator"
3404 [(match_operand
2 "cc_register" "") (const_int
0)])
3405 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
3406 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
3408 "csel
\\t%w0, %w3, %w4, %m1"
3409 [(set_attr "type" "csel")]
3412 (define_insn "*cmov<mode>_insn"
3413 [(set (match_operand:GPF
0 "register_operand" "=w")
3415 (match_operator
1 "aarch64_comparison_operator"
3416 [(match_operand
2 "cc_register" "") (const_int
0)])
3417 (match_operand:GPF
3 "register_operand" "w")
3418 (match_operand:GPF
4 "register_operand" "w")))]
3420 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
3421 [(set_attr "type" "fcsel")]
3424 (define_expand "mov<mode>cc"
3425 [(set (match_operand:ALLI
0 "register_operand" "")
3426 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator" "")
3427 (match_operand:ALLI
2 "register_operand" "")
3428 (match_operand:ALLI
3 "register_operand" "")))]
3432 enum rtx_code code = GET_CODE (operands[
1]);
3434 if (code == UNEQ || code == LTGT)
3437 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3438 XEXP (operands[
1],
1));
3439 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3443 (define_expand "mov<GPF:mode><GPI:mode>cc"
3444 [(set (match_operand:GPI
0 "register_operand" "")
3445 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3446 (match_operand:GPF
2 "register_operand" "")
3447 (match_operand:GPF
3 "register_operand" "")))]
3451 enum rtx_code code = GET_CODE (operands[
1]);
3453 if (code == UNEQ || code == LTGT)
3456 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3457 XEXP (operands[
1],
1));
3458 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3462 (define_expand "mov<mode>cc"
3463 [(set (match_operand:GPF
0 "register_operand" "")
3464 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator" "")
3465 (match_operand:GPF
2 "register_operand" "")
3466 (match_operand:GPF
3 "register_operand" "")))]
3470 enum rtx_code code = GET_CODE (operands[
1]);
3472 if (code == UNEQ || code == LTGT)
3475 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3476 XEXP (operands[
1],
1));
3477 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3481 (define_expand "<neg_not_op><mode>cc"
3482 [(set (match_operand:GPI
0 "register_operand" "")
3483 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3484 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand" ""))
3485 (match_operand:GPI
3 "register_operand" "")))]
3489 enum rtx_code code = GET_CODE (operands[
1]);
3491 if (code == UNEQ || code == LTGT)
3494 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3495 XEXP (operands[
1],
1));
3496 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3500 ;; CRC32 instructions.
3501 (define_insn "aarch64_<crc_variant>"
3502 [(set (match_operand:SI
0 "register_operand" "=r")
3503 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
3504 (match_operand:<crc_mode>
2 "register_operand" "r")]
3508 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
3509 return "<crc_variant>
\\t%w0, %w1, %x2";
3511 return "<crc_variant>
\\t%w0, %w1, %w2";
3513 [(set_attr "type" "crc")]
3516 (define_insn "*csinc2<mode>_insn"
3517 [(set (match_operand:GPI
0 "register_operand" "=r")
3518 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
3519 (match_operand:GPI
1 "register_operand" "r")))]
3521 "cinc
\\t%<w>
0, %<w>
1, %m2"
3522 [(set_attr "type" "csel")]
3525 (define_insn "csinc3<mode>_insn"
3526 [(set (match_operand:GPI
0 "register_operand" "=r")
3528 (match_operand
1 "aarch64_comparison_operation" "")
3529 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
3531 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3533 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3534 [(set_attr "type" "csel")]
3537 (define_insn "*csinv3<mode>_insn"
3538 [(set (match_operand:GPI
0 "register_operand" "=r")
3540 (match_operand
1 "aarch64_comparison_operation" "")
3541 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
3542 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3544 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3545 [(set_attr "type" "csel")]
3548 (define_insn "csneg3_uxtw_insn"
3549 [(set (match_operand:DI
0 "register_operand" "=r")
3552 (match_operand
1 "aarch64_comparison_operation" "")
3553 (neg:SI (match_operand:SI
2 "register_operand" "r"))
3554 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
3556 "csneg
\\t%w0, %w3, %w2, %M1"
3557 [(set_attr "type" "csel")]
3560 (define_insn "csneg3<mode>_insn"
3561 [(set (match_operand:GPI
0 "register_operand" "=r")
3563 (match_operand
1 "aarch64_comparison_operation" "")
3564 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
3565 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3567 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3568 [(set_attr "type" "csel")]
3571 ;; If X can be loaded by a single CNT[BHWD] instruction,
3575 ;; is equivalent to:
3577 ;; TMP = UQDEC[BHWD] (B, X)
3580 ;; Defining the pattern this way means that:
3582 ;; A = UMAX (B, X) - X
3586 ;; TMP1 = UQDEC[BHWD] (B, X)
3590 ;; which combine can optimize to:
3592 ;; A = UQDEC[BHWD] (B, X)
3594 ;; We don't use match_operand predicates because the order of the operands
3595 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
3596 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
3597 (define_expand "umax<mode>
3"
3598 [(set (match_operand:GPI
0 "register_operand")
3599 (umax:GPI (match_operand:GPI
1 "")
3600 (match_operand:GPI
2 "")))]
3603 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
3604 std::swap (operands[
1], operands[
2]);
3605 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
3607 rtx temp = gen_reg_rtx (<MODE>mode);
3608 operands[
1] = force_reg (<MODE>mode, operands[
1]);
3609 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
3610 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
3615 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
3616 (define_insn "aarch64_uqdec<mode>"
3617 [(set (match_operand:GPI
0 "register_operand" "=r")
3619 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
3620 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
3624 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
3628 ;; -------------------------------------------------------------------
3629 ;; Logical operations
3630 ;; -------------------------------------------------------------------
3633 (define_insn_and_split "*aarch64_and<mode>_imm2"
3634 [(set (match_operand:GPI
0 "register_operand" "=rk")
3635 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
3636 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
3642 HOST_WIDE_INT val = INTVAL (operands[
2]);
3643 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3644 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3646 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
3647 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
3652 (define_insn "<optab><mode>
3"
3653 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
3654 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
3655 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
3658 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
3659 <logical>
\\t%<w>
0, %<w>
1, %
2
3660 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
3661 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3662 (set_attr "simd" "*,*,yes")]
3665 ;; zero_extend version of above
3666 (define_insn "*<optab>si3_uxtw"
3667 [(set (match_operand:DI
0 "register_operand" "=r,rk")
3669 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
3670 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
3673 <logical>
\\t%w0, %w1, %w2
3674 <logical>
\\t%w0, %w1, %
2"
3675 [(set_attr "type" "logic_reg,logic_imm")]
3678 (define_insn "*and<mode>
3_compare0"
3679 [(set (reg:CC_NZ CC_REGNUM)
3681 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
3682 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
3684 (set (match_operand:GPI
0 "register_operand" "=r,r")
3685 (and:GPI (match_dup
1) (match_dup
2)))]
3688 ands
\\t%<w>
0, %<w>
1, %<w>
2
3689 ands
\\t%<w>
0, %<w>
1, %
2"
3690 [(set_attr "type" "logics_reg,logics_imm")]
3693 ;; zero_extend version of above
3694 (define_insn "*andsi3_compare0_uxtw"
3695 [(set (reg:CC_NZ CC_REGNUM)
3697 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
3698 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
3700 (set (match_operand:DI
0 "register_operand" "=r,r")
3701 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
3704 ands
\\t%w0, %w1, %w2
3705 ands
\\t%w0, %w1, %
2"
3706 [(set_attr "type" "logics_reg,logics_imm")]
3709 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
3710 [(set (reg:CC_NZ CC_REGNUM)
3713 (match_operand:GPI
1 "register_operand" "r")
3714 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
3715 (match_operand:GPI
3 "register_operand" "r"))
3717 (set (match_operand:GPI
0 "register_operand" "=r")
3718 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
3720 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
3721 [(set_attr "type" "logics_shift_imm")]
3724 ;; zero_extend version of above
3725 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3726 [(set (reg:CC_NZ CC_REGNUM)
3729 (match_operand:SI
1 "register_operand" "r")
3730 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
3731 (match_operand:SI
3 "register_operand" "r"))
3733 (set (match_operand:DI
0 "register_operand" "=r")
3734 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
3737 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
3738 [(set_attr "type" "logics_shift_imm")]
3741 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
3742 [(set (match_operand:GPI
0 "register_operand" "=r")
3743 (LOGICAL:GPI (SHIFT:GPI
3744 (match_operand:GPI
1 "register_operand" "r")
3745 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
3746 (match_operand:GPI
3 "register_operand" "r")))]
3748 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
3749 [(set_attr "type" "logic_shift_imm")]
3752 (define_insn "*<optab>_rol<mode>
3"
3753 [(set (match_operand:GPI
0 "register_operand" "=r")
3754 (LOGICAL:GPI (rotate:GPI
3755 (match_operand:GPI
1 "register_operand" "r")
3756 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
3757 (match_operand:GPI
3 "register_operand" "r")))]
3759 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
3760 [(set_attr "type" "logic_shift_imm")]
3763 ;; zero_extend versions of above
3764 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3765 [(set (match_operand:DI
0 "register_operand" "=r")
3767 (LOGICAL:SI (SHIFT:SI
3768 (match_operand:SI
1 "register_operand" "r")
3769 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
3770 (match_operand:SI
3 "register_operand" "r"))))]
3772 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
3773 [(set_attr "type" "logic_shift_imm")]
3776 (define_insn "*<optab>_rolsi3_uxtw"
3777 [(set (match_operand:DI
0 "register_operand" "=r")
3779 (LOGICAL:SI (rotate:SI
3780 (match_operand:SI
1 "register_operand" "r")
3781 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
3782 (match_operand:SI
3 "register_operand" "r"))))]
3784 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
3785 [(set_attr "type" "logic_shift_imm")]
3788 (define_insn "one_cmpl<mode>
2"
3789 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3790 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3795 [(set_attr "type" "logic_reg,neon_logic")
3796 (set_attr "simd" "*,yes")]
3799 (define_insn "*one_cmpl_<optab><mode>
2"
3800 [(set (match_operand:GPI
0 "register_operand" "=r")
3801 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
3802 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3804 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
3805 [(set_attr "type" "logic_shift_imm")]
3808 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3810 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
3811 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3812 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
3813 (match_operand:GPI
2 "register_operand" "r,w")))]
3816 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
3817 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
3818 [(set_attr "type" "logic_reg,neon_logic")
3819 (set_attr "simd" "*,yes")]
3822 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3823 [(set (match_operand:DI
0 "register_operand" "=r")
3825 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
3826 (match_operand:SI
2 "register_operand" "r"))))]
3828 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
3829 [(set_attr "type" "logic_reg")]
3832 (define_insn "*xor_one_cmplsidi3_ze"
3833 [(set (match_operand:DI
0 "register_operand" "=r")
3835 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
3836 (match_operand:SI
2 "register_operand" "r")))))]
3838 "eon
\\t%w0, %w1, %w2"
3839 [(set_attr "type" "logic_reg")]
3842 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3843 ;; eon does not operate on SIMD registers so the vector variant must be split.
3844 (define_insn_and_split "*xor_one_cmpl<mode>
3"
3845 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3846 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
3847 (match_operand:GPI
2 "register_operand" "r,w"))))]
3850 eon
\\t%<w>
0, %<w>
1, %<w>
2
3852 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
3853 [(set (match_operand:GPI
0 "register_operand" "=w")
3854 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
3855 (match_operand:GPI
2 "register_operand" "w")))
3856 (set (match_dup
0) (not:GPI (match_dup
0)))]
3858 [(set_attr "type" "logic_reg,multiple")
3859 (set_attr "simd" "*,yes")]
3862 (define_insn "*and_one_cmpl<mode>
3_compare0"
3863 [(set (reg:CC_NZ CC_REGNUM)
3866 (match_operand:GPI
1 "register_operand" "r"))
3867 (match_operand:GPI
2 "register_operand" "r"))
3869 (set (match_operand:GPI
0 "register_operand" "=r")
3870 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
3872 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
3873 [(set_attr "type" "logics_reg")]
3876 ;; zero_extend version of above
3877 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3878 [(set (reg:CC_NZ CC_REGNUM)
3881 (match_operand:SI
1 "register_operand" "r"))
3882 (match_operand:SI
2 "register_operand" "r"))
3884 (set (match_operand:DI
0 "register_operand" "=r")
3885 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
3887 "bics
\\t%w0, %w2, %w1"
3888 [(set_attr "type" "logics_reg")]
3891 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
3892 [(set (reg:CC_NZ CC_REGNUM)
3895 (match_operand:GPI
0 "register_operand" "r"))
3896 (match_operand:GPI
1 "register_operand" "r"))
3899 "bics
\\t<w>zr, %<w>
1, %<w>
0"
3900 [(set_attr "type" "logics_reg")]
3903 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
3904 [(set (match_operand:GPI
0 "register_operand" "=r")
3905 (LOGICAL:GPI (not:GPI
3907 (match_operand:GPI
1 "register_operand" "r")
3908 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3909 (match_operand:GPI
3 "register_operand" "r")))]
3911 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
3912 [(set_attr "type" "logic_shift_imm")]
3915 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
3916 [(set (match_operand:GPI
0 "register_operand" "=r")
3919 (match_operand:GPI
1 "register_operand" "r")
3920 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
3921 (match_operand:GPI
3 "register_operand" "r"))))]
3923 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
3924 [(set_attr "type" "logic_shift_imm")]
3927 ;; Zero-extend version of the above.
3928 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3929 [(set (match_operand:DI
0 "register_operand" "=r")
3933 (match_operand:SI
1 "register_operand" "r")
3934 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
3935 (match_operand:SI
3 "register_operand" "r")))))]
3937 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
3938 [(set_attr "type" "logic_shift_imm")]
3941 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
3942 [(set (reg:CC_NZ CC_REGNUM)
3946 (match_operand:GPI
1 "register_operand" "r")
3947 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3948 (match_operand:GPI
3 "register_operand" "r"))
3950 (set (match_operand:GPI
0 "register_operand" "=r")
3953 (match_dup
1) (match_dup
2))) (match_dup
3)))]
3955 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
3956 [(set_attr "type" "logics_shift_imm")]
3959 ;; zero_extend version of above
3960 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3961 [(set (reg:CC_NZ CC_REGNUM)
3965 (match_operand:SI
1 "register_operand" "r")
3966 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
3967 (match_operand:SI
3 "register_operand" "r"))
3969 (set (match_operand:DI
0 "register_operand" "=r")
3970 (zero_extend:DI (and:SI
3972 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
3974 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
3975 [(set_attr "type" "logics_shift_imm")]
3978 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
3979 [(set (reg:CC_NZ CC_REGNUM)
3983 (match_operand:GPI
0 "register_operand" "r")
3984 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
3985 (match_operand:GPI
2 "register_operand" "r"))
3988 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
3989 [(set_attr "type" "logics_shift_imm")]
3992 (define_insn "clz<mode>
2"
3993 [(set (match_operand:GPI
0 "register_operand" "=r")
3994 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
3996 "clz
\\t%<w>
0, %<w>
1"
3997 [(set_attr "type" "clz")]
4000 (define_expand "ffs<mode>
2"
4001 [(match_operand:GPI
0 "register_operand")
4002 (match_operand:GPI
1 "register_operand")]
4005 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4006 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4008 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4009 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4010 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4015 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4022 (define_expand "popcount<mode>
2"
4023 [(match_operand:GPI
0 "register_operand")
4024 (match_operand:GPI
1 "register_operand")]
4027 rtx v = gen_reg_rtx (V8QImode);
4028 rtx v1 = gen_reg_rtx (V8QImode);
4029 rtx r = gen_reg_rtx (QImode);
4030 rtx in = operands[
1];
4031 rtx out = operands[
0];
4032 if(<MODE>mode == SImode)
4035 tmp = gen_reg_rtx (DImode);
4036 /* If we have SImode, zero extend to DImode, pop count does
4037 not change if we have extra zeros. */
4038 emit_insn (gen_zero_extendsidi2 (tmp, in));
4041 emit_move_insn (v, gen_lowpart (V8QImode, in));
4042 emit_insn (gen_popcountv8qi2 (v1, v));
4043 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4044 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4048 (define_insn "clrsb<mode>
2"
4049 [(set (match_operand:GPI
0 "register_operand" "=r")
4050 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4052 "cls
\\t%<w>
0, %<w>
1"
4053 [(set_attr "type" "clz")]
4056 (define_insn "rbit<mode>
2"
4057 [(set (match_operand:GPI
0 "register_operand" "=r")
4058 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4060 "rbit
\\t%<w>
0, %<w>
1"
4061 [(set_attr "type" "rbit")]
4064 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4065 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4066 ;; expression and split after reload to enable scheduling them apart if
4069 (define_insn_and_split "ctz<mode>
2"
4070 [(set (match_operand:GPI
0 "register_operand" "=r")
4071 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4077 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4078 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4082 (define_insn "*and<mode>_compare0"
4083 [(set (reg:CC_NZ CC_REGNUM)
4085 (match_operand:SHORT
0 "register_operand" "r")
4088 "tst
\\t%<w>
0, <short_mask>"
4089 [(set_attr "type" "alus_imm")]
4092 (define_insn "*ands<mode>_compare0"
4093 [(set (reg:CC_NZ CC_REGNUM)
4095 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4097 (set (match_operand:GPI
0 "register_operand" "=r")
4098 (zero_extend:GPI (match_dup
1)))]
4100 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4101 [(set_attr "type" "alus_imm")]
4104 (define_insn "*and<mode>
3nr_compare0"
4105 [(set (reg:CC_NZ CC_REGNUM)
4107 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4108 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4114 [(set_attr "type" "logics_reg,logics_imm")]
4118 [(set (reg:CC_NZ CC_REGNUM)
4120 (and:GPI (match_operand:GPI
0 "register_operand")
4121 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4123 (clobber (match_operand:SI
2 "register_operand"))]
4125 [(set (match_dup
2) (match_dup
1))
4126 (set (reg:CC_NZ CC_REGNUM)
4128 (and:GPI (match_dup
0)
4133 (define_insn "*and<mode>
3nr_compare0_zextract"
4134 [(set (reg:CC_NZ CC_REGNUM)
4136 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4137 (match_operand:GPI
1 "const_int_operand" "n")
4138 (match_operand:GPI
2 "const_int_operand" "n"))
4140 "INTVAL (operands[
1]) >
0
4141 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4142 <= GET_MODE_BITSIZE (<MODE>mode))
4143 && aarch64_bitmask_imm (
4144 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4149 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4150 return "tst
\\t%<w>
0, %
1";
4152 [(set_attr "type" "logics_shift_imm")]
4155 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4156 [(set (reg:CC_NZ CC_REGNUM)
4159 (match_operand:GPI
0 "register_operand" "r")
4160 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4161 (match_operand:GPI
2 "register_operand" "r"))
4164 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4165 [(set_attr "type" "logics_shift_imm")]
4169 [(set (reg:CC_NZ CC_REGNUM)
4172 (match_operand:GPI
0 "register_operand")
4173 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4174 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4176 (clobber (match_operand:SI
3 "register_operand"))]
4178 [(set (match_dup
3) (match_dup
2))
4179 (set (reg:CC_NZ CC_REGNUM)
4188 ;; -------------------------------------------------------------------
4190 ;; -------------------------------------------------------------------
4192 (define_expand "<optab><mode>
3"
4193 [(set (match_operand:GPI
0 "register_operand")
4194 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4195 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4198 if (CONST_INT_P (operands[
2]))
4200 operands[
2] = GEN_INT (INTVAL (operands[
2])
4201 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4203 if (operands[
2] == const0_rtx)
4205 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4212 (define_expand "ashl<mode>
3"
4213 [(set (match_operand:SHORT
0 "register_operand")
4214 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4215 (match_operand:QI
2 "const_int_operand")))]
4218 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4220 if (operands[
2] == const0_rtx)
4222 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4228 (define_expand "rotr<mode>
3"
4229 [(set (match_operand:GPI
0 "register_operand")
4230 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4231 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4234 if (CONST_INT_P (operands[
2]))
4236 operands[
2] = GEN_INT (INTVAL (operands[
2])
4237 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4239 if (operands[
2] == const0_rtx)
4241 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4248 (define_expand "rotl<mode>
3"
4249 [(set (match_operand:GPI
0 "register_operand")
4250 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4251 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4254 /* (SZ - cnt) % SZ == -cnt % SZ */
4255 if (CONST_INT_P (operands[
2]))
4257 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
4258 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4259 if (operands[
2] == const0_rtx)
4261 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4266 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
4271 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4272 ;; they truncate the shift/rotate amount by the size of the registers they
4273 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
4274 ;; such redundant masking instructions. GCC can do that automatically when
4275 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4276 ;; because some of the SISD shift alternatives don't perform this truncations.
4277 ;; So this pattern exists to catch such cases.
4279 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
4280 [(set (match_operand:GPI
0 "register_operand" "=r")
4282 (match_operand:GPI
1 "register_operand" "r")
4283 (match_operator
4 "subreg_lowpart_operator"
4284 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
4285 (match_operand
3 "const_int_operand" "n"))])))]
4286 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
4287 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
4288 [(set_attr "type" "shift_reg")]
4291 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
4292 [(set (match_operand:GPI
0 "register_operand" "=&r")
4294 (match_operand:GPI
1 "register_operand" "r")
4295 (match_operator
4 "subreg_lowpart_operator"
4296 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
4297 (match_operand
3 "const_int_operand" "n")))])))]
4298 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
4303 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4304 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
4305 emit_insn (gen_negsi2 (tmp, operands[
2]));
4307 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
4308 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
4309 SUBREG_BYTE (operands[
4]));
4310 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
4315 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
4316 [(set (match_operand:GPI
0 "register_operand" "=&r")
4318 (match_operand:GPI
1 "register_operand" "r")
4319 (minus:QI (match_operand
2 "const_int_operand" "n")
4320 (match_operator
5 "subreg_lowpart_operator"
4321 [(and:SI (match_operand:SI
3 "register_operand" "r")
4322 (match_operand
4 "const_int_operand" "n"))]))))]
4323 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
4324 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4329 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4332 emit_insn (gen_negsi2 (tmp, operands[
3]));
4334 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
4335 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
4336 SUBREG_BYTE (operands[
5]));
4338 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
4343 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4344 [(set (match_operand:DI
0 "register_operand" "=r")
4346 (match_operand:DI
1 "register_operand" "r")
4347 (match_operator
4 "subreg_lowpart_operator"
4348 [(and:SI (match_operand:SI
2 "register_operand" "r")
4349 (match_operand
3 "const_int_operand" "n"))])))]
4350 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
4353 xop[
0] = operands[
0];
4354 xop[
1] = operands[
1];
4355 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
4356 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
4359 [(set_attr "type" "shift_reg")]
4362 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
4363 [(set (match_operand:GPI
0 "register_operand" "=&r")
4365 (match_operand:GPI
1 "register_operand" "r")
4366 (minus:QI (match_operand
2 "const_int_operand" "n")
4367 (match_operand:QI
3 "register_operand" "r"))))]
4368 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4373 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
4375 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4376 : gen_lowpart (SImode, operands[
0]));
4378 emit_insn (gen_negsi2 (tmp, subreg_tmp));
4380 rtx and_op = gen_rtx_AND (SImode, tmp,
4381 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
4383 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
4385 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
4388 [(set_attr "length" "
8")]
4391 ;; Logical left shift using SISD or Integer instruction
4392 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
4393 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
4395 (match_operand:GPI
1 "register_operand" "r,r,w,w")
4396 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4399 lsl
\t%<w>
0, %<w>
1, %
2
4400 lsl
\t%<w>
0, %<w>
1, %<w>
2
4401 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4402 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
4403 [(set_attr "simd" "no,no,yes,yes")
4404 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4407 ;; Logical right shift using SISD or Integer instruction
4408 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
4409 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4411 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4412 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
4413 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4416 lsr
\t%<w>
0, %<w>
1, %
2
4417 lsr
\t%<w>
0, %<w>
1, %<w>
2
4418 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4421 [(set_attr "simd" "no,no,yes,yes,yes")
4422 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4426 [(set (match_operand:DI
0 "aarch64_simd_register")
4428 (match_operand:DI
1 "aarch64_simd_register")
4429 (match_operand:QI
2 "aarch64_simd_register")))]
4430 "TARGET_SIMD && reload_completed"
4432 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4434 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
4436 operands[
3] = gen_lowpart (QImode, operands[
0]);
4441 [(set (match_operand:SI
0 "aarch64_simd_register")
4443 (match_operand:SI
1 "aarch64_simd_register")
4444 (match_operand:QI
2 "aarch64_simd_register")))]
4445 "TARGET_SIMD && reload_completed"
4447 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4449 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
4451 operands[
3] = gen_lowpart (QImode, operands[
0]);
4455 ;; Arithmetic right shift using SISD or Integer instruction
4456 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
4457 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4459 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4460 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
4461 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4464 asr
\t%<w>
0, %<w>
1, %
2
4465 asr
\t%<w>
0, %<w>
1, %<w>
2
4466 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4469 [(set_attr "simd" "no,no,yes,yes,yes")
4470 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4474 [(set (match_operand:DI
0 "aarch64_simd_register")
4476 (match_operand:DI
1 "aarch64_simd_register")
4477 (match_operand:QI
2 "aarch64_simd_register")))]
4478 "TARGET_SIMD && reload_completed"
4480 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4482 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
4484 operands[
3] = gen_lowpart (QImode, operands[
0]);
4489 [(set (match_operand:SI
0 "aarch64_simd_register")
4491 (match_operand:SI
1 "aarch64_simd_register")
4492 (match_operand:QI
2 "aarch64_simd_register")))]
4493 "TARGET_SIMD && reload_completed"
4495 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4497 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
4499 operands[
3] = gen_lowpart (QImode, operands[
0]);
4503 (define_insn "*aarch64_sisd_ushl"
4504 [(set (match_operand:DI
0 "register_operand" "=w")
4505 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4506 (match_operand:QI
2 "register_operand" "w")]
4509 "ushl
\t%d0, %d1, %d2"
4510 [(set_attr "simd" "yes")
4511 (set_attr "type" "neon_shift_reg")]
4514 (define_insn "*aarch64_ushl_2s"
4515 [(set (match_operand:SI
0 "register_operand" "=w")
4516 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4517 (match_operand:QI
2 "register_operand" "w")]
4520 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
4521 [(set_attr "simd" "yes")
4522 (set_attr "type" "neon_shift_reg")]
4525 (define_insn "*aarch64_sisd_sshl"
4526 [(set (match_operand:DI
0 "register_operand" "=w")
4527 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4528 (match_operand:QI
2 "register_operand" "w")]
4531 "sshl
\t%d0, %d1, %d2"
4532 [(set_attr "simd" "yes")
4533 (set_attr "type" "neon_shift_reg")]
4536 (define_insn "*aarch64_sshl_2s"
4537 [(set (match_operand:SI
0 "register_operand" "=w")
4538 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4539 (match_operand:QI
2 "register_operand" "w")]
4542 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
4543 [(set_attr "simd" "yes")
4544 (set_attr "type" "neon_shift_reg")]
4547 (define_insn "*aarch64_sisd_neg_qi"
4548 [(set (match_operand:QI
0 "register_operand" "=w")
4549 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
4553 [(set_attr "simd" "yes")
4554 (set_attr "type" "neon_neg")]
4558 (define_insn "*ror<mode>
3_insn"
4559 [(set (match_operand:GPI
0 "register_operand" "=r,r")
4561 (match_operand:GPI
1 "register_operand" "r,r")
4562 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4565 ror
\\t%<w>
0, %<w>
1, %
2
4566 ror
\\t%<w>
0, %<w>
1, %<w>
2"
4567 [(set_attr "type" "rotate_imm,shift_reg")]
4570 ;; zero_extend version of above
4571 (define_insn "*<optab>si3_insn_uxtw"
4572 [(set (match_operand:DI
0 "register_operand" "=r,r")
4573 (zero_extend:DI (SHIFT:SI
4574 (match_operand:SI
1 "register_operand" "r,r")
4575 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4578 <shift>
\\t%w0, %w1, %
2
4579 <shift>
\\t%w0, %w1, %w2"
4580 [(set_attr "type" "bfx,shift_reg")]
4583 (define_insn "*<optab><mode>
3_insn"
4584 [(set (match_operand:SHORT
0 "register_operand" "=r")
4585 (ASHIFT:SHORT (match_operand:SHORT
1 "register_operand" "r")
4586 (match_operand
2 "const_int_operand" "n")))]
4587 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
4589 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
4590 return "<bfshift>
\t%w0, %w1, %
2, %
3";
4592 [(set_attr "type" "bfx")]
4595 (define_insn "*extr<mode>
5_insn"
4596 [(set (match_operand:GPI
0 "register_operand" "=r")
4597 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
4598 (match_operand
3 "const_int_operand" "n"))
4599 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
4600 (match_operand
4 "const_int_operand" "n"))))]
4601 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4602 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
4603 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
4604 [(set_attr "type" "rotate_imm")]
4607 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4608 ;; so we have to match both orderings.
4609 (define_insn "*extr<mode>
5_insn_alt"
4610 [(set (match_operand:GPI
0 "register_operand" "=r")
4611 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
4612 (match_operand
4 "const_int_operand" "n"))
4613 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
4614 (match_operand
3 "const_int_operand" "n"))))]
4615 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
4616 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
4617 == GET_MODE_BITSIZE (<MODE>mode))"
4618 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
4619 [(set_attr "type" "rotate_imm")]
4622 ;; zero_extend version of the above
4623 (define_insn "*extrsi5_insn_uxtw"
4624 [(set (match_operand:DI
0 "register_operand" "=r")
4626 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
4627 (match_operand
3 "const_int_operand" "n"))
4628 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
4629 (match_operand
4 "const_int_operand" "n")))))]
4630 "UINTVAL (operands[
3]) <
32 &&
4631 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
4632 "extr
\\t%w0, %w1, %w2, %
4"
4633 [(set_attr "type" "rotate_imm")]
4636 (define_insn "*extrsi5_insn_uxtw_alt"
4637 [(set (match_operand:DI
0 "register_operand" "=r")
4639 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
4640 (match_operand
4 "const_int_operand" "n"))
4641 (ashift:SI (match_operand:SI
1 "register_operand" "r")
4642 (match_operand
3 "const_int_operand" "n")))))]
4643 "UINTVAL (operands[
3]) <
32 &&
4644 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
4645 "extr
\\t%w0, %w1, %w2, %
4"
4646 [(set_attr "type" "rotate_imm")]
4649 (define_insn "*ror<mode>
3_insn"
4650 [(set (match_operand:GPI
0 "register_operand" "=r")
4651 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
4652 (match_operand
2 "const_int_operand" "n")))]
4653 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
4655 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
4656 return "ror
\\t%<w>
0, %<w>
1, %
3";
4658 [(set_attr "type" "rotate_imm")]
4661 ;; zero_extend version of the above
4662 (define_insn "*rorsi3_insn_uxtw"
4663 [(set (match_operand:DI
0 "register_operand" "=r")
4665 (rotate:SI (match_operand:SI
1 "register_operand" "r")
4666 (match_operand
2 "const_int_operand" "n"))))]
4667 "UINTVAL (operands[
2]) <
32"
4669 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
4670 return "ror
\\t%w0, %w1, %
3";
4672 [(set_attr "type" "rotate_imm")]
4675 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4676 [(set (match_operand:GPI
0 "register_operand" "=r")
4678 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
4679 (match_operand
2 "const_int_operand" "n"))))]
4680 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4682 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
4683 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
4685 [(set_attr "type" "bfx")]
4688 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4689 [(set (match_operand:GPI
0 "register_operand" "=r")
4691 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
4692 (match_operand
2 "const_int_operand" "n"))))]
4693 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4695 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
4696 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
4698 [(set_attr "type" "bfx")]
4701 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4702 [(set (match_operand:GPI
0 "register_operand" "=r")
4704 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
4705 (match_operand
2 "const_int_operand" "n"))))]
4706 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4708 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
4709 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
4711 [(set_attr "type" "bfx")]
4714 ;; -------------------------------------------------------------------
4716 ;; -------------------------------------------------------------------
4718 (define_expand "<optab>"
4719 [(set (match_operand:DI
0 "register_operand" "=r")
4720 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
4722 "aarch64_simd_shift_imm_offset_di")
4723 (match_operand
3 "aarch64_simd_shift_imm_di")))]
4726 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
4727 1, GET_MODE_BITSIZE (DImode) -
1))
4733 (define_insn "*<optab><mode>"
4734 [(set (match_operand:GPI
0 "register_operand" "=r")
4735 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
4737 "aarch64_simd_shift_imm_offset_<mode>" "n")
4739 "aarch64_simd_shift_imm_<mode>" "n")))]
4740 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
4741 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
4742 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
4743 [(set_attr "type" "bfx")]
4746 ;; When the bit position and width add up to
32 we can use a W-reg LSR
4747 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4749 [(set (match_operand:DI
0 "register_operand")
4750 (zero_extract:DI (match_operand:DI
1 "register_operand")
4752 "aarch64_simd_shift_imm_offset_di")
4754 "aarch64_simd_shift_imm_di")))]
4755 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
4756 GET_MODE_BITSIZE (DImode) -
1)
4757 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
4758 == GET_MODE_BITSIZE (SImode)"
4760 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
4762 operands[
4] = gen_lowpart (SImode, operands[
1]);
4766 ;; Bitfield Insert (insv)
4767 (define_expand "insv<mode>"
4768 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
4769 (match_operand
1 "const_int_operand")
4770 (match_operand
2 "const_int_operand"))
4771 (match_operand:GPI
3 "general_operand"))]
4774 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
4775 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
4776 rtx value = operands[
3];
4778 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4781 if (CONST_INT_P (value))
4783 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
4785 /* Prefer AND/OR for inserting all zeros or all ones. */
4786 if ((UINTVAL (value) & mask) ==
0
4787 || (UINTVAL (value) & mask) == mask)
4790 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
4791 if (width ==
16 && (pos %
16) ==
0)
4794 operands[
3] = force_reg (<MODE>mode, value);
4797 (define_insn "*insv_reg<mode>"
4798 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
4799 (match_operand
1 "const_int_operand" "n")
4800 (match_operand
2 "const_int_operand" "n"))
4801 (match_operand:GPI
3 "register_operand" "r"))]
4802 "!(UINTVAL (operands[
1]) ==
0
4803 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
4804 > GET_MODE_BITSIZE (<MODE>mode)))"
4805 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
4806 [(set_attr "type" "bfm")]
4809 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
4810 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
4811 (match_operand
1 "const_int_operand" "n")
4812 (match_operand
2 "const_int_operand" "n"))
4813 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
4814 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
4815 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
4816 [(set_attr "type" "bfm")]
4819 (define_insn "*extr_insv_lower_reg<mode>"
4820 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
4821 (match_operand
1 "const_int_operand" "n")
4823 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
4825 (match_operand
3 "const_int_operand" "n")))]
4826 "!(UINTVAL (operands[
1]) ==
0
4827 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
4828 > GET_MODE_BITSIZE (<MODE>mode)))"
4829 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
4830 [(set_attr "type" "bfm")]
4833 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4834 [(set (match_operand:GPI
0 "register_operand" "=r")
4835 (ashift:GPI (ANY_EXTEND:GPI
4836 (match_operand:ALLX
1 "register_operand" "r"))
4837 (match_operand
2 "const_int_operand" "n")))]
4838 "UINTVAL (operands[
2]) < <GPI:sizen>"
4840 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
4841 ? GEN_INT (<ALLX:sizen>)
4842 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
4843 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
4845 [(set_attr "type" "bfx")]
4848 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4850 (define_insn "*andim_ashift<mode>_bfiz"
4851 [(set (match_operand:GPI
0 "register_operand" "=r")
4852 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
4853 (match_operand
2 "const_int_operand" "n"))
4854 (match_operand
3 "const_int_operand" "n")))]
4855 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
4856 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
4857 [(set_attr "type" "bfx")]
4860 ;; When the bit position and width of the equivalent extraction add up to
32
4861 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4862 ;; zero-extension of the X-reg.
4864 [(set (match_operand:DI
0 "register_operand")
4865 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
4866 (match_operand
2 "const_int_operand"))
4867 (match_operand
3 "const_int_operand")))]
4868 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
4869 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
4870 == GET_MODE_BITSIZE (SImode)"
4872 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
4874 operands[
4] = gen_lowpart (SImode, operands[
1]);
4878 (define_insn "bswap<mode>
2"
4879 [(set (match_operand:GPI
0 "register_operand" "=r")
4880 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
4882 "rev
\\t%<w>
0, %<w>
1"
4883 [(set_attr "type" "rev")]
4886 (define_insn "bswaphi2"
4887 [(set (match_operand:HI
0 "register_operand" "=r")
4888 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
4891 [(set_attr "type" "rev")]
4894 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4895 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4896 ;; each valid permutation.
4898 (define_insn "rev16<mode>
2"
4899 [(set (match_operand:GPI
0 "register_operand" "=r")
4900 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
4902 (match_operand:GPI
3 "const_int_operand" "n"))
4903 (and:GPI (lshiftrt:GPI (match_dup
1)
4905 (match_operand:GPI
2 "const_int_operand" "n"))))]
4906 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
4907 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
4908 "rev16
\\t%<w>
0, %<w>
1"
4909 [(set_attr "type" "rev")]
4912 (define_insn "rev16<mode>
2_alt"
4913 [(set (match_operand:GPI
0 "register_operand" "=r")
4914 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
4916 (match_operand:GPI
2 "const_int_operand" "n"))
4917 (and:GPI (ashift:GPI (match_dup
1)
4919 (match_operand:GPI
3 "const_int_operand" "n"))))]
4920 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
4921 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
4922 "rev16
\\t%<w>
0, %<w>
1"
4923 [(set_attr "type" "rev")]
4926 ;; zero_extend version of above
4927 (define_insn "*bswapsi2_uxtw"
4928 [(set (match_operand:DI
0 "register_operand" "=r")
4929 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
4932 [(set_attr "type" "rev")]
4935 ;; -------------------------------------------------------------------
4936 ;; Floating-point intrinsics
4937 ;; -------------------------------------------------------------------
4939 ;; frint floating-point round to integral standard patterns.
4940 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4942 (define_insn "<frint_pattern><mode>
2"
4943 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
4944 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
4947 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
4948 [(set_attr "type" "f_rint<stype>")]
4951 ;; frcvt floating-point round to integer and convert standard patterns.
4952 ;; Expands to lbtrunc, lceil, lfloor, lround.
4953 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
4954 [(set (match_operand:GPI
0 "register_operand" "=r")
4956 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
4959 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
4960 [(set_attr "type" "f_cvtf2i")]
4963 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
4964 [(set (match_operand:GPI
0 "register_operand" "=r")
4967 (match_operand:GPF
1 "register_operand" "w")
4968 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
4970 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
4971 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4973 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
4975 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
4976 output_asm_insn (buf, operands);
4979 [(set_attr "type" "f_cvtf2i")]
4982 ;; fma - expand fma into patterns with the accumulator operand first since
4983 ;; reusing the accumulator results in better register allocation.
4984 ;; The register allocator considers copy preferences in operand order,
4985 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
4987 (define_expand "fma<mode>
4"
4988 [(set (match_operand:GPF_F16
0 "register_operand")
4989 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
4990 (match_operand:GPF_F16
2 "register_operand")
4991 (match_operand:GPF_F16
3 "register_operand")))]
4995 (define_insn "*aarch64_fma<mode>
4"
4996 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
4997 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
4998 (match_operand:GPF_F16
3 "register_operand" "w")
4999 (match_operand:GPF_F16
1 "register_operand" "w")))]
5001 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5002 [(set_attr "type" "fmac<stype>")]
5005 (define_expand "fnma<mode>
4"
5006 [(set (match_operand:GPF_F16
0 "register_operand")
5008 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5009 (match_operand:GPF_F16
2 "register_operand")
5010 (match_operand:GPF_F16
3 "register_operand")))]
5014 (define_insn "*aarch64_fnma<mode>
4"
5015 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5017 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5018 (match_operand:GPF_F16
3 "register_operand" "w")
5019 (match_operand:GPF_F16
1 "register_operand" "w")))]
5021 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5022 [(set_attr "type" "fmac<stype>")]
5026 (define_expand "fms<mode>
4"
5027 [(set (match_operand:GPF
0 "register_operand")
5028 (fma:GPF (match_operand:GPF
1 "register_operand")
5029 (match_operand:GPF
2 "register_operand")
5030 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5034 (define_insn "*aarch64_fms<mode>
4"
5035 [(set (match_operand:GPF
0 "register_operand" "=w")
5036 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5037 (match_operand:GPF
3 "register_operand" "w")
5038 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5040 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5041 [(set_attr "type" "fmac<s>")]
5044 (define_expand "fnms<mode>
4"
5045 [(set (match_operand:GPF
0 "register_operand")
5046 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5047 (match_operand:GPF
2 "register_operand")
5048 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5052 (define_insn "*aarch64_fnms<mode>
4"
5053 [(set (match_operand:GPF
0 "register_operand" "=w")
5054 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5055 (match_operand:GPF
3 "register_operand" "w")
5056 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5058 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5059 [(set_attr "type" "fmac<s>")]
5062 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5063 (define_insn "*aarch64_fnmadd<mode>
4"
5064 [(set (match_operand:GPF
0 "register_operand" "=w")
5065 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5066 (match_operand:GPF
3 "register_operand" "w")
5067 (match_operand:GPF
1 "register_operand" "w"))))]
5068 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5069 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5070 [(set_attr "type" "fmac<s>")]
5073 ;; -------------------------------------------------------------------
5074 ;; Floating-point conversions
5075 ;; -------------------------------------------------------------------
5077 (define_insn "extendsfdf2"
5078 [(set (match_operand:DF
0 "register_operand" "=w")
5079 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
5082 [(set_attr "type" "f_cvt")]
5085 (define_insn "extendhfsf2"
5086 [(set (match_operand:SF
0 "register_operand" "=w")
5087 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
5090 [(set_attr "type" "f_cvt")]
5093 (define_insn "extendhfdf2"
5094 [(set (match_operand:DF
0 "register_operand" "=w")
5095 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
5098 [(set_attr "type" "f_cvt")]
5101 (define_insn "truncdfsf2"
5102 [(set (match_operand:SF
0 "register_operand" "=w")
5103 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
5106 [(set_attr "type" "f_cvt")]
5109 (define_insn "truncsfhf2"
5110 [(set (match_operand:HF
0 "register_operand" "=w")
5111 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
5114 [(set_attr "type" "f_cvt")]
5117 (define_insn "truncdfhf2"
5118 [(set (match_operand:HF
0 "register_operand" "=w")
5119 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
5122 [(set_attr "type" "f_cvt")]
5125 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5126 ;; and making r = w more expensive
5128 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
5129 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
5130 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
5133 fcvtz<su>
\t%<s>
0, %<s>
1
5134 fcvtz<su>
\t%<w>
0, %<s>
1"
5135 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5138 ;; Convert HF -> SI or DI
5140 (define_insn "<optab>_trunchf<GPI:mode>
2"
5141 [(set (match_operand:GPI
0 "register_operand" "=r")
5142 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
5144 "fcvtz<su>
\t%<w>
0, %h1"
5145 [(set_attr "type" "f_cvtf2i")]
5148 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5149 ;; input in a fp register and output in a integer register
5151 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
5152 [(set (match_operand:GPI
0 "register_operand" "=r")
5153 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
5155 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
5156 [(set_attr "type" "f_cvtf2i")]
5159 (define_insn "<optab><fcvt_target><GPF:mode>
2"
5160 [(set (match_operand:GPF
0 "register_operand" "=w,w")
5161 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
5164 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
5165 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
5166 [(set_attr "simd" "yes,no")
5167 (set_attr "fp" "no,yes")
5168 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
5171 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
5172 [(set (match_operand:GPF
0 "register_operand" "=w")
5173 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
5175 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
5176 [(set_attr "type" "f_cvti2f")]
5179 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
5180 ;; midend will arrange for an SImode conversion to HFmode to first go
5181 ;; through DFmode, then to HFmode. But first it will try converting
5182 ;; to DImode then down, which would match our DImode pattern below and
5183 ;; give very poor code-generation. So, we must provide our own emulation
5184 ;; of the mid-end logic.
5186 (define_insn "aarch64_fp16_<optab><mode>hf2"
5187 [(set (match_operand:HF
0 "register_operand" "=w")
5188 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
5190 "<su_optab>cvtf
\t%h0, %<w>
1"
5191 [(set_attr "type" "f_cvti2f")]
5194 (define_expand "<optab>sihf2"
5195 [(set (match_operand:HF
0 "register_operand")
5196 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
5199 if (TARGET_FP_F16INST)
5200 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
5203 rtx convert_target = gen_reg_rtx (DFmode);
5204 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
5205 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
5211 ;; For DImode there is no wide enough floating-point mode that we
5212 ;; can convert through natively (TFmode would work, but requires a library
5213 ;; call). However, we know that any value >=
65504 will be rounded
5214 ;; to infinity on conversion. This is well within the range of SImode, so
5216 ;; Saturate to SImode.
5217 ;; Convert from that to DFmode
5218 ;; Convert from that to HFmode (phew!).
5219 ;; Note that the saturation to SImode requires the SIMD extensions. If
5220 ;; we ever need to provide this pattern where the SIMD extensions are not
5221 ;; available, we would need a different approach.
5223 (define_expand "<optab>dihf2"
5224 [(set (match_operand:HF
0 "register_operand")
5225 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
5226 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
5228 if (TARGET_FP_F16INST)
5229 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
5232 rtx sat_target = gen_reg_rtx (SImode);
5233 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
5234 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
5241 ;; Convert between fixed-point and floating-point (scalar modes)
5243 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
5244 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
5245 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
5246 (match_operand:SI
2 "immediate_operand" "i, i")]
5250 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
5251 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
5252 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
5253 (set_attr "fp" "yes, *")
5254 (set_attr "simd" "*, yes")]
5257 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
5258 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
5259 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
5260 (match_operand:SI
2 "immediate_operand" "i, i")]
5264 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
5265 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
5266 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
5267 (set_attr "fp" "yes, *")
5268 (set_attr "simd" "*, yes")]
5271 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
5272 [(set (match_operand:GPI
0 "register_operand" "=r")
5273 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
5274 (match_operand:SI
2 "immediate_operand" "i")]
5277 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
5278 [(set_attr "type" "f_cvtf2i")]
5281 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
5282 [(set (match_operand:HF
0 "register_operand" "=w")
5283 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
5284 (match_operand:SI
2 "immediate_operand" "i")]
5287 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
5288 [(set_attr "type" "f_cvti2f")]
5291 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
5292 [(set (match_operand:HI
0 "register_operand" "=w")
5293 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
5294 (match_operand:SI
2 "immediate_operand" "i")]
5297 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5298 [(set_attr "type" "neon_fp_to_int_s")]
5301 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
5302 [(set (match_operand:HF
0 "register_operand" "=w")
5303 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
5304 (match_operand:SI
2 "immediate_operand" "i")]
5307 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5308 [(set_attr "type" "neon_int_to_fp_s")]
5311 ;; -------------------------------------------------------------------
5312 ;; Floating-point arithmetic
5313 ;; -------------------------------------------------------------------
5315 (define_insn "add<mode>
3"
5316 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5318 (match_operand:GPF_F16
1 "register_operand" "w")
5319 (match_operand:GPF_F16
2 "register_operand" "w")))]
5321 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
5322 [(set_attr "type" "fadd<stype>")]
5325 (define_insn "sub<mode>
3"
5326 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5328 (match_operand:GPF_F16
1 "register_operand" "w")
5329 (match_operand:GPF_F16
2 "register_operand" "w")))]
5331 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
5332 [(set_attr "type" "fadd<stype>")]
5335 (define_insn "mul<mode>
3"
5336 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5338 (match_operand:GPF_F16
1 "register_operand" "w")
5339 (match_operand:GPF_F16
2 "register_operand" "w")))]
5341 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
5342 [(set_attr "type" "fmul<stype>")]
5345 (define_insn "*fnmul<mode>
3"
5346 [(set (match_operand:GPF
0 "register_operand" "=w")
5348 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
5349 (match_operand:GPF
2 "register_operand" "w")))]
5350 "TARGET_FLOAT && !flag_rounding_math"
5351 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5352 [(set_attr "type" "fmul<s>")]
5355 (define_insn "*fnmul<mode>
3"
5356 [(set (match_operand:GPF
0 "register_operand" "=w")
5358 (match_operand:GPF
1 "register_operand" "w")
5359 (match_operand:GPF
2 "register_operand" "w"))))]
5361 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5362 [(set_attr "type" "fmul<s>")]
5365 (define_expand "div<mode>
3"
5366 [(set (match_operand:GPF_F16
0 "register_operand")
5367 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
5368 (match_operand:GPF_F16
2 "register_operand")))]
5371 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
5374 operands[
1] = force_reg (<MODE>mode, operands[
1]);
5377 (define_insn "*div<mode>
3"
5378 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5379 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
5380 (match_operand:GPF_F16
2 "register_operand" "w")))]
5382 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
5383 [(set_attr "type" "fdiv<stype>")]
5386 (define_insn "neg<mode>
2"
5387 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5388 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5390 "fneg
\\t%<s>
0, %<s>
1"
5391 [(set_attr "type" "ffarith<stype>")]
5394 (define_expand "sqrt<mode>
2"
5395 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5396 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5399 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
5403 (define_insn "*sqrt<mode>
2"
5404 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5405 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5407 "fsqrt
\\t%<s>
0, %<s>
1"
5408 [(set_attr "type" "fsqrt<stype>")]
5411 (define_insn "abs<mode>
2"
5412 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5413 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5415 "fabs
\\t%<s>
0, %<s>
1"
5416 [(set_attr "type" "ffarith<stype>")]
5419 ;; Given that smax/smin do not specify the result when either input is NaN,
5420 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5423 (define_insn "smax<mode>
3"
5424 [(set (match_operand:GPF
0 "register_operand" "=w")
5425 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
5426 (match_operand:GPF
2 "register_operand" "w")))]
5428 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
5429 [(set_attr "type" "f_minmax<s>")]
5432 (define_insn "smin<mode>
3"
5433 [(set (match_operand:GPF
0 "register_operand" "=w")
5434 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
5435 (match_operand:GPF
2 "register_operand" "w")))]
5437 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
5438 [(set_attr "type" "f_minmax<s>")]
5441 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5442 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
5443 ;; which implement the IEEE fmax ()/fmin () functions.
5444 (define_insn "<maxmin_uns><mode>
3"
5445 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5446 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
5447 (match_operand:GPF_F16
2 "register_operand" "w")]
5450 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
5451 [(set_attr "type" "f_minmax<stype>")]
5454 (define_expand "lrint<GPF:mode><GPI:mode>
2"
5455 [(match_operand:GPI
0 "register_operand")
5456 (match_operand:GPF
1 "register_operand")]
5458 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
5459 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
5461 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5462 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
5463 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
5468 ;; For copysign (x, y), we want to generate:
5470 ;; LDR d2, #(
1 <<
63)
5471 ;; BSL v2.8b, [y], [x]
5473 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5474 ;; aarch64_simd_bsldf will select the best suited of these instructions
5475 ;; to generate based on register allocation, and knows how to partially
5476 ;; constant fold based on the values of X and Y, so expand through that.
5478 (define_expand "copysigndf3"
5479 [(match_operand:DF
0 "register_operand")
5480 (match_operand:DF
1 "register_operand")
5481 (match_operand:DF
2 "register_operand")]
5482 "TARGET_FLOAT && TARGET_SIMD"
5484 rtx mask = gen_reg_rtx (DImode);
5485 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U <<
63));
5486 emit_insn (gen_aarch64_simd_bsldf (operands[
0], mask,
5487 operands[
2], operands[
1]));
5492 ;; As above, but we must first get to a
64-bit value if we wish to use
5493 ;; aarch64_simd_bslv2sf.
5495 (define_expand "copysignsf3"
5496 [(match_operand:SF
0 "register_operand")
5497 (match_operand:SF
1 "register_operand")
5498 (match_operand:SF
2 "register_operand")]
5499 "TARGET_FLOAT && TARGET_SIMD"
5501 rtx v_bitmask = gen_reg_rtx (V2SImode);
5503 /* Juggle modes to get us in to a vector mode for BSL. */
5504 rtx op1 = lowpart_subreg (DImode, operands[
1], SFmode);
5505 rtx op2 = lowpart_subreg (V2SFmode, operands[
2], SFmode);
5506 rtx tmp = gen_reg_rtx (V2SFmode);
5507 emit_move_insn (v_bitmask,
5508 aarch64_simd_gen_const_vector_dup (V2SImode,
5509 HOST_WIDE_INT_M1U <<
31));
5510 emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5511 emit_move_insn (operands[
0], lowpart_subreg (SFmode, tmp, V2SFmode));
5516 ;; For xorsign (x, y), we want to generate:
5519 ;; AND v3.8B, v1.8B, v2.8B
5520 ;; EOR v0.8B, v0.8B, v3.8B
5523 (define_expand "xorsign<mode>
3"
5524 [(match_operand:GPF
0 "register_operand")
5525 (match_operand:GPF
1 "register_operand")
5526 (match_operand:GPF
2 "register_operand")]
5527 "TARGET_FLOAT && TARGET_SIMD"
5530 machine_mode imode = <V_INT_EQUIV>mode;
5531 rtx mask = gen_reg_rtx (imode);
5532 rtx op1x = gen_reg_rtx (imode);
5533 rtx op2x = gen_reg_rtx (imode);
5535 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
5536 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
5539 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
5540 lowpart_subreg (imode, operands[
2],
5542 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
5543 lowpart_subreg (imode, operands[
1],
5546 emit_move_insn (operands[
0],
5547 lowpart_subreg (<MODE>mode, op1x, imode));
5552 ;; -------------------------------------------------------------------
5554 ;; -------------------------------------------------------------------
5555 ;; Reload Scalar Floating point modes from constant pool.
5556 ;; The AArch64 port doesn't have __int128 constant move support.
5557 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5558 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
5559 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
5560 (clobber (match_operand:P
2 "register_operand" "=&r"))]
5563 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
5564 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
5569 ;; Reload Vector modes from constant pool.
5570 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5571 [(set (match_operand:VALL
0 "register_operand" "=w")
5572 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
5573 (clobber (match_operand:P
2 "register_operand" "=&r"))]
5576 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
5577 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
5582 (define_expand "aarch64_reload_mov<mode>"
5583 [(set (match_operand:TX
0 "register_operand" "=w")
5584 (match_operand:TX
1 "register_operand" "w"))
5585 (clobber (match_operand:DI
2 "register_operand" "=&r"))
5589 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
5590 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
5591 gen_aarch64_movtilow_tilow (op0, op1);
5592 gen_aarch64_movdi_tihigh (operands[
2], op1);
5593 gen_aarch64_movtihigh_di (op0, operands[
2]);
5598 ;; The following secondary reload helpers patterns are invoked
5599 ;; after or during reload as we don't want these patterns to start
5600 ;; kicking in during the combiner.
5602 (define_insn "aarch64_movdi_<mode>low"
5603 [(set (match_operand:DI
0 "register_operand" "=r")
5604 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
5605 (const_int
64) (const_int
0)))]
5606 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5608 [(set_attr "type" "f_mrc")
5609 (set_attr "length" "
4")
5612 (define_insn "aarch64_movdi_<mode>high"
5613 [(set (match_operand:DI
0 "register_operand" "=r")
5614 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
5615 (const_int
64) (const_int
64)))]
5616 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5617 "fmov
\\t%x0, %
1.d[
1]"
5618 [(set_attr "type" "f_mrc")
5619 (set_attr "length" "
4")
5622 (define_insn "aarch64_mov<mode>high_di"
5623 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
5624 (const_int
64) (const_int
64))
5625 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
5626 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5627 "fmov
\\t%
0.d[
1], %x1"
5628 [(set_attr "type" "f_mcr")
5629 (set_attr "length" "
4")
5632 (define_insn "aarch64_mov<mode>low_di"
5633 [(set (match_operand:TX
0 "register_operand" "=w")
5634 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
5635 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5637 [(set_attr "type" "f_mcr")
5638 (set_attr "length" "
4")
5641 (define_insn "aarch64_movtilow_tilow"
5642 [(set (match_operand:TI
0 "register_operand" "=w")
5644 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
5645 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5647 [(set_attr "type" "fmov")
5648 (set_attr "length" "
4")
5651 ;; There is a deliberate reason why the parameters of high and lo_sum's
5652 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5653 ;; and lo_sum's to be used with the labels defining the jump tables in
5656 (define_expand "add_losym"
5657 [(set (match_operand
0 "register_operand" "=r")
5658 (lo_sum (match_operand
1 "register_operand" "r")
5659 (match_operand
2 "aarch64_valid_symref" "S")))]
5662 machine_mode mode = GET_MODE (operands[
0]);
5664 emit_insn ((mode == DImode
5666 : gen_add_losym_si) (operands[
0],
5672 (define_insn "add_losym_<mode>"
5673 [(set (match_operand:P
0 "register_operand" "=r")
5674 (lo_sum:P (match_operand:P
1 "register_operand" "r")
5675 (match_operand
2 "aarch64_valid_symref" "S")))]
5677 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
5678 [(set_attr "type" "alu_imm")]
5681 (define_insn "ldr_got_small_<mode>"
5682 [(set (match_operand:PTR
0 "register_operand" "=r")
5683 (unspec:PTR [(mem:PTR (lo_sum:PTR
5684 (match_operand:PTR
1 "register_operand" "r")
5685 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
5686 UNSPEC_GOTSMALLPIC))]
5688 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
5689 [(set_attr "type" "load_<ldst_sz>")]
5692 (define_insn "ldr_got_small_sidi"
5693 [(set (match_operand:DI
0 "register_operand" "=r")
5695 (unspec:SI [(mem:SI (lo_sum:DI
5696 (match_operand:DI
1 "register_operand" "r")
5697 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
5698 UNSPEC_GOTSMALLPIC)))]
5700 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
5701 [(set_attr "type" "load_4")]
5704 (define_insn "ldr_got_small_28k_<mode>"
5705 [(set (match_operand:PTR
0 "register_operand" "=r")
5706 (unspec:PTR [(mem:PTR (lo_sum:PTR
5707 (match_operand:PTR
1 "register_operand" "r")
5708 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
5709 UNSPEC_GOTSMALLPIC28K))]
5711 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
5712 [(set_attr "type" "load_<ldst_sz>")]
5715 (define_insn "ldr_got_small_28k_sidi"
5716 [(set (match_operand:DI
0 "register_operand" "=r")
5718 (unspec:SI [(mem:SI (lo_sum:DI
5719 (match_operand:DI
1 "register_operand" "r")
5720 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
5721 UNSPEC_GOTSMALLPIC28K)))]
5723 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
5724 [(set_attr "type" "load_4")]
5727 (define_insn "ldr_got_tiny"
5728 [(set (match_operand:DI
0 "register_operand" "=r")
5729 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
5730 UNSPEC_GOTTINYPIC))]
5733 [(set_attr "type" "load_8")]
5736 (define_insn "aarch64_load_tp_hard"
5737 [(set (match_operand:DI
0 "register_operand" "=r")
5738 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
5740 "mrs
\\t%
0, tpidr_el0"
5741 [(set_attr "type" "mrs")]
5744 ;; The TLS ABI specifically requires that the compiler does not schedule
5745 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5746 ;; Therefore we treat the stubs as an atomic sequence.
5747 (define_expand "tlsgd_small_<mode>"
5748 [(parallel [(set (match_operand
0 "register_operand" "")
5749 (call (mem:DI (match_dup
2)) (const_int
1)))
5750 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5751 (clobber (reg:DI LR_REGNUM))])]
5754 operands[
2] = aarch64_tls_get_addr ();
5757 (define_insn "*tlsgd_small_<mode>"
5758 [(set (match_operand
0 "register_operand" "")
5759 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
5760 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5761 (clobber (reg:DI LR_REGNUM))
5764 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
5765 [(set_attr "type" "call")
5766 (set_attr "length" "
16")])
5768 (define_insn "tlsie_small_<mode>"
5769 [(set (match_operand:PTR
0 "register_operand" "=r")
5770 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
5771 UNSPEC_GOTSMALLTLS))]
5773 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
5774 [(set_attr "type" "load_4")
5775 (set_attr "length" "
8")]
5778 (define_insn "tlsie_small_sidi"
5779 [(set (match_operand:DI
0 "register_operand" "=r")
5781 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
5782 UNSPEC_GOTSMALLTLS)))]
5784 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
5785 [(set_attr "type" "load_4")
5786 (set_attr "length" "
8")]
5789 (define_insn "tlsie_tiny_<mode>"
5790 [(set (match_operand:PTR
0 "register_operand" "=&r")
5791 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
5792 (match_operand:PTR
2 "register_operand" "r")]
5793 UNSPEC_GOTTINYTLS))]
5795 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
5796 [(set_attr "type" "multiple")
5797 (set_attr "length" "
8")]
5800 (define_insn "tlsie_tiny_sidi"
5801 [(set (match_operand:DI
0 "register_operand" "=&r")
5803 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
5804 (match_operand:DI
2 "register_operand" "r")
5806 UNSPEC_GOTTINYTLS)))]
5808 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
5809 [(set_attr "type" "multiple")
5810 (set_attr "length" "
8")]
5813 (define_insn "tlsle12_<mode>"
5814 [(set (match_operand:P
0 "register_operand" "=r")
5815 (unspec:P [(match_operand:P
1 "register_operand" "r")
5816 (match_operand
2 "aarch64_tls_le_symref" "S")]
5819 "add
\\t%<w>
0, %<w>
1, #%L2";
5820 [(set_attr "type" "alu_sreg")
5821 (set_attr "length" "
4")]
5824 (define_insn "tlsle24_<mode>"
5825 [(set (match_operand:P
0 "register_operand" "=r")
5826 (unspec:P [(match_operand:P
1 "register_operand" "r")
5827 (match_operand
2 "aarch64_tls_le_symref" "S")]
5830 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
5831 [(set_attr "type" "multiple")
5832 (set_attr "length" "
8")]
5835 (define_insn "tlsle32_<mode>"
5836 [(set (match_operand:P
0 "register_operand" "=r")
5837 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
5840 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
5841 [(set_attr "type" "multiple")
5842 (set_attr "length" "
8")]
5845 (define_insn "tlsle48_<mode>"
5846 [(set (match_operand:P
0 "register_operand" "=r")
5847 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
5850 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
5851 [(set_attr "type" "multiple")
5852 (set_attr "length" "
12")]
5855 (define_expand "tlsdesc_small_<mode>"
5856 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
5860 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[
0]));
5862 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
5867 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
5869 (define_insn "tlsdesc_small_advsimd_<mode>"
5870 [(set (reg:PTR R0_REGNUM)
5871 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
5873 (clobber (reg:DI LR_REGNUM))
5874 (clobber (reg:CC CC_REGNUM))
5875 (clobber (match_scratch:DI
1 "=r"))]
5876 "TARGET_TLS_DESC && !TARGET_SVE"
5877 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
5878 [(set_attr "type" "call")
5879 (set_attr "length" "
16")])
5881 ;; For SVE, model tlsdesc calls as clobbering all vector and predicate
5882 ;; registers, on top of the usual R0 and LR. In reality the calls
5883 ;; preserve the low
128 bits of the vector registers, but we don't
5884 ;; yet have a way of representing that in the instruction pattern.
5885 (define_insn "tlsdesc_small_sve_<mode>"
5886 [(set (reg:PTR R0_REGNUM)
5887 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
5889 (clobber (reg:DI LR_REGNUM))
5890 (clobber (reg:CC CC_REGNUM))
5891 (clobber (reg:XI V0_REGNUM))
5892 (clobber (reg:XI V4_REGNUM))
5893 (clobber (reg:XI V8_REGNUM))
5894 (clobber (reg:XI V12_REGNUM))
5895 (clobber (reg:XI V16_REGNUM))
5896 (clobber (reg:XI V20_REGNUM))
5897 (clobber (reg:XI V24_REGNUM))
5898 (clobber (reg:XI V28_REGNUM))
5899 (clobber (reg:VNx2BI P0_REGNUM))
5900 (clobber (reg:VNx2BI P1_REGNUM))
5901 (clobber (reg:VNx2BI P2_REGNUM))
5902 (clobber (reg:VNx2BI P3_REGNUM))
5903 (clobber (reg:VNx2BI P4_REGNUM))
5904 (clobber (reg:VNx2BI P5_REGNUM))
5905 (clobber (reg:VNx2BI P6_REGNUM))
5906 (clobber (reg:VNx2BI P7_REGNUM))
5907 (clobber (reg:VNx2BI P8_REGNUM))
5908 (clobber (reg:VNx2BI P9_REGNUM))
5909 (clobber (reg:VNx2BI P10_REGNUM))
5910 (clobber (reg:VNx2BI P11_REGNUM))
5911 (clobber (reg:VNx2BI P12_REGNUM))
5912 (clobber (reg:VNx2BI P13_REGNUM))
5913 (clobber (reg:VNx2BI P14_REGNUM))
5914 (clobber (reg:VNx2BI P15_REGNUM))
5915 (clobber (match_scratch:DI
1 "=r"))]
5916 "TARGET_TLS_DESC && TARGET_SVE"
5917 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
5918 [(set_attr "type" "call")
5919 (set_attr "length" "
16")])
5921 (define_insn "stack_tie"
5922 [(set (mem:BLK (scratch))
5923 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
5924 (match_operand:DI
1 "register_operand" "rk")]
5928 [(set_attr "length" "
0")]
5931 ;; Pointer authentication patterns are always provided. In architecture
5932 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5933 ;; This lets the user write portable software which authenticates pointers
5934 ;; when run on something which implements ARMv8.3-A, and which runs
5935 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5938 ;; Signing/Authenticating R30 using SP as the salt.
5940 (define_insn "<pauth_mnem_prefix>sp"
5941 [(set (reg:DI R30_REGNUM)
5942 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5944 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5947 ;; Signing/Authenticating X17 using X16 as the salt.
5949 (define_insn "<pauth_mnem_prefix>
1716"
5950 [(set (reg:DI R17_REGNUM)
5951 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5953 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5956 ;; Stripping the signature in R30.
5958 (define_insn "xpaclri"
5959 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5961 "hint
\t7 // xpaclri"
5964 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5965 ;; all of memory. This blocks insns from being moved across this point.
5967 (define_insn "blockage"
5968 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
5971 [(set_attr "length" "
0")
5972 (set_attr "type" "block")]
5975 (define_insn "probe_stack_range"
5976 [(set (match_operand:DI
0 "register_operand" "=r")
5977 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
5978 (match_operand:DI
2 "register_operand" "r")]
5979 UNSPECV_PROBE_STACK_RANGE))]
5982 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
5984 [(set_attr "length" "
32")]
5987 ;; Named pattern for expanding thread pointer reference.
5988 (define_expand "get_thread_pointerdi"
5989 [(match_operand:DI
0 "register_operand" "=r")]
5992 rtx tmp = aarch64_load_tp (operands[
0]);
5993 if (tmp != operands[
0])
5994 emit_move_insn (operands[
0], tmp);
5998 ;; Named patterns for stack smashing protection.
5999 (define_expand "stack_protect_set"
6000 [(match_operand
0 "memory_operand")
6001 (match_operand
1 "memory_operand")]
6004 machine_mode mode = GET_MODE (operands[
0]);
6006 emit_insn ((mode == DImode
6007 ? gen_stack_protect_set_di
6008 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
6012 (define_insn "stack_protect_set_<mode>"
6013 [(set (match_operand:PTR
0 "memory_operand" "=m")
6014 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
6016 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
6018 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
6019 [(set_attr "length" "
12")
6020 (set_attr "type" "multiple")])
6022 (define_expand "stack_protect_test"
6023 [(match_operand
0 "memory_operand")
6024 (match_operand
1 "memory_operand")
6029 machine_mode mode = GET_MODE (operands[
0]);
6031 result = gen_reg_rtx(mode);
6033 emit_insn ((mode == DImode
6034 ? gen_stack_protect_test_di
6035 : gen_stack_protect_test_si) (result,
6040 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6041 result, const0_rtx, operands[
2]));
6043 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6044 result, const0_rtx, operands[
2]));
6048 (define_insn "stack_protect_test_<mode>"
6049 [(set (match_operand:PTR
0 "register_operand" "=r")
6050 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
6051 (match_operand:PTR
2 "memory_operand" "m")]
6053 (clobber (match_scratch:PTR
3 "=&r"))]
6055 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
6056 [(set_attr "length" "
12")
6057 (set_attr "type" "multiple")])
6059 ;; Write Floating-point Control Register.
6060 (define_insn "set_fpcr"
6061 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
6064 [(set_attr "type" "mrs")])
6066 ;; Read Floating-point Control Register.
6067 (define_insn "get_fpcr"
6068 [(set (match_operand:SI
0 "register_operand" "=r")
6069 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
6072 [(set_attr "type" "mrs")])
6074 ;; Write Floating-point Status Register.
6075 (define_insn "set_fpsr"
6076 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
6079 [(set_attr "type" "mrs")])
6081 ;; Read Floating-point Status Register.
6082 (define_insn "get_fpsr"
6083 [(set (match_operand:SI
0 "register_operand" "=r")
6084 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
6087 [(set_attr "type" "mrs")])
6090 ;; Define the subtract-one-and-jump insns so loop.c
6091 ;; knows what to generate.
6092 (define_expand "doloop_end"
6093 [(use (match_operand
0 "" "")) ; loop pseudo
6094 (use (match_operand
1 "" ""))] ; label
6095 "optimize >
0 && flag_modulo_sched"
6104 /* Currently SMS relies on the do-loop pattern to recognize loops
6105 where (
1) the control part consists of all insns defining and/or
6106 using a certain 'count' register and (
2) the loop count can be
6107 adjusted by modifying this register prior to the loop.
6108 ??? The possible introduction of a new block to initialize the
6109 new IV can potentially affect branch optimizations. */
6111 if (GET_MODE (operands[
0]) != DImode)
6115 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
6117 cmp = XVECEXP (PATTERN (insn),
0,
0);
6118 cc_reg = SET_DEST (cmp);
6119 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
6120 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
6121 emit_jump_insn (gen_rtx_SET (pc_rtx,
6122 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
6127 ;; Helper for aarch64.c code.
6128 (define_expand "set_clobber_cc"
6129 [(parallel [(set (match_operand
0)
6131 (clobber (reg:CC CC_REGNUM))])])
6134 (include "aarch64-simd.md")
6136 ;; Atomic Operations
6137 (include "atomics.md")
6139 ;; ldp/stp peephole patterns
6140 (include "aarch64-ldpstp.md")
6143 (include "aarch64-sve.md")