1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
62 (LAST_SAVED_REGNUM 63)
69 (define_c_enum "unspec" [
145 (define_c_enum "unspecv" [
146 UNSPECV_EH_RETURN ; Represent EH_RETURN
147 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
148 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
149 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
150 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
151 UNSPECV_BLOCKAGE ; Represent a blockage
152 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
156 ;; If further include files are added the defintion of MD_INCLUDES
159 (include "constraints.md")
160 (include "predicates.md")
161 (include "iterators.md")
163 ;; -------------------------------------------------------------------
164 ;; Instruction types and attributes
165 ;; -------------------------------------------------------------------
167 ; The "type" attribute is included here from AArch32 backend to be able
168 ; to share pipeline descriptions.
169 (include "../arm/types.md")
171 ;; It is important to set the fp or simd attributes to yes when a pattern
172 ;; alternative uses the FP or SIMD register files, usually signified by use of
173 ;; the 'w' constraint. This will ensure that the alternative will be
174 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
175 ;; architecture extensions. If all the alternatives in a pattern use the
176 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
179 ;; Attribute that specifies whether or not the instruction touches fp
180 ;; registers. When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_FLOAT.
182 (define_attr "fp" "no,yes" (const_string "no"))
184 ;; Attribute that specifies whether or not the instruction touches simd
185 ;; registers. When this is set to yes for an alternative, that alternative
186 ;; will be disabled when !TARGET_SIMD.
187 (define_attr "simd" "no,yes" (const_string "no"))
189 (define_attr "length" ""
192 ;; Attribute that controls whether an alternative is enabled or not.
193 ;; Currently it is only used to disable alternatives which touch fp or simd
194 ;; registers when -mgeneral-regs-only is specified.
195 (define_attr "enabled" "no,yes"
197 (and (eq_attr "fp" "yes")
198 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
199 (and (eq_attr "simd" "yes")
200 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
202 ] (const_string "yes")))
204 ;; Attribute that specifies whether we are dealing with a branch to a
205 ;; label that is far away, i.e. further away than the maximum/minimum
206 ;; representable in a signed 21-bits number.
209 (define_attr "far_branch" "" (const_int 0))
211 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
212 ;; no predicated insns.
213 (define_attr "predicated" "yes,no" (const_string "no"))
215 ;; -------------------------------------------------------------------
216 ;; Pipeline descriptions and scheduling
217 ;; -------------------------------------------------------------------
220 (include "aarch64-tune.md")
223 (include "../arm/cortex-a53.md")
224 (include "../arm/cortex-a57.md")
225 (include "../arm/exynos-m1.md")
226 (include "thunderx.md")
227 (include "../arm/xgene1.md")
228 (include "thunderx2t99.md")
230 ;; -------------------------------------------------------------------
231 ;; Jumps and other miscellaneous insns
232 ;; -------------------------------------------------------------------
234 (define_insn "indirect_jump"
235 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
238 [(set_attr "type" "branch")]
242 [(set (pc) (label_ref (match_operand 0 "" "")))]
245 [(set_attr "type" "branch")]
248 (define_expand "cbranch<mode>4"
249 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
250 [(match_operand:GPI 1 "register_operand" "")
251 (match_operand:GPI 2 "aarch64_plus_operand" "")])
252 (label_ref (match_operand 3 "" ""))
256 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
258 operands[2] = const0_rtx;
262 (define_expand "cbranch<mode>4"
263 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
264 [(match_operand:GPF 1 "register_operand" "")
265 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
266 (label_ref (match_operand 3 "" ""))
270 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
272 operands[2] = const0_rtx;
276 (define_expand "cbranchcc4"
277 [(set (pc) (if_then_else
278 (match_operator 0 "aarch64_comparison_operator"
279 [(match_operand 1 "cc_register" "")
280 (match_operand 2 "const0_operand")])
281 (label_ref (match_operand 3 "" ""))
286 (define_insn "ccmp<mode>"
287 [(set (match_operand:CC 1 "cc_register" "")
289 (match_operator 4 "aarch64_comparison_operator"
290 [(match_operand 0 "cc_register" "")
293 (match_operand:GPI 2 "register_operand" "r,r,r")
294 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
295 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
298 ccmp\\t%<w>2, %<w>3, %k5, %m4
299 ccmp\\t%<w>2, %3, %k5, %m4
300 ccmn\\t%<w>2, #%n3, %k5, %m4"
301 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
304 (define_insn "fccmp<mode>"
305 [(set (match_operand:CCFP 1 "cc_register" "")
307 (match_operator 4 "aarch64_comparison_operator"
308 [(match_operand 0 "cc_register" "")
311 (match_operand:GPF 2 "register_operand" "w")
312 (match_operand:GPF 3 "register_operand" "w"))
313 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
315 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
316 [(set_attr "type" "fccmp<s>")]
319 (define_insn "fccmpe<mode>"
320 [(set (match_operand:CCFPE 1 "cc_register" "")
322 (match_operator 4 "aarch64_comparison_operator"
323 [(match_operand 0 "cc_register" "")
326 (match_operand:GPF 2 "register_operand" "w")
327 (match_operand:GPF 3 "register_operand" "w"))
328 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
330 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
331 [(set_attr "type" "fccmp<s>")]
334 ;; Expansion of signed mod by a power of 2 using CSNEG.
335 ;; For x0 % n where n is a power of 2 produce:
337 ;; and x0, x0, #(n - 1)
338 ;; and x1, x1, #(n - 1)
339 ;; csneg x0, x0, x1, mi
341 (define_expand "mod<mode>3"
342 [(match_operand:GPI 0 "register_operand" "")
343 (match_operand:GPI 1 "register_operand" "")
344 (match_operand:GPI 2 "const_int_operand" "")]
347 HOST_WIDE_INT val = INTVAL (operands[2]);
350 || exact_log2 (val) <= 0
351 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
354 rtx mask = GEN_INT (val - 1);
356 /* In the special case of x0 % 2 we can do the even shorter:
362 rtx masked = gen_reg_rtx (<MODE>mode);
363 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
364 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
365 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
366 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
370 rtx neg_op = gen_reg_rtx (<MODE>mode);
371 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
373 /* Extract the condition register and mode. */
374 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
375 rtx cc_reg = SET_DEST (cmp);
376 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
378 rtx masked_pos = gen_reg_rtx (<MODE>mode);
379 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
381 rtx masked_neg = gen_reg_rtx (<MODE>mode);
382 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
384 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
385 masked_neg, masked_pos));
390 (define_insn "condjump"
391 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
392 [(match_operand 1 "cc_register" "") (const_int 0)])
393 (label_ref (match_operand 2 "" ""))
397 if (get_attr_length (insn) == 8)
398 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
402 [(set_attr "type" "branch")
404 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
405 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
408 (set (attr "far_branch")
409 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
410 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
415 ;; For a 24-bit immediate CST we can optimize the compare for equality
416 ;; and branch sequence from:
418 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
422 ;; sub x0, x1, #(CST & 0xfff000)
423 ;; subs x0, x0, #(CST & 0x000fff)
425 (define_insn_and_split "*compare_condjump<mode>"
426 [(set (pc) (if_then_else (EQL
427 (match_operand:GPI 0 "register_operand" "r")
428 (match_operand:GPI 1 "aarch64_imm24" "n"))
429 (label_ref:P (match_operand 2 "" ""))
431 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
432 && !aarch64_plus_operand (operands[1], <MODE>mode)
433 && !reload_completed"
438 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
439 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
440 rtx tmp = gen_reg_rtx (<MODE>mode);
441 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
442 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
443 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
444 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
445 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
450 (define_expand "casesi"
451 [(match_operand:SI 0 "register_operand" "") ; Index
452 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
453 (match_operand:SI 2 "const_int_operand" "") ; Total range
454 (match_operand:DI 3 "" "") ; Table label
455 (match_operand:DI 4 "" "")] ; Out of range label
458 if (operands[1] != const0_rtx)
460 rtx reg = gen_reg_rtx (SImode);
462 /* Canonical RTL says that if you have:
466 then this should be emitted as:
470 The use of trunc_int_for_mode ensures that the resulting
471 constant can be represented in SImode, this is important
472 for the corner case where operand[1] is INT_MIN. */
474 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
476 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
477 (operands[1], SImode))
478 operands[1] = force_reg (SImode, operands[1]);
479 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
483 if (!aarch64_plus_operand (operands[2], SImode))
484 operands[2] = force_reg (SImode, operands[2]);
485 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
487 operands[0], operands[2], operands[4]));
489 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
490 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
496 (define_insn "casesi_dispatch"
499 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
500 (match_operand:SI 1 "register_operand" "r")]
502 (clobber (reg:CC CC_REGNUM))
503 (clobber (match_scratch:DI 3 "=r"))
504 (clobber (match_scratch:DI 4 "=r"))
505 (use (label_ref (match_operand 2 "" "")))])]
508 return aarch64_output_casesi (operands);
510 [(set_attr "length" "16")
511 (set_attr "type" "branch")]
515 [(unspec[(const_int 0)] UNSPEC_NOP)]
518 [(set_attr "type" "no_insn")]
521 (define_insn "prefetch"
522 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
523 (match_operand:QI 1 "const_int_operand" "")
524 (match_operand:QI 2 "const_int_operand" ""))]
527 const char * pftype[2][4] =
529 {"prfm\\tPLDL1STRM, %0",
530 "prfm\\tPLDL3KEEP, %0",
531 "prfm\\tPLDL2KEEP, %0",
532 "prfm\\tPLDL1KEEP, %0"},
533 {"prfm\\tPSTL1STRM, %0",
534 "prfm\\tPSTL3KEEP, %0",
535 "prfm\\tPSTL2KEEP, %0",
536 "prfm\\tPSTL1KEEP, %0"},
539 int locality = INTVAL (operands[2]);
541 gcc_assert (IN_RANGE (locality, 0, 3));
543 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
544 the address into a DImode MEM so that aarch64_print_operand knows
546 operands[0] = gen_rtx_MEM (DImode, operands[0]);
547 return pftype[INTVAL(operands[1])][locality];
549 [(set_attr "type" "load1")]
553 [(trap_if (const_int 1) (const_int 8))]
556 [(set_attr "type" "trap")])
558 (define_expand "prologue"
559 [(clobber (const_int 0))]
562 aarch64_expand_prologue ();
567 (define_expand "epilogue"
568 [(clobber (const_int 0))]
571 aarch64_expand_epilogue (false);
576 (define_expand "sibcall_epilogue"
577 [(clobber (const_int 0))]
580 aarch64_expand_epilogue (true);
585 (define_insn "*do_return"
589 if (aarch64_return_address_signing_enabled ()
591 && !crtl->calls_eh_return)
596 [(set_attr "type" "branch")]
599 (define_expand "return"
601 "aarch64_use_return_insn_p ()"
605 (define_insn "simple_return"
609 [(set_attr "type" "branch")]
612 (define_insn "*cb<optab><mode>1"
613 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
615 (label_ref (match_operand 1 "" ""))
619 if (get_attr_length (insn) == 8)
620 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
622 return "<cbz>\\t%<w>0, %l1";
624 [(set_attr "type" "branch")
626 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
627 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
630 (set (attr "far_branch")
631 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
632 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
637 (define_insn "*tb<optab><mode>1"
638 [(set (pc) (if_then_else
639 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
642 "aarch64_simd_shift_imm_<mode>" "n"))
644 (label_ref (match_operand 2 "" ""))
646 (clobber (reg:CC CC_REGNUM))]
649 if (get_attr_length (insn) == 8)
651 if (get_attr_far_branch (insn) == 1)
652 return aarch64_gen_far_branch (operands, 2, "Ltb",
653 "<inv_tb>\\t%<w>0, %1, ");
656 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
657 return "tst\t%<w>0, %1\;<bcond>\t%l2";
661 return "<tbz>\t%<w>0, %1, %l2";
663 [(set_attr "type" "branch")
665 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
666 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
669 (set (attr "far_branch")
670 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
671 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
677 (define_insn "*cb<optab><mode>1"
678 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
680 (label_ref (match_operand 1 "" ""))
682 (clobber (reg:CC CC_REGNUM))]
685 if (get_attr_length (insn) == 8)
687 if (get_attr_far_branch (insn) == 1)
688 return aarch64_gen_far_branch (operands, 1, "Ltb",
689 "<inv_tb>\\t%<w>0, <sizem1>, ");
693 uint64_t val = ((uint64_t) 1)
694 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
695 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
696 output_asm_insn (buf, operands);
697 return "<bcond>\t%l1";
701 return "<tbz>\t%<w>0, <sizem1>, %l1";
703 [(set_attr "type" "branch")
705 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
706 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
709 (set (attr "far_branch")
710 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
711 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
716 ;; -------------------------------------------------------------------
717 ;; Subroutine calls and sibcalls
718 ;; -------------------------------------------------------------------
720 (define_expand "call_internal"
721 [(parallel [(call (match_operand 0 "memory_operand" "")
722 (match_operand 1 "general_operand" ""))
723 (use (match_operand 2 "" ""))
724 (clobber (reg:DI LR_REGNUM))])])
726 (define_expand "call"
727 [(parallel [(call (match_operand 0 "memory_operand" "")
728 (match_operand 1 "general_operand" ""))
729 (use (match_operand 2 "" ""))
730 (clobber (reg:DI LR_REGNUM))])]
736 /* In an untyped call, we can get NULL for operand 2. */
737 if (operands[2] == NULL)
738 operands[2] = const0_rtx;
740 /* Decide if we should generate indirect calls by loading the
741 64-bit address of the callee into a register before performing
742 the branch-and-link. */
743 callee = XEXP (operands[0], 0);
744 if (GET_CODE (callee) == SYMBOL_REF
745 ? (aarch64_is_long_call_p (callee)
746 || aarch64_is_noplt_call_p (callee))
748 XEXP (operands[0], 0) = force_reg (Pmode, callee);
750 pat = gen_call_internal (operands[0], operands[1], operands[2]);
751 aarch64_emit_call_insn (pat);
756 (define_insn "*call_reg"
757 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
758 (match_operand 1 "" ""))
759 (use (match_operand 2 "" ""))
760 (clobber (reg:DI LR_REGNUM))]
763 [(set_attr "type" "call")]
766 (define_insn "*call_symbol"
767 [(call (mem:DI (match_operand:DI 0 "" ""))
768 (match_operand 1 "" ""))
769 (use (match_operand 2 "" ""))
770 (clobber (reg:DI LR_REGNUM))]
771 "GET_CODE (operands[0]) == SYMBOL_REF
772 && !aarch64_is_long_call_p (operands[0])
773 && !aarch64_is_noplt_call_p (operands[0])"
775 [(set_attr "type" "call")]
778 (define_expand "call_value_internal"
779 [(parallel [(set (match_operand 0 "" "")
780 (call (match_operand 1 "memory_operand" "")
781 (match_operand 2 "general_operand" "")))
782 (use (match_operand 3 "" ""))
783 (clobber (reg:DI LR_REGNUM))])])
785 (define_expand "call_value"
786 [(parallel [(set (match_operand 0 "" "")
787 (call (match_operand 1 "memory_operand" "")
788 (match_operand 2 "general_operand" "")))
789 (use (match_operand 3 "" ""))
790 (clobber (reg:DI LR_REGNUM))])]
796 /* In an untyped call, we can get NULL for operand 3. */
797 if (operands[3] == NULL)
798 operands[3] = const0_rtx;
800 /* Decide if we should generate indirect calls by loading the
801 64-bit address of the callee into a register before performing
802 the branch-and-link. */
803 callee = XEXP (operands[1], 0);
804 if (GET_CODE (callee) == SYMBOL_REF
805 ? (aarch64_is_long_call_p (callee)
806 || aarch64_is_noplt_call_p (callee))
808 XEXP (operands[1], 0) = force_reg (Pmode, callee);
810 pat = gen_call_value_internal (operands[0], operands[1], operands[2],
812 aarch64_emit_call_insn (pat);
817 (define_insn "*call_value_reg"
818 [(set (match_operand 0 "" "")
819 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
820 (match_operand 2 "" "")))
821 (use (match_operand 3 "" ""))
822 (clobber (reg:DI LR_REGNUM))]
825 [(set_attr "type" "call")]
829 (define_insn "*call_value_symbol"
830 [(set (match_operand 0 "" "")
831 (call (mem:DI (match_operand:DI 1 "" ""))
832 (match_operand 2 "" "")))
833 (use (match_operand 3 "" ""))
834 (clobber (reg:DI LR_REGNUM))]
835 "GET_CODE (operands[1]) == SYMBOL_REF
836 && !aarch64_is_long_call_p (operands[1])
837 && !aarch64_is_noplt_call_p (operands[1])"
839 [(set_attr "type" "call")]
842 (define_expand "sibcall_internal"
843 [(parallel [(call (match_operand 0 "memory_operand" "")
844 (match_operand 1 "general_operand" ""))
846 (use (match_operand 2 "" ""))])])
848 (define_expand "sibcall"
849 [(parallel [(call (match_operand 0 "memory_operand" "")
850 (match_operand 1 "general_operand" ""))
852 (use (match_operand 2 "" ""))])]
856 rtx callee = XEXP (operands[0], 0);
858 && ((GET_CODE (callee) != SYMBOL_REF)
859 || aarch64_is_noplt_call_p (callee)))
860 XEXP (operands[0], 0) = force_reg (Pmode, callee);
862 if (operands[2] == NULL_RTX)
863 operands[2] = const0_rtx;
865 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
866 aarch64_emit_call_insn (pat);
871 (define_expand "sibcall_value_internal"
872 [(parallel [(set (match_operand 0 "" "")
873 (call (match_operand 1 "memory_operand" "")
874 (match_operand 2 "general_operand" "")))
876 (use (match_operand 3 "" ""))])])
878 (define_expand "sibcall_value"
879 [(parallel [(set (match_operand 0 "" "")
880 (call (match_operand 1 "memory_operand" "")
881 (match_operand 2 "general_operand" "")))
883 (use (match_operand 3 "" ""))])]
887 rtx callee = XEXP (operands[1], 0);
889 && ((GET_CODE (callee) != SYMBOL_REF)
890 || aarch64_is_noplt_call_p (callee)))
891 XEXP (operands[1], 0) = force_reg (Pmode, callee);
893 if (operands[3] == NULL_RTX)
894 operands[3] = const0_rtx;
896 pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
898 aarch64_emit_call_insn (pat);
903 (define_insn "*sibcall_insn"
904 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
905 (match_operand 1 "" ""))
907 (use (match_operand 2 "" ""))]
908 "SIBLING_CALL_P (insn)"
912 [(set_attr "type" "branch, branch")]
915 (define_insn "*sibcall_value_insn"
916 [(set (match_operand 0 "" "")
918 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
919 (match_operand 2 "" "")))
921 (use (match_operand 3 "" ""))]
922 "SIBLING_CALL_P (insn)"
926 [(set_attr "type" "branch, branch")]
929 ;; Call subroutine returning any type.
931 (define_expand "untyped_call"
932 [(parallel [(call (match_operand 0 "")
935 (match_operand 2 "")])]
940 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
942 for (i = 0; i < XVECLEN (operands[2], 0); i++)
944 rtx set = XVECEXP (operands[2], 0, i);
945 emit_move_insn (SET_DEST (set), SET_SRC (set));
948 /* The optimizer does not know that the call sets the function value
949 registers we stored in the result block. We avoid problems by
950 claiming that all hard registers are used and clobbered at this
952 emit_insn (gen_blockage ());
956 ;; -------------------------------------------------------------------
958 ;; -------------------------------------------------------------------
960 (define_expand "mov<mode>"
961 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
962 (match_operand:SHORT 1 "general_operand" ""))]
965 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
966 operands[1] = force_reg (<MODE>mode, operands[1]);
970 (define_insn "*mov<mode>_aarch64"
971 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
972 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
973 "(register_operand (operands[0], <MODE>mode)
974 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
976 switch (which_alternative)
979 return "mov\t%w0, %w1";
981 return "mov\t%w0, %1";
983 return aarch64_output_scalar_simd_mov_immediate (operands[1],
986 return "ldr<size>\t%w0, %1";
988 return "ldr\t%<size>0, %1";
990 return "str<size>\t%w1, %0";
992 return "str\t%<size>1, %0";
994 return "umov\t%w0, %1.<v>[0]";
996 return "dup\t%0.<Vallxd>, %w1";
998 return "dup\t%<Vetype>0, %1.<v>[0]";
1003 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1004 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1005 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1008 (define_expand "mov<mode>"
1009 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1010 (match_operand:GPI 1 "general_operand" ""))]
1013 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1014 && <MODE>mode == DImode
1015 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1018 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1019 operands[1] = force_reg (<MODE>mode, operands[1]);
1021 /* FIXME: RR we still need to fix up what we are doing with
1022 symbol_refs and other types of constants. */
1023 if (CONSTANT_P (operands[1])
1024 && !CONST_INT_P (operands[1]))
1026 aarch64_expand_mov_immediate (operands[0], operands[1]);
1032 (define_insn_and_split "*movsi_aarch64"
1033 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w")
1034 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1035 "(register_operand (operands[0], SImode)
1036 || aarch64_reg_or_zero (operands[1], SImode))"
1052 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1053 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1056 aarch64_expand_mov_immediate (operands[0], operands[1]);
1059 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1060 adr,adr,f_mcr,f_mrc,fmov")
1061 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1064 (define_insn_and_split "*movdi_aarch64"
1065 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w, r,*w,w")
1066 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1067 "(register_operand (operands[0], DImode)
1068 || aarch64_reg_or_zero (operands[1], DImode))"
1085 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1086 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1089 aarch64_expand_mov_immediate (operands[0], operands[1]);
1092 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1093 adr,adr,f_mcr,f_mrc,fmov,neon_move")
1094 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1095 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1098 (define_insn "insv_imm<mode>"
1099 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1101 (match_operand:GPI 1 "const_int_operand" "n"))
1102 (match_operand:GPI 2 "const_int_operand" "n"))]
1103 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1104 && UINTVAL (operands[1]) % 16 == 0"
1105 "movk\\t%<w>0, %X2, lsl %1"
1106 [(set_attr "type" "mov_imm")]
1109 (define_expand "movti"
1110 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1111 (match_operand:TI 1 "general_operand" ""))]
1114 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1115 operands[1] = force_reg (TImode, operands[1]);
1119 (define_insn "*movti_aarch64"
1120 [(set (match_operand:TI 0
1121 "nonimmediate_operand" "=r, *w,r ,*w,r,m,m,*w,m")
1123 "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1124 "(register_operand (operands[0], TImode)
1125 || aarch64_reg_or_zero (operands[1], TImode))"
1130 orr\\t%0.16b, %1.16b, %1.16b
1136 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1137 load2,store2,store2,f_loadd,f_stored")
1138 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1139 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1140 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1143 ;; Split a TImode register-register or register-immediate move into
1144 ;; its component DImode pieces, taking care to handle overlapping
1145 ;; source and dest registers.
1147 [(set (match_operand:TI 0 "register_operand" "")
1148 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1149 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1152 aarch64_split_128bit_move (operands[0], operands[1]);
1156 (define_expand "mov<mode>"
1157 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1158 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1163 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1167 if (GET_CODE (operands[0]) == MEM
1168 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1169 && aarch64_float_const_zero_rtx_p (operands[1])))
1170 operands[1] = force_reg (<MODE>mode, operands[1]);
1174 (define_insn "*movhf_aarch64"
1175 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
1176 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
1177 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1178 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1183 mov\\t%0.h[0], %1.h[0]
1189 [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1190 f_loads,f_stores,load1,store1,mov_reg")
1191 (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1194 (define_insn "*movsf_aarch64"
1195 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1196 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1197 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1198 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1210 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1211 f_loads,f_stores,load1,store1,mov_reg")
1212 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1215 (define_insn "*movdf_aarch64"
1216 [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1217 (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1218 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1219 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1231 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1232 f_loadd,f_stored,load1,store1,mov_reg")
1233 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1236 (define_insn "*movtf_aarch64"
1237 [(set (match_operand:TF 0
1238 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1240 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1241 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1242 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1244 orr\\t%0.16b, %1.16b, %1.16b
1255 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1256 f_loadd,f_stored,load2,store2,store2")
1257 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1258 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1262 [(set (match_operand:TF 0 "register_operand" "")
1263 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1264 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1267 aarch64_split_128bit_move (operands[0], operands[1]);
1274 ;; 2 is size of move in bytes
1277 (define_expand "movmemdi"
1278 [(match_operand:BLK 0 "memory_operand")
1279 (match_operand:BLK 1 "memory_operand")
1280 (match_operand:DI 2 "immediate_operand")
1281 (match_operand:DI 3 "immediate_operand")]
1284 if (aarch64_expand_movmem (operands))
1290 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1291 ;; fairly lax checking on the second memory operation.
1292 (define_insn "load_pairsi"
1293 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1294 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1295 (set (match_operand:SI 2 "register_operand" "=r,*w")
1296 (match_operand:SI 3 "memory_operand" "m,m"))]
1297 "rtx_equal_p (XEXP (operands[3], 0),
1298 plus_constant (Pmode,
1299 XEXP (operands[1], 0),
1300 GET_MODE_SIZE (SImode)))"
1304 [(set_attr "type" "load2,neon_load1_2reg")
1305 (set_attr "fp" "*,yes")]
1308 (define_insn "load_pairdi"
1309 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1310 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1311 (set (match_operand:DI 2 "register_operand" "=r,*w")
1312 (match_operand:DI 3 "memory_operand" "m,m"))]
1313 "rtx_equal_p (XEXP (operands[3], 0),
1314 plus_constant (Pmode,
1315 XEXP (operands[1], 0),
1316 GET_MODE_SIZE (DImode)))"
1320 [(set_attr "type" "load2,neon_load1_2reg")
1321 (set_attr "fp" "*,yes")]
1325 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1326 ;; fairly lax checking on the second memory operation.
1327 (define_insn "store_pairsi"
1328 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1329 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1330 (set (match_operand:SI 2 "memory_operand" "=m,m")
1331 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1332 "rtx_equal_p (XEXP (operands[2], 0),
1333 plus_constant (Pmode,
1334 XEXP (operands[0], 0),
1335 GET_MODE_SIZE (SImode)))"
1339 [(set_attr "type" "store2,neon_store1_2reg")
1340 (set_attr "fp" "*,yes")]
1343 (define_insn "store_pairdi"
1344 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1345 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1346 (set (match_operand:DI 2 "memory_operand" "=m,m")
1347 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1348 "rtx_equal_p (XEXP (operands[2], 0),
1349 plus_constant (Pmode,
1350 XEXP (operands[0], 0),
1351 GET_MODE_SIZE (DImode)))"
1355 [(set_attr "type" "store2,neon_store1_2reg")
1356 (set_attr "fp" "*,yes")]
1359 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1360 ;; fairly lax checking on the second memory operation.
1361 (define_insn "load_pairsf"
1362 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1363 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1364 (set (match_operand:SF 2 "register_operand" "=w,*r")
1365 (match_operand:SF 3 "memory_operand" "m,m"))]
1366 "rtx_equal_p (XEXP (operands[3], 0),
1367 plus_constant (Pmode,
1368 XEXP (operands[1], 0),
1369 GET_MODE_SIZE (SFmode)))"
1373 [(set_attr "type" "neon_load1_2reg,load2")
1374 (set_attr "fp" "yes,*")]
1377 (define_insn "load_pairdf"
1378 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1379 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1380 (set (match_operand:DF 2 "register_operand" "=w,*r")
1381 (match_operand:DF 3 "memory_operand" "m,m"))]
1382 "rtx_equal_p (XEXP (operands[3], 0),
1383 plus_constant (Pmode,
1384 XEXP (operands[1], 0),
1385 GET_MODE_SIZE (DFmode)))"
1389 [(set_attr "type" "neon_load1_2reg,load2")
1390 (set_attr "fp" "yes,*")]
1393 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1394 ;; fairly lax checking on the second memory operation.
1395 (define_insn "store_pairsf"
1396 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1397 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1398 (set (match_operand:SF 2 "memory_operand" "=m,m")
1399 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1400 "rtx_equal_p (XEXP (operands[2], 0),
1401 plus_constant (Pmode,
1402 XEXP (operands[0], 0),
1403 GET_MODE_SIZE (SFmode)))"
1407 [(set_attr "type" "neon_store1_2reg,store2")
1408 (set_attr "fp" "yes,*")]
1411 (define_insn "store_pairdf"
1412 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1413 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1414 (set (match_operand:DF 2 "memory_operand" "=m,m")
1415 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1416 "rtx_equal_p (XEXP (operands[2], 0),
1417 plus_constant (Pmode,
1418 XEXP (operands[0], 0),
1419 GET_MODE_SIZE (DFmode)))"
1423 [(set_attr "type" "neon_store1_2reg,store2")
1424 (set_attr "fp" "yes,*")]
1427 ;; Load pair with post-index writeback. This is primarily used in function
1429 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1431 [(set (match_operand:P 0 "register_operand" "=k")
1432 (plus:P (match_operand:P 1 "register_operand" "0")
1433 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1434 (set (match_operand:GPI 2 "register_operand" "=r")
1435 (mem:GPI (match_dup 1)))
1436 (set (match_operand:GPI 3 "register_operand" "=r")
1437 (mem:GPI (plus:P (match_dup 1)
1438 (match_operand:P 5 "const_int_operand" "n"))))])]
1439 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1440 "ldp\\t%<w>2, %<w>3, [%1], %4"
1441 [(set_attr "type" "load2")]
1444 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1446 [(set (match_operand:P 0 "register_operand" "=k")
1447 (plus:P (match_operand:P 1 "register_operand" "0")
1448 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1449 (set (match_operand:GPF 2 "register_operand" "=w")
1450 (mem:GPF (match_dup 1)))
1451 (set (match_operand:GPF 3 "register_operand" "=w")
1452 (mem:GPF (plus:P (match_dup 1)
1453 (match_operand:P 5 "const_int_operand" "n"))))])]
1454 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1455 "ldp\\t%<w>2, %<w>3, [%1], %4"
1456 [(set_attr "type" "neon_load1_2reg")]
1459 ;; Store pair with pre-index writeback. This is primarily used in function
1461 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1463 [(set (match_operand:P 0 "register_operand" "=&k")
1464 (plus:P (match_operand:P 1 "register_operand" "0")
1465 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1466 (set (mem:GPI (plus:P (match_dup 0)
1468 (match_operand:GPI 2 "register_operand" "r"))
1469 (set (mem:GPI (plus:P (match_dup 0)
1470 (match_operand:P 5 "const_int_operand" "n")))
1471 (match_operand:GPI 3 "register_operand" "r"))])]
1472 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1473 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1474 [(set_attr "type" "store2")]
1477 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1479 [(set (match_operand:P 0 "register_operand" "=&k")
1480 (plus:P (match_operand:P 1 "register_operand" "0")
1481 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1482 (set (mem:GPF (plus:P (match_dup 0)
1484 (match_operand:GPF 2 "register_operand" "w"))
1485 (set (mem:GPF (plus:P (match_dup 0)
1486 (match_operand:P 5 "const_int_operand" "n")))
1487 (match_operand:GPF 3 "register_operand" "w"))])]
1488 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1489 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1490 [(set_attr "type" "neon_store1_2reg<q>")]
1493 ;; -------------------------------------------------------------------
1494 ;; Sign/Zero extension
1495 ;; -------------------------------------------------------------------
1497 (define_expand "<optab>sidi2"
1498 [(set (match_operand:DI 0 "register_operand")
1499 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1503 (define_insn "*extendsidi2_aarch64"
1504 [(set (match_operand:DI 0 "register_operand" "=r,r")
1505 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1510 [(set_attr "type" "extend,load1")]
1513 (define_insn "*load_pair_extendsidi2_aarch64"
1514 [(set (match_operand:DI 0 "register_operand" "=r")
1515 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1516 (set (match_operand:DI 2 "register_operand" "=r")
1517 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1518 "rtx_equal_p (XEXP (operands[3], 0),
1519 plus_constant (Pmode,
1520 XEXP (operands[1], 0),
1521 GET_MODE_SIZE (SImode)))"
1522 "ldpsw\\t%0, %2, %1"
1523 [(set_attr "type" "load2")]
1526 (define_insn "*zero_extendsidi2_aarch64"
1527 [(set (match_operand:DI 0 "register_operand" "=r,r")
1528 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1533 [(set_attr "type" "extend,load1")]
1536 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1537 [(set (match_operand:DI 0 "register_operand" "=r")
1538 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1539 (set (match_operand:DI 2 "register_operand" "=r")
1540 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1541 "rtx_equal_p (XEXP (operands[3], 0),
1542 plus_constant (Pmode,
1543 XEXP (operands[1], 0),
1544 GET_MODE_SIZE (SImode)))"
1545 "ldp\\t%w0, %w2, %1"
1546 [(set_attr "type" "load2")]
1549 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1550 [(set (match_operand:GPI 0 "register_operand")
1551 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1555 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1556 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1557 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1560 sxt<SHORT:size>\t%<GPI:w>0, %w1
1561 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1562 [(set_attr "type" "extend,load1")]
1565 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1566 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1567 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1570 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1571 ldr<SHORT:size>\t%w0, %1
1572 ldr\t%<SHORT:size>0, %1"
1573 [(set_attr "type" "logic_imm,load1,load1")]
1576 (define_expand "<optab>qihi2"
1577 [(set (match_operand:HI 0 "register_operand")
1578 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1582 (define_insn "*extendqihi2_aarch64"
1583 [(set (match_operand:HI 0 "register_operand" "=r,r")
1584 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1589 [(set_attr "type" "extend,load1")]
1592 (define_insn "*zero_extendqihi2_aarch64"
1593 [(set (match_operand:HI 0 "register_operand" "=r,r")
1594 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1599 [(set_attr "type" "logic_imm,load1")]
1602 ;; -------------------------------------------------------------------
1603 ;; Simple arithmetic
1604 ;; -------------------------------------------------------------------
1606 (define_expand "add<mode>3"
1608 (match_operand:GPI 0 "register_operand" "")
1609 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1610 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1613 /* If operands[1] is a subreg extract the inner RTX. */
1614 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1616 /* If the constant is too large for a single instruction and isn't frame
1617 based, split off the immediate so it is available for CSE. */
1618 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1619 && can_create_pseudo_p ()
1621 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1622 operands[2] = force_reg (<MODE>mode, operands[2]);
1625 (define_insn "*add<mode>3_aarch64"
1627 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1629 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1630 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1633 add\\t%<w>0, %<w>1, %2
1634 add\\t%<w>0, %<w>1, %<w>2
1635 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1636 sub\\t%<w>0, %<w>1, #%n2
1638 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1639 (set_attr "simd" "*,*,yes,*,*")]
1642 ;; zero_extend version of above
1643 (define_insn "*addsi3_aarch64_uxtw"
1645 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1647 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1648 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1653 sub\\t%w0, %w1, #%n2
1655 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1658 ;; If there's a free register, and we can load the constant with a
1659 ;; single instruction, do so. This has a chance to improve scheduling.
1661 [(match_scratch:GPI 3 "r")
1662 (set (match_operand:GPI 0 "register_operand")
1664 (match_operand:GPI 1 "register_operand")
1665 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1666 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1667 [(set (match_dup 3) (match_dup 2))
1668 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1672 [(match_scratch:SI 3 "r")
1673 (set (match_operand:DI 0 "register_operand")
1676 (match_operand:SI 1 "register_operand")
1677 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1678 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1679 [(set (match_dup 3) (match_dup 2))
1680 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1683 ;; After peephole2 has had a chance to run, split any remaining long
1684 ;; additions into two add immediates.
1686 [(set (match_operand:GPI 0 "register_operand")
1688 (match_operand:GPI 1 "register_operand")
1689 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1690 "epilogue_completed"
1691 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1692 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1694 HOST_WIDE_INT i = INTVAL (operands[2]);
1695 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1696 operands[3] = GEN_INT (i - s);
1697 operands[4] = GEN_INT (s);
1702 [(set (match_operand:DI 0 "register_operand")
1705 (match_operand:SI 1 "register_operand")
1706 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1707 "epilogue_completed"
1708 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1709 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1711 HOST_WIDE_INT i = INTVAL (operands[2]);
1712 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1713 operands[3] = GEN_INT (i - s);
1714 operands[4] = GEN_INT (s);
1715 operands[5] = gen_lowpart (SImode, operands[0]);
1719 (define_expand "addti3"
1720 [(set (match_operand:TI 0 "register_operand" "")
1721 (plus:TI (match_operand:TI 1 "register_operand" "")
1722 (match_operand:TI 2 "register_operand" "")))]
1725 rtx low = gen_reg_rtx (DImode);
1726 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1727 gen_lowpart (DImode, operands[2])));
1729 rtx high = gen_reg_rtx (DImode);
1730 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1731 gen_highpart (DImode, operands[2])));
1733 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1734 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1738 (define_insn "add<mode>3_compare0"
1739 [(set (reg:CC_NZ CC_REGNUM)
1741 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1742 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1744 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1745 (plus:GPI (match_dup 1) (match_dup 2)))]
1748 adds\\t%<w>0, %<w>1, %<w>2
1749 adds\\t%<w>0, %<w>1, %2
1750 subs\\t%<w>0, %<w>1, #%n2"
1751 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1754 ;; zero_extend version of above
1755 (define_insn "*addsi3_compare0_uxtw"
1756 [(set (reg:CC_NZ CC_REGNUM)
1758 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1759 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1761 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1762 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1765 adds\\t%w0, %w1, %w2
1767 subs\\t%w0, %w1, #%n2"
1768 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1771 (define_insn "*add<mode>3_compareC_cconly_imm"
1772 [(set (reg:CC_C CC_REGNUM)
1775 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1776 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1780 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1781 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1782 <MODE>mode, operands[1])"
1786 [(set_attr "type" "alus_imm")]
1789 (define_insn "*add<mode>3_compareC_cconly"
1790 [(set (reg:CC_C CC_REGNUM)
1793 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1794 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1795 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1797 "cmn\\t%<w>0, %<w>1"
1798 [(set_attr "type" "alus_sreg")]
1801 (define_insn "*add<mode>3_compareC_imm"
1802 [(set (reg:CC_C CC_REGNUM)
1805 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1806 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1810 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1811 (set (match_operand:GPI 0 "register_operand" "=r,r")
1812 (plus:GPI (match_dup 1) (match_dup 2)))]
1813 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1814 <MODE>mode, operands[2])"
1816 adds\\t%<w>0, %<w>1, %2
1817 subs\\t%<w>0, %<w>1, #%n2"
1818 [(set_attr "type" "alus_imm")]
1821 (define_insn "add<mode>3_compareC"
1822 [(set (reg:CC_C CC_REGNUM)
1825 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1826 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1828 (plus:GPI (match_dup 1) (match_dup 2)))))
1829 (set (match_operand:GPI 0 "register_operand" "=r")
1830 (plus:GPI (match_dup 1) (match_dup 2)))]
1832 "adds\\t%<w>0, %<w>1, %<w>2"
1833 [(set_attr "type" "alus_sreg")]
1836 (define_insn "*adds_shift_imm_<mode>"
1837 [(set (reg:CC_NZ CC_REGNUM)
1839 (plus:GPI (ASHIFT:GPI
1840 (match_operand:GPI 1 "register_operand" "r")
1841 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1842 (match_operand:GPI 3 "register_operand" "r"))
1844 (set (match_operand:GPI 0 "register_operand" "=r")
1845 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1848 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1849 [(set_attr "type" "alus_shift_imm")]
1852 (define_insn "*subs_shift_imm_<mode>"
1853 [(set (reg:CC_NZ CC_REGNUM)
1855 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1857 (match_operand:GPI 2 "register_operand" "r")
1858 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1860 (set (match_operand:GPI 0 "register_operand" "=r")
1861 (minus:GPI (match_dup 1)
1862 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1864 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1865 [(set_attr "type" "alus_shift_imm")]
1868 (define_insn "*adds_mul_imm_<mode>"
1869 [(set (reg:CC_NZ CC_REGNUM)
1872 (match_operand:GPI 1 "register_operand" "r")
1873 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1874 (match_operand:GPI 3 "register_operand" "r"))
1876 (set (match_operand:GPI 0 "register_operand" "=r")
1877 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1880 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1881 [(set_attr "type" "alus_shift_imm")]
1884 (define_insn "*subs_mul_imm_<mode>"
1885 [(set (reg:CC_NZ CC_REGNUM)
1887 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1889 (match_operand:GPI 2 "register_operand" "r")
1890 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1892 (set (match_operand:GPI 0 "register_operand" "=r")
1893 (minus:GPI (match_dup 1)
1894 (mult:GPI (match_dup 2) (match_dup 3))))]
1896 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1897 [(set_attr "type" "alus_shift_imm")]
1900 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1901 [(set (reg:CC_NZ CC_REGNUM)
1904 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1905 (match_operand:GPI 2 "register_operand" "r"))
1907 (set (match_operand:GPI 0 "register_operand" "=r")
1908 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1910 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1911 [(set_attr "type" "alus_ext")]
1914 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1915 [(set (reg:CC_NZ CC_REGNUM)
1917 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1919 (match_operand:ALLX 2 "register_operand" "r")))
1921 (set (match_operand:GPI 0 "register_operand" "=r")
1922 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1924 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1925 [(set_attr "type" "alus_ext")]
1928 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1929 [(set (reg:CC_NZ CC_REGNUM)
1931 (plus:GPI (ashift:GPI
1933 (match_operand:ALLX 1 "register_operand" "r"))
1934 (match_operand 2 "aarch64_imm3" "Ui3"))
1935 (match_operand:GPI 3 "register_operand" "r"))
1937 (set (match_operand:GPI 0 "register_operand" "=rk")
1938 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1942 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1943 [(set_attr "type" "alus_ext")]
1946 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1947 [(set (reg:CC_NZ CC_REGNUM)
1949 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1952 (match_operand:ALLX 2 "register_operand" "r"))
1953 (match_operand 3 "aarch64_imm3" "Ui3")))
1955 (set (match_operand:GPI 0 "register_operand" "=rk")
1956 (minus:GPI (match_dup 1)
1957 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1960 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1961 [(set_attr "type" "alus_ext")]
1964 (define_insn "*adds_<optab><mode>_multp2"
1965 [(set (reg:CC_NZ CC_REGNUM)
1967 (plus:GPI (ANY_EXTRACT:GPI
1968 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1969 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1970 (match_operand 3 "const_int_operand" "n")
1972 (match_operand:GPI 4 "register_operand" "r"))
1974 (set (match_operand:GPI 0 "register_operand" "=r")
1975 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1979 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1980 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1981 [(set_attr "type" "alus_ext")]
1984 (define_insn "*subs_<optab><mode>_multp2"
1985 [(set (reg:CC_NZ CC_REGNUM)
1987 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1989 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1990 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1991 (match_operand 3 "const_int_operand" "n")
1994 (set (match_operand:GPI 0 "register_operand" "=r")
1995 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1996 (mult:GPI (match_dup 1) (match_dup 2))
1999 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2000 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2001 [(set_attr "type" "alus_ext")]
2004 (define_insn "*add<mode>3nr_compare0"
2005 [(set (reg:CC_NZ CC_REGNUM)
2007 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2008 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2015 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2018 (define_insn "*compare_neg<mode>"
2019 [(set (reg:CC_Z CC_REGNUM)
2021 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2022 (match_operand:GPI 1 "register_operand" "r")))]
2024 "cmn\\t%<w>1, %<w>0"
2025 [(set_attr "type" "alus_sreg")]
2028 (define_insn "*add_<shift>_<mode>"
2029 [(set (match_operand:GPI 0 "register_operand" "=r")
2030 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2031 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2032 (match_operand:GPI 3 "register_operand" "r")))]
2034 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2035 [(set_attr "type" "alu_shift_imm")]
2038 ;; zero_extend version of above
2039 (define_insn "*add_<shift>_si_uxtw"
2040 [(set (match_operand:DI 0 "register_operand" "=r")
2042 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2043 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2044 (match_operand:SI 3 "register_operand" "r"))))]
2046 "add\\t%w0, %w3, %w1, <shift> %2"
2047 [(set_attr "type" "alu_shift_imm")]
2050 (define_insn "*add_mul_imm_<mode>"
2051 [(set (match_operand:GPI 0 "register_operand" "=r")
2052 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2053 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2054 (match_operand:GPI 3 "register_operand" "r")))]
2056 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2057 [(set_attr "type" "alu_shift_imm")]
2060 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2061 [(set (match_operand:GPI 0 "register_operand" "=rk")
2062 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2063 (match_operand:GPI 2 "register_operand" "r")))]
2065 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2066 [(set_attr "type" "alu_ext")]
2069 ;; zero_extend version of above
2070 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2071 [(set (match_operand:DI 0 "register_operand" "=rk")
2073 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2074 (match_operand:GPI 2 "register_operand" "r"))))]
2076 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2077 [(set_attr "type" "alu_ext")]
2080 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2081 [(set (match_operand:GPI 0 "register_operand" "=rk")
2082 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2083 (match_operand:ALLX 1 "register_operand" "r"))
2084 (match_operand 2 "aarch64_imm3" "Ui3"))
2085 (match_operand:GPI 3 "register_operand" "r")))]
2087 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2088 [(set_attr "type" "alu_ext")]
2091 ;; zero_extend version of above
2092 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2093 [(set (match_operand:DI 0 "register_operand" "=rk")
2095 (plus:SI (ashift:SI (ANY_EXTEND:SI
2096 (match_operand:SHORT 1 "register_operand" "r"))
2097 (match_operand 2 "aarch64_imm3" "Ui3"))
2098 (match_operand:SI 3 "register_operand" "r"))))]
2100 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2101 [(set_attr "type" "alu_ext")]
2104 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2105 [(set (match_operand:GPI 0 "register_operand" "=rk")
2106 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2107 (match_operand:ALLX 1 "register_operand" "r"))
2108 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2109 (match_operand:GPI 3 "register_operand" "r")))]
2111 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2112 [(set_attr "type" "alu_ext")]
2115 ;; zero_extend version of above
2116 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2117 [(set (match_operand:DI 0 "register_operand" "=rk")
2118 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2119 (match_operand:SHORT 1 "register_operand" "r"))
2120 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2121 (match_operand:SI 3 "register_operand" "r"))))]
2123 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2124 [(set_attr "type" "alu_ext")]
2127 (define_insn "*add_<optab><mode>_multp2"
2128 [(set (match_operand:GPI 0 "register_operand" "=rk")
2129 (plus:GPI (ANY_EXTRACT:GPI
2130 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2131 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2132 (match_operand 3 "const_int_operand" "n")
2134 (match_operand:GPI 4 "register_operand" "r")))]
2135 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2136 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2137 [(set_attr "type" "alu_ext")]
2140 ;; zero_extend version of above
2141 (define_insn "*add_<optab>si_multp2_uxtw"
2142 [(set (match_operand:DI 0 "register_operand" "=rk")
2144 (plus:SI (ANY_EXTRACT:SI
2145 (mult:SI (match_operand:SI 1 "register_operand" "r")
2146 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2147 (match_operand 3 "const_int_operand" "n")
2149 (match_operand:SI 4 "register_operand" "r"))))]
2150 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2151 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2152 [(set_attr "type" "alu_ext")]
2155 (define_expand "add<mode>3_carryin"
2156 [(set (match_operand:GPI 0 "register_operand")
2159 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2160 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2161 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2166 ;; Note that add with carry with two zero inputs is matched by cset,
2167 ;; and that add with carry with one zero input is matched by cinc.
2169 (define_insn "*add<mode>3_carryin"
2170 [(set (match_operand:GPI 0 "register_operand" "=r")
2173 (match_operand:GPI 3 "aarch64_carry_operation" "")
2174 (match_operand:GPI 1 "register_operand" "r"))
2175 (match_operand:GPI 2 "register_operand" "r")))]
2177 "adc\\t%<w>0, %<w>1, %<w>2"
2178 [(set_attr "type" "adc_reg")]
2181 ;; zero_extend version of above
2182 (define_insn "*addsi3_carryin_uxtw"
2183 [(set (match_operand:DI 0 "register_operand" "=r")
2187 (match_operand:SI 3 "aarch64_carry_operation" "")
2188 (match_operand:SI 1 "register_operand" "r"))
2189 (match_operand:SI 2 "register_operand" "r"))))]
2191 "adc\\t%w0, %w1, %w2"
2192 [(set_attr "type" "adc_reg")]
2195 (define_insn "*add_uxt<mode>_shift2"
2196 [(set (match_operand:GPI 0 "register_operand" "=rk")
2198 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2199 (match_operand 2 "aarch64_imm3" "Ui3"))
2200 (match_operand 3 "const_int_operand" "n"))
2201 (match_operand:GPI 4 "register_operand" "r")))]
2202 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2204 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2205 INTVAL (operands[3])));
2206 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2207 [(set_attr "type" "alu_ext")]
2210 ;; zero_extend version of above
2211 (define_insn "*add_uxtsi_shift2_uxtw"
2212 [(set (match_operand:DI 0 "register_operand" "=rk")
2215 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2216 (match_operand 2 "aarch64_imm3" "Ui3"))
2217 (match_operand 3 "const_int_operand" "n"))
2218 (match_operand:SI 4 "register_operand" "r"))))]
2219 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2221 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2222 INTVAL (operands[3])));
2223 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2224 [(set_attr "type" "alu_ext")]
2227 (define_insn "*add_uxt<mode>_multp2"
2228 [(set (match_operand:GPI 0 "register_operand" "=rk")
2230 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2231 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2232 (match_operand 3 "const_int_operand" "n"))
2233 (match_operand:GPI 4 "register_operand" "r")))]
2234 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2236 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2237 INTVAL (operands[3])));
2238 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2239 [(set_attr "type" "alu_ext")]
2242 ;; zero_extend version of above
2243 (define_insn "*add_uxtsi_multp2_uxtw"
2244 [(set (match_operand:DI 0 "register_operand" "=rk")
2247 (mult:SI (match_operand:SI 1 "register_operand" "r")
2248 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2249 (match_operand 3 "const_int_operand" "n"))
2250 (match_operand:SI 4 "register_operand" "r"))))]
2251 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2253 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2254 INTVAL (operands[3])));
2255 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2256 [(set_attr "type" "alu_ext")]
2259 (define_insn "subsi3"
2260 [(set (match_operand:SI 0 "register_operand" "=rk")
2261 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2262 (match_operand:SI 2 "register_operand" "r")))]
2264 "sub\\t%w0, %w1, %w2"
2265 [(set_attr "type" "alu_sreg")]
2268 ;; zero_extend version of above
2269 (define_insn "*subsi3_uxtw"
2270 [(set (match_operand:DI 0 "register_operand" "=rk")
2272 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2273 (match_operand:SI 2 "register_operand" "r"))))]
2275 "sub\\t%w0, %w1, %w2"
2276 [(set_attr "type" "alu_sreg")]
2279 (define_insn "subdi3"
2280 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2281 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2282 (match_operand:DI 2 "register_operand" "r,w")))]
2286 sub\\t%d0, %d1, %d2"
2287 [(set_attr "type" "alu_sreg, neon_sub")
2288 (set_attr "simd" "*,yes")]
2291 (define_expand "subti3"
2292 [(set (match_operand:TI 0 "register_operand" "")
2293 (minus:TI (match_operand:TI 1 "register_operand" "")
2294 (match_operand:TI 2 "register_operand" "")))]
2297 rtx low = gen_reg_rtx (DImode);
2298 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2299 gen_lowpart (DImode, operands[2])));
2301 rtx high = gen_reg_rtx (DImode);
2302 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2303 gen_highpart (DImode, operands[2])));
2305 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2306 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2310 (define_insn "*sub<mode>3_compare0"
2311 [(set (reg:CC_NZ CC_REGNUM)
2312 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2313 (match_operand:GPI 2 "register_operand" "r"))
2315 (set (match_operand:GPI 0 "register_operand" "=r")
2316 (minus:GPI (match_dup 1) (match_dup 2)))]
2318 "subs\\t%<w>0, %<w>1, %<w>2"
2319 [(set_attr "type" "alus_sreg")]
2322 ;; zero_extend version of above
2323 (define_insn "*subsi3_compare0_uxtw"
2324 [(set (reg:CC_NZ CC_REGNUM)
2325 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2326 (match_operand:SI 2 "register_operand" "r"))
2328 (set (match_operand:DI 0 "register_operand" "=r")
2329 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2331 "subs\\t%w0, %w1, %w2"
2332 [(set_attr "type" "alus_sreg")]
2335 (define_insn "sub<mode>3_compare1"
2336 [(set (reg:CC CC_REGNUM)
2338 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2339 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2340 (set (match_operand:GPI 0 "register_operand" "=r")
2341 (minus:GPI (match_dup 1) (match_dup 2)))]
2343 "subs\\t%<w>0, %<w>1, %<w>2"
2344 [(set_attr "type" "alus_sreg")]
2347 (define_insn "*sub_<shift>_<mode>"
2348 [(set (match_operand:GPI 0 "register_operand" "=r")
2349 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2351 (match_operand:GPI 1 "register_operand" "r")
2352 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2354 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2355 [(set_attr "type" "alu_shift_imm")]
2358 ;; zero_extend version of above
2359 (define_insn "*sub_<shift>_si_uxtw"
2360 [(set (match_operand:DI 0 "register_operand" "=r")
2362 (minus:SI (match_operand:SI 3 "register_operand" "r")
2364 (match_operand:SI 1 "register_operand" "r")
2365 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2367 "sub\\t%w0, %w3, %w1, <shift> %2"
2368 [(set_attr "type" "alu_shift_imm")]
2371 (define_insn "*sub_mul_imm_<mode>"
2372 [(set (match_operand:GPI 0 "register_operand" "=r")
2373 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2375 (match_operand:GPI 1 "register_operand" "r")
2376 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2378 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2379 [(set_attr "type" "alu_shift_imm")]
2382 ;; zero_extend version of above
2383 (define_insn "*sub_mul_imm_si_uxtw"
2384 [(set (match_operand:DI 0 "register_operand" "=r")
2386 (minus:SI (match_operand:SI 3 "register_operand" "r")
2388 (match_operand:SI 1 "register_operand" "r")
2389 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2391 "sub\\t%w0, %w3, %w1, lsl %p2"
2392 [(set_attr "type" "alu_shift_imm")]
2395 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2396 [(set (match_operand:GPI 0 "register_operand" "=rk")
2397 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2399 (match_operand:ALLX 2 "register_operand" "r"))))]
2401 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2402 [(set_attr "type" "alu_ext")]
2405 ;; zero_extend version of above
2406 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2407 [(set (match_operand:DI 0 "register_operand" "=rk")
2409 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2411 (match_operand:SHORT 2 "register_operand" "r")))))]
2413 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2414 [(set_attr "type" "alu_ext")]
2417 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2418 [(set (match_operand:GPI 0 "register_operand" "=rk")
2419 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2420 (ashift:GPI (ANY_EXTEND:GPI
2421 (match_operand:ALLX 2 "register_operand" "r"))
2422 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2424 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2425 [(set_attr "type" "alu_ext")]
2428 ;; zero_extend version of above
2429 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2430 [(set (match_operand:DI 0 "register_operand" "=rk")
2432 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2433 (ashift:SI (ANY_EXTEND:SI
2434 (match_operand:SHORT 2 "register_operand" "r"))
2435 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2437 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2438 [(set_attr "type" "alu_ext")]
2441 (define_insn "*sub_<optab><mode>_multp2"
2442 [(set (match_operand:GPI 0 "register_operand" "=rk")
2443 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2445 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2446 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2447 (match_operand 3 "const_int_operand" "n")
2449 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2450 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2451 [(set_attr "type" "alu_ext")]
2454 ;; zero_extend version of above
2455 (define_insn "*sub_<optab>si_multp2_uxtw"
2456 [(set (match_operand:DI 0 "register_operand" "=rk")
2458 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2460 (mult:SI (match_operand:SI 1 "register_operand" "r")
2461 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2462 (match_operand 3 "const_int_operand" "n")
2464 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2465 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2466 [(set_attr "type" "alu_ext")]
2469 ;; The hardware description is op1 + ~op2 + C.
2470 ;; = op1 + (-op2 + 1) + (1 - !C)
2471 ;; = op1 - op2 - 1 + 1 - !C
2472 ;; = op1 - op2 - !C.
2473 ;; We describe the latter.
2475 (define_insn "*sub<mode>3_carryin0"
2476 [(set (match_operand:GPI 0 "register_operand" "=r")
2478 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2479 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2481 "sbc\\t%<w>0, %<w>1, <w>zr"
2482 [(set_attr "type" "adc_reg")]
2485 ;; zero_extend version of the above
2486 (define_insn "*subsi3_carryin_uxtw"
2487 [(set (match_operand:DI 0 "register_operand" "=r")
2490 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2491 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2493 "sbc\\t%w0, %w1, wzr"
2494 [(set_attr "type" "adc_reg")]
2497 (define_expand "sub<mode>3_carryin"
2498 [(set (match_operand:GPI 0 "register_operand")
2501 (match_operand:GPI 1 "aarch64_reg_or_zero")
2502 (match_operand:GPI 2 "register_operand"))
2503 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2508 (define_insn "*sub<mode>3_carryin"
2509 [(set (match_operand:GPI 0 "register_operand" "=r")
2512 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2513 (match_operand:GPI 2 "register_operand" "r"))
2514 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2517 "sbc\\t%<w>0, %<w>1, %<w>2"
2518 [(set_attr "type" "adc_reg")]
2521 ;; zero_extend version of the above
2522 (define_insn "*subsi3_carryin_uxtw"
2523 [(set (match_operand:DI 0 "register_operand" "=r")
2527 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2528 (match_operand:SI 2 "register_operand" "r"))
2529 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2532 "sbc\\t%w0, %w1, %w2"
2533 [(set_attr "type" "adc_reg")]
2536 (define_insn "*sub<mode>3_carryin_alt"
2537 [(set (match_operand:GPI 0 "register_operand" "=r")
2540 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2541 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2542 (match_operand:GPI 2 "register_operand" "r")))]
2544 "sbc\\t%<w>0, %<w>1, %<w>2"
2545 [(set_attr "type" "adc_reg")]
2548 ;; zero_extend version of the above
2549 (define_insn "*subsi3_carryin_alt_uxtw"
2550 [(set (match_operand:DI 0 "register_operand" "=r")
2554 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2555 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2556 (match_operand:SI 2 "register_operand" "r"))))]
2558 "sbc\\t%w0, %w1, %w2"
2559 [(set_attr "type" "adc_reg")]
2562 (define_insn "*sub_uxt<mode>_shift2"
2563 [(set (match_operand:GPI 0 "register_operand" "=rk")
2564 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2566 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2567 (match_operand 2 "aarch64_imm3" "Ui3"))
2568 (match_operand 3 "const_int_operand" "n"))))]
2569 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2571 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2572 INTVAL (operands[3])));
2573 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2574 [(set_attr "type" "alu_ext")]
2577 ;; zero_extend version of above
2578 (define_insn "*sub_uxtsi_shift2_uxtw"
2579 [(set (match_operand:DI 0 "register_operand" "=rk")
2581 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2583 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2584 (match_operand 2 "aarch64_imm3" "Ui3"))
2585 (match_operand 3 "const_int_operand" "n")))))]
2586 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2588 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2589 INTVAL (operands[3])));
2590 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2591 [(set_attr "type" "alu_ext")]
2594 (define_insn "*sub_uxt<mode>_multp2"
2595 [(set (match_operand:GPI 0 "register_operand" "=rk")
2596 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2598 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2599 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2600 (match_operand 3 "const_int_operand" "n"))))]
2601 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2603 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2604 INTVAL (operands[3])));
2605 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2606 [(set_attr "type" "alu_ext")]
2609 ;; zero_extend version of above
2610 (define_insn "*sub_uxtsi_multp2_uxtw"
2611 [(set (match_operand:DI 0 "register_operand" "=rk")
2613 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2615 (mult:SI (match_operand:SI 1 "register_operand" "r")
2616 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2617 (match_operand 3 "const_int_operand" "n")))))]
2618 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2620 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2621 INTVAL (operands[3])));
2622 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2623 [(set_attr "type" "alu_ext")]
2626 (define_expand "abs<mode>2"
2627 [(match_operand:GPI 0 "register_operand" "")
2628 (match_operand:GPI 1 "register_operand" "")]
2631 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2632 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2633 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2638 (define_insn "neg<mode>2"
2639 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2640 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2644 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2645 [(set_attr "type" "alu_sreg, neon_neg<q>")
2646 (set_attr "simd" "*,yes")]
2649 ;; zero_extend version of above
2650 (define_insn "*negsi2_uxtw"
2651 [(set (match_operand:DI 0 "register_operand" "=r")
2652 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2655 [(set_attr "type" "alu_sreg")]
2658 (define_insn "*ngc<mode>"
2659 [(set (match_operand:GPI 0 "register_operand" "=r")
2661 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2662 (match_operand:GPI 1 "register_operand" "r")))]
2664 "ngc\\t%<w>0, %<w>1"
2665 [(set_attr "type" "adc_reg")]
2668 (define_insn "*ngcsi_uxtw"
2669 [(set (match_operand:DI 0 "register_operand" "=r")
2672 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2673 (match_operand:SI 1 "register_operand" "r"))))]
2676 [(set_attr "type" "adc_reg")]
2679 (define_insn "neg<mode>2_compare0"
2680 [(set (reg:CC_NZ CC_REGNUM)
2681 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2683 (set (match_operand:GPI 0 "register_operand" "=r")
2684 (neg:GPI (match_dup 1)))]
2686 "negs\\t%<w>0, %<w>1"
2687 [(set_attr "type" "alus_sreg")]
2690 ;; zero_extend version of above
2691 (define_insn "*negsi2_compare0_uxtw"
2692 [(set (reg:CC_NZ CC_REGNUM)
2693 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2695 (set (match_operand:DI 0 "register_operand" "=r")
2696 (zero_extend:DI (neg:SI (match_dup 1))))]
2699 [(set_attr "type" "alus_sreg")]
2702 (define_insn "*neg_<shift><mode>3_compare0"
2703 [(set (reg:CC_NZ CC_REGNUM)
2705 (neg:GPI (ASHIFT:GPI
2706 (match_operand:GPI 1 "register_operand" "r")
2707 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2709 (set (match_operand:GPI 0 "register_operand" "=r")
2710 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2712 "negs\\t%<w>0, %<w>1, <shift> %2"
2713 [(set_attr "type" "alus_shift_imm")]
2716 (define_insn "*neg_<shift>_<mode>2"
2717 [(set (match_operand:GPI 0 "register_operand" "=r")
2718 (neg:GPI (ASHIFT:GPI
2719 (match_operand:GPI 1 "register_operand" "r")
2720 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2722 "neg\\t%<w>0, %<w>1, <shift> %2"
2723 [(set_attr "type" "alu_shift_imm")]
2726 ;; zero_extend version of above
2727 (define_insn "*neg_<shift>_si2_uxtw"
2728 [(set (match_operand:DI 0 "register_operand" "=r")
2731 (match_operand:SI 1 "register_operand" "r")
2732 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2734 "neg\\t%w0, %w1, <shift> %2"
2735 [(set_attr "type" "alu_shift_imm")]
2738 (define_insn "*neg_mul_imm_<mode>2"
2739 [(set (match_operand:GPI 0 "register_operand" "=r")
2741 (match_operand:GPI 1 "register_operand" "r")
2742 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2744 "neg\\t%<w>0, %<w>1, lsl %p2"
2745 [(set_attr "type" "alu_shift_imm")]
2748 ;; zero_extend version of above
2749 (define_insn "*neg_mul_imm_si2_uxtw"
2750 [(set (match_operand:DI 0 "register_operand" "=r")
2753 (match_operand:SI 1 "register_operand" "r")
2754 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2756 "neg\\t%w0, %w1, lsl %p2"
2757 [(set_attr "type" "alu_shift_imm")]
2760 (define_insn "mul<mode>3"
2761 [(set (match_operand:GPI 0 "register_operand" "=r")
2762 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2763 (match_operand:GPI 2 "register_operand" "r")))]
2765 "mul\\t%<w>0, %<w>1, %<w>2"
2766 [(set_attr "type" "mul")]
2769 ;; zero_extend version of above
2770 (define_insn "*mulsi3_uxtw"
2771 [(set (match_operand:DI 0 "register_operand" "=r")
2773 (mult:SI (match_operand:SI 1 "register_operand" "r")
2774 (match_operand:SI 2 "register_operand" "r"))))]
2776 "mul\\t%w0, %w1, %w2"
2777 [(set_attr "type" "mul")]
2780 (define_insn "madd<mode>"
2781 [(set (match_operand:GPI 0 "register_operand" "=r")
2782 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2783 (match_operand:GPI 2 "register_operand" "r"))
2784 (match_operand:GPI 3 "register_operand" "r")))]
2786 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2787 [(set_attr "type" "mla")]
2790 ;; zero_extend version of above
2791 (define_insn "*maddsi_uxtw"
2792 [(set (match_operand:DI 0 "register_operand" "=r")
2794 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2795 (match_operand:SI 2 "register_operand" "r"))
2796 (match_operand:SI 3 "register_operand" "r"))))]
2798 "madd\\t%w0, %w1, %w2, %w3"
2799 [(set_attr "type" "mla")]
2802 (define_insn "*msub<mode>"
2803 [(set (match_operand:GPI 0 "register_operand" "=r")
2804 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2805 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2806 (match_operand:GPI 2 "register_operand" "r"))))]
2809 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2810 [(set_attr "type" "mla")]
2813 ;; zero_extend version of above
2814 (define_insn "*msubsi_uxtw"
2815 [(set (match_operand:DI 0 "register_operand" "=r")
2817 (minus:SI (match_operand:SI 3 "register_operand" "r")
2818 (mult:SI (match_operand:SI 1 "register_operand" "r")
2819 (match_operand:SI 2 "register_operand" "r")))))]
2822 "msub\\t%w0, %w1, %w2, %w3"
2823 [(set_attr "type" "mla")]
2826 (define_insn "*mul<mode>_neg"
2827 [(set (match_operand:GPI 0 "register_operand" "=r")
2828 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2829 (match_operand:GPI 2 "register_operand" "r")))]
2832 "mneg\\t%<w>0, %<w>1, %<w>2"
2833 [(set_attr "type" "mul")]
2836 ;; zero_extend version of above
2837 (define_insn "*mulsi_neg_uxtw"
2838 [(set (match_operand:DI 0 "register_operand" "=r")
2840 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2841 (match_operand:SI 2 "register_operand" "r"))))]
2844 "mneg\\t%w0, %w1, %w2"
2845 [(set_attr "type" "mul")]
2848 (define_insn "<su_optab>mulsidi3"
2849 [(set (match_operand:DI 0 "register_operand" "=r")
2850 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2851 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2853 "<su>mull\\t%0, %w1, %w2"
2854 [(set_attr "type" "<su>mull")]
2857 (define_insn "<su_optab>maddsidi4"
2858 [(set (match_operand:DI 0 "register_operand" "=r")
2860 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2861 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2862 (match_operand:DI 3 "register_operand" "r")))]
2864 "<su>maddl\\t%0, %w1, %w2, %3"
2865 [(set_attr "type" "<su>mlal")]
2868 (define_insn "<su_optab>msubsidi4"
2869 [(set (match_operand:DI 0 "register_operand" "=r")
2871 (match_operand:DI 3 "register_operand" "r")
2872 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2874 (match_operand:SI 2 "register_operand" "r")))))]
2876 "<su>msubl\\t%0, %w1, %w2, %3"
2877 [(set_attr "type" "<su>mlal")]
2880 (define_insn "*<su_optab>mulsidi_neg"
2881 [(set (match_operand:DI 0 "register_operand" "=r")
2883 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2884 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2886 "<su>mnegl\\t%0, %w1, %w2"
2887 [(set_attr "type" "<su>mull")]
2890 (define_expand "<su_optab>mulditi3"
2891 [(set (match_operand:TI 0 "register_operand")
2892 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2893 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2896 rtx low = gen_reg_rtx (DImode);
2897 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2899 rtx high = gen_reg_rtx (DImode);
2900 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2902 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2903 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2907 ;; The default expansion of multi3 using umuldi3_highpart will perform
2908 ;; the additions in an order that fails to combine into two madd insns.
2909 (define_expand "multi3"
2910 [(set (match_operand:TI 0 "register_operand")
2911 (mult:TI (match_operand:TI 1 "register_operand")
2912 (match_operand:TI 2 "register_operand")))]
2915 rtx l0 = gen_reg_rtx (DImode);
2916 rtx l1 = gen_lowpart (DImode, operands[1]);
2917 rtx l2 = gen_lowpart (DImode, operands[2]);
2918 rtx h0 = gen_reg_rtx (DImode);
2919 rtx h1 = gen_highpart (DImode, operands[1]);
2920 rtx h2 = gen_highpart (DImode, operands[2]);
2922 emit_insn (gen_muldi3 (l0, l1, l2));
2923 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2924 emit_insn (gen_madddi (h0, h1, l2, h0));
2925 emit_insn (gen_madddi (h0, l1, h2, h0));
2927 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2928 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2932 (define_insn "<su>muldi3_highpart"
2933 [(set (match_operand:DI 0 "register_operand" "=r")
2937 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2938 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2941 "<su>mulh\\t%0, %1, %2"
2942 [(set_attr "type" "<su>mull")]
2945 (define_insn "<su_optab>div<mode>3"
2946 [(set (match_operand:GPI 0 "register_operand" "=r")
2947 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2948 (match_operand:GPI 2 "register_operand" "r")))]
2950 "<su>div\\t%<w>0, %<w>1, %<w>2"
2951 [(set_attr "type" "<su>div")]
2954 ;; zero_extend version of above
2955 (define_insn "*<su_optab>divsi3_uxtw"
2956 [(set (match_operand:DI 0 "register_operand" "=r")
2958 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2959 (match_operand:SI 2 "register_operand" "r"))))]
2961 "<su>div\\t%w0, %w1, %w2"
2962 [(set_attr "type" "<su>div")]
2965 ;; -------------------------------------------------------------------
2967 ;; -------------------------------------------------------------------
2969 (define_insn "cmp<mode>"
2970 [(set (reg:CC CC_REGNUM)
2971 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2972 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2978 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2981 (define_insn "fcmp<mode>"
2982 [(set (reg:CCFP CC_REGNUM)
2983 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2984 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2988 fcmp\\t%<s>0, %<s>1"
2989 [(set_attr "type" "fcmp<s>")]
2992 (define_insn "fcmpe<mode>"
2993 [(set (reg:CCFPE CC_REGNUM)
2994 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2995 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2999 fcmpe\\t%<s>0, %<s>1"
3000 [(set_attr "type" "fcmp<s>")]
3003 (define_insn "*cmp_swp_<shift>_reg<mode>"
3004 [(set (reg:CC_SWP CC_REGNUM)
3005 (compare:CC_SWP (ASHIFT:GPI
3006 (match_operand:GPI 0 "register_operand" "r")
3007 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3008 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3010 "cmp\\t%<w>2, %<w>0, <shift> %1"
3011 [(set_attr "type" "alus_shift_imm")]
3014 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3015 [(set (reg:CC_SWP CC_REGNUM)
3016 (compare:CC_SWP (ANY_EXTEND:GPI
3017 (match_operand:ALLX 0 "register_operand" "r"))
3018 (match_operand:GPI 1 "register_operand" "r")))]
3020 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3021 [(set_attr "type" "alus_ext")]
3024 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3025 [(set (reg:CC_SWP CC_REGNUM)
3026 (compare:CC_SWP (ashift:GPI
3028 (match_operand:ALLX 0 "register_operand" "r"))
3029 (match_operand 1 "aarch64_imm3" "Ui3"))
3030 (match_operand:GPI 2 "register_operand" "r")))]
3032 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3033 [(set_attr "type" "alus_ext")]
3036 ;; -------------------------------------------------------------------
3037 ;; Store-flag and conditional select insns
3038 ;; -------------------------------------------------------------------
3040 (define_expand "cstore<mode>4"
3041 [(set (match_operand:SI 0 "register_operand" "")
3042 (match_operator:SI 1 "aarch64_comparison_operator"
3043 [(match_operand:GPI 2 "register_operand" "")
3044 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3047 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3049 operands[3] = const0_rtx;
3053 (define_expand "cstorecc4"
3054 [(set (match_operand:SI 0 "register_operand")
3055 (match_operator 1 "aarch64_comparison_operator_mode"
3056 [(match_operand 2 "cc_register")
3057 (match_operand 3 "const0_operand")]))]
3060 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3065 (define_expand "cstore<mode>4"
3066 [(set (match_operand:SI 0 "register_operand" "")
3067 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3068 [(match_operand:GPF 2 "register_operand" "")
3069 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3072 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3074 operands[3] = const0_rtx;
3078 (define_insn "aarch64_cstore<mode>"
3079 [(set (match_operand:ALLI 0 "register_operand" "=r")
3080 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3081 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3084 [(set_attr "type" "csel")]
3087 ;; For a 24-bit immediate CST we can optimize the compare for equality
3088 ;; and branch sequence from:
3090 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3093 ;; into the shorter:
3094 ;; sub x0, x1, #(CST & 0xfff000)
3095 ;; subs x0, x0, #(CST & 0x000fff)
3096 ;; cset x2, <ne, eq>.
3097 (define_insn_and_split "*compare_cstore<mode>_insn"
3098 [(set (match_operand:GPI 0 "register_operand" "=r")
3099 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3100 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3101 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3102 && !aarch64_plus_operand (operands[2], <MODE>mode)
3103 && !reload_completed"
3108 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3109 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3110 rtx tmp = gen_reg_rtx (<MODE>mode);
3111 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3112 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3113 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3114 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3115 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3118 [(set_attr "type" "csel")]
3121 ;; zero_extend version of the above
3122 (define_insn "*cstoresi_insn_uxtw"
3123 [(set (match_operand:DI 0 "register_operand" "=r")
3125 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3126 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3129 [(set_attr "type" "csel")]
3132 (define_insn "cstore<mode>_neg"
3133 [(set (match_operand:ALLI 0 "register_operand" "=r")
3134 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3135 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3137 "csetm\\t%<w>0, %m1"
3138 [(set_attr "type" "csel")]
3141 ;; zero_extend version of the above
3142 (define_insn "*cstoresi_neg_uxtw"
3143 [(set (match_operand:DI 0 "register_operand" "=r")
3145 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3146 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3149 [(set_attr "type" "csel")]
3152 (define_expand "cmov<mode>6"
3153 [(set (match_operand:GPI 0 "register_operand" "")
3155 (match_operator 1 "aarch64_comparison_operator"
3156 [(match_operand:GPI 2 "register_operand" "")
3157 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3158 (match_operand:GPI 4 "register_operand" "")
3159 (match_operand:GPI 5 "register_operand" "")))]
3162 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3164 operands[3] = const0_rtx;
3168 (define_expand "cmov<mode>6"
3169 [(set (match_operand:GPF 0 "register_operand" "")
3171 (match_operator 1 "aarch64_comparison_operator"
3172 [(match_operand:GPF 2 "register_operand" "")
3173 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3174 (match_operand:GPF 4 "register_operand" "")
3175 (match_operand:GPF 5 "register_operand" "")))]
3178 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3180 operands[3] = const0_rtx;
3184 (define_insn "*cmov<mode>_insn"
3185 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3187 (match_operator 1 "aarch64_comparison_operator"
3188 [(match_operand 2 "cc_register" "") (const_int 0)])
3189 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3190 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3191 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3192 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3193 ;; Final two alternatives should be unreachable, but included for completeness
3195 csel\\t%<w>0, %<w>3, %<w>4, %m1
3196 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3197 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3198 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3199 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3202 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3205 ;; zero_extend version of above
3206 (define_insn "*cmovsi_insn_uxtw"
3207 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3210 (match_operator 1 "aarch64_comparison_operator"
3211 [(match_operand 2 "cc_register" "") (const_int 0)])
3212 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3213 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3214 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3215 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3216 ;; Final two alternatives should be unreachable, but included for completeness
3218 csel\\t%w0, %w3, %w4, %m1
3219 csinv\\t%w0, %w3, wzr, %m1
3220 csinv\\t%w0, %w4, wzr, %M1
3221 csinc\\t%w0, %w3, wzr, %m1
3222 csinc\\t%w0, %w4, wzr, %M1
3225 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3228 (define_insn "*cmovdi_insn_uxtw"
3229 [(set (match_operand:DI 0 "register_operand" "=r")
3231 (match_operator 1 "aarch64_comparison_operator"
3232 [(match_operand 2 "cc_register" "") (const_int 0)])
3233 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3234 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3236 "csel\\t%w0, %w3, %w4, %m1"
3237 [(set_attr "type" "csel")]
3240 (define_insn "*cmov<mode>_insn"
3241 [(set (match_operand:GPF 0 "register_operand" "=w")
3243 (match_operator 1 "aarch64_comparison_operator"
3244 [(match_operand 2 "cc_register" "") (const_int 0)])
3245 (match_operand:GPF 3 "register_operand" "w")
3246 (match_operand:GPF 4 "register_operand" "w")))]
3248 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3249 [(set_attr "type" "fcsel")]
3252 (define_expand "mov<mode>cc"
3253 [(set (match_operand:ALLI 0 "register_operand" "")
3254 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3255 (match_operand:ALLI 2 "register_operand" "")
3256 (match_operand:ALLI 3 "register_operand" "")))]
3260 enum rtx_code code = GET_CODE (operands[1]);
3262 if (code == UNEQ || code == LTGT)
3265 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3266 XEXP (operands[1], 1));
3267 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3271 (define_expand "mov<GPF:mode><GPI:mode>cc"
3272 [(set (match_operand:GPI 0 "register_operand" "")
3273 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3274 (match_operand:GPF 2 "register_operand" "")
3275 (match_operand:GPF 3 "register_operand" "")))]
3279 enum rtx_code code = GET_CODE (operands[1]);
3281 if (code == UNEQ || code == LTGT)
3284 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3285 XEXP (operands[1], 1));
3286 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3290 (define_expand "mov<mode>cc"
3291 [(set (match_operand:GPF 0 "register_operand" "")
3292 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3293 (match_operand:GPF 2 "register_operand" "")
3294 (match_operand:GPF 3 "register_operand" "")))]
3298 enum rtx_code code = GET_CODE (operands[1]);
3300 if (code == UNEQ || code == LTGT)
3303 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3304 XEXP (operands[1], 1));
3305 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3309 (define_expand "<neg_not_op><mode>cc"
3310 [(set (match_operand:GPI 0 "register_operand" "")
3311 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3312 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3313 (match_operand:GPI 3 "register_operand" "")))]
3317 enum rtx_code code = GET_CODE (operands[1]);
3319 if (code == UNEQ || code == LTGT)
3322 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3323 XEXP (operands[1], 1));
3324 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3328 ;; CRC32 instructions.
3329 (define_insn "aarch64_<crc_variant>"
3330 [(set (match_operand:SI 0 "register_operand" "=r")
3331 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3332 (match_operand:<crc_mode> 2 "register_operand" "r")]
3336 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3337 return "<crc_variant>\\t%w0, %w1, %x2";
3339 return "<crc_variant>\\t%w0, %w1, %w2";
3341 [(set_attr "type" "crc")]
3344 (define_insn "*csinc2<mode>_insn"
3345 [(set (match_operand:GPI 0 "register_operand" "=r")
3346 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3347 (match_operand:GPI 1 "register_operand" "r")))]
3349 "cinc\\t%<w>0, %<w>1, %m2"
3350 [(set_attr "type" "csel")]
3353 (define_insn "csinc3<mode>_insn"
3354 [(set (match_operand:GPI 0 "register_operand" "=r")
3356 (match_operand 1 "aarch64_comparison_operation" "")
3357 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3359 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3361 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3362 [(set_attr "type" "csel")]
3365 (define_insn "*csinv3<mode>_insn"
3366 [(set (match_operand:GPI 0 "register_operand" "=r")
3368 (match_operand 1 "aarch64_comparison_operation" "")
3369 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3370 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3372 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3373 [(set_attr "type" "csel")]
3376 (define_insn "csneg3_uxtw_insn"
3377 [(set (match_operand:DI 0 "register_operand" "=r")
3380 (match_operand 1 "aarch64_comparison_operation" "")
3381 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3382 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3384 "csneg\\t%w0, %w3, %w2, %M1"
3385 [(set_attr "type" "csel")]
3388 (define_insn "csneg3<mode>_insn"
3389 [(set (match_operand:GPI 0 "register_operand" "=r")
3391 (match_operand 1 "aarch64_comparison_operation" "")
3392 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3393 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3395 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3396 [(set_attr "type" "csel")]
3399 ;; -------------------------------------------------------------------
3400 ;; Logical operations
3401 ;; -------------------------------------------------------------------
3404 (define_insn_and_split "*aarch64_and<mode>_imm2"
3405 [(set (match_operand:GPI 0 "register_operand" "=rk")
3406 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3407 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3413 HOST_WIDE_INT val = INTVAL (operands[2]);
3414 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3415 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3417 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3418 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3423 (define_insn "<optab><mode>3"
3424 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3425 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3426 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3429 <logical>\\t%<w>0, %<w>1, %<w>2
3430 <logical>\\t%<w>0, %<w>1, %2
3431 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3432 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3433 (set_attr "simd" "*,*,yes")]
3436 ;; zero_extend version of above
3437 (define_insn "*<optab>si3_uxtw"
3438 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3440 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3441 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3444 <logical>\\t%w0, %w1, %w2
3445 <logical>\\t%w0, %w1, %2"
3446 [(set_attr "type" "logic_reg,logic_imm")]
3449 (define_insn "*and<mode>3_compare0"
3450 [(set (reg:CC_NZ CC_REGNUM)
3452 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3453 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3455 (set (match_operand:GPI 0 "register_operand" "=r,r")
3456 (and:GPI (match_dup 1) (match_dup 2)))]
3459 ands\\t%<w>0, %<w>1, %<w>2
3460 ands\\t%<w>0, %<w>1, %2"
3461 [(set_attr "type" "logics_reg,logics_imm")]
3464 ;; zero_extend version of above
3465 (define_insn "*andsi3_compare0_uxtw"
3466 [(set (reg:CC_NZ CC_REGNUM)
3468 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3469 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3471 (set (match_operand:DI 0 "register_operand" "=r,r")
3472 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3475 ands\\t%w0, %w1, %w2
3476 ands\\t%w0, %w1, %2"
3477 [(set_attr "type" "logics_reg,logics_imm")]
3480 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3481 [(set (reg:CC_NZ CC_REGNUM)
3484 (match_operand:GPI 1 "register_operand" "r")
3485 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3486 (match_operand:GPI 3 "register_operand" "r"))
3488 (set (match_operand:GPI 0 "register_operand" "=r")
3489 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3491 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3492 [(set_attr "type" "logics_shift_imm")]
3495 ;; zero_extend version of above
3496 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3497 [(set (reg:CC_NZ CC_REGNUM)
3500 (match_operand:SI 1 "register_operand" "r")
3501 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3502 (match_operand:SI 3 "register_operand" "r"))
3504 (set (match_operand:DI 0 "register_operand" "=r")
3505 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3508 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3509 [(set_attr "type" "logics_shift_imm")]
3512 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3513 [(set (match_operand:GPI 0 "register_operand" "=r")
3514 (LOGICAL:GPI (SHIFT:GPI
3515 (match_operand:GPI 1 "register_operand" "r")
3516 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3517 (match_operand:GPI 3 "register_operand" "r")))]
3519 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3520 [(set_attr "type" "logic_shift_imm")]
3523 (define_insn "*<optab>_rol<mode>3"
3524 [(set (match_operand:GPI 0 "register_operand" "=r")
3525 (LOGICAL:GPI (rotate:GPI
3526 (match_operand:GPI 1 "register_operand" "r")
3527 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3528 (match_operand:GPI 3 "register_operand" "r")))]
3530 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3531 [(set_attr "type" "logic_shift_imm")]
3534 ;; zero_extend versions of above
3535 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3536 [(set (match_operand:DI 0 "register_operand" "=r")
3538 (LOGICAL:SI (SHIFT:SI
3539 (match_operand:SI 1 "register_operand" "r")
3540 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3541 (match_operand:SI 3 "register_operand" "r"))))]
3543 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3544 [(set_attr "type" "logic_shift_imm")]
3547 (define_insn "*<optab>_rolsi3_uxtw"
3548 [(set (match_operand:DI 0 "register_operand" "=r")
3550 (LOGICAL:SI (rotate:SI
3551 (match_operand:SI 1 "register_operand" "r")
3552 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3553 (match_operand:SI 3 "register_operand" "r"))))]
3555 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3556 [(set_attr "type" "logic_shift_imm")]
3559 (define_insn "one_cmpl<mode>2"
3560 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3561 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3566 [(set_attr "type" "logic_reg,neon_logic")
3567 (set_attr "simd" "*,yes")]
3570 (define_insn "*one_cmpl_<optab><mode>2"
3571 [(set (match_operand:GPI 0 "register_operand" "=r")
3572 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3573 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3575 "mvn\\t%<w>0, %<w>1, <shift> %2"
3576 [(set_attr "type" "logic_shift_imm")]
3579 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3581 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3582 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3583 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3584 (match_operand:GPI 2 "register_operand" "r,w")))]
3587 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3588 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3589 [(set_attr "type" "logic_reg,neon_logic")
3590 (set_attr "simd" "*,yes")]
3593 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3594 [(set (match_operand:DI 0 "register_operand" "=r")
3596 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3597 (match_operand:SI 2 "register_operand" "r"))))]
3599 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3600 [(set_attr "type" "logic_reg")]
3603 (define_insn "*xor_one_cmplsidi3_ze"
3604 [(set (match_operand:DI 0 "register_operand" "=r")
3606 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3607 (match_operand:SI 2 "register_operand" "r")))))]
3609 "eon\\t%w0, %w1, %w2"
3610 [(set_attr "type" "logic_reg")]
3613 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3614 ;; eon does not operate on SIMD registers so the vector variant must be split.
3615 (define_insn_and_split "*xor_one_cmpl<mode>3"
3616 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3617 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3618 (match_operand:GPI 2 "register_operand" "r,w"))))]
3621 eon\\t%<w>0, %<w>1, %<w>2
3623 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3624 [(set (match_operand:GPI 0 "register_operand" "=w")
3625 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3626 (match_operand:GPI 2 "register_operand" "w")))
3627 (set (match_dup 0) (not:GPI (match_dup 0)))]
3629 [(set_attr "type" "logic_reg,multiple")
3630 (set_attr "simd" "*,yes")]
3633 (define_insn "*and_one_cmpl<mode>3_compare0"
3634 [(set (reg:CC_NZ CC_REGNUM)
3637 (match_operand:GPI 1 "register_operand" "r"))
3638 (match_operand:GPI 2 "register_operand" "r"))
3640 (set (match_operand:GPI 0 "register_operand" "=r")
3641 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3643 "bics\\t%<w>0, %<w>2, %<w>1"
3644 [(set_attr "type" "logics_reg")]
3647 ;; zero_extend version of above
3648 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3649 [(set (reg:CC_NZ CC_REGNUM)
3652 (match_operand:SI 1 "register_operand" "r"))
3653 (match_operand:SI 2 "register_operand" "r"))
3655 (set (match_operand:DI 0 "register_operand" "=r")
3656 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3658 "bics\\t%w0, %w2, %w1"
3659 [(set_attr "type" "logics_reg")]
3662 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3663 [(set (reg:CC_NZ CC_REGNUM)
3666 (match_operand:GPI 0 "register_operand" "r"))
3667 (match_operand:GPI 1 "register_operand" "r"))
3670 "bics\\t<w>zr, %<w>1, %<w>0"
3671 [(set_attr "type" "logics_reg")]
3674 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3675 [(set (match_operand:GPI 0 "register_operand" "=r")
3676 (LOGICAL:GPI (not:GPI
3678 (match_operand:GPI 1 "register_operand" "r")
3679 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3680 (match_operand:GPI 3 "register_operand" "r")))]
3682 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3683 [(set_attr "type" "logic_shift_imm")]
3686 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3687 [(set (match_operand:GPI 0 "register_operand" "=r")
3690 (match_operand:GPI 1 "register_operand" "r")
3691 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3692 (match_operand:GPI 3 "register_operand" "r"))))]
3694 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3695 [(set_attr "type" "logic_shift_imm")]
3698 ;; Zero-extend version of the above.
3699 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3700 [(set (match_operand:DI 0 "register_operand" "=r")
3704 (match_operand:SI 1 "register_operand" "r")
3705 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3706 (match_operand:SI 3 "register_operand" "r")))))]
3708 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3709 [(set_attr "type" "logic_shift_imm")]
3712 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3713 [(set (reg:CC_NZ CC_REGNUM)
3717 (match_operand:GPI 1 "register_operand" "r")
3718 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3719 (match_operand:GPI 3 "register_operand" "r"))
3721 (set (match_operand:GPI 0 "register_operand" "=r")
3724 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3726 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3727 [(set_attr "type" "logics_shift_imm")]
3730 ;; zero_extend version of above
3731 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3732 [(set (reg:CC_NZ CC_REGNUM)
3736 (match_operand:SI 1 "register_operand" "r")
3737 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3738 (match_operand:SI 3 "register_operand" "r"))
3740 (set (match_operand:DI 0 "register_operand" "=r")
3741 (zero_extend:DI (and:SI
3743 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3745 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3746 [(set_attr "type" "logics_shift_imm")]
3749 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3750 [(set (reg:CC_NZ CC_REGNUM)
3754 (match_operand:GPI 0 "register_operand" "r")
3755 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3756 (match_operand:GPI 2 "register_operand" "r"))
3759 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3760 [(set_attr "type" "logics_shift_imm")]
3763 (define_insn "clz<mode>2"
3764 [(set (match_operand:GPI 0 "register_operand" "=r")
3765 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3767 "clz\\t%<w>0, %<w>1"
3768 [(set_attr "type" "clz")]
3771 (define_expand "ffs<mode>2"
3772 [(match_operand:GPI 0 "register_operand")
3773 (match_operand:GPI 1 "register_operand")]
3776 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3777 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3779 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3780 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3781 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3786 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3793 (define_expand "popcount<mode>2"
3794 [(match_operand:GPI 0 "register_operand")
3795 (match_operand:GPI 1 "register_operand")]
3798 rtx v = gen_reg_rtx (V8QImode);
3799 rtx v1 = gen_reg_rtx (V8QImode);
3800 rtx r = gen_reg_rtx (QImode);
3801 rtx in = operands[1];
3802 rtx out = operands[0];
3803 if(<MODE>mode == SImode)
3806 tmp = gen_reg_rtx (DImode);
3807 /* If we have SImode, zero extend to DImode, pop count does
3808 not change if we have extra zeros. */
3809 emit_insn (gen_zero_extendsidi2 (tmp, in));
3812 emit_move_insn (v, gen_lowpart (V8QImode, in));
3813 emit_insn (gen_popcountv8qi2 (v1, v));
3814 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3815 emit_insn (gen_zero_extendqi<mode>2 (out, r));
3819 (define_insn "clrsb<mode>2"
3820 [(set (match_operand:GPI 0 "register_operand" "=r")
3821 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3823 "cls\\t%<w>0, %<w>1"
3824 [(set_attr "type" "clz")]
3827 (define_insn "rbit<mode>2"
3828 [(set (match_operand:GPI 0 "register_operand" "=r")
3829 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3831 "rbit\\t%<w>0, %<w>1"
3832 [(set_attr "type" "rbit")]
3835 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3836 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3837 ;; expression and split after reload to enable scheduling them apart if
3840 (define_insn_and_split "ctz<mode>2"
3841 [(set (match_operand:GPI 0 "register_operand" "=r")
3842 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3848 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3849 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3853 (define_insn "*and<mode>_compare0"
3854 [(set (reg:CC_NZ CC_REGNUM)
3856 (match_operand:SHORT 0 "register_operand" "r")
3859 "tst\\t%<w>0, <short_mask>"
3860 [(set_attr "type" "alus_imm")]
3863 (define_insn "*ands<mode>_compare0"
3864 [(set (reg:CC_NZ CC_REGNUM)
3866 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3868 (set (match_operand:GPI 0 "register_operand" "=r")
3869 (zero_extend:GPI (match_dup 1)))]
3871 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3872 [(set_attr "type" "alus_imm")]
3875 (define_insn "*and<mode>3nr_compare0"
3876 [(set (reg:CC_NZ CC_REGNUM)
3878 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3879 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3885 [(set_attr "type" "logics_reg,logics_imm")]
3888 (define_insn "*and<mode>3nr_compare0_zextract"
3889 [(set (reg:CC_NZ CC_REGNUM)
3891 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3892 (match_operand:GPI 1 "const_int_operand" "n")
3893 (match_operand:GPI 2 "const_int_operand" "n"))
3895 "INTVAL (operands[1]) > 0
3896 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3897 <= GET_MODE_BITSIZE (<MODE>mode))
3898 && aarch64_bitmask_imm (
3899 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3904 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3905 return "tst\\t%<w>0, %1";
3907 [(set_attr "type" "logics_shift_imm")]
3910 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3911 [(set (reg:CC_NZ CC_REGNUM)
3914 (match_operand:GPI 0 "register_operand" "r")
3915 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3916 (match_operand:GPI 2 "register_operand" "r"))
3919 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3920 [(set_attr "type" "logics_shift_imm")]
3923 ;; -------------------------------------------------------------------
3925 ;; -------------------------------------------------------------------
3927 (define_expand "<optab><mode>3"
3928 [(set (match_operand:GPI 0 "register_operand")
3929 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3930 (match_operand:QI 2 "nonmemory_operand")))]
3933 if (CONST_INT_P (operands[2]))
3935 operands[2] = GEN_INT (INTVAL (operands[2])
3936 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3938 if (operands[2] == const0_rtx)
3940 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3947 (define_expand "ashl<mode>3"
3948 [(set (match_operand:SHORT 0 "register_operand")
3949 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3950 (match_operand:QI 2 "const_int_operand")))]
3953 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3955 if (operands[2] == const0_rtx)
3957 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3963 (define_expand "rotr<mode>3"
3964 [(set (match_operand:GPI 0 "register_operand")
3965 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3966 (match_operand:QI 2 "nonmemory_operand")))]
3969 if (CONST_INT_P (operands[2]))
3971 operands[2] = GEN_INT (INTVAL (operands[2])
3972 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3974 if (operands[2] == const0_rtx)
3976 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3983 (define_expand "rotl<mode>3"
3984 [(set (match_operand:GPI 0 "register_operand")
3985 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3986 (match_operand:QI 2 "nonmemory_operand")))]
3989 /* (SZ - cnt) % SZ == -cnt % SZ */
3990 if (CONST_INT_P (operands[2]))
3992 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3993 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3994 if (operands[2] == const0_rtx)
3996 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4001 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4006 ;; Logical left shift using SISD or Integer instruction
4007 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4008 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4010 (match_operand:GPI 1 "register_operand" "r,r,w,w")
4011 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4014 lsl\t%<w>0, %<w>1, %2
4015 lsl\t%<w>0, %<w>1, %<w>2
4016 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4017 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4018 [(set_attr "simd" "no,no,yes,yes")
4019 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4022 ;; Logical right shift using SISD or Integer instruction
4023 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4024 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4026 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4027 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
4030 lsr\t%<w>0, %<w>1, %2
4031 lsr\t%<w>0, %<w>1, %<w>2
4032 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4035 [(set_attr "simd" "no,no,yes,yes,yes")
4036 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4040 [(set (match_operand:DI 0 "aarch64_simd_register")
4042 (match_operand:DI 1 "aarch64_simd_register")
4043 (match_operand:QI 2 "aarch64_simd_register")))]
4044 "TARGET_SIMD && reload_completed"
4046 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4048 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4050 operands[3] = gen_lowpart (QImode, operands[0]);
4055 [(set (match_operand:SI 0 "aarch64_simd_register")
4057 (match_operand:SI 1 "aarch64_simd_register")
4058 (match_operand:QI 2 "aarch64_simd_register")))]
4059 "TARGET_SIMD && reload_completed"
4061 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4063 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4065 operands[3] = gen_lowpart (QImode, operands[0]);
4069 ;; Arithmetic right shift using SISD or Integer instruction
4070 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4071 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4073 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4074 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4077 asr\t%<w>0, %<w>1, %2
4078 asr\t%<w>0, %<w>1, %<w>2
4079 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4082 [(set_attr "simd" "no,no,yes,yes,yes")
4083 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4087 [(set (match_operand:DI 0 "aarch64_simd_register")
4089 (match_operand:DI 1 "aarch64_simd_register")
4090 (match_operand:QI 2 "aarch64_simd_register")))]
4091 "TARGET_SIMD && reload_completed"
4093 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4095 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4097 operands[3] = gen_lowpart (QImode, operands[0]);
4102 [(set (match_operand:SI 0 "aarch64_simd_register")
4104 (match_operand:SI 1 "aarch64_simd_register")
4105 (match_operand:QI 2 "aarch64_simd_register")))]
4106 "TARGET_SIMD && reload_completed"
4108 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4110 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4112 operands[3] = gen_lowpart (QImode, operands[0]);
4116 (define_insn "*aarch64_sisd_ushl"
4117 [(set (match_operand:DI 0 "register_operand" "=w")
4118 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4119 (match_operand:QI 2 "register_operand" "w")]
4122 "ushl\t%d0, %d1, %d2"
4123 [(set_attr "simd" "yes")
4124 (set_attr "type" "neon_shift_reg")]
4127 (define_insn "*aarch64_ushl_2s"
4128 [(set (match_operand:SI 0 "register_operand" "=w")
4129 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4130 (match_operand:QI 2 "register_operand" "w")]
4133 "ushl\t%0.2s, %1.2s, %2.2s"
4134 [(set_attr "simd" "yes")
4135 (set_attr "type" "neon_shift_reg")]
4138 (define_insn "*aarch64_sisd_sshl"
4139 [(set (match_operand:DI 0 "register_operand" "=w")
4140 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4141 (match_operand:QI 2 "register_operand" "w")]
4144 "sshl\t%d0, %d1, %d2"
4145 [(set_attr "simd" "yes")
4146 (set_attr "type" "neon_shift_reg")]
4149 (define_insn "*aarch64_sshl_2s"
4150 [(set (match_operand:SI 0 "register_operand" "=w")
4151 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4152 (match_operand:QI 2 "register_operand" "w")]
4155 "sshl\t%0.2s, %1.2s, %2.2s"
4156 [(set_attr "simd" "yes")
4157 (set_attr "type" "neon_shift_reg")]
4160 (define_insn "*aarch64_sisd_neg_qi"
4161 [(set (match_operand:QI 0 "register_operand" "=w")
4162 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4166 [(set_attr "simd" "yes")
4167 (set_attr "type" "neon_neg")]
4171 (define_insn "*ror<mode>3_insn"
4172 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4174 (match_operand:GPI 1 "register_operand" "r,r")
4175 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4178 ror\\t%<w>0, %<w>1, %2
4179 ror\\t%<w>0, %<w>1, %<w>2"
4180 [(set_attr "type" "rotate_imm,shift_reg")]
4183 ;; zero_extend version of above
4184 (define_insn "*<optab>si3_insn_uxtw"
4185 [(set (match_operand:DI 0 "register_operand" "=r,r")
4186 (zero_extend:DI (SHIFT:SI
4187 (match_operand:SI 1 "register_operand" "r,r")
4188 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4191 <shift>\\t%w0, %w1, %2
4192 <shift>\\t%w0, %w1, %w2"
4193 [(set_attr "type" "bfx,shift_reg")]
4196 (define_insn "*<optab><mode>3_insn"
4197 [(set (match_operand:SHORT 0 "register_operand" "=r")
4198 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4199 (match_operand 2 "const_int_operand" "n")))]
4200 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4202 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4203 return "<bfshift>\t%w0, %w1, %2, %3";
4205 [(set_attr "type" "bfx")]
4208 (define_insn "*extr<mode>5_insn"
4209 [(set (match_operand:GPI 0 "register_operand" "=r")
4210 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4211 (match_operand 3 "const_int_operand" "n"))
4212 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4213 (match_operand 4 "const_int_operand" "n"))))]
4214 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4215 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4216 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4217 [(set_attr "type" "rotate_imm")]
4220 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4221 ;; so we have to match both orderings.
4222 (define_insn "*extr<mode>5_insn_alt"
4223 [(set (match_operand:GPI 0 "register_operand" "=r")
4224 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4225 (match_operand 4 "const_int_operand" "n"))
4226 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4227 (match_operand 3 "const_int_operand" "n"))))]
4228 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4229 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4230 == GET_MODE_BITSIZE (<MODE>mode))"
4231 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4232 [(set_attr "type" "rotate_imm")]
4235 ;; zero_extend version of the above
4236 (define_insn "*extrsi5_insn_uxtw"
4237 [(set (match_operand:DI 0 "register_operand" "=r")
4239 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4240 (match_operand 3 "const_int_operand" "n"))
4241 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4242 (match_operand 4 "const_int_operand" "n")))))]
4243 "UINTVAL (operands[3]) < 32 &&
4244 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4245 "extr\\t%w0, %w1, %w2, %4"
4246 [(set_attr "type" "rotate_imm")]
4249 (define_insn "*extrsi5_insn_uxtw_alt"
4250 [(set (match_operand:DI 0 "register_operand" "=r")
4252 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4253 (match_operand 4 "const_int_operand" "n"))
4254 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4255 (match_operand 3 "const_int_operand" "n")))))]
4256 "UINTVAL (operands[3]) < 32 &&
4257 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4258 "extr\\t%w0, %w1, %w2, %4"
4259 [(set_attr "type" "rotate_imm")]
4262 (define_insn "*ror<mode>3_insn"
4263 [(set (match_operand:GPI 0 "register_operand" "=r")
4264 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4265 (match_operand 2 "const_int_operand" "n")))]
4266 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4268 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4269 return "ror\\t%<w>0, %<w>1, %3";
4271 [(set_attr "type" "rotate_imm")]
4274 ;; zero_extend version of the above
4275 (define_insn "*rorsi3_insn_uxtw"
4276 [(set (match_operand:DI 0 "register_operand" "=r")
4278 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4279 (match_operand 2 "const_int_operand" "n"))))]
4280 "UINTVAL (operands[2]) < 32"
4282 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4283 return "ror\\t%w0, %w1, %3";
4285 [(set_attr "type" "rotate_imm")]
4288 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4289 [(set (match_operand:GPI 0 "register_operand" "=r")
4291 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4292 (match_operand 2 "const_int_operand" "n"))))]
4293 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4295 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4296 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4298 [(set_attr "type" "bfx")]
4301 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4302 [(set (match_operand:GPI 0 "register_operand" "=r")
4304 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4305 (match_operand 2 "const_int_operand" "n"))))]
4306 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4308 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4309 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4311 [(set_attr "type" "bfx")]
4314 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4315 [(set (match_operand:GPI 0 "register_operand" "=r")
4317 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4318 (match_operand 2 "const_int_operand" "n"))))]
4319 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4321 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4322 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4324 [(set_attr "type" "bfx")]
4327 ;; -------------------------------------------------------------------
4329 ;; -------------------------------------------------------------------
4331 (define_expand "<optab>"
4332 [(set (match_operand:DI 0 "register_operand" "=r")
4333 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4335 "aarch64_simd_shift_imm_offset_di")
4336 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4339 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4340 1, GET_MODE_BITSIZE (DImode) - 1))
4346 (define_insn "*<optab><mode>"
4347 [(set (match_operand:GPI 0 "register_operand" "=r")
4348 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4350 "aarch64_simd_shift_imm_offset_<mode>" "n")
4352 "aarch64_simd_shift_imm_<mode>" "n")))]
4353 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4354 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4355 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4356 [(set_attr "type" "bfx")]
4359 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4360 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4362 [(set (match_operand:DI 0 "register_operand")
4363 (zero_extract:DI (match_operand:DI 1 "register_operand")
4365 "aarch64_simd_shift_imm_offset_di")
4367 "aarch64_simd_shift_imm_di")))]
4368 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4369 GET_MODE_BITSIZE (DImode) - 1)
4370 && (INTVAL (operands[2]) + INTVAL (operands[3]))
4371 == GET_MODE_BITSIZE (SImode)"
4373 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4375 operands[4] = gen_lowpart (SImode, operands[1]);
4379 ;; Bitfield Insert (insv)
4380 (define_expand "insv<mode>"
4381 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4382 (match_operand 1 "const_int_operand")
4383 (match_operand 2 "const_int_operand"))
4384 (match_operand:GPI 3 "general_operand"))]
4387 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4388 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4389 rtx value = operands[3];
4391 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4394 if (CONST_INT_P (value))
4396 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4398 /* Prefer AND/OR for inserting all zeros or all ones. */
4399 if ((UINTVAL (value) & mask) == 0
4400 || (UINTVAL (value) & mask) == mask)
4403 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4404 if (width == 16 && (pos % 16) == 0)
4407 operands[3] = force_reg (<MODE>mode, value);
4410 (define_insn "*insv_reg<mode>"
4411 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4412 (match_operand 1 "const_int_operand" "n")
4413 (match_operand 2 "const_int_operand" "n"))
4414 (match_operand:GPI 3 "register_operand" "r"))]
4415 "!(UINTVAL (operands[1]) == 0
4416 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4417 > GET_MODE_BITSIZE (<MODE>mode)))"
4418 "bfi\\t%<w>0, %<w>3, %2, %1"
4419 [(set_attr "type" "bfm")]
4422 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4423 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4424 (match_operand 1 "const_int_operand" "n")
4425 (match_operand 2 "const_int_operand" "n"))
4426 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4427 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4428 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4429 [(set_attr "type" "bfm")]
4432 (define_insn "*extr_insv_lower_reg<mode>"
4433 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4434 (match_operand 1 "const_int_operand" "n")
4436 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4438 (match_operand 3 "const_int_operand" "n")))]
4439 "!(UINTVAL (operands[1]) == 0
4440 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4441 > GET_MODE_BITSIZE (<MODE>mode)))"
4442 "bfxil\\t%<w>0, %<w>2, %3, %1"
4443 [(set_attr "type" "bfm")]
4446 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4447 [(set (match_operand:GPI 0 "register_operand" "=r")
4448 (ashift:GPI (ANY_EXTEND:GPI
4449 (match_operand:ALLX 1 "register_operand" "r"))
4450 (match_operand 2 "const_int_operand" "n")))]
4451 "UINTVAL (operands[2]) < <GPI:sizen>"
4453 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4454 ? GEN_INT (<ALLX:sizen>)
4455 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4456 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4458 [(set_attr "type" "bfx")]
4461 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4463 (define_insn "*andim_ashift<mode>_bfiz"
4464 [(set (match_operand:GPI 0 "register_operand" "=r")
4465 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4466 (match_operand 2 "const_int_operand" "n"))
4467 (match_operand 3 "const_int_operand" "n")))]
4468 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4469 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4470 [(set_attr "type" "bfx")]
4473 ;; When the bit position and width of the equivalent extraction add up to 32
4474 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4475 ;; zero-extension of the X-reg.
4477 [(set (match_operand:DI 0 "register_operand")
4478 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4479 (match_operand 2 "const_int_operand"))
4480 (match_operand 3 "const_int_operand")))]
4481 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4482 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4483 == GET_MODE_BITSIZE (SImode)"
4485 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4487 operands[4] = gen_lowpart (SImode, operands[1]);
4491 (define_insn "bswap<mode>2"
4492 [(set (match_operand:GPI 0 "register_operand" "=r")
4493 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4495 "rev\\t%<w>0, %<w>1"
4496 [(set_attr "type" "rev")]
4499 (define_insn "bswaphi2"
4500 [(set (match_operand:HI 0 "register_operand" "=r")
4501 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4504 [(set_attr "type" "rev")]
4507 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4508 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4509 ;; each valid permutation.
4511 (define_insn "rev16<mode>2"
4512 [(set (match_operand:GPI 0 "register_operand" "=r")
4513 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4515 (match_operand:GPI 3 "const_int_operand" "n"))
4516 (and:GPI (lshiftrt:GPI (match_dup 1)
4518 (match_operand:GPI 2 "const_int_operand" "n"))))]
4519 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4520 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4521 "rev16\\t%<w>0, %<w>1"
4522 [(set_attr "type" "rev")]
4525 (define_insn "rev16<mode>2_alt"
4526 [(set (match_operand:GPI 0 "register_operand" "=r")
4527 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4529 (match_operand:GPI 2 "const_int_operand" "n"))
4530 (and:GPI (ashift:GPI (match_dup 1)
4532 (match_operand:GPI 3 "const_int_operand" "n"))))]
4533 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4534 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4535 "rev16\\t%<w>0, %<w>1"
4536 [(set_attr "type" "rev")]
4539 ;; zero_extend version of above
4540 (define_insn "*bswapsi2_uxtw"
4541 [(set (match_operand:DI 0 "register_operand" "=r")
4542 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4545 [(set_attr "type" "rev")]
4548 ;; -------------------------------------------------------------------
4549 ;; Floating-point intrinsics
4550 ;; -------------------------------------------------------------------
4552 ;; frint floating-point round to integral standard patterns.
4553 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4555 (define_insn "<frint_pattern><mode>2"
4556 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4557 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4560 "frint<frint_suffix>\\t%<s>0, %<s>1"
4561 [(set_attr "type" "f_rint<stype>")]
4564 ;; frcvt floating-point round to integer and convert standard patterns.
4565 ;; Expands to lbtrunc, lceil, lfloor, lround.
4566 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4567 [(set (match_operand:GPI 0 "register_operand" "=r")
4569 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4572 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4573 [(set_attr "type" "f_cvtf2i")]
4576 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4577 [(set (match_operand:GPI 0 "register_operand" "=r")
4580 (match_operand:GPF 1 "register_operand" "w")
4581 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4583 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4584 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4586 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4588 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4589 output_asm_insn (buf, operands);
4592 [(set_attr "type" "f_cvtf2i")]
4597 (define_insn "fma<mode>4"
4598 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4599 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4600 (match_operand:GPF_F16 2 "register_operand" "w")
4601 (match_operand:GPF_F16 3 "register_operand" "w")))]
4603 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4604 [(set_attr "type" "fmac<stype>")]
4607 (define_insn "fnma<mode>4"
4608 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4610 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4611 (match_operand:GPF_F16 2 "register_operand" "w")
4612 (match_operand:GPF_F16 3 "register_operand" "w")))]
4614 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4615 [(set_attr "type" "fmac<stype>")]
4618 (define_insn "fms<mode>4"
4619 [(set (match_operand:GPF 0 "register_operand" "=w")
4620 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4621 (match_operand:GPF 2 "register_operand" "w")
4622 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4624 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4625 [(set_attr "type" "fmac<s>")]
4628 (define_insn "fnms<mode>4"
4629 [(set (match_operand:GPF 0 "register_operand" "=w")
4630 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4631 (match_operand:GPF 2 "register_operand" "w")
4632 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4634 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4635 [(set_attr "type" "fmac<s>")]
4638 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4639 (define_insn "*fnmadd<mode>4"
4640 [(set (match_operand:GPF 0 "register_operand" "=w")
4641 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4642 (match_operand:GPF 2 "register_operand" "w")
4643 (match_operand:GPF 3 "register_operand" "w"))))]
4644 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4645 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4646 [(set_attr "type" "fmac<s>")]
4649 ;; -------------------------------------------------------------------
4650 ;; Floating-point conversions
4651 ;; -------------------------------------------------------------------
4653 (define_insn "extendsfdf2"
4654 [(set (match_operand:DF 0 "register_operand" "=w")
4655 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4658 [(set_attr "type" "f_cvt")]
4661 (define_insn "extendhfsf2"
4662 [(set (match_operand:SF 0 "register_operand" "=w")
4663 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4666 [(set_attr "type" "f_cvt")]
4669 (define_insn "extendhfdf2"
4670 [(set (match_operand:DF 0 "register_operand" "=w")
4671 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4674 [(set_attr "type" "f_cvt")]
4677 (define_insn "truncdfsf2"
4678 [(set (match_operand:SF 0 "register_operand" "=w")
4679 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4682 [(set_attr "type" "f_cvt")]
4685 (define_insn "truncsfhf2"
4686 [(set (match_operand:HF 0 "register_operand" "=w")
4687 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4690 [(set_attr "type" "f_cvt")]
4693 (define_insn "truncdfhf2"
4694 [(set (match_operand:HF 0 "register_operand" "=w")
4695 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4698 [(set_attr "type" "f_cvt")]
4701 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4702 [(set (match_operand:GPI 0 "register_operand" "=r")
4703 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4705 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4706 [(set_attr "type" "f_cvtf2i")]
4709 (define_insn "<optab><fcvt_target><GPF:mode>2"
4710 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4711 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4714 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4715 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4716 [(set_attr "simd" "yes,no")
4717 (set_attr "fp" "no,yes")
4718 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4721 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4722 [(set (match_operand:GPF 0 "register_operand" "=w")
4723 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4725 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4726 [(set_attr "type" "f_cvti2f")]
4729 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4730 ;; midend will arrange for an SImode conversion to HFmode to first go
4731 ;; through DFmode, then to HFmode. But first it will try converting
4732 ;; to DImode then down, which would match our DImode pattern below and
4733 ;; give very poor code-generation. So, we must provide our own emulation
4734 ;; of the mid-end logic.
4736 (define_insn "aarch64_fp16_<optab><mode>hf2"
4737 [(set (match_operand:HF 0 "register_operand" "=w")
4738 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4740 "<su_optab>cvtf\t%h0, %<w>1"
4741 [(set_attr "type" "f_cvti2f")]
4744 (define_expand "<optab>sihf2"
4745 [(set (match_operand:HF 0 "register_operand")
4746 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4749 if (TARGET_FP_F16INST)
4750 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4753 rtx convert_target = gen_reg_rtx (DFmode);
4754 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4755 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4761 ;; For DImode there is no wide enough floating-point mode that we
4762 ;; can convert through natively (TFmode would work, but requires a library
4763 ;; call). However, we know that any value >= 65504 will be rounded
4764 ;; to infinity on conversion. This is well within the range of SImode, so
4766 ;; Saturate to SImode.
4767 ;; Convert from that to DFmode
4768 ;; Convert from that to HFmode (phew!).
4769 ;; Note that the saturation to SImode requires the SIMD extensions. If
4770 ;; we ever need to provide this pattern where the SIMD extensions are not
4771 ;; available, we would need a different approach.
4773 (define_expand "<optab>dihf2"
4774 [(set (match_operand:HF 0 "register_operand")
4775 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4776 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4778 if (TARGET_FP_F16INST)
4779 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4782 rtx sat_target = gen_reg_rtx (SImode);
4783 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4784 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4791 ;; Convert between fixed-point and floating-point (scalar modes)
4793 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4794 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4795 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4796 (match_operand:SI 2 "immediate_operand" "i, i")]
4800 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4801 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4802 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4803 (set_attr "fp" "yes, *")
4804 (set_attr "simd" "*, yes")]
4807 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4808 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4809 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4810 (match_operand:SI 2 "immediate_operand" "i, i")]
4814 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4815 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4816 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4817 (set_attr "fp" "yes, *")
4818 (set_attr "simd" "*, yes")]
4821 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4822 [(set (match_operand:GPI 0 "register_operand" "=r")
4823 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4824 (match_operand:SI 2 "immediate_operand" "i")]
4827 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4828 [(set_attr "type" "f_cvtf2i")]
4831 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4832 [(set (match_operand:HF 0 "register_operand" "=w")
4833 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4834 (match_operand:SI 2 "immediate_operand" "i")]
4837 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4838 [(set_attr "type" "f_cvti2f")]
4841 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4842 [(set (match_operand:HI 0 "register_operand" "=w")
4843 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4844 (match_operand:SI 2 "immediate_operand" "i")]
4847 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4848 [(set_attr "type" "neon_fp_to_int_s")]
4851 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4852 [(set (match_operand:HF 0 "register_operand" "=w")
4853 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4854 (match_operand:SI 2 "immediate_operand" "i")]
4857 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4858 [(set_attr "type" "neon_int_to_fp_s")]
4861 ;; -------------------------------------------------------------------
4862 ;; Floating-point arithmetic
4863 ;; -------------------------------------------------------------------
4865 (define_insn "add<mode>3"
4866 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4868 (match_operand:GPF_F16 1 "register_operand" "w")
4869 (match_operand:GPF_F16 2 "register_operand" "w")))]
4871 "fadd\\t%<s>0, %<s>1, %<s>2"
4872 [(set_attr "type" "fadd<stype>")]
4875 (define_insn "sub<mode>3"
4876 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4878 (match_operand:GPF_F16 1 "register_operand" "w")
4879 (match_operand:GPF_F16 2 "register_operand" "w")))]
4881 "fsub\\t%<s>0, %<s>1, %<s>2"
4882 [(set_attr "type" "fadd<stype>")]
4885 (define_insn "mul<mode>3"
4886 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4888 (match_operand:GPF_F16 1 "register_operand" "w")
4889 (match_operand:GPF_F16 2 "register_operand" "w")))]
4891 "fmul\\t%<s>0, %<s>1, %<s>2"
4892 [(set_attr "type" "fmul<stype>")]
4895 (define_insn "*fnmul<mode>3"
4896 [(set (match_operand:GPF 0 "register_operand" "=w")
4898 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4899 (match_operand:GPF 2 "register_operand" "w")))]
4900 "TARGET_FLOAT && !flag_rounding_math"
4901 "fnmul\\t%<s>0, %<s>1, %<s>2"
4902 [(set_attr "type" "fmul<s>")]
4905 (define_insn "*fnmul<mode>3"
4906 [(set (match_operand:GPF 0 "register_operand" "=w")
4908 (match_operand:GPF 1 "register_operand" "w")
4909 (match_operand:GPF 2 "register_operand" "w"))))]
4911 "fnmul\\t%<s>0, %<s>1, %<s>2"
4912 [(set_attr "type" "fmul<s>")]
4915 (define_expand "div<mode>3"
4916 [(set (match_operand:GPF_F16 0 "register_operand")
4917 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4918 (match_operand:GPF_F16 2 "register_operand")))]
4921 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4924 operands[1] = force_reg (<MODE>mode, operands[1]);
4927 (define_insn "*div<mode>3"
4928 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4929 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4930 (match_operand:GPF_F16 2 "register_operand" "w")))]
4932 "fdiv\\t%<s>0, %<s>1, %<s>2"
4933 [(set_attr "type" "fdiv<stype>")]
4936 (define_insn "neg<mode>2"
4937 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4938 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4940 "fneg\\t%<s>0, %<s>1"
4941 [(set_attr "type" "ffarith<stype>")]
4944 (define_expand "sqrt<mode>2"
4945 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4946 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4949 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4953 (define_insn "*sqrt<mode>2"
4954 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4955 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4957 "fsqrt\\t%<s>0, %<s>1"
4958 [(set_attr "type" "fsqrt<stype>")]
4961 (define_insn "abs<mode>2"
4962 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4963 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4965 "fabs\\t%<s>0, %<s>1"
4966 [(set_attr "type" "ffarith<stype>")]
4969 ;; Given that smax/smin do not specify the result when either input is NaN,
4970 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4973 (define_insn "smax<mode>3"
4974 [(set (match_operand:GPF 0 "register_operand" "=w")
4975 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4976 (match_operand:GPF 2 "register_operand" "w")))]
4978 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4979 [(set_attr "type" "f_minmax<s>")]
4982 (define_insn "smin<mode>3"
4983 [(set (match_operand:GPF 0 "register_operand" "=w")
4984 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4985 (match_operand:GPF 2 "register_operand" "w")))]
4987 "fminnm\\t%<s>0, %<s>1, %<s>2"
4988 [(set_attr "type" "f_minmax<s>")]
4991 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4992 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4993 ;; which implement the IEEE fmax ()/fmin () functions.
4994 (define_insn "<maxmin_uns><mode>3"
4995 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4996 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4997 (match_operand:GPF_F16 2 "register_operand" "w")]
5000 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5001 [(set_attr "type" "f_minmax<stype>")]
5004 ;; For copysign (x, y), we want to generate:
5006 ;; LDR d2, #(1 << 63)
5007 ;; BSL v2.8b, [y], [x]
5009 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5010 ;; aarch64_simd_bsldf will select the best suited of these instructions
5011 ;; to generate based on register allocation, and knows how to partially
5012 ;; constant fold based on the values of X and Y, so expand through that.
5014 (define_expand "copysigndf3"
5015 [(match_operand:DF 0 "register_operand")
5016 (match_operand:DF 1 "register_operand")
5017 (match_operand:DF 2 "register_operand")]
5018 "TARGET_FLOAT && TARGET_SIMD"
5020 rtx mask = gen_reg_rtx (DImode);
5021 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5022 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5023 operands[2], operands[1]));
5028 ;; As above, but we must first get to a 64-bit value if we wish to use
5029 ;; aarch64_simd_bslv2sf.
5031 (define_expand "copysignsf3"
5032 [(match_operand:SF 0 "register_operand")
5033 (match_operand:SF 1 "register_operand")
5034 (match_operand:SF 2 "register_operand")]
5035 "TARGET_FLOAT && TARGET_SIMD"
5037 rtx mask = gen_reg_rtx (DImode);
5039 /* Juggle modes to get us in to a vector mode for BSL. */
5040 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
5041 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5042 rtx tmp = gen_reg_rtx (V2SFmode);
5043 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
5044 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
5045 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5050 ;; -------------------------------------------------------------------
5052 ;; -------------------------------------------------------------------
5053 ;; Reload Scalar Floating point modes from constant pool.
5054 ;; The AArch64 port doesn't have __int128 constant move support.
5055 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5056 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5057 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5058 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5061 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5062 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5067 ;; Reload Vector modes from constant pool.
5068 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5069 [(set (match_operand:VALL 0 "register_operand" "=w")
5070 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5071 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5074 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5075 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5080 (define_expand "aarch64_reload_mov<mode>"
5081 [(set (match_operand:TX 0 "register_operand" "=w")
5082 (match_operand:TX 1 "register_operand" "w"))
5083 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5087 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5088 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5089 gen_aarch64_movtilow_tilow (op0, op1);
5090 gen_aarch64_movdi_tihigh (operands[2], op1);
5091 gen_aarch64_movtihigh_di (op0, operands[2]);
5096 ;; The following secondary reload helpers patterns are invoked
5097 ;; after or during reload as we don't want these patterns to start
5098 ;; kicking in during the combiner.
5100 (define_insn "aarch64_movdi_<mode>low"
5101 [(set (match_operand:DI 0 "register_operand" "=r")
5102 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5103 (const_int 64) (const_int 0)))]
5104 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5106 [(set_attr "type" "f_mrc")
5107 (set_attr "length" "4")
5110 (define_insn "aarch64_movdi_<mode>high"
5111 [(set (match_operand:DI 0 "register_operand" "=r")
5112 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5113 (const_int 64) (const_int 64)))]
5114 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5115 "fmov\\t%x0, %1.d[1]"
5116 [(set_attr "type" "f_mrc")
5117 (set_attr "length" "4")
5120 (define_insn "aarch64_mov<mode>high_di"
5121 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5122 (const_int 64) (const_int 64))
5123 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5124 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5125 "fmov\\t%0.d[1], %x1"
5126 [(set_attr "type" "f_mcr")
5127 (set_attr "length" "4")
5130 (define_insn "aarch64_mov<mode>low_di"
5131 [(set (match_operand:TX 0 "register_operand" "=w")
5132 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5133 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5135 [(set_attr "type" "f_mcr")
5136 (set_attr "length" "4")
5139 (define_insn "aarch64_movtilow_tilow"
5140 [(set (match_operand:TI 0 "register_operand" "=w")
5142 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5143 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5145 [(set_attr "type" "fmov")
5146 (set_attr "length" "4")
5149 ;; There is a deliberate reason why the parameters of high and lo_sum's
5150 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5151 ;; and lo_sum's to be used with the labels defining the jump tables in
5154 (define_expand "add_losym"
5155 [(set (match_operand 0 "register_operand" "=r")
5156 (lo_sum (match_operand 1 "register_operand" "r")
5157 (match_operand 2 "aarch64_valid_symref" "S")))]
5160 machine_mode mode = GET_MODE (operands[0]);
5162 emit_insn ((mode == DImode
5164 : gen_add_losym_si) (operands[0],
5170 (define_insn "add_losym_<mode>"
5171 [(set (match_operand:P 0 "register_operand" "=r")
5172 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5173 (match_operand 2 "aarch64_valid_symref" "S")))]
5175 "add\\t%<w>0, %<w>1, :lo12:%a2"
5176 [(set_attr "type" "alu_imm")]
5179 (define_insn "ldr_got_small_<mode>"
5180 [(set (match_operand:PTR 0 "register_operand" "=r")
5181 (unspec:PTR [(mem:PTR (lo_sum:PTR
5182 (match_operand:PTR 1 "register_operand" "r")
5183 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5184 UNSPEC_GOTSMALLPIC))]
5186 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5187 [(set_attr "type" "load1")]
5190 (define_insn "ldr_got_small_sidi"
5191 [(set (match_operand:DI 0 "register_operand" "=r")
5193 (unspec:SI [(mem:SI (lo_sum:DI
5194 (match_operand:DI 1 "register_operand" "r")
5195 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5196 UNSPEC_GOTSMALLPIC)))]
5198 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5199 [(set_attr "type" "load1")]
5202 (define_insn "ldr_got_small_28k_<mode>"
5203 [(set (match_operand:PTR 0 "register_operand" "=r")
5204 (unspec:PTR [(mem:PTR (lo_sum:PTR
5205 (match_operand:PTR 1 "register_operand" "r")
5206 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5207 UNSPEC_GOTSMALLPIC28K))]
5209 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5210 [(set_attr "type" "load1")]
5213 (define_insn "ldr_got_small_28k_sidi"
5214 [(set (match_operand:DI 0 "register_operand" "=r")
5216 (unspec:SI [(mem:SI (lo_sum:DI
5217 (match_operand:DI 1 "register_operand" "r")
5218 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5219 UNSPEC_GOTSMALLPIC28K)))]
5221 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5222 [(set_attr "type" "load1")]
5225 (define_insn "ldr_got_tiny"
5226 [(set (match_operand:DI 0 "register_operand" "=r")
5227 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5228 UNSPEC_GOTTINYPIC))]
5231 [(set_attr "type" "load1")]
5234 (define_insn "aarch64_load_tp_hard"
5235 [(set (match_operand:DI 0 "register_operand" "=r")
5236 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5238 "mrs\\t%0, tpidr_el0"
5239 [(set_attr "type" "mrs")]
5242 ;; The TLS ABI specifically requires that the compiler does not schedule
5243 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5244 ;; Therefore we treat the stubs as an atomic sequence.
5245 (define_expand "tlsgd_small_<mode>"
5246 [(parallel [(set (match_operand 0 "register_operand" "")
5247 (call (mem:DI (match_dup 2)) (const_int 1)))
5248 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5249 (clobber (reg:DI LR_REGNUM))])]
5252 operands[2] = aarch64_tls_get_addr ();
5255 (define_insn "*tlsgd_small_<mode>"
5256 [(set (match_operand 0 "register_operand" "")
5257 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5258 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5259 (clobber (reg:DI LR_REGNUM))
5262 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5263 [(set_attr "type" "call")
5264 (set_attr "length" "16")])
5266 (define_insn "tlsie_small_<mode>"
5267 [(set (match_operand:PTR 0 "register_operand" "=r")
5268 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5269 UNSPEC_GOTSMALLTLS))]
5271 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5272 [(set_attr "type" "load1")
5273 (set_attr "length" "8")]
5276 (define_insn "tlsie_small_sidi"
5277 [(set (match_operand:DI 0 "register_operand" "=r")
5279 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5280 UNSPEC_GOTSMALLTLS)))]
5282 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5283 [(set_attr "type" "load1")
5284 (set_attr "length" "8")]
5287 (define_insn "tlsie_tiny_<mode>"
5288 [(set (match_operand:PTR 0 "register_operand" "=&r")
5289 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5290 (match_operand:PTR 2 "register_operand" "r")]
5291 UNSPEC_GOTTINYTLS))]
5293 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5294 [(set_attr "type" "multiple")
5295 (set_attr "length" "8")]
5298 (define_insn "tlsie_tiny_sidi"
5299 [(set (match_operand:DI 0 "register_operand" "=&r")
5301 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5302 (match_operand:DI 2 "register_operand" "r")
5304 UNSPEC_GOTTINYTLS)))]
5306 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5307 [(set_attr "type" "multiple")
5308 (set_attr "length" "8")]
5311 (define_insn "tlsle12_<mode>"
5312 [(set (match_operand:P 0 "register_operand" "=r")
5313 (unspec:P [(match_operand:P 1 "register_operand" "r")
5314 (match_operand 2 "aarch64_tls_le_symref" "S")]
5317 "add\\t%<w>0, %<w>1, #%L2";
5318 [(set_attr "type" "alu_sreg")
5319 (set_attr "length" "4")]
5322 (define_insn "tlsle24_<mode>"
5323 [(set (match_operand:P 0 "register_operand" "=r")
5324 (unspec:P [(match_operand:P 1 "register_operand" "r")
5325 (match_operand 2 "aarch64_tls_le_symref" "S")]
5328 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5329 [(set_attr "type" "multiple")
5330 (set_attr "length" "8")]
5333 (define_insn "tlsle32_<mode>"
5334 [(set (match_operand:P 0 "register_operand" "=r")
5335 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5338 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5339 [(set_attr "type" "multiple")
5340 (set_attr "length" "8")]
5343 (define_insn "tlsle48_<mode>"
5344 [(set (match_operand:P 0 "register_operand" "=r")
5345 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5348 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5349 [(set_attr "type" "multiple")
5350 (set_attr "length" "12")]
5353 (define_insn "tlsdesc_small_<mode>"
5354 [(set (reg:PTR R0_REGNUM)
5355 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5357 (clobber (reg:DI LR_REGNUM))
5358 (clobber (reg:CC CC_REGNUM))
5359 (clobber (match_scratch:DI 1 "=r"))]
5361 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5362 [(set_attr "type" "call")
5363 (set_attr "length" "16")])
5365 (define_insn "stack_tie"
5366 [(set (mem:BLK (scratch))
5367 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5368 (match_operand:DI 1 "register_operand" "rk")]
5372 [(set_attr "length" "0")]
5375 ;; Pointer authentication patterns are always provided. In architecture
5376 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5377 ;; This lets the user write portable software which authenticates pointers
5378 ;; when run on something which implements ARMv8.3-A, and which runs
5379 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5382 ;; Signing/Authenticating R30 using SP as the salt.
5384 (define_insn "<pauth_mnem_prefix>sp"
5385 [(set (reg:DI R30_REGNUM)
5386 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5388 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5391 ;; Signing/Authenticating X17 using X16 as the salt.
5393 (define_insn "<pauth_mnem_prefix>1716"
5394 [(set (reg:DI R17_REGNUM)
5395 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5397 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5400 ;; Stripping the signature in R30.
5402 (define_insn "xpaclri"
5403 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5405 "hint\t7 // xpaclri"
5408 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5409 ;; all of memory. This blocks insns from being moved across this point.
5411 (define_insn "blockage"
5412 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5415 [(set_attr "length" "0")
5416 (set_attr "type" "block")]
5419 (define_insn "probe_stack_range"
5420 [(set (match_operand:DI 0 "register_operand" "=r")
5421 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5422 (match_operand:DI 2 "register_operand" "r")]
5423 UNSPECV_PROBE_STACK_RANGE))]
5426 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5428 [(set_attr "length" "32")]
5431 ;; Named pattern for expanding thread pointer reference.
5432 (define_expand "get_thread_pointerdi"
5433 [(match_operand:DI 0 "register_operand" "=r")]
5436 rtx tmp = aarch64_load_tp (operands[0]);
5437 if (tmp != operands[0])
5438 emit_move_insn (operands[0], tmp);
5442 ;; Named patterns for stack smashing protection.
5443 (define_expand "stack_protect_set"
5444 [(match_operand 0 "memory_operand")
5445 (match_operand 1 "memory_operand")]
5448 machine_mode mode = GET_MODE (operands[0]);
5450 emit_insn ((mode == DImode
5451 ? gen_stack_protect_set_di
5452 : gen_stack_protect_set_si) (operands[0], operands[1]));
5456 (define_insn "stack_protect_set_<mode>"
5457 [(set (match_operand:PTR 0 "memory_operand" "=m")
5458 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5460 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5462 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5463 [(set_attr "length" "12")
5464 (set_attr "type" "multiple")])
5466 (define_expand "stack_protect_test"
5467 [(match_operand 0 "memory_operand")
5468 (match_operand 1 "memory_operand")
5473 machine_mode mode = GET_MODE (operands[0]);
5475 result = gen_reg_rtx(mode);
5477 emit_insn ((mode == DImode
5478 ? gen_stack_protect_test_di
5479 : gen_stack_protect_test_si) (result,
5484 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5485 result, const0_rtx, operands[2]));
5487 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5488 result, const0_rtx, operands[2]));
5492 (define_insn "stack_protect_test_<mode>"
5493 [(set (match_operand:PTR 0 "register_operand" "=r")
5494 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5495 (match_operand:PTR 2 "memory_operand" "m")]
5497 (clobber (match_scratch:PTR 3 "=&r"))]
5499 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5500 [(set_attr "length" "12")
5501 (set_attr "type" "multiple")])
5503 ;; Write Floating-point Control Register.
5504 (define_insn "set_fpcr"
5505 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5508 [(set_attr "type" "mrs")])
5510 ;; Read Floating-point Control Register.
5511 (define_insn "get_fpcr"
5512 [(set (match_operand:SI 0 "register_operand" "=r")
5513 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5516 [(set_attr "type" "mrs")])
5518 ;; Write Floating-point Status Register.
5519 (define_insn "set_fpsr"
5520 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5523 [(set_attr "type" "mrs")])
5525 ;; Read Floating-point Status Register.
5526 (define_insn "get_fpsr"
5527 [(set (match_operand:SI 0 "register_operand" "=r")
5528 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5531 [(set_attr "type" "mrs")])
5534 ;; Define the subtract-one-and-jump insns so loop.c
5535 ;; knows what to generate.
5536 (define_expand "doloop_end"
5537 [(use (match_operand 0 "" "")) ; loop pseudo
5538 (use (match_operand 1 "" ""))] ; label
5539 "optimize > 0 && flag_modulo_sched"
5548 /* Currently SMS relies on the do-loop pattern to recognize loops
5549 where (1) the control part consists of all insns defining and/or
5550 using a certain 'count' register and (2) the loop count can be
5551 adjusted by modifying this register prior to the loop.
5552 ??? The possible introduction of a new block to initialize the
5553 new IV can potentially affect branch optimizations. */
5555 if (GET_MODE (operands[0]) != DImode)
5559 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5561 cmp = XVECEXP (PATTERN (insn), 0, 0);
5562 cc_reg = SET_DEST (cmp);
5563 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5564 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5565 emit_jump_insn (gen_rtx_SET (pc_rtx,
5566 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5572 (include "aarch64-simd.md")
5574 ;; Atomic Operations
5575 (include "atomics.md")
5577 ;; ldp/stp peephole patterns
5578 (include "aarch64-ldpstp.md")