1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2016 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 "eh_return"
596 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
600 [(set_attr "type" "branch")]
605 [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
608 [(set (match_dup 1) (match_dup 0))]
610 operands[1] = aarch64_final_eh_return_addr ();
614 (define_insn "*cb<optab><mode>1"
615 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
617 (label_ref (match_operand 1 "" ""))
621 if (get_attr_length (insn) == 8)
622 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
624 return "<cbz>\\t%<w>0, %l1";
626 [(set_attr "type" "branch")
628 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
629 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
632 (set (attr "far_branch")
633 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
634 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
639 (define_insn "*tb<optab><mode>1"
640 [(set (pc) (if_then_else
641 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
644 "aarch64_simd_shift_imm_<mode>" "n"))
646 (label_ref (match_operand 2 "" ""))
648 (clobber (reg:CC CC_REGNUM))]
651 if (get_attr_length (insn) == 8)
653 if (get_attr_far_branch (insn) == 1)
654 return aarch64_gen_far_branch (operands, 2, "Ltb",
655 "<inv_tb>\\t%<w>0, %1, ");
658 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
659 return "tst\t%<w>0, %1\;<bcond>\t%l2";
663 return "<tbz>\t%<w>0, %1, %l2";
665 [(set_attr "type" "branch")
667 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
668 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
671 (set (attr "far_branch")
672 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
673 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
679 (define_insn "*cb<optab><mode>1"
680 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
682 (label_ref (match_operand 1 "" ""))
684 (clobber (reg:CC CC_REGNUM))]
687 if (get_attr_length (insn) == 8)
689 if (get_attr_far_branch (insn) == 1)
690 return aarch64_gen_far_branch (operands, 1, "Ltb",
691 "<inv_tb>\\t%<w>0, <sizem1>, ");
695 uint64_t val = ((uint64_t) 1)
696 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
697 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
698 output_asm_insn (buf, operands);
699 return "<bcond>\t%l1";
703 return "<tbz>\t%<w>0, <sizem1>, %l1";
705 [(set_attr "type" "branch")
707 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
708 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
711 (set (attr "far_branch")
712 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
713 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
718 ;; -------------------------------------------------------------------
719 ;; Subroutine calls and sibcalls
720 ;; -------------------------------------------------------------------
722 (define_expand "call_internal"
723 [(parallel [(call (match_operand 0 "memory_operand" "")
724 (match_operand 1 "general_operand" ""))
725 (use (match_operand 2 "" ""))
726 (clobber (reg:DI LR_REGNUM))])])
728 (define_expand "call"
729 [(parallel [(call (match_operand 0 "memory_operand" "")
730 (match_operand 1 "general_operand" ""))
731 (use (match_operand 2 "" ""))
732 (clobber (reg:DI LR_REGNUM))])]
738 /* In an untyped call, we can get NULL for operand 2. */
739 if (operands[2] == NULL)
740 operands[2] = const0_rtx;
742 /* Decide if we should generate indirect calls by loading the
743 64-bit address of the callee into a register before performing
744 the branch-and-link. */
745 callee = XEXP (operands[0], 0);
746 if (GET_CODE (callee) == SYMBOL_REF
747 ? (aarch64_is_long_call_p (callee)
748 || aarch64_is_noplt_call_p (callee))
750 XEXP (operands[0], 0) = force_reg (Pmode, callee);
752 pat = gen_call_internal (operands[0], operands[1], operands[2]);
753 aarch64_emit_call_insn (pat);
758 (define_insn "*call_reg"
759 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
760 (match_operand 1 "" ""))
761 (use (match_operand 2 "" ""))
762 (clobber (reg:DI LR_REGNUM))]
765 [(set_attr "type" "call")]
768 (define_insn "*call_symbol"
769 [(call (mem:DI (match_operand:DI 0 "" ""))
770 (match_operand 1 "" ""))
771 (use (match_operand 2 "" ""))
772 (clobber (reg:DI LR_REGNUM))]
773 "GET_CODE (operands[0]) == SYMBOL_REF
774 && !aarch64_is_long_call_p (operands[0])
775 && !aarch64_is_noplt_call_p (operands[0])"
777 [(set_attr "type" "call")]
780 (define_expand "call_value_internal"
781 [(parallel [(set (match_operand 0 "" "")
782 (call (match_operand 1 "memory_operand" "")
783 (match_operand 2 "general_operand" "")))
784 (use (match_operand 3 "" ""))
785 (clobber (reg:DI LR_REGNUM))])])
787 (define_expand "call_value"
788 [(parallel [(set (match_operand 0 "" "")
789 (call (match_operand 1 "memory_operand" "")
790 (match_operand 2 "general_operand" "")))
791 (use (match_operand 3 "" ""))
792 (clobber (reg:DI LR_REGNUM))])]
798 /* In an untyped call, we can get NULL for operand 3. */
799 if (operands[3] == NULL)
800 operands[3] = const0_rtx;
802 /* Decide if we should generate indirect calls by loading the
803 64-bit address of the callee into a register before performing
804 the branch-and-link. */
805 callee = XEXP (operands[1], 0);
806 if (GET_CODE (callee) == SYMBOL_REF
807 ? (aarch64_is_long_call_p (callee)
808 || aarch64_is_noplt_call_p (callee))
810 XEXP (operands[1], 0) = force_reg (Pmode, callee);
812 pat = gen_call_value_internal (operands[0], operands[1], operands[2],
814 aarch64_emit_call_insn (pat);
819 (define_insn "*call_value_reg"
820 [(set (match_operand 0 "" "")
821 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
822 (match_operand 2 "" "")))
823 (use (match_operand 3 "" ""))
824 (clobber (reg:DI LR_REGNUM))]
827 [(set_attr "type" "call")]
831 (define_insn "*call_value_symbol"
832 [(set (match_operand 0 "" "")
833 (call (mem:DI (match_operand:DI 1 "" ""))
834 (match_operand 2 "" "")))
835 (use (match_operand 3 "" ""))
836 (clobber (reg:DI LR_REGNUM))]
837 "GET_CODE (operands[1]) == SYMBOL_REF
838 && !aarch64_is_long_call_p (operands[1])
839 && !aarch64_is_noplt_call_p (operands[1])"
841 [(set_attr "type" "call")]
844 (define_expand "sibcall_internal"
845 [(parallel [(call (match_operand 0 "memory_operand" "")
846 (match_operand 1 "general_operand" ""))
848 (use (match_operand 2 "" ""))])])
850 (define_expand "sibcall"
851 [(parallel [(call (match_operand 0 "memory_operand" "")
852 (match_operand 1 "general_operand" ""))
854 (use (match_operand 2 "" ""))])]
858 rtx callee = XEXP (operands[0], 0);
860 && ((GET_CODE (callee) != SYMBOL_REF)
861 || aarch64_is_noplt_call_p (callee)))
862 XEXP (operands[0], 0) = force_reg (Pmode, callee);
864 if (operands[2] == NULL_RTX)
865 operands[2] = const0_rtx;
867 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
868 aarch64_emit_call_insn (pat);
873 (define_expand "sibcall_value_internal"
874 [(parallel [(set (match_operand 0 "" "")
875 (call (match_operand 1 "memory_operand" "")
876 (match_operand 2 "general_operand" "")))
878 (use (match_operand 3 "" ""))])])
880 (define_expand "sibcall_value"
881 [(parallel [(set (match_operand 0 "" "")
882 (call (match_operand 1 "memory_operand" "")
883 (match_operand 2 "general_operand" "")))
885 (use (match_operand 3 "" ""))])]
889 rtx callee = XEXP (operands[1], 0);
891 && ((GET_CODE (callee) != SYMBOL_REF)
892 || aarch64_is_noplt_call_p (callee)))
893 XEXP (operands[1], 0) = force_reg (Pmode, callee);
895 if (operands[3] == NULL_RTX)
896 operands[3] = const0_rtx;
898 pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
900 aarch64_emit_call_insn (pat);
905 (define_insn "*sibcall_insn"
906 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
907 (match_operand 1 "" ""))
909 (use (match_operand 2 "" ""))]
910 "SIBLING_CALL_P (insn)"
914 [(set_attr "type" "branch, branch")]
917 (define_insn "*sibcall_value_insn"
918 [(set (match_operand 0 "" "")
920 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
921 (match_operand 2 "" "")))
923 (use (match_operand 3 "" ""))]
924 "SIBLING_CALL_P (insn)"
928 [(set_attr "type" "branch, branch")]
931 ;; Call subroutine returning any type.
933 (define_expand "untyped_call"
934 [(parallel [(call (match_operand 0 "")
937 (match_operand 2 "")])]
942 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
944 for (i = 0; i < XVECLEN (operands[2], 0); i++)
946 rtx set = XVECEXP (operands[2], 0, i);
947 emit_move_insn (SET_DEST (set), SET_SRC (set));
950 /* The optimizer does not know that the call sets the function value
951 registers we stored in the result block. We avoid problems by
952 claiming that all hard registers are used and clobbered at this
954 emit_insn (gen_blockage ());
958 ;; -------------------------------------------------------------------
960 ;; -------------------------------------------------------------------
962 (define_expand "mov<mode>"
963 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
964 (match_operand:SHORT 1 "general_operand" ""))]
967 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
968 operands[1] = force_reg (<MODE>mode, operands[1]);
972 (define_insn "*mov<mode>_aarch64"
973 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
974 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
975 "(register_operand (operands[0], <MODE>mode)
976 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
978 switch (which_alternative)
981 return "mov\t%w0, %w1";
983 return "mov\t%w0, %1";
985 return aarch64_output_scalar_simd_mov_immediate (operands[1],
988 return "ldr<size>\t%w0, %1";
990 return "ldr\t%<size>0, %1";
992 return "str<size>\t%w1, %0";
994 return "str\t%<size>1, %0";
996 return "umov\t%w0, %1.<v>[0]";
998 return "dup\t%0.<Vallxd>, %w1";
1000 return "dup\t%<Vetype>0, %1.<v>[0]";
1005 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1006 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1007 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1010 (define_expand "mov<mode>"
1011 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1012 (match_operand:GPI 1 "general_operand" ""))]
1015 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1016 && <MODE>mode == DImode
1017 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1020 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1021 operands[1] = force_reg (<MODE>mode, operands[1]);
1023 /* FIXME: RR we still need to fix up what we are doing with
1024 symbol_refs and other types of constants. */
1025 if (CONSTANT_P (operands[1])
1026 && !CONST_INT_P (operands[1]))
1028 aarch64_expand_mov_immediate (operands[0], operands[1]);
1034 (define_insn_and_split "*movsi_aarch64"
1035 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w")
1036 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1037 "(register_operand (operands[0], SImode)
1038 || aarch64_reg_or_zero (operands[1], SImode))"
1054 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1055 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1058 aarch64_expand_mov_immediate (operands[0], operands[1]);
1061 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1062 adr,adr,f_mcr,f_mrc,fmov")
1063 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1066 (define_insn_and_split "*movdi_aarch64"
1067 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w, r,*w,w")
1068 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1069 "(register_operand (operands[0], DImode)
1070 || aarch64_reg_or_zero (operands[1], DImode))"
1087 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1088 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1091 aarch64_expand_mov_immediate (operands[0], operands[1]);
1094 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1095 adr,adr,f_mcr,f_mrc,fmov,neon_move")
1096 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1097 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1100 (define_insn "insv_imm<mode>"
1101 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1103 (match_operand:GPI 1 "const_int_operand" "n"))
1104 (match_operand:GPI 2 "const_int_operand" "n"))]
1105 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1106 && UINTVAL (operands[1]) % 16 == 0"
1107 "movk\\t%<w>0, %X2, lsl %1"
1108 [(set_attr "type" "mov_imm")]
1111 (define_expand "movti"
1112 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1113 (match_operand:TI 1 "general_operand" ""))]
1116 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1117 operands[1] = force_reg (TImode, operands[1]);
1121 (define_insn "*movti_aarch64"
1122 [(set (match_operand:TI 0
1123 "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
1125 "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
1126 "(register_operand (operands[0], TImode)
1127 || aarch64_reg_or_zero (operands[1], TImode))"
1132 orr\\t%0.16b, %1.16b, %1.16b
1138 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1139 load2,store2,store2,f_loadd,f_stored")
1140 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1141 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1142 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1145 ;; Split a TImode register-register or register-immediate move into
1146 ;; its component DImode pieces, taking care to handle overlapping
1147 ;; source and dest registers.
1149 [(set (match_operand:TI 0 "register_operand" "")
1150 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1151 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1154 aarch64_split_128bit_move (operands[0], operands[1]);
1158 (define_expand "mov<mode>"
1159 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1160 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1165 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1169 if (GET_CODE (operands[0]) == MEM
1170 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1171 && aarch64_float_const_zero_rtx_p (operands[1])))
1172 operands[1] = force_reg (<MODE>mode, operands[1]);
1176 (define_insn "*movhf_aarch64"
1177 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
1178 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
1179 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1180 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1185 mov\\t%0.h[0], %1.h[0]
1191 [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1192 f_loads,f_stores,load1,store1,mov_reg")
1193 (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1196 (define_insn "*movsf_aarch64"
1197 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1198 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1199 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1200 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1212 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1213 f_loads,f_stores,load1,store1,mov_reg")
1214 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1217 (define_insn "*movdf_aarch64"
1218 [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1219 (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1220 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1221 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1233 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1234 f_loadd,f_stored,load1,store1,mov_reg")
1235 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1238 (define_insn "*movtf_aarch64"
1239 [(set (match_operand:TF 0
1240 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1242 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1243 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1244 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1246 orr\\t%0.16b, %1.16b, %1.16b
1257 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1258 f_loadd,f_stored,load2,store2,store2")
1259 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1260 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1264 [(set (match_operand:TF 0 "register_operand" "")
1265 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1266 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1269 aarch64_split_128bit_move (operands[0], operands[1]);
1276 ;; 2 is size of move in bytes
1279 (define_expand "movmemdi"
1280 [(match_operand:BLK 0 "memory_operand")
1281 (match_operand:BLK 1 "memory_operand")
1282 (match_operand:DI 2 "immediate_operand")
1283 (match_operand:DI 3 "immediate_operand")]
1286 if (aarch64_expand_movmem (operands))
1292 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1293 ;; fairly lax checking on the second memory operation.
1294 (define_insn "load_pairsi"
1295 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1296 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1297 (set (match_operand:SI 2 "register_operand" "=r,*w")
1298 (match_operand:SI 3 "memory_operand" "m,m"))]
1299 "rtx_equal_p (XEXP (operands[3], 0),
1300 plus_constant (Pmode,
1301 XEXP (operands[1], 0),
1302 GET_MODE_SIZE (SImode)))"
1306 [(set_attr "type" "load2,neon_load1_2reg")
1307 (set_attr "fp" "*,yes")]
1310 (define_insn "load_pairdi"
1311 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1312 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1313 (set (match_operand:DI 2 "register_operand" "=r,*w")
1314 (match_operand:DI 3 "memory_operand" "m,m"))]
1315 "rtx_equal_p (XEXP (operands[3], 0),
1316 plus_constant (Pmode,
1317 XEXP (operands[1], 0),
1318 GET_MODE_SIZE (DImode)))"
1322 [(set_attr "type" "load2,neon_load1_2reg")
1323 (set_attr "fp" "*,yes")]
1327 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1328 ;; fairly lax checking on the second memory operation.
1329 (define_insn "store_pairsi"
1330 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1331 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1332 (set (match_operand:SI 2 "memory_operand" "=m,m")
1333 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1334 "rtx_equal_p (XEXP (operands[2], 0),
1335 plus_constant (Pmode,
1336 XEXP (operands[0], 0),
1337 GET_MODE_SIZE (SImode)))"
1341 [(set_attr "type" "store2,neon_store1_2reg")
1342 (set_attr "fp" "*,yes")]
1345 (define_insn "store_pairdi"
1346 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1347 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1348 (set (match_operand:DI 2 "memory_operand" "=m,m")
1349 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1350 "rtx_equal_p (XEXP (operands[2], 0),
1351 plus_constant (Pmode,
1352 XEXP (operands[0], 0),
1353 GET_MODE_SIZE (DImode)))"
1357 [(set_attr "type" "store2,neon_store1_2reg")
1358 (set_attr "fp" "*,yes")]
1361 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1362 ;; fairly lax checking on the second memory operation.
1363 (define_insn "load_pairsf"
1364 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1365 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1366 (set (match_operand:SF 2 "register_operand" "=w,*r")
1367 (match_operand:SF 3 "memory_operand" "m,m"))]
1368 "rtx_equal_p (XEXP (operands[3], 0),
1369 plus_constant (Pmode,
1370 XEXP (operands[1], 0),
1371 GET_MODE_SIZE (SFmode)))"
1375 [(set_attr "type" "neon_load1_2reg,load2")
1376 (set_attr "fp" "yes,*")]
1379 (define_insn "load_pairdf"
1380 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1381 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1382 (set (match_operand:DF 2 "register_operand" "=w,*r")
1383 (match_operand:DF 3 "memory_operand" "m,m"))]
1384 "rtx_equal_p (XEXP (operands[3], 0),
1385 plus_constant (Pmode,
1386 XEXP (operands[1], 0),
1387 GET_MODE_SIZE (DFmode)))"
1391 [(set_attr "type" "neon_load1_2reg,load2")
1392 (set_attr "fp" "yes,*")]
1395 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1396 ;; fairly lax checking on the second memory operation.
1397 (define_insn "store_pairsf"
1398 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1399 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1400 (set (match_operand:SF 2 "memory_operand" "=m,m")
1401 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1402 "rtx_equal_p (XEXP (operands[2], 0),
1403 plus_constant (Pmode,
1404 XEXP (operands[0], 0),
1405 GET_MODE_SIZE (SFmode)))"
1409 [(set_attr "type" "neon_store1_2reg,store2")
1410 (set_attr "fp" "yes,*")]
1413 (define_insn "store_pairdf"
1414 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1415 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1416 (set (match_operand:DF 2 "memory_operand" "=m,m")
1417 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1418 "rtx_equal_p (XEXP (operands[2], 0),
1419 plus_constant (Pmode,
1420 XEXP (operands[0], 0),
1421 GET_MODE_SIZE (DFmode)))"
1425 [(set_attr "type" "neon_store1_2reg,store2")
1426 (set_attr "fp" "yes,*")]
1429 ;; Load pair with post-index writeback. This is primarily used in function
1431 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1433 [(set (match_operand:P 0 "register_operand" "=k")
1434 (plus:P (match_operand:P 1 "register_operand" "0")
1435 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1436 (set (match_operand:GPI 2 "register_operand" "=r")
1437 (mem:GPI (match_dup 1)))
1438 (set (match_operand:GPI 3 "register_operand" "=r")
1439 (mem:GPI (plus:P (match_dup 1)
1440 (match_operand:P 5 "const_int_operand" "n"))))])]
1441 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1442 "ldp\\t%<w>2, %<w>3, [%1], %4"
1443 [(set_attr "type" "load2")]
1446 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1448 [(set (match_operand:P 0 "register_operand" "=k")
1449 (plus:P (match_operand:P 1 "register_operand" "0")
1450 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1451 (set (match_operand:GPF 2 "register_operand" "=w")
1452 (mem:GPF (match_dup 1)))
1453 (set (match_operand:GPF 3 "register_operand" "=w")
1454 (mem:GPF (plus:P (match_dup 1)
1455 (match_operand:P 5 "const_int_operand" "n"))))])]
1456 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1457 "ldp\\t%<w>2, %<w>3, [%1], %4"
1458 [(set_attr "type" "neon_load1_2reg")]
1461 ;; Store pair with pre-index writeback. This is primarily used in function
1463 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1465 [(set (match_operand:P 0 "register_operand" "=&k")
1466 (plus:P (match_operand:P 1 "register_operand" "0")
1467 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1468 (set (mem:GPI (plus:P (match_dup 0)
1470 (match_operand:GPI 2 "register_operand" "r"))
1471 (set (mem:GPI (plus:P (match_dup 0)
1472 (match_operand:P 5 "const_int_operand" "n")))
1473 (match_operand:GPI 3 "register_operand" "r"))])]
1474 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1475 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1476 [(set_attr "type" "store2")]
1479 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1481 [(set (match_operand:P 0 "register_operand" "=&k")
1482 (plus:P (match_operand:P 1 "register_operand" "0")
1483 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1484 (set (mem:GPF (plus:P (match_dup 0)
1486 (match_operand:GPF 2 "register_operand" "w"))
1487 (set (mem:GPF (plus:P (match_dup 0)
1488 (match_operand:P 5 "const_int_operand" "n")))
1489 (match_operand:GPF 3 "register_operand" "w"))])]
1490 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1491 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1492 [(set_attr "type" "neon_store1_2reg<q>")]
1495 ;; -------------------------------------------------------------------
1496 ;; Sign/Zero extension
1497 ;; -------------------------------------------------------------------
1499 (define_expand "<optab>sidi2"
1500 [(set (match_operand:DI 0 "register_operand")
1501 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1505 (define_insn "*extendsidi2_aarch64"
1506 [(set (match_operand:DI 0 "register_operand" "=r,r")
1507 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1512 [(set_attr "type" "extend,load1")]
1515 (define_insn "*load_pair_extendsidi2_aarch64"
1516 [(set (match_operand:DI 0 "register_operand" "=r")
1517 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1518 (set (match_operand:DI 2 "register_operand" "=r")
1519 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1520 "rtx_equal_p (XEXP (operands[3], 0),
1521 plus_constant (Pmode,
1522 XEXP (operands[1], 0),
1523 GET_MODE_SIZE (SImode)))"
1524 "ldpsw\\t%0, %2, %1"
1525 [(set_attr "type" "load2")]
1528 (define_insn "*zero_extendsidi2_aarch64"
1529 [(set (match_operand:DI 0 "register_operand" "=r,r")
1530 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1535 [(set_attr "type" "extend,load1")]
1538 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1539 [(set (match_operand:DI 0 "register_operand" "=r")
1540 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1541 (set (match_operand:DI 2 "register_operand" "=r")
1542 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1543 "rtx_equal_p (XEXP (operands[3], 0),
1544 plus_constant (Pmode,
1545 XEXP (operands[1], 0),
1546 GET_MODE_SIZE (SImode)))"
1547 "ldp\\t%w0, %w2, %1"
1548 [(set_attr "type" "load2")]
1551 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1552 [(set (match_operand:GPI 0 "register_operand")
1553 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1557 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1558 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1559 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1562 sxt<SHORT:size>\t%<GPI:w>0, %w1
1563 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1564 [(set_attr "type" "extend,load1")]
1567 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1568 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1569 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1572 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1573 ldr<SHORT:size>\t%w0, %1
1574 ldr\t%<SHORT:size>0, %1"
1575 [(set_attr "type" "logic_imm,load1,load1")]
1578 (define_expand "<optab>qihi2"
1579 [(set (match_operand:HI 0 "register_operand")
1580 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1584 (define_insn "*extendqihi2_aarch64"
1585 [(set (match_operand:HI 0 "register_operand" "=r,r")
1586 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1591 [(set_attr "type" "extend,load1")]
1594 (define_insn "*zero_extendqihi2_aarch64"
1595 [(set (match_operand:HI 0 "register_operand" "=r,r")
1596 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1601 [(set_attr "type" "logic_imm,load1")]
1604 ;; -------------------------------------------------------------------
1605 ;; Simple arithmetic
1606 ;; -------------------------------------------------------------------
1608 (define_expand "add<mode>3"
1610 (match_operand:GPI 0 "register_operand" "")
1611 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1612 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1615 /* If operands[1] is a subreg extract the inner RTX. */
1616 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1618 /* If the constant is too large for a single instruction and isn't frame
1619 based, split off the immediate so it is available for CSE. */
1620 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1621 && can_create_pseudo_p ()
1623 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1624 operands[2] = force_reg (<MODE>mode, operands[2]);
1627 (define_insn "*add<mode>3_aarch64"
1629 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1631 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1632 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1635 add\\t%<w>0, %<w>1, %2
1636 add\\t%<w>0, %<w>1, %<w>2
1637 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1638 sub\\t%<w>0, %<w>1, #%n2
1640 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1641 (set_attr "simd" "*,*,yes,*,*")]
1644 ;; zero_extend version of above
1645 (define_insn "*addsi3_aarch64_uxtw"
1647 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1649 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1650 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1655 sub\\t%w0, %w1, #%n2
1657 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1660 ;; If there's a free register, and we can load the constant with a
1661 ;; single instruction, do so. This has a chance to improve scheduling.
1663 [(match_scratch:GPI 3 "r")
1664 (set (match_operand:GPI 0 "register_operand")
1666 (match_operand:GPI 1 "register_operand")
1667 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1668 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1669 [(set (match_dup 3) (match_dup 2))
1670 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1674 [(match_scratch:SI 3 "r")
1675 (set (match_operand:DI 0 "register_operand")
1678 (match_operand:SI 1 "register_operand")
1679 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1680 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1681 [(set (match_dup 3) (match_dup 2))
1682 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1685 ;; After peephole2 has had a chance to run, split any remaining long
1686 ;; additions into two add immediates.
1688 [(set (match_operand:GPI 0 "register_operand")
1690 (match_operand:GPI 1 "register_operand")
1691 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1692 "epilogue_completed"
1693 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1694 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1696 HOST_WIDE_INT i = INTVAL (operands[2]);
1697 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1698 operands[3] = GEN_INT (i - s);
1699 operands[4] = GEN_INT (s);
1704 [(set (match_operand:DI 0 "register_operand")
1707 (match_operand:SI 1 "register_operand")
1708 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1709 "epilogue_completed"
1710 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1711 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1713 HOST_WIDE_INT i = INTVAL (operands[2]);
1714 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1715 operands[3] = GEN_INT (i - s);
1716 operands[4] = GEN_INT (s);
1717 operands[5] = gen_lowpart (SImode, operands[0]);
1721 (define_expand "addti3"
1722 [(set (match_operand:TI 0 "register_operand" "")
1723 (plus:TI (match_operand:TI 1 "register_operand" "")
1724 (match_operand:TI 2 "register_operand" "")))]
1727 rtx low = gen_reg_rtx (DImode);
1728 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1729 gen_lowpart (DImode, operands[2])));
1731 rtx high = gen_reg_rtx (DImode);
1732 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1733 gen_highpart (DImode, operands[2])));
1735 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1736 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1740 (define_insn "add<mode>3_compare0"
1741 [(set (reg:CC_NZ CC_REGNUM)
1743 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1744 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1746 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1747 (plus:GPI (match_dup 1) (match_dup 2)))]
1750 adds\\t%<w>0, %<w>1, %<w>2
1751 adds\\t%<w>0, %<w>1, %2
1752 subs\\t%<w>0, %<w>1, #%n2"
1753 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1756 ;; zero_extend version of above
1757 (define_insn "*addsi3_compare0_uxtw"
1758 [(set (reg:CC_NZ CC_REGNUM)
1760 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1761 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1763 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1764 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1767 adds\\t%w0, %w1, %w2
1769 subs\\t%w0, %w1, #%n2"
1770 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1773 (define_insn "*add<mode>3_compareC_cconly_imm"
1774 [(set (reg:CC_C CC_REGNUM)
1777 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1778 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1782 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1783 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1784 <MODE>mode, operands[1])"
1788 [(set_attr "type" "alus_imm")]
1791 (define_insn "*add<mode>3_compareC_cconly"
1792 [(set (reg:CC_C CC_REGNUM)
1795 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1796 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1797 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1799 "cmn\\t%<w>0, %<w>1"
1800 [(set_attr "type" "alus_sreg")]
1803 (define_insn "*add<mode>3_compareC_imm"
1804 [(set (reg:CC_C CC_REGNUM)
1807 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1808 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1812 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1813 (set (match_operand:GPI 0 "register_operand" "=r,r")
1814 (plus:GPI (match_dup 1) (match_dup 2)))]
1815 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1816 <MODE>mode, operands[2])"
1818 adds\\t%<w>0, %<w>1, %2
1819 subs\\t%<w>0, %<w>1, #%n2"
1820 [(set_attr "type" "alus_imm")]
1823 (define_insn "add<mode>3_compareC"
1824 [(set (reg:CC_C CC_REGNUM)
1827 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1828 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1830 (plus:GPI (match_dup 1) (match_dup 2)))))
1831 (set (match_operand:GPI 0 "register_operand" "=r")
1832 (plus:GPI (match_dup 1) (match_dup 2)))]
1834 "adds\\t%<w>0, %<w>1, %<w>2"
1835 [(set_attr "type" "alus_sreg")]
1838 (define_insn "*adds_shift_imm_<mode>"
1839 [(set (reg:CC_NZ CC_REGNUM)
1841 (plus:GPI (ASHIFT:GPI
1842 (match_operand:GPI 1 "register_operand" "r")
1843 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1844 (match_operand:GPI 3 "register_operand" "r"))
1846 (set (match_operand:GPI 0 "register_operand" "=r")
1847 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1850 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1851 [(set_attr "type" "alus_shift_imm")]
1854 (define_insn "*subs_shift_imm_<mode>"
1855 [(set (reg:CC_NZ CC_REGNUM)
1857 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1859 (match_operand:GPI 2 "register_operand" "r")
1860 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1862 (set (match_operand:GPI 0 "register_operand" "=r")
1863 (minus:GPI (match_dup 1)
1864 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1866 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1867 [(set_attr "type" "alus_shift_imm")]
1870 (define_insn "*adds_mul_imm_<mode>"
1871 [(set (reg:CC_NZ CC_REGNUM)
1874 (match_operand:GPI 1 "register_operand" "r")
1875 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1876 (match_operand:GPI 3 "register_operand" "r"))
1878 (set (match_operand:GPI 0 "register_operand" "=r")
1879 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1882 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1883 [(set_attr "type" "alus_shift_imm")]
1886 (define_insn "*subs_mul_imm_<mode>"
1887 [(set (reg:CC_NZ CC_REGNUM)
1889 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1891 (match_operand:GPI 2 "register_operand" "r")
1892 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1894 (set (match_operand:GPI 0 "register_operand" "=r")
1895 (minus:GPI (match_dup 1)
1896 (mult:GPI (match_dup 2) (match_dup 3))))]
1898 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1899 [(set_attr "type" "alus_shift_imm")]
1902 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1903 [(set (reg:CC_NZ CC_REGNUM)
1906 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1907 (match_operand:GPI 2 "register_operand" "r"))
1909 (set (match_operand:GPI 0 "register_operand" "=r")
1910 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1912 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1913 [(set_attr "type" "alus_ext")]
1916 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1917 [(set (reg:CC_NZ CC_REGNUM)
1919 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1921 (match_operand:ALLX 2 "register_operand" "r")))
1923 (set (match_operand:GPI 0 "register_operand" "=r")
1924 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1926 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1927 [(set_attr "type" "alus_ext")]
1930 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1931 [(set (reg:CC_NZ CC_REGNUM)
1933 (plus:GPI (ashift:GPI
1935 (match_operand:ALLX 1 "register_operand" "r"))
1936 (match_operand 2 "aarch64_imm3" "Ui3"))
1937 (match_operand:GPI 3 "register_operand" "r"))
1939 (set (match_operand:GPI 0 "register_operand" "=rk")
1940 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1944 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1945 [(set_attr "type" "alus_ext")]
1948 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1949 [(set (reg:CC_NZ CC_REGNUM)
1951 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1954 (match_operand:ALLX 2 "register_operand" "r"))
1955 (match_operand 3 "aarch64_imm3" "Ui3")))
1957 (set (match_operand:GPI 0 "register_operand" "=rk")
1958 (minus:GPI (match_dup 1)
1959 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1962 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1963 [(set_attr "type" "alus_ext")]
1966 (define_insn "*adds_<optab><mode>_multp2"
1967 [(set (reg:CC_NZ CC_REGNUM)
1969 (plus:GPI (ANY_EXTRACT:GPI
1970 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1971 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1972 (match_operand 3 "const_int_operand" "n")
1974 (match_operand:GPI 4 "register_operand" "r"))
1976 (set (match_operand:GPI 0 "register_operand" "=r")
1977 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1981 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1982 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1983 [(set_attr "type" "alus_ext")]
1986 (define_insn "*subs_<optab><mode>_multp2"
1987 [(set (reg:CC_NZ CC_REGNUM)
1989 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1991 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1992 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1993 (match_operand 3 "const_int_operand" "n")
1996 (set (match_operand:GPI 0 "register_operand" "=r")
1997 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1998 (mult:GPI (match_dup 1) (match_dup 2))
2001 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2002 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2003 [(set_attr "type" "alus_ext")]
2006 (define_insn "*add<mode>3nr_compare0"
2007 [(set (reg:CC_NZ CC_REGNUM)
2009 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2010 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2017 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2020 (define_insn "*compare_neg<mode>"
2021 [(set (reg:CC_Z CC_REGNUM)
2023 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2024 (match_operand:GPI 1 "register_operand" "r")))]
2026 "cmn\\t%<w>1, %<w>0"
2027 [(set_attr "type" "alus_sreg")]
2030 (define_insn "*add_<shift>_<mode>"
2031 [(set (match_operand:GPI 0 "register_operand" "=r")
2032 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2033 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2034 (match_operand:GPI 3 "register_operand" "r")))]
2036 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2037 [(set_attr "type" "alu_shift_imm")]
2040 ;; zero_extend version of above
2041 (define_insn "*add_<shift>_si_uxtw"
2042 [(set (match_operand:DI 0 "register_operand" "=r")
2044 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2045 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2046 (match_operand:SI 3 "register_operand" "r"))))]
2048 "add\\t%w0, %w3, %w1, <shift> %2"
2049 [(set_attr "type" "alu_shift_imm")]
2052 (define_insn "*add_mul_imm_<mode>"
2053 [(set (match_operand:GPI 0 "register_operand" "=r")
2054 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2055 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2056 (match_operand:GPI 3 "register_operand" "r")))]
2058 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2059 [(set_attr "type" "alu_shift_imm")]
2062 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2063 [(set (match_operand:GPI 0 "register_operand" "=rk")
2064 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2065 (match_operand:GPI 2 "register_operand" "r")))]
2067 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2068 [(set_attr "type" "alu_ext")]
2071 ;; zero_extend version of above
2072 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2073 [(set (match_operand:DI 0 "register_operand" "=rk")
2075 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2076 (match_operand:GPI 2 "register_operand" "r"))))]
2078 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2079 [(set_attr "type" "alu_ext")]
2082 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2083 [(set (match_operand:GPI 0 "register_operand" "=rk")
2084 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2085 (match_operand:ALLX 1 "register_operand" "r"))
2086 (match_operand 2 "aarch64_imm3" "Ui3"))
2087 (match_operand:GPI 3 "register_operand" "r")))]
2089 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2090 [(set_attr "type" "alu_ext")]
2093 ;; zero_extend version of above
2094 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2095 [(set (match_operand:DI 0 "register_operand" "=rk")
2097 (plus:SI (ashift:SI (ANY_EXTEND:SI
2098 (match_operand:SHORT 1 "register_operand" "r"))
2099 (match_operand 2 "aarch64_imm3" "Ui3"))
2100 (match_operand:SI 3 "register_operand" "r"))))]
2102 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2103 [(set_attr "type" "alu_ext")]
2106 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2107 [(set (match_operand:GPI 0 "register_operand" "=rk")
2108 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2109 (match_operand:ALLX 1 "register_operand" "r"))
2110 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2111 (match_operand:GPI 3 "register_operand" "r")))]
2113 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2114 [(set_attr "type" "alu_ext")]
2117 ;; zero_extend version of above
2118 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2119 [(set (match_operand:DI 0 "register_operand" "=rk")
2120 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2121 (match_operand:SHORT 1 "register_operand" "r"))
2122 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2123 (match_operand:SI 3 "register_operand" "r"))))]
2125 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2126 [(set_attr "type" "alu_ext")]
2129 (define_insn "*add_<optab><mode>_multp2"
2130 [(set (match_operand:GPI 0 "register_operand" "=rk")
2131 (plus:GPI (ANY_EXTRACT:GPI
2132 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2133 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2134 (match_operand 3 "const_int_operand" "n")
2136 (match_operand:GPI 4 "register_operand" "r")))]
2137 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2138 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2139 [(set_attr "type" "alu_ext")]
2142 ;; zero_extend version of above
2143 (define_insn "*add_<optab>si_multp2_uxtw"
2144 [(set (match_operand:DI 0 "register_operand" "=rk")
2146 (plus:SI (ANY_EXTRACT:SI
2147 (mult:SI (match_operand:SI 1 "register_operand" "r")
2148 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2149 (match_operand 3 "const_int_operand" "n")
2151 (match_operand:SI 4 "register_operand" "r"))))]
2152 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2153 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2154 [(set_attr "type" "alu_ext")]
2157 (define_expand "add<mode>3_carryin"
2158 [(set (match_operand:GPI 0 "register_operand")
2161 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2162 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2163 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2168 ;; Note that add with carry with two zero inputs is matched by cset,
2169 ;; and that add with carry with one zero input is matched by cinc.
2171 (define_insn "*add<mode>3_carryin"
2172 [(set (match_operand:GPI 0 "register_operand" "=r")
2175 (match_operand:GPI 3 "aarch64_carry_operation" "")
2176 (match_operand:GPI 1 "register_operand" "r"))
2177 (match_operand:GPI 2 "register_operand" "r")))]
2179 "adc\\t%<w>0, %<w>1, %<w>2"
2180 [(set_attr "type" "adc_reg")]
2183 ;; zero_extend version of above
2184 (define_insn "*addsi3_carryin_uxtw"
2185 [(set (match_operand:DI 0 "register_operand" "=r")
2189 (match_operand:SI 3 "aarch64_carry_operation" "")
2190 (match_operand:SI 1 "register_operand" "r"))
2191 (match_operand:SI 2 "register_operand" "r"))))]
2193 "adc\\t%w0, %w1, %w2"
2194 [(set_attr "type" "adc_reg")]
2197 (define_insn "*add_uxt<mode>_shift2"
2198 [(set (match_operand:GPI 0 "register_operand" "=rk")
2200 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2201 (match_operand 2 "aarch64_imm3" "Ui3"))
2202 (match_operand 3 "const_int_operand" "n"))
2203 (match_operand:GPI 4 "register_operand" "r")))]
2204 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2206 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2207 INTVAL (operands[3])));
2208 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2209 [(set_attr "type" "alu_ext")]
2212 ;; zero_extend version of above
2213 (define_insn "*add_uxtsi_shift2_uxtw"
2214 [(set (match_operand:DI 0 "register_operand" "=rk")
2217 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2218 (match_operand 2 "aarch64_imm3" "Ui3"))
2219 (match_operand 3 "const_int_operand" "n"))
2220 (match_operand:SI 4 "register_operand" "r"))))]
2221 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2223 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2224 INTVAL (operands[3])));
2225 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2226 [(set_attr "type" "alu_ext")]
2229 (define_insn "*add_uxt<mode>_multp2"
2230 [(set (match_operand:GPI 0 "register_operand" "=rk")
2232 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2233 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2234 (match_operand 3 "const_int_operand" "n"))
2235 (match_operand:GPI 4 "register_operand" "r")))]
2236 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2238 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2239 INTVAL (operands[3])));
2240 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2241 [(set_attr "type" "alu_ext")]
2244 ;; zero_extend version of above
2245 (define_insn "*add_uxtsi_multp2_uxtw"
2246 [(set (match_operand:DI 0 "register_operand" "=rk")
2249 (mult:SI (match_operand:SI 1 "register_operand" "r")
2250 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2251 (match_operand 3 "const_int_operand" "n"))
2252 (match_operand:SI 4 "register_operand" "r"))))]
2253 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2255 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2256 INTVAL (operands[3])));
2257 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2258 [(set_attr "type" "alu_ext")]
2261 (define_insn "subsi3"
2262 [(set (match_operand:SI 0 "register_operand" "=rk")
2263 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2264 (match_operand:SI 2 "register_operand" "r")))]
2266 "sub\\t%w0, %w1, %w2"
2267 [(set_attr "type" "alu_sreg")]
2270 ;; zero_extend version of above
2271 (define_insn "*subsi3_uxtw"
2272 [(set (match_operand:DI 0 "register_operand" "=rk")
2274 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2275 (match_operand:SI 2 "register_operand" "r"))))]
2277 "sub\\t%w0, %w1, %w2"
2278 [(set_attr "type" "alu_sreg")]
2281 (define_insn "subdi3"
2282 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2283 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2284 (match_operand:DI 2 "register_operand" "r,w")))]
2288 sub\\t%d0, %d1, %d2"
2289 [(set_attr "type" "alu_sreg, neon_sub")
2290 (set_attr "simd" "*,yes")]
2293 (define_expand "subti3"
2294 [(set (match_operand:TI 0 "register_operand" "")
2295 (minus:TI (match_operand:TI 1 "register_operand" "")
2296 (match_operand:TI 2 "register_operand" "")))]
2299 rtx low = gen_reg_rtx (DImode);
2300 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2301 gen_lowpart (DImode, operands[2])));
2303 rtx high = gen_reg_rtx (DImode);
2304 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2305 gen_highpart (DImode, operands[2])));
2307 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2308 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2312 (define_insn "*sub<mode>3_compare0"
2313 [(set (reg:CC_NZ CC_REGNUM)
2314 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2315 (match_operand:GPI 2 "register_operand" "r"))
2317 (set (match_operand:GPI 0 "register_operand" "=r")
2318 (minus:GPI (match_dup 1) (match_dup 2)))]
2320 "subs\\t%<w>0, %<w>1, %<w>2"
2321 [(set_attr "type" "alus_sreg")]
2324 ;; zero_extend version of above
2325 (define_insn "*subsi3_compare0_uxtw"
2326 [(set (reg:CC_NZ CC_REGNUM)
2327 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2328 (match_operand:SI 2 "register_operand" "r"))
2330 (set (match_operand:DI 0 "register_operand" "=r")
2331 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2333 "subs\\t%w0, %w1, %w2"
2334 [(set_attr "type" "alus_sreg")]
2337 (define_insn "sub<mode>3_compare1"
2338 [(set (reg:CC CC_REGNUM)
2340 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2341 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2342 (set (match_operand:GPI 0 "register_operand" "=r")
2343 (minus:GPI (match_dup 1) (match_dup 2)))]
2345 "subs\\t%<w>0, %<w>1, %<w>2"
2346 [(set_attr "type" "alus_sreg")]
2349 (define_insn "*sub_<shift>_<mode>"
2350 [(set (match_operand:GPI 0 "register_operand" "=r")
2351 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2353 (match_operand:GPI 1 "register_operand" "r")
2354 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2356 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2357 [(set_attr "type" "alu_shift_imm")]
2360 ;; zero_extend version of above
2361 (define_insn "*sub_<shift>_si_uxtw"
2362 [(set (match_operand:DI 0 "register_operand" "=r")
2364 (minus:SI (match_operand:SI 3 "register_operand" "r")
2366 (match_operand:SI 1 "register_operand" "r")
2367 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2369 "sub\\t%w0, %w3, %w1, <shift> %2"
2370 [(set_attr "type" "alu_shift_imm")]
2373 (define_insn "*sub_mul_imm_<mode>"
2374 [(set (match_operand:GPI 0 "register_operand" "=r")
2375 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2377 (match_operand:GPI 1 "register_operand" "r")
2378 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2380 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2381 [(set_attr "type" "alu_shift_imm")]
2384 ;; zero_extend version of above
2385 (define_insn "*sub_mul_imm_si_uxtw"
2386 [(set (match_operand:DI 0 "register_operand" "=r")
2388 (minus:SI (match_operand:SI 3 "register_operand" "r")
2390 (match_operand:SI 1 "register_operand" "r")
2391 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2393 "sub\\t%w0, %w3, %w1, lsl %p2"
2394 [(set_attr "type" "alu_shift_imm")]
2397 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2398 [(set (match_operand:GPI 0 "register_operand" "=rk")
2399 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2401 (match_operand:ALLX 2 "register_operand" "r"))))]
2403 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2404 [(set_attr "type" "alu_ext")]
2407 ;; zero_extend version of above
2408 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2409 [(set (match_operand:DI 0 "register_operand" "=rk")
2411 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2413 (match_operand:SHORT 2 "register_operand" "r")))))]
2415 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2416 [(set_attr "type" "alu_ext")]
2419 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2420 [(set (match_operand:GPI 0 "register_operand" "=rk")
2421 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2422 (ashift:GPI (ANY_EXTEND:GPI
2423 (match_operand:ALLX 2 "register_operand" "r"))
2424 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2426 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2427 [(set_attr "type" "alu_ext")]
2430 ;; zero_extend version of above
2431 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2432 [(set (match_operand:DI 0 "register_operand" "=rk")
2434 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2435 (ashift:SI (ANY_EXTEND:SI
2436 (match_operand:SHORT 2 "register_operand" "r"))
2437 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2439 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2440 [(set_attr "type" "alu_ext")]
2443 (define_insn "*sub_<optab><mode>_multp2"
2444 [(set (match_operand:GPI 0 "register_operand" "=rk")
2445 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2447 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2448 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2449 (match_operand 3 "const_int_operand" "n")
2451 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2452 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2453 [(set_attr "type" "alu_ext")]
2456 ;; zero_extend version of above
2457 (define_insn "*sub_<optab>si_multp2_uxtw"
2458 [(set (match_operand:DI 0 "register_operand" "=rk")
2460 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2462 (mult:SI (match_operand:SI 1 "register_operand" "r")
2463 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2464 (match_operand 3 "const_int_operand" "n")
2466 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2467 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2468 [(set_attr "type" "alu_ext")]
2471 ;; The hardware description is op1 + ~op2 + C.
2472 ;; = op1 + (-op2 + 1) + (1 - !C)
2473 ;; = op1 - op2 - 1 + 1 - !C
2474 ;; = op1 - op2 - !C.
2475 ;; We describe the latter.
2477 (define_insn "*sub<mode>3_carryin0"
2478 [(set (match_operand:GPI 0 "register_operand" "=r")
2480 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2481 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2483 "sbc\\t%<w>0, %<w>1, <w>zr"
2484 [(set_attr "type" "adc_reg")]
2487 ;; zero_extend version of the above
2488 (define_insn "*subsi3_carryin_uxtw"
2489 [(set (match_operand:DI 0 "register_operand" "=r")
2492 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2493 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2495 "sbc\\t%w0, %w1, wzr"
2496 [(set_attr "type" "adc_reg")]
2499 (define_expand "sub<mode>3_carryin"
2500 [(set (match_operand:GPI 0 "register_operand")
2503 (match_operand:GPI 1 "aarch64_reg_or_zero")
2504 (match_operand:GPI 2 "register_operand"))
2505 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2510 (define_insn "*sub<mode>3_carryin"
2511 [(set (match_operand:GPI 0 "register_operand" "=r")
2514 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2515 (match_operand:GPI 2 "register_operand" "r"))
2516 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2519 "sbc\\t%<w>0, %<w>1, %<w>2"
2520 [(set_attr "type" "adc_reg")]
2523 ;; zero_extend version of the above
2524 (define_insn "*subsi3_carryin_uxtw"
2525 [(set (match_operand:DI 0 "register_operand" "=r")
2529 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2530 (match_operand:SI 2 "register_operand" "r"))
2531 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2534 "sbc\\t%w0, %w1, %w2"
2535 [(set_attr "type" "adc_reg")]
2538 (define_insn "*sub<mode>3_carryin_alt"
2539 [(set (match_operand:GPI 0 "register_operand" "=r")
2542 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2543 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2544 (match_operand:GPI 2 "register_operand" "r")))]
2546 "sbc\\t%<w>0, %<w>1, %<w>2"
2547 [(set_attr "type" "adc_reg")]
2550 ;; zero_extend version of the above
2551 (define_insn "*subsi3_carryin_alt_uxtw"
2552 [(set (match_operand:DI 0 "register_operand" "=r")
2556 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2557 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2558 (match_operand:SI 2 "register_operand" "r"))))]
2560 "sbc\\t%w0, %w1, %w2"
2561 [(set_attr "type" "adc_reg")]
2564 (define_insn "*sub_uxt<mode>_shift2"
2565 [(set (match_operand:GPI 0 "register_operand" "=rk")
2566 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2568 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2569 (match_operand 2 "aarch64_imm3" "Ui3"))
2570 (match_operand 3 "const_int_operand" "n"))))]
2571 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2573 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2574 INTVAL (operands[3])));
2575 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2576 [(set_attr "type" "alu_ext")]
2579 ;; zero_extend version of above
2580 (define_insn "*sub_uxtsi_shift2_uxtw"
2581 [(set (match_operand:DI 0 "register_operand" "=rk")
2583 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2585 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2586 (match_operand 2 "aarch64_imm3" "Ui3"))
2587 (match_operand 3 "const_int_operand" "n")))))]
2588 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2590 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2591 INTVAL (operands[3])));
2592 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2593 [(set_attr "type" "alu_ext")]
2596 (define_insn "*sub_uxt<mode>_multp2"
2597 [(set (match_operand:GPI 0 "register_operand" "=rk")
2598 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2600 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2601 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2602 (match_operand 3 "const_int_operand" "n"))))]
2603 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2605 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2606 INTVAL (operands[3])));
2607 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2608 [(set_attr "type" "alu_ext")]
2611 ;; zero_extend version of above
2612 (define_insn "*sub_uxtsi_multp2_uxtw"
2613 [(set (match_operand:DI 0 "register_operand" "=rk")
2615 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2617 (mult:SI (match_operand:SI 1 "register_operand" "r")
2618 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2619 (match_operand 3 "const_int_operand" "n")))))]
2620 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2622 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2623 INTVAL (operands[3])));
2624 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2625 [(set_attr "type" "alu_ext")]
2628 (define_expand "abs<mode>2"
2629 [(match_operand:GPI 0 "register_operand" "")
2630 (match_operand:GPI 1 "register_operand" "")]
2633 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2634 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2635 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2640 (define_insn "neg<mode>2"
2641 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2642 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2646 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2647 [(set_attr "type" "alu_sreg, neon_neg<q>")
2648 (set_attr "simd" "*,yes")]
2651 ;; zero_extend version of above
2652 (define_insn "*negsi2_uxtw"
2653 [(set (match_operand:DI 0 "register_operand" "=r")
2654 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2657 [(set_attr "type" "alu_sreg")]
2660 (define_insn "*ngc<mode>"
2661 [(set (match_operand:GPI 0 "register_operand" "=r")
2663 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2664 (match_operand:GPI 1 "register_operand" "r")))]
2666 "ngc\\t%<w>0, %<w>1"
2667 [(set_attr "type" "adc_reg")]
2670 (define_insn "*ngcsi_uxtw"
2671 [(set (match_operand:DI 0 "register_operand" "=r")
2674 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2675 (match_operand:SI 1 "register_operand" "r"))))]
2678 [(set_attr "type" "adc_reg")]
2681 (define_insn "neg<mode>2_compare0"
2682 [(set (reg:CC_NZ CC_REGNUM)
2683 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2685 (set (match_operand:GPI 0 "register_operand" "=r")
2686 (neg:GPI (match_dup 1)))]
2688 "negs\\t%<w>0, %<w>1"
2689 [(set_attr "type" "alus_sreg")]
2692 ;; zero_extend version of above
2693 (define_insn "*negsi2_compare0_uxtw"
2694 [(set (reg:CC_NZ CC_REGNUM)
2695 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2697 (set (match_operand:DI 0 "register_operand" "=r")
2698 (zero_extend:DI (neg:SI (match_dup 1))))]
2701 [(set_attr "type" "alus_sreg")]
2704 (define_insn "*neg_<shift><mode>3_compare0"
2705 [(set (reg:CC_NZ CC_REGNUM)
2707 (neg:GPI (ASHIFT:GPI
2708 (match_operand:GPI 1 "register_operand" "r")
2709 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2711 (set (match_operand:GPI 0 "register_operand" "=r")
2712 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2714 "negs\\t%<w>0, %<w>1, <shift> %2"
2715 [(set_attr "type" "alus_shift_imm")]
2718 (define_insn "*neg_<shift>_<mode>2"
2719 [(set (match_operand:GPI 0 "register_operand" "=r")
2720 (neg:GPI (ASHIFT:GPI
2721 (match_operand:GPI 1 "register_operand" "r")
2722 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2724 "neg\\t%<w>0, %<w>1, <shift> %2"
2725 [(set_attr "type" "alu_shift_imm")]
2728 ;; zero_extend version of above
2729 (define_insn "*neg_<shift>_si2_uxtw"
2730 [(set (match_operand:DI 0 "register_operand" "=r")
2733 (match_operand:SI 1 "register_operand" "r")
2734 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2736 "neg\\t%w0, %w1, <shift> %2"
2737 [(set_attr "type" "alu_shift_imm")]
2740 (define_insn "*neg_mul_imm_<mode>2"
2741 [(set (match_operand:GPI 0 "register_operand" "=r")
2743 (match_operand:GPI 1 "register_operand" "r")
2744 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2746 "neg\\t%<w>0, %<w>1, lsl %p2"
2747 [(set_attr "type" "alu_shift_imm")]
2750 ;; zero_extend version of above
2751 (define_insn "*neg_mul_imm_si2_uxtw"
2752 [(set (match_operand:DI 0 "register_operand" "=r")
2755 (match_operand:SI 1 "register_operand" "r")
2756 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2758 "neg\\t%w0, %w1, lsl %p2"
2759 [(set_attr "type" "alu_shift_imm")]
2762 (define_insn "mul<mode>3"
2763 [(set (match_operand:GPI 0 "register_operand" "=r")
2764 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2765 (match_operand:GPI 2 "register_operand" "r")))]
2767 "mul\\t%<w>0, %<w>1, %<w>2"
2768 [(set_attr "type" "mul")]
2771 ;; zero_extend version of above
2772 (define_insn "*mulsi3_uxtw"
2773 [(set (match_operand:DI 0 "register_operand" "=r")
2775 (mult:SI (match_operand:SI 1 "register_operand" "r")
2776 (match_operand:SI 2 "register_operand" "r"))))]
2778 "mul\\t%w0, %w1, %w2"
2779 [(set_attr "type" "mul")]
2782 (define_insn "madd<mode>"
2783 [(set (match_operand:GPI 0 "register_operand" "=r")
2784 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2785 (match_operand:GPI 2 "register_operand" "r"))
2786 (match_operand:GPI 3 "register_operand" "r")))]
2788 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2789 [(set_attr "type" "mla")]
2792 ;; zero_extend version of above
2793 (define_insn "*maddsi_uxtw"
2794 [(set (match_operand:DI 0 "register_operand" "=r")
2796 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2797 (match_operand:SI 2 "register_operand" "r"))
2798 (match_operand:SI 3 "register_operand" "r"))))]
2800 "madd\\t%w0, %w1, %w2, %w3"
2801 [(set_attr "type" "mla")]
2804 (define_insn "*msub<mode>"
2805 [(set (match_operand:GPI 0 "register_operand" "=r")
2806 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2807 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2808 (match_operand:GPI 2 "register_operand" "r"))))]
2811 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2812 [(set_attr "type" "mla")]
2815 ;; zero_extend version of above
2816 (define_insn "*msubsi_uxtw"
2817 [(set (match_operand:DI 0 "register_operand" "=r")
2819 (minus:SI (match_operand:SI 3 "register_operand" "r")
2820 (mult:SI (match_operand:SI 1 "register_operand" "r")
2821 (match_operand:SI 2 "register_operand" "r")))))]
2824 "msub\\t%w0, %w1, %w2, %w3"
2825 [(set_attr "type" "mla")]
2828 (define_insn "*mul<mode>_neg"
2829 [(set (match_operand:GPI 0 "register_operand" "=r")
2830 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2831 (match_operand:GPI 2 "register_operand" "r")))]
2834 "mneg\\t%<w>0, %<w>1, %<w>2"
2835 [(set_attr "type" "mul")]
2838 ;; zero_extend version of above
2839 (define_insn "*mulsi_neg_uxtw"
2840 [(set (match_operand:DI 0 "register_operand" "=r")
2842 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2843 (match_operand:SI 2 "register_operand" "r"))))]
2846 "mneg\\t%w0, %w1, %w2"
2847 [(set_attr "type" "mul")]
2850 (define_insn "<su_optab>mulsidi3"
2851 [(set (match_operand:DI 0 "register_operand" "=r")
2852 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2853 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2855 "<su>mull\\t%0, %w1, %w2"
2856 [(set_attr "type" "<su>mull")]
2859 (define_insn "<su_optab>maddsidi4"
2860 [(set (match_operand:DI 0 "register_operand" "=r")
2862 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2863 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2864 (match_operand:DI 3 "register_operand" "r")))]
2866 "<su>maddl\\t%0, %w1, %w2, %3"
2867 [(set_attr "type" "<su>mlal")]
2870 (define_insn "<su_optab>msubsidi4"
2871 [(set (match_operand:DI 0 "register_operand" "=r")
2873 (match_operand:DI 3 "register_operand" "r")
2874 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2876 (match_operand:SI 2 "register_operand" "r")))))]
2878 "<su>msubl\\t%0, %w1, %w2, %3"
2879 [(set_attr "type" "<su>mlal")]
2882 (define_insn "*<su_optab>mulsidi_neg"
2883 [(set (match_operand:DI 0 "register_operand" "=r")
2885 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2886 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2888 "<su>mnegl\\t%0, %w1, %w2"
2889 [(set_attr "type" "<su>mull")]
2892 (define_expand "<su_optab>mulditi3"
2893 [(set (match_operand:TI 0 "register_operand")
2894 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2895 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2898 rtx low = gen_reg_rtx (DImode);
2899 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2901 rtx high = gen_reg_rtx (DImode);
2902 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2904 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2905 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2909 ;; The default expansion of multi3 using umuldi3_highpart will perform
2910 ;; the additions in an order that fails to combine into two madd insns.
2911 (define_expand "multi3"
2912 [(set (match_operand:TI 0 "register_operand")
2913 (mult:TI (match_operand:TI 1 "register_operand")
2914 (match_operand:TI 2 "register_operand")))]
2917 rtx l0 = gen_reg_rtx (DImode);
2918 rtx l1 = gen_lowpart (DImode, operands[1]);
2919 rtx l2 = gen_lowpart (DImode, operands[2]);
2920 rtx h0 = gen_reg_rtx (DImode);
2921 rtx h1 = gen_highpart (DImode, operands[1]);
2922 rtx h2 = gen_highpart (DImode, operands[2]);
2924 emit_insn (gen_muldi3 (l0, l1, l2));
2925 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2926 emit_insn (gen_madddi (h0, h1, l2, h0));
2927 emit_insn (gen_madddi (h0, l1, h2, h0));
2929 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2930 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2934 (define_insn "<su>muldi3_highpart"
2935 [(set (match_operand:DI 0 "register_operand" "=r")
2939 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2940 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2943 "<su>mulh\\t%0, %1, %2"
2944 [(set_attr "type" "<su>mull")]
2947 (define_insn "<su_optab>div<mode>3"
2948 [(set (match_operand:GPI 0 "register_operand" "=r")
2949 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2950 (match_operand:GPI 2 "register_operand" "r")))]
2952 "<su>div\\t%<w>0, %<w>1, %<w>2"
2953 [(set_attr "type" "<su>div")]
2956 ;; zero_extend version of above
2957 (define_insn "*<su_optab>divsi3_uxtw"
2958 [(set (match_operand:DI 0 "register_operand" "=r")
2960 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2961 (match_operand:SI 2 "register_operand" "r"))))]
2963 "<su>div\\t%w0, %w1, %w2"
2964 [(set_attr "type" "<su>div")]
2967 ;; -------------------------------------------------------------------
2969 ;; -------------------------------------------------------------------
2971 (define_insn "cmp<mode>"
2972 [(set (reg:CC CC_REGNUM)
2973 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2974 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2980 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2983 (define_insn "fcmp<mode>"
2984 [(set (reg:CCFP CC_REGNUM)
2985 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2986 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2990 fcmp\\t%<s>0, %<s>1"
2991 [(set_attr "type" "fcmp<s>")]
2994 (define_insn "fcmpe<mode>"
2995 [(set (reg:CCFPE CC_REGNUM)
2996 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2997 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3001 fcmpe\\t%<s>0, %<s>1"
3002 [(set_attr "type" "fcmp<s>")]
3005 (define_insn "*cmp_swp_<shift>_reg<mode>"
3006 [(set (reg:CC_SWP CC_REGNUM)
3007 (compare:CC_SWP (ASHIFT:GPI
3008 (match_operand:GPI 0 "register_operand" "r")
3009 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3010 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3012 "cmp\\t%<w>2, %<w>0, <shift> %1"
3013 [(set_attr "type" "alus_shift_imm")]
3016 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3017 [(set (reg:CC_SWP CC_REGNUM)
3018 (compare:CC_SWP (ANY_EXTEND:GPI
3019 (match_operand:ALLX 0 "register_operand" "r"))
3020 (match_operand:GPI 1 "register_operand" "r")))]
3022 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3023 [(set_attr "type" "alus_ext")]
3026 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3027 [(set (reg:CC_SWP CC_REGNUM)
3028 (compare:CC_SWP (ashift:GPI
3030 (match_operand:ALLX 0 "register_operand" "r"))
3031 (match_operand 1 "aarch64_imm3" "Ui3"))
3032 (match_operand:GPI 2 "register_operand" "r")))]
3034 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3035 [(set_attr "type" "alus_ext")]
3038 ;; -------------------------------------------------------------------
3039 ;; Store-flag and conditional select insns
3040 ;; -------------------------------------------------------------------
3042 (define_expand "cstore<mode>4"
3043 [(set (match_operand:SI 0 "register_operand" "")
3044 (match_operator:SI 1 "aarch64_comparison_operator"
3045 [(match_operand:GPI 2 "register_operand" "")
3046 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3049 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3051 operands[3] = const0_rtx;
3055 (define_expand "cstorecc4"
3056 [(set (match_operand:SI 0 "register_operand")
3057 (match_operator 1 "aarch64_comparison_operator_mode"
3058 [(match_operand 2 "cc_register")
3059 (match_operand 3 "const0_operand")]))]
3062 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3067 (define_expand "cstore<mode>4"
3068 [(set (match_operand:SI 0 "register_operand" "")
3069 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3070 [(match_operand:GPF 2 "register_operand" "")
3071 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3074 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3076 operands[3] = const0_rtx;
3080 (define_insn "aarch64_cstore<mode>"
3081 [(set (match_operand:ALLI 0 "register_operand" "=r")
3082 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3083 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3086 [(set_attr "type" "csel")]
3089 ;; For a 24-bit immediate CST we can optimize the compare for equality
3090 ;; and branch sequence from:
3092 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3095 ;; into the shorter:
3096 ;; sub x0, x1, #(CST & 0xfff000)
3097 ;; subs x0, x0, #(CST & 0x000fff)
3098 ;; cset x2, <ne, eq>.
3099 (define_insn_and_split "*compare_cstore<mode>_insn"
3100 [(set (match_operand:GPI 0 "register_operand" "=r")
3101 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3102 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3103 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3104 && !aarch64_plus_operand (operands[2], <MODE>mode)
3105 && !reload_completed"
3110 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3111 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3112 rtx tmp = gen_reg_rtx (<MODE>mode);
3113 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3114 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3115 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3116 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3117 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3120 [(set_attr "type" "csel")]
3123 ;; zero_extend version of the above
3124 (define_insn "*cstoresi_insn_uxtw"
3125 [(set (match_operand:DI 0 "register_operand" "=r")
3127 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3128 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3131 [(set_attr "type" "csel")]
3134 (define_insn "cstore<mode>_neg"
3135 [(set (match_operand:ALLI 0 "register_operand" "=r")
3136 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3137 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3139 "csetm\\t%<w>0, %m1"
3140 [(set_attr "type" "csel")]
3143 ;; zero_extend version of the above
3144 (define_insn "*cstoresi_neg_uxtw"
3145 [(set (match_operand:DI 0 "register_operand" "=r")
3147 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3148 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3151 [(set_attr "type" "csel")]
3154 (define_expand "cmov<mode>6"
3155 [(set (match_operand:GPI 0 "register_operand" "")
3157 (match_operator 1 "aarch64_comparison_operator"
3158 [(match_operand:GPI 2 "register_operand" "")
3159 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3160 (match_operand:GPI 4 "register_operand" "")
3161 (match_operand:GPI 5 "register_operand" "")))]
3164 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3166 operands[3] = const0_rtx;
3170 (define_expand "cmov<mode>6"
3171 [(set (match_operand:GPF 0 "register_operand" "")
3173 (match_operator 1 "aarch64_comparison_operator"
3174 [(match_operand:GPF 2 "register_operand" "")
3175 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3176 (match_operand:GPF 4 "register_operand" "")
3177 (match_operand:GPF 5 "register_operand" "")))]
3180 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3182 operands[3] = const0_rtx;
3186 (define_insn "*cmov<mode>_insn"
3187 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3189 (match_operator 1 "aarch64_comparison_operator"
3190 [(match_operand 2 "cc_register" "") (const_int 0)])
3191 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3192 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3193 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3194 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3195 ;; Final two alternatives should be unreachable, but included for completeness
3197 csel\\t%<w>0, %<w>3, %<w>4, %m1
3198 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3199 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3200 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3201 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3204 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3207 ;; zero_extend version of above
3208 (define_insn "*cmovsi_insn_uxtw"
3209 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3212 (match_operator 1 "aarch64_comparison_operator"
3213 [(match_operand 2 "cc_register" "") (const_int 0)])
3214 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3215 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3216 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3217 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3218 ;; Final two alternatives should be unreachable, but included for completeness
3220 csel\\t%w0, %w3, %w4, %m1
3221 csinv\\t%w0, %w3, wzr, %m1
3222 csinv\\t%w0, %w4, wzr, %M1
3223 csinc\\t%w0, %w3, wzr, %m1
3224 csinc\\t%w0, %w4, wzr, %M1
3227 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3230 (define_insn "*cmovdi_insn_uxtw"
3231 [(set (match_operand:DI 0 "register_operand" "=r")
3233 (match_operator 1 "aarch64_comparison_operator"
3234 [(match_operand 2 "cc_register" "") (const_int 0)])
3235 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3236 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3238 "csel\\t%w0, %w3, %w4, %m1"
3239 [(set_attr "type" "csel")]
3242 (define_insn "*cmov<mode>_insn"
3243 [(set (match_operand:GPF 0 "register_operand" "=w")
3245 (match_operator 1 "aarch64_comparison_operator"
3246 [(match_operand 2 "cc_register" "") (const_int 0)])
3247 (match_operand:GPF 3 "register_operand" "w")
3248 (match_operand:GPF 4 "register_operand" "w")))]
3250 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3251 [(set_attr "type" "fcsel")]
3254 (define_expand "mov<mode>cc"
3255 [(set (match_operand:ALLI 0 "register_operand" "")
3256 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3257 (match_operand:ALLI 2 "register_operand" "")
3258 (match_operand:ALLI 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<GPF:mode><GPI:mode>cc"
3274 [(set (match_operand:GPI 0 "register_operand" "")
3275 (if_then_else:GPI (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 "mov<mode>cc"
3293 [(set (match_operand:GPF 0 "register_operand" "")
3294 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3295 (match_operand:GPF 2 "register_operand" "")
3296 (match_operand:GPF 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 (define_expand "<neg_not_op><mode>cc"
3312 [(set (match_operand:GPI 0 "register_operand" "")
3313 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3314 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3315 (match_operand:GPI 3 "register_operand" "")))]
3319 enum rtx_code code = GET_CODE (operands[1]);
3321 if (code == UNEQ || code == LTGT)
3324 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3325 XEXP (operands[1], 1));
3326 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3330 ;; CRC32 instructions.
3331 (define_insn "aarch64_<crc_variant>"
3332 [(set (match_operand:SI 0 "register_operand" "=r")
3333 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3334 (match_operand:<crc_mode> 2 "register_operand" "r")]
3338 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3339 return "<crc_variant>\\t%w0, %w1, %x2";
3341 return "<crc_variant>\\t%w0, %w1, %w2";
3343 [(set_attr "type" "crc")]
3346 (define_insn "*csinc2<mode>_insn"
3347 [(set (match_operand:GPI 0 "register_operand" "=r")
3348 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3349 (match_operand:GPI 1 "register_operand" "r")))]
3351 "cinc\\t%<w>0, %<w>1, %m2"
3352 [(set_attr "type" "csel")]
3355 (define_insn "csinc3<mode>_insn"
3356 [(set (match_operand:GPI 0 "register_operand" "=r")
3358 (match_operand 1 "aarch64_comparison_operation" "")
3359 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3361 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3363 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3364 [(set_attr "type" "csel")]
3367 (define_insn "*csinv3<mode>_insn"
3368 [(set (match_operand:GPI 0 "register_operand" "=r")
3370 (match_operand 1 "aarch64_comparison_operation" "")
3371 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3372 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3374 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3375 [(set_attr "type" "csel")]
3378 (define_insn "csneg3_uxtw_insn"
3379 [(set (match_operand:DI 0 "register_operand" "=r")
3382 (match_operand 1 "aarch64_comparison_operation" "")
3383 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3384 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3386 "csneg\\t%w0, %w3, %w2, %M1"
3387 [(set_attr "type" "csel")]
3390 (define_insn "csneg3<mode>_insn"
3391 [(set (match_operand:GPI 0 "register_operand" "=r")
3393 (match_operand 1 "aarch64_comparison_operation" "")
3394 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3395 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3397 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3398 [(set_attr "type" "csel")]
3401 ;; -------------------------------------------------------------------
3402 ;; Logical operations
3403 ;; -------------------------------------------------------------------
3406 (define_insn_and_split "*aarch64_and<mode>_imm2"
3407 [(set (match_operand:GPI 0 "register_operand" "=rk")
3408 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3409 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3415 HOST_WIDE_INT val = INTVAL (operands[2]);
3416 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3417 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3419 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3420 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3425 (define_insn "<optab><mode>3"
3426 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3427 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3428 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3431 <logical>\\t%<w>0, %<w>1, %<w>2
3432 <logical>\\t%<w>0, %<w>1, %2
3433 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3434 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3435 (set_attr "simd" "*,*,yes")]
3438 ;; zero_extend version of above
3439 (define_insn "*<optab>si3_uxtw"
3440 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3442 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3443 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3446 <logical>\\t%w0, %w1, %w2
3447 <logical>\\t%w0, %w1, %2"
3448 [(set_attr "type" "logic_reg,logic_imm")]
3451 (define_insn "*and<mode>3_compare0"
3452 [(set (reg:CC_NZ CC_REGNUM)
3454 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3455 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3457 (set (match_operand:GPI 0 "register_operand" "=r,r")
3458 (and:GPI (match_dup 1) (match_dup 2)))]
3461 ands\\t%<w>0, %<w>1, %<w>2
3462 ands\\t%<w>0, %<w>1, %2"
3463 [(set_attr "type" "logics_reg,logics_imm")]
3466 ;; zero_extend version of above
3467 (define_insn "*andsi3_compare0_uxtw"
3468 [(set (reg:CC_NZ CC_REGNUM)
3470 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3471 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3473 (set (match_operand:DI 0 "register_operand" "=r,r")
3474 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3477 ands\\t%w0, %w1, %w2
3478 ands\\t%w0, %w1, %2"
3479 [(set_attr "type" "logics_reg,logics_imm")]
3482 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3483 [(set (reg:CC_NZ CC_REGNUM)
3486 (match_operand:GPI 1 "register_operand" "r")
3487 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3488 (match_operand:GPI 3 "register_operand" "r"))
3490 (set (match_operand:GPI 0 "register_operand" "=r")
3491 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3493 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3494 [(set_attr "type" "logics_shift_imm")]
3497 ;; zero_extend version of above
3498 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3499 [(set (reg:CC_NZ CC_REGNUM)
3502 (match_operand:SI 1 "register_operand" "r")
3503 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3504 (match_operand:SI 3 "register_operand" "r"))
3506 (set (match_operand:DI 0 "register_operand" "=r")
3507 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3510 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3511 [(set_attr "type" "logics_shift_imm")]
3514 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3515 [(set (match_operand:GPI 0 "register_operand" "=r")
3516 (LOGICAL:GPI (SHIFT:GPI
3517 (match_operand:GPI 1 "register_operand" "r")
3518 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3519 (match_operand:GPI 3 "register_operand" "r")))]
3521 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3522 [(set_attr "type" "logic_shift_imm")]
3525 (define_insn "*<optab>_rol<mode>3"
3526 [(set (match_operand:GPI 0 "register_operand" "=r")
3527 (LOGICAL:GPI (rotate:GPI
3528 (match_operand:GPI 1 "register_operand" "r")
3529 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3530 (match_operand:GPI 3 "register_operand" "r")))]
3532 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3533 [(set_attr "type" "logic_shift_imm")]
3536 ;; zero_extend versions of above
3537 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3538 [(set (match_operand:DI 0 "register_operand" "=r")
3540 (LOGICAL:SI (SHIFT:SI
3541 (match_operand:SI 1 "register_operand" "r")
3542 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3543 (match_operand:SI 3 "register_operand" "r"))))]
3545 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3546 [(set_attr "type" "logic_shift_imm")]
3549 (define_insn "*<optab>_rolsi3_uxtw"
3550 [(set (match_operand:DI 0 "register_operand" "=r")
3552 (LOGICAL:SI (rotate:SI
3553 (match_operand:SI 1 "register_operand" "r")
3554 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3555 (match_operand:SI 3 "register_operand" "r"))))]
3557 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3558 [(set_attr "type" "logic_shift_imm")]
3561 (define_insn "one_cmpl<mode>2"
3562 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3563 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3568 [(set_attr "type" "logic_reg,neon_logic")
3569 (set_attr "simd" "*,yes")]
3572 (define_insn "*one_cmpl_<optab><mode>2"
3573 [(set (match_operand:GPI 0 "register_operand" "=r")
3574 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3575 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3577 "mvn\\t%<w>0, %<w>1, <shift> %2"
3578 [(set_attr "type" "logic_shift_imm")]
3581 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3583 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3584 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3585 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3586 (match_operand:GPI 2 "register_operand" "r,w")))]
3589 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3590 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3591 [(set_attr "type" "logic_reg,neon_logic")
3592 (set_attr "simd" "*,yes")]
3595 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3596 [(set (match_operand:DI 0 "register_operand" "=r")
3598 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3599 (match_operand:SI 2 "register_operand" "r"))))]
3601 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3602 [(set_attr "type" "logic_reg")]
3605 (define_insn "*xor_one_cmplsidi3_ze"
3606 [(set (match_operand:DI 0 "register_operand" "=r")
3608 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3609 (match_operand:SI 2 "register_operand" "r")))))]
3611 "eon\\t%w0, %w1, %w2"
3612 [(set_attr "type" "logic_reg")]
3615 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3616 ;; eon does not operate on SIMD registers so the vector variant must be split.
3617 (define_insn_and_split "*xor_one_cmpl<mode>3"
3618 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3619 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3620 (match_operand:GPI 2 "register_operand" "r,w"))))]
3623 eon\\t%<w>0, %<w>1, %<w>2
3625 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3626 [(set (match_operand:GPI 0 "register_operand" "=w")
3627 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3628 (match_operand:GPI 2 "register_operand" "w")))
3629 (set (match_dup 0) (not:GPI (match_dup 0)))]
3631 [(set_attr "type" "logic_reg,multiple")
3632 (set_attr "simd" "*,yes")]
3635 (define_insn "*and_one_cmpl<mode>3_compare0"
3636 [(set (reg:CC_NZ CC_REGNUM)
3639 (match_operand:GPI 1 "register_operand" "r"))
3640 (match_operand:GPI 2 "register_operand" "r"))
3642 (set (match_operand:GPI 0 "register_operand" "=r")
3643 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3645 "bics\\t%<w>0, %<w>2, %<w>1"
3646 [(set_attr "type" "logics_reg")]
3649 ;; zero_extend version of above
3650 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3651 [(set (reg:CC_NZ CC_REGNUM)
3654 (match_operand:SI 1 "register_operand" "r"))
3655 (match_operand:SI 2 "register_operand" "r"))
3657 (set (match_operand:DI 0 "register_operand" "=r")
3658 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3660 "bics\\t%w0, %w2, %w1"
3661 [(set_attr "type" "logics_reg")]
3664 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3665 [(set (reg:CC_NZ CC_REGNUM)
3668 (match_operand:GPI 0 "register_operand" "r"))
3669 (match_operand:GPI 1 "register_operand" "r"))
3672 "bics\\t<w>zr, %<w>1, %<w>0"
3673 [(set_attr "type" "logics_reg")]
3676 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3677 [(set (match_operand:GPI 0 "register_operand" "=r")
3678 (LOGICAL:GPI (not:GPI
3680 (match_operand:GPI 1 "register_operand" "r")
3681 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3682 (match_operand:GPI 3 "register_operand" "r")))]
3684 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3685 [(set_attr "type" "logic_shift_imm")]
3688 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3689 [(set (match_operand:GPI 0 "register_operand" "=r")
3692 (match_operand:GPI 1 "register_operand" "r")
3693 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3694 (match_operand:GPI 3 "register_operand" "r"))))]
3696 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3697 [(set_attr "type" "logic_shift_imm")]
3700 ;; Zero-extend version of the above.
3701 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3702 [(set (match_operand:DI 0 "register_operand" "=r")
3706 (match_operand:SI 1 "register_operand" "r")
3707 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3708 (match_operand:SI 3 "register_operand" "r")))))]
3710 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3711 [(set_attr "type" "logic_shift_imm")]
3714 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3715 [(set (reg:CC_NZ CC_REGNUM)
3719 (match_operand:GPI 1 "register_operand" "r")
3720 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3721 (match_operand:GPI 3 "register_operand" "r"))
3723 (set (match_operand:GPI 0 "register_operand" "=r")
3726 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3728 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3729 [(set_attr "type" "logics_shift_imm")]
3732 ;; zero_extend version of above
3733 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3734 [(set (reg:CC_NZ CC_REGNUM)
3738 (match_operand:SI 1 "register_operand" "r")
3739 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3740 (match_operand:SI 3 "register_operand" "r"))
3742 (set (match_operand:DI 0 "register_operand" "=r")
3743 (zero_extend:DI (and:SI
3745 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3747 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3748 [(set_attr "type" "logics_shift_imm")]
3751 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3752 [(set (reg:CC_NZ CC_REGNUM)
3756 (match_operand:GPI 0 "register_operand" "r")
3757 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3758 (match_operand:GPI 2 "register_operand" "r"))
3761 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3762 [(set_attr "type" "logics_shift_imm")]
3765 (define_insn "clz<mode>2"
3766 [(set (match_operand:GPI 0 "register_operand" "=r")
3767 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3769 "clz\\t%<w>0, %<w>1"
3770 [(set_attr "type" "clz")]
3773 (define_expand "ffs<mode>2"
3774 [(match_operand:GPI 0 "register_operand")
3775 (match_operand:GPI 1 "register_operand")]
3778 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3779 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3781 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3782 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3783 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3788 (define_insn "clrsb<mode>2"
3789 [(set (match_operand:GPI 0 "register_operand" "=r")
3790 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3792 "cls\\t%<w>0, %<w>1"
3793 [(set_attr "type" "clz")]
3796 (define_insn "rbit<mode>2"
3797 [(set (match_operand:GPI 0 "register_operand" "=r")
3798 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3800 "rbit\\t%<w>0, %<w>1"
3801 [(set_attr "type" "rbit")]
3804 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3805 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3806 ;; expression and split after reload to enable scheduling them apart if
3809 (define_insn_and_split "ctz<mode>2"
3810 [(set (match_operand:GPI 0 "register_operand" "=r")
3811 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3817 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3818 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3822 (define_insn "*and<mode>_compare0"
3823 [(set (reg:CC_NZ CC_REGNUM)
3825 (match_operand:SHORT 0 "register_operand" "r")
3828 "tst\\t%<w>0, <short_mask>"
3829 [(set_attr "type" "alus_imm")]
3832 (define_insn "*ands<mode>_compare0"
3833 [(set (reg:CC_NZ CC_REGNUM)
3835 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3837 (set (match_operand:GPI 0 "register_operand" "=r")
3838 (zero_extend:GPI (match_dup 1)))]
3840 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3841 [(set_attr "type" "alus_imm")]
3844 (define_insn "*and<mode>3nr_compare0"
3845 [(set (reg:CC_NZ CC_REGNUM)
3847 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3848 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3854 [(set_attr "type" "logics_reg,logics_imm")]
3857 (define_insn "*and<mode>3nr_compare0_zextract"
3858 [(set (reg:CC_NZ CC_REGNUM)
3860 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3861 (match_operand:GPI 1 "const_int_operand" "n")
3862 (match_operand:GPI 2 "const_int_operand" "n"))
3864 "INTVAL (operands[1]) > 0
3865 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3866 <= GET_MODE_BITSIZE (<MODE>mode))
3867 && aarch64_bitmask_imm (
3868 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3873 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3874 return "tst\\t%<w>0, %1";
3876 [(set_attr "type" "logics_shift_imm")]
3879 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3880 [(set (reg:CC_NZ CC_REGNUM)
3883 (match_operand:GPI 0 "register_operand" "r")
3884 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3885 (match_operand:GPI 2 "register_operand" "r"))
3888 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3889 [(set_attr "type" "logics_shift_imm")]
3892 ;; -------------------------------------------------------------------
3894 ;; -------------------------------------------------------------------
3896 (define_expand "<optab><mode>3"
3897 [(set (match_operand:GPI 0 "register_operand")
3898 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3899 (match_operand:QI 2 "nonmemory_operand")))]
3902 if (CONST_INT_P (operands[2]))
3904 operands[2] = GEN_INT (INTVAL (operands[2])
3905 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3907 if (operands[2] == const0_rtx)
3909 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3916 (define_expand "ashl<mode>3"
3917 [(set (match_operand:SHORT 0 "register_operand")
3918 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3919 (match_operand:QI 2 "const_int_operand")))]
3922 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3924 if (operands[2] == const0_rtx)
3926 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3932 (define_expand "rotr<mode>3"
3933 [(set (match_operand:GPI 0 "register_operand")
3934 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3935 (match_operand:QI 2 "nonmemory_operand")))]
3938 if (CONST_INT_P (operands[2]))
3940 operands[2] = GEN_INT (INTVAL (operands[2])
3941 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3943 if (operands[2] == const0_rtx)
3945 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3952 (define_expand "rotl<mode>3"
3953 [(set (match_operand:GPI 0 "register_operand")
3954 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3955 (match_operand:QI 2 "nonmemory_operand")))]
3958 /* (SZ - cnt) % SZ == -cnt % SZ */
3959 if (CONST_INT_P (operands[2]))
3961 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3962 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3963 if (operands[2] == const0_rtx)
3965 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3970 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3975 ;; Logical left shift using SISD or Integer instruction
3976 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3977 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3979 (match_operand:GPI 1 "register_operand" "r,r,w,w")
3980 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3983 lsl\t%<w>0, %<w>1, %2
3984 lsl\t%<w>0, %<w>1, %<w>2
3985 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3986 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3987 [(set_attr "simd" "no,no,yes,yes")
3988 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3991 ;; Logical right shift using SISD or Integer instruction
3992 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3993 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3995 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3996 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3999 lsr\t%<w>0, %<w>1, %2
4000 lsr\t%<w>0, %<w>1, %<w>2
4001 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4004 [(set_attr "simd" "no,no,yes,yes,yes")
4005 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4009 [(set (match_operand:DI 0 "aarch64_simd_register")
4011 (match_operand:DI 1 "aarch64_simd_register")
4012 (match_operand:QI 2 "aarch64_simd_register")))]
4013 "TARGET_SIMD && reload_completed"
4015 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4017 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4019 operands[3] = gen_lowpart (QImode, operands[0]);
4024 [(set (match_operand:SI 0 "aarch64_simd_register")
4026 (match_operand:SI 1 "aarch64_simd_register")
4027 (match_operand:QI 2 "aarch64_simd_register")))]
4028 "TARGET_SIMD && reload_completed"
4030 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4032 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4034 operands[3] = gen_lowpart (QImode, operands[0]);
4038 ;; Arithmetic right shift using SISD or Integer instruction
4039 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4040 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4042 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4043 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4046 asr\t%<w>0, %<w>1, %2
4047 asr\t%<w>0, %<w>1, %<w>2
4048 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4051 [(set_attr "simd" "no,no,yes,yes,yes")
4052 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4056 [(set (match_operand:DI 0 "aarch64_simd_register")
4058 (match_operand:DI 1 "aarch64_simd_register")
4059 (match_operand:QI 2 "aarch64_simd_register")))]
4060 "TARGET_SIMD && reload_completed"
4062 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4064 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4066 operands[3] = gen_lowpart (QImode, operands[0]);
4071 [(set (match_operand:SI 0 "aarch64_simd_register")
4073 (match_operand:SI 1 "aarch64_simd_register")
4074 (match_operand:QI 2 "aarch64_simd_register")))]
4075 "TARGET_SIMD && reload_completed"
4077 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4079 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4081 operands[3] = gen_lowpart (QImode, operands[0]);
4085 (define_insn "*aarch64_sisd_ushl"
4086 [(set (match_operand:DI 0 "register_operand" "=w")
4087 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4088 (match_operand:QI 2 "register_operand" "w")]
4091 "ushl\t%d0, %d1, %d2"
4092 [(set_attr "simd" "yes")
4093 (set_attr "type" "neon_shift_reg")]
4096 (define_insn "*aarch64_ushl_2s"
4097 [(set (match_operand:SI 0 "register_operand" "=w")
4098 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4099 (match_operand:QI 2 "register_operand" "w")]
4102 "ushl\t%0.2s, %1.2s, %2.2s"
4103 [(set_attr "simd" "yes")
4104 (set_attr "type" "neon_shift_reg")]
4107 (define_insn "*aarch64_sisd_sshl"
4108 [(set (match_operand:DI 0 "register_operand" "=w")
4109 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4110 (match_operand:QI 2 "register_operand" "w")]
4113 "sshl\t%d0, %d1, %d2"
4114 [(set_attr "simd" "yes")
4115 (set_attr "type" "neon_shift_reg")]
4118 (define_insn "*aarch64_sshl_2s"
4119 [(set (match_operand:SI 0 "register_operand" "=w")
4120 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4121 (match_operand:QI 2 "register_operand" "w")]
4124 "sshl\t%0.2s, %1.2s, %2.2s"
4125 [(set_attr "simd" "yes")
4126 (set_attr "type" "neon_shift_reg")]
4129 (define_insn "*aarch64_sisd_neg_qi"
4130 [(set (match_operand:QI 0 "register_operand" "=w")
4131 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4135 [(set_attr "simd" "yes")
4136 (set_attr "type" "neon_neg")]
4140 (define_insn "*ror<mode>3_insn"
4141 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4143 (match_operand:GPI 1 "register_operand" "r,r")
4144 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4147 ror\\t%<w>0, %<w>1, %2
4148 ror\\t%<w>0, %<w>1, %<w>2"
4149 [(set_attr "type" "rotate_imm,shift_reg")]
4152 ;; zero_extend version of above
4153 (define_insn "*<optab>si3_insn_uxtw"
4154 [(set (match_operand:DI 0 "register_operand" "=r,r")
4155 (zero_extend:DI (SHIFT:SI
4156 (match_operand:SI 1 "register_operand" "r,r")
4157 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4160 <shift>\\t%w0, %w1, %2
4161 <shift>\\t%w0, %w1, %w2"
4162 [(set_attr "type" "bfx,shift_reg")]
4165 (define_insn "*<optab><mode>3_insn"
4166 [(set (match_operand:SHORT 0 "register_operand" "=r")
4167 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4168 (match_operand 2 "const_int_operand" "n")))]
4169 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4171 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4172 return "<bfshift>\t%w0, %w1, %2, %3";
4174 [(set_attr "type" "bfx")]
4177 (define_insn "*extr<mode>5_insn"
4178 [(set (match_operand:GPI 0 "register_operand" "=r")
4179 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4180 (match_operand 3 "const_int_operand" "n"))
4181 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4182 (match_operand 4 "const_int_operand" "n"))))]
4183 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4184 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4185 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4186 [(set_attr "type" "rotate_imm")]
4189 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4190 ;; so we have to match both orderings.
4191 (define_insn "*extr<mode>5_insn_alt"
4192 [(set (match_operand:GPI 0 "register_operand" "=r")
4193 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4194 (match_operand 4 "const_int_operand" "n"))
4195 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4196 (match_operand 3 "const_int_operand" "n"))))]
4197 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4198 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4199 == GET_MODE_BITSIZE (<MODE>mode))"
4200 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4201 [(set_attr "type" "rotate_imm")]
4204 ;; zero_extend version of the above
4205 (define_insn "*extrsi5_insn_uxtw"
4206 [(set (match_operand:DI 0 "register_operand" "=r")
4208 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4209 (match_operand 3 "const_int_operand" "n"))
4210 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4211 (match_operand 4 "const_int_operand" "n")))))]
4212 "UINTVAL (operands[3]) < 32 &&
4213 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4214 "extr\\t%w0, %w1, %w2, %4"
4215 [(set_attr "type" "rotate_imm")]
4218 (define_insn "*extrsi5_insn_uxtw_alt"
4219 [(set (match_operand:DI 0 "register_operand" "=r")
4221 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4222 (match_operand 4 "const_int_operand" "n"))
4223 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4224 (match_operand 3 "const_int_operand" "n")))))]
4225 "UINTVAL (operands[3]) < 32 &&
4226 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4227 "extr\\t%w0, %w1, %w2, %4"
4228 [(set_attr "type" "rotate_imm")]
4231 (define_insn "*ror<mode>3_insn"
4232 [(set (match_operand:GPI 0 "register_operand" "=r")
4233 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4234 (match_operand 2 "const_int_operand" "n")))]
4235 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4237 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4238 return "ror\\t%<w>0, %<w>1, %3";
4240 [(set_attr "type" "rotate_imm")]
4243 ;; zero_extend version of the above
4244 (define_insn "*rorsi3_insn_uxtw"
4245 [(set (match_operand:DI 0 "register_operand" "=r")
4247 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4248 (match_operand 2 "const_int_operand" "n"))))]
4249 "UINTVAL (operands[2]) < 32"
4251 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4252 return "ror\\t%w0, %w1, %3";
4254 [(set_attr "type" "rotate_imm")]
4257 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4258 [(set (match_operand:GPI 0 "register_operand" "=r")
4260 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4261 (match_operand 2 "const_int_operand" "n"))))]
4262 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4264 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4265 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4267 [(set_attr "type" "bfx")]
4270 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4271 [(set (match_operand:GPI 0 "register_operand" "=r")
4273 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4274 (match_operand 2 "const_int_operand" "n"))))]
4275 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4277 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4278 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4280 [(set_attr "type" "bfx")]
4283 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4284 [(set (match_operand:GPI 0 "register_operand" "=r")
4286 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4287 (match_operand 2 "const_int_operand" "n"))))]
4288 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4290 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4291 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4293 [(set_attr "type" "bfx")]
4296 ;; -------------------------------------------------------------------
4298 ;; -------------------------------------------------------------------
4300 (define_expand "<optab>"
4301 [(set (match_operand:DI 0 "register_operand" "=r")
4302 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4304 "aarch64_simd_shift_imm_offset_di")
4305 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4308 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4309 1, GET_MODE_BITSIZE (DImode) - 1))
4315 (define_insn "*<optab><mode>"
4316 [(set (match_operand:GPI 0 "register_operand" "=r")
4317 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4319 "aarch64_simd_shift_imm_offset_<mode>" "n")
4321 "aarch64_simd_shift_imm_<mode>" "n")))]
4322 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4323 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4324 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4325 [(set_attr "type" "bfx")]
4328 ;; Bitfield Insert (insv)
4329 (define_expand "insv<mode>"
4330 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4331 (match_operand 1 "const_int_operand")
4332 (match_operand 2 "const_int_operand"))
4333 (match_operand:GPI 3 "general_operand"))]
4336 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4337 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4338 rtx value = operands[3];
4340 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4343 if (CONST_INT_P (value))
4345 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4347 /* Prefer AND/OR for inserting all zeros or all ones. */
4348 if ((UINTVAL (value) & mask) == 0
4349 || (UINTVAL (value) & mask) == mask)
4352 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4353 if (width == 16 && (pos % 16) == 0)
4356 operands[3] = force_reg (<MODE>mode, value);
4359 (define_insn "*insv_reg<mode>"
4360 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4361 (match_operand 1 "const_int_operand" "n")
4362 (match_operand 2 "const_int_operand" "n"))
4363 (match_operand:GPI 3 "register_operand" "r"))]
4364 "!(UINTVAL (operands[1]) == 0
4365 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4366 > GET_MODE_BITSIZE (<MODE>mode)))"
4367 "bfi\\t%<w>0, %<w>3, %2, %1"
4368 [(set_attr "type" "bfm")]
4371 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4372 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4373 (match_operand 1 "const_int_operand" "n")
4374 (match_operand 2 "const_int_operand" "n"))
4375 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4376 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4377 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4378 [(set_attr "type" "bfm")]
4381 (define_insn "*extr_insv_lower_reg<mode>"
4382 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4383 (match_operand 1 "const_int_operand" "n")
4385 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4387 (match_operand 3 "const_int_operand" "n")))]
4388 "!(UINTVAL (operands[1]) == 0
4389 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4390 > GET_MODE_BITSIZE (<MODE>mode)))"
4391 "bfxil\\t%<w>0, %<w>2, %3, %1"
4392 [(set_attr "type" "bfm")]
4395 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4396 [(set (match_operand:GPI 0 "register_operand" "=r")
4397 (ashift:GPI (ANY_EXTEND:GPI
4398 (match_operand:ALLX 1 "register_operand" "r"))
4399 (match_operand 2 "const_int_operand" "n")))]
4400 "UINTVAL (operands[2]) < <GPI:sizen>"
4402 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4403 ? GEN_INT (<ALLX:sizen>)
4404 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4405 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4407 [(set_attr "type" "bfx")]
4410 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4412 (define_insn "*andim_ashift<mode>_bfiz"
4413 [(set (match_operand:GPI 0 "register_operand" "=r")
4414 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4415 (match_operand 2 "const_int_operand" "n"))
4416 (match_operand 3 "const_int_operand" "n")))]
4417 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4418 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4419 [(set_attr "type" "bfx")]
4422 (define_insn "bswap<mode>2"
4423 [(set (match_operand:GPI 0 "register_operand" "=r")
4424 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4426 "rev\\t%<w>0, %<w>1"
4427 [(set_attr "type" "rev")]
4430 (define_insn "bswaphi2"
4431 [(set (match_operand:HI 0 "register_operand" "=r")
4432 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4435 [(set_attr "type" "rev")]
4438 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4439 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4440 ;; each valid permutation.
4442 (define_insn "rev16<mode>2"
4443 [(set (match_operand:GPI 0 "register_operand" "=r")
4444 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4446 (match_operand:GPI 3 "const_int_operand" "n"))
4447 (and:GPI (lshiftrt:GPI (match_dup 1)
4449 (match_operand:GPI 2 "const_int_operand" "n"))))]
4450 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4451 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4452 "rev16\\t%<w>0, %<w>1"
4453 [(set_attr "type" "rev")]
4456 (define_insn "rev16<mode>2_alt"
4457 [(set (match_operand:GPI 0 "register_operand" "=r")
4458 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4460 (match_operand:GPI 2 "const_int_operand" "n"))
4461 (and:GPI (ashift:GPI (match_dup 1)
4463 (match_operand:GPI 3 "const_int_operand" "n"))))]
4464 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4465 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4466 "rev16\\t%<w>0, %<w>1"
4467 [(set_attr "type" "rev")]
4470 ;; zero_extend version of above
4471 (define_insn "*bswapsi2_uxtw"
4472 [(set (match_operand:DI 0 "register_operand" "=r")
4473 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4476 [(set_attr "type" "rev")]
4479 ;; -------------------------------------------------------------------
4480 ;; Floating-point intrinsics
4481 ;; -------------------------------------------------------------------
4483 ;; frint floating-point round to integral standard patterns.
4484 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4486 (define_insn "<frint_pattern><mode>2"
4487 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4488 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4491 "frint<frint_suffix>\\t%<s>0, %<s>1"
4492 [(set_attr "type" "f_rint<stype>")]
4495 ;; frcvt floating-point round to integer and convert standard patterns.
4496 ;; Expands to lbtrunc, lceil, lfloor, lround.
4497 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4498 [(set (match_operand:GPI 0 "register_operand" "=r")
4500 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4503 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4504 [(set_attr "type" "f_cvtf2i")]
4507 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4508 [(set (match_operand:GPI 0 "register_operand" "=r")
4511 (match_operand:GPF 1 "register_operand" "w")
4512 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4514 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4515 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4517 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4519 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4520 output_asm_insn (buf, operands);
4523 [(set_attr "type" "f_cvtf2i")]
4528 (define_insn "fma<mode>4"
4529 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4530 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4531 (match_operand:GPF_F16 2 "register_operand" "w")
4532 (match_operand:GPF_F16 3 "register_operand" "w")))]
4534 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4535 [(set_attr "type" "fmac<stype>")]
4538 (define_insn "fnma<mode>4"
4539 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4541 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4542 (match_operand:GPF_F16 2 "register_operand" "w")
4543 (match_operand:GPF_F16 3 "register_operand" "w")))]
4545 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4546 [(set_attr "type" "fmac<stype>")]
4549 (define_insn "fms<mode>4"
4550 [(set (match_operand:GPF 0 "register_operand" "=w")
4551 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4552 (match_operand:GPF 2 "register_operand" "w")
4553 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4555 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4556 [(set_attr "type" "fmac<s>")]
4559 (define_insn "fnms<mode>4"
4560 [(set (match_operand:GPF 0 "register_operand" "=w")
4561 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4562 (match_operand:GPF 2 "register_operand" "w")
4563 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4565 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4566 [(set_attr "type" "fmac<s>")]
4569 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4570 (define_insn "*fnmadd<mode>4"
4571 [(set (match_operand:GPF 0 "register_operand" "=w")
4572 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4573 (match_operand:GPF 2 "register_operand" "w")
4574 (match_operand:GPF 3 "register_operand" "w"))))]
4575 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4576 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4577 [(set_attr "type" "fmac<s>")]
4580 ;; -------------------------------------------------------------------
4581 ;; Floating-point conversions
4582 ;; -------------------------------------------------------------------
4584 (define_insn "extendsfdf2"
4585 [(set (match_operand:DF 0 "register_operand" "=w")
4586 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4589 [(set_attr "type" "f_cvt")]
4592 (define_insn "extendhfsf2"
4593 [(set (match_operand:SF 0 "register_operand" "=w")
4594 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4597 [(set_attr "type" "f_cvt")]
4600 (define_insn "extendhfdf2"
4601 [(set (match_operand:DF 0 "register_operand" "=w")
4602 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4605 [(set_attr "type" "f_cvt")]
4608 (define_insn "truncdfsf2"
4609 [(set (match_operand:SF 0 "register_operand" "=w")
4610 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4613 [(set_attr "type" "f_cvt")]
4616 (define_insn "truncsfhf2"
4617 [(set (match_operand:HF 0 "register_operand" "=w")
4618 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4621 [(set_attr "type" "f_cvt")]
4624 (define_insn "truncdfhf2"
4625 [(set (match_operand:HF 0 "register_operand" "=w")
4626 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4629 [(set_attr "type" "f_cvt")]
4632 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4633 [(set (match_operand:GPI 0 "register_operand" "=r")
4634 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4636 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4637 [(set_attr "type" "f_cvtf2i")]
4640 (define_insn "<optab><fcvt_target><GPF:mode>2"
4641 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4642 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4645 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4646 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4647 [(set_attr "simd" "yes,no")
4648 (set_attr "fp" "no,yes")
4649 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4652 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4653 [(set (match_operand:GPF 0 "register_operand" "=w")
4654 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4656 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4657 [(set_attr "type" "f_cvti2f")]
4660 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4661 ;; midend will arrange for an SImode conversion to HFmode to first go
4662 ;; through DFmode, then to HFmode. But first it will try converting
4663 ;; to DImode then down, which would match our DImode pattern below and
4664 ;; give very poor code-generation. So, we must provide our own emulation
4665 ;; of the mid-end logic.
4667 (define_insn "aarch64_fp16_<optab><mode>hf2"
4668 [(set (match_operand:HF 0 "register_operand" "=w")
4669 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4671 "<su_optab>cvtf\t%h0, %<w>1"
4672 [(set_attr "type" "f_cvti2f")]
4675 (define_expand "<optab>sihf2"
4676 [(set (match_operand:HF 0 "register_operand")
4677 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4680 if (TARGET_FP_F16INST)
4681 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4684 rtx convert_target = gen_reg_rtx (DFmode);
4685 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4686 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4692 ;; For DImode there is no wide enough floating-point mode that we
4693 ;; can convert through natively (TFmode would work, but requires a library
4694 ;; call). However, we know that any value >= 65504 will be rounded
4695 ;; to infinity on conversion. This is well within the range of SImode, so
4697 ;; Saturate to SImode.
4698 ;; Convert from that to DFmode
4699 ;; Convert from that to HFmode (phew!).
4700 ;; Note that the saturation to SImode requires the SIMD extensions. If
4701 ;; we ever need to provide this pattern where the SIMD extensions are not
4702 ;; available, we would need a different approach.
4704 (define_expand "<optab>dihf2"
4705 [(set (match_operand:HF 0 "register_operand")
4706 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4707 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4709 if (TARGET_FP_F16INST)
4710 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4713 rtx sat_target = gen_reg_rtx (SImode);
4714 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4715 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4722 ;; Convert between fixed-point and floating-point (scalar modes)
4724 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4725 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4726 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4727 (match_operand:SI 2 "immediate_operand" "i, i")]
4731 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4732 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4733 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4734 (set_attr "fp" "yes, *")
4735 (set_attr "simd" "*, yes")]
4738 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4739 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4740 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4741 (match_operand:SI 2 "immediate_operand" "i, i")]
4745 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4746 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4747 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4748 (set_attr "fp" "yes, *")
4749 (set_attr "simd" "*, yes")]
4752 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4753 [(set (match_operand:GPI 0 "register_operand" "=r")
4754 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4755 (match_operand:SI 2 "immediate_operand" "i")]
4758 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4759 [(set_attr "type" "f_cvtf2i")]
4762 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4763 [(set (match_operand:HF 0 "register_operand" "=w")
4764 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4765 (match_operand:SI 2 "immediate_operand" "i")]
4768 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4769 [(set_attr "type" "f_cvti2f")]
4772 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4773 [(set (match_operand:HI 0 "register_operand" "=w")
4774 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4775 (match_operand:SI 2 "immediate_operand" "i")]
4778 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4779 [(set_attr "type" "neon_fp_to_int_s")]
4782 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4783 [(set (match_operand:HF 0 "register_operand" "=w")
4784 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4785 (match_operand:SI 2 "immediate_operand" "i")]
4788 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4789 [(set_attr "type" "neon_int_to_fp_s")]
4792 ;; -------------------------------------------------------------------
4793 ;; Floating-point arithmetic
4794 ;; -------------------------------------------------------------------
4796 (define_insn "add<mode>3"
4797 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4799 (match_operand:GPF_F16 1 "register_operand" "w")
4800 (match_operand:GPF_F16 2 "register_operand" "w")))]
4802 "fadd\\t%<s>0, %<s>1, %<s>2"
4803 [(set_attr "type" "fadd<stype>")]
4806 (define_insn "sub<mode>3"
4807 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4809 (match_operand:GPF_F16 1 "register_operand" "w")
4810 (match_operand:GPF_F16 2 "register_operand" "w")))]
4812 "fsub\\t%<s>0, %<s>1, %<s>2"
4813 [(set_attr "type" "fadd<stype>")]
4816 (define_insn "mul<mode>3"
4817 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4819 (match_operand:GPF_F16 1 "register_operand" "w")
4820 (match_operand:GPF_F16 2 "register_operand" "w")))]
4822 "fmul\\t%<s>0, %<s>1, %<s>2"
4823 [(set_attr "type" "fmul<stype>")]
4826 (define_insn "*fnmul<mode>3"
4827 [(set (match_operand:GPF 0 "register_operand" "=w")
4829 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4830 (match_operand:GPF 2 "register_operand" "w")))]
4831 "TARGET_FLOAT && !flag_rounding_math"
4832 "fnmul\\t%<s>0, %<s>1, %<s>2"
4833 [(set_attr "type" "fmul<s>")]
4836 (define_insn "*fnmul<mode>3"
4837 [(set (match_operand:GPF 0 "register_operand" "=w")
4839 (match_operand:GPF 1 "register_operand" "w")
4840 (match_operand:GPF 2 "register_operand" "w"))))]
4842 "fnmul\\t%<s>0, %<s>1, %<s>2"
4843 [(set_attr "type" "fmul<s>")]
4846 (define_expand "div<mode>3"
4847 [(set (match_operand:GPF_F16 0 "register_operand")
4848 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4849 (match_operand:GPF_F16 2 "register_operand")))]
4852 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4855 operands[1] = force_reg (<MODE>mode, operands[1]);
4858 (define_insn "*div<mode>3"
4859 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4860 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4861 (match_operand:GPF_F16 2 "register_operand" "w")))]
4863 "fdiv\\t%<s>0, %<s>1, %<s>2"
4864 [(set_attr "type" "fdiv<stype>")]
4867 (define_insn "neg<mode>2"
4868 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4869 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4871 "fneg\\t%<s>0, %<s>1"
4872 [(set_attr "type" "ffarith<stype>")]
4875 (define_expand "sqrt<mode>2"
4876 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4880 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4884 (define_insn "*sqrt<mode>2"
4885 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4886 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4888 "fsqrt\\t%<s>0, %<s>1"
4889 [(set_attr "type" "fsqrt<stype>")]
4892 (define_insn "abs<mode>2"
4893 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4894 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4896 "fabs\\t%<s>0, %<s>1"
4897 [(set_attr "type" "ffarith<stype>")]
4900 ;; Given that smax/smin do not specify the result when either input is NaN,
4901 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4904 (define_insn "smax<mode>3"
4905 [(set (match_operand:GPF 0 "register_operand" "=w")
4906 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4907 (match_operand:GPF 2 "register_operand" "w")))]
4909 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4910 [(set_attr "type" "f_minmax<s>")]
4913 (define_insn "smin<mode>3"
4914 [(set (match_operand:GPF 0 "register_operand" "=w")
4915 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4916 (match_operand:GPF 2 "register_operand" "w")))]
4918 "fminnm\\t%<s>0, %<s>1, %<s>2"
4919 [(set_attr "type" "f_minmax<s>")]
4922 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4923 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4924 ;; which implement the IEEE fmax ()/fmin () functions.
4925 (define_insn "<maxmin_uns><mode>3"
4926 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4927 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4928 (match_operand:GPF_F16 2 "register_operand" "w")]
4931 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4932 [(set_attr "type" "f_minmax<stype>")]
4935 ;; For copysign (x, y), we want to generate:
4937 ;; LDR d2, #(1 << 63)
4938 ;; BSL v2.8b, [y], [x]
4940 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4941 ;; aarch64_simd_bsldf will select the best suited of these instructions
4942 ;; to generate based on register allocation, and knows how to partially
4943 ;; constant fold based on the values of X and Y, so expand through that.
4945 (define_expand "copysigndf3"
4946 [(match_operand:DF 0 "register_operand")
4947 (match_operand:DF 1 "register_operand")
4948 (match_operand:DF 2 "register_operand")]
4949 "TARGET_FLOAT && TARGET_SIMD"
4951 rtx mask = gen_reg_rtx (DImode);
4952 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4953 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4954 operands[2], operands[1]));
4959 ;; As above, but we must first get to a 64-bit value if we wish to use
4960 ;; aarch64_simd_bslv2sf.
4962 (define_expand "copysignsf3"
4963 [(match_operand:SF 0 "register_operand")
4964 (match_operand:SF 1 "register_operand")
4965 (match_operand:SF 2 "register_operand")]
4966 "TARGET_FLOAT && TARGET_SIMD"
4968 rtx mask = gen_reg_rtx (DImode);
4970 /* Juggle modes to get us in to a vector mode for BSL. */
4971 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4972 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4973 rtx tmp = gen_reg_rtx (V2SFmode);
4974 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4975 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4976 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4981 ;; -------------------------------------------------------------------
4983 ;; -------------------------------------------------------------------
4984 ;; Reload Scalar Floating point modes from constant pool.
4985 ;; The AArch64 port doesn't have __int128 constant move support.
4986 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4987 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4988 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4989 (clobber (match_operand:P 2 "register_operand" "=&r"))]
4990 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4992 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4993 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4998 ;; Reload Vector modes from constant pool.
4999 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5000 [(set (match_operand:VALL 0 "register_operand" "=w")
5001 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5002 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5003 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
5005 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5006 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5011 (define_expand "aarch64_reload_mov<mode>"
5012 [(set (match_operand:TX 0 "register_operand" "=w")
5013 (match_operand:TX 1 "register_operand" "w"))
5014 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5018 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5019 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5020 gen_aarch64_movtilow_tilow (op0, op1);
5021 gen_aarch64_movdi_tihigh (operands[2], op1);
5022 gen_aarch64_movtihigh_di (op0, operands[2]);
5027 ;; The following secondary reload helpers patterns are invoked
5028 ;; after or during reload as we don't want these patterns to start
5029 ;; kicking in during the combiner.
5031 (define_insn "aarch64_movdi_<mode>low"
5032 [(set (match_operand:DI 0 "register_operand" "=r")
5033 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5034 (const_int 64) (const_int 0)))]
5035 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5037 [(set_attr "type" "f_mrc")
5038 (set_attr "length" "4")
5041 (define_insn "aarch64_movdi_<mode>high"
5042 [(set (match_operand:DI 0 "register_operand" "=r")
5043 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5044 (const_int 64) (const_int 64)))]
5045 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5046 "fmov\\t%x0, %1.d[1]"
5047 [(set_attr "type" "f_mrc")
5048 (set_attr "length" "4")
5051 (define_insn "aarch64_mov<mode>high_di"
5052 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5053 (const_int 64) (const_int 64))
5054 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5055 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5056 "fmov\\t%0.d[1], %x1"
5057 [(set_attr "type" "f_mcr")
5058 (set_attr "length" "4")
5061 (define_insn "aarch64_mov<mode>low_di"
5062 [(set (match_operand:TX 0 "register_operand" "=w")
5063 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5064 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5066 [(set_attr "type" "f_mcr")
5067 (set_attr "length" "4")
5070 (define_insn "aarch64_movtilow_tilow"
5071 [(set (match_operand:TI 0 "register_operand" "=w")
5073 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5074 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5076 [(set_attr "type" "fmov")
5077 (set_attr "length" "4")
5080 ;; There is a deliberate reason why the parameters of high and lo_sum's
5081 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5082 ;; and lo_sum's to be used with the labels defining the jump tables in
5085 (define_expand "add_losym"
5086 [(set (match_operand 0 "register_operand" "=r")
5087 (lo_sum (match_operand 1 "register_operand" "r")
5088 (match_operand 2 "aarch64_valid_symref" "S")))]
5091 machine_mode mode = GET_MODE (operands[0]);
5093 emit_insn ((mode == DImode
5095 : gen_add_losym_si) (operands[0],
5101 (define_insn "add_losym_<mode>"
5102 [(set (match_operand:P 0 "register_operand" "=r")
5103 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5104 (match_operand 2 "aarch64_valid_symref" "S")))]
5106 "add\\t%<w>0, %<w>1, :lo12:%a2"
5107 [(set_attr "type" "alu_imm")]
5110 (define_insn "ldr_got_small_<mode>"
5111 [(set (match_operand:PTR 0 "register_operand" "=r")
5112 (unspec:PTR [(mem:PTR (lo_sum:PTR
5113 (match_operand:PTR 1 "register_operand" "r")
5114 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5115 UNSPEC_GOTSMALLPIC))]
5117 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5118 [(set_attr "type" "load1")]
5121 (define_insn "ldr_got_small_sidi"
5122 [(set (match_operand:DI 0 "register_operand" "=r")
5124 (unspec:SI [(mem:SI (lo_sum:DI
5125 (match_operand:DI 1 "register_operand" "r")
5126 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5127 UNSPEC_GOTSMALLPIC)))]
5129 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5130 [(set_attr "type" "load1")]
5133 (define_insn "ldr_got_small_28k_<mode>"
5134 [(set (match_operand:PTR 0 "register_operand" "=r")
5135 (unspec:PTR [(mem:PTR (lo_sum:PTR
5136 (match_operand:PTR 1 "register_operand" "r")
5137 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5138 UNSPEC_GOTSMALLPIC28K))]
5140 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5141 [(set_attr "type" "load1")]
5144 (define_insn "ldr_got_small_28k_sidi"
5145 [(set (match_operand:DI 0 "register_operand" "=r")
5147 (unspec:SI [(mem:SI (lo_sum:DI
5148 (match_operand:DI 1 "register_operand" "r")
5149 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5150 UNSPEC_GOTSMALLPIC28K)))]
5152 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5153 [(set_attr "type" "load1")]
5156 (define_insn "ldr_got_tiny"
5157 [(set (match_operand:DI 0 "register_operand" "=r")
5158 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5159 UNSPEC_GOTTINYPIC))]
5162 [(set_attr "type" "load1")]
5165 (define_insn "aarch64_load_tp_hard"
5166 [(set (match_operand:DI 0 "register_operand" "=r")
5167 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5169 "mrs\\t%0, tpidr_el0"
5170 [(set_attr "type" "mrs")]
5173 ;; The TLS ABI specifically requires that the compiler does not schedule
5174 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5175 ;; Therefore we treat the stubs as an atomic sequence.
5176 (define_expand "tlsgd_small"
5177 [(parallel [(set (match_operand 0 "register_operand" "")
5178 (call (mem:DI (match_dup 2)) (const_int 1)))
5179 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5180 (clobber (reg:DI LR_REGNUM))])]
5183 operands[2] = aarch64_tls_get_addr ();
5186 (define_insn "*tlsgd_small"
5187 [(set (match_operand 0 "register_operand" "")
5188 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5189 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5190 (clobber (reg:DI LR_REGNUM))
5193 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5194 [(set_attr "type" "call")
5195 (set_attr "length" "16")])
5197 (define_insn "tlsie_small_<mode>"
5198 [(set (match_operand:PTR 0 "register_operand" "=r")
5199 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5200 UNSPEC_GOTSMALLTLS))]
5202 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5203 [(set_attr "type" "load1")
5204 (set_attr "length" "8")]
5207 (define_insn "tlsie_small_sidi"
5208 [(set (match_operand:DI 0 "register_operand" "=r")
5210 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5211 UNSPEC_GOTSMALLTLS)))]
5213 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5214 [(set_attr "type" "load1")
5215 (set_attr "length" "8")]
5218 (define_insn "tlsie_tiny_<mode>"
5219 [(set (match_operand:PTR 0 "register_operand" "=&r")
5220 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5221 (match_operand:PTR 2 "register_operand" "r")]
5222 UNSPEC_GOTTINYTLS))]
5224 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5225 [(set_attr "type" "multiple")
5226 (set_attr "length" "8")]
5229 (define_insn "tlsie_tiny_sidi"
5230 [(set (match_operand:DI 0 "register_operand" "=&r")
5232 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5233 (match_operand:DI 2 "register_operand" "r")
5235 UNSPEC_GOTTINYTLS)))]
5237 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5238 [(set_attr "type" "multiple")
5239 (set_attr "length" "8")]
5242 (define_insn "tlsle12_<mode>"
5243 [(set (match_operand:P 0 "register_operand" "=r")
5244 (unspec:P [(match_operand:P 1 "register_operand" "r")
5245 (match_operand 2 "aarch64_tls_le_symref" "S")]
5248 "add\\t%<w>0, %<w>1, #%L2";
5249 [(set_attr "type" "alu_sreg")
5250 (set_attr "length" "4")]
5253 (define_insn "tlsle24_<mode>"
5254 [(set (match_operand:P 0 "register_operand" "=r")
5255 (unspec:P [(match_operand:P 1 "register_operand" "r")
5256 (match_operand 2 "aarch64_tls_le_symref" "S")]
5259 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5260 [(set_attr "type" "multiple")
5261 (set_attr "length" "8")]
5264 (define_insn "tlsle32_<mode>"
5265 [(set (match_operand:P 0 "register_operand" "=r")
5266 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5269 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5270 [(set_attr "type" "multiple")
5271 (set_attr "length" "8")]
5274 (define_insn "tlsle48_<mode>"
5275 [(set (match_operand:P 0 "register_operand" "=r")
5276 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5279 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5280 [(set_attr "type" "multiple")
5281 (set_attr "length" "12")]
5284 (define_insn "tlsdesc_small_<mode>"
5285 [(set (reg:PTR R0_REGNUM)
5286 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5288 (clobber (reg:DI LR_REGNUM))
5289 (clobber (reg:CC CC_REGNUM))
5290 (clobber (match_scratch:DI 1 "=r"))]
5292 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5293 [(set_attr "type" "call")
5294 (set_attr "length" "16")])
5296 (define_insn "stack_tie"
5297 [(set (mem:BLK (scratch))
5298 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5299 (match_operand:DI 1 "register_operand" "rk")]
5303 [(set_attr "length" "0")]
5306 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5307 ;; all of memory. This blocks insns from being moved across this point.
5309 (define_insn "blockage"
5310 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5313 [(set_attr "length" "0")
5314 (set_attr "type" "block")]
5317 (define_insn "probe_stack_range_<PTR:mode>"
5318 [(set (match_operand:PTR 0 "register_operand" "=r")
5319 (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5320 (match_operand:PTR 2 "register_operand" "r")]
5321 UNSPECV_PROBE_STACK_RANGE))]
5324 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5326 [(set_attr "length" "32")]
5329 ;; Named pattern for expanding thread pointer reference.
5330 (define_expand "get_thread_pointerdi"
5331 [(match_operand:DI 0 "register_operand" "=r")]
5334 rtx tmp = aarch64_load_tp (operands[0]);
5335 if (tmp != operands[0])
5336 emit_move_insn (operands[0], tmp);
5340 ;; Named patterns for stack smashing protection.
5341 (define_expand "stack_protect_set"
5342 [(match_operand 0 "memory_operand")
5343 (match_operand 1 "memory_operand")]
5346 machine_mode mode = GET_MODE (operands[0]);
5348 emit_insn ((mode == DImode
5349 ? gen_stack_protect_set_di
5350 : gen_stack_protect_set_si) (operands[0], operands[1]));
5354 (define_insn "stack_protect_set_<mode>"
5355 [(set (match_operand:PTR 0 "memory_operand" "=m")
5356 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5358 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5360 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5361 [(set_attr "length" "12")
5362 (set_attr "type" "multiple")])
5364 (define_expand "stack_protect_test"
5365 [(match_operand 0 "memory_operand")
5366 (match_operand 1 "memory_operand")
5371 machine_mode mode = GET_MODE (operands[0]);
5373 result = gen_reg_rtx(mode);
5375 emit_insn ((mode == DImode
5376 ? gen_stack_protect_test_di
5377 : gen_stack_protect_test_si) (result,
5382 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5383 result, const0_rtx, operands[2]));
5385 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5386 result, const0_rtx, operands[2]));
5390 (define_insn "stack_protect_test_<mode>"
5391 [(set (match_operand:PTR 0 "register_operand" "=r")
5392 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5393 (match_operand:PTR 2 "memory_operand" "m")]
5395 (clobber (match_scratch:PTR 3 "=&r"))]
5397 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5398 [(set_attr "length" "12")
5399 (set_attr "type" "multiple")])
5401 ;; Write Floating-point Control Register.
5402 (define_insn "set_fpcr"
5403 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5406 [(set_attr "type" "mrs")])
5408 ;; Read Floating-point Control Register.
5409 (define_insn "get_fpcr"
5410 [(set (match_operand:SI 0 "register_operand" "=r")
5411 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5414 [(set_attr "type" "mrs")])
5416 ;; Write Floating-point Status Register.
5417 (define_insn "set_fpsr"
5418 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5421 [(set_attr "type" "mrs")])
5423 ;; Read Floating-point Status Register.
5424 (define_insn "get_fpsr"
5425 [(set (match_operand:SI 0 "register_operand" "=r")
5426 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5429 [(set_attr "type" "mrs")])
5432 ;; Define the subtract-one-and-jump insns so loop.c
5433 ;; knows what to generate.
5434 (define_expand "doloop_end"
5435 [(use (match_operand 0 "" "")) ; loop pseudo
5436 (use (match_operand 1 "" ""))] ; label
5437 "optimize > 0 && flag_modulo_sched"
5446 /* Currently SMS relies on the do-loop pattern to recognize loops
5447 where (1) the control part consists of all insns defining and/or
5448 using a certain 'count' register and (2) the loop count can be
5449 adjusted by modifying this register prior to the loop.
5450 ??? The possible introduction of a new block to initialize the
5451 new IV can potentially affect branch optimizations. */
5453 if (GET_MODE (operands[0]) != DImode)
5457 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5459 cmp = XVECEXP (PATTERN (insn), 0, 0);
5460 cc_reg = SET_DEST (cmp);
5461 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5462 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5463 emit_jump_insn (gen_rtx_SET (pc_rtx,
5464 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5470 (include "aarch64-simd.md")
5472 ;; Atomic Operations
5473 (include "atomics.md")
5475 ;; ldp/stp peephole patterns
5476 (include "aarch64-ldpstp.md")