1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2017 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/>.
62 (LAST_SAVED_REGNUM 63)
69 (define_c_enum "unspec" [
140 (define_c_enum "unspecv" [
141 UNSPECV_EH_RETURN ; Represent EH_RETURN
142 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
143 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
144 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
145 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
146 UNSPECV_BLOCKAGE ; Represent a blockage
147 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
151 ;; If further include files are added the defintion of MD_INCLUDES
154 (include "constraints.md")
155 (include "predicates.md")
156 (include "iterators.md")
158 ;; -------------------------------------------------------------------
159 ;; Instruction types and attributes
160 ;; -------------------------------------------------------------------
162 ; The "type" attribute is included here from AArch32 backend to be able
163 ; to share pipeline descriptions.
164 (include "../arm/types.md")
166 ;; It is important to set the fp or simd attributes to yes when a pattern
167 ;; alternative uses the FP or SIMD register files, usually signified by use of
168 ;; the 'w' constraint. This will ensure that the alternative will be
169 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
170 ;; architecture extensions. If all the alternatives in a pattern use the
171 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
174 ;; Attribute that specifies whether or not the instruction touches fp
175 ;; registers. When this is set to yes for an alternative, that alternative
176 ;; will be disabled when !TARGET_FLOAT.
177 (define_attr "fp" "no,yes" (const_string "no"))
179 ;; Attribute that specifies whether or not the instruction touches simd
180 ;; registers. When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_SIMD.
182 (define_attr "simd" "no,yes" (const_string "no"))
184 (define_attr "length" ""
187 ;; Attribute that controls whether an alternative is enabled or not.
188 ;; Currently it is only used to disable alternatives which touch fp or simd
189 ;; registers when -mgeneral-regs-only is specified.
190 (define_attr "enabled" "no,yes"
192 (and (eq_attr "fp" "yes")
193 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
194 (and (eq_attr "simd" "yes")
195 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
197 ] (const_string "yes")))
199 ;; Attribute that specifies whether we are dealing with a branch to a
200 ;; label that is far away, i.e. further away than the maximum/minimum
201 ;; representable in a signed 21-bits number.
204 (define_attr "far_branch" "" (const_int 0))
206 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
207 ;; no predicated insns.
208 (define_attr "predicated" "yes,no" (const_string "no"))
210 ;; -------------------------------------------------------------------
211 ;; Pipeline descriptions and scheduling
212 ;; -------------------------------------------------------------------
215 (include "aarch64-tune.md")
218 (include "../arm/cortex-a53.md")
219 (include "../arm/cortex-a57.md")
220 (include "../arm/exynos-m1.md")
221 (include "thunderx.md")
222 (include "../arm/xgene1.md")
224 ;; -------------------------------------------------------------------
225 ;; Jumps and other miscellaneous insns
226 ;; -------------------------------------------------------------------
228 (define_insn "indirect_jump"
229 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
232 [(set_attr "type" "branch")]
236 [(set (pc) (label_ref (match_operand 0 "" "")))]
239 [(set_attr "type" "branch")]
242 (define_expand "cbranch<mode>4"
243 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
244 [(match_operand:GPI 1 "register_operand" "")
245 (match_operand:GPI 2 "aarch64_plus_operand" "")])
246 (label_ref (match_operand 3 "" ""))
250 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
252 operands[2] = const0_rtx;
256 (define_expand "cbranch<mode>4"
257 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
258 [(match_operand:GPF 1 "register_operand" "")
259 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
260 (label_ref (match_operand 3 "" ""))
264 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
266 operands[2] = const0_rtx;
270 (define_expand "cbranchcc4"
271 [(set (pc) (if_then_else
272 (match_operator 0 "aarch64_comparison_operator"
273 [(match_operand 1 "cc_register" "")
274 (match_operand 2 "const0_operand")])
275 (label_ref (match_operand 3 "" ""))
280 (define_insn "ccmp<mode>"
281 [(set (match_operand:CC 1 "cc_register" "")
283 (match_operator 4 "aarch64_comparison_operator"
284 [(match_operand 0 "cc_register" "")
287 (match_operand:GPI 2 "register_operand" "r,r,r")
288 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
289 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
292 ccmp\\t%<w>2, %<w>3, %k5, %m4
293 ccmp\\t%<w>2, %3, %k5, %m4
294 ccmn\\t%<w>2, #%n3, %k5, %m4"
295 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
298 (define_insn "fccmp<mode>"
299 [(set (match_operand:CCFP 1 "cc_register" "")
301 (match_operator 4 "aarch64_comparison_operator"
302 [(match_operand 0 "cc_register" "")
305 (match_operand:GPF 2 "register_operand" "w")
306 (match_operand:GPF 3 "register_operand" "w"))
307 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
309 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
310 [(set_attr "type" "fccmp<s>")]
313 (define_insn "fccmpe<mode>"
314 [(set (match_operand:CCFPE 1 "cc_register" "")
316 (match_operator 4 "aarch64_comparison_operator"
317 [(match_operand 0 "cc_register" "")
320 (match_operand:GPF 2 "register_operand" "w")
321 (match_operand:GPF 3 "register_operand" "w"))
322 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
324 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
325 [(set_attr "type" "fccmp<s>")]
328 ;; Expansion of signed mod by a power of 2 using CSNEG.
329 ;; For x0 % n where n is a power of 2 produce:
331 ;; and x0, x0, #(n - 1)
332 ;; and x1, x1, #(n - 1)
333 ;; csneg x0, x0, x1, mi
335 (define_expand "mod<mode>3"
336 [(match_operand:GPI 0 "register_operand" "")
337 (match_operand:GPI 1 "register_operand" "")
338 (match_operand:GPI 2 "const_int_operand" "")]
341 HOST_WIDE_INT val = INTVAL (operands[2]);
344 || exact_log2 (val) <= 0
345 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
348 rtx mask = GEN_INT (val - 1);
350 /* In the special case of x0 % 2 we can do the even shorter:
356 rtx masked = gen_reg_rtx (<MODE>mode);
357 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
358 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
359 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
360 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
364 rtx neg_op = gen_reg_rtx (<MODE>mode);
365 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
367 /* Extract the condition register and mode. */
368 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
369 rtx cc_reg = SET_DEST (cmp);
370 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
372 rtx masked_pos = gen_reg_rtx (<MODE>mode);
373 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
375 rtx masked_neg = gen_reg_rtx (<MODE>mode);
376 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
378 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
379 masked_neg, masked_pos));
384 (define_insn "condjump"
385 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
386 [(match_operand 1 "cc_register" "") (const_int 0)])
387 (label_ref (match_operand 2 "" ""))
391 if (get_attr_length (insn) == 8)
392 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
396 [(set_attr "type" "branch")
398 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
399 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
402 (set (attr "far_branch")
403 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
404 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
409 ;; For a 24-bit immediate CST we can optimize the compare for equality
410 ;; and branch sequence from:
412 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
416 ;; sub x0, x1, #(CST & 0xfff000)
417 ;; subs x0, x0, #(CST & 0x000fff)
419 (define_insn_and_split "*compare_condjump<mode>"
420 [(set (pc) (if_then_else (EQL
421 (match_operand:GPI 0 "register_operand" "r")
422 (match_operand:GPI 1 "aarch64_imm24" "n"))
423 (label_ref:P (match_operand 2 "" ""))
425 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
426 && !aarch64_plus_operand (operands[1], <MODE>mode)
427 && !reload_completed"
432 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
433 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
434 rtx tmp = gen_reg_rtx (<MODE>mode);
435 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
436 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
437 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
438 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
439 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
444 (define_expand "casesi"
445 [(match_operand:SI 0 "register_operand" "") ; Index
446 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
447 (match_operand:SI 2 "const_int_operand" "") ; Total range
448 (match_operand:DI 3 "" "") ; Table label
449 (match_operand:DI 4 "" "")] ; Out of range label
452 if (operands[1] != const0_rtx)
454 rtx reg = gen_reg_rtx (SImode);
456 /* Canonical RTL says that if you have:
460 then this should be emitted as:
464 The use of trunc_int_for_mode ensures that the resulting
465 constant can be represented in SImode, this is important
466 for the corner case where operand[1] is INT_MIN. */
468 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
470 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
471 (operands[1], SImode))
472 operands[1] = force_reg (SImode, operands[1]);
473 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
477 if (!aarch64_plus_operand (operands[2], SImode))
478 operands[2] = force_reg (SImode, operands[2]);
479 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
481 operands[0], operands[2], operands[4]));
483 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
484 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
490 (define_insn "casesi_dispatch"
493 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
494 (match_operand:SI 1 "register_operand" "r")]
496 (clobber (reg:CC CC_REGNUM))
497 (clobber (match_scratch:DI 3 "=r"))
498 (clobber (match_scratch:DI 4 "=r"))
499 (use (label_ref (match_operand 2 "" "")))])]
502 return aarch64_output_casesi (operands);
504 [(set_attr "length" "16")
505 (set_attr "type" "branch")]
509 [(unspec[(const_int 0)] UNSPEC_NOP)]
512 [(set_attr "type" "no_insn")]
515 (define_insn "prefetch"
516 [(prefetch (match_operand:DI 0 "register_operand" "r")
517 (match_operand:QI 1 "const_int_operand" "")
518 (match_operand:QI 2 "const_int_operand" ""))]
521 const char * pftype[2][4] =
523 {"prfm\\tPLDL1STRM, %a0",
524 "prfm\\tPLDL3KEEP, %a0",
525 "prfm\\tPLDL2KEEP, %a0",
526 "prfm\\tPLDL1KEEP, %a0"},
527 {"prfm\\tPSTL1STRM, %a0",
528 "prfm\\tPSTL3KEEP, %a0",
529 "prfm\\tPSTL2KEEP, %a0",
530 "prfm\\tPSTL1KEEP, %a0"},
533 int locality = INTVAL (operands[2]);
535 gcc_assert (IN_RANGE (locality, 0, 3));
537 return pftype[INTVAL(operands[1])][locality];
539 [(set_attr "type" "load1")]
543 [(trap_if (const_int 1) (const_int 8))]
546 [(set_attr "type" "trap")])
548 (define_expand "prologue"
549 [(clobber (const_int 0))]
552 aarch64_expand_prologue ();
557 (define_expand "epilogue"
558 [(clobber (const_int 0))]
561 aarch64_expand_epilogue (false);
566 (define_expand "sibcall_epilogue"
567 [(clobber (const_int 0))]
570 aarch64_expand_epilogue (true);
575 (define_insn "*do_return"
579 [(set_attr "type" "branch")]
582 (define_expand "return"
584 "aarch64_use_return_insn_p ()"
588 (define_insn "simple_return"
592 [(set_attr "type" "branch")]
595 (define_insn "*cb<optab><mode>1"
596 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
598 (label_ref (match_operand 1 "" ""))
602 if (get_attr_length (insn) == 8)
603 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
605 return "<cbz>\\t%<w>0, %l1";
607 [(set_attr "type" "branch")
609 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
610 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
613 (set (attr "far_branch")
614 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
615 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
620 (define_insn "*tb<optab><mode>1"
621 [(set (pc) (if_then_else
622 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
625 "aarch64_simd_shift_imm_<mode>" "n"))
627 (label_ref (match_operand 2 "" ""))
629 (clobber (reg:CC CC_REGNUM))]
632 if (get_attr_length (insn) == 8)
634 if (get_attr_far_branch (insn) == 1)
635 return aarch64_gen_far_branch (operands, 2, "Ltb",
636 "<inv_tb>\\t%<w>0, %1, ");
639 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
640 return "tst\t%<w>0, %1\;<bcond>\t%l2";
644 return "<tbz>\t%<w>0, %1, %l2";
646 [(set_attr "type" "branch")
648 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
649 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
652 (set (attr "far_branch")
653 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
654 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
660 (define_insn "*cb<optab><mode>1"
661 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
663 (label_ref (match_operand 1 "" ""))
665 (clobber (reg:CC CC_REGNUM))]
668 if (get_attr_length (insn) == 8)
670 if (get_attr_far_branch (insn) == 1)
671 return aarch64_gen_far_branch (operands, 1, "Ltb",
672 "<inv_tb>\\t%<w>0, <sizem1>, ");
676 uint64_t val = ((uint64_t) 1)
677 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
678 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
679 output_asm_insn (buf, operands);
680 return "<bcond>\t%l1";
684 return "<tbz>\t%<w>0, <sizem1>, %l1";
686 [(set_attr "type" "branch")
688 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
689 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
692 (set (attr "far_branch")
693 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
694 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
699 ;; -------------------------------------------------------------------
700 ;; Subroutine calls and sibcalls
701 ;; -------------------------------------------------------------------
703 (define_expand "call_internal"
704 [(parallel [(call (match_operand 0 "memory_operand" "")
705 (match_operand 1 "general_operand" ""))
706 (use (match_operand 2 "" ""))
707 (clobber (reg:DI LR_REGNUM))])])
709 (define_expand "call"
710 [(parallel [(call (match_operand 0 "memory_operand" "")
711 (match_operand 1 "general_operand" ""))
712 (use (match_operand 2 "" ""))
713 (clobber (reg:DI LR_REGNUM))])]
719 /* In an untyped call, we can get NULL for operand 2. */
720 if (operands[2] == NULL)
721 operands[2] = const0_rtx;
723 /* Decide if we should generate indirect calls by loading the
724 64-bit address of the callee into a register before performing
725 the branch-and-link. */
726 callee = XEXP (operands[0], 0);
727 if (GET_CODE (callee) == SYMBOL_REF
728 ? (aarch64_is_long_call_p (callee)
729 || aarch64_is_noplt_call_p (callee))
731 XEXP (operands[0], 0) = force_reg (Pmode, callee);
733 pat = gen_call_internal (operands[0], operands[1], operands[2]);
734 aarch64_emit_call_insn (pat);
739 (define_insn "*call_reg"
740 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
741 (match_operand 1 "" ""))
742 (use (match_operand 2 "" ""))
743 (clobber (reg:DI LR_REGNUM))]
746 [(set_attr "type" "call")]
749 (define_insn "*call_symbol"
750 [(call (mem:DI (match_operand:DI 0 "" ""))
751 (match_operand 1 "" ""))
752 (use (match_operand 2 "" ""))
753 (clobber (reg:DI LR_REGNUM))]
754 "GET_CODE (operands[0]) == SYMBOL_REF
755 && !aarch64_is_long_call_p (operands[0])
756 && !aarch64_is_noplt_call_p (operands[0])"
758 [(set_attr "type" "call")]
761 (define_expand "call_value_internal"
762 [(parallel [(set (match_operand 0 "" "")
763 (call (match_operand 1 "memory_operand" "")
764 (match_operand 2 "general_operand" "")))
765 (use (match_operand 3 "" ""))
766 (clobber (reg:DI LR_REGNUM))])])
768 (define_expand "call_value"
769 [(parallel [(set (match_operand 0 "" "")
770 (call (match_operand 1 "memory_operand" "")
771 (match_operand 2 "general_operand" "")))
772 (use (match_operand 3 "" ""))
773 (clobber (reg:DI LR_REGNUM))])]
779 /* In an untyped call, we can get NULL for operand 3. */
780 if (operands[3] == NULL)
781 operands[3] = const0_rtx;
783 /* Decide if we should generate indirect calls by loading the
784 64-bit address of the callee into a register before performing
785 the branch-and-link. */
786 callee = XEXP (operands[1], 0);
787 if (GET_CODE (callee) == SYMBOL_REF
788 ? (aarch64_is_long_call_p (callee)
789 || aarch64_is_noplt_call_p (callee))
791 XEXP (operands[1], 0) = force_reg (Pmode, callee);
793 pat = gen_call_value_internal (operands[0], operands[1], operands[2],
795 aarch64_emit_call_insn (pat);
800 (define_insn "*call_value_reg"
801 [(set (match_operand 0 "" "")
802 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
803 (match_operand 2 "" "")))
804 (use (match_operand 3 "" ""))
805 (clobber (reg:DI LR_REGNUM))]
808 [(set_attr "type" "call")]
812 (define_insn "*call_value_symbol"
813 [(set (match_operand 0 "" "")
814 (call (mem:DI (match_operand:DI 1 "" ""))
815 (match_operand 2 "" "")))
816 (use (match_operand 3 "" ""))
817 (clobber (reg:DI LR_REGNUM))]
818 "GET_CODE (operands[1]) == SYMBOL_REF
819 && !aarch64_is_long_call_p (operands[1])
820 && !aarch64_is_noplt_call_p (operands[1])"
822 [(set_attr "type" "call")]
825 (define_expand "sibcall_internal"
826 [(parallel [(call (match_operand 0 "memory_operand" "")
827 (match_operand 1 "general_operand" ""))
829 (use (match_operand 2 "" ""))])])
831 (define_expand "sibcall"
832 [(parallel [(call (match_operand 0 "memory_operand" "")
833 (match_operand 1 "general_operand" ""))
835 (use (match_operand 2 "" ""))])]
839 rtx callee = XEXP (operands[0], 0);
841 && ((GET_CODE (callee) != SYMBOL_REF)
842 || aarch64_is_noplt_call_p (callee)))
843 XEXP (operands[0], 0) = force_reg (Pmode, callee);
845 if (operands[2] == NULL_RTX)
846 operands[2] = const0_rtx;
848 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
849 aarch64_emit_call_insn (pat);
854 (define_expand "sibcall_value_internal"
855 [(parallel [(set (match_operand 0 "" "")
856 (call (match_operand 1 "memory_operand" "")
857 (match_operand 2 "general_operand" "")))
859 (use (match_operand 3 "" ""))])])
861 (define_expand "sibcall_value"
862 [(parallel [(set (match_operand 0 "" "")
863 (call (match_operand 1 "memory_operand" "")
864 (match_operand 2 "general_operand" "")))
866 (use (match_operand 3 "" ""))])]
870 rtx callee = XEXP (operands[1], 0);
872 && ((GET_CODE (callee) != SYMBOL_REF)
873 || aarch64_is_noplt_call_p (callee)))
874 XEXP (operands[1], 0) = force_reg (Pmode, callee);
876 if (operands[3] == NULL_RTX)
877 operands[3] = const0_rtx;
879 pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
881 aarch64_emit_call_insn (pat);
886 (define_insn "*sibcall_insn"
887 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
888 (match_operand 1 "" ""))
890 (use (match_operand 2 "" ""))]
891 "SIBLING_CALL_P (insn)"
895 [(set_attr "type" "branch, branch")]
898 (define_insn "*sibcall_value_insn"
899 [(set (match_operand 0 "" "")
901 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
902 (match_operand 2 "" "")))
904 (use (match_operand 3 "" ""))]
905 "SIBLING_CALL_P (insn)"
909 [(set_attr "type" "branch, branch")]
912 ;; Call subroutine returning any type.
914 (define_expand "untyped_call"
915 [(parallel [(call (match_operand 0 "")
918 (match_operand 2 "")])]
923 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
925 for (i = 0; i < XVECLEN (operands[2], 0); i++)
927 rtx set = XVECEXP (operands[2], 0, i);
928 emit_move_insn (SET_DEST (set), SET_SRC (set));
931 /* The optimizer does not know that the call sets the function value
932 registers we stored in the result block. We avoid problems by
933 claiming that all hard registers are used and clobbered at this
935 emit_insn (gen_blockage ());
939 ;; -------------------------------------------------------------------
941 ;; -------------------------------------------------------------------
943 (define_expand "mov<mode>"
944 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
945 (match_operand:SHORT 1 "general_operand" ""))]
948 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
949 operands[1] = force_reg (<MODE>mode, operands[1]);
953 (define_insn "*mov<mode>_aarch64"
954 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
955 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
956 "(register_operand (operands[0], <MODE>mode)
957 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
959 switch (which_alternative)
962 return "mov\t%w0, %w1";
964 return "mov\t%w0, %1";
966 return aarch64_output_scalar_simd_mov_immediate (operands[1],
969 return "ldr<size>\t%w0, %1";
971 return "ldr\t%<size>0, %1";
973 return "str<size>\t%w1, %0";
975 return "str\t%<size>1, %0";
977 return "umov\t%w0, %1.<v>[0]";
979 return "dup\t%0.<Vallxd>, %w1";
981 return "dup\t%<Vetype>0, %1.<v>[0]";
986 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
987 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
988 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
991 (define_expand "mov<mode>"
992 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
993 (match_operand:GPI 1 "general_operand" ""))]
996 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
997 && <MODE>mode == DImode
998 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1001 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1002 operands[1] = force_reg (<MODE>mode, operands[1]);
1004 /* FIXME: RR we still need to fix up what we are doing with
1005 symbol_refs and other types of constants. */
1006 if (CONSTANT_P (operands[1])
1007 && !CONST_INT_P (operands[1]))
1009 aarch64_expand_mov_immediate (operands[0], operands[1]);
1015 (define_insn_and_split "*movsi_aarch64"
1016 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w")
1017 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1018 "(register_operand (operands[0], SImode)
1019 || aarch64_reg_or_zero (operands[1], SImode))"
1035 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1036 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1039 aarch64_expand_mov_immediate (operands[0], operands[1]);
1042 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1043 adr,adr,f_mcr,f_mrc,fmov")
1044 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1047 (define_insn_and_split "*movdi_aarch64"
1048 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w, r,*w,w")
1049 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1050 "(register_operand (operands[0], DImode)
1051 || aarch64_reg_or_zero (operands[1], DImode))"
1068 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1069 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1072 aarch64_expand_mov_immediate (operands[0], operands[1]);
1075 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1076 adr,adr,f_mcr,f_mrc,fmov,neon_move")
1077 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1078 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1081 (define_insn "insv_imm<mode>"
1082 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1084 (match_operand:GPI 1 "const_int_operand" "n"))
1085 (match_operand:GPI 2 "const_int_operand" "n"))]
1086 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1087 && UINTVAL (operands[1]) % 16 == 0"
1088 "movk\\t%<w>0, %X2, lsl %1"
1089 [(set_attr "type" "mov_imm")]
1092 (define_expand "movti"
1093 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1094 (match_operand:TI 1 "general_operand" ""))]
1097 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1098 operands[1] = force_reg (TImode, operands[1]);
1102 (define_insn "*movti_aarch64"
1103 [(set (match_operand:TI 0
1104 "nonimmediate_operand" "=r, *w,r ,*w,r,m,m,*w,m")
1106 "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1107 "(register_operand (operands[0], TImode)
1108 || aarch64_reg_or_zero (operands[1], TImode))"
1113 orr\\t%0.16b, %1.16b, %1.16b
1119 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1120 load2,store2,store2,f_loadd,f_stored")
1121 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1122 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1123 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1126 ;; Split a TImode register-register or register-immediate move into
1127 ;; its component DImode pieces, taking care to handle overlapping
1128 ;; source and dest registers.
1130 [(set (match_operand:TI 0 "register_operand" "")
1131 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1132 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1135 aarch64_split_128bit_move (operands[0], operands[1]);
1139 (define_expand "mov<mode>"
1140 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1141 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1146 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1150 if (GET_CODE (operands[0]) == MEM
1151 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1152 && aarch64_float_const_zero_rtx_p (operands[1])))
1153 operands[1] = force_reg (<MODE>mode, operands[1]);
1157 (define_insn "*movhf_aarch64"
1158 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
1159 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
1160 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1161 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1166 mov\\t%0.h[0], %1.h[0]
1172 [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1173 f_loads,f_stores,load1,store1,mov_reg")
1174 (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1177 (define_insn "*movsf_aarch64"
1178 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1179 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1180 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1181 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1193 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1194 f_loads,f_stores,load1,store1,mov_reg")
1195 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1198 (define_insn "*movdf_aarch64"
1199 [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1200 (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1201 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1202 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1214 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1215 f_loadd,f_stored,load1,store1,mov_reg")
1216 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1219 (define_insn "*movtf_aarch64"
1220 [(set (match_operand:TF 0
1221 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1223 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1224 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1225 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1227 orr\\t%0.16b, %1.16b, %1.16b
1238 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1239 f_loadd,f_stored,load2,store2,store2")
1240 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1241 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1245 [(set (match_operand:TF 0 "register_operand" "")
1246 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1247 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1250 aarch64_split_128bit_move (operands[0], operands[1]);
1257 ;; 2 is size of move in bytes
1260 (define_expand "movmemdi"
1261 [(match_operand:BLK 0 "memory_operand")
1262 (match_operand:BLK 1 "memory_operand")
1263 (match_operand:DI 2 "immediate_operand")
1264 (match_operand:DI 3 "immediate_operand")]
1267 if (aarch64_expand_movmem (operands))
1273 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1274 ;; fairly lax checking on the second memory operation.
1275 (define_insn "load_pairsi"
1276 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1277 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1278 (set (match_operand:SI 2 "register_operand" "=r,*w")
1279 (match_operand:SI 3 "memory_operand" "m,m"))]
1280 "rtx_equal_p (XEXP (operands[3], 0),
1281 plus_constant (Pmode,
1282 XEXP (operands[1], 0),
1283 GET_MODE_SIZE (SImode)))"
1287 [(set_attr "type" "load2,neon_load1_2reg")
1288 (set_attr "fp" "*,yes")]
1291 (define_insn "load_pairdi"
1292 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1293 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1294 (set (match_operand:DI 2 "register_operand" "=r,*w")
1295 (match_operand:DI 3 "memory_operand" "m,m"))]
1296 "rtx_equal_p (XEXP (operands[3], 0),
1297 plus_constant (Pmode,
1298 XEXP (operands[1], 0),
1299 GET_MODE_SIZE (DImode)))"
1303 [(set_attr "type" "load2,neon_load1_2reg")
1304 (set_attr "fp" "*,yes")]
1308 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1309 ;; fairly lax checking on the second memory operation.
1310 (define_insn "store_pairsi"
1311 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1312 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1313 (set (match_operand:SI 2 "memory_operand" "=m,m")
1314 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1315 "rtx_equal_p (XEXP (operands[2], 0),
1316 plus_constant (Pmode,
1317 XEXP (operands[0], 0),
1318 GET_MODE_SIZE (SImode)))"
1322 [(set_attr "type" "store2,neon_store1_2reg")
1323 (set_attr "fp" "*,yes")]
1326 (define_insn "store_pairdi"
1327 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1328 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1329 (set (match_operand:DI 2 "memory_operand" "=m,m")
1330 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1331 "rtx_equal_p (XEXP (operands[2], 0),
1332 plus_constant (Pmode,
1333 XEXP (operands[0], 0),
1334 GET_MODE_SIZE (DImode)))"
1338 [(set_attr "type" "store2,neon_store1_2reg")
1339 (set_attr "fp" "*,yes")]
1342 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1343 ;; fairly lax checking on the second memory operation.
1344 (define_insn "load_pairsf"
1345 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1346 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1347 (set (match_operand:SF 2 "register_operand" "=w,*r")
1348 (match_operand:SF 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 (SFmode)))"
1356 [(set_attr "type" "neon_load1_2reg,load2")
1357 (set_attr "fp" "yes,*")]
1360 (define_insn "load_pairdf"
1361 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1362 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1363 (set (match_operand:DF 2 "register_operand" "=w,*r")
1364 (match_operand:DF 3 "memory_operand" "m,m"))]
1365 "rtx_equal_p (XEXP (operands[3], 0),
1366 plus_constant (Pmode,
1367 XEXP (operands[1], 0),
1368 GET_MODE_SIZE (DFmode)))"
1372 [(set_attr "type" "neon_load1_2reg,load2")
1373 (set_attr "fp" "yes,*")]
1376 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1377 ;; fairly lax checking on the second memory operation.
1378 (define_insn "store_pairsf"
1379 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1380 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1381 (set (match_operand:SF 2 "memory_operand" "=m,m")
1382 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1383 "rtx_equal_p (XEXP (operands[2], 0),
1384 plus_constant (Pmode,
1385 XEXP (operands[0], 0),
1386 GET_MODE_SIZE (SFmode)))"
1390 [(set_attr "type" "neon_store1_2reg,store2")
1391 (set_attr "fp" "yes,*")]
1394 (define_insn "store_pairdf"
1395 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1396 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1397 (set (match_operand:DF 2 "memory_operand" "=m,m")
1398 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1399 "rtx_equal_p (XEXP (operands[2], 0),
1400 plus_constant (Pmode,
1401 XEXP (operands[0], 0),
1402 GET_MODE_SIZE (DFmode)))"
1406 [(set_attr "type" "neon_store1_2reg,store2")
1407 (set_attr "fp" "yes,*")]
1410 ;; Load pair with post-index writeback. This is primarily used in function
1412 (define_insn "loadwb_pair<GPI: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:GPI 2 "register_operand" "=r")
1418 (mem:GPI (match_dup 1)))
1419 (set (match_operand:GPI 3 "register_operand" "=r")
1420 (mem:GPI (plus:P (match_dup 1)
1421 (match_operand:P 5 "const_int_operand" "n"))))])]
1422 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1423 "ldp\\t%<w>2, %<w>3, [%1], %4"
1424 [(set_attr "type" "load2")]
1427 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1429 [(set (match_operand:P 0 "register_operand" "=k")
1430 (plus:P (match_operand:P 1 "register_operand" "0")
1431 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1432 (set (match_operand:GPF 2 "register_operand" "=w")
1433 (mem:GPF (match_dup 1)))
1434 (set (match_operand:GPF 3 "register_operand" "=w")
1435 (mem:GPF (plus:P (match_dup 1)
1436 (match_operand:P 5 "const_int_operand" "n"))))])]
1437 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1438 "ldp\\t%<w>2, %<w>3, [%1], %4"
1439 [(set_attr "type" "neon_load1_2reg")]
1442 ;; Store pair with pre-index writeback. This is primarily used in function
1444 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1446 [(set (match_operand:P 0 "register_operand" "=&k")
1447 (plus:P (match_operand:P 1 "register_operand" "0")
1448 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1449 (set (mem:GPI (plus:P (match_dup 0)
1451 (match_operand:GPI 2 "register_operand" "r"))
1452 (set (mem:GPI (plus:P (match_dup 0)
1453 (match_operand:P 5 "const_int_operand" "n")))
1454 (match_operand:GPI 3 "register_operand" "r"))])]
1455 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1456 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1457 [(set_attr "type" "store2")]
1460 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1462 [(set (match_operand:P 0 "register_operand" "=&k")
1463 (plus:P (match_operand:P 1 "register_operand" "0")
1464 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1465 (set (mem:GPF (plus:P (match_dup 0)
1467 (match_operand:GPF 2 "register_operand" "w"))
1468 (set (mem:GPF (plus:P (match_dup 0)
1469 (match_operand:P 5 "const_int_operand" "n")))
1470 (match_operand:GPF 3 "register_operand" "w"))])]
1471 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1472 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1473 [(set_attr "type" "neon_store1_2reg<q>")]
1476 ;; -------------------------------------------------------------------
1477 ;; Sign/Zero extension
1478 ;; -------------------------------------------------------------------
1480 (define_expand "<optab>sidi2"
1481 [(set (match_operand:DI 0 "register_operand")
1482 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1486 (define_insn "*extendsidi2_aarch64"
1487 [(set (match_operand:DI 0 "register_operand" "=r,r")
1488 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1493 [(set_attr "type" "extend,load1")]
1496 (define_insn "*load_pair_extendsidi2_aarch64"
1497 [(set (match_operand:DI 0 "register_operand" "=r")
1498 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1499 (set (match_operand:DI 2 "register_operand" "=r")
1500 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1501 "rtx_equal_p (XEXP (operands[3], 0),
1502 plus_constant (Pmode,
1503 XEXP (operands[1], 0),
1504 GET_MODE_SIZE (SImode)))"
1505 "ldpsw\\t%0, %2, %1"
1506 [(set_attr "type" "load2")]
1509 (define_insn "*zero_extendsidi2_aarch64"
1510 [(set (match_operand:DI 0 "register_operand" "=r,r")
1511 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1516 [(set_attr "type" "extend,load1")]
1519 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1520 [(set (match_operand:DI 0 "register_operand" "=r")
1521 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1522 (set (match_operand:DI 2 "register_operand" "=r")
1523 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1524 "rtx_equal_p (XEXP (operands[3], 0),
1525 plus_constant (Pmode,
1526 XEXP (operands[1], 0),
1527 GET_MODE_SIZE (SImode)))"
1528 "ldp\\t%w0, %w2, %1"
1529 [(set_attr "type" "load2")]
1532 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1533 [(set (match_operand:GPI 0 "register_operand")
1534 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1538 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1539 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1540 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1543 sxt<SHORT:size>\t%<GPI:w>0, %w1
1544 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1545 [(set_attr "type" "extend,load1")]
1548 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1549 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1550 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1553 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1554 ldr<SHORT:size>\t%w0, %1
1555 ldr\t%<SHORT:size>0, %1"
1556 [(set_attr "type" "logic_imm,load1,load1")]
1559 (define_expand "<optab>qihi2"
1560 [(set (match_operand:HI 0 "register_operand")
1561 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1565 (define_insn "*extendqihi2_aarch64"
1566 [(set (match_operand:HI 0 "register_operand" "=r,r")
1567 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1572 [(set_attr "type" "extend,load1")]
1575 (define_insn "*zero_extendqihi2_aarch64"
1576 [(set (match_operand:HI 0 "register_operand" "=r,r")
1577 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1582 [(set_attr "type" "logic_imm,load1")]
1585 ;; -------------------------------------------------------------------
1586 ;; Simple arithmetic
1587 ;; -------------------------------------------------------------------
1589 (define_expand "add<mode>3"
1591 (match_operand:GPI 0 "register_operand" "")
1592 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1593 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1596 /* If operands[1] is a subreg extract the inner RTX. */
1597 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1599 /* If the constant is too large for a single instruction and isn't frame
1600 based, split off the immediate so it is available for CSE. */
1601 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1602 && can_create_pseudo_p ()
1604 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1605 operands[2] = force_reg (<MODE>mode, operands[2]);
1608 (define_insn "*add<mode>3_aarch64"
1610 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1612 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1613 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1616 add\\t%<w>0, %<w>1, %2
1617 add\\t%<w>0, %<w>1, %<w>2
1618 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1619 sub\\t%<w>0, %<w>1, #%n2
1621 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1622 (set_attr "simd" "*,*,yes,*,*")]
1625 ;; zero_extend version of above
1626 (define_insn "*addsi3_aarch64_uxtw"
1628 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1630 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1631 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1636 sub\\t%w0, %w1, #%n2
1638 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1641 ;; If there's a free register, and we can load the constant with a
1642 ;; single instruction, do so. This has a chance to improve scheduling.
1644 [(match_scratch:GPI 3 "r")
1645 (set (match_operand:GPI 0 "register_operand")
1647 (match_operand:GPI 1 "register_operand")
1648 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1649 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1650 [(set (match_dup 3) (match_dup 2))
1651 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1655 [(match_scratch:SI 3 "r")
1656 (set (match_operand:DI 0 "register_operand")
1659 (match_operand:SI 1 "register_operand")
1660 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1661 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1662 [(set (match_dup 3) (match_dup 2))
1663 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1666 ;; After peephole2 has had a chance to run, split any remaining long
1667 ;; additions into two add immediates.
1669 [(set (match_operand:GPI 0 "register_operand")
1671 (match_operand:GPI 1 "register_operand")
1672 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1673 "epilogue_completed"
1674 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1675 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1677 HOST_WIDE_INT i = INTVAL (operands[2]);
1678 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1679 operands[3] = GEN_INT (i - s);
1680 operands[4] = GEN_INT (s);
1685 [(set (match_operand:DI 0 "register_operand")
1688 (match_operand:SI 1 "register_operand")
1689 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1690 "epilogue_completed"
1691 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1692 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1694 HOST_WIDE_INT i = INTVAL (operands[2]);
1695 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1696 operands[3] = GEN_INT (i - s);
1697 operands[4] = GEN_INT (s);
1698 operands[5] = gen_lowpart (SImode, operands[0]);
1702 (define_expand "addti3"
1703 [(set (match_operand:TI 0 "register_operand" "")
1704 (plus:TI (match_operand:TI 1 "register_operand" "")
1705 (match_operand:TI 2 "register_operand" "")))]
1708 rtx low = gen_reg_rtx (DImode);
1709 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1710 gen_lowpart (DImode, operands[2])));
1712 rtx high = gen_reg_rtx (DImode);
1713 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1714 gen_highpart (DImode, operands[2])));
1716 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1717 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1721 (define_insn "add<mode>3_compare0"
1722 [(set (reg:CC_NZ CC_REGNUM)
1724 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1725 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1727 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1728 (plus:GPI (match_dup 1) (match_dup 2)))]
1731 adds\\t%<w>0, %<w>1, %<w>2
1732 adds\\t%<w>0, %<w>1, %2
1733 subs\\t%<w>0, %<w>1, #%n2"
1734 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1737 ;; zero_extend version of above
1738 (define_insn "*addsi3_compare0_uxtw"
1739 [(set (reg:CC_NZ CC_REGNUM)
1741 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1742 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1744 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1745 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1748 adds\\t%w0, %w1, %w2
1750 subs\\t%w0, %w1, #%n2"
1751 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1754 (define_insn "*add<mode>3_compareC_cconly_imm"
1755 [(set (reg:CC_C CC_REGNUM)
1758 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1759 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1763 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1764 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1765 <MODE>mode, operands[1])"
1769 [(set_attr "type" "alus_imm")]
1772 (define_insn "*add<mode>3_compareC_cconly"
1773 [(set (reg:CC_C CC_REGNUM)
1776 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1777 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1778 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1780 "cmn\\t%<w>0, %<w>1"
1781 [(set_attr "type" "alus_sreg")]
1784 (define_insn "*add<mode>3_compareC_imm"
1785 [(set (reg:CC_C CC_REGNUM)
1788 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1789 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1793 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1794 (set (match_operand:GPI 0 "register_operand" "=r,r")
1795 (plus:GPI (match_dup 1) (match_dup 2)))]
1796 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1797 <MODE>mode, operands[2])"
1799 adds\\t%<w>0, %<w>1, %2
1800 subs\\t%<w>0, %<w>1, #%n2"
1801 [(set_attr "type" "alus_imm")]
1804 (define_insn "add<mode>3_compareC"
1805 [(set (reg:CC_C CC_REGNUM)
1808 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1809 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1811 (plus:GPI (match_dup 1) (match_dup 2)))))
1812 (set (match_operand:GPI 0 "register_operand" "=r")
1813 (plus:GPI (match_dup 1) (match_dup 2)))]
1815 "adds\\t%<w>0, %<w>1, %<w>2"
1816 [(set_attr "type" "alus_sreg")]
1819 (define_insn "*adds_shift_imm_<mode>"
1820 [(set (reg:CC_NZ CC_REGNUM)
1822 (plus:GPI (ASHIFT:GPI
1823 (match_operand:GPI 1 "register_operand" "r")
1824 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1825 (match_operand:GPI 3 "register_operand" "r"))
1827 (set (match_operand:GPI 0 "register_operand" "=r")
1828 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1831 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1832 [(set_attr "type" "alus_shift_imm")]
1835 (define_insn "*subs_shift_imm_<mode>"
1836 [(set (reg:CC_NZ CC_REGNUM)
1838 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1840 (match_operand:GPI 2 "register_operand" "r")
1841 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1843 (set (match_operand:GPI 0 "register_operand" "=r")
1844 (minus:GPI (match_dup 1)
1845 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1847 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1848 [(set_attr "type" "alus_shift_imm")]
1851 (define_insn "*adds_mul_imm_<mode>"
1852 [(set (reg:CC_NZ CC_REGNUM)
1855 (match_operand:GPI 1 "register_operand" "r")
1856 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1857 (match_operand:GPI 3 "register_operand" "r"))
1859 (set (match_operand:GPI 0 "register_operand" "=r")
1860 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1863 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1864 [(set_attr "type" "alus_shift_imm")]
1867 (define_insn "*subs_mul_imm_<mode>"
1868 [(set (reg:CC_NZ CC_REGNUM)
1870 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1872 (match_operand:GPI 2 "register_operand" "r")
1873 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1875 (set (match_operand:GPI 0 "register_operand" "=r")
1876 (minus:GPI (match_dup 1)
1877 (mult:GPI (match_dup 2) (match_dup 3))))]
1879 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1880 [(set_attr "type" "alus_shift_imm")]
1883 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1884 [(set (reg:CC_NZ CC_REGNUM)
1887 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1888 (match_operand:GPI 2 "register_operand" "r"))
1890 (set (match_operand:GPI 0 "register_operand" "=r")
1891 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1893 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1894 [(set_attr "type" "alus_ext")]
1897 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1898 [(set (reg:CC_NZ CC_REGNUM)
1900 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1902 (match_operand:ALLX 2 "register_operand" "r")))
1904 (set (match_operand:GPI 0 "register_operand" "=r")
1905 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1907 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1908 [(set_attr "type" "alus_ext")]
1911 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1912 [(set (reg:CC_NZ CC_REGNUM)
1914 (plus:GPI (ashift:GPI
1916 (match_operand:ALLX 1 "register_operand" "r"))
1917 (match_operand 2 "aarch64_imm3" "Ui3"))
1918 (match_operand:GPI 3 "register_operand" "r"))
1920 (set (match_operand:GPI 0 "register_operand" "=rk")
1921 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1925 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1926 [(set_attr "type" "alus_ext")]
1929 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1930 [(set (reg:CC_NZ CC_REGNUM)
1932 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1935 (match_operand:ALLX 2 "register_operand" "r"))
1936 (match_operand 3 "aarch64_imm3" "Ui3")))
1938 (set (match_operand:GPI 0 "register_operand" "=rk")
1939 (minus:GPI (match_dup 1)
1940 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1943 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1944 [(set_attr "type" "alus_ext")]
1947 (define_insn "*adds_<optab><mode>_multp2"
1948 [(set (reg:CC_NZ CC_REGNUM)
1950 (plus:GPI (ANY_EXTRACT:GPI
1951 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1952 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1953 (match_operand 3 "const_int_operand" "n")
1955 (match_operand:GPI 4 "register_operand" "r"))
1957 (set (match_operand:GPI 0 "register_operand" "=r")
1958 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1962 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1963 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1964 [(set_attr "type" "alus_ext")]
1967 (define_insn "*subs_<optab><mode>_multp2"
1968 [(set (reg:CC_NZ CC_REGNUM)
1970 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1972 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1973 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1974 (match_operand 3 "const_int_operand" "n")
1977 (set (match_operand:GPI 0 "register_operand" "=r")
1978 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1979 (mult:GPI (match_dup 1) (match_dup 2))
1982 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1983 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1984 [(set_attr "type" "alus_ext")]
1987 (define_insn "*add<mode>3nr_compare0"
1988 [(set (reg:CC_NZ CC_REGNUM)
1990 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1991 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1998 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2001 (define_insn "*compare_neg<mode>"
2002 [(set (reg:CC_Z CC_REGNUM)
2004 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2005 (match_operand:GPI 1 "register_operand" "r")))]
2007 "cmn\\t%<w>1, %<w>0"
2008 [(set_attr "type" "alus_sreg")]
2011 (define_insn "*add_<shift>_<mode>"
2012 [(set (match_operand:GPI 0 "register_operand" "=r")
2013 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2014 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2015 (match_operand:GPI 3 "register_operand" "r")))]
2017 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2018 [(set_attr "type" "alu_shift_imm")]
2021 ;; zero_extend version of above
2022 (define_insn "*add_<shift>_si_uxtw"
2023 [(set (match_operand:DI 0 "register_operand" "=r")
2025 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2026 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2027 (match_operand:SI 3 "register_operand" "r"))))]
2029 "add\\t%w0, %w3, %w1, <shift> %2"
2030 [(set_attr "type" "alu_shift_imm")]
2033 (define_insn "*add_mul_imm_<mode>"
2034 [(set (match_operand:GPI 0 "register_operand" "=r")
2035 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2036 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2037 (match_operand:GPI 3 "register_operand" "r")))]
2039 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2040 [(set_attr "type" "alu_shift_imm")]
2043 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2044 [(set (match_operand:GPI 0 "register_operand" "=rk")
2045 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2046 (match_operand:GPI 2 "register_operand" "r")))]
2048 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2049 [(set_attr "type" "alu_ext")]
2052 ;; zero_extend version of above
2053 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2054 [(set (match_operand:DI 0 "register_operand" "=rk")
2056 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2057 (match_operand:GPI 2 "register_operand" "r"))))]
2059 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2060 [(set_attr "type" "alu_ext")]
2063 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2064 [(set (match_operand:GPI 0 "register_operand" "=rk")
2065 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2066 (match_operand:ALLX 1 "register_operand" "r"))
2067 (match_operand 2 "aarch64_imm3" "Ui3"))
2068 (match_operand:GPI 3 "register_operand" "r")))]
2070 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2071 [(set_attr "type" "alu_ext")]
2074 ;; zero_extend version of above
2075 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2076 [(set (match_operand:DI 0 "register_operand" "=rk")
2078 (plus:SI (ashift:SI (ANY_EXTEND:SI
2079 (match_operand:SHORT 1 "register_operand" "r"))
2080 (match_operand 2 "aarch64_imm3" "Ui3"))
2081 (match_operand:SI 3 "register_operand" "r"))))]
2083 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2084 [(set_attr "type" "alu_ext")]
2087 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2088 [(set (match_operand:GPI 0 "register_operand" "=rk")
2089 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2090 (match_operand:ALLX 1 "register_operand" "r"))
2091 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2092 (match_operand:GPI 3 "register_operand" "r")))]
2094 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2095 [(set_attr "type" "alu_ext")]
2098 ;; zero_extend version of above
2099 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2100 [(set (match_operand:DI 0 "register_operand" "=rk")
2101 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2102 (match_operand:SHORT 1 "register_operand" "r"))
2103 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2104 (match_operand:SI 3 "register_operand" "r"))))]
2106 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2107 [(set_attr "type" "alu_ext")]
2110 (define_insn "*add_<optab><mode>_multp2"
2111 [(set (match_operand:GPI 0 "register_operand" "=rk")
2112 (plus:GPI (ANY_EXTRACT:GPI
2113 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2114 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2115 (match_operand 3 "const_int_operand" "n")
2117 (match_operand:GPI 4 "register_operand" "r")))]
2118 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2119 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2120 [(set_attr "type" "alu_ext")]
2123 ;; zero_extend version of above
2124 (define_insn "*add_<optab>si_multp2_uxtw"
2125 [(set (match_operand:DI 0 "register_operand" "=rk")
2127 (plus:SI (ANY_EXTRACT:SI
2128 (mult:SI (match_operand:SI 1 "register_operand" "r")
2129 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2130 (match_operand 3 "const_int_operand" "n")
2132 (match_operand:SI 4 "register_operand" "r"))))]
2133 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2134 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2135 [(set_attr "type" "alu_ext")]
2138 (define_expand "add<mode>3_carryin"
2139 [(set (match_operand:GPI 0 "register_operand")
2142 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2143 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2144 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2149 ;; Note that add with carry with two zero inputs is matched by cset,
2150 ;; and that add with carry with one zero input is matched by cinc.
2152 (define_insn "*add<mode>3_carryin"
2153 [(set (match_operand:GPI 0 "register_operand" "=r")
2156 (match_operand:GPI 3 "aarch64_carry_operation" "")
2157 (match_operand:GPI 1 "register_operand" "r"))
2158 (match_operand:GPI 2 "register_operand" "r")))]
2160 "adc\\t%<w>0, %<w>1, %<w>2"
2161 [(set_attr "type" "adc_reg")]
2164 ;; zero_extend version of above
2165 (define_insn "*addsi3_carryin_uxtw"
2166 [(set (match_operand:DI 0 "register_operand" "=r")
2170 (match_operand:SI 3 "aarch64_carry_operation" "")
2171 (match_operand:SI 1 "register_operand" "r"))
2172 (match_operand:SI 2 "register_operand" "r"))))]
2174 "adc\\t%w0, %w1, %w2"
2175 [(set_attr "type" "adc_reg")]
2178 (define_insn "*add_uxt<mode>_shift2"
2179 [(set (match_operand:GPI 0 "register_operand" "=rk")
2181 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2182 (match_operand 2 "aarch64_imm3" "Ui3"))
2183 (match_operand 3 "const_int_operand" "n"))
2184 (match_operand:GPI 4 "register_operand" "r")))]
2185 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2187 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2188 INTVAL (operands[3])));
2189 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2190 [(set_attr "type" "alu_ext")]
2193 ;; zero_extend version of above
2194 (define_insn "*add_uxtsi_shift2_uxtw"
2195 [(set (match_operand:DI 0 "register_operand" "=rk")
2198 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2199 (match_operand 2 "aarch64_imm3" "Ui3"))
2200 (match_operand 3 "const_int_operand" "n"))
2201 (match_operand:SI 4 "register_operand" "r"))))]
2202 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2204 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2205 INTVAL (operands[3])));
2206 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2207 [(set_attr "type" "alu_ext")]
2210 (define_insn "*add_uxt<mode>_multp2"
2211 [(set (match_operand:GPI 0 "register_operand" "=rk")
2213 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2214 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2215 (match_operand 3 "const_int_operand" "n"))
2216 (match_operand:GPI 4 "register_operand" "r")))]
2217 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2219 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2220 INTVAL (operands[3])));
2221 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2222 [(set_attr "type" "alu_ext")]
2225 ;; zero_extend version of above
2226 (define_insn "*add_uxtsi_multp2_uxtw"
2227 [(set (match_operand:DI 0 "register_operand" "=rk")
2230 (mult:SI (match_operand:SI 1 "register_operand" "r")
2231 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2232 (match_operand 3 "const_int_operand" "n"))
2233 (match_operand:SI 4 "register_operand" "r"))))]
2234 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2236 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2237 INTVAL (operands[3])));
2238 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2239 [(set_attr "type" "alu_ext")]
2242 (define_insn "subsi3"
2243 [(set (match_operand:SI 0 "register_operand" "=rk")
2244 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2245 (match_operand:SI 2 "register_operand" "r")))]
2247 "sub\\t%w0, %w1, %w2"
2248 [(set_attr "type" "alu_sreg")]
2251 ;; zero_extend version of above
2252 (define_insn "*subsi3_uxtw"
2253 [(set (match_operand:DI 0 "register_operand" "=rk")
2255 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2256 (match_operand:SI 2 "register_operand" "r"))))]
2258 "sub\\t%w0, %w1, %w2"
2259 [(set_attr "type" "alu_sreg")]
2262 (define_insn "subdi3"
2263 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2264 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2265 (match_operand:DI 2 "register_operand" "r,w")))]
2269 sub\\t%d0, %d1, %d2"
2270 [(set_attr "type" "alu_sreg, neon_sub")
2271 (set_attr "simd" "*,yes")]
2274 (define_expand "subti3"
2275 [(set (match_operand:TI 0 "register_operand" "")
2276 (minus:TI (match_operand:TI 1 "register_operand" "")
2277 (match_operand:TI 2 "register_operand" "")))]
2280 rtx low = gen_reg_rtx (DImode);
2281 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2282 gen_lowpart (DImode, operands[2])));
2284 rtx high = gen_reg_rtx (DImode);
2285 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2286 gen_highpart (DImode, operands[2])));
2288 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2289 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2293 (define_insn "*sub<mode>3_compare0"
2294 [(set (reg:CC_NZ CC_REGNUM)
2295 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2296 (match_operand:GPI 2 "register_operand" "r"))
2298 (set (match_operand:GPI 0 "register_operand" "=r")
2299 (minus:GPI (match_dup 1) (match_dup 2)))]
2301 "subs\\t%<w>0, %<w>1, %<w>2"
2302 [(set_attr "type" "alus_sreg")]
2305 ;; zero_extend version of above
2306 (define_insn "*subsi3_compare0_uxtw"
2307 [(set (reg:CC_NZ CC_REGNUM)
2308 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2309 (match_operand:SI 2 "register_operand" "r"))
2311 (set (match_operand:DI 0 "register_operand" "=r")
2312 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2314 "subs\\t%w0, %w1, %w2"
2315 [(set_attr "type" "alus_sreg")]
2318 (define_insn "sub<mode>3_compare1"
2319 [(set (reg:CC CC_REGNUM)
2321 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2322 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2323 (set (match_operand:GPI 0 "register_operand" "=r")
2324 (minus:GPI (match_dup 1) (match_dup 2)))]
2326 "subs\\t%<w>0, %<w>1, %<w>2"
2327 [(set_attr "type" "alus_sreg")]
2330 (define_insn "*sub_<shift>_<mode>"
2331 [(set (match_operand:GPI 0 "register_operand" "=r")
2332 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2334 (match_operand:GPI 1 "register_operand" "r")
2335 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2337 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2338 [(set_attr "type" "alu_shift_imm")]
2341 ;; zero_extend version of above
2342 (define_insn "*sub_<shift>_si_uxtw"
2343 [(set (match_operand:DI 0 "register_operand" "=r")
2345 (minus:SI (match_operand:SI 3 "register_operand" "r")
2347 (match_operand:SI 1 "register_operand" "r")
2348 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2350 "sub\\t%w0, %w3, %w1, <shift> %2"
2351 [(set_attr "type" "alu_shift_imm")]
2354 (define_insn "*sub_mul_imm_<mode>"
2355 [(set (match_operand:GPI 0 "register_operand" "=r")
2356 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2358 (match_operand:GPI 1 "register_operand" "r")
2359 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2361 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2362 [(set_attr "type" "alu_shift_imm")]
2365 ;; zero_extend version of above
2366 (define_insn "*sub_mul_imm_si_uxtw"
2367 [(set (match_operand:DI 0 "register_operand" "=r")
2369 (minus:SI (match_operand:SI 3 "register_operand" "r")
2371 (match_operand:SI 1 "register_operand" "r")
2372 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2374 "sub\\t%w0, %w3, %w1, lsl %p2"
2375 [(set_attr "type" "alu_shift_imm")]
2378 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2379 [(set (match_operand:GPI 0 "register_operand" "=rk")
2380 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2382 (match_operand:ALLX 2 "register_operand" "r"))))]
2384 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2385 [(set_attr "type" "alu_ext")]
2388 ;; zero_extend version of above
2389 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2390 [(set (match_operand:DI 0 "register_operand" "=rk")
2392 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2394 (match_operand:SHORT 2 "register_operand" "r")))))]
2396 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2397 [(set_attr "type" "alu_ext")]
2400 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2401 [(set (match_operand:GPI 0 "register_operand" "=rk")
2402 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2403 (ashift:GPI (ANY_EXTEND:GPI
2404 (match_operand:ALLX 2 "register_operand" "r"))
2405 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2407 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2408 [(set_attr "type" "alu_ext")]
2411 ;; zero_extend version of above
2412 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2413 [(set (match_operand:DI 0 "register_operand" "=rk")
2415 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2416 (ashift:SI (ANY_EXTEND:SI
2417 (match_operand:SHORT 2 "register_operand" "r"))
2418 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2420 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2421 [(set_attr "type" "alu_ext")]
2424 (define_insn "*sub_<optab><mode>_multp2"
2425 [(set (match_operand:GPI 0 "register_operand" "=rk")
2426 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2428 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2429 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2430 (match_operand 3 "const_int_operand" "n")
2432 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2433 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2434 [(set_attr "type" "alu_ext")]
2437 ;; zero_extend version of above
2438 (define_insn "*sub_<optab>si_multp2_uxtw"
2439 [(set (match_operand:DI 0 "register_operand" "=rk")
2441 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2443 (mult:SI (match_operand:SI 1 "register_operand" "r")
2444 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2445 (match_operand 3 "const_int_operand" "n")
2447 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2448 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2449 [(set_attr "type" "alu_ext")]
2452 ;; The hardware description is op1 + ~op2 + C.
2453 ;; = op1 + (-op2 + 1) + (1 - !C)
2454 ;; = op1 - op2 - 1 + 1 - !C
2455 ;; = op1 - op2 - !C.
2456 ;; We describe the latter.
2458 (define_insn "*sub<mode>3_carryin0"
2459 [(set (match_operand:GPI 0 "register_operand" "=r")
2461 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2462 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2464 "sbc\\t%<w>0, %<w>1, <w>zr"
2465 [(set_attr "type" "adc_reg")]
2468 ;; zero_extend version of the above
2469 (define_insn "*subsi3_carryin_uxtw"
2470 [(set (match_operand:DI 0 "register_operand" "=r")
2473 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2474 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2476 "sbc\\t%w0, %w1, wzr"
2477 [(set_attr "type" "adc_reg")]
2480 (define_expand "sub<mode>3_carryin"
2481 [(set (match_operand:GPI 0 "register_operand")
2484 (match_operand:GPI 1 "aarch64_reg_or_zero")
2485 (match_operand:GPI 2 "register_operand"))
2486 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2491 (define_insn "*sub<mode>3_carryin"
2492 [(set (match_operand:GPI 0 "register_operand" "=r")
2495 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2496 (match_operand:GPI 2 "register_operand" "r"))
2497 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2500 "sbc\\t%<w>0, %<w>1, %<w>2"
2501 [(set_attr "type" "adc_reg")]
2504 ;; zero_extend version of the above
2505 (define_insn "*subsi3_carryin_uxtw"
2506 [(set (match_operand:DI 0 "register_operand" "=r")
2510 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2511 (match_operand:SI 2 "register_operand" "r"))
2512 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2515 "sbc\\t%w0, %w1, %w2"
2516 [(set_attr "type" "adc_reg")]
2519 (define_insn "*sub<mode>3_carryin_alt"
2520 [(set (match_operand:GPI 0 "register_operand" "=r")
2523 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2524 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2525 (match_operand:GPI 2 "register_operand" "r")))]
2527 "sbc\\t%<w>0, %<w>1, %<w>2"
2528 [(set_attr "type" "adc_reg")]
2531 ;; zero_extend version of the above
2532 (define_insn "*subsi3_carryin_alt_uxtw"
2533 [(set (match_operand:DI 0 "register_operand" "=r")
2537 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2538 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2539 (match_operand:SI 2 "register_operand" "r"))))]
2541 "sbc\\t%w0, %w1, %w2"
2542 [(set_attr "type" "adc_reg")]
2545 (define_insn "*sub_uxt<mode>_shift2"
2546 [(set (match_operand:GPI 0 "register_operand" "=rk")
2547 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2549 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2550 (match_operand 2 "aarch64_imm3" "Ui3"))
2551 (match_operand 3 "const_int_operand" "n"))))]
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 \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2557 [(set_attr "type" "alu_ext")]
2560 ;; zero_extend version of above
2561 (define_insn "*sub_uxtsi_shift2_uxtw"
2562 [(set (match_operand:DI 0 "register_operand" "=rk")
2564 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2566 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2567 (match_operand 2 "aarch64_imm3" "Ui3"))
2568 (match_operand 3 "const_int_operand" "n")))))]
2569 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2571 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2572 INTVAL (operands[3])));
2573 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2574 [(set_attr "type" "alu_ext")]
2577 (define_insn "*sub_uxt<mode>_multp2"
2578 [(set (match_operand:GPI 0 "register_operand" "=rk")
2579 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2581 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2582 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2583 (match_operand 3 "const_int_operand" "n"))))]
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 \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2589 [(set_attr "type" "alu_ext")]
2592 ;; zero_extend version of above
2593 (define_insn "*sub_uxtsi_multp2_uxtw"
2594 [(set (match_operand:DI 0 "register_operand" "=rk")
2596 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2598 (mult:SI (match_operand:SI 1 "register_operand" "r")
2599 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2600 (match_operand 3 "const_int_operand" "n")))))]
2601 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2603 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2604 INTVAL (operands[3])));
2605 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2606 [(set_attr "type" "alu_ext")]
2609 (define_expand "abs<mode>2"
2610 [(match_operand:GPI 0 "register_operand" "")
2611 (match_operand:GPI 1 "register_operand" "")]
2614 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2615 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2616 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2621 (define_insn "neg<mode>2"
2622 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2623 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2627 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2628 [(set_attr "type" "alu_sreg, neon_neg<q>")
2629 (set_attr "simd" "*,yes")]
2632 ;; zero_extend version of above
2633 (define_insn "*negsi2_uxtw"
2634 [(set (match_operand:DI 0 "register_operand" "=r")
2635 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2638 [(set_attr "type" "alu_sreg")]
2641 (define_insn "*ngc<mode>"
2642 [(set (match_operand:GPI 0 "register_operand" "=r")
2644 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2645 (match_operand:GPI 1 "register_operand" "r")))]
2647 "ngc\\t%<w>0, %<w>1"
2648 [(set_attr "type" "adc_reg")]
2651 (define_insn "*ngcsi_uxtw"
2652 [(set (match_operand:DI 0 "register_operand" "=r")
2655 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2656 (match_operand:SI 1 "register_operand" "r"))))]
2659 [(set_attr "type" "adc_reg")]
2662 (define_insn "neg<mode>2_compare0"
2663 [(set (reg:CC_NZ CC_REGNUM)
2664 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2666 (set (match_operand:GPI 0 "register_operand" "=r")
2667 (neg:GPI (match_dup 1)))]
2669 "negs\\t%<w>0, %<w>1"
2670 [(set_attr "type" "alus_sreg")]
2673 ;; zero_extend version of above
2674 (define_insn "*negsi2_compare0_uxtw"
2675 [(set (reg:CC_NZ CC_REGNUM)
2676 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2678 (set (match_operand:DI 0 "register_operand" "=r")
2679 (zero_extend:DI (neg:SI (match_dup 1))))]
2682 [(set_attr "type" "alus_sreg")]
2685 (define_insn "*neg_<shift><mode>3_compare0"
2686 [(set (reg:CC_NZ CC_REGNUM)
2688 (neg:GPI (ASHIFT:GPI
2689 (match_operand:GPI 1 "register_operand" "r")
2690 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2692 (set (match_operand:GPI 0 "register_operand" "=r")
2693 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2695 "negs\\t%<w>0, %<w>1, <shift> %2"
2696 [(set_attr "type" "alus_shift_imm")]
2699 (define_insn "*neg_<shift>_<mode>2"
2700 [(set (match_operand:GPI 0 "register_operand" "=r")
2701 (neg:GPI (ASHIFT:GPI
2702 (match_operand:GPI 1 "register_operand" "r")
2703 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2705 "neg\\t%<w>0, %<w>1, <shift> %2"
2706 [(set_attr "type" "alu_shift_imm")]
2709 ;; zero_extend version of above
2710 (define_insn "*neg_<shift>_si2_uxtw"
2711 [(set (match_operand:DI 0 "register_operand" "=r")
2714 (match_operand:SI 1 "register_operand" "r")
2715 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2717 "neg\\t%w0, %w1, <shift> %2"
2718 [(set_attr "type" "alu_shift_imm")]
2721 (define_insn "*neg_mul_imm_<mode>2"
2722 [(set (match_operand:GPI 0 "register_operand" "=r")
2724 (match_operand:GPI 1 "register_operand" "r")
2725 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2727 "neg\\t%<w>0, %<w>1, lsl %p2"
2728 [(set_attr "type" "alu_shift_imm")]
2731 ;; zero_extend version of above
2732 (define_insn "*neg_mul_imm_si2_uxtw"
2733 [(set (match_operand:DI 0 "register_operand" "=r")
2736 (match_operand:SI 1 "register_operand" "r")
2737 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2739 "neg\\t%w0, %w1, lsl %p2"
2740 [(set_attr "type" "alu_shift_imm")]
2743 (define_insn "mul<mode>3"
2744 [(set (match_operand:GPI 0 "register_operand" "=r")
2745 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2746 (match_operand:GPI 2 "register_operand" "r")))]
2748 "mul\\t%<w>0, %<w>1, %<w>2"
2749 [(set_attr "type" "mul")]
2752 ;; zero_extend version of above
2753 (define_insn "*mulsi3_uxtw"
2754 [(set (match_operand:DI 0 "register_operand" "=r")
2756 (mult:SI (match_operand:SI 1 "register_operand" "r")
2757 (match_operand:SI 2 "register_operand" "r"))))]
2759 "mul\\t%w0, %w1, %w2"
2760 [(set_attr "type" "mul")]
2763 (define_insn "madd<mode>"
2764 [(set (match_operand:GPI 0 "register_operand" "=r")
2765 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2766 (match_operand:GPI 2 "register_operand" "r"))
2767 (match_operand:GPI 3 "register_operand" "r")))]
2769 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2770 [(set_attr "type" "mla")]
2773 ;; zero_extend version of above
2774 (define_insn "*maddsi_uxtw"
2775 [(set (match_operand:DI 0 "register_operand" "=r")
2777 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2778 (match_operand:SI 2 "register_operand" "r"))
2779 (match_operand:SI 3 "register_operand" "r"))))]
2781 "madd\\t%w0, %w1, %w2, %w3"
2782 [(set_attr "type" "mla")]
2785 (define_insn "*msub<mode>"
2786 [(set (match_operand:GPI 0 "register_operand" "=r")
2787 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2788 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2789 (match_operand:GPI 2 "register_operand" "r"))))]
2792 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2793 [(set_attr "type" "mla")]
2796 ;; zero_extend version of above
2797 (define_insn "*msubsi_uxtw"
2798 [(set (match_operand:DI 0 "register_operand" "=r")
2800 (minus:SI (match_operand:SI 3 "register_operand" "r")
2801 (mult:SI (match_operand:SI 1 "register_operand" "r")
2802 (match_operand:SI 2 "register_operand" "r")))))]
2805 "msub\\t%w0, %w1, %w2, %w3"
2806 [(set_attr "type" "mla")]
2809 (define_insn "*mul<mode>_neg"
2810 [(set (match_operand:GPI 0 "register_operand" "=r")
2811 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2812 (match_operand:GPI 2 "register_operand" "r")))]
2815 "mneg\\t%<w>0, %<w>1, %<w>2"
2816 [(set_attr "type" "mul")]
2819 ;; zero_extend version of above
2820 (define_insn "*mulsi_neg_uxtw"
2821 [(set (match_operand:DI 0 "register_operand" "=r")
2823 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2824 (match_operand:SI 2 "register_operand" "r"))))]
2827 "mneg\\t%w0, %w1, %w2"
2828 [(set_attr "type" "mul")]
2831 (define_insn "<su_optab>mulsidi3"
2832 [(set (match_operand:DI 0 "register_operand" "=r")
2833 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2834 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2836 "<su>mull\\t%0, %w1, %w2"
2837 [(set_attr "type" "<su>mull")]
2840 (define_insn "<su_optab>maddsidi4"
2841 [(set (match_operand:DI 0 "register_operand" "=r")
2843 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2844 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2845 (match_operand:DI 3 "register_operand" "r")))]
2847 "<su>maddl\\t%0, %w1, %w2, %3"
2848 [(set_attr "type" "<su>mlal")]
2851 (define_insn "<su_optab>msubsidi4"
2852 [(set (match_operand:DI 0 "register_operand" "=r")
2854 (match_operand:DI 3 "register_operand" "r")
2855 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2857 (match_operand:SI 2 "register_operand" "r")))))]
2859 "<su>msubl\\t%0, %w1, %w2, %3"
2860 [(set_attr "type" "<su>mlal")]
2863 (define_insn "*<su_optab>mulsidi_neg"
2864 [(set (match_operand:DI 0 "register_operand" "=r")
2866 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2867 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2869 "<su>mnegl\\t%0, %w1, %w2"
2870 [(set_attr "type" "<su>mull")]
2873 (define_expand "<su_optab>mulditi3"
2874 [(set (match_operand:TI 0 "register_operand")
2875 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2876 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2879 rtx low = gen_reg_rtx (DImode);
2880 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2882 rtx high = gen_reg_rtx (DImode);
2883 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2885 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2886 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2890 ;; The default expansion of multi3 using umuldi3_highpart will perform
2891 ;; the additions in an order that fails to combine into two madd insns.
2892 (define_expand "multi3"
2893 [(set (match_operand:TI 0 "register_operand")
2894 (mult:TI (match_operand:TI 1 "register_operand")
2895 (match_operand:TI 2 "register_operand")))]
2898 rtx l0 = gen_reg_rtx (DImode);
2899 rtx l1 = gen_lowpart (DImode, operands[1]);
2900 rtx l2 = gen_lowpart (DImode, operands[2]);
2901 rtx h0 = gen_reg_rtx (DImode);
2902 rtx h1 = gen_highpart (DImode, operands[1]);
2903 rtx h2 = gen_highpart (DImode, operands[2]);
2905 emit_insn (gen_muldi3 (l0, l1, l2));
2906 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2907 emit_insn (gen_madddi (h0, h1, l2, h0));
2908 emit_insn (gen_madddi (h0, l1, h2, h0));
2910 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2911 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2915 (define_insn "<su>muldi3_highpart"
2916 [(set (match_operand:DI 0 "register_operand" "=r")
2920 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2921 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2924 "<su>mulh\\t%0, %1, %2"
2925 [(set_attr "type" "<su>mull")]
2928 (define_insn "<su_optab>div<mode>3"
2929 [(set (match_operand:GPI 0 "register_operand" "=r")
2930 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2931 (match_operand:GPI 2 "register_operand" "r")))]
2933 "<su>div\\t%<w>0, %<w>1, %<w>2"
2934 [(set_attr "type" "<su>div")]
2937 ;; zero_extend version of above
2938 (define_insn "*<su_optab>divsi3_uxtw"
2939 [(set (match_operand:DI 0 "register_operand" "=r")
2941 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2942 (match_operand:SI 2 "register_operand" "r"))))]
2944 "<su>div\\t%w0, %w1, %w2"
2945 [(set_attr "type" "<su>div")]
2948 ;; -------------------------------------------------------------------
2950 ;; -------------------------------------------------------------------
2952 (define_insn "cmp<mode>"
2953 [(set (reg:CC CC_REGNUM)
2954 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2955 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2961 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2964 (define_insn "fcmp<mode>"
2965 [(set (reg:CCFP CC_REGNUM)
2966 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2967 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2971 fcmp\\t%<s>0, %<s>1"
2972 [(set_attr "type" "fcmp<s>")]
2975 (define_insn "fcmpe<mode>"
2976 [(set (reg:CCFPE CC_REGNUM)
2977 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2978 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2982 fcmpe\\t%<s>0, %<s>1"
2983 [(set_attr "type" "fcmp<s>")]
2986 (define_insn "*cmp_swp_<shift>_reg<mode>"
2987 [(set (reg:CC_SWP CC_REGNUM)
2988 (compare:CC_SWP (ASHIFT:GPI
2989 (match_operand:GPI 0 "register_operand" "r")
2990 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2991 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2993 "cmp\\t%<w>2, %<w>0, <shift> %1"
2994 [(set_attr "type" "alus_shift_imm")]
2997 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2998 [(set (reg:CC_SWP CC_REGNUM)
2999 (compare:CC_SWP (ANY_EXTEND:GPI
3000 (match_operand:ALLX 0 "register_operand" "r"))
3001 (match_operand:GPI 1 "register_operand" "r")))]
3003 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3004 [(set_attr "type" "alus_ext")]
3007 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3008 [(set (reg:CC_SWP CC_REGNUM)
3009 (compare:CC_SWP (ashift:GPI
3011 (match_operand:ALLX 0 "register_operand" "r"))
3012 (match_operand 1 "aarch64_imm3" "Ui3"))
3013 (match_operand:GPI 2 "register_operand" "r")))]
3015 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3016 [(set_attr "type" "alus_ext")]
3019 ;; -------------------------------------------------------------------
3020 ;; Store-flag and conditional select insns
3021 ;; -------------------------------------------------------------------
3023 (define_expand "cstore<mode>4"
3024 [(set (match_operand:SI 0 "register_operand" "")
3025 (match_operator:SI 1 "aarch64_comparison_operator"
3026 [(match_operand:GPI 2 "register_operand" "")
3027 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3030 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3032 operands[3] = const0_rtx;
3036 (define_expand "cstorecc4"
3037 [(set (match_operand:SI 0 "register_operand")
3038 (match_operator 1 "aarch64_comparison_operator_mode"
3039 [(match_operand 2 "cc_register")
3040 (match_operand 3 "const0_operand")]))]
3043 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3048 (define_expand "cstore<mode>4"
3049 [(set (match_operand:SI 0 "register_operand" "")
3050 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3051 [(match_operand:GPF 2 "register_operand" "")
3052 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3055 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3057 operands[3] = const0_rtx;
3061 (define_insn "aarch64_cstore<mode>"
3062 [(set (match_operand:ALLI 0 "register_operand" "=r")
3063 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3064 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3067 [(set_attr "type" "csel")]
3070 ;; For a 24-bit immediate CST we can optimize the compare for equality
3071 ;; and branch sequence from:
3073 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3076 ;; into the shorter:
3077 ;; sub x0, x1, #(CST & 0xfff000)
3078 ;; subs x0, x0, #(CST & 0x000fff)
3079 ;; cset x2, <ne, eq>.
3080 (define_insn_and_split "*compare_cstore<mode>_insn"
3081 [(set (match_operand:GPI 0 "register_operand" "=r")
3082 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3083 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3084 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3085 && !aarch64_plus_operand (operands[2], <MODE>mode)
3086 && !reload_completed"
3091 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3092 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3093 rtx tmp = gen_reg_rtx (<MODE>mode);
3094 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3095 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3096 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3097 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3098 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3101 [(set_attr "type" "csel")]
3104 ;; zero_extend version of the above
3105 (define_insn "*cstoresi_insn_uxtw"
3106 [(set (match_operand:DI 0 "register_operand" "=r")
3108 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3109 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3112 [(set_attr "type" "csel")]
3115 (define_insn "cstore<mode>_neg"
3116 [(set (match_operand:ALLI 0 "register_operand" "=r")
3117 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3118 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3120 "csetm\\t%<w>0, %m1"
3121 [(set_attr "type" "csel")]
3124 ;; zero_extend version of the above
3125 (define_insn "*cstoresi_neg_uxtw"
3126 [(set (match_operand:DI 0 "register_operand" "=r")
3128 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3129 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3132 [(set_attr "type" "csel")]
3135 (define_expand "cmov<mode>6"
3136 [(set (match_operand:GPI 0 "register_operand" "")
3138 (match_operator 1 "aarch64_comparison_operator"
3139 [(match_operand:GPI 2 "register_operand" "")
3140 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3141 (match_operand:GPI 4 "register_operand" "")
3142 (match_operand:GPI 5 "register_operand" "")))]
3145 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3147 operands[3] = const0_rtx;
3151 (define_expand "cmov<mode>6"
3152 [(set (match_operand:GPF 0 "register_operand" "")
3154 (match_operator 1 "aarch64_comparison_operator"
3155 [(match_operand:GPF 2 "register_operand" "")
3156 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3157 (match_operand:GPF 4 "register_operand" "")
3158 (match_operand:GPF 5 "register_operand" "")))]
3161 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3163 operands[3] = const0_rtx;
3167 (define_insn "*cmov<mode>_insn"
3168 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3170 (match_operator 1 "aarch64_comparison_operator"
3171 [(match_operand 2 "cc_register" "") (const_int 0)])
3172 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3173 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3174 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3175 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3176 ;; Final two alternatives should be unreachable, but included for completeness
3178 csel\\t%<w>0, %<w>3, %<w>4, %m1
3179 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3180 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3181 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3182 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3185 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3188 ;; zero_extend version of above
3189 (define_insn "*cmovsi_insn_uxtw"
3190 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3193 (match_operator 1 "aarch64_comparison_operator"
3194 [(match_operand 2 "cc_register" "") (const_int 0)])
3195 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3196 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3197 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3198 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3199 ;; Final two alternatives should be unreachable, but included for completeness
3201 csel\\t%w0, %w3, %w4, %m1
3202 csinv\\t%w0, %w3, wzr, %m1
3203 csinv\\t%w0, %w4, wzr, %M1
3204 csinc\\t%w0, %w3, wzr, %m1
3205 csinc\\t%w0, %w4, wzr, %M1
3208 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3211 (define_insn "*cmovdi_insn_uxtw"
3212 [(set (match_operand:DI 0 "register_operand" "=r")
3214 (match_operator 1 "aarch64_comparison_operator"
3215 [(match_operand 2 "cc_register" "") (const_int 0)])
3216 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3217 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3219 "csel\\t%w0, %w3, %w4, %m1"
3220 [(set_attr "type" "csel")]
3223 (define_insn "*cmov<mode>_insn"
3224 [(set (match_operand:GPF 0 "register_operand" "=w")
3226 (match_operator 1 "aarch64_comparison_operator"
3227 [(match_operand 2 "cc_register" "") (const_int 0)])
3228 (match_operand:GPF 3 "register_operand" "w")
3229 (match_operand:GPF 4 "register_operand" "w")))]
3231 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3232 [(set_attr "type" "fcsel")]
3235 (define_expand "mov<mode>cc"
3236 [(set (match_operand:ALLI 0 "register_operand" "")
3237 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3238 (match_operand:ALLI 2 "register_operand" "")
3239 (match_operand:ALLI 3 "register_operand" "")))]
3243 enum rtx_code code = GET_CODE (operands[1]);
3245 if (code == UNEQ || code == LTGT)
3248 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3249 XEXP (operands[1], 1));
3250 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3254 (define_expand "mov<GPF:mode><GPI:mode>cc"
3255 [(set (match_operand:GPI 0 "register_operand" "")
3256 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3257 (match_operand:GPF 2 "register_operand" "")
3258 (match_operand:GPF 3 "register_operand" "")))]
3262 enum rtx_code code = GET_CODE (operands[1]);
3264 if (code == UNEQ || code == LTGT)
3267 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3268 XEXP (operands[1], 1));
3269 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3273 (define_expand "mov<mode>cc"
3274 [(set (match_operand:GPF 0 "register_operand" "")
3275 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3276 (match_operand:GPF 2 "register_operand" "")
3277 (match_operand:GPF 3 "register_operand" "")))]
3281 enum rtx_code code = GET_CODE (operands[1]);
3283 if (code == UNEQ || code == LTGT)
3286 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3287 XEXP (operands[1], 1));
3288 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3292 (define_expand "<neg_not_op><mode>cc"
3293 [(set (match_operand:GPI 0 "register_operand" "")
3294 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3295 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3296 (match_operand:GPI 3 "register_operand" "")))]
3300 enum rtx_code code = GET_CODE (operands[1]);
3302 if (code == UNEQ || code == LTGT)
3305 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3306 XEXP (operands[1], 1));
3307 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3311 ;; CRC32 instructions.
3312 (define_insn "aarch64_<crc_variant>"
3313 [(set (match_operand:SI 0 "register_operand" "=r")
3314 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3315 (match_operand:<crc_mode> 2 "register_operand" "r")]
3319 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3320 return "<crc_variant>\\t%w0, %w1, %x2";
3322 return "<crc_variant>\\t%w0, %w1, %w2";
3324 [(set_attr "type" "crc")]
3327 (define_insn "*csinc2<mode>_insn"
3328 [(set (match_operand:GPI 0 "register_operand" "=r")
3329 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3330 (match_operand:GPI 1 "register_operand" "r")))]
3332 "cinc\\t%<w>0, %<w>1, %m2"
3333 [(set_attr "type" "csel")]
3336 (define_insn "csinc3<mode>_insn"
3337 [(set (match_operand:GPI 0 "register_operand" "=r")
3339 (match_operand 1 "aarch64_comparison_operation" "")
3340 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3342 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3344 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3345 [(set_attr "type" "csel")]
3348 (define_insn "*csinv3<mode>_insn"
3349 [(set (match_operand:GPI 0 "register_operand" "=r")
3351 (match_operand 1 "aarch64_comparison_operation" "")
3352 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3353 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3355 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3356 [(set_attr "type" "csel")]
3359 (define_insn "csneg3_uxtw_insn"
3360 [(set (match_operand:DI 0 "register_operand" "=r")
3363 (match_operand 1 "aarch64_comparison_operation" "")
3364 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3365 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3367 "csneg\\t%w0, %w3, %w2, %M1"
3368 [(set_attr "type" "csel")]
3371 (define_insn "csneg3<mode>_insn"
3372 [(set (match_operand:GPI 0 "register_operand" "=r")
3374 (match_operand 1 "aarch64_comparison_operation" "")
3375 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3376 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3378 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3379 [(set_attr "type" "csel")]
3382 ;; -------------------------------------------------------------------
3383 ;; Logical operations
3384 ;; -------------------------------------------------------------------
3387 (define_insn_and_split "*aarch64_and<mode>_imm2"
3388 [(set (match_operand:GPI 0 "register_operand" "=rk")
3389 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3390 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3396 HOST_WIDE_INT val = INTVAL (operands[2]);
3397 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3398 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3400 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3401 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3406 (define_insn "<optab><mode>3"
3407 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3408 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3409 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3412 <logical>\\t%<w>0, %<w>1, %<w>2
3413 <logical>\\t%<w>0, %<w>1, %2
3414 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3415 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3416 (set_attr "simd" "*,*,yes")]
3419 ;; zero_extend version of above
3420 (define_insn "*<optab>si3_uxtw"
3421 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3423 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3424 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3427 <logical>\\t%w0, %w1, %w2
3428 <logical>\\t%w0, %w1, %2"
3429 [(set_attr "type" "logic_reg,logic_imm")]
3432 (define_insn "*and<mode>3_compare0"
3433 [(set (reg:CC_NZ CC_REGNUM)
3435 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3436 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3438 (set (match_operand:GPI 0 "register_operand" "=r,r")
3439 (and:GPI (match_dup 1) (match_dup 2)))]
3442 ands\\t%<w>0, %<w>1, %<w>2
3443 ands\\t%<w>0, %<w>1, %2"
3444 [(set_attr "type" "logics_reg,logics_imm")]
3447 ;; zero_extend version of above
3448 (define_insn "*andsi3_compare0_uxtw"
3449 [(set (reg:CC_NZ CC_REGNUM)
3451 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3452 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3454 (set (match_operand:DI 0 "register_operand" "=r,r")
3455 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3458 ands\\t%w0, %w1, %w2
3459 ands\\t%w0, %w1, %2"
3460 [(set_attr "type" "logics_reg,logics_imm")]
3463 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3464 [(set (reg:CC_NZ CC_REGNUM)
3467 (match_operand:GPI 1 "register_operand" "r")
3468 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3469 (match_operand:GPI 3 "register_operand" "r"))
3471 (set (match_operand:GPI 0 "register_operand" "=r")
3472 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3474 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3475 [(set_attr "type" "logics_shift_imm")]
3478 ;; zero_extend version of above
3479 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3480 [(set (reg:CC_NZ CC_REGNUM)
3483 (match_operand:SI 1 "register_operand" "r")
3484 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3485 (match_operand:SI 3 "register_operand" "r"))
3487 (set (match_operand:DI 0 "register_operand" "=r")
3488 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3491 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3492 [(set_attr "type" "logics_shift_imm")]
3495 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3496 [(set (match_operand:GPI 0 "register_operand" "=r")
3497 (LOGICAL:GPI (SHIFT:GPI
3498 (match_operand:GPI 1 "register_operand" "r")
3499 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3500 (match_operand:GPI 3 "register_operand" "r")))]
3502 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3503 [(set_attr "type" "logic_shift_imm")]
3506 (define_insn "*<optab>_rol<mode>3"
3507 [(set (match_operand:GPI 0 "register_operand" "=r")
3508 (LOGICAL:GPI (rotate:GPI
3509 (match_operand:GPI 1 "register_operand" "r")
3510 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3511 (match_operand:GPI 3 "register_operand" "r")))]
3513 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3514 [(set_attr "type" "logic_shift_imm")]
3517 ;; zero_extend versions of above
3518 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3519 [(set (match_operand:DI 0 "register_operand" "=r")
3521 (LOGICAL:SI (SHIFT:SI
3522 (match_operand:SI 1 "register_operand" "r")
3523 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3524 (match_operand:SI 3 "register_operand" "r"))))]
3526 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3527 [(set_attr "type" "logic_shift_imm")]
3530 (define_insn "*<optab>_rolsi3_uxtw"
3531 [(set (match_operand:DI 0 "register_operand" "=r")
3533 (LOGICAL:SI (rotate:SI
3534 (match_operand:SI 1 "register_operand" "r")
3535 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3536 (match_operand:SI 3 "register_operand" "r"))))]
3538 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3539 [(set_attr "type" "logic_shift_imm")]
3542 (define_insn "one_cmpl<mode>2"
3543 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3544 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3549 [(set_attr "type" "logic_reg,neon_logic")
3550 (set_attr "simd" "*,yes")]
3553 (define_insn "*one_cmpl_<optab><mode>2"
3554 [(set (match_operand:GPI 0 "register_operand" "=r")
3555 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3556 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3558 "mvn\\t%<w>0, %<w>1, <shift> %2"
3559 [(set_attr "type" "logic_shift_imm")]
3562 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3564 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3565 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3566 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3567 (match_operand:GPI 2 "register_operand" "r,w")))]
3570 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3571 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3572 [(set_attr "type" "logic_reg,neon_logic")
3573 (set_attr "simd" "*,yes")]
3576 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3577 [(set (match_operand:DI 0 "register_operand" "=r")
3579 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3580 (match_operand:SI 2 "register_operand" "r"))))]
3582 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3583 [(set_attr "type" "logic_reg")]
3586 (define_insn "*xor_one_cmplsidi3_ze"
3587 [(set (match_operand:DI 0 "register_operand" "=r")
3589 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3590 (match_operand:SI 2 "register_operand" "r")))))]
3592 "eon\\t%w0, %w1, %w2"
3593 [(set_attr "type" "logic_reg")]
3596 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3597 ;; eon does not operate on SIMD registers so the vector variant must be split.
3598 (define_insn_and_split "*xor_one_cmpl<mode>3"
3599 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3600 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3601 (match_operand:GPI 2 "register_operand" "r,w"))))]
3604 eon\\t%<w>0, %<w>1, %<w>2
3606 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3607 [(set (match_operand:GPI 0 "register_operand" "=w")
3608 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3609 (match_operand:GPI 2 "register_operand" "w")))
3610 (set (match_dup 0) (not:GPI (match_dup 0)))]
3612 [(set_attr "type" "logic_reg,multiple")
3613 (set_attr "simd" "*,yes")]
3616 (define_insn "*and_one_cmpl<mode>3_compare0"
3617 [(set (reg:CC_NZ CC_REGNUM)
3620 (match_operand:GPI 1 "register_operand" "r"))
3621 (match_operand:GPI 2 "register_operand" "r"))
3623 (set (match_operand:GPI 0 "register_operand" "=r")
3624 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3626 "bics\\t%<w>0, %<w>2, %<w>1"
3627 [(set_attr "type" "logics_reg")]
3630 ;; zero_extend version of above
3631 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3632 [(set (reg:CC_NZ CC_REGNUM)
3635 (match_operand:SI 1 "register_operand" "r"))
3636 (match_operand:SI 2 "register_operand" "r"))
3638 (set (match_operand:DI 0 "register_operand" "=r")
3639 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3641 "bics\\t%w0, %w2, %w1"
3642 [(set_attr "type" "logics_reg")]
3645 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3646 [(set (reg:CC_NZ CC_REGNUM)
3649 (match_operand:GPI 0 "register_operand" "r"))
3650 (match_operand:GPI 1 "register_operand" "r"))
3653 "bics\\t<w>zr, %<w>1, %<w>0"
3654 [(set_attr "type" "logics_reg")]
3657 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3658 [(set (match_operand:GPI 0 "register_operand" "=r")
3659 (LOGICAL:GPI (not:GPI
3661 (match_operand:GPI 1 "register_operand" "r")
3662 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3663 (match_operand:GPI 3 "register_operand" "r")))]
3665 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3666 [(set_attr "type" "logic_shift_imm")]
3669 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3670 [(set (match_operand:GPI 0 "register_operand" "=r")
3673 (match_operand:GPI 1 "register_operand" "r")
3674 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3675 (match_operand:GPI 3 "register_operand" "r"))))]
3677 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3678 [(set_attr "type" "logic_shift_imm")]
3681 ;; Zero-extend version of the above.
3682 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3683 [(set (match_operand:DI 0 "register_operand" "=r")
3687 (match_operand:SI 1 "register_operand" "r")
3688 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3689 (match_operand:SI 3 "register_operand" "r")))))]
3691 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3692 [(set_attr "type" "logic_shift_imm")]
3695 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3696 [(set (reg:CC_NZ CC_REGNUM)
3700 (match_operand:GPI 1 "register_operand" "r")
3701 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3702 (match_operand:GPI 3 "register_operand" "r"))
3704 (set (match_operand:GPI 0 "register_operand" "=r")
3707 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3709 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3710 [(set_attr "type" "logics_shift_imm")]
3713 ;; zero_extend version of above
3714 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3715 [(set (reg:CC_NZ CC_REGNUM)
3719 (match_operand:SI 1 "register_operand" "r")
3720 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3721 (match_operand:SI 3 "register_operand" "r"))
3723 (set (match_operand:DI 0 "register_operand" "=r")
3724 (zero_extend:DI (and:SI
3726 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3728 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3729 [(set_attr "type" "logics_shift_imm")]
3732 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3733 [(set (reg:CC_NZ CC_REGNUM)
3737 (match_operand:GPI 0 "register_operand" "r")
3738 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3739 (match_operand:GPI 2 "register_operand" "r"))
3742 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3743 [(set_attr "type" "logics_shift_imm")]
3746 (define_insn "clz<mode>2"
3747 [(set (match_operand:GPI 0 "register_operand" "=r")
3748 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3750 "clz\\t%<w>0, %<w>1"
3751 [(set_attr "type" "clz")]
3754 (define_expand "ffs<mode>2"
3755 [(match_operand:GPI 0 "register_operand")
3756 (match_operand:GPI 1 "register_operand")]
3759 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3760 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3762 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3763 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3764 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3769 (define_insn "clrsb<mode>2"
3770 [(set (match_operand:GPI 0 "register_operand" "=r")
3771 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3773 "cls\\t%<w>0, %<w>1"
3774 [(set_attr "type" "clz")]
3777 (define_insn "rbit<mode>2"
3778 [(set (match_operand:GPI 0 "register_operand" "=r")
3779 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3781 "rbit\\t%<w>0, %<w>1"
3782 [(set_attr "type" "rbit")]
3785 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3786 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3787 ;; expression and split after reload to enable scheduling them apart if
3790 (define_insn_and_split "ctz<mode>2"
3791 [(set (match_operand:GPI 0 "register_operand" "=r")
3792 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3798 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3799 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3803 (define_insn "*and<mode>_compare0"
3804 [(set (reg:CC_NZ CC_REGNUM)
3806 (match_operand:SHORT 0 "register_operand" "r")
3809 "tst\\t%<w>0, <short_mask>"
3810 [(set_attr "type" "alus_imm")]
3813 (define_insn "*ands<mode>_compare0"
3814 [(set (reg:CC_NZ CC_REGNUM)
3816 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3818 (set (match_operand:GPI 0 "register_operand" "=r")
3819 (zero_extend:GPI (match_dup 1)))]
3821 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3822 [(set_attr "type" "alus_imm")]
3825 (define_insn "*and<mode>3nr_compare0"
3826 [(set (reg:CC_NZ CC_REGNUM)
3828 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3829 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3835 [(set_attr "type" "logics_reg,logics_imm")]
3838 (define_insn "*and<mode>3nr_compare0_zextract"
3839 [(set (reg:CC_NZ CC_REGNUM)
3841 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3842 (match_operand:GPI 1 "const_int_operand" "n")
3843 (match_operand:GPI 2 "const_int_operand" "n"))
3845 "INTVAL (operands[1]) > 0
3846 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3847 <= GET_MODE_BITSIZE (<MODE>mode))
3848 && aarch64_bitmask_imm (
3849 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3854 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3855 return "tst\\t%<w>0, %1";
3857 [(set_attr "type" "logics_shift_imm")]
3860 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3861 [(set (reg:CC_NZ CC_REGNUM)
3864 (match_operand:GPI 0 "register_operand" "r")
3865 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3866 (match_operand:GPI 2 "register_operand" "r"))
3869 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3870 [(set_attr "type" "logics_shift_imm")]
3873 ;; -------------------------------------------------------------------
3875 ;; -------------------------------------------------------------------
3877 (define_expand "<optab><mode>3"
3878 [(set (match_operand:GPI 0 "register_operand")
3879 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3880 (match_operand:QI 2 "nonmemory_operand")))]
3883 if (CONST_INT_P (operands[2]))
3885 operands[2] = GEN_INT (INTVAL (operands[2])
3886 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3888 if (operands[2] == const0_rtx)
3890 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3897 (define_expand "ashl<mode>3"
3898 [(set (match_operand:SHORT 0 "register_operand")
3899 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3900 (match_operand:QI 2 "const_int_operand")))]
3903 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3905 if (operands[2] == const0_rtx)
3907 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3913 (define_expand "rotr<mode>3"
3914 [(set (match_operand:GPI 0 "register_operand")
3915 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3916 (match_operand:QI 2 "nonmemory_operand")))]
3919 if (CONST_INT_P (operands[2]))
3921 operands[2] = GEN_INT (INTVAL (operands[2])
3922 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3924 if (operands[2] == const0_rtx)
3926 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3933 (define_expand "rotl<mode>3"
3934 [(set (match_operand:GPI 0 "register_operand")
3935 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3936 (match_operand:QI 2 "nonmemory_operand")))]
3939 /* (SZ - cnt) % SZ == -cnt % SZ */
3940 if (CONST_INT_P (operands[2]))
3942 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3943 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3944 if (operands[2] == const0_rtx)
3946 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3951 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3956 ;; Logical left shift using SISD or Integer instruction
3957 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3958 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3960 (match_operand:GPI 1 "register_operand" "r,r,w,w")
3961 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3964 lsl\t%<w>0, %<w>1, %2
3965 lsl\t%<w>0, %<w>1, %<w>2
3966 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3967 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3968 [(set_attr "simd" "no,no,yes,yes")
3969 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3972 ;; Logical right shift using SISD or Integer instruction
3973 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3974 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3976 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3977 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3980 lsr\t%<w>0, %<w>1, %2
3981 lsr\t%<w>0, %<w>1, %<w>2
3982 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3985 [(set_attr "simd" "no,no,yes,yes,yes")
3986 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3990 [(set (match_operand:DI 0 "aarch64_simd_register")
3992 (match_operand:DI 1 "aarch64_simd_register")
3993 (match_operand:QI 2 "aarch64_simd_register")))]
3994 "TARGET_SIMD && reload_completed"
3996 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3998 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4000 operands[3] = gen_lowpart (QImode, operands[0]);
4005 [(set (match_operand:SI 0 "aarch64_simd_register")
4007 (match_operand:SI 1 "aarch64_simd_register")
4008 (match_operand:QI 2 "aarch64_simd_register")))]
4009 "TARGET_SIMD && reload_completed"
4011 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4013 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4015 operands[3] = gen_lowpart (QImode, operands[0]);
4019 ;; Arithmetic right shift using SISD or Integer instruction
4020 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4021 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4023 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4024 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4027 asr\t%<w>0, %<w>1, %2
4028 asr\t%<w>0, %<w>1, %<w>2
4029 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4032 [(set_attr "simd" "no,no,yes,yes,yes")
4033 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4037 [(set (match_operand:DI 0 "aarch64_simd_register")
4039 (match_operand:DI 1 "aarch64_simd_register")
4040 (match_operand:QI 2 "aarch64_simd_register")))]
4041 "TARGET_SIMD && reload_completed"
4043 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4045 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4047 operands[3] = gen_lowpart (QImode, operands[0]);
4052 [(set (match_operand:SI 0 "aarch64_simd_register")
4054 (match_operand:SI 1 "aarch64_simd_register")
4055 (match_operand:QI 2 "aarch64_simd_register")))]
4056 "TARGET_SIMD && reload_completed"
4058 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4060 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4062 operands[3] = gen_lowpart (QImode, operands[0]);
4066 (define_insn "*aarch64_sisd_ushl"
4067 [(set (match_operand:DI 0 "register_operand" "=w")
4068 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4069 (match_operand:QI 2 "register_operand" "w")]
4072 "ushl\t%d0, %d1, %d2"
4073 [(set_attr "simd" "yes")
4074 (set_attr "type" "neon_shift_reg")]
4077 (define_insn "*aarch64_ushl_2s"
4078 [(set (match_operand:SI 0 "register_operand" "=w")
4079 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4080 (match_operand:QI 2 "register_operand" "w")]
4083 "ushl\t%0.2s, %1.2s, %2.2s"
4084 [(set_attr "simd" "yes")
4085 (set_attr "type" "neon_shift_reg")]
4088 (define_insn "*aarch64_sisd_sshl"
4089 [(set (match_operand:DI 0 "register_operand" "=w")
4090 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4091 (match_operand:QI 2 "register_operand" "w")]
4094 "sshl\t%d0, %d1, %d2"
4095 [(set_attr "simd" "yes")
4096 (set_attr "type" "neon_shift_reg")]
4099 (define_insn "*aarch64_sshl_2s"
4100 [(set (match_operand:SI 0 "register_operand" "=w")
4101 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4102 (match_operand:QI 2 "register_operand" "w")]
4105 "sshl\t%0.2s, %1.2s, %2.2s"
4106 [(set_attr "simd" "yes")
4107 (set_attr "type" "neon_shift_reg")]
4110 (define_insn "*aarch64_sisd_neg_qi"
4111 [(set (match_operand:QI 0 "register_operand" "=w")
4112 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4116 [(set_attr "simd" "yes")
4117 (set_attr "type" "neon_neg")]
4121 (define_insn "*ror<mode>3_insn"
4122 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4124 (match_operand:GPI 1 "register_operand" "r,r")
4125 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4128 ror\\t%<w>0, %<w>1, %2
4129 ror\\t%<w>0, %<w>1, %<w>2"
4130 [(set_attr "type" "rotate_imm,shift_reg")]
4133 ;; zero_extend version of above
4134 (define_insn "*<optab>si3_insn_uxtw"
4135 [(set (match_operand:DI 0 "register_operand" "=r,r")
4136 (zero_extend:DI (SHIFT:SI
4137 (match_operand:SI 1 "register_operand" "r,r")
4138 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4141 <shift>\\t%w0, %w1, %2
4142 <shift>\\t%w0, %w1, %w2"
4143 [(set_attr "type" "bfx,shift_reg")]
4146 (define_insn "*<optab><mode>3_insn"
4147 [(set (match_operand:SHORT 0 "register_operand" "=r")
4148 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4149 (match_operand 2 "const_int_operand" "n")))]
4150 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4152 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4153 return "<bfshift>\t%w0, %w1, %2, %3";
4155 [(set_attr "type" "bfx")]
4158 (define_insn "*extr<mode>5_insn"
4159 [(set (match_operand:GPI 0 "register_operand" "=r")
4160 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4161 (match_operand 3 "const_int_operand" "n"))
4162 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4163 (match_operand 4 "const_int_operand" "n"))))]
4164 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4165 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4166 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4167 [(set_attr "type" "rotate_imm")]
4170 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4171 ;; so we have to match both orderings.
4172 (define_insn "*extr<mode>5_insn_alt"
4173 [(set (match_operand:GPI 0 "register_operand" "=r")
4174 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4175 (match_operand 4 "const_int_operand" "n"))
4176 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4177 (match_operand 3 "const_int_operand" "n"))))]
4178 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4179 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4180 == GET_MODE_BITSIZE (<MODE>mode))"
4181 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4182 [(set_attr "type" "rotate_imm")]
4185 ;; zero_extend version of the above
4186 (define_insn "*extrsi5_insn_uxtw"
4187 [(set (match_operand:DI 0 "register_operand" "=r")
4189 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4190 (match_operand 3 "const_int_operand" "n"))
4191 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4192 (match_operand 4 "const_int_operand" "n")))))]
4193 "UINTVAL (operands[3]) < 32 &&
4194 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4195 "extr\\t%w0, %w1, %w2, %4"
4196 [(set_attr "type" "rotate_imm")]
4199 (define_insn "*extrsi5_insn_uxtw_alt"
4200 [(set (match_operand:DI 0 "register_operand" "=r")
4202 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4203 (match_operand 4 "const_int_operand" "n"))
4204 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4205 (match_operand 3 "const_int_operand" "n")))))]
4206 "UINTVAL (operands[3]) < 32 &&
4207 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4208 "extr\\t%w0, %w1, %w2, %4"
4209 [(set_attr "type" "rotate_imm")]
4212 (define_insn "*ror<mode>3_insn"
4213 [(set (match_operand:GPI 0 "register_operand" "=r")
4214 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4215 (match_operand 2 "const_int_operand" "n")))]
4216 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4218 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4219 return "ror\\t%<w>0, %<w>1, %3";
4221 [(set_attr "type" "rotate_imm")]
4224 ;; zero_extend version of the above
4225 (define_insn "*rorsi3_insn_uxtw"
4226 [(set (match_operand:DI 0 "register_operand" "=r")
4228 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4229 (match_operand 2 "const_int_operand" "n"))))]
4230 "UINTVAL (operands[2]) < 32"
4232 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4233 return "ror\\t%w0, %w1, %3";
4235 [(set_attr "type" "rotate_imm")]
4238 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4239 [(set (match_operand:GPI 0 "register_operand" "=r")
4241 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4242 (match_operand 2 "const_int_operand" "n"))))]
4243 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4245 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4246 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4248 [(set_attr "type" "bfx")]
4251 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4252 [(set (match_operand:GPI 0 "register_operand" "=r")
4254 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4255 (match_operand 2 "const_int_operand" "n"))))]
4256 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4258 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4259 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4261 [(set_attr "type" "bfx")]
4264 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4265 [(set (match_operand:GPI 0 "register_operand" "=r")
4267 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4268 (match_operand 2 "const_int_operand" "n"))))]
4269 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4271 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4272 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4274 [(set_attr "type" "bfx")]
4277 ;; -------------------------------------------------------------------
4279 ;; -------------------------------------------------------------------
4281 (define_expand "<optab>"
4282 [(set (match_operand:DI 0 "register_operand" "=r")
4283 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4285 "aarch64_simd_shift_imm_offset_di")
4286 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4289 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4290 1, GET_MODE_BITSIZE (DImode) - 1))
4296 (define_insn "*<optab><mode>"
4297 [(set (match_operand:GPI 0 "register_operand" "=r")
4298 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4300 "aarch64_simd_shift_imm_offset_<mode>" "n")
4302 "aarch64_simd_shift_imm_<mode>" "n")))]
4303 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4304 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4305 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4306 [(set_attr "type" "bfx")]
4309 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4310 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4312 [(set (match_operand:DI 0 "register_operand")
4313 (zero_extract:DI (match_operand:DI 1 "register_operand")
4315 "aarch64_simd_shift_imm_offset_di")
4317 "aarch64_simd_shift_imm_di")))]
4318 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4319 GET_MODE_BITSIZE (DImode) - 1)
4320 && (INTVAL (operands[2]) + INTVAL (operands[3]))
4321 == GET_MODE_BITSIZE (SImode)"
4323 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4325 operands[4] = gen_lowpart (SImode, operands[1]);
4329 ;; Bitfield Insert (insv)
4330 (define_expand "insv<mode>"
4331 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4332 (match_operand 1 "const_int_operand")
4333 (match_operand 2 "const_int_operand"))
4334 (match_operand:GPI 3 "general_operand"))]
4337 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4338 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4339 rtx value = operands[3];
4341 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4344 if (CONST_INT_P (value))
4346 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4348 /* Prefer AND/OR for inserting all zeros or all ones. */
4349 if ((UINTVAL (value) & mask) == 0
4350 || (UINTVAL (value) & mask) == mask)
4353 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4354 if (width == 16 && (pos % 16) == 0)
4357 operands[3] = force_reg (<MODE>mode, value);
4360 (define_insn "*insv_reg<mode>"
4361 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4362 (match_operand 1 "const_int_operand" "n")
4363 (match_operand 2 "const_int_operand" "n"))
4364 (match_operand:GPI 3 "register_operand" "r"))]
4365 "!(UINTVAL (operands[1]) == 0
4366 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4367 > GET_MODE_BITSIZE (<MODE>mode)))"
4368 "bfi\\t%<w>0, %<w>3, %2, %1"
4369 [(set_attr "type" "bfm")]
4372 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4373 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4374 (match_operand 1 "const_int_operand" "n")
4375 (match_operand 2 "const_int_operand" "n"))
4376 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4377 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4378 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4379 [(set_attr "type" "bfm")]
4382 (define_insn "*extr_insv_lower_reg<mode>"
4383 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4384 (match_operand 1 "const_int_operand" "n")
4386 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4388 (match_operand 3 "const_int_operand" "n")))]
4389 "!(UINTVAL (operands[1]) == 0
4390 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4391 > GET_MODE_BITSIZE (<MODE>mode)))"
4392 "bfxil\\t%<w>0, %<w>2, %3, %1"
4393 [(set_attr "type" "bfm")]
4396 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4397 [(set (match_operand:GPI 0 "register_operand" "=r")
4398 (ashift:GPI (ANY_EXTEND:GPI
4399 (match_operand:ALLX 1 "register_operand" "r"))
4400 (match_operand 2 "const_int_operand" "n")))]
4401 "UINTVAL (operands[2]) < <GPI:sizen>"
4403 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4404 ? GEN_INT (<ALLX:sizen>)
4405 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4406 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4408 [(set_attr "type" "bfx")]
4411 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4413 (define_insn "*andim_ashift<mode>_bfiz"
4414 [(set (match_operand:GPI 0 "register_operand" "=r")
4415 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4416 (match_operand 2 "const_int_operand" "n"))
4417 (match_operand 3 "const_int_operand" "n")))]
4418 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4419 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4420 [(set_attr "type" "bfx")]
4423 ;; When the bit position and width of the equivalent extraction add up to 32
4424 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4425 ;; zero-extension of the X-reg.
4427 [(set (match_operand:DI 0 "register_operand")
4428 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4429 (match_operand 2 "const_int_operand"))
4430 (match_operand 3 "const_int_operand")))]
4431 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4432 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4433 == GET_MODE_BITSIZE (SImode)"
4435 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4437 operands[4] = gen_lowpart (SImode, operands[1]);
4441 (define_insn "bswap<mode>2"
4442 [(set (match_operand:GPI 0 "register_operand" "=r")
4443 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4445 "rev\\t%<w>0, %<w>1"
4446 [(set_attr "type" "rev")]
4449 (define_insn "bswaphi2"
4450 [(set (match_operand:HI 0 "register_operand" "=r")
4451 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4454 [(set_attr "type" "rev")]
4457 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4458 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4459 ;; each valid permutation.
4461 (define_insn "rev16<mode>2"
4462 [(set (match_operand:GPI 0 "register_operand" "=r")
4463 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4465 (match_operand:GPI 3 "const_int_operand" "n"))
4466 (and:GPI (lshiftrt:GPI (match_dup 1)
4468 (match_operand:GPI 2 "const_int_operand" "n"))))]
4469 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4470 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4471 "rev16\\t%<w>0, %<w>1"
4472 [(set_attr "type" "rev")]
4475 (define_insn "rev16<mode>2_alt"
4476 [(set (match_operand:GPI 0 "register_operand" "=r")
4477 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4479 (match_operand:GPI 2 "const_int_operand" "n"))
4480 (and:GPI (ashift:GPI (match_dup 1)
4482 (match_operand:GPI 3 "const_int_operand" "n"))))]
4483 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4484 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4485 "rev16\\t%<w>0, %<w>1"
4486 [(set_attr "type" "rev")]
4489 ;; zero_extend version of above
4490 (define_insn "*bswapsi2_uxtw"
4491 [(set (match_operand:DI 0 "register_operand" "=r")
4492 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4495 [(set_attr "type" "rev")]
4498 ;; -------------------------------------------------------------------
4499 ;; Floating-point intrinsics
4500 ;; -------------------------------------------------------------------
4502 ;; frint floating-point round to integral standard patterns.
4503 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4505 (define_insn "<frint_pattern><mode>2"
4506 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4507 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4510 "frint<frint_suffix>\\t%<s>0, %<s>1"
4511 [(set_attr "type" "f_rint<stype>")]
4514 ;; frcvt floating-point round to integer and convert standard patterns.
4515 ;; Expands to lbtrunc, lceil, lfloor, lround.
4516 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4517 [(set (match_operand:GPI 0 "register_operand" "=r")
4519 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4522 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4523 [(set_attr "type" "f_cvtf2i")]
4526 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4527 [(set (match_operand:GPI 0 "register_operand" "=r")
4530 (match_operand:GPF 1 "register_operand" "w")
4531 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4533 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4534 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4536 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4538 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4539 output_asm_insn (buf, operands);
4542 [(set_attr "type" "f_cvtf2i")]
4547 (define_insn "fma<mode>4"
4548 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4549 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4550 (match_operand:GPF_F16 2 "register_operand" "w")
4551 (match_operand:GPF_F16 3 "register_operand" "w")))]
4553 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4554 [(set_attr "type" "fmac<stype>")]
4557 (define_insn "fnma<mode>4"
4558 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4560 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4561 (match_operand:GPF_F16 2 "register_operand" "w")
4562 (match_operand:GPF_F16 3 "register_operand" "w")))]
4564 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4565 [(set_attr "type" "fmac<stype>")]
4568 (define_insn "fms<mode>4"
4569 [(set (match_operand:GPF 0 "register_operand" "=w")
4570 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4571 (match_operand:GPF 2 "register_operand" "w")
4572 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4574 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4575 [(set_attr "type" "fmac<s>")]
4578 (define_insn "fnms<mode>4"
4579 [(set (match_operand:GPF 0 "register_operand" "=w")
4580 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4581 (match_operand:GPF 2 "register_operand" "w")
4582 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4584 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4585 [(set_attr "type" "fmac<s>")]
4588 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4589 (define_insn "*fnmadd<mode>4"
4590 [(set (match_operand:GPF 0 "register_operand" "=w")
4591 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4592 (match_operand:GPF 2 "register_operand" "w")
4593 (match_operand:GPF 3 "register_operand" "w"))))]
4594 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4595 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4596 [(set_attr "type" "fmac<s>")]
4599 ;; -------------------------------------------------------------------
4600 ;; Floating-point conversions
4601 ;; -------------------------------------------------------------------
4603 (define_insn "extendsfdf2"
4604 [(set (match_operand:DF 0 "register_operand" "=w")
4605 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4608 [(set_attr "type" "f_cvt")]
4611 (define_insn "extendhfsf2"
4612 [(set (match_operand:SF 0 "register_operand" "=w")
4613 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4616 [(set_attr "type" "f_cvt")]
4619 (define_insn "extendhfdf2"
4620 [(set (match_operand:DF 0 "register_operand" "=w")
4621 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4624 [(set_attr "type" "f_cvt")]
4627 (define_insn "truncdfsf2"
4628 [(set (match_operand:SF 0 "register_operand" "=w")
4629 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4632 [(set_attr "type" "f_cvt")]
4635 (define_insn "truncsfhf2"
4636 [(set (match_operand:HF 0 "register_operand" "=w")
4637 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4640 [(set_attr "type" "f_cvt")]
4643 (define_insn "truncdfhf2"
4644 [(set (match_operand:HF 0 "register_operand" "=w")
4645 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4648 [(set_attr "type" "f_cvt")]
4651 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4652 [(set (match_operand:GPI 0 "register_operand" "=r")
4653 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4655 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4656 [(set_attr "type" "f_cvtf2i")]
4659 (define_insn "<optab><fcvt_target><GPF:mode>2"
4660 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4661 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4664 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4665 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4666 [(set_attr "simd" "yes,no")
4667 (set_attr "fp" "no,yes")
4668 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4671 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4672 [(set (match_operand:GPF 0 "register_operand" "=w")
4673 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4675 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4676 [(set_attr "type" "f_cvti2f")]
4679 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4680 ;; midend will arrange for an SImode conversion to HFmode to first go
4681 ;; through DFmode, then to HFmode. But first it will try converting
4682 ;; to DImode then down, which would match our DImode pattern below and
4683 ;; give very poor code-generation. So, we must provide our own emulation
4684 ;; of the mid-end logic.
4686 (define_insn "aarch64_fp16_<optab><mode>hf2"
4687 [(set (match_operand:HF 0 "register_operand" "=w")
4688 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4690 "<su_optab>cvtf\t%h0, %<w>1"
4691 [(set_attr "type" "f_cvti2f")]
4694 (define_expand "<optab>sihf2"
4695 [(set (match_operand:HF 0 "register_operand")
4696 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4699 if (TARGET_FP_F16INST)
4700 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4703 rtx convert_target = gen_reg_rtx (DFmode);
4704 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4705 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4711 ;; For DImode there is no wide enough floating-point mode that we
4712 ;; can convert through natively (TFmode would work, but requires a library
4713 ;; call). However, we know that any value >= 65504 will be rounded
4714 ;; to infinity on conversion. This is well within the range of SImode, so
4716 ;; Saturate to SImode.
4717 ;; Convert from that to DFmode
4718 ;; Convert from that to HFmode (phew!).
4719 ;; Note that the saturation to SImode requires the SIMD extensions. If
4720 ;; we ever need to provide this pattern where the SIMD extensions are not
4721 ;; available, we would need a different approach.
4723 (define_expand "<optab>dihf2"
4724 [(set (match_operand:HF 0 "register_operand")
4725 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4726 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4728 if (TARGET_FP_F16INST)
4729 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4732 rtx sat_target = gen_reg_rtx (SImode);
4733 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4734 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4741 ;; Convert between fixed-point and floating-point (scalar modes)
4743 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4744 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4745 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4746 (match_operand:SI 2 "immediate_operand" "i, i")]
4750 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4751 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4752 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4753 (set_attr "fp" "yes, *")
4754 (set_attr "simd" "*, yes")]
4757 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4758 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4759 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4760 (match_operand:SI 2 "immediate_operand" "i, i")]
4764 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4765 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4766 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4767 (set_attr "fp" "yes, *")
4768 (set_attr "simd" "*, yes")]
4771 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4772 [(set (match_operand:GPI 0 "register_operand" "=r")
4773 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4774 (match_operand:SI 2 "immediate_operand" "i")]
4777 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4778 [(set_attr "type" "f_cvtf2i")]
4781 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4782 [(set (match_operand:HF 0 "register_operand" "=w")
4783 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4784 (match_operand:SI 2 "immediate_operand" "i")]
4787 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4788 [(set_attr "type" "f_cvti2f")]
4791 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4792 [(set (match_operand:HI 0 "register_operand" "=w")
4793 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4794 (match_operand:SI 2 "immediate_operand" "i")]
4797 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4798 [(set_attr "type" "neon_fp_to_int_s")]
4801 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4802 [(set (match_operand:HF 0 "register_operand" "=w")
4803 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4804 (match_operand:SI 2 "immediate_operand" "i")]
4807 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4808 [(set_attr "type" "neon_int_to_fp_s")]
4811 ;; -------------------------------------------------------------------
4812 ;; Floating-point arithmetic
4813 ;; -------------------------------------------------------------------
4815 (define_insn "add<mode>3"
4816 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4818 (match_operand:GPF_F16 1 "register_operand" "w")
4819 (match_operand:GPF_F16 2 "register_operand" "w")))]
4821 "fadd\\t%<s>0, %<s>1, %<s>2"
4822 [(set_attr "type" "fadd<stype>")]
4825 (define_insn "sub<mode>3"
4826 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4828 (match_operand:GPF_F16 1 "register_operand" "w")
4829 (match_operand:GPF_F16 2 "register_operand" "w")))]
4831 "fsub\\t%<s>0, %<s>1, %<s>2"
4832 [(set_attr "type" "fadd<stype>")]
4835 (define_insn "mul<mode>3"
4836 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4838 (match_operand:GPF_F16 1 "register_operand" "w")
4839 (match_operand:GPF_F16 2 "register_operand" "w")))]
4841 "fmul\\t%<s>0, %<s>1, %<s>2"
4842 [(set_attr "type" "fmul<stype>")]
4845 (define_insn "*fnmul<mode>3"
4846 [(set (match_operand:GPF 0 "register_operand" "=w")
4848 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4849 (match_operand:GPF 2 "register_operand" "w")))]
4850 "TARGET_FLOAT && !flag_rounding_math"
4851 "fnmul\\t%<s>0, %<s>1, %<s>2"
4852 [(set_attr "type" "fmul<s>")]
4855 (define_insn "*fnmul<mode>3"
4856 [(set (match_operand:GPF 0 "register_operand" "=w")
4858 (match_operand:GPF 1 "register_operand" "w")
4859 (match_operand:GPF 2 "register_operand" "w"))))]
4861 "fnmul\\t%<s>0, %<s>1, %<s>2"
4862 [(set_attr "type" "fmul<s>")]
4865 (define_expand "div<mode>3"
4866 [(set (match_operand:GPF_F16 0 "register_operand")
4867 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4868 (match_operand:GPF_F16 2 "register_operand")))]
4871 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4874 operands[1] = force_reg (<MODE>mode, operands[1]);
4877 (define_insn "*div<mode>3"
4878 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4879 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4880 (match_operand:GPF_F16 2 "register_operand" "w")))]
4882 "fdiv\\t%<s>0, %<s>1, %<s>2"
4883 [(set_attr "type" "fdiv<stype>")]
4886 (define_insn "neg<mode>2"
4887 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4888 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4890 "fneg\\t%<s>0, %<s>1"
4891 [(set_attr "type" "ffarith<stype>")]
4894 (define_expand "sqrt<mode>2"
4895 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4896 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4899 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4903 (define_insn "*sqrt<mode>2"
4904 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4905 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4907 "fsqrt\\t%<s>0, %<s>1"
4908 [(set_attr "type" "fsqrt<stype>")]
4911 (define_insn "abs<mode>2"
4912 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4913 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4915 "fabs\\t%<s>0, %<s>1"
4916 [(set_attr "type" "ffarith<stype>")]
4919 ;; Given that smax/smin do not specify the result when either input is NaN,
4920 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4923 (define_insn "smax<mode>3"
4924 [(set (match_operand:GPF 0 "register_operand" "=w")
4925 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4926 (match_operand:GPF 2 "register_operand" "w")))]
4928 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4929 [(set_attr "type" "f_minmax<s>")]
4932 (define_insn "smin<mode>3"
4933 [(set (match_operand:GPF 0 "register_operand" "=w")
4934 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4935 (match_operand:GPF 2 "register_operand" "w")))]
4937 "fminnm\\t%<s>0, %<s>1, %<s>2"
4938 [(set_attr "type" "f_minmax<s>")]
4941 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4942 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4943 ;; which implement the IEEE fmax ()/fmin () functions.
4944 (define_insn "<maxmin_uns><mode>3"
4945 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4946 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4947 (match_operand:GPF_F16 2 "register_operand" "w")]
4950 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4951 [(set_attr "type" "f_minmax<stype>")]
4954 ;; For copysign (x, y), we want to generate:
4956 ;; LDR d2, #(1 << 63)
4957 ;; BSL v2.8b, [y], [x]
4959 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4960 ;; aarch64_simd_bsldf will select the best suited of these instructions
4961 ;; to generate based on register allocation, and knows how to partially
4962 ;; constant fold based on the values of X and Y, so expand through that.
4964 (define_expand "copysigndf3"
4965 [(match_operand:DF 0 "register_operand")
4966 (match_operand:DF 1 "register_operand")
4967 (match_operand:DF 2 "register_operand")]
4968 "TARGET_FLOAT && TARGET_SIMD"
4970 rtx mask = gen_reg_rtx (DImode);
4971 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4972 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4973 operands[2], operands[1]));
4978 ;; As above, but we must first get to a 64-bit value if we wish to use
4979 ;; aarch64_simd_bslv2sf.
4981 (define_expand "copysignsf3"
4982 [(match_operand:SF 0 "register_operand")
4983 (match_operand:SF 1 "register_operand")
4984 (match_operand:SF 2 "register_operand")]
4985 "TARGET_FLOAT && TARGET_SIMD"
4987 rtx mask = gen_reg_rtx (DImode);
4989 /* Juggle modes to get us in to a vector mode for BSL. */
4990 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4991 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4992 rtx tmp = gen_reg_rtx (V2SFmode);
4993 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4994 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4995 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5000 ;; -------------------------------------------------------------------
5002 ;; -------------------------------------------------------------------
5003 ;; Reload Scalar Floating point modes from constant pool.
5004 ;; The AArch64 port doesn't have __int128 constant move support.
5005 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5006 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5007 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5008 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5011 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5012 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5017 ;; Reload Vector modes from constant pool.
5018 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5019 [(set (match_operand:VALL 0 "register_operand" "=w")
5020 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5021 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5024 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5025 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5030 (define_expand "aarch64_reload_mov<mode>"
5031 [(set (match_operand:TX 0 "register_operand" "=w")
5032 (match_operand:TX 1 "register_operand" "w"))
5033 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5037 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5038 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5039 gen_aarch64_movtilow_tilow (op0, op1);
5040 gen_aarch64_movdi_tihigh (operands[2], op1);
5041 gen_aarch64_movtihigh_di (op0, operands[2]);
5046 ;; The following secondary reload helpers patterns are invoked
5047 ;; after or during reload as we don't want these patterns to start
5048 ;; kicking in during the combiner.
5050 (define_insn "aarch64_movdi_<mode>low"
5051 [(set (match_operand:DI 0 "register_operand" "=r")
5052 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5053 (const_int 64) (const_int 0)))]
5054 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5056 [(set_attr "type" "f_mrc")
5057 (set_attr "length" "4")
5060 (define_insn "aarch64_movdi_<mode>high"
5061 [(set (match_operand:DI 0 "register_operand" "=r")
5062 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5063 (const_int 64) (const_int 64)))]
5064 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5065 "fmov\\t%x0, %1.d[1]"
5066 [(set_attr "type" "f_mrc")
5067 (set_attr "length" "4")
5070 (define_insn "aarch64_mov<mode>high_di"
5071 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5072 (const_int 64) (const_int 64))
5073 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5074 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5075 "fmov\\t%0.d[1], %x1"
5076 [(set_attr "type" "f_mcr")
5077 (set_attr "length" "4")
5080 (define_insn "aarch64_mov<mode>low_di"
5081 [(set (match_operand:TX 0 "register_operand" "=w")
5082 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5083 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5085 [(set_attr "type" "f_mcr")
5086 (set_attr "length" "4")
5089 (define_insn "aarch64_movtilow_tilow"
5090 [(set (match_operand:TI 0 "register_operand" "=w")
5092 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5093 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5095 [(set_attr "type" "fmov")
5096 (set_attr "length" "4")
5099 ;; There is a deliberate reason why the parameters of high and lo_sum's
5100 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5101 ;; and lo_sum's to be used with the labels defining the jump tables in
5104 (define_expand "add_losym"
5105 [(set (match_operand 0 "register_operand" "=r")
5106 (lo_sum (match_operand 1 "register_operand" "r")
5107 (match_operand 2 "aarch64_valid_symref" "S")))]
5110 machine_mode mode = GET_MODE (operands[0]);
5112 emit_insn ((mode == DImode
5114 : gen_add_losym_si) (operands[0],
5120 (define_insn "add_losym_<mode>"
5121 [(set (match_operand:P 0 "register_operand" "=r")
5122 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5123 (match_operand 2 "aarch64_valid_symref" "S")))]
5125 "add\\t%<w>0, %<w>1, :lo12:%a2"
5126 [(set_attr "type" "alu_imm")]
5129 (define_insn "ldr_got_small_<mode>"
5130 [(set (match_operand:PTR 0 "register_operand" "=r")
5131 (unspec:PTR [(mem:PTR (lo_sum:PTR
5132 (match_operand:PTR 1 "register_operand" "r")
5133 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5134 UNSPEC_GOTSMALLPIC))]
5136 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5137 [(set_attr "type" "load1")]
5140 (define_insn "ldr_got_small_sidi"
5141 [(set (match_operand:DI 0 "register_operand" "=r")
5143 (unspec:SI [(mem:SI (lo_sum:DI
5144 (match_operand:DI 1 "register_operand" "r")
5145 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5146 UNSPEC_GOTSMALLPIC)))]
5148 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5149 [(set_attr "type" "load1")]
5152 (define_insn "ldr_got_small_28k_<mode>"
5153 [(set (match_operand:PTR 0 "register_operand" "=r")
5154 (unspec:PTR [(mem:PTR (lo_sum:PTR
5155 (match_operand:PTR 1 "register_operand" "r")
5156 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5157 UNSPEC_GOTSMALLPIC28K))]
5159 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5160 [(set_attr "type" "load1")]
5163 (define_insn "ldr_got_small_28k_sidi"
5164 [(set (match_operand:DI 0 "register_operand" "=r")
5166 (unspec:SI [(mem:SI (lo_sum:DI
5167 (match_operand:DI 1 "register_operand" "r")
5168 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5169 UNSPEC_GOTSMALLPIC28K)))]
5171 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5172 [(set_attr "type" "load1")]
5175 (define_insn "ldr_got_tiny"
5176 [(set (match_operand:DI 0 "register_operand" "=r")
5177 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5178 UNSPEC_GOTTINYPIC))]
5181 [(set_attr "type" "load1")]
5184 (define_insn "aarch64_load_tp_hard"
5185 [(set (match_operand:DI 0 "register_operand" "=r")
5186 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5188 "mrs\\t%0, tpidr_el0"
5189 [(set_attr "type" "mrs")]
5192 ;; The TLS ABI specifically requires that the compiler does not schedule
5193 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5194 ;; Therefore we treat the stubs as an atomic sequence.
5195 (define_expand "tlsgd_small_<mode>"
5196 [(parallel [(set (match_operand 0 "register_operand" "")
5197 (call (mem:DI (match_dup 2)) (const_int 1)))
5198 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5199 (clobber (reg:DI LR_REGNUM))])]
5202 operands[2] = aarch64_tls_get_addr ();
5205 (define_insn "*tlsgd_small_<mode>"
5206 [(set (match_operand 0 "register_operand" "")
5207 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5208 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5209 (clobber (reg:DI LR_REGNUM))
5212 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5213 [(set_attr "type" "call")
5214 (set_attr "length" "16")])
5216 (define_insn "tlsie_small_<mode>"
5217 [(set (match_operand:PTR 0 "register_operand" "=r")
5218 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5219 UNSPEC_GOTSMALLTLS))]
5221 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5222 [(set_attr "type" "load1")
5223 (set_attr "length" "8")]
5226 (define_insn "tlsie_small_sidi"
5227 [(set (match_operand:DI 0 "register_operand" "=r")
5229 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5230 UNSPEC_GOTSMALLTLS)))]
5232 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5233 [(set_attr "type" "load1")
5234 (set_attr "length" "8")]
5237 (define_insn "tlsie_tiny_<mode>"
5238 [(set (match_operand:PTR 0 "register_operand" "=&r")
5239 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5240 (match_operand:PTR 2 "register_operand" "r")]
5241 UNSPEC_GOTTINYTLS))]
5243 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5244 [(set_attr "type" "multiple")
5245 (set_attr "length" "8")]
5248 (define_insn "tlsie_tiny_sidi"
5249 [(set (match_operand:DI 0 "register_operand" "=&r")
5251 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5252 (match_operand:DI 2 "register_operand" "r")
5254 UNSPEC_GOTTINYTLS)))]
5256 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5257 [(set_attr "type" "multiple")
5258 (set_attr "length" "8")]
5261 (define_insn "tlsle12_<mode>"
5262 [(set (match_operand:P 0 "register_operand" "=r")
5263 (unspec:P [(match_operand:P 1 "register_operand" "r")
5264 (match_operand 2 "aarch64_tls_le_symref" "S")]
5267 "add\\t%<w>0, %<w>1, #%L2";
5268 [(set_attr "type" "alu_sreg")
5269 (set_attr "length" "4")]
5272 (define_insn "tlsle24_<mode>"
5273 [(set (match_operand:P 0 "register_operand" "=r")
5274 (unspec:P [(match_operand:P 1 "register_operand" "r")
5275 (match_operand 2 "aarch64_tls_le_symref" "S")]
5278 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5279 [(set_attr "type" "multiple")
5280 (set_attr "length" "8")]
5283 (define_insn "tlsle32_<mode>"
5284 [(set (match_operand:P 0 "register_operand" "=r")
5285 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5288 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5289 [(set_attr "type" "multiple")
5290 (set_attr "length" "8")]
5293 (define_insn "tlsle48_<mode>"
5294 [(set (match_operand:P 0 "register_operand" "=r")
5295 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5298 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5299 [(set_attr "type" "multiple")
5300 (set_attr "length" "12")]
5303 (define_insn "tlsdesc_small_<mode>"
5304 [(set (reg:PTR R0_REGNUM)
5305 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5307 (clobber (reg:DI LR_REGNUM))
5308 (clobber (reg:CC CC_REGNUM))
5309 (clobber (match_scratch:DI 1 "=r"))]
5311 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5312 [(set_attr "type" "call")
5313 (set_attr "length" "16")])
5315 (define_insn "stack_tie"
5316 [(set (mem:BLK (scratch))
5317 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5318 (match_operand:DI 1 "register_operand" "rk")]
5322 [(set_attr "length" "0")]
5325 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5326 ;; all of memory. This blocks insns from being moved across this point.
5328 (define_insn "blockage"
5329 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5332 [(set_attr "length" "0")
5333 (set_attr "type" "block")]
5336 (define_insn "probe_stack_range_<PTR:mode>"
5337 [(set (match_operand:PTR 0 "register_operand" "=r")
5338 (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5339 (match_operand:PTR 2 "register_operand" "r")]
5340 UNSPECV_PROBE_STACK_RANGE))]
5343 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5345 [(set_attr "length" "32")]
5348 ;; Named pattern for expanding thread pointer reference.
5349 (define_expand "get_thread_pointerdi"
5350 [(match_operand:DI 0 "register_operand" "=r")]
5353 rtx tmp = aarch64_load_tp (operands[0]);
5354 if (tmp != operands[0])
5355 emit_move_insn (operands[0], tmp);
5359 ;; Named patterns for stack smashing protection.
5360 (define_expand "stack_protect_set"
5361 [(match_operand 0 "memory_operand")
5362 (match_operand 1 "memory_operand")]
5365 machine_mode mode = GET_MODE (operands[0]);
5367 emit_insn ((mode == DImode
5368 ? gen_stack_protect_set_di
5369 : gen_stack_protect_set_si) (operands[0], operands[1]));
5373 (define_insn "stack_protect_set_<mode>"
5374 [(set (match_operand:PTR 0 "memory_operand" "=m")
5375 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5377 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5379 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5380 [(set_attr "length" "12")
5381 (set_attr "type" "multiple")])
5383 (define_expand "stack_protect_test"
5384 [(match_operand 0 "memory_operand")
5385 (match_operand 1 "memory_operand")
5390 machine_mode mode = GET_MODE (operands[0]);
5392 result = gen_reg_rtx(mode);
5394 emit_insn ((mode == DImode
5395 ? gen_stack_protect_test_di
5396 : gen_stack_protect_test_si) (result,
5401 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5402 result, const0_rtx, operands[2]));
5404 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5405 result, const0_rtx, operands[2]));
5409 (define_insn "stack_protect_test_<mode>"
5410 [(set (match_operand:PTR 0 "register_operand" "=r")
5411 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5412 (match_operand:PTR 2 "memory_operand" "m")]
5414 (clobber (match_scratch:PTR 3 "=&r"))]
5416 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5417 [(set_attr "length" "12")
5418 (set_attr "type" "multiple")])
5420 ;; Write Floating-point Control Register.
5421 (define_insn "set_fpcr"
5422 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5425 [(set_attr "type" "mrs")])
5427 ;; Read Floating-point Control Register.
5428 (define_insn "get_fpcr"
5429 [(set (match_operand:SI 0 "register_operand" "=r")
5430 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5433 [(set_attr "type" "mrs")])
5435 ;; Write Floating-point Status Register.
5436 (define_insn "set_fpsr"
5437 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5440 [(set_attr "type" "mrs")])
5442 ;; Read Floating-point Status Register.
5443 (define_insn "get_fpsr"
5444 [(set (match_operand:SI 0 "register_operand" "=r")
5445 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5448 [(set_attr "type" "mrs")])
5451 ;; Define the subtract-one-and-jump insns so loop.c
5452 ;; knows what to generate.
5453 (define_expand "doloop_end"
5454 [(use (match_operand 0 "" "")) ; loop pseudo
5455 (use (match_operand 1 "" ""))] ; label
5456 "optimize > 0 && flag_modulo_sched"
5465 /* Currently SMS relies on the do-loop pattern to recognize loops
5466 where (1) the control part consists of all insns defining and/or
5467 using a certain 'count' register and (2) the loop count can be
5468 adjusted by modifying this register prior to the loop.
5469 ??? The possible introduction of a new block to initialize the
5470 new IV can potentially affect branch optimizations. */
5472 if (GET_MODE (operands[0]) != DImode)
5476 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5478 cmp = XVECEXP (PATTERN (insn), 0, 0);
5479 cc_reg = SET_DEST (cmp);
5480 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5481 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5482 emit_jump_insn (gen_rtx_SET (pc_rtx,
5483 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5489 (include "aarch64-simd.md")
5491 ;; Atomic Operations
5492 (include "atomics.md")
5494 ;; ldp/stp peephole patterns
5495 (include "aarch64-ldpstp.md")