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.
91 ;; A couple of call-clobbered registers that we need to reserve when
92 ;; tracking speculation this is not ABI, so is subject to change.
93 (SPECULATION_TRACKER_REGNUM
15)
94 (SPECULATION_SCRATCH_REGNUM
14)
98 (define_c_enum "unspec" [
124 UNSPEC_GOTSMALLPIC28K
202 UNSPEC_SPECULATION_TRACKER
205 (define_c_enum "unspecv" [
206 UNSPECV_EH_RETURN ; Represent EH_RETURN
207 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
208 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
209 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
210 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
211 UNSPECV_BLOCKAGE ; Represent a blockage
212 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
213 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
217 ;; If further include files are added the defintion of MD_INCLUDES
220 (include "constraints.md")
221 (include "predicates.md")
222 (include "iterators.md")
224 ;; -------------------------------------------------------------------
225 ;; Instruction types and attributes
226 ;; -------------------------------------------------------------------
228 ; The "type" attribute is included here from AArch32 backend to be able
229 ; to share pipeline descriptions.
230 (include "../arm/types.md")
232 ;; It is important to set the fp or simd attributes to yes when a pattern
233 ;; alternative uses the FP or SIMD register files, usually signified by use of
234 ;; the 'w' constraint. This will ensure that the alternative will be
235 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
236 ;; architecture extensions. If all the alternatives in a pattern use the
237 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
240 ;; Attribute that specifies whether or not the instruction touches fp
241 ;; registers. When this is set to yes for an alternative, that alternative
242 ;; will be disabled when !TARGET_FLOAT.
243 (define_attr "fp" "no,yes" (const_string "no"))
245 ;; Attribute that specifies whether or not the instruction touches half
246 ;; precision fp registers. When this is set to yes for an alternative,
247 ;; that alternative will be disabled when !TARGET_FP_F16INST.
248 (define_attr "fp16" "no,yes" (const_string "no"))
250 ;; Attribute that specifies whether or not the instruction touches simd
251 ;; registers. When this is set to yes for an alternative, that alternative
252 ;; will be disabled when !TARGET_SIMD.
253 (define_attr "simd" "no,yes" (const_string "no"))
255 ;; Attribute that specifies whether or not the instruction uses SVE.
256 ;; When this is set to yes for an alternative, that alternative
257 ;; will be disabled when !TARGET_SVE.
258 (define_attr "sve" "no,yes" (const_string "no"))
260 ;; Attribute that controls whether an alternative is enabled or not.
261 ;; Currently it is only used to disable alternatives which touch fp or simd
262 ;; registers when -mgeneral-regs-only is specified.
263 (define_attr "enabled" "no,yes"
265 (and (eq_attr "fp" "yes")
266 (eq (symbol_ref "TARGET_FLOAT") (const_int
0)))
267 (and (eq_attr "simd" "yes")
268 (eq (symbol_ref "TARGET_SIMD") (const_int
0)))
269 (and (eq_attr "fp16" "yes")
270 (eq (symbol_ref "TARGET_FP_F16INST") (const_int
0)))
271 (and (eq_attr "sve" "yes")
272 (eq (symbol_ref "TARGET_SVE") (const_int
0))))
274 ] (const_string "yes")))
276 ;; Attribute that specifies whether we are dealing with a branch to a
277 ;; label that is far away, i.e. further away than the maximum/minimum
278 ;; representable in a signed
21-bits number.
281 (define_attr "far_branch" "" (const_int
0))
283 ;; Attribute that specifies whether the alternative uses MOVPRFX.
284 (define_attr "movprfx" "no,yes" (const_string "no"))
286 (define_attr "length" ""
287 (cond [(eq_attr "movprfx" "yes")
291 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
292 ;; no predicated insns.
293 (define_attr "predicated" "yes,no" (const_string "no"))
295 ;; Set to true on an insn that requires the speculation tracking state to be
296 ;; in the tracking register before the insn issues. Otherwise the compiler
297 ;; may chose to hold the tracking state encoded in SP.
298 (define_attr "speculation_barrier" "true,false" (const_string "false"))
300 ;; -------------------------------------------------------------------
301 ;; Pipeline descriptions and scheduling
302 ;; -------------------------------------------------------------------
305 (include "aarch64-tune.md")
308 (include "../arm/cortex-a53.md")
309 (include "../arm/cortex-a57.md")
310 (include "../arm/exynos-m1.md")
311 (include "falkor.md")
312 (include "thunderx.md")
313 (include "../arm/xgene1.md")
314 (include "thunderx2t99.md")
316 ;; -------------------------------------------------------------------
317 ;; Jumps and other miscellaneous insns
318 ;; -------------------------------------------------------------------
320 (define_insn "indirect_jump"
321 [(set (pc) (match_operand:DI
0 "register_operand" "r"))]
324 [(set_attr "type" "branch")]
328 [(set (pc) (label_ref (match_operand
0 "" "")))]
331 [(set_attr "type" "branch")]
334 (define_expand "cbranch<mode>
4"
335 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
336 [(match_operand:GPI
1 "register_operand" "")
337 (match_operand:GPI
2 "aarch64_plus_operand" "")])
338 (label_ref (match_operand
3 "" ""))
342 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
344 operands[
2] = const0_rtx;
348 (define_expand "cbranch<mode>
4"
349 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
350 [(match_operand:GPF
1 "register_operand" "")
351 (match_operand:GPF
2 "aarch64_fp_compare_operand" "")])
352 (label_ref (match_operand
3 "" ""))
356 operands[
1] = aarch64_gen_compare_reg (GET_CODE (operands[
0]), operands[
1],
358 operands[
2] = const0_rtx;
362 (define_expand "cbranchcc4"
363 [(set (pc) (if_then_else
364 (match_operator
0 "aarch64_comparison_operator"
365 [(match_operand
1 "cc_register" "")
366 (match_operand
2 "const0_operand")])
367 (label_ref (match_operand
3 "" ""))
372 (define_insn "ccmp<mode>"
373 [(set (match_operand:CC
1 "cc_register" "")
375 (match_operator
4 "aarch64_comparison_operator"
376 [(match_operand
0 "cc_register" "")
379 (match_operand:GPI
2 "register_operand" "r,r,r")
380 (match_operand:GPI
3 "aarch64_ccmp_operand" "r,Uss,Usn"))
381 (unspec:CC [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
384 ccmp
\\t%<w>
2, %<w>
3, %k5, %m4
385 ccmp
\\t%<w>
2, %
3, %k5, %m4
386 ccmn
\\t%<w>
2, #%n3, %k5, %m4"
387 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
390 (define_insn "fccmp<mode>"
391 [(set (match_operand:CCFP
1 "cc_register" "")
393 (match_operator
4 "aarch64_comparison_operator"
394 [(match_operand
0 "cc_register" "")
397 (match_operand:GPF
2 "register_operand" "w")
398 (match_operand:GPF
3 "register_operand" "w"))
399 (unspec:CCFP [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
401 "fccmp
\\t%<s>
2, %<s>
3, %k5, %m4"
402 [(set_attr "type" "fccmp<s>")]
405 (define_insn "fccmpe<mode>"
406 [(set (match_operand:CCFPE
1 "cc_register" "")
408 (match_operator
4 "aarch64_comparison_operator"
409 [(match_operand
0 "cc_register" "")
412 (match_operand:GPF
2 "register_operand" "w")
413 (match_operand:GPF
3 "register_operand" "w"))
414 (unspec:CCFPE [(match_operand
5 "immediate_operand")] UNSPEC_NZCV)))]
416 "fccmpe
\\t%<s>
2, %<s>
3, %k5, %m4"
417 [(set_attr "type" "fccmp<s>")]
420 ;; Expansion of signed mod by a power of
2 using CSNEG.
421 ;; For x0 % n where n is a power of
2 produce:
423 ;; and x0, x0, #(n -
1)
424 ;; and x1, x1, #(n -
1)
425 ;; csneg x0, x0, x1, mi
427 (define_expand "mod<mode>
3"
428 [(match_operand:GPI
0 "register_operand" "")
429 (match_operand:GPI
1 "register_operand" "")
430 (match_operand:GPI
2 "const_int_operand" "")]
433 HOST_WIDE_INT val = INTVAL (operands[
2]);
436 || exact_log2 (val) <=
0
437 || !aarch64_bitmask_imm (val -
1, <MODE>mode))
440 rtx mask = GEN_INT (val -
1);
442 /* In the special case of x0 %
2 we can do the even shorter:
448 rtx masked = gen_reg_rtx (<MODE>mode);
449 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
450 emit_insn (gen_and<mode>
3 (masked, operands[
1], mask));
451 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
452 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, masked, masked));
456 rtx neg_op = gen_reg_rtx (<MODE>mode);
457 rtx_insn *insn = emit_insn (gen_neg<mode>
2_compare0 (neg_op, operands[
1]));
459 /* Extract the condition register and mode. */
460 rtx cmp = XVECEXP (PATTERN (insn),
0,
0);
461 rtx cc_reg = SET_DEST (cmp);
462 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
464 rtx masked_pos = gen_reg_rtx (<MODE>mode);
465 emit_insn (gen_and<mode>
3 (masked_pos, operands[
1], mask));
467 rtx masked_neg = gen_reg_rtx (<MODE>mode);
468 emit_insn (gen_and<mode>
3 (masked_neg, neg_op, mask));
470 emit_insn (gen_csneg3<mode>_insn (operands[
0], cond,
471 masked_neg, masked_pos));
476 (define_insn "condjump"
477 [(set (pc) (if_then_else (match_operator
0 "aarch64_comparison_operator"
478 [(match_operand
1 "cc_register" "") (const_int
0)])
479 (label_ref (match_operand
2 "" ""))
483 if (get_attr_length (insn) ==
8)
484 return aarch64_gen_far_branch (operands,
2, "Lbcond", "b%M0
\\t");
488 [(set_attr "type" "branch")
490 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
491 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
494 (set (attr "far_branch")
495 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
496 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
501 ;; For a
24-bit immediate CST we can optimize the compare for equality
502 ;; and branch sequence from:
504 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
508 ;; sub x0, x1, #(CST &
0xfff000)
509 ;; subs x0, x0, #(CST &
0x000fff)
511 (define_insn_and_split "*compare_condjump<mode>"
512 [(set (pc) (if_then_else (EQL
513 (match_operand:GPI
0 "register_operand" "r")
514 (match_operand:GPI
1 "aarch64_imm24" "n"))
515 (label_ref:P (match_operand
2 "" ""))
517 "!aarch64_move_imm (INTVAL (operands[
1]), <MODE>mode)
518 && !aarch64_plus_operand (operands[
1], <MODE>mode)
519 && !reload_completed"
524 HOST_WIDE_INT lo_imm = UINTVAL (operands[
1]) &
0xfff;
525 HOST_WIDE_INT hi_imm = UINTVAL (operands[
1]) &
0xfff000;
526 rtx tmp = gen_reg_rtx (<MODE>mode);
527 emit_insn (gen_add<mode>
3 (tmp, operands[
0], GEN_INT (-hi_imm)));
528 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
529 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
530 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
531 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[
2]));
536 (define_expand "casesi"
537 [(match_operand:SI
0 "register_operand" "") ; Index
538 (match_operand:SI
1 "const_int_operand" "") ; Lower bound
539 (match_operand:SI
2 "const_int_operand" "") ; Total range
540 (match_operand:DI
3 "" "") ; Table label
541 (match_operand:DI
4 "" "")] ; Out of range label
544 if (operands[
1] != const0_rtx)
546 rtx reg = gen_reg_rtx (SImode);
548 /* Canonical RTL says that if you have:
552 then this should be emitted as:
556 The use of trunc_int_for_mode ensures that the resulting
557 constant can be represented in SImode, this is important
558 for the corner case where operand[
1] is INT_MIN. */
560 operands[
1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[
1]), SImode));
562 if (!(*insn_data[CODE_FOR_addsi3].operand[
2].predicate)
563 (operands[
1], SImode))
564 operands[
1] = force_reg (SImode, operands[
1]);
565 emit_insn (gen_addsi3 (reg, operands[
0], operands[
1]));
569 if (!aarch64_plus_operand (operands[
2], SImode))
570 operands[
2] = force_reg (SImode, operands[
2]);
571 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
573 operands[
0], operands[
2], operands[
4]));
575 operands[
2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[
3]));
576 emit_jump_insn (gen_casesi_dispatch (operands[
2], operands[
0],
582 (define_insn "casesi_dispatch"
585 (mem:DI (unspec [(match_operand:DI
0 "register_operand" "r")
586 (match_operand:SI
1 "register_operand" "r")]
588 (clobber (reg:CC CC_REGNUM))
589 (clobber (match_scratch:DI
3 "=r"))
590 (clobber (match_scratch:DI
4 "=r"))
591 (use (label_ref (match_operand
2 "" "")))])]
594 return aarch64_output_casesi (operands);
596 [(set_attr "length" "
16")
597 (set_attr "type" "branch")]
601 [(unspec[(const_int
0)] UNSPEC_NOP)]
604 [(set_attr "type" "no_insn")]
607 (define_insn "prefetch"
608 [(prefetch (match_operand:DI
0 "aarch64_prefetch_operand" "Dp")
609 (match_operand:QI
1 "const_int_operand" "")
610 (match_operand:QI
2 "const_int_operand" ""))]
613 const char * pftype[
2][
4] =
615 {"prfm
\\tPLDL1STRM, %
0",
616 "prfm
\\tPLDL3KEEP, %
0",
617 "prfm
\\tPLDL2KEEP, %
0",
618 "prfm
\\tPLDL1KEEP, %
0"},
619 {"prfm
\\tPSTL1STRM, %
0",
620 "prfm
\\tPSTL3KEEP, %
0",
621 "prfm
\\tPSTL2KEEP, %
0",
622 "prfm
\\tPSTL1KEEP, %
0"},
625 int locality = INTVAL (operands[
2]);
627 gcc_assert (IN_RANGE (locality,
0,
3));
629 /* PRFM accepts the same addresses as a
64-bit LDR so wrap
630 the address into a DImode MEM so that aarch64_print_operand knows
632 operands[
0] = gen_rtx_MEM (DImode, operands[
0]);
633 return pftype[INTVAL(operands[
1])][locality];
635 [(set_attr "type" "load_4")]
639 [(trap_if (const_int
1) (const_int
8))]
642 [(set_attr "type" "trap")])
644 (define_expand "prologue"
645 [(clobber (const_int
0))]
648 aarch64_expand_prologue ();
653 (define_expand "epilogue"
654 [(clobber (const_int
0))]
657 aarch64_expand_epilogue (false);
662 (define_expand "sibcall_epilogue"
663 [(clobber (const_int
0))]
666 aarch64_expand_epilogue (true);
671 (define_insn "*do_return"
675 if (aarch64_return_address_signing_enabled ()
677 && !crtl->calls_eh_return)
682 [(set_attr "type" "branch")]
685 (define_expand "return"
687 "aarch64_use_return_insn_p ()"
691 (define_insn "simple_return"
695 [(set_attr "type" "branch")]
698 (define_insn "*cb<optab><mode>
1"
699 [(set (pc) (if_then_else (EQL (match_operand:GPI
0 "register_operand" "r")
701 (label_ref (match_operand
1 "" ""))
703 "!aarch64_track_speculation"
705 if (get_attr_length (insn) ==
8)
706 return aarch64_gen_far_branch (operands,
1, "Lcb", "<inv_cb>
\\t%<w>
0, ");
708 return "<cbz>
\\t%<w>
0, %l1";
710 [(set_attr "type" "branch")
712 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
713 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
716 (set (attr "far_branch")
717 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
718 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
723 (define_insn "*tb<optab><mode>
1"
724 [(set (pc) (if_then_else
725 (EQL (zero_extract:DI (match_operand:GPI
0 "register_operand" "r")
728 "aarch64_simd_shift_imm_<mode>" "n"))
730 (label_ref (match_operand
2 "" ""))
732 (clobber (reg:CC CC_REGNUM))]
733 "!aarch64_track_speculation"
735 if (get_attr_length (insn) ==
8)
737 if (get_attr_far_branch (insn) ==
1)
738 return aarch64_gen_far_branch (operands,
2, "Ltb",
739 "<inv_tb>
\\t%<w>
0, %
1, ");
742 operands[
1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[
1]));
743 return "tst
\t%<w>
0, %
1\;<bcond>
\t%l2";
747 return "<tbz>
\t%<w>
0, %
1, %l2";
749 [(set_attr "type" "branch")
751 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
32768))
752 (lt (minus (match_dup
2) (pc)) (const_int
32764)))
755 (set (attr "far_branch")
756 (if_then_else (and (ge (minus (match_dup
2) (pc)) (const_int -
1048576))
757 (lt (minus (match_dup
2) (pc)) (const_int
1048572)))
763 (define_insn "*cb<optab><mode>
1"
764 [(set (pc) (if_then_else (LTGE (match_operand:ALLI
0 "register_operand" "r")
766 (label_ref (match_operand
1 "" ""))
768 (clobber (reg:CC CC_REGNUM))]
769 "!aarch64_track_speculation"
771 if (get_attr_length (insn) ==
8)
773 if (get_attr_far_branch (insn) ==
1)
774 return aarch64_gen_far_branch (operands,
1, "Ltb",
775 "<inv_tb>
\\t%<w>
0, <sizem1>, ");
779 uint64_t val = ((uint64_t)
1)
780 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT -
1);
781 sprintf (buf, "tst
\t%%<w>
0, %" PRId64, val);
782 output_asm_insn (buf, operands);
783 return "<bcond>
\t%l1";
787 return "<tbz>
\t%<w>
0, <sizem1>, %l1";
789 [(set_attr "type" "branch")
791 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
32768))
792 (lt (minus (match_dup
1) (pc)) (const_int
32764)))
795 (set (attr "far_branch")
796 (if_then_else (and (ge (minus (match_dup
1) (pc)) (const_int -
1048576))
797 (lt (minus (match_dup
1) (pc)) (const_int
1048572)))
802 ;; -------------------------------------------------------------------
803 ;; Subroutine calls and sibcalls
804 ;; -------------------------------------------------------------------
806 (define_expand "call"
807 [(parallel [(call (match_operand
0 "memory_operand" "")
808 (match_operand
1 "general_operand" ""))
809 (use (match_operand
2 "" ""))
810 (clobber (reg:DI LR_REGNUM))])]
814 aarch64_expand_call (NULL_RTX, operands[
0], false);
819 (define_insn "*call_insn"
820 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "r, Usf"))
821 (match_operand
1 "" ""))
822 (clobber (reg:DI LR_REGNUM))]
827 [(set_attr "type" "call, call")]
830 (define_expand "call_value"
831 [(parallel [(set (match_operand
0 "" "")
832 (call (match_operand
1 "memory_operand" "")
833 (match_operand
2 "general_operand" "")))
834 (use (match_operand
3 "" ""))
835 (clobber (reg:DI LR_REGNUM))])]
839 aarch64_expand_call (operands[
0], operands[
1], false);
844 (define_insn "*call_value_insn"
845 [(set (match_operand
0 "" "")
846 (call (mem:DI (match_operand:DI
1 "aarch64_call_insn_operand" "r, Usf"))
847 (match_operand
2 "" "")))
848 (clobber (reg:DI LR_REGNUM))]
853 [(set_attr "type" "call, call")]
856 (define_expand "sibcall"
857 [(parallel [(call (match_operand
0 "memory_operand" "")
858 (match_operand
1 "general_operand" ""))
860 (use (match_operand
2 "" ""))])]
863 aarch64_expand_call (NULL_RTX, operands[
0], true);
868 (define_expand "sibcall_value"
869 [(parallel [(set (match_operand
0 "" "")
870 (call (match_operand
1 "memory_operand" "")
871 (match_operand
2 "general_operand" "")))
873 (use (match_operand
3 "" ""))])]
876 aarch64_expand_call (operands[
0], operands[
1], true);
881 (define_insn "*sibcall_insn"
882 [(call (mem:DI (match_operand:DI
0 "aarch64_call_insn_operand" "Ucs, Usf"))
883 (match_operand
1 "" ""))
885 "SIBLING_CALL_P (insn)"
889 [(set_attr "type" "branch, branch")]
892 (define_insn "*sibcall_value_insn"
893 [(set (match_operand
0 "" "")
895 (match_operand:DI
1 "aarch64_call_insn_operand" "Ucs, Usf"))
896 (match_operand
2 "" "")))
898 "SIBLING_CALL_P (insn)"
902 [(set_attr "type" "branch, branch")]
905 ;; Call subroutine returning any type.
907 (define_expand "untyped_call"
908 [(parallel [(call (match_operand
0 "")
911 (match_operand
2 "")])]
916 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL));
918 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
920 rtx set = XVECEXP (operands[
2],
0, i);
921 emit_move_insn (SET_DEST (set), SET_SRC (set));
924 /* The optimizer does not know that the call sets the function value
925 registers we stored in the result block. We avoid problems by
926 claiming that all hard registers are used and clobbered at this
928 emit_insn (gen_blockage ());
932 ;; -------------------------------------------------------------------
934 ;; -------------------------------------------------------------------
936 (define_expand "mov<mode>"
937 [(set (match_operand:SHORT
0 "nonimmediate_operand" "")
938 (match_operand:SHORT
1 "general_operand" ""))]
941 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
942 operands[
1] = force_reg (<MODE>mode, operands[
1]);
944 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
946 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
952 (define_insn "*mov<mode>_aarch64"
953 [(set (match_operand:SHORT
0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
954 (match_operand:SHORT
1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
955 "(register_operand (operands[
0], <MODE>mode)
956 || aarch64_reg_or_zero (operands[
1], <MODE>mode))"
958 switch (which_alternative)
961 return "mov
\t%w0, %w1";
963 return "mov
\t%w0, %
1";
965 return aarch64_output_scalar_simd_mov_immediate (operands[
1],
968 return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
970 return "ldr<size>
\t%w0, %
1";
972 return "ldr
\t%<size>
0, %
1";
974 return "str<size>
\t%w1, %
0";
976 return "str
\t%<size>
1, %
0";
978 return "umov
\t%w0, %
1.<v>[
0]";
980 return "dup
\t%
0.<Vallxd>, %w1";
982 return "dup
\t%<Vetype>
0, %
1.<v>[
0]";
987 ;; The "mov_imm" type for CNT is just a placeholder.
988 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
989 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
990 (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes")
991 (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")]
994 (define_expand "mov<mode>"
995 [(set (match_operand:GPI
0 "nonimmediate_operand" "")
996 (match_operand:GPI
1 "general_operand" ""))]
999 if (MEM_P (operands[
0]) && CONST_INT_P (operands[
1])
1000 && <MODE>mode == DImode
1001 && aarch64_split_dimode_const_store (operands[
0], operands[
1]))
1004 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1005 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1007 /* FIXME: RR we still need to fix up what we are doing with
1008 symbol_refs and other types of constants. */
1009 if (CONSTANT_P (operands[
1])
1010 && !CONST_INT_P (operands[
1]))
1012 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1018 (define_insn_and_split "*movsi_aarch64"
1019 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1020 (match_operand:SI
1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1021 "(register_operand (operands[
0], SImode)
1022 || aarch64_reg_or_zero (operands[
1], SImode))"
1029 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1039 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);"
1040 "CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), SImode)
1041 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1044 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1047 ;; The "mov_imm" type for CNT is just a placeholder.
1048 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1049 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1050 (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1051 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1052 (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1055 (define_insn_and_split "*movdi_aarch64"
1056 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1057 (match_operand:DI
1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1058 "(register_operand (operands[
0], DImode)
1059 || aarch64_reg_or_zero (operands[
1], DImode))"
1067 * return aarch64_output_sve_cnt_immediate (
\"cnt
\",
\"%x0
\", operands[
1]);
1077 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);"
1078 "(CONST_INT_P (operands[
1]) && !aarch64_move_imm (INTVAL (operands[
1]), DImode))
1079 && REG_P (operands[
0]) && GP_REGNUM_P (REGNO (operands[
0]))"
1082 aarch64_expand_mov_immediate (operands[
0], operands[
1]);
1085 ;; The "mov_imm" type for CNTD is just a placeholder.
1086 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1087 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1089 (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1090 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1091 (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1094 (define_insn "insv_imm<mode>"
1095 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
1097 (match_operand:GPI
1 "const_int_operand" "n"))
1098 (match_operand:GPI
2 "const_int_operand" "n"))]
1099 "UINTVAL (operands[
1]) < GET_MODE_BITSIZE (<MODE>mode)
1100 && UINTVAL (operands[
1]) %
16 ==
0"
1101 "movk
\\t%<w>
0, %X2, lsl %
1"
1102 [(set_attr "type" "mov_imm")]
1105 (define_expand "movti"
1106 [(set (match_operand:TI
0 "nonimmediate_operand" "")
1107 (match_operand:TI
1 "general_operand" ""))]
1110 if (GET_CODE (operands[
0]) == MEM && operands[
1] != const0_rtx)
1111 operands[
1] = force_reg (TImode, operands[
1]);
1113 if (GET_CODE (operands[
1]) == CONST_POLY_INT)
1115 emit_move_insn (gen_lowpart (DImode, operands[
0]),
1116 gen_lowpart (DImode, operands[
1]));
1117 emit_move_insn (gen_highpart (DImode, operands[
0]), const0_rtx);
1123 (define_insn "*movti_aarch64"
1124 [(set (match_operand:TI
0
1125 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1127 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1128 "(register_operand (operands[
0], TImode)
1129 || aarch64_reg_or_zero (operands[
1], TImode))"
1134 mov
\\t%
0.16b, %
1.16b
1140 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1141 load_16,store_16,store_16,\
1143 (set_attr "length" "
8,
8,
8,
4,
4,
4,
4,
4,
4")
1144 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1145 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1148 ;; Split a TImode register-register or register-immediate move into
1149 ;; its component DImode pieces, taking care to handle overlapping
1150 ;; source and dest registers.
1152 [(set (match_operand:TI
0 "register_operand" "")
1153 (match_operand:TI
1 "aarch64_reg_or_imm" ""))]
1154 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1157 aarch64_split_128bit_move (operands[
0], operands[
1]);
1161 (define_expand "mov<mode>"
1162 [(set (match_operand:GPF_TF_F16
0 "nonimmediate_operand" "")
1163 (match_operand:GPF_TF_F16
1 "general_operand" ""))]
1168 aarch64_err_no_fpadvsimd (<MODE>mode);
1172 if (GET_CODE (operands[
0]) == MEM
1173 && ! (GET_CODE (operands[
1]) == CONST_DOUBLE
1174 && aarch64_float_const_zero_rtx_p (operands[
1])))
1175 operands[
1] = force_reg (<MODE>mode, operands[
1]);
1179 (define_insn "*movhf_aarch64"
1180 [(set (match_operand:HF
0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1181 (match_operand:HF
1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1182 "TARGET_FLOAT && (register_operand (operands[
0], HFmode)
1183 || aarch64_reg_or_fp_zero (operands[
1], HFmode))"
1189 mov
\\t%
0.h[
0], %
1.h[
0]
1191 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], HImode);
1197 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1198 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1199 (set_attr "simd" "yes,*,yes,yes,yes,*,yes,*,*,*,*,*")
1200 (set_attr "fp16" "*,yes,*,*,*,yes,*,*,*,*,*,*")]
1203 (define_insn "*movsf_aarch64"
1204 [(set (match_operand:SF
0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1205 (match_operand:SF
1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1206 "TARGET_FLOAT && (register_operand (operands[
0], SFmode)
1207 || aarch64_reg_or_fp_zero (operands[
1], SFmode))"
1214 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], SImode);
1221 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1222 f_loads,f_stores,load_4,store_4,mov_reg,\
1224 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1227 (define_insn "*movdf_aarch64"
1228 [(set (match_operand:DF
0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1229 (match_operand:DF
1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1230 "TARGET_FLOAT && (register_operand (operands[
0], DFmode)
1231 || aarch64_reg_or_fp_zero (operands[
1], DFmode))"
1238 * return aarch64_output_scalar_simd_mov_immediate (operands[
1], DImode);
1245 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1246 f_loadd,f_stored,load_8,store_8,mov_reg,\
1248 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1252 [(set (match_operand:GPF_HF
0 "nonimmediate_operand")
1253 (match_operand:GPF_HF
1 "general_operand"))]
1254 "can_create_pseudo_p ()
1255 && !aarch64_can_const_movi_rtx_p (operands[
1], <MODE>mode)
1256 && !aarch64_float_const_representable_p (operands[
1])
1257 && aarch64_float_const_rtx_p (operands[
1])"
1260 unsigned HOST_WIDE_INT ival;
1261 if (!aarch64_reinterpret_float_as_int (operands[
1], &ival))
1264 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1265 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1266 emit_move_insn (operands[
0], gen_lowpart (<MODE>mode, tmp));
1271 (define_insn "*movtf_aarch64"
1272 [(set (match_operand:TF
0
1273 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1275 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1276 "TARGET_FLOAT && (register_operand (operands[
0], TFmode)
1277 || aarch64_reg_or_fp_zero (operands[
1], TFmode))"
1279 mov
\\t%
0.16b, %
1.16b
1290 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1291 f_loadd,f_stored,load_16,store_16,store_16")
1292 (set_attr "length" "
4,
8,
8,
8,
4,
4,
4,
4,
4,
4,
4")
1293 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1297 [(set (match_operand:TF
0 "register_operand" "")
1298 (match_operand:TF
1 "aarch64_reg_or_imm" ""))]
1299 "reload_completed && aarch64_split_128bit_move_p (operands[
0], operands[
1])"
1302 aarch64_split_128bit_move (operands[
0], operands[
1]);
1309 ;;
2 is size of move in bytes
1312 (define_expand "movmemdi"
1313 [(match_operand:BLK
0 "memory_operand")
1314 (match_operand:BLK
1 "memory_operand")
1315 (match_operand:DI
2 "immediate_operand")
1316 (match_operand:DI
3 "immediate_operand")]
1319 if (aarch64_expand_movmem (operands))
1325 ;; Operands
1 and
3 are tied together by the final condition; so we allow
1326 ;; fairly lax checking on the second memory operation.
1327 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1328 [(set (match_operand:SX
0 "register_operand" "=r,w")
1329 (match_operand:SX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1330 (set (match_operand:SX2
2 "register_operand" "=r,w")
1331 (match_operand:SX2
3 "memory_operand" "m,m"))]
1332 "rtx_equal_p (XEXP (operands[
3],
0),
1333 plus_constant (Pmode,
1334 XEXP (operands[
1],
0),
1335 GET_MODE_SIZE (<SX:MODE>mode)))"
1339 [(set_attr "type" "load_8,neon_load1_2reg")
1340 (set_attr "fp" "*,yes")]
1343 ;; Storing different modes that can still be merged
1344 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1345 [(set (match_operand:DX
0 "register_operand" "=r,w")
1346 (match_operand:DX
1 "aarch64_mem_pair_operand" "Ump,Ump"))
1347 (set (match_operand:DX2
2 "register_operand" "=r,w")
1348 (match_operand:DX2
3 "memory_operand" "m,m"))]
1349 "rtx_equal_p (XEXP (operands[
3],
0),
1350 plus_constant (Pmode,
1351 XEXP (operands[
1],
0),
1352 GET_MODE_SIZE (<DX:MODE>mode)))"
1356 [(set_attr "type" "load_16,neon_load1_2reg")
1357 (set_attr "fp" "*,yes")]
1360 ;; Operands
0 and
2 are tied together by the final condition; so we allow
1361 ;; fairly lax checking on the second memory operation.
1362 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1363 [(set (match_operand:SX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1364 (match_operand:SX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1365 (set (match_operand:SX2
2 "memory_operand" "=m,m")
1366 (match_operand:SX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1367 "rtx_equal_p (XEXP (operands[
2],
0),
1368 plus_constant (Pmode,
1369 XEXP (operands[
0],
0),
1370 GET_MODE_SIZE (<SX:MODE>mode)))"
1374 [(set_attr "type" "store_8,neon_store1_2reg")
1375 (set_attr "fp" "*,yes")]
1378 ;; Storing different modes that can still be merged
1379 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1380 [(set (match_operand:DX
0 "aarch64_mem_pair_operand" "=Ump,Ump")
1381 (match_operand:DX
1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1382 (set (match_operand:DX2
2 "memory_operand" "=m,m")
1383 (match_operand:DX2
3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1384 "rtx_equal_p (XEXP (operands[
2],
0),
1385 plus_constant (Pmode,
1386 XEXP (operands[
0],
0),
1387 GET_MODE_SIZE (<DX:MODE>mode)))"
1391 [(set_attr "type" "store_16,neon_store1_2reg")
1392 (set_attr "fp" "*,yes")]
1395 ;; Load pair with post-index writeback. This is primarily used in function
1397 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1399 [(set (match_operand:P
0 "register_operand" "=k")
1400 (plus:P (match_operand:P
1 "register_operand" "
0")
1401 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1402 (set (match_operand:GPI
2 "register_operand" "=r")
1403 (mem:GPI (match_dup
1)))
1404 (set (match_operand:GPI
3 "register_operand" "=r")
1405 (mem:GPI (plus:P (match_dup
1)
1406 (match_operand:P
5 "const_int_operand" "n"))))])]
1407 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1408 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1409 [(set_attr "type" "load_<ldpstp_sz>")]
1412 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1414 [(set (match_operand:P
0 "register_operand" "=k")
1415 (plus:P (match_operand:P
1 "register_operand" "
0")
1416 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1417 (set (match_operand:GPF
2 "register_operand" "=w")
1418 (mem:GPF (match_dup
1)))
1419 (set (match_operand:GPF
3 "register_operand" "=w")
1420 (mem:GPF (plus:P (match_dup
1)
1421 (match_operand:P
5 "const_int_operand" "n"))))])]
1422 "INTVAL (operands[
5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1423 "ldp
\\t%<w>
2, %<w>
3, [%
1], %
4"
1424 [(set_attr "type" "neon_load1_2reg")]
1427 ;; Store pair with pre-index writeback. This is primarily used in function
1429 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1431 [(set (match_operand:P
0 "register_operand" "=&k")
1432 (plus:P (match_operand:P
1 "register_operand" "
0")
1433 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1434 (set (mem:GPI (plus:P (match_dup
0)
1436 (match_operand:GPI
2 "register_operand" "r"))
1437 (set (mem:GPI (plus:P (match_dup
0)
1438 (match_operand:P
5 "const_int_operand" "n")))
1439 (match_operand:GPI
3 "register_operand" "r"))])]
1440 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1441 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1442 [(set_attr "type" "store_<ldpstp_sz>")]
1445 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1447 [(set (match_operand:P
0 "register_operand" "=&k")
1448 (plus:P (match_operand:P
1 "register_operand" "
0")
1449 (match_operand:P
4 "aarch64_mem_pair_offset" "n")))
1450 (set (mem:GPF (plus:P (match_dup
0)
1452 (match_operand:GPF
2 "register_operand" "w"))
1453 (set (mem:GPF (plus:P (match_dup
0)
1454 (match_operand:P
5 "const_int_operand" "n")))
1455 (match_operand:GPF
3 "register_operand" "w"))])]
1456 "INTVAL (operands[
5]) == INTVAL (operands[
4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1457 "stp
\\t%<w>
2, %<w>
3, [%
0, %
4]!"
1458 [(set_attr "type" "neon_store1_2reg<q>")]
1461 ;; -------------------------------------------------------------------
1462 ;; Sign/Zero extension
1463 ;; -------------------------------------------------------------------
1465 (define_expand "<optab>sidi2"
1466 [(set (match_operand:DI
0 "register_operand")
1467 (ANY_EXTEND:DI (match_operand:SI
1 "nonimmediate_operand")))]
1471 (define_insn "*extendsidi2_aarch64"
1472 [(set (match_operand:DI
0 "register_operand" "=r,r")
1473 (sign_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1478 [(set_attr "type" "extend,load_4")]
1481 (define_insn "*load_pair_extendsidi2_aarch64"
1482 [(set (match_operand:DI
0 "register_operand" "=r")
1483 (sign_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1484 (set (match_operand:DI
2 "register_operand" "=r")
1485 (sign_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1486 "rtx_equal_p (XEXP (operands[
3],
0),
1487 plus_constant (Pmode,
1488 XEXP (operands[
1],
0),
1489 GET_MODE_SIZE (SImode)))"
1490 "ldpsw
\\t%
0, %
2, %
1"
1491 [(set_attr "type" "load_8")]
1494 (define_insn "*zero_extendsidi2_aarch64"
1495 [(set (match_operand:DI
0 "register_operand" "=r,r")
1496 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand" "r,m")))]
1501 [(set_attr "type" "extend,load_4")]
1504 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1505 [(set (match_operand:DI
0 "register_operand" "=r")
1506 (zero_extend:DI (match_operand:SI
1 "aarch64_mem_pair_operand" "Ump")))
1507 (set (match_operand:DI
2 "register_operand" "=r")
1508 (zero_extend:DI (match_operand:SI
3 "memory_operand" "m")))]
1509 "rtx_equal_p (XEXP (operands[
3],
0),
1510 plus_constant (Pmode,
1511 XEXP (operands[
1],
0),
1512 GET_MODE_SIZE (SImode)))"
1513 "ldp
\\t%w0, %w2, %
1"
1514 [(set_attr "type" "load_8")]
1517 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>
2"
1518 [(set (match_operand:GPI
0 "register_operand")
1519 (ANY_EXTEND:GPI (match_operand:SHORT
1 "nonimmediate_operand")))]
1523 (define_insn "*extend<SHORT:mode><GPI:mode>
2_aarch64"
1524 [(set (match_operand:GPI
0 "register_operand" "=r,r")
1525 (sign_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m")))]
1528 sxt<SHORT:size>
\t%<GPI:w>
0, %w1
1529 ldrs<SHORT:size>
\t%<GPI:w>
0, %
1"
1530 [(set_attr "type" "extend,load_4")]
1533 (define_insn "*zero_extend<SHORT:mode><GPI:mode>
2_aarch64"
1534 [(set (match_operand:GPI
0 "register_operand" "=r,r,w")
1535 (zero_extend:GPI (match_operand:SHORT
1 "nonimmediate_operand" "r,m,m")))]
1538 and
\t%<GPI:w>
0, %<GPI:w>
1, <SHORT:short_mask>
1539 ldr<SHORT:size>
\t%w0, %
1
1540 ldr
\t%<SHORT:size>
0, %
1"
1541 [(set_attr "type" "logic_imm,load_4,load_4")]
1544 (define_expand "<optab>qihi2"
1545 [(set (match_operand:HI
0 "register_operand")
1546 (ANY_EXTEND:HI (match_operand:QI
1 "nonimmediate_operand")))]
1550 (define_insn "*extendqihi2_aarch64"
1551 [(set (match_operand:HI
0 "register_operand" "=r,r")
1552 (sign_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1557 [(set_attr "type" "extend,load_4")]
1560 (define_insn "*zero_extendqihi2_aarch64"
1561 [(set (match_operand:HI
0 "register_operand" "=r,r")
1562 (zero_extend:HI (match_operand:QI
1 "nonimmediate_operand" "r,m")))]
1567 [(set_attr "type" "logic_imm,load_4")]
1570 ;; -------------------------------------------------------------------
1571 ;; Simple arithmetic
1572 ;; -------------------------------------------------------------------
1574 (define_expand "add<mode>
3"
1576 (match_operand:GPI
0 "register_operand" "")
1577 (plus:GPI (match_operand:GPI
1 "register_operand" "")
1578 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "")))]
1581 /* If operands[
1] is a subreg extract the inner RTX. */
1582 rtx op1 = REG_P (operands[
1]) ? operands[
1] : SUBREG_REG (operands[
1]);
1584 /* If the constant is too large for a single instruction and isn't frame
1585 based, split off the immediate so it is available for CSE. */
1586 if (!aarch64_plus_immediate (operands[
2], <MODE>mode)
1587 && can_create_pseudo_p ()
1589 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1590 operands[
2] = force_reg (<MODE>mode, operands[
2]);
1591 /* Expand polynomial additions now if the destination is the stack
1592 pointer, since we don't want to use that as a temporary. */
1593 else if (operands[
0] == stack_pointer_rtx
1594 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode))
1596 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1597 operands[
2], NULL_RTX, NULL_RTX);
1602 (define_insn "*add<mode>
3_aarch64"
1604 (match_operand:GPI
0 "register_operand" "=rk,rk,w,rk,r,rk")
1606 (match_operand:GPI
1 "register_operand" "%rk,rk,w,rk,rk,rk")
1607 (match_operand:GPI
2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1610 add
\\t%<w>
0, %<w>
1, %
2
1611 add
\\t%<w>
0, %<w>
1, %<w>
2
1612 add
\\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>
1613 sub
\\t%<w>
0, %<w>
1, #%n2
1615 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);"
1616 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1617 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1618 (set_attr "simd" "*,*,yes,*,*,*")]
1621 ;; zero_extend version of above
1622 (define_insn "*addsi3_aarch64_uxtw"
1624 (match_operand:DI
0 "register_operand" "=rk,rk,rk,r")
1626 (plus:SI (match_operand:SI
1 "register_operand" "%rk,rk,rk,rk")
1627 (match_operand:SI
2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1632 sub
\\t%w0, %w1, #%n2
1634 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1637 ;; If there's a free register, and we can load the constant with a
1638 ;; single instruction, do so. This has a chance to improve scheduling.
1640 [(match_scratch:GPI
3 "r")
1641 (set (match_operand:GPI
0 "register_operand")
1643 (match_operand:GPI
1 "register_operand")
1644 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1645 "aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)"
1646 [(set (match_dup
3) (match_dup
2))
1647 (set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))]
1651 [(match_scratch:SI
3 "r")
1652 (set (match_operand:DI
0 "register_operand")
1655 (match_operand:SI
1 "register_operand")
1656 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1657 "aarch64_move_imm (INTVAL (operands[
2]), SImode)"
1658 [(set (match_dup
3) (match_dup
2))
1659 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
1) (match_dup
3))))]
1662 ;; After peephole2 has had a chance to run, split any remaining long
1663 ;; additions into two add immediates.
1665 [(set (match_operand:GPI
0 "register_operand")
1667 (match_operand:GPI
1 "register_operand")
1668 (match_operand:GPI
2 "aarch64_pluslong_strict_immedate")))]
1669 "epilogue_completed"
1670 [(set (match_dup
0) (plus:GPI (match_dup
1) (match_dup
3)))
1671 (set (match_dup
0) (plus:GPI (match_dup
0) (match_dup
4)))]
1673 HOST_WIDE_INT i = INTVAL (operands[
2]);
1674 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1675 operands[
3] = GEN_INT (i - s);
1676 operands[
4] = GEN_INT (s);
1680 ;; Match addition of polynomial offsets that require one temporary, for which
1681 ;; we can use the early-clobbered destination register. This is a separate
1682 ;; pattern so that the early clobber doesn't affect register allocation
1683 ;; for other forms of addition. However, we still need to provide an
1684 ;; all-register alternative, in case the offset goes out of range after
1685 ;; elimination. For completeness we might as well provide all GPR-based
1686 ;; alternatives from the main pattern.
1688 ;; We don't have a pattern for additions requiring two temporaries since at
1689 ;; present LRA doesn't allow new scratches to be added during elimination.
1690 ;; Such offsets should be rare anyway.
1692 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1693 ;; here would go away. We could just handle all polynomial constants in
1695 (define_insn_and_split "*add<mode>
3_poly_1"
1697 (match_operand:GPI
0 "register_operand" "=r,r,r,r,r,&r")
1699 (match_operand:GPI
1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1700 (match_operand:GPI
2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1701 "TARGET_SVE && operands[
0] != stack_pointer_rtx"
1703 add
\\t%<w>
0, %<w>
1, %
2
1704 add
\\t%<w>
0, %<w>
1, %<w>
2
1705 sub
\\t%<w>
0, %<w>
1, #%n2
1707 * return aarch64_output_sve_addvl_addpl (operands[
0], operands[
1], operands[
2]);
1709 "&& epilogue_completed
1710 && !reg_overlap_mentioned_p (operands[
0], operands[
1])
1711 && aarch64_split_add_offset_immediate (operands[
2], <MODE>mode)"
1714 aarch64_split_add_offset (<MODE>mode, operands[
0], operands[
1],
1715 operands[
2], operands[
0], NULL_RTX);
1718 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1719 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1723 [(set (match_operand:DI
0 "register_operand")
1726 (match_operand:SI
1 "register_operand")
1727 (match_operand:SI
2 "aarch64_pluslong_strict_immedate"))))]
1728 "epilogue_completed"
1729 [(set (match_dup
5) (plus:SI (match_dup
1) (match_dup
3)))
1730 (set (match_dup
0) (zero_extend:DI (plus:SI (match_dup
5) (match_dup
4))))]
1732 HOST_WIDE_INT i = INTVAL (operands[
2]);
1733 HOST_WIDE_INT s = (i >=
0 ? i &
0xfff : -(-i &
0xfff));
1734 operands[
3] = GEN_INT (i - s);
1735 operands[
4] = GEN_INT (s);
1736 operands[
5] = gen_lowpart (SImode, operands[
0]);
1740 (define_expand "addv<mode>
4"
1741 [(match_operand:GPI
0 "register_operand")
1742 (match_operand:GPI
1 "register_operand")
1743 (match_operand:GPI
2 "register_operand")
1744 (label_ref (match_operand
3 "" ""))]
1747 emit_insn (gen_add<mode>
3_compareV (operands[
0], operands[
1], operands[
2]));
1748 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1753 (define_expand "uaddv<mode>
4"
1754 [(match_operand:GPI
0 "register_operand")
1755 (match_operand:GPI
1 "register_operand")
1756 (match_operand:GPI
2 "register_operand")
1757 (label_ref (match_operand
3 "" ""))]
1760 emit_insn (gen_add<mode>
3_compareC (operands[
0], operands[
1], operands[
2]));
1761 aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[
3]);
1766 (define_expand "addti3"
1767 [(set (match_operand:TI
0 "register_operand" "")
1768 (plus:TI (match_operand:TI
1 "register_operand" "")
1769 (match_operand:TI
2 "aarch64_reg_or_imm" "")))]
1772 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1774 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1775 &low_dest, &op1_low, &op2_low,
1776 &high_dest, &op1_high, &op2_high);
1778 if (op2_low == const0_rtx)
1781 if (!aarch64_pluslong_operand (op2_high, DImode))
1782 op2_high = force_reg (DImode, op2_high);
1783 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
1787 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1788 force_reg (DImode, op2_low)));
1789 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
1790 force_reg (DImode, op2_high)));
1793 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1794 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1799 (define_expand "addvti4"
1800 [(match_operand:TI
0 "register_operand" "")
1801 (match_operand:TI
1 "register_operand" "")
1802 (match_operand:TI
2 "aarch64_reg_or_imm" "")
1803 (label_ref (match_operand
3 "" ""))]
1806 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1808 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1809 &low_dest, &op1_low, &op2_low,
1810 &high_dest, &op1_high, &op2_high);
1812 if (op2_low == const0_rtx)
1815 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
1816 force_reg (DImode, op2_high)));
1820 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1821 force_reg (DImode, op2_low)));
1822 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
1823 force_reg (DImode, op2_high)));
1826 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1827 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1829 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
1833 (define_expand "uaddvti4"
1834 [(match_operand:TI
0 "register_operand" "")
1835 (match_operand:TI
1 "register_operand" "")
1836 (match_operand:TI
2 "aarch64_reg_or_imm" "")
1837 (label_ref (match_operand
3 "" ""))]
1840 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1842 aarch64_addti_scratch_regs (operands[
1], operands[
2],
1843 &low_dest, &op1_low, &op2_low,
1844 &high_dest, &op1_high, &op2_high);
1846 if (op2_low == const0_rtx)
1849 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
1850 force_reg (DImode, op2_high)));
1854 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1855 force_reg (DImode, op2_low)));
1856 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
1857 force_reg (DImode, op2_high)));
1860 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
1861 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
1863 aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[
3]);
1867 (define_insn "add<mode>
3_compare0"
1868 [(set (reg:CC_NZ CC_REGNUM)
1870 (plus:GPI (match_operand:GPI
1 "register_operand" "%r,r,r")
1871 (match_operand:GPI
2 "aarch64_plus_operand" "r,I,J"))
1873 (set (match_operand:GPI
0 "register_operand" "=r,r,r")
1874 (plus:GPI (match_dup
1) (match_dup
2)))]
1877 adds
\\t%<w>
0, %<w>
1, %<w>
2
1878 adds
\\t%<w>
0, %<w>
1, %
2
1879 subs
\\t%<w>
0, %<w>
1, #%n2"
1880 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1883 ;; zero_extend version of above
1884 (define_insn "*addsi3_compare0_uxtw"
1885 [(set (reg:CC_NZ CC_REGNUM)
1887 (plus:SI (match_operand:SI
1 "register_operand" "%r,r,r")
1888 (match_operand:SI
2 "aarch64_plus_operand" "r,I,J"))
1890 (set (match_operand:DI
0 "register_operand" "=r,r,r")
1891 (zero_extend:DI (plus:SI (match_dup
1) (match_dup
2))))]
1894 adds
\\t%w0, %w1, %w2
1896 subs
\\t%w0, %w1, #%n2"
1897 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1900 (define_insn "*add<mode>
3_compareC_cconly_imm"
1901 [(set (reg:CC_C CC_REGNUM)
1904 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
1905 (match_operand:<DWI>
2 "const_scalar_int_operand" ""))
1909 (match_operand:GPI
1 "aarch64_plus_immediate" "I,J")))))]
1910 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
2],
1911 <MODE>mode, operands[
1])"
1915 [(set_attr "type" "alus_imm")]
1918 (define_insn "*add<mode>
3_compareC_cconly"
1919 [(set (reg:CC_C CC_REGNUM)
1922 (zero_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
1923 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
1924 (zero_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
1926 "cmn
\\t%<w>
0, %<w>
1"
1927 [(set_attr "type" "alus_sreg")]
1930 (define_insn "*add<mode>
3_compareC_imm"
1931 [(set (reg:CC_C CC_REGNUM)
1934 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r,r"))
1935 (match_operand:<DWI>
3 "const_scalar_int_operand" ""))
1939 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))
1940 (set (match_operand:GPI
0 "register_operand" "=r,r")
1941 (plus:GPI (match_dup
1) (match_dup
2)))]
1942 "aarch64_zero_extend_const_eq (<DWI>mode, operands[
3],
1943 <MODE>mode, operands[
2])"
1945 adds
\\t%<w>
0, %<w>
1, %
2
1946 subs
\\t%<w>
0, %<w>
1, #%n2"
1947 [(set_attr "type" "alus_imm")]
1950 (define_insn "add<mode>
3_compareC"
1951 [(set (reg:CC_C CC_REGNUM)
1954 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
1955 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
1957 (plus:GPI (match_dup
1) (match_dup
2)))))
1958 (set (match_operand:GPI
0 "register_operand" "=r")
1959 (plus:GPI (match_dup
1) (match_dup
2)))]
1961 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
1962 [(set_attr "type" "alus_sreg")]
1965 (define_insn "*add<mode>
3_compareV_cconly_imm"
1966 [(set (reg:CC_V CC_REGNUM)
1969 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r,r"))
1970 (match_operand:<DWI>
1 "const_scalar_int_operand" ""))
1974 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))))]
1975 "INTVAL (operands[
1]) == INTVAL (operands[
2])"
1979 [(set_attr "type" "alus_imm")]
1982 (define_insn "*add<mode>
3_compareV_cconly"
1983 [(set (reg:CC_V CC_REGNUM)
1986 (sign_extend:<DWI> (match_operand:GPI
0 "register_operand" "r"))
1987 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
1988 (sign_extend:<DWI> (plus:GPI (match_dup
0) (match_dup
1)))))]
1990 "cmn
\\t%<w>
0, %<w>
1"
1991 [(set_attr "type" "alus_sreg")]
1994 (define_insn "*add<mode>
3_compareV_imm"
1995 [(set (reg:CC_V CC_REGNUM)
1999 (match_operand:GPI
1 "register_operand" "r,r"))
2000 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J"))
2002 (plus:GPI (match_dup
1) (match_dup
2)))))
2003 (set (match_operand:GPI
0 "register_operand" "=r,r")
2004 (plus:GPI (match_dup
1) (match_dup
2)))]
2007 adds
\\t%<w>
0, %<w>
1, %<w>
2
2008 subs
\\t%<w>
0, %<w>
1, #%n2"
2009 [(set_attr "type" "alus_imm,alus_imm")]
2012 (define_insn "add<mode>
3_compareV"
2013 [(set (reg:CC_V CC_REGNUM)
2016 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r"))
2017 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2018 (sign_extend:<DWI> (plus:GPI (match_dup
1) (match_dup
2)))))
2019 (set (match_operand:GPI
0 "register_operand" "=r")
2020 (plus:GPI (match_dup
1) (match_dup
2)))]
2022 "adds
\\t%<w>
0, %<w>
1, %<w>
2"
2023 [(set_attr "type" "alus_sreg")]
2026 (define_insn "*adds_shift_imm_<mode>"
2027 [(set (reg:CC_NZ CC_REGNUM)
2029 (plus:GPI (ASHIFT:GPI
2030 (match_operand:GPI
1 "register_operand" "r")
2031 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2032 (match_operand:GPI
3 "register_operand" "r"))
2034 (set (match_operand:GPI
0 "register_operand" "=r")
2035 (plus:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))
2038 "adds
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2039 [(set_attr "type" "alus_shift_imm")]
2042 (define_insn "*subs_shift_imm_<mode>"
2043 [(set (reg:CC_NZ CC_REGNUM)
2045 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2047 (match_operand:GPI
2 "register_operand" "r")
2048 (match_operand:QI
3 "aarch64_shift_imm_<mode>" "n")))
2050 (set (match_operand:GPI
0 "register_operand" "=r")
2051 (minus:GPI (match_dup
1)
2052 (ASHIFT:GPI (match_dup
2) (match_dup
3))))]
2054 "subs
\\t%<w>
0, %<w>
1, %<w>
2, <shift> %
3"
2055 [(set_attr "type" "alus_shift_imm")]
2058 (define_insn "*adds_mul_imm_<mode>"
2059 [(set (reg:CC_NZ CC_REGNUM)
2062 (match_operand:GPI
1 "register_operand" "r")
2063 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2064 (match_operand:GPI
3 "register_operand" "r"))
2066 (set (match_operand:GPI
0 "register_operand" "=r")
2067 (plus:GPI (mult:GPI (match_dup
1) (match_dup
2))
2070 "adds
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2071 [(set_attr "type" "alus_shift_imm")]
2074 (define_insn "*subs_mul_imm_<mode>"
2075 [(set (reg:CC_NZ CC_REGNUM)
2077 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2079 (match_operand:GPI
2 "register_operand" "r")
2080 (match_operand:QI
3 "aarch64_pwr_2_<mode>" "n")))
2082 (set (match_operand:GPI
0 "register_operand" "=r")
2083 (minus:GPI (match_dup
1)
2084 (mult:GPI (match_dup
2) (match_dup
3))))]
2086 "subs
\\t%<w>
0, %<w>
1, %<w>
2, lsl %p3"
2087 [(set_attr "type" "alus_shift_imm")]
2090 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2091 [(set (reg:CC_NZ CC_REGNUM)
2094 (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2095 (match_operand:GPI
2 "register_operand" "r"))
2097 (set (match_operand:GPI
0 "register_operand" "=r")
2098 (plus:GPI (ANY_EXTEND:GPI (match_dup
1)) (match_dup
2)))]
2100 "adds
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2101 [(set_attr "type" "alus_ext")]
2104 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2105 [(set (reg:CC_NZ CC_REGNUM)
2107 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2109 (match_operand:ALLX
2 "register_operand" "r")))
2111 (set (match_operand:GPI
0 "register_operand" "=r")
2112 (minus:GPI (match_dup
1) (ANY_EXTEND:GPI (match_dup
2))))]
2114 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2115 [(set_attr "type" "alus_ext")]
2118 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2119 [(set (reg:CC_NZ CC_REGNUM)
2121 (plus:GPI (ashift:GPI
2123 (match_operand:ALLX
1 "register_operand" "r"))
2124 (match_operand
2 "aarch64_imm3" "Ui3"))
2125 (match_operand:GPI
3 "register_operand" "r"))
2127 (set (match_operand:GPI
0 "register_operand" "=rk")
2128 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup
1))
2132 "adds
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2133 [(set_attr "type" "alus_ext")]
2136 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2137 [(set (reg:CC_NZ CC_REGNUM)
2139 (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2142 (match_operand:ALLX
2 "register_operand" "r"))
2143 (match_operand
3 "aarch64_imm3" "Ui3")))
2145 (set (match_operand:GPI
0 "register_operand" "=rk")
2146 (minus:GPI (match_dup
1)
2147 (ashift:GPI (ANY_EXTEND:GPI (match_dup
2))
2150 "subs
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2151 [(set_attr "type" "alus_ext")]
2154 (define_insn "*adds_<optab><mode>_multp2"
2155 [(set (reg:CC_NZ CC_REGNUM)
2157 (plus:GPI (ANY_EXTRACT:GPI
2158 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2159 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2160 (match_operand
3 "const_int_operand" "n")
2162 (match_operand:GPI
4 "register_operand" "r"))
2164 (set (match_operand:GPI
0 "register_operand" "=r")
2165 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup
1) (match_dup
2))
2169 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2170 "adds
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2171 [(set_attr "type" "alus_ext")]
2174 (define_insn "*subs_<optab><mode>_multp2"
2175 [(set (reg:CC_NZ CC_REGNUM)
2177 (minus:GPI (match_operand:GPI
4 "register_operand" "r")
2179 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2180 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2181 (match_operand
3 "const_int_operand" "n")
2184 (set (match_operand:GPI
0 "register_operand" "=r")
2185 (minus:GPI (match_dup
4) (ANY_EXTRACT:GPI
2186 (mult:GPI (match_dup
1) (match_dup
2))
2189 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2190 "subs
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2191 [(set_attr "type" "alus_ext")]
2194 (define_insn "*add<mode>
3nr_compare0"
2195 [(set (reg:CC_NZ CC_REGNUM)
2197 (plus:GPI (match_operand:GPI
0 "register_operand" "%r,r,r")
2198 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J"))
2205 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2208 (define_insn "aarch64_sub<mode>_compare0"
2209 [(set (reg:CC_NZ CC_REGNUM)
2211 (minus:GPI (match_operand:GPI
0 "register_operand" "r")
2212 (match_operand:GPI
1 "aarch64_plus_operand" "r"))
2215 "cmp
\\t%<w>
0, %<w>
1"
2216 [(set_attr "type" "alus_sreg")]
2219 (define_insn "*compare_neg<mode>"
2220 [(set (reg:CC_Z CC_REGNUM)
2222 (neg:GPI (match_operand:GPI
0 "register_operand" "r"))
2223 (match_operand:GPI
1 "register_operand" "r")))]
2225 "cmn
\\t%<w>
1, %<w>
0"
2226 [(set_attr "type" "alus_sreg")]
2229 (define_insn "*add_<shift>_<mode>"
2230 [(set (match_operand:GPI
0 "register_operand" "=r")
2231 (plus:GPI (ASHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
2232 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
2233 (match_operand:GPI
3 "register_operand" "r")))]
2235 "add
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2236 [(set_attr "type" "alu_shift_imm")]
2239 ;; zero_extend version of above
2240 (define_insn "*add_<shift>_si_uxtw"
2241 [(set (match_operand:DI
0 "register_operand" "=r")
2243 (plus:SI (ASHIFT:SI (match_operand:SI
1 "register_operand" "r")
2244 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
2245 (match_operand:SI
3 "register_operand" "r"))))]
2247 "add
\\t%w0, %w3, %w1, <shift> %
2"
2248 [(set_attr "type" "alu_shift_imm")]
2251 (define_insn "*add_mul_imm_<mode>"
2252 [(set (match_operand:GPI
0 "register_operand" "=r")
2253 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2254 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))
2255 (match_operand:GPI
3 "register_operand" "r")))]
2257 "add
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2258 [(set_attr "type" "alu_shift_imm")]
2261 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2262 [(set (match_operand:GPI
0 "register_operand" "=rk")
2263 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX
1 "register_operand" "r"))
2264 (match_operand:GPI
2 "register_operand" "r")))]
2266 "add
\\t%<GPI:w>
0, %<GPI:w>
2, %<GPI:w>
1, <su>xt<ALLX:size>"
2267 [(set_attr "type" "alu_ext")]
2270 ;; zero_extend version of above
2271 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2272 [(set (match_operand:DI
0 "register_operand" "=rk")
2274 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT
1 "register_operand" "r"))
2275 (match_operand:GPI
2 "register_operand" "r"))))]
2277 "add
\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2278 [(set_attr "type" "alu_ext")]
2281 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2282 [(set (match_operand:GPI
0 "register_operand" "=rk")
2283 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2284 (match_operand:ALLX
1 "register_operand" "r"))
2285 (match_operand
2 "aarch64_imm3" "Ui3"))
2286 (match_operand:GPI
3 "register_operand" "r")))]
2288 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %
2"
2289 [(set_attr "type" "alu_ext")]
2292 ;; zero_extend version of above
2293 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2294 [(set (match_operand:DI
0 "register_operand" "=rk")
2296 (plus:SI (ashift:SI (ANY_EXTEND:SI
2297 (match_operand:SHORT
1 "register_operand" "r"))
2298 (match_operand
2 "aarch64_imm3" "Ui3"))
2299 (match_operand:SI
3 "register_operand" "r"))))]
2301 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %
2"
2302 [(set_attr "type" "alu_ext")]
2305 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2306 [(set (match_operand:GPI
0 "register_operand" "=rk")
2307 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2308 (match_operand:ALLX
1 "register_operand" "r"))
2309 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2310 (match_operand:GPI
3 "register_operand" "r")))]
2312 "add
\\t%<GPI:w>
0, %<GPI:w>
3, %<GPI:w>
1, <su>xt<ALLX:size> %p2"
2313 [(set_attr "type" "alu_ext")]
2316 ;; zero_extend version of above
2317 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2318 [(set (match_operand:DI
0 "register_operand" "=rk")
2319 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2320 (match_operand:SHORT
1 "register_operand" "r"))
2321 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2322 (match_operand:SI
3 "register_operand" "r"))))]
2324 "add
\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2325 [(set_attr "type" "alu_ext")]
2328 (define_insn "*add_<optab><mode>_multp2"
2329 [(set (match_operand:GPI
0 "register_operand" "=rk")
2330 (plus:GPI (ANY_EXTRACT:GPI
2331 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2332 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2333 (match_operand
3 "const_int_operand" "n")
2335 (match_operand:GPI
4 "register_operand" "r")))]
2336 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2337 "add
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2338 [(set_attr "type" "alu_ext")]
2341 ;; zero_extend version of above
2342 (define_insn "*add_<optab>si_multp2_uxtw"
2343 [(set (match_operand:DI
0 "register_operand" "=rk")
2345 (plus:SI (ANY_EXTRACT:SI
2346 (mult:SI (match_operand:SI
1 "register_operand" "r")
2347 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2348 (match_operand
3 "const_int_operand" "n")
2350 (match_operand:SI
4 "register_operand" "r"))))]
2351 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2352 "add
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2353 [(set_attr "type" "alu_ext")]
2356 (define_expand "add<mode>
3_carryin"
2357 [(set (match_operand:GPI
0 "register_operand")
2360 (ne:GPI (reg:CC_C CC_REGNUM) (const_int
0))
2361 (match_operand:GPI
1 "aarch64_reg_or_zero"))
2362 (match_operand:GPI
2 "aarch64_reg_or_zero")))]
2367 ;; Note that add with carry with two zero inputs is matched by cset,
2368 ;; and that add with carry with one zero input is matched by cinc.
2370 (define_insn "*add<mode>
3_carryin"
2371 [(set (match_operand:GPI
0 "register_operand" "=r")
2374 (match_operand:GPI
3 "aarch64_carry_operation" "")
2375 (match_operand:GPI
1 "register_operand" "r"))
2376 (match_operand:GPI
2 "register_operand" "r")))]
2378 "adc
\\t%<w>
0, %<w>
1, %<w>
2"
2379 [(set_attr "type" "adc_reg")]
2382 ;; zero_extend version of above
2383 (define_insn "*addsi3_carryin_uxtw"
2384 [(set (match_operand:DI
0 "register_operand" "=r")
2388 (match_operand:SI
3 "aarch64_carry_operation" "")
2389 (match_operand:SI
1 "register_operand" "r"))
2390 (match_operand:SI
2 "register_operand" "r"))))]
2392 "adc
\\t%w0, %w1, %w2"
2393 [(set_attr "type" "adc_reg")]
2396 (define_expand "add<mode>
3_carryinC"
2404 (match_operand:GPI
1 "register_operand" "")))
2406 (match_operand:GPI
2 "register_operand" "")))
2409 (plus:GPI (match_dup
5) (match_dup
1))
2411 (set (match_operand:GPI
0 "register_operand")
2413 (plus:GPI (match_dup
5) (match_dup
1))
2417 operands[
3] = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2418 operands[
4] = gen_rtx_NE (<DWI>mode, operands[
3], const0_rtx);
2419 operands[
5] = gen_rtx_NE (<MODE>mode, operands[
3], const0_rtx);
2422 (define_insn "*add<mode>
3_carryinC_zero"
2423 [(set (reg:CC_C CC_REGNUM)
2426 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2427 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2430 (match_operand:GPI
3 "aarch64_carry_operation" "")
2432 (set (match_operand:GPI
0 "register_operand")
2433 (plus:GPI (match_dup
3) (match_dup
1)))]
2435 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2436 [(set_attr "type" "adc_reg")]
2439 (define_insn "*add<mode>
3_carryinC"
2440 [(set (reg:CC_C CC_REGNUM)
2444 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2445 (zero_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2446 (zero_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2450 (match_operand:GPI
4 "aarch64_carry_operation" "")
2453 (set (match_operand:GPI
0 "register_operand")
2455 (plus:GPI (match_dup
4) (match_dup
1))
2458 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2459 [(set_attr "type" "adc_reg")]
2462 (define_expand "add<mode>
3_carryinV"
2464 [(set (reg:CC_V CC_REGNUM)
2470 (match_operand:GPI
1 "register_operand" "")))
2472 (match_operand:GPI
2 "register_operand" "")))
2475 (plus:GPI (match_dup
4) (match_dup
1))
2477 (set (match_operand:GPI
0 "register_operand")
2479 (plus:GPI (match_dup
4) (match_dup
1))
2483 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2484 operands[
3] = gen_rtx_NE (<DWI>mode, cc, const0_rtx);
2485 operands[
4] = gen_rtx_NE (<MODE>mode, cc, const0_rtx);
2488 (define_insn "*add<mode>
3_carryinV_zero"
2489 [(set (reg:CC_V CC_REGNUM)
2492 (match_operand:<DWI>
2 "aarch64_carry_operation" "")
2493 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2496 (match_operand:GPI
3 "aarch64_carry_operation" "")
2498 (set (match_operand:GPI
0 "register_operand")
2499 (plus:GPI (match_dup
3) (match_dup
1)))]
2501 "adcs
\\t%<w>
0, %<w>
1, <w>zr"
2502 [(set_attr "type" "adc_reg")]
2505 (define_insn "*add<mode>
3_carryinV"
2506 [(set (reg:CC_V CC_REGNUM)
2510 (match_operand:<DWI>
3 "aarch64_carry_operation" "")
2511 (sign_extend:<DWI> (match_operand:GPI
1 "register_operand" "r")))
2512 (sign_extend:<DWI> (match_operand:GPI
2 "register_operand" "r")))
2516 (match_operand:GPI
4 "aarch64_carry_operation" "")
2519 (set (match_operand:GPI
0 "register_operand")
2521 (plus:GPI (match_dup
4) (match_dup
1))
2524 "adcs
\\t%<w>
0, %<w>
1, %<w>
2"
2525 [(set_attr "type" "adc_reg")]
2528 (define_insn "*add_uxt<mode>_shift2"
2529 [(set (match_operand:GPI
0 "register_operand" "=rk")
2531 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
2532 (match_operand
2 "aarch64_imm3" "Ui3"))
2533 (match_operand
3 "const_int_operand" "n"))
2534 (match_operand:GPI
4 "register_operand" "r")))]
2535 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2537 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[
2]),
2538 INTVAL (operands[
3])));
2539 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
2540 [(set_attr "type" "alu_ext")]
2543 ;; zero_extend version of above
2544 (define_insn "*add_uxtsi_shift2_uxtw"
2545 [(set (match_operand:DI
0 "register_operand" "=rk")
2548 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2549 (match_operand
2 "aarch64_imm3" "Ui3"))
2550 (match_operand
3 "const_int_operand" "n"))
2551 (match_operand:SI
4 "register_operand" "r"))))]
2552 "aarch64_uxt_size (INTVAL (operands[
2]), INTVAL (operands[
3])) !=
0"
2554 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
2555 INTVAL (operands[
3])));
2556 return
\"add
\t%w0, %w4, %w1, uxt%e3 %
2\";"
2557 [(set_attr "type" "alu_ext")]
2560 (define_insn "*add_uxt<mode>_multp2"
2561 [(set (match_operand:GPI
0 "register_operand" "=rk")
2563 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2564 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2565 (match_operand
3 "const_int_operand" "n"))
2566 (match_operand:GPI
4 "register_operand" "r")))]
2567 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2569 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2570 INTVAL (operands[
3])));
2571 return
\"add
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
2572 [(set_attr "type" "alu_ext")]
2575 ;; zero_extend version of above
2576 (define_insn "*add_uxtsi_multp2_uxtw"
2577 [(set (match_operand:DI
0 "register_operand" "=rk")
2580 (mult:SI (match_operand:SI
1 "register_operand" "r")
2581 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2582 (match_operand
3 "const_int_operand" "n"))
2583 (match_operand:SI
4 "register_operand" "r"))))]
2584 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])), INTVAL (operands[
3])) !=
0"
2586 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
2587 INTVAL (operands[
3])));
2588 return
\"add
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
2589 [(set_attr "type" "alu_ext")]
2592 (define_insn "subsi3"
2593 [(set (match_operand:SI
0 "register_operand" "=rk")
2594 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2595 (match_operand:SI
2 "register_operand" "r")))]
2597 "sub
\\t%w0, %w1, %w2"
2598 [(set_attr "type" "alu_sreg")]
2601 ;; zero_extend version of above
2602 (define_insn "*subsi3_uxtw"
2603 [(set (match_operand:DI
0 "register_operand" "=rk")
2605 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2606 (match_operand:SI
2 "register_operand" "r"))))]
2608 "sub
\\t%w0, %w1, %w2"
2609 [(set_attr "type" "alu_sreg")]
2612 (define_insn "subdi3"
2613 [(set (match_operand:DI
0 "register_operand" "=rk,w")
2614 (minus:DI (match_operand:DI
1 "register_operand" "rk,w")
2615 (match_operand:DI
2 "register_operand" "r,w")))]
2619 sub
\\t%d0, %d1, %d2"
2620 [(set_attr "type" "alu_sreg, neon_sub")
2621 (set_attr "simd" "*,yes")]
2624 (define_expand "subv<mode>
4"
2625 [(match_operand:GPI
0 "register_operand")
2626 (match_operand:GPI
1 "aarch64_reg_or_zero")
2627 (match_operand:GPI
2 "aarch64_reg_or_zero")
2628 (label_ref (match_operand
3 "" ""))]
2631 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2632 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2637 (define_expand "usubv<mode>
4"
2638 [(match_operand:GPI
0 "register_operand")
2639 (match_operand:GPI
1 "aarch64_reg_or_zero")
2640 (match_operand:GPI
2 "aarch64_reg_or_zero")
2641 (label_ref (match_operand
3 "" ""))]
2644 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1], operands[
2]));
2645 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2650 (define_expand "subti3"
2651 [(set (match_operand:TI
0 "register_operand" "")
2652 (minus:TI (match_operand:TI
1 "aarch64_reg_or_zero" "")
2653 (match_operand:TI
2 "register_operand" "")))]
2656 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2658 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2659 &low_dest, &op1_low, &op2_low,
2660 &high_dest, &op1_high, &op2_high);
2662 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2663 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2665 emit_move_insn (gen_lowpart (DImode, operands[
0]), low_dest);
2666 emit_move_insn (gen_highpart (DImode, operands[
0]), high_dest);
2670 (define_expand "subvti4"
2671 [(match_operand:TI
0 "register_operand")
2672 (match_operand:TI
1 "aarch64_reg_or_zero")
2673 (match_operand:TI
2 "aarch64_reg_or_imm")
2674 (label_ref (match_operand
3 "" ""))]
2677 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2679 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2680 &low_dest, &op1_low, &op2_low,
2681 &high_dest, &op1_high, &op2_high);
2682 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2683 high_dest, op1_high, op2_high);
2685 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[
3]);
2689 (define_expand "usubvti4"
2690 [(match_operand:TI
0 "register_operand")
2691 (match_operand:TI
1 "aarch64_reg_or_zero")
2692 (match_operand:TI
2 "aarch64_reg_or_imm")
2693 (label_ref (match_operand
3 "" ""))]
2696 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2698 aarch64_subvti_scratch_regs (operands[
1], operands[
2],
2699 &low_dest, &op1_low, &op2_low,
2700 &high_dest, &op1_high, &op2_high);
2701 aarch64_expand_subvti (operands[
0], low_dest, op1_low, op2_low,
2702 high_dest, op1_high, op2_high);
2704 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[
3]);
2708 (define_insn "*sub<mode>
3_compare0"
2709 [(set (reg:CC_NZ CC_REGNUM)
2710 (compare:CC_NZ (minus:GPI (match_operand:GPI
1 "register_operand" "r")
2711 (match_operand:GPI
2 "register_operand" "r"))
2713 (set (match_operand:GPI
0 "register_operand" "=r")
2714 (minus:GPI (match_dup
1) (match_dup
2)))]
2716 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2717 [(set_attr "type" "alus_sreg")]
2720 ;; zero_extend version of above
2721 (define_insn "*subsi3_compare0_uxtw"
2722 [(set (reg:CC_NZ CC_REGNUM)
2723 (compare:CC_NZ (minus:SI (match_operand:SI
1 "register_operand" "r")
2724 (match_operand:SI
2 "register_operand" "r"))
2726 (set (match_operand:DI
0 "register_operand" "=r")
2727 (zero_extend:DI (minus:SI (match_dup
1) (match_dup
2))))]
2729 "subs
\\t%w0, %w1, %w2"
2730 [(set_attr "type" "alus_sreg")]
2733 (define_insn "*sub<mode>
3_compare1_imm"
2734 [(set (reg:CC CC_REGNUM)
2736 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ,rZ")
2737 (match_operand:GPI
2 "aarch64_plus_immediate" "I,J")))
2738 (set (match_operand:GPI
0 "register_operand" "=r,r")
2741 (match_operand:GPI
3 "aarch64_plus_immediate" "J,I")))]
2742 "UINTVAL (operands[
2]) == -UINTVAL (operands[
3])"
2744 subs
\\t%<w>
0, %<w>
1, #%n3
2745 adds
\\t%<w>
0, %<w>
1, %
3"
2746 [(set_attr "type" "alus_imm")]
2749 (define_insn "sub<mode>
3_compare1"
2750 [(set (reg:CC CC_REGNUM)
2752 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2753 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))
2754 (set (match_operand:GPI
0 "register_operand" "=r")
2755 (minus:GPI (match_dup
1) (match_dup
2)))]
2757 "subs
\\t%<w>
0, %<w>
1, %<w>
2"
2758 [(set_attr "type" "alus_sreg")]
2761 (define_insn "sub<mode>
3_compare1_imm"
2762 [(set (reg:CC CC_REGNUM)
2764 (match_operand:GPI
1 "register_operand" "r")
2765 (match_operand:GPI
3 "const_int_operand" "n")))
2766 (set (match_operand:GPI
0 "register_operand" "=r")
2767 (plus:GPI (match_dup
1)
2768 (match_operand:GPI
2 "aarch64_sub_immediate" "J")))]
2769 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2770 "subs
\\t%<w>
0, %<w>
1, #%n2"
2771 [(set_attr "type" "alus_sreg")]
2775 [(set (match_operand:GPI
0 "register_operand")
2776 (minus:GPI (match_operand:GPI
1 "aarch64_reg_or_zero")
2777 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2778 (set (reg:CC CC_REGNUM)
2782 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2783 && !reg_overlap_mentioned_p (operands[
0], operands[
2])"
2786 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2792 ;; Same as the above peephole but with the compare and minus in
2793 ;; swapped order. The restriction on overlap between operand
0
2794 ;; and operands
1 and
2 doesn't apply here.
2796 [(set (reg:CC CC_REGNUM)
2798 (match_operand:GPI
1 "aarch64_reg_or_zero")
2799 (match_operand:GPI
2 "aarch64_reg_or_zero")))
2800 (set (match_operand:GPI
0 "register_operand")
2801 (minus:GPI (match_dup
1)
2806 emit_insn (gen_sub<mode>
3_compare1 (operands[
0], operands[
1],
2813 [(set (match_operand:GPI
0 "register_operand")
2814 (plus:GPI (match_operand:GPI
1 "register_operand")
2815 (match_operand:GPI
2 "aarch64_sub_immediate")))
2816 (set (reg:CC CC_REGNUM)
2819 (match_operand:GPI
3 "const_int_operand")))]
2820 "!reg_overlap_mentioned_p (operands[
0], operands[
1])
2821 && INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2824 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2825 operands[
2], operands[
3]));
2830 ;; Same as the above peephole but with the compare and minus in
2831 ;; swapped order. The restriction on overlap between operand
0
2832 ;; and operands
1 doesn't apply here.
2834 [(set (reg:CC CC_REGNUM)
2836 (match_operand:GPI
1 "register_operand")
2837 (match_operand:GPI
3 "const_int_operand")))
2838 (set (match_operand:GPI
0 "register_operand")
2839 (plus:GPI (match_dup
1)
2840 (match_operand:GPI
2 "aarch64_sub_immediate")))]
2841 "INTVAL (operands[
3]) == -INTVAL (operands[
2])"
2844 emit_insn (gen_sub<mode>
3_compare1_imm (operands[
0], operands[
1],
2845 operands[
2], operands[
3]));
2850 (define_insn "*sub_<shift>_<mode>"
2851 [(set (match_operand:GPI
0 "register_operand" "=r")
2852 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2854 (match_operand:GPI
1 "register_operand" "r")
2855 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
2857 "sub
\\t%<w>
0, %<w>
3, %<w>
1, <shift> %
2"
2858 [(set_attr "type" "alu_shift_imm")]
2861 ;; zero_extend version of above
2862 (define_insn "*sub_<shift>_si_uxtw"
2863 [(set (match_operand:DI
0 "register_operand" "=r")
2865 (minus:SI (match_operand:SI
3 "register_operand" "r")
2867 (match_operand:SI
1 "register_operand" "r")
2868 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
2870 "sub
\\t%w0, %w3, %w1, <shift> %
2"
2871 [(set_attr "type" "alu_shift_imm")]
2874 (define_insn "*sub_mul_imm_<mode>"
2875 [(set (match_operand:GPI
0 "register_operand" "=r")
2876 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
2878 (match_operand:GPI
1 "register_operand" "r")
2879 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
2881 "sub
\\t%<w>
0, %<w>
3, %<w>
1, lsl %p2"
2882 [(set_attr "type" "alu_shift_imm")]
2885 ;; zero_extend version of above
2886 (define_insn "*sub_mul_imm_si_uxtw"
2887 [(set (match_operand:DI
0 "register_operand" "=r")
2889 (minus:SI (match_operand:SI
3 "register_operand" "r")
2891 (match_operand:SI
1 "register_operand" "r")
2892 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
2894 "sub
\\t%w0, %w3, %w1, lsl %p2"
2895 [(set_attr "type" "alu_shift_imm")]
2898 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2899 [(set (match_operand:GPI
0 "register_operand" "=rk")
2900 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2902 (match_operand:ALLX
2 "register_operand" "r"))))]
2904 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size>"
2905 [(set_attr "type" "alu_ext")]
2908 ;; zero_extend version of above
2909 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2910 [(set (match_operand:DI
0 "register_operand" "=rk")
2912 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2914 (match_operand:SHORT
2 "register_operand" "r")))))]
2916 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2917 [(set_attr "type" "alu_ext")]
2920 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2921 [(set (match_operand:GPI
0 "register_operand" "=rk")
2922 (minus:GPI (match_operand:GPI
1 "register_operand" "rk")
2923 (ashift:GPI (ANY_EXTEND:GPI
2924 (match_operand:ALLX
2 "register_operand" "r"))
2925 (match_operand
3 "aarch64_imm3" "Ui3"))))]
2927 "sub
\\t%<GPI:w>
0, %<GPI:w>
1, %<GPI:w>
2, <su>xt<ALLX:size> %
3"
2928 [(set_attr "type" "alu_ext")]
2931 ;; zero_extend version of above
2932 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2933 [(set (match_operand:DI
0 "register_operand" "=rk")
2935 (minus:SI (match_operand:SI
1 "register_operand" "rk")
2936 (ashift:SI (ANY_EXTEND:SI
2937 (match_operand:SHORT
2 "register_operand" "r"))
2938 (match_operand
3 "aarch64_imm3" "Ui3")))))]
2940 "sub
\\t%w0, %w1, %w2, <su>xt<SHORT:size> %
3"
2941 [(set_attr "type" "alu_ext")]
2944 (define_insn "*sub_<optab><mode>_multp2"
2945 [(set (match_operand:GPI
0 "register_operand" "=rk")
2946 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
2948 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
2949 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2950 (match_operand
3 "const_int_operand" "n")
2952 "aarch64_is_extend_from_extract (<MODE>mode, operands[
2], operands[
3])"
2953 "sub
\\t%<w>
0, %<w>
4, %<w>
1, <su>xt%e3 %p2"
2954 [(set_attr "type" "alu_ext")]
2957 ;; zero_extend version of above
2958 (define_insn "*sub_<optab>si_multp2_uxtw"
2959 [(set (match_operand:DI
0 "register_operand" "=rk")
2961 (minus:SI (match_operand:SI
4 "register_operand" "rk")
2963 (mult:SI (match_operand:SI
1 "register_operand" "r")
2964 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
2965 (match_operand
3 "const_int_operand" "n")
2967 "aarch64_is_extend_from_extract (SImode, operands[
2], operands[
3])"
2968 "sub
\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2969 [(set_attr "type" "alu_ext")]
2972 ;; The hardware description is op1 + ~op2 + C.
2973 ;; = op1 + (-op2 +
1) + (
1 - !C)
2974 ;; = op1 - op2 -
1 +
1 - !C
2975 ;; = op1 - op2 - !C.
2976 ;; We describe the latter.
2978 (define_insn "*sub<mode>
3_carryin0"
2979 [(set (match_operand:GPI
0 "register_operand" "=r")
2981 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
2982 (match_operand:GPI
2 "aarch64_borrow_operation" "")))]
2984 "sbc
\\t%<w>
0, %<w>
1, <w>zr"
2985 [(set_attr "type" "adc_reg")]
2988 ;; zero_extend version of the above
2989 (define_insn "*subsi3_carryin_uxtw"
2990 [(set (match_operand:DI
0 "register_operand" "=r")
2993 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
2994 (match_operand:SI
2 "aarch64_borrow_operation" ""))))]
2996 "sbc
\\t%w0, %w1, wzr"
2997 [(set_attr "type" "adc_reg")]
3000 (define_expand "sub<mode>
3_carryin"
3001 [(set (match_operand:GPI
0 "register_operand")
3004 (match_operand:GPI
1 "aarch64_reg_or_zero")
3005 (match_operand:GPI
2 "register_operand"))
3006 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))]
3011 (define_insn "*sub<mode>
3_carryin"
3012 [(set (match_operand:GPI
0 "register_operand" "=r")
3015 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3016 (match_operand:GPI
2 "register_operand" "r"))
3017 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3020 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3021 [(set_attr "type" "adc_reg")]
3024 ;; zero_extend version of the above
3025 (define_insn "*subsi3_carryin_uxtw"
3026 [(set (match_operand:DI
0 "register_operand" "=r")
3030 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3031 (match_operand:SI
2 "register_operand" "r"))
3032 (match_operand:SI
3 "aarch64_borrow_operation" ""))))]
3035 "sbc
\\t%w0, %w1, %w2"
3036 [(set_attr "type" "adc_reg")]
3039 (define_insn "*sub<mode>
3_carryin_alt"
3040 [(set (match_operand:GPI
0 "register_operand" "=r")
3043 (match_operand:GPI
1 "aarch64_reg_or_zero" "rZ")
3044 (match_operand:GPI
3 "aarch64_borrow_operation" ""))
3045 (match_operand:GPI
2 "register_operand" "r")))]
3047 "sbc
\\t%<w>
0, %<w>
1, %<w>
2"
3048 [(set_attr "type" "adc_reg")]
3051 ;; zero_extend version of the above
3052 (define_insn "*subsi3_carryin_alt_uxtw"
3053 [(set (match_operand:DI
0 "register_operand" "=r")
3057 (match_operand:SI
1 "aarch64_reg_or_zero" "rZ")
3058 (match_operand:SI
3 "aarch64_borrow_operation" ""))
3059 (match_operand:SI
2 "register_operand" "r"))))]
3061 "sbc
\\t%w0, %w1, %w2"
3062 [(set_attr "type" "adc_reg")]
3065 (define_expand "sub<mode>
3_carryinCV"
3067 [(set (reg:CC CC_REGNUM)
3070 (match_operand:GPI
1 "aarch64_reg_or_zero" ""))
3073 (match_operand:GPI
2 "register_operand" ""))
3074 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int
0)))))
3075 (set (match_operand:GPI
0 "register_operand" "")
3077 (minus:GPI (match_dup
1) (match_dup
2))
3078 (ltu:GPI (reg:CC CC_REGNUM) (const_int
0))))])]
3082 (define_insn "*sub<mode>
3_carryinCV_z1_z2"
3083 [(set (reg:CC CC_REGNUM)
3086 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3087 (set (match_operand:GPI
0 "register_operand" "=r")
3088 (neg:GPI (match_operand:GPI
1 "aarch64_borrow_operation" "")))]
3090 "sbcs
\\t%<w>
0, <w>zr, <w>zr"
3091 [(set_attr "type" "adc_reg")]
3094 (define_insn "*sub<mode>
3_carryinCV_z1"
3095 [(set (reg:CC CC_REGNUM)
3100 (match_operand:GPI
1 "register_operand" "r"))
3101 (match_operand:<DWI>
2 "aarch64_borrow_operation" ""))))
3102 (set (match_operand:GPI
0 "register_operand" "=r")
3104 (neg:GPI (match_dup
1))
3105 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3107 "sbcs
\\t%<w>
0, <w>zr, %<w>
1"
3108 [(set_attr "type" "adc_reg")]
3111 (define_insn "*sub<mode>
3_carryinCV_z2"
3112 [(set (reg:CC CC_REGNUM)
3115 (match_operand:GPI
1 "register_operand" "r"))
3116 (match_operand:<DWI>
2 "aarch64_borrow_operation" "")))
3117 (set (match_operand:GPI
0 "register_operand" "=r")
3120 (match_operand:GPI
3 "aarch64_borrow_operation" "")))]
3122 "sbcs
\\t%<w>
0, %<w>
1, <w>zr"
3123 [(set_attr "type" "adc_reg")]
3126 (define_insn "*sub<mode>
3_carryinCV"
3127 [(set (reg:CC CC_REGNUM)
3130 (match_operand:GPI
1 "register_operand" "r"))
3133 (match_operand:GPI
2 "register_operand" "r"))
3134 (match_operand:<DWI>
3 "aarch64_borrow_operation" ""))))
3135 (set (match_operand:GPI
0 "register_operand" "=r")
3137 (minus:GPI (match_dup
1) (match_dup
2))
3138 (match_operand:GPI
4 "aarch64_borrow_operation" "")))]
3140 "sbcs
\\t%<w>
0, %<w>
1, %<w>
2"
3141 [(set_attr "type" "adc_reg")]
3144 (define_insn "*sub_uxt<mode>_shift2"
3145 [(set (match_operand:GPI
0 "register_operand" "=rk")
3146 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3148 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
3149 (match_operand
2 "aarch64_imm3" "Ui3"))
3150 (match_operand
3 "const_int_operand" "n"))))]
3151 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3153 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3154 INTVAL (operands[
3])));
3155 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %
2\";"
3156 [(set_attr "type" "alu_ext")]
3159 ;; zero_extend version of above
3160 (define_insn "*sub_uxtsi_shift2_uxtw"
3161 [(set (match_operand:DI
0 "register_operand" "=rk")
3163 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3165 (ashift:SI (match_operand:SI
1 "register_operand" "r")
3166 (match_operand
2 "aarch64_imm3" "Ui3"))
3167 (match_operand
3 "const_int_operand" "n")))))]
3168 "aarch64_uxt_size (INTVAL (operands[
2]),INTVAL (operands[
3])) !=
0"
3170 operands[
3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[
2]),
3171 INTVAL (operands[
3])));
3172 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %
2\";"
3173 [(set_attr "type" "alu_ext")]
3176 (define_insn "*sub_uxt<mode>_multp2"
3177 [(set (match_operand:GPI
0 "register_operand" "=rk")
3178 (minus:GPI (match_operand:GPI
4 "register_operand" "rk")
3180 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3181 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3182 (match_operand
3 "const_int_operand" "n"))))]
3183 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3185 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3186 INTVAL (operands[
3])));
3187 return
\"sub
\t%<w>
0, %<w>
4, %<w>
1, uxt%e3 %p2
\";"
3188 [(set_attr "type" "alu_ext")]
3191 ;; zero_extend version of above
3192 (define_insn "*sub_uxtsi_multp2_uxtw"
3193 [(set (match_operand:DI
0 "register_operand" "=rk")
3195 (minus:SI (match_operand:SI
4 "register_operand" "rk")
3197 (mult:SI (match_operand:SI
1 "register_operand" "r")
3198 (match_operand
2 "aarch64_pwr_imm3" "Up3"))
3199 (match_operand
3 "const_int_operand" "n")))))]
3200 "aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),INTVAL (operands[
3])) !=
0"
3202 operands[
3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[
2])),
3203 INTVAL (operands[
3])));
3204 return
\"sub
\t%w0, %w4, %w1, uxt%e3 %p2
\";"
3205 [(set_attr "type" "alu_ext")]
3208 (define_expand "abs<mode>
2"
3209 [(match_operand:GPI
0 "register_operand" "")
3210 (match_operand:GPI
1 "register_operand" "")]
3213 rtx ccreg = aarch64_gen_compare_reg (LT, operands[
1], const0_rtx);
3214 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3215 emit_insn (gen_csneg3<mode>_insn (operands[
0], x, operands[
1], operands[
1]));
3220 (define_insn "neg<mode>
2"
3221 [(set (match_operand:GPI
0 "register_operand" "=r,w")
3222 (neg:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
3226 neg
\\t%<rtn>
0<vas>, %<rtn>
1<vas>"
3227 [(set_attr "type" "alu_sreg, neon_neg<q>")
3228 (set_attr "simd" "*,yes")]
3231 ;; zero_extend version of above
3232 (define_insn "*negsi2_uxtw"
3233 [(set (match_operand:DI
0 "register_operand" "=r")
3234 (zero_extend:DI (neg:SI (match_operand:SI
1 "register_operand" "r"))))]
3237 [(set_attr "type" "alu_sreg")]
3240 (define_insn "*ngc<mode>"
3241 [(set (match_operand:GPI
0 "register_operand" "=r")
3243 (neg:GPI (match_operand:GPI
2 "aarch64_borrow_operation" ""))
3244 (match_operand:GPI
1 "register_operand" "r")))]
3246 "ngc
\\t%<w>
0, %<w>
1"
3247 [(set_attr "type" "adc_reg")]
3250 (define_insn "*ngcsi_uxtw"
3251 [(set (match_operand:DI
0 "register_operand" "=r")
3254 (neg:SI (match_operand:SI
2 "aarch64_borrow_operation" ""))
3255 (match_operand:SI
1 "register_operand" "r"))))]
3258 [(set_attr "type" "adc_reg")]
3261 (define_insn "neg<mode>
2_compare0"
3262 [(set (reg:CC_NZ CC_REGNUM)
3263 (compare:CC_NZ (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3265 (set (match_operand:GPI
0 "register_operand" "=r")
3266 (neg:GPI (match_dup
1)))]
3268 "negs
\\t%<w>
0, %<w>
1"
3269 [(set_attr "type" "alus_sreg")]
3272 ;; zero_extend version of above
3273 (define_insn "*negsi2_compare0_uxtw"
3274 [(set (reg:CC_NZ CC_REGNUM)
3275 (compare:CC_NZ (neg:SI (match_operand:SI
1 "register_operand" "r"))
3277 (set (match_operand:DI
0 "register_operand" "=r")
3278 (zero_extend:DI (neg:SI (match_dup
1))))]
3281 [(set_attr "type" "alus_sreg")]
3284 (define_insn "*neg_<shift><mode>
3_compare0"
3285 [(set (reg:CC_NZ CC_REGNUM)
3287 (neg:GPI (ASHIFT:GPI
3288 (match_operand:GPI
1 "register_operand" "r")
3289 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
3291 (set (match_operand:GPI
0 "register_operand" "=r")
3292 (neg:GPI (ASHIFT:GPI (match_dup
1) (match_dup
2))))]
3294 "negs
\\t%<w>
0, %<w>
1, <shift> %
2"
3295 [(set_attr "type" "alus_shift_imm")]
3298 (define_insn "*neg_<shift>_<mode>
2"
3299 [(set (match_operand:GPI
0 "register_operand" "=r")
3300 (neg:GPI (ASHIFT:GPI
3301 (match_operand:GPI
1 "register_operand" "r")
3302 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
3304 "neg
\\t%<w>
0, %<w>
1, <shift> %
2"
3305 [(set_attr "type" "alu_shift_imm")]
3308 ;; zero_extend version of above
3309 (define_insn "*neg_<shift>_si2_uxtw"
3310 [(set (match_operand:DI
0 "register_operand" "=r")
3313 (match_operand:SI
1 "register_operand" "r")
3314 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))))]
3316 "neg
\\t%w0, %w1, <shift> %
2"
3317 [(set_attr "type" "alu_shift_imm")]
3320 (define_insn "*neg_mul_imm_<mode>
2"
3321 [(set (match_operand:GPI
0 "register_operand" "=r")
3323 (match_operand:GPI
1 "register_operand" "r")
3324 (match_operand:QI
2 "aarch64_pwr_2_<mode>" "n"))))]
3326 "neg
\\t%<w>
0, %<w>
1, lsl %p2"
3327 [(set_attr "type" "alu_shift_imm")]
3330 ;; zero_extend version of above
3331 (define_insn "*neg_mul_imm_si2_uxtw"
3332 [(set (match_operand:DI
0 "register_operand" "=r")
3335 (match_operand:SI
1 "register_operand" "r")
3336 (match_operand:QI
2 "aarch64_pwr_2_si" "n")))))]
3338 "neg
\\t%w0, %w1, lsl %p2"
3339 [(set_attr "type" "alu_shift_imm")]
3342 (define_insn "mul<mode>
3"
3343 [(set (match_operand:GPI
0 "register_operand" "=r")
3344 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3345 (match_operand:GPI
2 "register_operand" "r")))]
3347 "mul
\\t%<w>
0, %<w>
1, %<w>
2"
3348 [(set_attr "type" "mul")]
3351 ;; zero_extend version of above
3352 (define_insn "*mulsi3_uxtw"
3353 [(set (match_operand:DI
0 "register_operand" "=r")
3355 (mult:SI (match_operand:SI
1 "register_operand" "r")
3356 (match_operand:SI
2 "register_operand" "r"))))]
3358 "mul
\\t%w0, %w1, %w2"
3359 [(set_attr "type" "mul")]
3362 (define_insn "madd<mode>"
3363 [(set (match_operand:GPI
0 "register_operand" "=r")
3364 (plus:GPI (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3365 (match_operand:GPI
2 "register_operand" "r"))
3366 (match_operand:GPI
3 "register_operand" "r")))]
3368 "madd
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3369 [(set_attr "type" "mla")]
3372 ;; zero_extend version of above
3373 (define_insn "*maddsi_uxtw"
3374 [(set (match_operand:DI
0 "register_operand" "=r")
3376 (plus:SI (mult:SI (match_operand:SI
1 "register_operand" "r")
3377 (match_operand:SI
2 "register_operand" "r"))
3378 (match_operand:SI
3 "register_operand" "r"))))]
3380 "madd
\\t%w0, %w1, %w2, %w3"
3381 [(set_attr "type" "mla")]
3384 (define_insn "*msub<mode>"
3385 [(set (match_operand:GPI
0 "register_operand" "=r")
3386 (minus:GPI (match_operand:GPI
3 "register_operand" "r")
3387 (mult:GPI (match_operand:GPI
1 "register_operand" "r")
3388 (match_operand:GPI
2 "register_operand" "r"))))]
3391 "msub
\\t%<w>
0, %<w>
1, %<w>
2, %<w>
3"
3392 [(set_attr "type" "mla")]
3395 ;; zero_extend version of above
3396 (define_insn "*msubsi_uxtw"
3397 [(set (match_operand:DI
0 "register_operand" "=r")
3399 (minus:SI (match_operand:SI
3 "register_operand" "r")
3400 (mult:SI (match_operand:SI
1 "register_operand" "r")
3401 (match_operand:SI
2 "register_operand" "r")))))]
3404 "msub
\\t%w0, %w1, %w2, %w3"
3405 [(set_attr "type" "mla")]
3408 (define_insn "*mul<mode>_neg"
3409 [(set (match_operand:GPI
0 "register_operand" "=r")
3410 (mult:GPI (neg:GPI (match_operand:GPI
1 "register_operand" "r"))
3411 (match_operand:GPI
2 "register_operand" "r")))]
3414 "mneg
\\t%<w>
0, %<w>
1, %<w>
2"
3415 [(set_attr "type" "mul")]
3418 ;; zero_extend version of above
3419 (define_insn "*mulsi_neg_uxtw"
3420 [(set (match_operand:DI
0 "register_operand" "=r")
3422 (mult:SI (neg:SI (match_operand:SI
1 "register_operand" "r"))
3423 (match_operand:SI
2 "register_operand" "r"))))]
3426 "mneg
\\t%w0, %w1, %w2"
3427 [(set_attr "type" "mul")]
3430 (define_insn "<su_optab>mulsidi3"
3431 [(set (match_operand:DI
0 "register_operand" "=r")
3432 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3433 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3435 "<su>mull
\\t%
0, %w1, %w2"
3436 [(set_attr "type" "<su>mull")]
3439 (define_insn "<su_optab>maddsidi4"
3440 [(set (match_operand:DI
0 "register_operand" "=r")
3442 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3443 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r")))
3444 (match_operand:DI
3 "register_operand" "r")))]
3446 "<su>maddl
\\t%
0, %w1, %w2, %
3"
3447 [(set_attr "type" "<su>mlal")]
3450 (define_insn "<su_optab>msubsidi4"
3451 [(set (match_operand:DI
0 "register_operand" "=r")
3453 (match_operand:DI
3 "register_operand" "r")
3454 (mult:DI (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r"))
3456 (match_operand:SI
2 "register_operand" "r")))))]
3458 "<su>msubl
\\t%
0, %w1, %w2, %
3"
3459 [(set_attr "type" "<su>mlal")]
3462 (define_insn "*<su_optab>mulsidi_neg"
3463 [(set (match_operand:DI
0 "register_operand" "=r")
3465 (ANY_EXTEND:DI (match_operand:SI
1 "register_operand" "r")))
3466 (ANY_EXTEND:DI (match_operand:SI
2 "register_operand" "r"))))]
3468 "<su>mnegl
\\t%
0, %w1, %w2"
3469 [(set_attr "type" "<su>mull")]
3472 (define_expand "<su_optab>mulditi3"
3473 [(set (match_operand:TI
0 "register_operand")
3474 (mult:TI (ANY_EXTEND:TI (match_operand:DI
1 "register_operand"))
3475 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand"))))]
3478 rtx low = gen_reg_rtx (DImode);
3479 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
3481 rtx high = gen_reg_rtx (DImode);
3482 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
3484 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
3485 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
3489 ;; The default expansion of multi3 using umuldi3_highpart will perform
3490 ;; the additions in an order that fails to combine into two madd insns.
3491 (define_expand "multi3"
3492 [(set (match_operand:TI
0 "register_operand")
3493 (mult:TI (match_operand:TI
1 "register_operand")
3494 (match_operand:TI
2 "register_operand")))]
3497 rtx l0 = gen_reg_rtx (DImode);
3498 rtx l1 = gen_lowpart (DImode, operands[
1]);
3499 rtx l2 = gen_lowpart (DImode, operands[
2]);
3500 rtx h0 = gen_reg_rtx (DImode);
3501 rtx h1 = gen_highpart (DImode, operands[
1]);
3502 rtx h2 = gen_highpart (DImode, operands[
2]);
3504 emit_insn (gen_muldi3 (l0, l1, l2));
3505 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3506 emit_insn (gen_madddi (h0, h1, l2, h0));
3507 emit_insn (gen_madddi (h0, l1, h2, h0));
3509 emit_move_insn (gen_lowpart (DImode, operands[
0]), l0);
3510 emit_move_insn (gen_highpart (DImode, operands[
0]), h0);
3514 (define_insn "<su>muldi3_highpart"
3515 [(set (match_operand:DI
0 "register_operand" "=r")
3519 (ANY_EXTEND:TI (match_operand:DI
1 "register_operand" "r"))
3520 (ANY_EXTEND:TI (match_operand:DI
2 "register_operand" "r")))
3523 "<su>mulh
\\t%
0, %
1, %
2"
3524 [(set_attr "type" "<su>mull")]
3527 (define_insn "<su_optab>div<mode>
3"
3528 [(set (match_operand:GPI
0 "register_operand" "=r")
3529 (ANY_DIV:GPI (match_operand:GPI
1 "register_operand" "r")
3530 (match_operand:GPI
2 "register_operand" "r")))]
3532 "<su>div
\\t%<w>
0, %<w>
1, %<w>
2"
3533 [(set_attr "type" "<su>div")]
3536 ;; zero_extend version of above
3537 (define_insn "*<su_optab>divsi3_uxtw"
3538 [(set (match_operand:DI
0 "register_operand" "=r")
3540 (ANY_DIV:SI (match_operand:SI
1 "register_operand" "r")
3541 (match_operand:SI
2 "register_operand" "r"))))]
3543 "<su>div
\\t%w0, %w1, %w2"
3544 [(set_attr "type" "<su>div")]
3547 ;; -------------------------------------------------------------------
3549 ;; -------------------------------------------------------------------
3551 (define_insn "cmp<mode>"
3552 [(set (reg:CC CC_REGNUM)
3553 (compare:CC (match_operand:GPI
0 "register_operand" "rk,rk,rk")
3554 (match_operand:GPI
1 "aarch64_plus_operand" "r,I,J")))]
3560 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3563 (define_insn "fcmp<mode>"
3564 [(set (reg:CCFP CC_REGNUM)
3565 (compare:CCFP (match_operand:GPF
0 "register_operand" "w,w")
3566 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3570 fcmp
\\t%<s>
0, %<s>
1"
3571 [(set_attr "type" "fcmp<s>")]
3574 (define_insn "fcmpe<mode>"
3575 [(set (reg:CCFPE CC_REGNUM)
3576 (compare:CCFPE (match_operand:GPF
0 "register_operand" "w,w")
3577 (match_operand:GPF
1 "aarch64_fp_compare_operand" "Y,w")))]
3581 fcmpe
\\t%<s>
0, %<s>
1"
3582 [(set_attr "type" "fcmp<s>")]
3585 (define_insn "*cmp_swp_<shift>_reg<mode>"
3586 [(set (reg:CC_SWP CC_REGNUM)
3587 (compare:CC_SWP (ASHIFT:GPI
3588 (match_operand:GPI
0 "register_operand" "r")
3589 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
3590 (match_operand:GPI
2 "aarch64_reg_or_zero" "rZ")))]
3592 "cmp
\\t%<w>
2, %<w>
0, <shift> %
1"
3593 [(set_attr "type" "alus_shift_imm")]
3596 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3597 [(set (reg:CC_SWP CC_REGNUM)
3598 (compare:CC_SWP (ANY_EXTEND:GPI
3599 (match_operand:ALLX
0 "register_operand" "r"))
3600 (match_operand:GPI
1 "register_operand" "r")))]
3602 "cmp
\\t%<GPI:w>
1, %<GPI:w>
0, <su>xt<ALLX:size>"
3603 [(set_attr "type" "alus_ext")]
3606 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3607 [(set (reg:CC_SWP CC_REGNUM)
3608 (compare:CC_SWP (ashift:GPI
3610 (match_operand:ALLX
0 "register_operand" "r"))
3611 (match_operand
1 "aarch64_imm3" "Ui3"))
3612 (match_operand:GPI
2 "register_operand" "r")))]
3614 "cmp
\\t%<GPI:w>
2, %<GPI:w>
0, <su>xt<ALLX:size> %
1"
3615 [(set_attr "type" "alus_ext")]
3618 ;; -------------------------------------------------------------------
3619 ;; Store-flag and conditional select insns
3620 ;; -------------------------------------------------------------------
3622 (define_expand "cstore<mode>
4"
3623 [(set (match_operand:SI
0 "register_operand" "")
3624 (match_operator:SI
1 "aarch64_comparison_operator"
3625 [(match_operand:GPI
2 "register_operand" "")
3626 (match_operand:GPI
3 "aarch64_plus_operand" "")]))]
3629 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3631 operands[
3] = const0_rtx;
3635 (define_expand "cstorecc4"
3636 [(set (match_operand:SI
0 "register_operand")
3637 (match_operator
1 "aarch64_comparison_operator_mode"
3638 [(match_operand
2 "cc_register")
3639 (match_operand
3 "const0_operand")]))]
3642 emit_insn (gen_rtx_SET (operands[
0], operands[
1]));
3647 (define_expand "cstore<mode>
4"
3648 [(set (match_operand:SI
0 "register_operand" "")
3649 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3650 [(match_operand:GPF
2 "register_operand" "")
3651 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")]))]
3654 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3656 operands[
3] = const0_rtx;
3660 (define_insn "aarch64_cstore<mode>"
3661 [(set (match_operand:ALLI
0 "register_operand" "=r")
3662 (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3663 [(match_operand
2 "cc_register" "") (const_int
0)]))]
3666 [(set_attr "type" "csel")]
3669 ;; For a
24-bit immediate CST we can optimize the compare for equality
3670 ;; and branch sequence from:
3672 ;; movk x0, #imm2, lsl
16 /* x0 contains CST. */
3675 ;; into the shorter:
3676 ;; sub x0, x1, #(CST &
0xfff000)
3677 ;; subs x0, x0, #(CST &
0x000fff)
3678 ;; cset x2, <ne, eq>.
3679 (define_insn_and_split "*compare_cstore<mode>_insn"
3680 [(set (match_operand:GPI
0 "register_operand" "=r")
3681 (EQL:GPI (match_operand:GPI
1 "register_operand" "r")
3682 (match_operand:GPI
2 "aarch64_imm24" "n")))
3683 (clobber (reg:CC CC_REGNUM))]
3684 "!aarch64_move_imm (INTVAL (operands[
2]), <MODE>mode)
3685 && !aarch64_plus_operand (operands[
2], <MODE>mode)
3686 && !reload_completed"
3691 HOST_WIDE_INT lo_imm = UINTVAL (operands[
2]) &
0xfff;
3692 HOST_WIDE_INT hi_imm = UINTVAL (operands[
2]) &
0xfff000;
3693 rtx tmp = gen_reg_rtx (<MODE>mode);
3694 emit_insn (gen_add<mode>
3 (tmp, operands[
1], GEN_INT (-hi_imm)));
3695 emit_insn (gen_add<mode>
3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3696 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3697 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3698 emit_insn (gen_aarch64_cstore<mode> (operands[
0], cmp_rtx, cc_reg));
3701 [(set_attr "type" "csel")]
3704 ;; zero_extend version of the above
3705 (define_insn "*cstoresi_insn_uxtw"
3706 [(set (match_operand:DI
0 "register_operand" "=r")
3708 (match_operator:SI
1 "aarch64_comparison_operator_mode"
3709 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3712 [(set_attr "type" "csel")]
3715 (define_insn "cstore<mode>_neg"
3716 [(set (match_operand:ALLI
0 "register_operand" "=r")
3717 (neg:ALLI (match_operator:ALLI
1 "aarch64_comparison_operator_mode"
3718 [(match_operand
2 "cc_register" "") (const_int
0)])))]
3720 "csetm
\\t%<w>
0, %m1"
3721 [(set_attr "type" "csel")]
3724 ;; zero_extend version of the above
3725 (define_insn "*cstoresi_neg_uxtw"
3726 [(set (match_operand:DI
0 "register_operand" "=r")
3728 (neg:SI (match_operator:SI
1 "aarch64_comparison_operator_mode"
3729 [(match_operand
2 "cc_register" "") (const_int
0)]))))]
3732 [(set_attr "type" "csel")]
3735 (define_expand "cmov<mode>
6"
3736 [(set (match_operand:GPI
0 "register_operand" "")
3738 (match_operator
1 "aarch64_comparison_operator"
3739 [(match_operand:GPI
2 "register_operand" "")
3740 (match_operand:GPI
3 "aarch64_plus_operand" "")])
3741 (match_operand:GPI
4 "register_operand" "")
3742 (match_operand:GPI
5 "register_operand" "")))]
3745 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3747 operands[
3] = const0_rtx;
3751 (define_expand "cmov<mode>
6"
3752 [(set (match_operand:GPF
0 "register_operand" "")
3754 (match_operator
1 "aarch64_comparison_operator"
3755 [(match_operand:GPF
2 "register_operand" "")
3756 (match_operand:GPF
3 "aarch64_fp_compare_operand" "")])
3757 (match_operand:GPF
4 "register_operand" "")
3758 (match_operand:GPF
5 "register_operand" "")))]
3761 operands[
2] = aarch64_gen_compare_reg (GET_CODE (operands[
1]), operands[
2],
3763 operands[
3] = const0_rtx;
3767 (define_insn "*cmov<mode>_insn"
3768 [(set (match_operand:ALLI
0 "register_operand" "=r,r,r,r,r,r,r")
3770 (match_operator
1 "aarch64_comparison_operator"
3771 [(match_operand
2 "cc_register" "") (const_int
0)])
3772 (match_operand:ALLI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3773 (match_operand:ALLI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3774 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3775 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3776 ;; Final two alternatives should be unreachable, but included for completeness
3778 csel
\\t%<w>
0, %<w>
3, %<w>
4, %m1
3779 csinv
\\t%<w>
0, %<w>
3, <w>zr, %m1
3780 csinv
\\t%<w>
0, %<w>
4, <w>zr, %M1
3781 csinc
\\t%<w>
0, %<w>
3, <w>zr, %m1
3782 csinc
\\t%<w>
0, %<w>
4, <w>zr, %M1
3785 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3788 ;; zero_extend version of above
3789 (define_insn "*cmovsi_insn_uxtw"
3790 [(set (match_operand:DI
0 "register_operand" "=r,r,r,r,r,r,r")
3793 (match_operator
1 "aarch64_comparison_operator"
3794 [(match_operand
2 "cc_register" "") (const_int
0)])
3795 (match_operand:SI
3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3796 (match_operand:SI
4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3797 "!((operands[
3] == const1_rtx && operands[
4] == constm1_rtx)
3798 || (operands[
3] == constm1_rtx && operands[
4] == const1_rtx))"
3799 ;; Final two alternatives should be unreachable, but included for completeness
3801 csel
\\t%w0, %w3, %w4, %m1
3802 csinv
\\t%w0, %w3, wzr, %m1
3803 csinv
\\t%w0, %w4, wzr, %M1
3804 csinc
\\t%w0, %w3, wzr, %m1
3805 csinc
\\t%w0, %w4, wzr, %M1
3808 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3811 (define_insn "*cmovdi_insn_uxtw"
3812 [(set (match_operand:DI
0 "register_operand" "=r")
3814 (match_operator
1 "aarch64_comparison_operator"
3815 [(match_operand
2 "cc_register" "") (const_int
0)])
3816 (zero_extend:DI (match_operand:SI
3 "register_operand" "r"))
3817 (zero_extend:DI (match_operand:SI
4 "register_operand" "r"))))]
3819 "csel
\\t%w0, %w3, %w4, %m1"
3820 [(set_attr "type" "csel")]
3823 (define_insn "*cmov<mode>_insn"
3824 [(set (match_operand:GPF
0 "register_operand" "=w")
3826 (match_operator
1 "aarch64_comparison_operator"
3827 [(match_operand
2 "cc_register" "") (const_int
0)])
3828 (match_operand:GPF
3 "register_operand" "w")
3829 (match_operand:GPF
4 "register_operand" "w")))]
3831 "fcsel
\\t%<s>
0, %<s>
3, %<s>
4, %m1"
3832 [(set_attr "type" "fcsel")]
3835 (define_expand "mov<mode>cc"
3836 [(set (match_operand:ALLI
0 "register_operand" "")
3837 (if_then_else:ALLI (match_operand
1 "aarch64_comparison_operator" "")
3838 (match_operand:ALLI
2 "register_operand" "")
3839 (match_operand:ALLI
3 "register_operand" "")))]
3843 enum rtx_code code = GET_CODE (operands[
1]);
3845 if (code == UNEQ || code == LTGT)
3848 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3849 XEXP (operands[
1],
1));
3850 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3854 (define_expand "mov<GPF:mode><GPI:mode>cc"
3855 [(set (match_operand:GPI
0 "register_operand" "")
3856 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3857 (match_operand:GPF
2 "register_operand" "")
3858 (match_operand:GPF
3 "register_operand" "")))]
3862 enum rtx_code code = GET_CODE (operands[
1]);
3864 if (code == UNEQ || code == LTGT)
3867 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3868 XEXP (operands[
1],
1));
3869 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3873 (define_expand "mov<mode>cc"
3874 [(set (match_operand:GPF
0 "register_operand" "")
3875 (if_then_else:GPF (match_operand
1 "aarch64_comparison_operator" "")
3876 (match_operand:GPF
2 "register_operand" "")
3877 (match_operand:GPF
3 "register_operand" "")))]
3881 enum rtx_code code = GET_CODE (operands[
1]);
3883 if (code == UNEQ || code == LTGT)
3886 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3887 XEXP (operands[
1],
1));
3888 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3892 (define_expand "<neg_not_op><mode>cc"
3893 [(set (match_operand:GPI
0 "register_operand" "")
3894 (if_then_else:GPI (match_operand
1 "aarch64_comparison_operator" "")
3895 (NEG_NOT:GPI (match_operand:GPI
2 "register_operand" ""))
3896 (match_operand:GPI
3 "register_operand" "")))]
3900 enum rtx_code code = GET_CODE (operands[
1]);
3902 if (code == UNEQ || code == LTGT)
3905 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[
1],
0),
3906 XEXP (operands[
1],
1));
3907 operands[
1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3911 ;; CRC32 instructions.
3912 (define_insn "aarch64_<crc_variant>"
3913 [(set (match_operand:SI
0 "register_operand" "=r")
3914 (unspec:SI [(match_operand:SI
1 "register_operand" "r")
3915 (match_operand:<crc_mode>
2 "register_operand" "r")]
3919 if (GET_MODE_BITSIZE (<crc_mode>mode) >=
64)
3920 return "<crc_variant>
\\t%w0, %w1, %x2";
3922 return "<crc_variant>
\\t%w0, %w1, %w2";
3924 [(set_attr "type" "crc")]
3927 (define_insn "*csinc2<mode>_insn"
3928 [(set (match_operand:GPI
0 "register_operand" "=r")
3929 (plus:GPI (match_operand
2 "aarch64_comparison_operation" "")
3930 (match_operand:GPI
1 "register_operand" "r")))]
3932 "cinc
\\t%<w>
0, %<w>
1, %m2"
3933 [(set_attr "type" "csel")]
3936 (define_insn "csinc3<mode>_insn"
3937 [(set (match_operand:GPI
0 "register_operand" "=r")
3939 (match_operand
1 "aarch64_comparison_operation" "")
3940 (plus:GPI (match_operand:GPI
2 "register_operand" "r")
3942 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3944 "csinc
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3945 [(set_attr "type" "csel")]
3948 (define_insn "*csinv3<mode>_insn"
3949 [(set (match_operand:GPI
0 "register_operand" "=r")
3951 (match_operand
1 "aarch64_comparison_operation" "")
3952 (not:GPI (match_operand:GPI
2 "register_operand" "r"))
3953 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3955 "csinv
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3956 [(set_attr "type" "csel")]
3959 (define_insn "csneg3_uxtw_insn"
3960 [(set (match_operand:DI
0 "register_operand" "=r")
3963 (match_operand
1 "aarch64_comparison_operation" "")
3964 (neg:SI (match_operand:SI
2 "register_operand" "r"))
3965 (match_operand:SI
3 "aarch64_reg_or_zero" "rZ"))))]
3967 "csneg
\\t%w0, %w3, %w2, %M1"
3968 [(set_attr "type" "csel")]
3971 (define_insn "csneg3<mode>_insn"
3972 [(set (match_operand:GPI
0 "register_operand" "=r")
3974 (match_operand
1 "aarch64_comparison_operation" "")
3975 (neg:GPI (match_operand:GPI
2 "register_operand" "r"))
3976 (match_operand:GPI
3 "aarch64_reg_or_zero" "rZ")))]
3978 "csneg
\\t%<w>
0, %<w>
3, %<w>
2, %M1"
3979 [(set_attr "type" "csel")]
3982 ;; If X can be loaded by a single CNT[BHWD] instruction,
3986 ;; is equivalent to:
3988 ;; TMP = UQDEC[BHWD] (B, X)
3991 ;; Defining the pattern this way means that:
3993 ;; A = UMAX (B, X) - X
3997 ;; TMP1 = UQDEC[BHWD] (B, X)
4001 ;; which combine can optimize to:
4003 ;; A = UQDEC[BHWD] (B, X)
4005 ;; We don't use match_operand predicates because the order of the operands
4006 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4007 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4008 (define_expand "umax<mode>
3"
4009 [(set (match_operand:GPI
0 "register_operand")
4010 (umax:GPI (match_operand:GPI
1 "")
4011 (match_operand:GPI
2 "")))]
4014 if (aarch64_sve_cnt_immediate (operands[
1], <MODE>mode))
4015 std::swap (operands[
1], operands[
2]);
4016 else if (!aarch64_sve_cnt_immediate (operands[
2], <MODE>mode))
4018 rtx temp = gen_reg_rtx (<MODE>mode);
4019 operands[
1] = force_reg (<MODE>mode, operands[
1]);
4020 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[
1], operands[
2]));
4021 emit_insn (gen_add<mode>
3 (operands[
0], temp, operands[
2]));
4026 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4027 (define_insn "aarch64_uqdec<mode>"
4028 [(set (match_operand:GPI
0 "register_operand" "=r")
4030 (umax:GPI (match_operand:GPI
1 "register_operand" "
0")
4031 (match_operand:GPI
2 "aarch64_sve_cnt_immediate" "Usv"))
4035 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>
0", operands[
2]);
4039 ;; -------------------------------------------------------------------
4040 ;; Logical operations
4041 ;; -------------------------------------------------------------------
4044 (define_insn_and_split "*aarch64_and<mode>_imm2"
4045 [(set (match_operand:GPI
0 "register_operand" "=rk")
4046 (and:GPI (match_operand:GPI
1 "register_operand" "%r")
4047 (match_operand:GPI
2 "aarch64_logical_and_immediate" "<lconst2>")))]
4053 HOST_WIDE_INT val = INTVAL (operands[
2]);
4054 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4055 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4057 emit_insn (gen_and<mode>
3 (operands[
0], operands[
1], imm1));
4058 emit_insn (gen_and<mode>
3 (operands[
0], operands[
0], imm2));
4063 (define_insn "<optab><mode>
3"
4064 [(set (match_operand:GPI
0 "register_operand" "=r,rk,w")
4065 (LOGICAL:GPI (match_operand:GPI
1 "register_operand" "%r,r,w")
4066 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>,w")))]
4069 <logical>
\\t%<w>
0, %<w>
1, %<w>
2
4070 <logical>
\\t%<w>
0, %<w>
1, %
2
4071 <logical>
\\t%
0.<Vbtype>, %
1.<Vbtype>, %
2.<Vbtype>"
4072 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4073 (set_attr "simd" "*,*,yes")]
4076 ;; zero_extend version of above
4077 (define_insn "*<optab>si3_uxtw"
4078 [(set (match_operand:DI
0 "register_operand" "=r,rk")
4080 (LOGICAL:SI (match_operand:SI
1 "register_operand" "%r,r")
4081 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))))]
4084 <logical>
\\t%w0, %w1, %w2
4085 <logical>
\\t%w0, %w1, %
2"
4086 [(set_attr "type" "logic_reg,logic_imm")]
4089 (define_insn "*and<mode>
3_compare0"
4090 [(set (reg:CC_NZ CC_REGNUM)
4092 (and:GPI (match_operand:GPI
1 "register_operand" "%r,r")
4093 (match_operand:GPI
2 "aarch64_logical_operand" "r,<lconst>"))
4095 (set (match_operand:GPI
0 "register_operand" "=r,r")
4096 (and:GPI (match_dup
1) (match_dup
2)))]
4099 ands
\\t%<w>
0, %<w>
1, %<w>
2
4100 ands
\\t%<w>
0, %<w>
1, %
2"
4101 [(set_attr "type" "logics_reg,logics_imm")]
4104 ;; zero_extend version of above
4105 (define_insn "*andsi3_compare0_uxtw"
4106 [(set (reg:CC_NZ CC_REGNUM)
4108 (and:SI (match_operand:SI
1 "register_operand" "%r,r")
4109 (match_operand:SI
2 "aarch64_logical_operand" "r,K"))
4111 (set (match_operand:DI
0 "register_operand" "=r,r")
4112 (zero_extend:DI (and:SI (match_dup
1) (match_dup
2))))]
4115 ands
\\t%w0, %w1, %w2
4116 ands
\\t%w0, %w1, %
2"
4117 [(set_attr "type" "logics_reg,logics_imm")]
4120 (define_insn "*and_<SHIFT:optab><mode>
3_compare0"
4121 [(set (reg:CC_NZ CC_REGNUM)
4124 (match_operand:GPI
1 "register_operand" "r")
4125 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4126 (match_operand:GPI
3 "register_operand" "r"))
4128 (set (match_operand:GPI
0 "register_operand" "=r")
4129 (and:GPI (SHIFT:GPI (match_dup
1) (match_dup
2)) (match_dup
3)))]
4131 "ands
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4132 [(set_attr "type" "logics_shift_imm")]
4135 ;; zero_extend version of above
4136 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4137 [(set (reg:CC_NZ CC_REGNUM)
4140 (match_operand:SI
1 "register_operand" "r")
4141 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4142 (match_operand:SI
3 "register_operand" "r"))
4144 (set (match_operand:DI
0 "register_operand" "=r")
4145 (zero_extend:DI (and:SI (SHIFT:SI (match_dup
1) (match_dup
2))
4148 "ands
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4149 [(set_attr "type" "logics_shift_imm")]
4152 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>
3"
4153 [(set (match_operand:GPI
0 "register_operand" "=r")
4154 (LOGICAL:GPI (SHIFT:GPI
4155 (match_operand:GPI
1 "register_operand" "r")
4156 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4157 (match_operand:GPI
3 "register_operand" "r")))]
4159 "<LOGICAL:logical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4160 [(set_attr "type" "logic_shift_imm")]
4163 (define_insn "*<optab>_rol<mode>
3"
4164 [(set (match_operand:GPI
0 "register_operand" "=r")
4165 (LOGICAL:GPI (rotate:GPI
4166 (match_operand:GPI
1 "register_operand" "r")
4167 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4168 (match_operand:GPI
3 "register_operand" "r")))]
4170 "<logical>
\\t%<w>
0, %<w>
3, %<w>
1, ror (<sizen> - %
2)"
4171 [(set_attr "type" "logic_shift_imm")]
4174 ;; zero_extend versions of above
4175 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4176 [(set (match_operand:DI
0 "register_operand" "=r")
4178 (LOGICAL:SI (SHIFT:SI
4179 (match_operand:SI
1 "register_operand" "r")
4180 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4181 (match_operand:SI
3 "register_operand" "r"))))]
4183 "<LOGICAL:logical>
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4184 [(set_attr "type" "logic_shift_imm")]
4187 (define_insn "*<optab>_rolsi3_uxtw"
4188 [(set (match_operand:DI
0 "register_operand" "=r")
4190 (LOGICAL:SI (rotate:SI
4191 (match_operand:SI
1 "register_operand" "r")
4192 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4193 (match_operand:SI
3 "register_operand" "r"))))]
4195 "<logical>
\\t%w0, %w3, %w1, ror (
32 - %
2)"
4196 [(set_attr "type" "logic_shift_imm")]
4199 (define_insn "one_cmpl<mode>
2"
4200 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4201 (not:GPI (match_operand:GPI
1 "register_operand" "r,w")))]
4206 [(set_attr "type" "logic_reg,neon_logic")
4207 (set_attr "simd" "*,yes")]
4210 (define_insn "*one_cmpl_<optab><mode>
2"
4211 [(set (match_operand:GPI
0 "register_operand" "=r")
4212 (not:GPI (SHIFT:GPI (match_operand:GPI
1 "register_operand" "r")
4213 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))))]
4215 "mvn
\\t%<w>
0, %<w>
1, <shift> %
2"
4216 [(set_attr "type" "logic_shift_imm")]
4219 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4221 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>
3"
4222 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4223 (NLOGICAL:GPI (not:GPI (match_operand:GPI
1 "register_operand" "r,w"))
4224 (match_operand:GPI
2 "register_operand" "r,w")))]
4227 <NLOGICAL:nlogical>
\\t%<w>
0, %<w>
2, %<w>
1
4228 <NLOGICAL:nlogical>
\\t%
0.<Vbtype>, %
2.<Vbtype>, %
1.<Vbtype>"
4229 [(set_attr "type" "logic_reg,neon_logic")
4230 (set_attr "simd" "*,yes")]
4233 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4234 [(set (match_operand:DI
0 "register_operand" "=r")
4236 (NLOGICAL:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
4237 (match_operand:SI
2 "register_operand" "r"))))]
4239 "<NLOGICAL:nlogical>
\\t%w0, %w2, %w1"
4240 [(set_attr "type" "logic_reg")]
4243 (define_insn "*xor_one_cmplsidi3_ze"
4244 [(set (match_operand:DI
0 "register_operand" "=r")
4246 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "r")
4247 (match_operand:SI
2 "register_operand" "r")))))]
4249 "eon
\\t%w0, %w1, %w2"
4250 [(set_attr "type" "logic_reg")]
4253 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4254 ;; eon does not operate on SIMD registers so the vector variant must be split.
4255 (define_insn_and_split "*xor_one_cmpl<mode>
3"
4256 [(set (match_operand:GPI
0 "register_operand" "=r,w")
4257 (not:GPI (xor:GPI (match_operand:GPI
1 "register_operand" "r,?w")
4258 (match_operand:GPI
2 "register_operand" "r,w"))))]
4261 eon
\\t%<w>
0, %<w>
1, %<w>
2
4263 "reload_completed && FP_REGNUM_P (REGNO (operands[
0]))" ;; For SIMD registers.
4264 [(set (match_operand:GPI
0 "register_operand" "=w")
4265 (xor:GPI (match_operand:GPI
1 "register_operand" "w")
4266 (match_operand:GPI
2 "register_operand" "w")))
4267 (set (match_dup
0) (not:GPI (match_dup
0)))]
4269 [(set_attr "type" "logic_reg,multiple")
4270 (set_attr "simd" "*,yes")]
4273 (define_insn "*and_one_cmpl<mode>
3_compare0"
4274 [(set (reg:CC_NZ CC_REGNUM)
4277 (match_operand:GPI
1 "register_operand" "r"))
4278 (match_operand:GPI
2 "register_operand" "r"))
4280 (set (match_operand:GPI
0 "register_operand" "=r")
4281 (and:GPI (not:GPI (match_dup
1)) (match_dup
2)))]
4283 "bics
\\t%<w>
0, %<w>
2, %<w>
1"
4284 [(set_attr "type" "logics_reg")]
4287 ;; zero_extend version of above
4288 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4289 [(set (reg:CC_NZ CC_REGNUM)
4292 (match_operand:SI
1 "register_operand" "r"))
4293 (match_operand:SI
2 "register_operand" "r"))
4295 (set (match_operand:DI
0 "register_operand" "=r")
4296 (zero_extend:DI (and:SI (not:SI (match_dup
1)) (match_dup
2))))]
4298 "bics
\\t%w0, %w2, %w1"
4299 [(set_attr "type" "logics_reg")]
4302 (define_insn "*and_one_cmpl<mode>
3_compare0_no_reuse"
4303 [(set (reg:CC_NZ CC_REGNUM)
4306 (match_operand:GPI
0 "register_operand" "r"))
4307 (match_operand:GPI
1 "register_operand" "r"))
4310 "bics
\\t<w>zr, %<w>
1, %<w>
0"
4311 [(set_attr "type" "logics_reg")]
4314 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>
3"
4315 [(set (match_operand:GPI
0 "register_operand" "=r")
4316 (LOGICAL:GPI (not:GPI
4318 (match_operand:GPI
1 "register_operand" "r")
4319 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4320 (match_operand:GPI
3 "register_operand" "r")))]
4322 "<LOGICAL:nlogical>
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4323 [(set_attr "type" "logic_shift_imm")]
4326 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>
3_alt"
4327 [(set (match_operand:GPI
0 "register_operand" "=r")
4330 (match_operand:GPI
1 "register_operand" "r")
4331 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n"))
4332 (match_operand:GPI
3 "register_operand" "r"))))]
4334 "eon
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4335 [(set_attr "type" "logic_shift_imm")]
4338 ;; Zero-extend version of the above.
4339 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4340 [(set (match_operand:DI
0 "register_operand" "=r")
4344 (match_operand:SI
1 "register_operand" "r")
4345 (match_operand:QI
2 "aarch64_shift_imm_si" "n"))
4346 (match_operand:SI
3 "register_operand" "r")))))]
4348 "eon
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4349 [(set_attr "type" "logic_shift_imm")]
4352 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0"
4353 [(set (reg:CC_NZ CC_REGNUM)
4357 (match_operand:GPI
1 "register_operand" "r")
4358 (match_operand:QI
2 "aarch64_shift_imm_<mode>" "n")))
4359 (match_operand:GPI
3 "register_operand" "r"))
4361 (set (match_operand:GPI
0 "register_operand" "=r")
4364 (match_dup
1) (match_dup
2))) (match_dup
3)))]
4366 "bics
\\t%<w>
0, %<w>
3, %<w>
1, <SHIFT:shift> %
2"
4367 [(set_attr "type" "logics_shift_imm")]
4370 ;; zero_extend version of above
4371 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4372 [(set (reg:CC_NZ CC_REGNUM)
4376 (match_operand:SI
1 "register_operand" "r")
4377 (match_operand:QI
2 "aarch64_shift_imm_si" "n")))
4378 (match_operand:SI
3 "register_operand" "r"))
4380 (set (match_operand:DI
0 "register_operand" "=r")
4381 (zero_extend:DI (and:SI
4383 (SHIFT:SI (match_dup
1) (match_dup
2))) (match_dup
3))))]
4385 "bics
\\t%w0, %w3, %w1, <SHIFT:shift> %
2"
4386 [(set_attr "type" "logics_shift_imm")]
4389 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>
3_compare0_no_reuse"
4390 [(set (reg:CC_NZ CC_REGNUM)
4394 (match_operand:GPI
0 "register_operand" "r")
4395 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n")))
4396 (match_operand:GPI
2 "register_operand" "r"))
4399 "bics
\\t<w>zr, %<w>
2, %<w>
0, <SHIFT:shift> %
1"
4400 [(set_attr "type" "logics_shift_imm")]
4403 (define_insn "clz<mode>
2"
4404 [(set (match_operand:GPI
0 "register_operand" "=r")
4405 (clz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4407 "clz
\\t%<w>
0, %<w>
1"
4408 [(set_attr "type" "clz")]
4411 (define_expand "ffs<mode>
2"
4412 [(match_operand:GPI
0 "register_operand")
4413 (match_operand:GPI
1 "register_operand")]
4416 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[
1], const0_rtx);
4417 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4419 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4420 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4421 emit_insn (gen_csinc3<mode>_insn (operands[
0], x, operands[
0], const0_rtx));
4426 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4433 (define_expand "popcount<mode>
2"
4434 [(match_operand:GPI
0 "register_operand")
4435 (match_operand:GPI
1 "register_operand")]
4438 rtx v = gen_reg_rtx (V8QImode);
4439 rtx v1 = gen_reg_rtx (V8QImode);
4440 rtx r = gen_reg_rtx (QImode);
4441 rtx in = operands[
1];
4442 rtx out = operands[
0];
4443 if(<MODE>mode == SImode)
4446 tmp = gen_reg_rtx (DImode);
4447 /* If we have SImode, zero extend to DImode, pop count does
4448 not change if we have extra zeros. */
4449 emit_insn (gen_zero_extendsidi2 (tmp, in));
4452 emit_move_insn (v, gen_lowpart (V8QImode, in));
4453 emit_insn (gen_popcountv8qi2 (v1, v));
4454 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4455 emit_insn (gen_zero_extendqi<mode>
2 (out, r));
4459 (define_insn "clrsb<mode>
2"
4460 [(set (match_operand:GPI
0 "register_operand" "=r")
4461 (clrsb:GPI (match_operand:GPI
1 "register_operand" "r")))]
4463 "cls
\\t%<w>
0, %<w>
1"
4464 [(set_attr "type" "clz")]
4467 (define_insn "rbit<mode>
2"
4468 [(set (match_operand:GPI
0 "register_operand" "=r")
4469 (unspec:GPI [(match_operand:GPI
1 "register_operand" "r")] UNSPEC_RBIT))]
4471 "rbit
\\t%<w>
0, %<w>
1"
4472 [(set_attr "type" "rbit")]
4475 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4476 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4477 ;; expression and split after reload to enable scheduling them apart if
4480 (define_insn_and_split "ctz<mode>
2"
4481 [(set (match_operand:GPI
0 "register_operand" "=r")
4482 (ctz:GPI (match_operand:GPI
1 "register_operand" "r")))]
4488 emit_insn (gen_rbit<mode>
2 (operands[
0], operands[
1]));
4489 emit_insn (gen_clz<mode>
2 (operands[
0], operands[
0]));
4493 (define_insn "*and<mode>_compare0"
4494 [(set (reg:CC_NZ CC_REGNUM)
4496 (match_operand:SHORT
0 "register_operand" "r")
4499 "tst
\\t%<w>
0, <short_mask>"
4500 [(set_attr "type" "alus_imm")]
4503 (define_insn "*ands<mode>_compare0"
4504 [(set (reg:CC_NZ CC_REGNUM)
4506 (zero_extend:GPI (match_operand:SHORT
1 "register_operand" "r"))
4508 (set (match_operand:GPI
0 "register_operand" "=r")
4509 (zero_extend:GPI (match_dup
1)))]
4511 "ands
\\t%<GPI:w>
0, %<GPI:w>
1, <short_mask>"
4512 [(set_attr "type" "alus_imm")]
4515 (define_insn "*and<mode>
3nr_compare0"
4516 [(set (reg:CC_NZ CC_REGNUM)
4518 (and:GPI (match_operand:GPI
0 "register_operand" "%r,r")
4519 (match_operand:GPI
1 "aarch64_logical_operand" "r,<lconst>"))
4525 [(set_attr "type" "logics_reg,logics_imm")]
4529 [(set (reg:CC_NZ CC_REGNUM)
4531 (and:GPI (match_operand:GPI
0 "register_operand")
4532 (match_operand:GPI
1 "aarch64_mov_imm_operand"))
4534 (clobber (match_operand:SI
2 "register_operand"))]
4536 [(set (match_dup
2) (match_dup
1))
4537 (set (reg:CC_NZ CC_REGNUM)
4539 (and:GPI (match_dup
0)
4544 (define_insn "*and<mode>
3nr_compare0_zextract"
4545 [(set (reg:CC_NZ CC_REGNUM)
4547 (zero_extract:GPI (match_operand:GPI
0 "register_operand" "r")
4548 (match_operand:GPI
1 "const_int_operand" "n")
4549 (match_operand:GPI
2 "const_int_operand" "n"))
4551 "INTVAL (operands[
1]) >
0
4552 && ((INTVAL (operands[
1]) + INTVAL (operands[
2]))
4553 <= GET_MODE_BITSIZE (<MODE>mode))
4554 && aarch64_bitmask_imm (
4555 UINTVAL (aarch64_mask_from_zextract_ops (operands[
1],
4560 = aarch64_mask_from_zextract_ops (operands[
1], operands[
2]);
4561 return "tst
\\t%<w>
0, %
1";
4563 [(set_attr "type" "logics_shift_imm")]
4566 (define_insn "*and_<SHIFT:optab><mode>
3nr_compare0"
4567 [(set (reg:CC_NZ CC_REGNUM)
4570 (match_operand:GPI
0 "register_operand" "r")
4571 (match_operand:QI
1 "aarch64_shift_imm_<mode>" "n"))
4572 (match_operand:GPI
2 "register_operand" "r"))
4575 "tst
\\t%<w>
2, %<w>
0, <SHIFT:shift> %
1"
4576 [(set_attr "type" "logics_shift_imm")]
4580 [(set (reg:CC_NZ CC_REGNUM)
4583 (match_operand:GPI
0 "register_operand")
4584 (match_operand:QI
1 "aarch64_shift_imm_<mode>"))
4585 (match_operand:GPI
2 "aarch64_mov_imm_operand"))
4587 (clobber (match_operand:SI
3 "register_operand"))]
4589 [(set (match_dup
3) (match_dup
2))
4590 (set (reg:CC_NZ CC_REGNUM)
4599 ;; -------------------------------------------------------------------
4601 ;; -------------------------------------------------------------------
4603 (define_expand "<optab><mode>
3"
4604 [(set (match_operand:GPI
0 "register_operand")
4605 (ASHIFT:GPI (match_operand:GPI
1 "register_operand")
4606 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4609 if (CONST_INT_P (operands[
2]))
4611 operands[
2] = GEN_INT (INTVAL (operands[
2])
4612 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4614 if (operands[
2] == const0_rtx)
4616 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4623 (define_expand "ashl<mode>
3"
4624 [(set (match_operand:SHORT
0 "register_operand")
4625 (ashift:SHORT (match_operand:SHORT
1 "register_operand")
4626 (match_operand:QI
2 "const_int_operand")))]
4629 operands[
2] = GEN_INT (INTVAL (operands[
2]) & GET_MODE_MASK (<MODE>mode));
4631 if (operands[
2] == const0_rtx)
4633 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4639 (define_expand "rotr<mode>
3"
4640 [(set (match_operand:GPI
0 "register_operand")
4641 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4642 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4645 if (CONST_INT_P (operands[
2]))
4647 operands[
2] = GEN_INT (INTVAL (operands[
2])
4648 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4650 if (operands[
2] == const0_rtx)
4652 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4659 (define_expand "rotl<mode>
3"
4660 [(set (match_operand:GPI
0 "register_operand")
4661 (rotatert:GPI (match_operand:GPI
1 "register_operand")
4662 (match_operand:QI
2 "aarch64_reg_or_imm")))]
4665 /* (SZ - cnt) % SZ == -cnt % SZ */
4666 if (CONST_INT_P (operands[
2]))
4668 operands[
2] = GEN_INT ((-INTVAL (operands[
2]))
4669 & (GET_MODE_BITSIZE (<MODE>mode) -
1));
4670 if (operands[
2] == const0_rtx)
4672 emit_insn (gen_mov<mode> (operands[
0], operands[
1]));
4677 operands[
2] = expand_simple_unop (QImode, NEG, operands[
2],
4682 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4683 ;; they truncate the shift/rotate amount by the size of the registers they
4684 ;; operate on:
32 for W-regs,
64 for X-regs. This allows us to optimise away
4685 ;; such redundant masking instructions. GCC can do that automatically when
4686 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4687 ;; because some of the SISD shift alternatives don't perform this truncations.
4688 ;; So this pattern exists to catch such cases.
4690 (define_insn "*aarch64_<optab>_reg_<mode>
3_mask1"
4691 [(set (match_operand:GPI
0 "register_operand" "=r")
4693 (match_operand:GPI
1 "register_operand" "r")
4694 (match_operator
4 "subreg_lowpart_operator"
4695 [(and:GPI (match_operand:GPI
2 "register_operand" "r")
4696 (match_operand
3 "const_int_operand" "n"))])))]
4697 "(~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0"
4698 "<shift>
\t%<w>
0, %<w>
1, %<w>
2"
4699 [(set_attr "type" "shift_reg")]
4702 (define_insn_and_split "*aarch64_<optab>_reg_<mode>
3_neg_mask2"
4703 [(set (match_operand:GPI
0 "register_operand" "=&r")
4705 (match_operand:GPI
1 "register_operand" "r")
4706 (match_operator
4 "subreg_lowpart_operator"
4707 [(neg:SI (and:SI (match_operand:SI
2 "register_operand" "r")
4708 (match_operand
3 "const_int_operand" "n")))])))]
4709 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)"
4714 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4715 : lowpart_subreg (SImode, operands[
0], <MODE>mode));
4716 emit_insn (gen_negsi2 (tmp, operands[
2]));
4718 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
3]);
4719 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
4]), and_op,
4720 SUBREG_BYTE (operands[
4]));
4721 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp));
4726 (define_insn_and_split "*aarch64_ashl_reg_<mode>
3_minus_mask"
4727 [(set (match_operand:GPI
0 "register_operand" "=&r")
4729 (match_operand:GPI
1 "register_operand" "r")
4730 (minus:QI (match_operand
2 "const_int_operand" "n")
4731 (match_operator
5 "subreg_lowpart_operator"
4732 [(and:SI (match_operand:SI
3 "register_operand" "r")
4733 (match_operand
4 "const_int_operand" "n"))]))))]
4734 "((~INTVAL (operands[
4]) & (GET_MODE_BITSIZE (<MODE>mode) -
1)) ==
0)
4735 && INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4740 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4743 emit_insn (gen_negsi2 (tmp, operands[
3]));
4745 rtx and_op = gen_rtx_AND (SImode, tmp, operands[
4]);
4746 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[
5]), and_op,
4747 SUBREG_BYTE (operands[
5]));
4749 emit_insn (gen_ashl<mode>
3 (operands[
0], operands[
1], subreg_tmp));
4754 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4755 [(set (match_operand:DI
0 "register_operand" "=r")
4757 (match_operand:DI
1 "register_operand" "r")
4758 (match_operator
4 "subreg_lowpart_operator"
4759 [(and:SI (match_operand:SI
2 "register_operand" "r")
4760 (match_operand
3 "const_int_operand" "n"))])))]
4761 "((~INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode) -
1)) ==
0)"
4764 xop[
0] = operands[
0];
4765 xop[
1] = operands[
1];
4766 xop[
2] = gen_lowpart (GET_MODE (operands[
4]), operands[
2]);
4767 output_asm_insn ("<shift>
\t%x0, %x1, %x2", xop);
4770 [(set_attr "type" "shift_reg")]
4773 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>
3"
4774 [(set (match_operand:GPI
0 "register_operand" "=&r")
4776 (match_operand:GPI
1 "register_operand" "r")
4777 (minus:QI (match_operand
2 "const_int_operand" "n")
4778 (match_operand:QI
3 "register_operand" "r"))))]
4779 "INTVAL (operands[
2]) == GET_MODE_BITSIZE (<MODE>mode)"
4784 rtx subreg_tmp = gen_lowpart (SImode, operands[
3]);
4786 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4787 : gen_lowpart (SImode, operands[
0]));
4789 emit_insn (gen_negsi2 (tmp, subreg_tmp));
4791 rtx and_op = gen_rtx_AND (SImode, tmp,
4792 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
1));
4794 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
4796 emit_insn (gen_<optab><mode>
3 (operands[
0], operands[
1], subreg_tmp2));
4799 [(set_attr "length" "
8")]
4802 ;; Logical left shift using SISD or Integer instruction
4803 (define_insn "*aarch64_ashl_sisd_or_int_<mode>
3"
4804 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,w")
4806 (match_operand:GPI
1 "register_operand" "r,r,w,w")
4807 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4810 lsl
\t%<w>
0, %<w>
1, %
2
4811 lsl
\t%<w>
0, %<w>
1, %<w>
2
4812 shl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4813 ushl
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %<rtn>
2<vas>"
4814 [(set_attr "simd" "no,no,yes,yes")
4815 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4818 ;; Logical right shift using SISD or Integer instruction
4819 (define_insn "*aarch64_lshr_sisd_or_int_<mode>
3"
4820 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4822 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4823 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>"
4824 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4827 lsr
\t%<w>
0, %<w>
1, %
2
4828 lsr
\t%<w>
0, %<w>
1, %<w>
2
4829 ushr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4832 [(set_attr "simd" "no,no,yes,yes,yes")
4833 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4837 [(set (match_operand:DI
0 "aarch64_simd_register")
4839 (match_operand:DI
1 "aarch64_simd_register")
4840 (match_operand:QI
2 "aarch64_simd_register")))]
4841 "TARGET_SIMD && reload_completed"
4843 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4845 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_USHL))]
4847 operands[
3] = gen_lowpart (QImode, operands[
0]);
4852 [(set (match_operand:SI
0 "aarch64_simd_register")
4854 (match_operand:SI
1 "aarch64_simd_register")
4855 (match_operand:QI
2 "aarch64_simd_register")))]
4856 "TARGET_SIMD && reload_completed"
4858 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4860 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_USHL_2S))]
4862 operands[
3] = gen_lowpart (QImode, operands[
0]);
4866 ;; Arithmetic right shift using SISD or Integer instruction
4867 (define_insn "*aarch64_ashr_sisd_or_int_<mode>
3"
4868 [(set (match_operand:GPI
0 "register_operand" "=r,r,w,&w,&w")
4870 (match_operand:GPI
1 "register_operand" "r,r,w,w,w")
4871 (match_operand:QI
2 "aarch64_reg_or_shift_imm_di"
4872 "Us<cmode>,r,Us<cmode_simd>,w,
0")))]
4875 asr
\t%<w>
0, %<w>
1, %
2
4876 asr
\t%<w>
0, %<w>
1, %<w>
2
4877 sshr
\t%<rtn>
0<vas>, %<rtn>
1<vas>, %
2
4880 [(set_attr "simd" "no,no,yes,yes,yes")
4881 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4885 [(set (match_operand:DI
0 "aarch64_simd_register")
4887 (match_operand:DI
1 "aarch64_simd_register")
4888 (match_operand:QI
2 "aarch64_simd_register")))]
4889 "TARGET_SIMD && reload_completed"
4891 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4893 (unspec:DI [(match_dup
1) (match_dup
3)] UNSPEC_SISD_SSHL))]
4895 operands[
3] = gen_lowpart (QImode, operands[
0]);
4900 [(set (match_operand:SI
0 "aarch64_simd_register")
4902 (match_operand:SI
1 "aarch64_simd_register")
4903 (match_operand:QI
2 "aarch64_simd_register")))]
4904 "TARGET_SIMD && reload_completed"
4906 (unspec:QI [(match_dup
2)] UNSPEC_SISD_NEG))
4908 (unspec:SI [(match_dup
1) (match_dup
3)] UNSPEC_SSHL_2S))]
4910 operands[
3] = gen_lowpart (QImode, operands[
0]);
4914 (define_insn "*aarch64_sisd_ushl"
4915 [(set (match_operand:DI
0 "register_operand" "=w")
4916 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4917 (match_operand:QI
2 "register_operand" "w")]
4920 "ushl
\t%d0, %d1, %d2"
4921 [(set_attr "simd" "yes")
4922 (set_attr "type" "neon_shift_reg")]
4925 (define_insn "*aarch64_ushl_2s"
4926 [(set (match_operand:SI
0 "register_operand" "=w")
4927 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4928 (match_operand:QI
2 "register_operand" "w")]
4931 "ushl
\t%
0.2s, %
1.2s, %
2.2s"
4932 [(set_attr "simd" "yes")
4933 (set_attr "type" "neon_shift_reg")]
4936 (define_insn "*aarch64_sisd_sshl"
4937 [(set (match_operand:DI
0 "register_operand" "=w")
4938 (unspec:DI [(match_operand:DI
1 "register_operand" "w")
4939 (match_operand:QI
2 "register_operand" "w")]
4942 "sshl
\t%d0, %d1, %d2"
4943 [(set_attr "simd" "yes")
4944 (set_attr "type" "neon_shift_reg")]
4947 (define_insn "*aarch64_sshl_2s"
4948 [(set (match_operand:SI
0 "register_operand" "=w")
4949 (unspec:SI [(match_operand:SI
1 "register_operand" "w")
4950 (match_operand:QI
2 "register_operand" "w")]
4953 "sshl
\t%
0.2s, %
1.2s, %
2.2s"
4954 [(set_attr "simd" "yes")
4955 (set_attr "type" "neon_shift_reg")]
4958 (define_insn "*aarch64_sisd_neg_qi"
4959 [(set (match_operand:QI
0 "register_operand" "=w")
4960 (unspec:QI [(match_operand:QI
1 "register_operand" "w")]
4964 [(set_attr "simd" "yes")
4965 (set_attr "type" "neon_neg")]
4969 (define_insn "*ror<mode>
3_insn"
4970 [(set (match_operand:GPI
0 "register_operand" "=r,r")
4972 (match_operand:GPI
1 "register_operand" "r,r")
4973 (match_operand:QI
2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4976 ror
\\t%<w>
0, %<w>
1, %
2
4977 ror
\\t%<w>
0, %<w>
1, %<w>
2"
4978 [(set_attr "type" "rotate_imm,shift_reg")]
4981 ;; zero_extend version of above
4982 (define_insn "*<optab>si3_insn_uxtw"
4983 [(set (match_operand:DI
0 "register_operand" "=r,r")
4984 (zero_extend:DI (SHIFT:SI
4985 (match_operand:SI
1 "register_operand" "r,r")
4986 (match_operand:QI
2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4989 <shift>
\\t%w0, %w1, %
2
4990 <shift>
\\t%w0, %w1, %w2"
4991 [(set_attr "type" "bfx,shift_reg")]
4994 (define_insn "*<optab><mode>
3_insn"
4995 [(set (match_operand:SHORT
0 "register_operand" "=r")
4996 (ASHIFT:SHORT (match_operand:SHORT
1 "register_operand" "r")
4997 (match_operand
2 "const_int_operand" "n")))]
4998 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5000 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5001 return "<bfshift>
\t%w0, %w1, %
2, %
3";
5003 [(set_attr "type" "bfx")]
5006 (define_insn "*extr<mode>
5_insn"
5007 [(set (match_operand:GPI
0 "register_operand" "=r")
5008 (ior:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5009 (match_operand
3 "const_int_operand" "n"))
5010 (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5011 (match_operand
4 "const_int_operand" "n"))))]
5012 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5013 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) == GET_MODE_BITSIZE (<MODE>mode))"
5014 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5015 [(set_attr "type" "rotate_imm")]
5018 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5019 ;; so we have to match both orderings.
5020 (define_insn "*extr<mode>
5_insn_alt"
5021 [(set (match_operand:GPI
0 "register_operand" "=r")
5022 (ior:GPI (lshiftrt:GPI (match_operand:GPI
2 "register_operand" "r")
5023 (match_operand
4 "const_int_operand" "n"))
5024 (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5025 (match_operand
3 "const_int_operand" "n"))))]
5026 "UINTVAL (operands[
3]) < GET_MODE_BITSIZE (<MODE>mode)
5027 && (UINTVAL (operands[
3]) + UINTVAL (operands[
4])
5028 == GET_MODE_BITSIZE (<MODE>mode))"
5029 "extr
\\t%<w>
0, %<w>
1, %<w>
2, %
4"
5030 [(set_attr "type" "rotate_imm")]
5033 ;; zero_extend version of the above
5034 (define_insn "*extrsi5_insn_uxtw"
5035 [(set (match_operand:DI
0 "register_operand" "=r")
5037 (ior:SI (ashift:SI (match_operand:SI
1 "register_operand" "r")
5038 (match_operand
3 "const_int_operand" "n"))
5039 (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5040 (match_operand
4 "const_int_operand" "n")))))]
5041 "UINTVAL (operands[
3]) <
32 &&
5042 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5043 "extr
\\t%w0, %w1, %w2, %
4"
5044 [(set_attr "type" "rotate_imm")]
5047 (define_insn "*extrsi5_insn_uxtw_alt"
5048 [(set (match_operand:DI
0 "register_operand" "=r")
5050 (ior:SI (lshiftrt:SI (match_operand:SI
2 "register_operand" "r")
5051 (match_operand
4 "const_int_operand" "n"))
5052 (ashift:SI (match_operand:SI
1 "register_operand" "r")
5053 (match_operand
3 "const_int_operand" "n")))))]
5054 "UINTVAL (operands[
3]) <
32 &&
5055 (UINTVAL (operands[
3]) + UINTVAL (operands[
4]) ==
32)"
5056 "extr
\\t%w0, %w1, %w2, %
4"
5057 [(set_attr "type" "rotate_imm")]
5060 (define_insn "*ror<mode>
3_insn"
5061 [(set (match_operand:GPI
0 "register_operand" "=r")
5062 (rotate:GPI (match_operand:GPI
1 "register_operand" "r")
5063 (match_operand
2 "const_int_operand" "n")))]
5064 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<MODE>mode)"
5066 operands[
3] = GEN_INT (<sizen> - UINTVAL (operands[
2]));
5067 return "ror
\\t%<w>
0, %<w>
1, %
3";
5069 [(set_attr "type" "rotate_imm")]
5072 ;; zero_extend version of the above
5073 (define_insn "*rorsi3_insn_uxtw"
5074 [(set (match_operand:DI
0 "register_operand" "=r")
5076 (rotate:SI (match_operand:SI
1 "register_operand" "r")
5077 (match_operand
2 "const_int_operand" "n"))))]
5078 "UINTVAL (operands[
2]) <
32"
5080 operands[
3] = GEN_INT (
32 - UINTVAL (operands[
2]));
5081 return "ror
\\t%w0, %w1, %
3";
5083 [(set_attr "type" "rotate_imm")]
5086 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5087 [(set (match_operand:GPI
0 "register_operand" "=r")
5089 (ashift:SHORT (match_operand:SHORT
1 "register_operand" "r")
5090 (match_operand
2 "const_int_operand" "n"))))]
5091 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5093 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5094 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5096 [(set_attr "type" "bfx")]
5099 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5100 [(set (match_operand:GPI
0 "register_operand" "=r")
5102 (lshiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5103 (match_operand
2 "const_int_operand" "n"))))]
5104 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5106 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5107 return "ubfx
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5109 [(set_attr "type" "bfx")]
5112 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5113 [(set (match_operand:GPI
0 "register_operand" "=r")
5115 (ashiftrt:SHORT (match_operand:SHORT
1 "register_operand" "r")
5116 (match_operand
2 "const_int_operand" "n"))))]
5117 "UINTVAL (operands[
2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5119 operands[
3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[
2]));
5120 return "sbfx
\\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5122 [(set_attr "type" "bfx")]
5125 ;; -------------------------------------------------------------------
5127 ;; -------------------------------------------------------------------
5129 (define_expand "<optab>"
5130 [(set (match_operand:DI
0 "register_operand" "=r")
5131 (ANY_EXTRACT:DI (match_operand:DI
1 "register_operand")
5133 "aarch64_simd_shift_imm_offset_di")
5134 (match_operand
3 "aarch64_simd_shift_imm_di")))]
5137 if (!IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5138 1, GET_MODE_BITSIZE (DImode) -
1))
5144 (define_insn "*<optab><mode>"
5145 [(set (match_operand:GPI
0 "register_operand" "=r")
5146 (ANY_EXTRACT:GPI (match_operand:GPI
1 "register_operand" "r")
5148 "aarch64_simd_shift_imm_offset_<mode>" "n")
5150 "aarch64_simd_shift_imm_<mode>" "n")))]
5151 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5152 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5153 "<su>bfx
\\t%<w>
0, %<w>
1, %
3, %
2"
5154 [(set_attr "type" "bfx")]
5157 ;; When the bit position and width add up to
32 we can use a W-reg LSR
5158 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5160 [(set (match_operand:DI
0 "register_operand")
5161 (zero_extract:DI (match_operand:DI
1 "register_operand")
5163 "aarch64_simd_shift_imm_offset_di")
5165 "aarch64_simd_shift_imm_di")))]
5166 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
1,
5167 GET_MODE_BITSIZE (DImode) -
1)
5168 && (INTVAL (operands[
2]) + INTVAL (operands[
3]))
5169 == GET_MODE_BITSIZE (SImode)"
5171 (zero_extend:DI (lshiftrt:SI (match_dup
4) (match_dup
3))))]
5173 operands[
4] = gen_lowpart (SImode, operands[
1]);
5177 ;; Bitfield Insert (insv)
5178 (define_expand "insv<mode>"
5179 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand")
5180 (match_operand
1 "const_int_operand")
5181 (match_operand
2 "const_int_operand"))
5182 (match_operand:GPI
3 "general_operand"))]
5185 unsigned HOST_WIDE_INT width = UINTVAL (operands[
1]);
5186 unsigned HOST_WIDE_INT pos = UINTVAL (operands[
2]);
5187 rtx value = operands[
3];
5189 if (width ==
0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5192 if (CONST_INT_P (value))
5194 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)
1 << width) -
1;
5196 /* Prefer AND/OR for inserting all zeros or all ones. */
5197 if ((UINTVAL (value) & mask) ==
0
5198 || (UINTVAL (value) & mask) == mask)
5201 /*
16-bit aligned
16-bit wide insert is handled by insv_imm. */
5202 if (width ==
16 && (pos %
16) ==
0)
5205 operands[
3] = force_reg (<MODE>mode, value);
5208 (define_insn "*insv_reg<mode>"
5209 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5210 (match_operand
1 "const_int_operand" "n")
5211 (match_operand
2 "const_int_operand" "n"))
5212 (match_operand:GPI
3 "register_operand" "r"))]
5213 "!(UINTVAL (operands[
1]) ==
0
5214 || (UINTVAL (operands[
2]) + UINTVAL (operands[
1])
5215 > GET_MODE_BITSIZE (<MODE>mode)))"
5216 "bfi
\\t%<w>
0, %<w>
3, %
2, %
1"
5217 [(set_attr "type" "bfm")]
5220 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>
4"
5221 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5222 (match_operand
1 "const_int_operand" "n")
5223 (match_operand
2 "const_int_operand" "n"))
5224 (zero_extend:GPI (match_operand:ALLX
3 "register_operand" "r")))]
5225 "UINTVAL (operands[
1]) <= <ALLX:sizen>"
5226 "bfi
\\t%<GPI:w>
0, %<GPI:w>
3, %
2, %
1"
5227 [(set_attr "type" "bfm")]
5230 (define_insn "*extr_insv_lower_reg<mode>"
5231 [(set (zero_extract:GPI (match_operand:GPI
0 "register_operand" "+r")
5232 (match_operand
1 "const_int_operand" "n")
5234 (zero_extract:GPI (match_operand:GPI
2 "register_operand" "r")
5236 (match_operand
3 "const_int_operand" "n")))]
5237 "!(UINTVAL (operands[
1]) ==
0
5238 || (UINTVAL (operands[
3]) + UINTVAL (operands[
1])
5239 > GET_MODE_BITSIZE (<MODE>mode)))"
5240 "bfxil
\\t%<w>
0, %<w>
2, %
3, %
1"
5241 [(set_attr "type" "bfm")]
5244 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5245 [(set (match_operand:GPI
0 "register_operand" "=r")
5246 (ashift:GPI (ANY_EXTEND:GPI
5247 (match_operand:ALLX
1 "register_operand" "r"))
5248 (match_operand
2 "const_int_operand" "n")))]
5249 "UINTVAL (operands[
2]) < <GPI:sizen>"
5251 operands[
3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[
2])))
5252 ? GEN_INT (<ALLX:sizen>)
5253 : GEN_INT (<GPI:sizen> - UINTVAL (operands[
2]));
5254 return "<su>bfiz
\t%<GPI:w>
0, %<GPI:w>
1, %
2, %
3";
5256 [(set_attr "type" "bfx")]
5259 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5261 (define_insn "*andim_ashift<mode>_bfiz"
5262 [(set (match_operand:GPI
0 "register_operand" "=r")
5263 (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5264 (match_operand
2 "const_int_operand" "n"))
5265 (match_operand
3 "const_int_operand" "n")))]
5266 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[
3], operands[
2])"
5267 "ubfiz
\\t%<w>
0, %<w>
1, %
2, %P3"
5268 [(set_attr "type" "bfx")]
5271 ;; Match sbfiz pattern in a shift left + shift right operation.
5273 (define_insn "*ashift<mode>_extv_bfiz"
5274 [(set (match_operand:GPI
0 "register_operand" "=r")
5275 (ashift:GPI (sign_extract:GPI (match_operand:GPI
1 "register_operand" "r")
5276 (match_operand
2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5278 (match_operand
3 "aarch64_simd_shift_imm_<mode>" "n")))]
5279 "IN_RANGE (INTVAL (operands[
2]) + INTVAL (operands[
3]),
5280 1, GET_MODE_BITSIZE (<MODE>mode) -
1)"
5281 "sbfiz
\\t%<w>
0, %<w>
1, %
3, %
2"
5282 [(set_attr "type" "bfx")]
5285 ;; When the bit position and width of the equivalent extraction add up to
32
5286 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5287 ;; zero-extension of the X-reg.
5289 [(set (match_operand:DI
0 "register_operand")
5290 (and:DI (ashift:DI (match_operand:DI
1 "register_operand")
5291 (match_operand
2 "const_int_operand"))
5292 (match_operand
3 "const_int_operand")))]
5293 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[
3], operands[
2])
5294 && (INTVAL (operands[
2]) + popcount_hwi (INTVAL (operands[
3])))
5295 == GET_MODE_BITSIZE (SImode)"
5297 (zero_extend:DI (ashift:SI (match_dup
4) (match_dup
2))))]
5299 operands[
4] = gen_lowpart (SImode, operands[
1]);
5303 (define_insn "bswap<mode>
2"
5304 [(set (match_operand:GPI
0 "register_operand" "=r")
5305 (bswap:GPI (match_operand:GPI
1 "register_operand" "r")))]
5307 "rev
\\t%<w>
0, %<w>
1"
5308 [(set_attr "type" "rev")]
5311 (define_insn "bswaphi2"
5312 [(set (match_operand:HI
0 "register_operand" "=r")
5313 (bswap:HI (match_operand:HI
1 "register_operand" "r")))]
5316 [(set_attr "type" "rev")]
5319 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5320 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5321 ;; each valid permutation.
5323 (define_insn "rev16<mode>
2"
5324 [(set (match_operand:GPI
0 "register_operand" "=r")
5325 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI
1 "register_operand" "r")
5327 (match_operand:GPI
3 "const_int_operand" "n"))
5328 (and:GPI (lshiftrt:GPI (match_dup
1)
5330 (match_operand:GPI
2 "const_int_operand" "n"))))]
5331 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5332 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5333 "rev16
\\t%<w>
0, %<w>
1"
5334 [(set_attr "type" "rev")]
5337 (define_insn "rev16<mode>
2_alt"
5338 [(set (match_operand:GPI
0 "register_operand" "=r")
5339 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI
1 "register_operand" "r")
5341 (match_operand:GPI
2 "const_int_operand" "n"))
5342 (and:GPI (ashift:GPI (match_dup
1)
5344 (match_operand:GPI
3 "const_int_operand" "n"))))]
5345 "aarch_rev16_shleft_mask_imm_p (operands[
3], <MODE>mode)
5346 && aarch_rev16_shright_mask_imm_p (operands[
2], <MODE>mode)"
5347 "rev16
\\t%<w>
0, %<w>
1"
5348 [(set_attr "type" "rev")]
5351 ;; zero_extend version of above
5352 (define_insn "*bswapsi2_uxtw"
5353 [(set (match_operand:DI
0 "register_operand" "=r")
5354 (zero_extend:DI (bswap:SI (match_operand:SI
1 "register_operand" "r"))))]
5357 [(set_attr "type" "rev")]
5360 ;; -------------------------------------------------------------------
5361 ;; Floating-point intrinsics
5362 ;; -------------------------------------------------------------------
5364 ;; frint floating-point round to integral standard patterns.
5365 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5367 (define_insn "<frint_pattern><mode>
2"
5368 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5369 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5372 "frint<frint_suffix>
\\t%<s>
0, %<s>
1"
5373 [(set_attr "type" "f_rint<stype>")]
5376 ;; frcvt floating-point round to integer and convert standard patterns.
5377 ;; Expands to lbtrunc, lceil, lfloor, lround.
5378 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>
2"
5379 [(set (match_operand:GPI
0 "register_operand" "=r")
5381 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")]
5384 "fcvt<frint_suffix><su>
\\t%<GPI:w>
0, %<GPF_F16:s>
1"
5385 [(set_attr "type" "f_cvtf2i")]
5388 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>
2_mult"
5389 [(set (match_operand:GPI
0 "register_operand" "=r")
5392 (match_operand:GPF
1 "register_operand" "w")
5393 (match_operand:GPF
2 "aarch64_fp_pow2" "F"))))]
5395 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[
2]),
1,
5396 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5398 int fbits = aarch64_fpconst_pow_of_2 (operands[
2]);
5400 snprintf (buf,
64, "fcvtz<su>
\\t%%<GPI:w>
0, %%<GPF:s>
1, #%d", fbits);
5401 output_asm_insn (buf, operands);
5404 [(set_attr "type" "f_cvtf2i")]
5407 ;; fma - expand fma into patterns with the accumulator operand first since
5408 ;; reusing the accumulator results in better register allocation.
5409 ;; The register allocator considers copy preferences in operand order,
5410 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5412 (define_expand "fma<mode>
4"
5413 [(set (match_operand:GPF_F16
0 "register_operand")
5414 (fma:GPF_F16 (match_operand:GPF_F16
1 "register_operand")
5415 (match_operand:GPF_F16
2 "register_operand")
5416 (match_operand:GPF_F16
3 "register_operand")))]
5420 (define_insn "*aarch64_fma<mode>
4"
5421 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5422 (fma:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w")
5423 (match_operand:GPF_F16
3 "register_operand" "w")
5424 (match_operand:GPF_F16
1 "register_operand" "w")))]
5426 "fmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5427 [(set_attr "type" "fmac<stype>")]
5430 (define_expand "fnma<mode>
4"
5431 [(set (match_operand:GPF_F16
0 "register_operand")
5433 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand"))
5434 (match_operand:GPF_F16
2 "register_operand")
5435 (match_operand:GPF_F16
3 "register_operand")))]
5439 (define_insn "*aarch64_fnma<mode>
4"
5440 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5442 (neg:GPF_F16 (match_operand:GPF_F16
2 "register_operand" "w"))
5443 (match_operand:GPF_F16
3 "register_operand" "w")
5444 (match_operand:GPF_F16
1 "register_operand" "w")))]
5446 "fmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5447 [(set_attr "type" "fmac<stype>")]
5451 (define_expand "fms<mode>
4"
5452 [(set (match_operand:GPF
0 "register_operand")
5453 (fma:GPF (match_operand:GPF
1 "register_operand")
5454 (match_operand:GPF
2 "register_operand")
5455 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5459 (define_insn "*aarch64_fms<mode>
4"
5460 [(set (match_operand:GPF
0 "register_operand" "=w")
5461 (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5462 (match_operand:GPF
3 "register_operand" "w")
5463 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5465 "fnmsub
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5466 [(set_attr "type" "fmac<s>")]
5469 (define_expand "fnms<mode>
4"
5470 [(set (match_operand:GPF
0 "register_operand")
5471 (fma:GPF (neg:GPF (match_operand:GPF
1 "register_operand"))
5472 (match_operand:GPF
2 "register_operand")
5473 (neg:GPF (match_operand:GPF
3 "register_operand"))))]
5477 (define_insn "*aarch64_fnms<mode>
4"
5478 [(set (match_operand:GPF
0 "register_operand" "=w")
5479 (fma:GPF (neg:GPF (match_operand:GPF
2 "register_operand" "w"))
5480 (match_operand:GPF
3 "register_operand" "w")
5481 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))))]
5483 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5484 [(set_attr "type" "fmac<s>")]
5487 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5488 (define_insn "*aarch64_fnmadd<mode>
4"
5489 [(set (match_operand:GPF
0 "register_operand" "=w")
5490 (neg:GPF (fma:GPF (match_operand:GPF
2 "register_operand" "w")
5491 (match_operand:GPF
3 "register_operand" "w")
5492 (match_operand:GPF
1 "register_operand" "w"))))]
5493 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5494 "fnmadd
\\t%<s>
0, %<s>
2, %<s>
3, %<s>
1"
5495 [(set_attr "type" "fmac<s>")]
5498 ;; -------------------------------------------------------------------
5499 ;; Floating-point conversions
5500 ;; -------------------------------------------------------------------
5502 (define_insn "extendsfdf2"
5503 [(set (match_operand:DF
0 "register_operand" "=w")
5504 (float_extend:DF (match_operand:SF
1 "register_operand" "w")))]
5507 [(set_attr "type" "f_cvt")]
5510 (define_insn "extendhfsf2"
5511 [(set (match_operand:SF
0 "register_operand" "=w")
5512 (float_extend:SF (match_operand:HF
1 "register_operand" "w")))]
5515 [(set_attr "type" "f_cvt")]
5518 (define_insn "extendhfdf2"
5519 [(set (match_operand:DF
0 "register_operand" "=w")
5520 (float_extend:DF (match_operand:HF
1 "register_operand" "w")))]
5523 [(set_attr "type" "f_cvt")]
5526 (define_insn "truncdfsf2"
5527 [(set (match_operand:SF
0 "register_operand" "=w")
5528 (float_truncate:SF (match_operand:DF
1 "register_operand" "w")))]
5531 [(set_attr "type" "f_cvt")]
5534 (define_insn "truncsfhf2"
5535 [(set (match_operand:HF
0 "register_operand" "=w")
5536 (float_truncate:HF (match_operand:SF
1 "register_operand" "w")))]
5539 [(set_attr "type" "f_cvt")]
5542 (define_insn "truncdfhf2"
5543 [(set (match_operand:HF
0 "register_operand" "=w")
5544 (float_truncate:HF (match_operand:DF
1 "register_operand" "w")))]
5547 [(set_attr "type" "f_cvt")]
5550 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5551 ;; and making r = w more expensive
5553 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>
2"
5554 [(set (match_operand:GPI
0 "register_operand" "=w,?r")
5555 (FIXUORS:GPI (match_operand:<FCVT_TARGET>
1 "register_operand" "w,w")))]
5558 fcvtz<su>
\t%<s>
0, %<s>
1
5559 fcvtz<su>
\t%<w>
0, %<s>
1"
5560 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5563 ;; Convert HF -> SI or DI
5565 (define_insn "<optab>_trunchf<GPI:mode>
2"
5566 [(set (match_operand:GPI
0 "register_operand" "=r")
5567 (FIXUORS:GPI (match_operand:HF
1 "register_operand" "w")))]
5569 "fcvtz<su>
\t%<w>
0, %h1"
5570 [(set_attr "type" "f_cvtf2i")]
5573 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5574 ;; input in a fp register and output in a integer register
5576 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>
2"
5577 [(set (match_operand:GPI
0 "register_operand" "=r")
5578 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE>
1 "register_operand" "w")))]
5580 "fcvtz<su>
\t%<w>
0, %<fpw>
1"
5581 [(set_attr "type" "f_cvtf2i")]
5584 (define_insn "*fix_to_zero_extend<mode>di2"
5585 [(set (match_operand:DI
0 "register_operand" "=r")
5588 (match_operand:GPF
1 "register_operand" "w"))))]
5590 "fcvtzu
\t%w0, %<s>
1"
5591 [(set_attr "type" "f_cvtf2i")]
5594 (define_insn "<optab><fcvt_target><GPF:mode>
2"
5595 [(set (match_operand:GPF
0 "register_operand" "=w,w")
5596 (FLOATUORS:GPF (match_operand:<FCVT_TARGET>
1 "register_operand" "w,?r")))]
5599 <su_optab>cvtf
\t%<GPF:s>
0, %<s>
1
5600 <su_optab>cvtf
\t%<GPF:s>
0, %<w1>
1"
5601 [(set_attr "simd" "yes,no")
5602 (set_attr "fp" "no,yes")
5603 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
5606 (define_insn "<optab><fcvt_iesize><GPF:mode>
2"
5607 [(set (match_operand:GPF
0 "register_operand" "=w")
5608 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE>
1 "register_operand" "r")))]
5610 "<su_optab>cvtf
\t%<GPF:s>
0, %<w2>
1"
5611 [(set_attr "type" "f_cvti2f")]
5614 ;; If we do not have ARMv8.2-A
16-bit floating point extensions, the
5615 ;; midend will arrange for an SImode conversion to HFmode to first go
5616 ;; through DFmode, then to HFmode. But first it will try converting
5617 ;; to DImode then down, which would match our DImode pattern below and
5618 ;; give very poor code-generation. So, we must provide our own emulation
5619 ;; of the mid-end logic.
5621 (define_insn "aarch64_fp16_<optab><mode>hf2"
5622 [(set (match_operand:HF
0 "register_operand" "=w")
5623 (FLOATUORS:HF (match_operand:GPI
1 "register_operand" "r")))]
5625 "<su_optab>cvtf
\t%h0, %<w>
1"
5626 [(set_attr "type" "f_cvti2f")]
5629 (define_expand "<optab>sihf2"
5630 [(set (match_operand:HF
0 "register_operand")
5631 (FLOATUORS:HF (match_operand:SI
1 "register_operand")))]
5634 if (TARGET_FP_F16INST)
5635 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[
0], operands[
1]));
5638 rtx convert_target = gen_reg_rtx (DFmode);
5639 emit_insn (gen_<optab>sidf2 (convert_target, operands[
1]));
5640 emit_insn (gen_truncdfhf2 (operands[
0], convert_target));
5646 ;; For DImode there is no wide enough floating-point mode that we
5647 ;; can convert through natively (TFmode would work, but requires a library
5648 ;; call). However, we know that any value >=
65504 will be rounded
5649 ;; to infinity on conversion. This is well within the range of SImode, so
5651 ;; Saturate to SImode.
5652 ;; Convert from that to DFmode
5653 ;; Convert from that to HFmode (phew!).
5654 ;; Note that the saturation to SImode requires the SIMD extensions. If
5655 ;; we ever need to provide this pattern where the SIMD extensions are not
5656 ;; available, we would need a different approach.
5658 (define_expand "<optab>dihf2"
5659 [(set (match_operand:HF
0 "register_operand")
5660 (FLOATUORS:HF (match_operand:DI
1 "register_operand")))]
5661 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
5663 if (TARGET_FP_F16INST)
5664 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[
0], operands[
1]));
5667 rtx sat_target = gen_reg_rtx (SImode);
5668 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[
1]));
5669 emit_insn (gen_<optab>sihf2 (operands[
0], sat_target));
5676 ;; Convert between fixed-point and floating-point (scalar modes)
5678 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>
3"
5679 [(set (match_operand:<GPF:FCVT_TARGET>
0 "register_operand" "=r, w")
5680 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF
1 "register_operand" "w, w")
5681 (match_operand:SI
2 "immediate_operand" "i, i")]
5685 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:w1>
0, %<GPF:s>
1, #%
2
5686 <FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPF:s>
0, %<GPF:s>
1, #%
2"
5687 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
5688 (set_attr "fp" "yes, *")
5689 (set_attr "simd" "*, yes")]
5692 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>
3"
5693 [(set (match_operand:<GPI:FCVT_TARGET>
0 "register_operand" "=w, w")
5694 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI
1 "register_operand" "r, w")
5695 (match_operand:SI
2 "immediate_operand" "i, i")]
5699 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:w>
1, #%
2
5700 <FCVT_FIXED2F:fcvt_fixed_insn>
\t%<GPI:v>
0, %<GPI:v>
1, #%
2"
5701 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
5702 (set_attr "fp" "yes, *")
5703 (set_attr "simd" "*, yes")]
5706 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>
3"
5707 [(set (match_operand:GPI
0 "register_operand" "=r")
5708 (unspec:GPI [(match_operand:HF
1 "register_operand" "w")
5709 (match_operand:SI
2 "immediate_operand" "i")]
5712 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%<GPI:w>
0, %h1, #%
2"
5713 [(set_attr "type" "f_cvtf2i")]
5716 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
5717 [(set (match_operand:HF
0 "register_operand" "=w")
5718 (unspec:HF [(match_operand:GPI
1 "register_operand" "r")
5719 (match_operand:SI
2 "immediate_operand" "i")]
5722 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %<GPI:w>
1, #%
2"
5723 [(set_attr "type" "f_cvti2f")]
5726 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
5727 [(set (match_operand:HI
0 "register_operand" "=w")
5728 (unspec:HI [(match_operand:HF
1 "register_operand" "w")
5729 (match_operand:SI
2 "immediate_operand" "i")]
5732 "<FCVT_F2FIXED:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5733 [(set_attr "type" "neon_fp_to_int_s")]
5736 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
5737 [(set (match_operand:HF
0 "register_operand" "=w")
5738 (unspec:HF [(match_operand:HI
1 "register_operand" "w")
5739 (match_operand:SI
2 "immediate_operand" "i")]
5742 "<FCVT_FIXED2F:fcvt_fixed_insn>
\t%h0, %h1, #%
2"
5743 [(set_attr "type" "neon_int_to_fp_s")]
5746 ;; -------------------------------------------------------------------
5747 ;; Floating-point arithmetic
5748 ;; -------------------------------------------------------------------
5750 (define_insn "add<mode>
3"
5751 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5753 (match_operand:GPF_F16
1 "register_operand" "w")
5754 (match_operand:GPF_F16
2 "register_operand" "w")))]
5756 "fadd
\\t%<s>
0, %<s>
1, %<s>
2"
5757 [(set_attr "type" "fadd<stype>")]
5760 (define_insn "sub<mode>
3"
5761 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5763 (match_operand:GPF_F16
1 "register_operand" "w")
5764 (match_operand:GPF_F16
2 "register_operand" "w")))]
5766 "fsub
\\t%<s>
0, %<s>
1, %<s>
2"
5767 [(set_attr "type" "fadd<stype>")]
5770 (define_insn "mul<mode>
3"
5771 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5773 (match_operand:GPF_F16
1 "register_operand" "w")
5774 (match_operand:GPF_F16
2 "register_operand" "w")))]
5776 "fmul
\\t%<s>
0, %<s>
1, %<s>
2"
5777 [(set_attr "type" "fmul<stype>")]
5780 (define_insn "*fnmul<mode>
3"
5781 [(set (match_operand:GPF
0 "register_operand" "=w")
5783 (neg:GPF (match_operand:GPF
1 "register_operand" "w"))
5784 (match_operand:GPF
2 "register_operand" "w")))]
5785 "TARGET_FLOAT && !flag_rounding_math"
5786 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5787 [(set_attr "type" "fmul<s>")]
5790 (define_insn "*fnmul<mode>
3"
5791 [(set (match_operand:GPF
0 "register_operand" "=w")
5793 (match_operand:GPF
1 "register_operand" "w")
5794 (match_operand:GPF
2 "register_operand" "w"))))]
5796 "fnmul
\\t%<s>
0, %<s>
1, %<s>
2"
5797 [(set_attr "type" "fmul<s>")]
5800 (define_expand "div<mode>
3"
5801 [(set (match_operand:GPF_F16
0 "register_operand")
5802 (div:GPF_F16 (match_operand:GPF_F16
1 "general_operand")
5803 (match_operand:GPF_F16
2 "register_operand")))]
5806 if (aarch64_emit_approx_div (operands[
0], operands[
1], operands[
2]))
5809 operands[
1] = force_reg (<MODE>mode, operands[
1]);
5812 (define_insn "*div<mode>
3"
5813 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5814 (div:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")
5815 (match_operand:GPF_F16
2 "register_operand" "w")))]
5817 "fdiv
\\t%<s>
0, %<s>
1, %<s>
2"
5818 [(set_attr "type" "fdiv<stype>")]
5821 (define_insn "neg<mode>
2"
5822 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5823 (neg:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5825 "fneg
\\t%<s>
0, %<s>
1"
5826 [(set_attr "type" "ffarith<stype>")]
5829 (define_expand "sqrt<mode>
2"
5830 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5831 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5834 if (aarch64_emit_approx_sqrt (operands[
0], operands[
1], false))
5838 (define_insn "*sqrt<mode>
2"
5839 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5840 (sqrt:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5842 "fsqrt
\\t%<s>
0, %<s>
1"
5843 [(set_attr "type" "fsqrt<stype>")]
5846 (define_insn "abs<mode>
2"
5847 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5848 (abs:GPF_F16 (match_operand:GPF_F16
1 "register_operand" "w")))]
5850 "fabs
\\t%<s>
0, %<s>
1"
5851 [(set_attr "type" "ffarith<stype>")]
5854 ;; Given that smax/smin do not specify the result when either input is NaN,
5855 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5858 (define_insn "smax<mode>
3"
5859 [(set (match_operand:GPF
0 "register_operand" "=w")
5860 (smax:GPF (match_operand:GPF
1 "register_operand" "w")
5861 (match_operand:GPF
2 "register_operand" "w")))]
5863 "fmaxnm
\\t%<s>
0, %<s>
1, %<s>
2"
5864 [(set_attr "type" "f_minmax<s>")]
5867 (define_insn "smin<mode>
3"
5868 [(set (match_operand:GPF
0 "register_operand" "=w")
5869 (smin:GPF (match_operand:GPF
1 "register_operand" "w")
5870 (match_operand:GPF
2 "register_operand" "w")))]
5872 "fminnm
\\t%<s>
0, %<s>
1, %<s>
2"
5873 [(set_attr "type" "f_minmax<s>")]
5876 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5877 ;; fmaxnm and fminnm are used for the fmax<mode>
3 standard pattern names,
5878 ;; which implement the IEEE fmax ()/fmin () functions.
5879 (define_insn "<maxmin_uns><mode>
3"
5880 [(set (match_operand:GPF_F16
0 "register_operand" "=w")
5881 (unspec:GPF_F16 [(match_operand:GPF_F16
1 "register_operand" "w")
5882 (match_operand:GPF_F16
2 "register_operand" "w")]
5885 "<maxmin_uns_op>
\\t%<s>
0, %<s>
1, %<s>
2"
5886 [(set_attr "type" "f_minmax<stype>")]
5889 (define_expand "lrint<GPF:mode><GPI:mode>
2"
5890 [(match_operand:GPI
0 "register_operand")
5891 (match_operand:GPF
1 "register_operand")]
5893 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
5894 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
5896 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5897 emit_insn (gen_rint<GPF:mode>
2 (cvt, operands[
1]));
5898 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>
2 (operands[
0], cvt));
5903 ;; For copysign (x, y), we want to generate:
5905 ;; LDR d2, #(
1 <<
63)
5906 ;; BSL v2.8b, [y], [x]
5908 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5909 ;; aarch64_simd_bsldf will select the best suited of these instructions
5910 ;; to generate based on register allocation, and knows how to partially
5911 ;; constant fold based on the values of X and Y, so expand through that.
5913 (define_expand "copysigndf3"
5914 [(match_operand:DF
0 "register_operand")
5915 (match_operand:DF
1 "register_operand")
5916 (match_operand:DF
2 "register_operand")]
5917 "TARGET_FLOAT && TARGET_SIMD"
5919 rtx mask = gen_reg_rtx (DImode);
5920 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U <<
63));
5921 emit_insn (gen_aarch64_simd_bsldf (operands[
0], mask,
5922 operands[
2], operands[
1]));
5927 ;; As above, but we must first get to a
64-bit value if we wish to use
5928 ;; aarch64_simd_bslv2sf.
5930 (define_expand "copysignsf3"
5931 [(match_operand:SF
0 "register_operand")
5932 (match_operand:SF
1 "register_operand")
5933 (match_operand:SF
2 "register_operand")]
5934 "TARGET_FLOAT && TARGET_SIMD"
5936 rtx v_bitmask = gen_reg_rtx (V2SImode);
5938 /* Juggle modes to get us in to a vector mode for BSL. */
5939 rtx op1 = lowpart_subreg (DImode, operands[
1], SFmode);
5940 rtx op2 = lowpart_subreg (V2SFmode, operands[
2], SFmode);
5941 rtx tmp = gen_reg_rtx (V2SFmode);
5942 emit_move_insn (v_bitmask,
5943 aarch64_simd_gen_const_vector_dup (V2SImode,
5944 HOST_WIDE_INT_M1U <<
31));
5945 emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5946 emit_move_insn (operands[
0], lowpart_subreg (SFmode, tmp, V2SFmode));
5951 ;; For xorsign (x, y), we want to generate:
5954 ;; AND v3.8B, v1.8B, v2.8B
5955 ;; EOR v0.8B, v0.8B, v3.8B
5958 (define_expand "xorsign<mode>
3"
5959 [(match_operand:GPF
0 "register_operand")
5960 (match_operand:GPF
1 "register_operand")
5961 (match_operand:GPF
2 "register_operand")]
5962 "TARGET_FLOAT && TARGET_SIMD"
5965 machine_mode imode = <V_INT_EQUIV>mode;
5966 rtx mask = gen_reg_rtx (imode);
5967 rtx op1x = gen_reg_rtx (imode);
5968 rtx op2x = gen_reg_rtx (imode);
5970 int bits = GET_MODE_BITSIZE (<MODE>mode) -
1;
5971 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
5974 emit_insn (gen_and<v_int_equiv>
3 (op2x, mask,
5975 lowpart_subreg (imode, operands[
2],
5977 emit_insn (gen_xor<v_int_equiv>
3 (op1x,
5978 lowpart_subreg (imode, operands[
1],
5981 emit_move_insn (operands[
0],
5982 lowpart_subreg (<MODE>mode, op1x, imode));
5987 ;; -------------------------------------------------------------------
5989 ;; -------------------------------------------------------------------
5990 ;; Reload Scalar Floating point modes from constant pool.
5991 ;; The AArch64 port doesn't have __int128 constant move support.
5992 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5993 [(set (match_operand:GPF_TF
0 "register_operand" "=w")
5994 (mem:GPF_TF (match_operand
1 "aarch64_constant_pool_symref" "S")))
5995 (clobber (match_operand:P
2 "register_operand" "=&r"))]
5998 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
5999 emit_move_insn (operands[
0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[
2]));
6004 ;; Reload Vector modes from constant pool.
6005 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
6006 [(set (match_operand:VALL
0 "register_operand" "=w")
6007 (mem:VALL (match_operand
1 "aarch64_constant_pool_symref" "S")))
6008 (clobber (match_operand:P
2 "register_operand" "=&r"))]
6011 aarch64_expand_mov_immediate (operands[
2], XEXP (operands[
1],
0));
6012 emit_move_insn (operands[
0], gen_rtx_MEM (<VALL:MODE>mode, operands[
2]));
6017 (define_expand "aarch64_reload_mov<mode>"
6018 [(set (match_operand:TX
0 "register_operand" "=w")
6019 (match_operand:TX
1 "register_operand" "w"))
6020 (clobber (match_operand:DI
2 "register_operand" "=&r"))
6024 rtx op0 = simplify_gen_subreg (TImode, operands[
0], <MODE>mode,
0);
6025 rtx op1 = simplify_gen_subreg (TImode, operands[
1], <MODE>mode,
0);
6026 gen_aarch64_movtilow_tilow (op0, op1);
6027 gen_aarch64_movdi_tihigh (operands[
2], op1);
6028 gen_aarch64_movtihigh_di (op0, operands[
2]);
6033 ;; The following secondary reload helpers patterns are invoked
6034 ;; after or during reload as we don't want these patterns to start
6035 ;; kicking in during the combiner.
6037 (define_insn "aarch64_movdi_<mode>low"
6038 [(set (match_operand:DI
0 "register_operand" "=r")
6039 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6040 (const_int
64) (const_int
0)))]
6041 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6043 [(set_attr "type" "f_mrc")
6044 (set_attr "length" "
4")
6047 (define_insn "aarch64_movdi_<mode>high"
6048 [(set (match_operand:DI
0 "register_operand" "=r")
6049 (zero_extract:DI (match_operand:TX
1 "register_operand" "w")
6050 (const_int
64) (const_int
64)))]
6051 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6052 "fmov
\\t%x0, %
1.d[
1]"
6053 [(set_attr "type" "f_mrc")
6054 (set_attr "length" "
4")
6057 (define_insn "aarch64_mov<mode>high_di"
6058 [(set (zero_extract:TX (match_operand:TX
0 "register_operand" "+w")
6059 (const_int
64) (const_int
64))
6060 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6061 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6062 "fmov
\\t%
0.d[
1], %x1"
6063 [(set_attr "type" "f_mcr")
6064 (set_attr "length" "
4")
6067 (define_insn "aarch64_mov<mode>low_di"
6068 [(set (match_operand:TX
0 "register_operand" "=w")
6069 (zero_extend:TX (match_operand:DI
1 "register_operand" "r")))]
6070 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6072 [(set_attr "type" "f_mcr")
6073 (set_attr "length" "
4")
6076 (define_insn "aarch64_movtilow_tilow"
6077 [(set (match_operand:TI
0 "register_operand" "=w")
6079 (truncate:DI (match_operand:TI
1 "register_operand" "w"))))]
6080 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6082 [(set_attr "type" "fmov")
6083 (set_attr "length" "
4")
6086 ;; There is a deliberate reason why the parameters of high and lo_sum's
6087 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6088 ;; and lo_sum's to be used with the labels defining the jump tables in
6091 (define_expand "add_losym"
6092 [(set (match_operand
0 "register_operand" "=r")
6093 (lo_sum (match_operand
1 "register_operand" "r")
6094 (match_operand
2 "aarch64_valid_symref" "S")))]
6097 machine_mode mode = GET_MODE (operands[
0]);
6099 emit_insn ((mode == DImode
6101 : gen_add_losym_si) (operands[
0],
6107 (define_insn "add_losym_<mode>"
6108 [(set (match_operand:P
0 "register_operand" "=r")
6109 (lo_sum:P (match_operand:P
1 "register_operand" "r")
6110 (match_operand
2 "aarch64_valid_symref" "S")))]
6112 "add
\\t%<w>
0, %<w>
1, :lo12:%c2"
6113 [(set_attr "type" "alu_imm")]
6116 (define_insn "ldr_got_small_<mode>"
6117 [(set (match_operand:PTR
0 "register_operand" "=r")
6118 (unspec:PTR [(mem:PTR (lo_sum:PTR
6119 (match_operand:PTR
1 "register_operand" "r")
6120 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6121 UNSPEC_GOTSMALLPIC))]
6123 "ldr
\\t%<w>
0, [%
1, #:got_lo12:%c2]"
6124 [(set_attr "type" "load_<ldst_sz>")]
6127 (define_insn "ldr_got_small_sidi"
6128 [(set (match_operand:DI
0 "register_operand" "=r")
6130 (unspec:SI [(mem:SI (lo_sum:DI
6131 (match_operand:DI
1 "register_operand" "r")
6132 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6133 UNSPEC_GOTSMALLPIC)))]
6135 "ldr
\\t%w0, [%
1, #:got_lo12:%c2]"
6136 [(set_attr "type" "load_4")]
6139 (define_insn "ldr_got_small_28k_<mode>"
6140 [(set (match_operand:PTR
0 "register_operand" "=r")
6141 (unspec:PTR [(mem:PTR (lo_sum:PTR
6142 (match_operand:PTR
1 "register_operand" "r")
6143 (match_operand:PTR
2 "aarch64_valid_symref" "S")))]
6144 UNSPEC_GOTSMALLPIC28K))]
6146 "ldr
\\t%<w>
0, [%
1, #:<got_modifier>:%c2]"
6147 [(set_attr "type" "load_<ldst_sz>")]
6150 (define_insn "ldr_got_small_28k_sidi"
6151 [(set (match_operand:DI
0 "register_operand" "=r")
6153 (unspec:SI [(mem:SI (lo_sum:DI
6154 (match_operand:DI
1 "register_operand" "r")
6155 (match_operand:DI
2 "aarch64_valid_symref" "S")))]
6156 UNSPEC_GOTSMALLPIC28K)))]
6158 "ldr
\\t%w0, [%
1, #:gotpage_lo14:%c2]"
6159 [(set_attr "type" "load_4")]
6162 (define_insn "ldr_got_tiny"
6163 [(set (match_operand:DI
0 "register_operand" "=r")
6164 (unspec:DI [(match_operand:DI
1 "aarch64_valid_symref" "S")]
6165 UNSPEC_GOTTINYPIC))]
6168 [(set_attr "type" "load_8")]
6171 (define_insn "aarch64_load_tp_hard"
6172 [(set (match_operand:DI
0 "register_operand" "=r")
6173 (unspec:DI [(const_int
0)] UNSPEC_TLS))]
6175 "mrs
\\t%
0, tpidr_el0"
6176 [(set_attr "type" "mrs")]
6179 ;; The TLS ABI specifically requires that the compiler does not schedule
6180 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6181 ;; Therefore we treat the stubs as an atomic sequence.
6182 (define_expand "tlsgd_small_<mode>"
6183 [(parallel [(set (match_operand
0 "register_operand" "")
6184 (call (mem:DI (match_dup
2)) (const_int
1)))
6185 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
6186 (clobber (reg:DI LR_REGNUM))])]
6189 operands[
2] = aarch64_tls_get_addr ();
6192 (define_insn "*tlsgd_small_<mode>"
6193 [(set (match_operand
0 "register_operand" "")
6194 (call (mem:DI (match_operand:DI
2 "" "")) (const_int
1)))
6195 (unspec:DI [(match_operand:PTR
1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6196 (clobber (reg:DI LR_REGNUM))
6199 "adrp
\\tx0, %A1\;add
\\tx0, x0, %L1\;bl
\\t%
2\;nop"
6200 [(set_attr "type" "call")
6201 (set_attr "length" "
16")])
6203 (define_insn "tlsie_small_<mode>"
6204 [(set (match_operand:PTR
0 "register_operand" "=r")
6205 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6206 UNSPEC_GOTSMALLTLS))]
6208 "adrp
\\t%
0, %A1\;ldr
\\t%<w>
0, [%
0, #%L1]"
6209 [(set_attr "type" "load_4")
6210 (set_attr "length" "
8")]
6213 (define_insn "tlsie_small_sidi"
6214 [(set (match_operand:DI
0 "register_operand" "=r")
6216 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")]
6217 UNSPEC_GOTSMALLTLS)))]
6219 "adrp
\\t%
0, %A1\;ldr
\\t%w0, [%
0, #%L1]"
6220 [(set_attr "type" "load_4")
6221 (set_attr "length" "
8")]
6224 (define_insn "tlsie_tiny_<mode>"
6225 [(set (match_operand:PTR
0 "register_operand" "=&r")
6226 (unspec:PTR [(match_operand
1 "aarch64_tls_ie_symref" "S")
6227 (match_operand:PTR
2 "register_operand" "r")]
6228 UNSPEC_GOTTINYTLS))]
6230 "ldr
\\t%<w>
0, %L1\;add
\\t%<w>
0, %<w>
0, %<w>
2"
6231 [(set_attr "type" "multiple")
6232 (set_attr "length" "
8")]
6235 (define_insn "tlsie_tiny_sidi"
6236 [(set (match_operand:DI
0 "register_operand" "=&r")
6238 (unspec:SI [(match_operand
1 "aarch64_tls_ie_symref" "S")
6239 (match_operand:DI
2 "register_operand" "r")
6241 UNSPEC_GOTTINYTLS)))]
6243 "ldr
\\t%w0, %L1\;add
\\t%w0, %w0, %w2"
6244 [(set_attr "type" "multiple")
6245 (set_attr "length" "
8")]
6248 (define_insn "tlsle12_<mode>"
6249 [(set (match_operand:P
0 "register_operand" "=r")
6250 (unspec:P [(match_operand:P
1 "register_operand" "r")
6251 (match_operand
2 "aarch64_tls_le_symref" "S")]
6254 "add
\\t%<w>
0, %<w>
1, #%L2";
6255 [(set_attr "type" "alu_sreg")
6256 (set_attr "length" "
4")]
6259 (define_insn "tlsle24_<mode>"
6260 [(set (match_operand:P
0 "register_operand" "=r")
6261 (unspec:P [(match_operand:P
1 "register_operand" "r")
6262 (match_operand
2 "aarch64_tls_le_symref" "S")]
6265 "add
\\t%<w>
0, %<w>
1, #%G2, lsl #
12\;add
\\t%<w>
0, %<w>
0, #%L2"
6266 [(set_attr "type" "multiple")
6267 (set_attr "length" "
8")]
6270 (define_insn "tlsle32_<mode>"
6271 [(set (match_operand:P
0 "register_operand" "=r")
6272 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6275 "movz
\\t%<w>
0, #:tprel_g1:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6276 [(set_attr "type" "multiple")
6277 (set_attr "length" "
8")]
6280 (define_insn "tlsle48_<mode>"
6281 [(set (match_operand:P
0 "register_operand" "=r")
6282 (unspec:P [(match_operand
1 "aarch64_tls_le_symref" "S")]
6285 "movz
\\t%<w>
0, #:tprel_g2:%
1\;movk
\\t%<w>
0, #:tprel_g1_nc:%
1\;movk
\\t%<w>
0, #:tprel_g0_nc:%
1"
6286 [(set_attr "type" "multiple")
6287 (set_attr "length" "
12")]
6290 (define_expand "tlsdesc_small_<mode>"
6291 [(unspec:PTR [(match_operand
0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6295 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[
0]));
6297 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[
0]));
6302 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6304 (define_insn "tlsdesc_small_advsimd_<mode>"
6305 [(set (reg:PTR R0_REGNUM)
6306 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6308 (clobber (reg:DI LR_REGNUM))
6309 (clobber (reg:CC CC_REGNUM))
6310 (clobber (match_scratch:DI
1 "=r"))]
6311 "TARGET_TLS_DESC && !TARGET_SVE"
6312 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6313 [(set_attr "type" "call")
6314 (set_attr "length" "
16")])
6316 ;; For SVE, model tlsdesc calls as clobbering all vector and predicate
6317 ;; registers, on top of the usual R0 and LR. In reality the calls
6318 ;; preserve the low
128 bits of the vector registers, but we don't
6319 ;; yet have a way of representing that in the instruction pattern.
6320 (define_insn "tlsdesc_small_sve_<mode>"
6321 [(set (reg:PTR R0_REGNUM)
6322 (unspec:PTR [(match_operand
0 "aarch64_valid_symref" "S")]
6324 (clobber (reg:DI LR_REGNUM))
6325 (clobber (reg:CC CC_REGNUM))
6326 (clobber (reg:XI V0_REGNUM))
6327 (clobber (reg:XI V4_REGNUM))
6328 (clobber (reg:XI V8_REGNUM))
6329 (clobber (reg:XI V12_REGNUM))
6330 (clobber (reg:XI V16_REGNUM))
6331 (clobber (reg:XI V20_REGNUM))
6332 (clobber (reg:XI V24_REGNUM))
6333 (clobber (reg:XI V28_REGNUM))
6334 (clobber (reg:VNx2BI P0_REGNUM))
6335 (clobber (reg:VNx2BI P1_REGNUM))
6336 (clobber (reg:VNx2BI P2_REGNUM))
6337 (clobber (reg:VNx2BI P3_REGNUM))
6338 (clobber (reg:VNx2BI P4_REGNUM))
6339 (clobber (reg:VNx2BI P5_REGNUM))
6340 (clobber (reg:VNx2BI P6_REGNUM))
6341 (clobber (reg:VNx2BI P7_REGNUM))
6342 (clobber (reg:VNx2BI P8_REGNUM))
6343 (clobber (reg:VNx2BI P9_REGNUM))
6344 (clobber (reg:VNx2BI P10_REGNUM))
6345 (clobber (reg:VNx2BI P11_REGNUM))
6346 (clobber (reg:VNx2BI P12_REGNUM))
6347 (clobber (reg:VNx2BI P13_REGNUM))
6348 (clobber (reg:VNx2BI P14_REGNUM))
6349 (clobber (reg:VNx2BI P15_REGNUM))
6350 (clobber (match_scratch:DI
1 "=r"))]
6351 "TARGET_TLS_DESC && TARGET_SVE"
6352 "adrp
\\tx0, %A0\;ldr
\\t%<w>
1, [x0, #%L0]\;add
\\t<w>
0, <w>
0, %L0\;.tlsdesccall
\\t%
0\;blr
\\t%
1"
6353 [(set_attr "type" "call")
6354 (set_attr "length" "
16")])
6356 (define_insn "stack_tie"
6357 [(set (mem:BLK (scratch))
6358 (unspec:BLK [(match_operand:DI
0 "register_operand" "rk")
6359 (match_operand:DI
1 "register_operand" "rk")]
6363 [(set_attr "length" "
0")]
6366 ;; Pointer authentication patterns are always provided. In architecture
6367 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6368 ;; This lets the user write portable software which authenticates pointers
6369 ;; when run on something which implements ARMv8.3-A, and which runs
6370 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6373 ;; Signing/Authenticating R30 using SP as the salt.
6375 (define_insn "<pauth_mnem_prefix>sp"
6376 [(set (reg:DI R30_REGNUM)
6377 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6379 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
6382 ;; Signing/Authenticating X17 using X16 as the salt.
6384 (define_insn "<pauth_mnem_prefix>
1716"
6385 [(set (reg:DI R17_REGNUM)
6386 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6388 "hint
\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
6391 ;; Stripping the signature in R30.
6393 (define_insn "xpaclri"
6394 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6396 "hint
\t7 // xpaclri"
6399 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6400 ;; all of memory. This blocks insns from being moved across this point.
6402 (define_insn "blockage"
6403 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
6406 [(set_attr "length" "
0")
6407 (set_attr "type" "block")]
6410 (define_insn "probe_stack_range"
6411 [(set (match_operand:DI
0 "register_operand" "=r")
6412 (unspec_volatile:DI [(match_operand:DI
1 "register_operand" "
0")
6413 (match_operand:DI
2 "register_operand" "r")]
6414 UNSPECV_PROBE_STACK_RANGE))]
6417 return aarch64_output_probe_stack_range (operands[
0], operands[
2]);
6419 [(set_attr "length" "
32")]
6422 ;; Named pattern for expanding thread pointer reference.
6423 (define_expand "get_thread_pointerdi"
6424 [(match_operand:DI
0 "register_operand" "=r")]
6427 rtx tmp = aarch64_load_tp (operands[
0]);
6428 if (tmp != operands[
0])
6429 emit_move_insn (operands[
0], tmp);
6433 ;; Named patterns for stack smashing protection.
6434 (define_expand "stack_protect_set"
6435 [(match_operand
0 "memory_operand")
6436 (match_operand
1 "memory_operand")]
6439 machine_mode mode = GET_MODE (operands[
0]);
6441 emit_insn ((mode == DImode
6442 ? gen_stack_protect_set_di
6443 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
6447 (define_insn "stack_protect_set_<mode>"
6448 [(set (match_operand:PTR
0 "memory_operand" "=m")
6449 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")]
6451 (set (match_scratch:PTR
2 "=&r") (const_int
0))]
6453 "ldr
\\t%<w>
2, %
1\;str
\\t%<w>
2, %
0\;mov
\t%<w>
2,
0"
6454 [(set_attr "length" "
12")
6455 (set_attr "type" "multiple")])
6457 (define_expand "stack_protect_test"
6458 [(match_operand
0 "memory_operand")
6459 (match_operand
1 "memory_operand")
6464 machine_mode mode = GET_MODE (operands[
0]);
6466 result = gen_reg_rtx(mode);
6468 emit_insn ((mode == DImode
6469 ? gen_stack_protect_test_di
6470 : gen_stack_protect_test_si) (result,
6475 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6476 result, const0_rtx, operands[
2]));
6478 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6479 result, const0_rtx, operands[
2]));
6483 (define_insn "stack_protect_test_<mode>"
6484 [(set (match_operand:PTR
0 "register_operand" "=r")
6485 (unspec:PTR [(match_operand:PTR
1 "memory_operand" "m")
6486 (match_operand:PTR
2 "memory_operand" "m")]
6488 (clobber (match_scratch:PTR
3 "=&r"))]
6490 "ldr
\t%<w>
3, %
1\;ldr
\t%<w>
0, %
2\;eor
\t%<w>
0, %<w>
3, %<w>
0"
6491 [(set_attr "length" "
12")
6492 (set_attr "type" "multiple")])
6494 ;; Write Floating-point Control Register.
6495 (define_insn "set_fpcr"
6496 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPCR)]
6499 [(set_attr "type" "mrs")])
6501 ;; Read Floating-point Control Register.
6502 (define_insn "get_fpcr"
6503 [(set (match_operand:SI
0 "register_operand" "=r")
6504 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPCR))]
6507 [(set_attr "type" "mrs")])
6509 ;; Write Floating-point Status Register.
6510 (define_insn "set_fpsr"
6511 [(unspec_volatile [(match_operand:SI
0 "register_operand" "r")] UNSPECV_SET_FPSR)]
6514 [(set_attr "type" "mrs")])
6516 ;; Read Floating-point Status Register.
6517 (define_insn "get_fpsr"
6518 [(set (match_operand:SI
0 "register_operand" "=r")
6519 (unspec_volatile:SI [(const_int
0)] UNSPECV_GET_FPSR))]
6522 [(set_attr "type" "mrs")])
6525 ;; Define the subtract-one-and-jump insns so loop.c
6526 ;; knows what to generate.
6527 (define_expand "doloop_end"
6528 [(use (match_operand
0 "" "")) ; loop pseudo
6529 (use (match_operand
1 "" ""))] ; label
6530 "optimize >
0 && flag_modulo_sched"
6539 /* Currently SMS relies on the do-loop pattern to recognize loops
6540 where (
1) the control part consists of all insns defining and/or
6541 using a certain 'count' register and (
2) the loop count can be
6542 adjusted by modifying this register prior to the loop.
6543 ??? The possible introduction of a new block to initialize the
6544 new IV can potentially affect branch optimizations. */
6546 if (GET_MODE (operands[
0]) != DImode)
6550 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-
1)));
6552 cmp = XVECEXP (PATTERN (insn),
0,
0);
6553 cc_reg = SET_DEST (cmp);
6554 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
6555 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [
1]);
6556 emit_jump_insn (gen_rtx_SET (pc_rtx,
6557 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
6562 ;; Track speculation through conditional branches. We assume that
6563 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
6564 (define_insn "speculation_tracker"
6565 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
6566 (unspec [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand
0)]
6567 UNSPEC_SPECULATION_TRACKER))]
6570 operands[
1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
6571 output_asm_insn ("csel
\\t%
1, %
1, xzr, %m0", operands);
6574 [(set_attr "type" "csel")]
6577 ;; Helper for aarch64.c code.
6578 (define_expand "set_clobber_cc"
6579 [(parallel [(set (match_operand
0)
6581 (clobber (reg:CC CC_REGNUM))])])
6583 ;; Hard speculation barrier.
6584 (define_insn "speculation_barrier"
6585 [(unspec_volatile [(const_int
0)] UNSPECV_SPECULATION_BARRIER)]
6588 [(set_attr "length" "
8")
6589 (set_attr "type" "block")
6590 (set_attr "speculation_barrier" "true")]
6594 (include "aarch64-simd.md")
6596 ;; Atomic Operations
6597 (include "atomics.md")
6599 ;; ldp/stp peephole patterns
6600 (include "aarch64-ldpstp.md")
6603 (include "aarch64-sve.md")