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 half
185 ;; precision fp registers. When this is set to yes for an alternative,
186 ;; that alternative will be disabled when !TARGET_FP_F16INST.
187 (define_attr "fp16" "no,yes" (const_string "no"))
189 ;; Attribute that specifies whether or not the instruction touches simd
190 ;; registers. When this is set to yes for an alternative, that alternative
191 ;; will be disabled when !TARGET_SIMD.
192 (define_attr "simd" "no,yes" (const_string "no"))
194 (define_attr "length" ""
197 ;; Attribute that controls whether an alternative is enabled or not.
198 ;; Currently it is only used to disable alternatives which touch fp or simd
199 ;; registers when -mgeneral-regs-only is specified.
200 (define_attr "enabled" "no,yes"
203 (and (eq_attr "fp" "yes")
204 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
205 (and (eq_attr "simd" "yes")
206 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
207 (and (eq_attr "fp16" "yes")
208 (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0))))
210 ] (const_string "yes")))
212 ;; Attribute that specifies whether we are dealing with a branch to a
213 ;; label that is far away, i.e. further away than the maximum/minimum
214 ;; representable in a signed 21-bits number.
217 (define_attr "far_branch" "" (const_int 0))
219 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
220 ;; no predicated insns.
221 (define_attr "predicated" "yes,no" (const_string "no"))
223 ;; -------------------------------------------------------------------
224 ;; Pipeline descriptions and scheduling
225 ;; -------------------------------------------------------------------
228 (include "aarch64-tune.md")
231 (include "../arm/cortex-a53.md")
232 (include "../arm/cortex-a57.md")
233 (include "../arm/exynos-m1.md")
234 (include "thunderx.md")
235 (include "../arm/xgene1.md")
236 (include "thunderx2t99.md")
238 ;; -------------------------------------------------------------------
239 ;; Jumps and other miscellaneous insns
240 ;; -------------------------------------------------------------------
242 (define_insn "indirect_jump"
243 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
246 [(set_attr "type" "branch")]
250 [(set (pc) (label_ref (match_operand 0 "" "")))]
253 [(set_attr "type" "branch")]
256 (define_expand "cbranch<mode>4"
257 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
258 [(match_operand:GPI 1 "register_operand" "")
259 (match_operand:GPI 2 "aarch64_plus_operand" "")])
260 (label_ref (match_operand 3 "" ""))
264 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
266 operands[2] = const0_rtx;
270 (define_expand "cbranch<mode>4"
271 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
272 [(match_operand:GPF 1 "register_operand" "")
273 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
274 (label_ref (match_operand 3 "" ""))
278 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
280 operands[2] = const0_rtx;
284 (define_expand "cbranchcc4"
285 [(set (pc) (if_then_else
286 (match_operator 0 "aarch64_comparison_operator"
287 [(match_operand 1 "cc_register" "")
288 (match_operand 2 "const0_operand")])
289 (label_ref (match_operand 3 "" ""))
294 (define_insn "ccmp<mode>"
295 [(set (match_operand:CC 1 "cc_register" "")
297 (match_operator 4 "aarch64_comparison_operator"
298 [(match_operand 0 "cc_register" "")
301 (match_operand:GPI 2 "register_operand" "r,r,r")
302 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
303 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
306 ccmp\\t%<w>2, %<w>3, %k5, %m4
307 ccmp\\t%<w>2, %3, %k5, %m4
308 ccmn\\t%<w>2, #%n3, %k5, %m4"
309 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
312 (define_insn "fccmp<mode>"
313 [(set (match_operand:CCFP 1 "cc_register" "")
315 (match_operator 4 "aarch64_comparison_operator"
316 [(match_operand 0 "cc_register" "")
319 (match_operand:GPF 2 "register_operand" "w")
320 (match_operand:GPF 3 "register_operand" "w"))
321 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
323 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
324 [(set_attr "type" "fccmp<s>")]
327 (define_insn "fccmpe<mode>"
328 [(set (match_operand:CCFPE 1 "cc_register" "")
330 (match_operator 4 "aarch64_comparison_operator"
331 [(match_operand 0 "cc_register" "")
334 (match_operand:GPF 2 "register_operand" "w")
335 (match_operand:GPF 3 "register_operand" "w"))
336 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
338 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
339 [(set_attr "type" "fccmp<s>")]
342 ;; Expansion of signed mod by a power of 2 using CSNEG.
343 ;; For x0 % n where n is a power of 2 produce:
345 ;; and x0, x0, #(n - 1)
346 ;; and x1, x1, #(n - 1)
347 ;; csneg x0, x0, x1, mi
349 (define_expand "mod<mode>3"
350 [(match_operand:GPI 0 "register_operand" "")
351 (match_operand:GPI 1 "register_operand" "")
352 (match_operand:GPI 2 "const_int_operand" "")]
355 HOST_WIDE_INT val = INTVAL (operands[2]);
358 || exact_log2 (val) <= 0
359 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
362 rtx mask = GEN_INT (val - 1);
364 /* In the special case of x0 % 2 we can do the even shorter:
370 rtx masked = gen_reg_rtx (<MODE>mode);
371 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
372 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
373 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
374 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
378 rtx neg_op = gen_reg_rtx (<MODE>mode);
379 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
381 /* Extract the condition register and mode. */
382 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
383 rtx cc_reg = SET_DEST (cmp);
384 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
386 rtx masked_pos = gen_reg_rtx (<MODE>mode);
387 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
389 rtx masked_neg = gen_reg_rtx (<MODE>mode);
390 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
392 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
393 masked_neg, masked_pos));
398 (define_insn "condjump"
399 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
400 [(match_operand 1 "cc_register" "") (const_int 0)])
401 (label_ref (match_operand 2 "" ""))
405 if (get_attr_length (insn) == 8)
406 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
410 [(set_attr "type" "branch")
412 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
413 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
416 (set (attr "far_branch")
417 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
418 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
423 ;; For a 24-bit immediate CST we can optimize the compare for equality
424 ;; and branch sequence from:
426 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
430 ;; sub x0, x1, #(CST & 0xfff000)
431 ;; subs x0, x0, #(CST & 0x000fff)
433 (define_insn_and_split "*compare_condjump<mode>"
434 [(set (pc) (if_then_else (EQL
435 (match_operand:GPI 0 "register_operand" "r")
436 (match_operand:GPI 1 "aarch64_imm24" "n"))
437 (label_ref:P (match_operand 2 "" ""))
439 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
440 && !aarch64_plus_operand (operands[1], <MODE>mode)
441 && !reload_completed"
446 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
447 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
448 rtx tmp = gen_reg_rtx (<MODE>mode);
449 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
450 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
451 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
452 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
453 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
458 (define_expand "casesi"
459 [(match_operand:SI 0 "register_operand" "") ; Index
460 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
461 (match_operand:SI 2 "const_int_operand" "") ; Total range
462 (match_operand:DI 3 "" "") ; Table label
463 (match_operand:DI 4 "" "")] ; Out of range label
466 if (operands[1] != const0_rtx)
468 rtx reg = gen_reg_rtx (SImode);
470 /* Canonical RTL says that if you have:
474 then this should be emitted as:
478 The use of trunc_int_for_mode ensures that the resulting
479 constant can be represented in SImode, this is important
480 for the corner case where operand[1] is INT_MIN. */
482 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
484 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
485 (operands[1], SImode))
486 operands[1] = force_reg (SImode, operands[1]);
487 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
491 if (!aarch64_plus_operand (operands[2], SImode))
492 operands[2] = force_reg (SImode, operands[2]);
493 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
495 operands[0], operands[2], operands[4]));
497 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
498 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
504 (define_insn "casesi_dispatch"
507 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
508 (match_operand:SI 1 "register_operand" "r")]
510 (clobber (reg:CC CC_REGNUM))
511 (clobber (match_scratch:DI 3 "=r"))
512 (clobber (match_scratch:DI 4 "=r"))
513 (use (label_ref (match_operand 2 "" "")))])]
516 return aarch64_output_casesi (operands);
518 [(set_attr "length" "16")
519 (set_attr "type" "branch")]
523 [(unspec[(const_int 0)] UNSPEC_NOP)]
526 [(set_attr "type" "no_insn")]
529 (define_insn "prefetch"
530 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
531 (match_operand:QI 1 "const_int_operand" "")
532 (match_operand:QI 2 "const_int_operand" ""))]
535 const char * pftype[2][4] =
537 {"prfm\\tPLDL1STRM, %0",
538 "prfm\\tPLDL3KEEP, %0",
539 "prfm\\tPLDL2KEEP, %0",
540 "prfm\\tPLDL1KEEP, %0"},
541 {"prfm\\tPSTL1STRM, %0",
542 "prfm\\tPSTL3KEEP, %0",
543 "prfm\\tPSTL2KEEP, %0",
544 "prfm\\tPSTL1KEEP, %0"},
547 int locality = INTVAL (operands[2]);
549 gcc_assert (IN_RANGE (locality, 0, 3));
551 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
552 the address into a DImode MEM so that aarch64_print_operand knows
554 operands[0] = gen_rtx_MEM (DImode, operands[0]);
555 return pftype[INTVAL(operands[1])][locality];
557 [(set_attr "type" "load1")]
561 [(trap_if (const_int 1) (const_int 8))]
564 [(set_attr "type" "trap")])
566 (define_expand "prologue"
567 [(clobber (const_int 0))]
570 aarch64_expand_prologue ();
575 (define_expand "epilogue"
576 [(clobber (const_int 0))]
579 aarch64_expand_epilogue (false);
584 (define_expand "sibcall_epilogue"
585 [(clobber (const_int 0))]
588 aarch64_expand_epilogue (true);
593 (define_insn "*do_return"
597 if (aarch64_return_address_signing_enabled ()
599 && !crtl->calls_eh_return)
604 [(set_attr "type" "branch")]
607 (define_expand "return"
609 "aarch64_use_return_insn_p ()"
613 (define_insn "simple_return"
617 [(set_attr "type" "branch")]
620 (define_insn "*cb<optab><mode>1"
621 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
623 (label_ref (match_operand 1 "" ""))
627 if (get_attr_length (insn) == 8)
628 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
630 return "<cbz>\\t%<w>0, %l1";
632 [(set_attr "type" "branch")
634 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
635 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
638 (set (attr "far_branch")
639 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
640 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
645 (define_insn "*tb<optab><mode>1"
646 [(set (pc) (if_then_else
647 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
650 "aarch64_simd_shift_imm_<mode>" "n"))
652 (label_ref (match_operand 2 "" ""))
654 (clobber (reg:CC CC_REGNUM))]
657 if (get_attr_length (insn) == 8)
659 if (get_attr_far_branch (insn) == 1)
660 return aarch64_gen_far_branch (operands, 2, "Ltb",
661 "<inv_tb>\\t%<w>0, %1, ");
664 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
665 return "tst\t%<w>0, %1\;<bcond>\t%l2";
669 return "<tbz>\t%<w>0, %1, %l2";
671 [(set_attr "type" "branch")
673 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
674 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
677 (set (attr "far_branch")
678 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
679 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
685 (define_insn "*cb<optab><mode>1"
686 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
688 (label_ref (match_operand 1 "" ""))
690 (clobber (reg:CC CC_REGNUM))]
693 if (get_attr_length (insn) == 8)
695 if (get_attr_far_branch (insn) == 1)
696 return aarch64_gen_far_branch (operands, 1, "Ltb",
697 "<inv_tb>\\t%<w>0, <sizem1>, ");
701 uint64_t val = ((uint64_t) 1)
702 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
703 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
704 output_asm_insn (buf, operands);
705 return "<bcond>\t%l1";
709 return "<tbz>\t%<w>0, <sizem1>, %l1";
711 [(set_attr "type" "branch")
713 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
714 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
717 (set (attr "far_branch")
718 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
719 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
724 ;; -------------------------------------------------------------------
725 ;; Subroutine calls and sibcalls
726 ;; -------------------------------------------------------------------
728 (define_expand "call"
729 [(parallel [(call (match_operand 0 "memory_operand" "")
730 (match_operand 1 "general_operand" ""))
731 (use (match_operand 2 "" ""))
732 (clobber (reg:DI LR_REGNUM))])]
736 aarch64_expand_call (NULL_RTX, operands[0], false);
741 (define_insn "*call_insn"
742 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
743 (match_operand 1 "" ""))
744 (clobber (reg:DI LR_REGNUM))]
749 [(set_attr "type" "call, call")]
752 (define_expand "call_value"
753 [(parallel [(set (match_operand 0 "" "")
754 (call (match_operand 1 "memory_operand" "")
755 (match_operand 2 "general_operand" "")))
756 (use (match_operand 3 "" ""))
757 (clobber (reg:DI LR_REGNUM))])]
761 aarch64_expand_call (operands[0], operands[1], false);
766 (define_insn "*call_value_insn"
767 [(set (match_operand 0 "" "")
768 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
769 (match_operand 2 "" "")))
770 (clobber (reg:DI LR_REGNUM))]
775 [(set_attr "type" "call, call")]
778 (define_expand "sibcall"
779 [(parallel [(call (match_operand 0 "memory_operand" "")
780 (match_operand 1 "general_operand" ""))
782 (use (match_operand 2 "" ""))])]
785 aarch64_expand_call (NULL_RTX, operands[0], true);
790 (define_expand "sibcall_value"
791 [(parallel [(set (match_operand 0 "" "")
792 (call (match_operand 1 "memory_operand" "")
793 (match_operand 2 "general_operand" "")))
795 (use (match_operand 3 "" ""))])]
798 aarch64_expand_call (operands[0], operands[1], true);
803 (define_insn "*sibcall_insn"
804 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
805 (match_operand 1 "" ""))
807 "SIBLING_CALL_P (insn)"
811 [(set_attr "type" "branch, branch")]
814 (define_insn "*sibcall_value_insn"
815 [(set (match_operand 0 "" "")
817 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
818 (match_operand 2 "" "")))
820 "SIBLING_CALL_P (insn)"
824 [(set_attr "type" "branch, branch")]
827 ;; Call subroutine returning any type.
829 (define_expand "untyped_call"
830 [(parallel [(call (match_operand 0 "")
833 (match_operand 2 "")])]
838 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
840 for (i = 0; i < XVECLEN (operands[2], 0); i++)
842 rtx set = XVECEXP (operands[2], 0, i);
843 emit_move_insn (SET_DEST (set), SET_SRC (set));
846 /* The optimizer does not know that the call sets the function value
847 registers we stored in the result block. We avoid problems by
848 claiming that all hard registers are used and clobbered at this
850 emit_insn (gen_blockage ());
854 ;; -------------------------------------------------------------------
856 ;; -------------------------------------------------------------------
858 (define_expand "mov<mode>"
859 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
860 (match_operand:SHORT 1 "general_operand" ""))]
863 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
864 operands[1] = force_reg (<MODE>mode, operands[1]);
868 (define_insn "*mov<mode>_aarch64"
869 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
870 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
871 "(register_operand (operands[0], <MODE>mode)
872 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
874 switch (which_alternative)
877 return "mov\t%w0, %w1";
879 return "mov\t%w0, %1";
881 return aarch64_output_scalar_simd_mov_immediate (operands[1],
884 return "ldr<size>\t%w0, %1";
886 return "ldr\t%<size>0, %1";
888 return "str<size>\t%w1, %0";
890 return "str\t%<size>1, %0";
892 return "umov\t%w0, %1.<v>[0]";
894 return "dup\t%0.<Vallxd>, %w1";
896 return "dup\t%<Vetype>0, %1.<v>[0]";
901 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
902 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
903 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
906 (define_expand "mov<mode>"
907 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
908 (match_operand:GPI 1 "general_operand" ""))]
911 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
912 && <MODE>mode == DImode
913 && aarch64_split_dimode_const_store (operands[0], operands[1]))
916 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
917 operands[1] = force_reg (<MODE>mode, operands[1]);
919 /* FIXME: RR we still need to fix up what we are doing with
920 symbol_refs and other types of constants. */
921 if (CONSTANT_P (operands[1])
922 && !CONST_INT_P (operands[1]))
924 aarch64_expand_mov_immediate (operands[0], operands[1]);
930 (define_insn_and_split "*movsi_aarch64"
931 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w,w")
932 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Ds"))]
933 "(register_operand (operands[0], SImode)
934 || aarch64_reg_or_zero (operands[1], SImode))"
950 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
951 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
952 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
955 aarch64_expand_mov_immediate (operands[0], operands[1]);
958 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
959 adr,adr,f_mcr,f_mrc,fmov,neon_move")
960 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
961 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
964 (define_insn_and_split "*movdi_aarch64"
965 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w,r,*w,w")
966 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
967 "(register_operand (operands[0], DImode)
968 || aarch64_reg_or_zero (operands[1], DImode))"
984 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
985 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
986 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
989 aarch64_expand_mov_immediate (operands[0], operands[1]);
992 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
993 adr,adr,f_mcr,f_mrc,fmov,neon_move")
994 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
995 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
998 (define_insn "insv_imm<mode>"
999 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1001 (match_operand:GPI 1 "const_int_operand" "n"))
1002 (match_operand:GPI 2 "const_int_operand" "n"))]
1003 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1004 && UINTVAL (operands[1]) % 16 == 0"
1005 "movk\\t%<w>0, %X2, lsl %1"
1006 [(set_attr "type" "mov_imm")]
1009 (define_expand "movti"
1010 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1011 (match_operand:TI 1 "general_operand" ""))]
1014 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1015 operands[1] = force_reg (TImode, operands[1]);
1019 (define_insn "*movti_aarch64"
1020 [(set (match_operand:TI 0
1021 "nonimmediate_operand" "=r, *w,r ,*w,r,m,m,*w,m")
1023 "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1024 "(register_operand (operands[0], TImode)
1025 || aarch64_reg_or_zero (operands[1], TImode))"
1030 mov\\t%0.16b, %1.16b
1036 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1037 load2,store2,store2,f_loadd,f_stored")
1038 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1039 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1040 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1043 ;; Split a TImode register-register or register-immediate move into
1044 ;; its component DImode pieces, taking care to handle overlapping
1045 ;; source and dest registers.
1047 [(set (match_operand:TI 0 "register_operand" "")
1048 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1049 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1052 aarch64_split_128bit_move (operands[0], operands[1]);
1056 (define_expand "mov<mode>"
1057 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1058 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1063 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1067 if (GET_CODE (operands[0]) == MEM
1068 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1069 && aarch64_float_const_zero_rtx_p (operands[1])))
1070 operands[1] = force_reg (<MODE>mode, operands[1]);
1074 (define_insn "*movhf_aarch64"
1075 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r")
1076 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1077 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1078 || aarch64_reg_or_fp_float (operands[1], HFmode))"
1083 mov\\t%0.h[0], %1.h[0]
1085 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1091 [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
1092 neon_move,f_loads,f_stores,load1,store1,mov_reg")
1093 (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
1094 (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")]
1097 (define_insn "*movsf_aarch64"
1098 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1099 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1100 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1101 || aarch64_reg_or_fp_float (operands[1], SFmode))"
1108 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1115 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1116 f_loads,f_stores,load1,store1,mov_reg,\
1118 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1121 (define_insn "*movdf_aarch64"
1122 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1123 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1124 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1125 || aarch64_reg_or_fp_float (operands[1], DFmode))"
1132 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1139 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1140 f_loadd,f_stored,load1,store1,mov_reg,\
1142 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1146 [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1147 (match_operand:GPF_HF 1 "general_operand"))]
1148 "can_create_pseudo_p ()
1149 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1150 && !aarch64_float_const_representable_p (operands[1])
1151 && aarch64_float_const_rtx_p (operands[1])"
1154 unsigned HOST_WIDE_INT ival;
1155 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1158 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1159 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1160 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1165 (define_insn "*movtf_aarch64"
1166 [(set (match_operand:TF 0
1167 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1169 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1170 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1171 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1173 mov\\t%0.16b, %1.16b
1184 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1185 f_loadd,f_stored,load2,store2,store2")
1186 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1187 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1191 [(set (match_operand:TF 0 "register_operand" "")
1192 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1193 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1196 aarch64_split_128bit_move (operands[0], operands[1]);
1203 ;; 2 is size of move in bytes
1206 (define_expand "movmemdi"
1207 [(match_operand:BLK 0 "memory_operand")
1208 (match_operand:BLK 1 "memory_operand")
1209 (match_operand:DI 2 "immediate_operand")
1210 (match_operand:DI 3 "immediate_operand")]
1213 if (aarch64_expand_movmem (operands))
1219 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1220 ;; fairly lax checking on the second memory operation.
1221 (define_insn "load_pairsi"
1222 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1223 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1224 (set (match_operand:SI 2 "register_operand" "=r,*w")
1225 (match_operand:SI 3 "memory_operand" "m,m"))]
1226 "rtx_equal_p (XEXP (operands[3], 0),
1227 plus_constant (Pmode,
1228 XEXP (operands[1], 0),
1229 GET_MODE_SIZE (SImode)))"
1233 [(set_attr "type" "load2,neon_load1_2reg")
1234 (set_attr "fp" "*,yes")]
1237 (define_insn "load_pairdi"
1238 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1239 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1240 (set (match_operand:DI 2 "register_operand" "=r,*w")
1241 (match_operand:DI 3 "memory_operand" "m,m"))]
1242 "rtx_equal_p (XEXP (operands[3], 0),
1243 plus_constant (Pmode,
1244 XEXP (operands[1], 0),
1245 GET_MODE_SIZE (DImode)))"
1249 [(set_attr "type" "load2,neon_load1_2reg")
1250 (set_attr "fp" "*,yes")]
1254 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1255 ;; fairly lax checking on the second memory operation.
1256 (define_insn "store_pairsi"
1257 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1258 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1259 (set (match_operand:SI 2 "memory_operand" "=m,m")
1260 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1261 "rtx_equal_p (XEXP (operands[2], 0),
1262 plus_constant (Pmode,
1263 XEXP (operands[0], 0),
1264 GET_MODE_SIZE (SImode)))"
1268 [(set_attr "type" "store2,neon_store1_2reg")
1269 (set_attr "fp" "*,yes")]
1272 (define_insn "store_pairdi"
1273 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1274 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1275 (set (match_operand:DI 2 "memory_operand" "=m,m")
1276 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1277 "rtx_equal_p (XEXP (operands[2], 0),
1278 plus_constant (Pmode,
1279 XEXP (operands[0], 0),
1280 GET_MODE_SIZE (DImode)))"
1284 [(set_attr "type" "store2,neon_store1_2reg")
1285 (set_attr "fp" "*,yes")]
1288 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1289 ;; fairly lax checking on the second memory operation.
1290 (define_insn "load_pairsf"
1291 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1292 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1293 (set (match_operand:SF 2 "register_operand" "=w,*r")
1294 (match_operand:SF 3 "memory_operand" "m,m"))]
1295 "rtx_equal_p (XEXP (operands[3], 0),
1296 plus_constant (Pmode,
1297 XEXP (operands[1], 0),
1298 GET_MODE_SIZE (SFmode)))"
1302 [(set_attr "type" "neon_load1_2reg,load2")
1303 (set_attr "fp" "yes,*")]
1306 (define_insn "load_pairdf"
1307 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1308 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1309 (set (match_operand:DF 2 "register_operand" "=w,*r")
1310 (match_operand:DF 3 "memory_operand" "m,m"))]
1311 "rtx_equal_p (XEXP (operands[3], 0),
1312 plus_constant (Pmode,
1313 XEXP (operands[1], 0),
1314 GET_MODE_SIZE (DFmode)))"
1318 [(set_attr "type" "neon_load1_2reg,load2")
1319 (set_attr "fp" "yes,*")]
1322 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1323 ;; fairly lax checking on the second memory operation.
1324 (define_insn "store_pairsf"
1325 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1326 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1327 (set (match_operand:SF 2 "memory_operand" "=m,m")
1328 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1329 "rtx_equal_p (XEXP (operands[2], 0),
1330 plus_constant (Pmode,
1331 XEXP (operands[0], 0),
1332 GET_MODE_SIZE (SFmode)))"
1336 [(set_attr "type" "neon_store1_2reg,store2")
1337 (set_attr "fp" "yes,*")]
1340 (define_insn "store_pairdf"
1341 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1342 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1343 (set (match_operand:DF 2 "memory_operand" "=m,m")
1344 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1345 "rtx_equal_p (XEXP (operands[2], 0),
1346 plus_constant (Pmode,
1347 XEXP (operands[0], 0),
1348 GET_MODE_SIZE (DFmode)))"
1352 [(set_attr "type" "neon_store1_2reg,store2")
1353 (set_attr "fp" "yes,*")]
1356 ;; Load pair with post-index writeback. This is primarily used in function
1358 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1360 [(set (match_operand:P 0 "register_operand" "=k")
1361 (plus:P (match_operand:P 1 "register_operand" "0")
1362 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1363 (set (match_operand:GPI 2 "register_operand" "=r")
1364 (mem:GPI (match_dup 1)))
1365 (set (match_operand:GPI 3 "register_operand" "=r")
1366 (mem:GPI (plus:P (match_dup 1)
1367 (match_operand:P 5 "const_int_operand" "n"))))])]
1368 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1369 "ldp\\t%<w>2, %<w>3, [%1], %4"
1370 [(set_attr "type" "load2")]
1373 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1375 [(set (match_operand:P 0 "register_operand" "=k")
1376 (plus:P (match_operand:P 1 "register_operand" "0")
1377 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1378 (set (match_operand:GPF 2 "register_operand" "=w")
1379 (mem:GPF (match_dup 1)))
1380 (set (match_operand:GPF 3 "register_operand" "=w")
1381 (mem:GPF (plus:P (match_dup 1)
1382 (match_operand:P 5 "const_int_operand" "n"))))])]
1383 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1384 "ldp\\t%<w>2, %<w>3, [%1], %4"
1385 [(set_attr "type" "neon_load1_2reg")]
1388 ;; Store pair with pre-index writeback. This is primarily used in function
1390 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1392 [(set (match_operand:P 0 "register_operand" "=&k")
1393 (plus:P (match_operand:P 1 "register_operand" "0")
1394 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1395 (set (mem:GPI (plus:P (match_dup 0)
1397 (match_operand:GPI 2 "register_operand" "r"))
1398 (set (mem:GPI (plus:P (match_dup 0)
1399 (match_operand:P 5 "const_int_operand" "n")))
1400 (match_operand:GPI 3 "register_operand" "r"))])]
1401 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1402 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1403 [(set_attr "type" "store2")]
1406 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1408 [(set (match_operand:P 0 "register_operand" "=&k")
1409 (plus:P (match_operand:P 1 "register_operand" "0")
1410 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1411 (set (mem:GPF (plus:P (match_dup 0)
1413 (match_operand:GPF 2 "register_operand" "w"))
1414 (set (mem:GPF (plus:P (match_dup 0)
1415 (match_operand:P 5 "const_int_operand" "n")))
1416 (match_operand:GPF 3 "register_operand" "w"))])]
1417 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1418 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1419 [(set_attr "type" "neon_store1_2reg<q>")]
1422 ;; -------------------------------------------------------------------
1423 ;; Sign/Zero extension
1424 ;; -------------------------------------------------------------------
1426 (define_expand "<optab>sidi2"
1427 [(set (match_operand:DI 0 "register_operand")
1428 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1432 (define_insn "*extendsidi2_aarch64"
1433 [(set (match_operand:DI 0 "register_operand" "=r,r")
1434 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1439 [(set_attr "type" "extend,load1")]
1442 (define_insn "*load_pair_extendsidi2_aarch64"
1443 [(set (match_operand:DI 0 "register_operand" "=r")
1444 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1445 (set (match_operand:DI 2 "register_operand" "=r")
1446 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1447 "rtx_equal_p (XEXP (operands[3], 0),
1448 plus_constant (Pmode,
1449 XEXP (operands[1], 0),
1450 GET_MODE_SIZE (SImode)))"
1451 "ldpsw\\t%0, %2, %1"
1452 [(set_attr "type" "load2")]
1455 (define_insn "*zero_extendsidi2_aarch64"
1456 [(set (match_operand:DI 0 "register_operand" "=r,r")
1457 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1462 [(set_attr "type" "extend,load1")]
1465 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1466 [(set (match_operand:DI 0 "register_operand" "=r")
1467 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1468 (set (match_operand:DI 2 "register_operand" "=r")
1469 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1470 "rtx_equal_p (XEXP (operands[3], 0),
1471 plus_constant (Pmode,
1472 XEXP (operands[1], 0),
1473 GET_MODE_SIZE (SImode)))"
1474 "ldp\\t%w0, %w2, %1"
1475 [(set_attr "type" "load2")]
1478 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1479 [(set (match_operand:GPI 0 "register_operand")
1480 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1484 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1485 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1486 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1489 sxt<SHORT:size>\t%<GPI:w>0, %w1
1490 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1491 [(set_attr "type" "extend,load1")]
1494 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1495 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1496 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1499 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1500 ldr<SHORT:size>\t%w0, %1
1501 ldr\t%<SHORT:size>0, %1"
1502 [(set_attr "type" "logic_imm,load1,load1")]
1505 (define_expand "<optab>qihi2"
1506 [(set (match_operand:HI 0 "register_operand")
1507 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1511 (define_insn "*extendqihi2_aarch64"
1512 [(set (match_operand:HI 0 "register_operand" "=r,r")
1513 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1518 [(set_attr "type" "extend,load1")]
1521 (define_insn "*zero_extendqihi2_aarch64"
1522 [(set (match_operand:HI 0 "register_operand" "=r,r")
1523 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1528 [(set_attr "type" "logic_imm,load1")]
1531 ;; -------------------------------------------------------------------
1532 ;; Simple arithmetic
1533 ;; -------------------------------------------------------------------
1535 (define_expand "add<mode>3"
1537 (match_operand:GPI 0 "register_operand" "")
1538 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1539 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1542 /* If operands[1] is a subreg extract the inner RTX. */
1543 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1545 /* If the constant is too large for a single instruction and isn't frame
1546 based, split off the immediate so it is available for CSE. */
1547 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1548 && can_create_pseudo_p ()
1550 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1551 operands[2] = force_reg (<MODE>mode, operands[2]);
1554 (define_insn "*add<mode>3_aarch64"
1556 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1558 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1559 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1562 add\\t%<w>0, %<w>1, %2
1563 add\\t%<w>0, %<w>1, %<w>2
1564 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1565 sub\\t%<w>0, %<w>1, #%n2
1567 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1568 (set_attr "simd" "*,*,yes,*,*")]
1571 ;; zero_extend version of above
1572 (define_insn "*addsi3_aarch64_uxtw"
1574 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1576 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1577 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1582 sub\\t%w0, %w1, #%n2
1584 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1587 ;; If there's a free register, and we can load the constant with a
1588 ;; single instruction, do so. This has a chance to improve scheduling.
1590 [(match_scratch:GPI 3 "r")
1591 (set (match_operand:GPI 0 "register_operand")
1593 (match_operand:GPI 1 "register_operand")
1594 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1595 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1596 [(set (match_dup 3) (match_dup 2))
1597 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1601 [(match_scratch:SI 3 "r")
1602 (set (match_operand:DI 0 "register_operand")
1605 (match_operand:SI 1 "register_operand")
1606 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1607 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1608 [(set (match_dup 3) (match_dup 2))
1609 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1612 ;; After peephole2 has had a chance to run, split any remaining long
1613 ;; additions into two add immediates.
1615 [(set (match_operand:GPI 0 "register_operand")
1617 (match_operand:GPI 1 "register_operand")
1618 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1619 "epilogue_completed"
1620 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1621 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1623 HOST_WIDE_INT i = INTVAL (operands[2]);
1624 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1625 operands[3] = GEN_INT (i - s);
1626 operands[4] = GEN_INT (s);
1631 [(set (match_operand:DI 0 "register_operand")
1634 (match_operand:SI 1 "register_operand")
1635 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1636 "epilogue_completed"
1637 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1638 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1640 HOST_WIDE_INT i = INTVAL (operands[2]);
1641 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1642 operands[3] = GEN_INT (i - s);
1643 operands[4] = GEN_INT (s);
1644 operands[5] = gen_lowpart (SImode, operands[0]);
1648 (define_expand "addti3"
1649 [(set (match_operand:TI 0 "register_operand" "")
1650 (plus:TI (match_operand:TI 1 "register_operand" "")
1651 (match_operand:TI 2 "register_operand" "")))]
1654 rtx low = gen_reg_rtx (DImode);
1655 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1656 gen_lowpart (DImode, operands[2])));
1658 rtx high = gen_reg_rtx (DImode);
1659 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1660 gen_highpart (DImode, operands[2])));
1662 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1663 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1667 (define_insn "add<mode>3_compare0"
1668 [(set (reg:CC_NZ CC_REGNUM)
1670 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1671 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1673 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1674 (plus:GPI (match_dup 1) (match_dup 2)))]
1677 adds\\t%<w>0, %<w>1, %<w>2
1678 adds\\t%<w>0, %<w>1, %2
1679 subs\\t%<w>0, %<w>1, #%n2"
1680 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1683 ;; zero_extend version of above
1684 (define_insn "*addsi3_compare0_uxtw"
1685 [(set (reg:CC_NZ CC_REGNUM)
1687 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1688 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1690 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1691 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1694 adds\\t%w0, %w1, %w2
1696 subs\\t%w0, %w1, #%n2"
1697 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1700 (define_insn "*add<mode>3_compareC_cconly_imm"
1701 [(set (reg:CC_C CC_REGNUM)
1704 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1705 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1709 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1710 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1711 <MODE>mode, operands[1])"
1715 [(set_attr "type" "alus_imm")]
1718 (define_insn "*add<mode>3_compareC_cconly"
1719 [(set (reg:CC_C CC_REGNUM)
1722 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1723 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1724 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1726 "cmn\\t%<w>0, %<w>1"
1727 [(set_attr "type" "alus_sreg")]
1730 (define_insn "*add<mode>3_compareC_imm"
1731 [(set (reg:CC_C CC_REGNUM)
1734 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1735 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1739 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1740 (set (match_operand:GPI 0 "register_operand" "=r,r")
1741 (plus:GPI (match_dup 1) (match_dup 2)))]
1742 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1743 <MODE>mode, operands[2])"
1745 adds\\t%<w>0, %<w>1, %2
1746 subs\\t%<w>0, %<w>1, #%n2"
1747 [(set_attr "type" "alus_imm")]
1750 (define_insn "add<mode>3_compareC"
1751 [(set (reg:CC_C CC_REGNUM)
1754 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1755 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1757 (plus:GPI (match_dup 1) (match_dup 2)))))
1758 (set (match_operand:GPI 0 "register_operand" "=r")
1759 (plus:GPI (match_dup 1) (match_dup 2)))]
1761 "adds\\t%<w>0, %<w>1, %<w>2"
1762 [(set_attr "type" "alus_sreg")]
1765 (define_insn "*adds_shift_imm_<mode>"
1766 [(set (reg:CC_NZ CC_REGNUM)
1768 (plus:GPI (ASHIFT:GPI
1769 (match_operand:GPI 1 "register_operand" "r")
1770 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1771 (match_operand:GPI 3 "register_operand" "r"))
1773 (set (match_operand:GPI 0 "register_operand" "=r")
1774 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1777 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1778 [(set_attr "type" "alus_shift_imm")]
1781 (define_insn "*subs_shift_imm_<mode>"
1782 [(set (reg:CC_NZ CC_REGNUM)
1784 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1786 (match_operand:GPI 2 "register_operand" "r")
1787 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1789 (set (match_operand:GPI 0 "register_operand" "=r")
1790 (minus:GPI (match_dup 1)
1791 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1793 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1794 [(set_attr "type" "alus_shift_imm")]
1797 (define_insn "*adds_mul_imm_<mode>"
1798 [(set (reg:CC_NZ CC_REGNUM)
1801 (match_operand:GPI 1 "register_operand" "r")
1802 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1803 (match_operand:GPI 3 "register_operand" "r"))
1805 (set (match_operand:GPI 0 "register_operand" "=r")
1806 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1809 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1810 [(set_attr "type" "alus_shift_imm")]
1813 (define_insn "*subs_mul_imm_<mode>"
1814 [(set (reg:CC_NZ CC_REGNUM)
1816 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1818 (match_operand:GPI 2 "register_operand" "r")
1819 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1821 (set (match_operand:GPI 0 "register_operand" "=r")
1822 (minus:GPI (match_dup 1)
1823 (mult:GPI (match_dup 2) (match_dup 3))))]
1825 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1826 [(set_attr "type" "alus_shift_imm")]
1829 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1830 [(set (reg:CC_NZ CC_REGNUM)
1833 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1834 (match_operand:GPI 2 "register_operand" "r"))
1836 (set (match_operand:GPI 0 "register_operand" "=r")
1837 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1839 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1840 [(set_attr "type" "alus_ext")]
1843 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1844 [(set (reg:CC_NZ CC_REGNUM)
1846 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1848 (match_operand:ALLX 2 "register_operand" "r")))
1850 (set (match_operand:GPI 0 "register_operand" "=r")
1851 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1853 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1854 [(set_attr "type" "alus_ext")]
1857 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1858 [(set (reg:CC_NZ CC_REGNUM)
1860 (plus:GPI (ashift:GPI
1862 (match_operand:ALLX 1 "register_operand" "r"))
1863 (match_operand 2 "aarch64_imm3" "Ui3"))
1864 (match_operand:GPI 3 "register_operand" "r"))
1866 (set (match_operand:GPI 0 "register_operand" "=rk")
1867 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1871 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1872 [(set_attr "type" "alus_ext")]
1875 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1876 [(set (reg:CC_NZ CC_REGNUM)
1878 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1881 (match_operand:ALLX 2 "register_operand" "r"))
1882 (match_operand 3 "aarch64_imm3" "Ui3")))
1884 (set (match_operand:GPI 0 "register_operand" "=rk")
1885 (minus:GPI (match_dup 1)
1886 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1889 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1890 [(set_attr "type" "alus_ext")]
1893 (define_insn "*adds_<optab><mode>_multp2"
1894 [(set (reg:CC_NZ CC_REGNUM)
1896 (plus:GPI (ANY_EXTRACT:GPI
1897 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1898 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1899 (match_operand 3 "const_int_operand" "n")
1901 (match_operand:GPI 4 "register_operand" "r"))
1903 (set (match_operand:GPI 0 "register_operand" "=r")
1904 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1908 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1909 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1910 [(set_attr "type" "alus_ext")]
1913 (define_insn "*subs_<optab><mode>_multp2"
1914 [(set (reg:CC_NZ CC_REGNUM)
1916 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1918 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1919 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1920 (match_operand 3 "const_int_operand" "n")
1923 (set (match_operand:GPI 0 "register_operand" "=r")
1924 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1925 (mult:GPI (match_dup 1) (match_dup 2))
1928 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1929 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1930 [(set_attr "type" "alus_ext")]
1933 (define_insn "*add<mode>3nr_compare0"
1934 [(set (reg:CC_NZ CC_REGNUM)
1936 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1937 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1944 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1947 (define_insn "aarch64_sub<mode>_compare0"
1948 [(set (reg:CC_NZ CC_REGNUM)
1950 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
1951 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
1954 "cmp\\t%<w>0, %<w>1"
1955 [(set_attr "type" "alus_sreg")]
1958 (define_insn "*compare_neg<mode>"
1959 [(set (reg:CC_Z CC_REGNUM)
1961 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1962 (match_operand:GPI 1 "register_operand" "r")))]
1964 "cmn\\t%<w>1, %<w>0"
1965 [(set_attr "type" "alus_sreg")]
1968 (define_insn "*add_<shift>_<mode>"
1969 [(set (match_operand:GPI 0 "register_operand" "=r")
1970 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1971 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1972 (match_operand:GPI 3 "register_operand" "r")))]
1974 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1975 [(set_attr "type" "alu_shift_imm")]
1978 ;; zero_extend version of above
1979 (define_insn "*add_<shift>_si_uxtw"
1980 [(set (match_operand:DI 0 "register_operand" "=r")
1982 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1983 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1984 (match_operand:SI 3 "register_operand" "r"))))]
1986 "add\\t%w0, %w3, %w1, <shift> %2"
1987 [(set_attr "type" "alu_shift_imm")]
1990 (define_insn "*add_mul_imm_<mode>"
1991 [(set (match_operand:GPI 0 "register_operand" "=r")
1992 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1993 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1994 (match_operand:GPI 3 "register_operand" "r")))]
1996 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1997 [(set_attr "type" "alu_shift_imm")]
2000 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2001 [(set (match_operand:GPI 0 "register_operand" "=rk")
2002 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2003 (match_operand:GPI 2 "register_operand" "r")))]
2005 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2006 [(set_attr "type" "alu_ext")]
2009 ;; zero_extend version of above
2010 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2011 [(set (match_operand:DI 0 "register_operand" "=rk")
2013 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2014 (match_operand:GPI 2 "register_operand" "r"))))]
2016 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2017 [(set_attr "type" "alu_ext")]
2020 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2021 [(set (match_operand:GPI 0 "register_operand" "=rk")
2022 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2023 (match_operand:ALLX 1 "register_operand" "r"))
2024 (match_operand 2 "aarch64_imm3" "Ui3"))
2025 (match_operand:GPI 3 "register_operand" "r")))]
2027 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2028 [(set_attr "type" "alu_ext")]
2031 ;; zero_extend version of above
2032 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2033 [(set (match_operand:DI 0 "register_operand" "=rk")
2035 (plus:SI (ashift:SI (ANY_EXTEND:SI
2036 (match_operand:SHORT 1 "register_operand" "r"))
2037 (match_operand 2 "aarch64_imm3" "Ui3"))
2038 (match_operand:SI 3 "register_operand" "r"))))]
2040 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2041 [(set_attr "type" "alu_ext")]
2044 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2045 [(set (match_operand:GPI 0 "register_operand" "=rk")
2046 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2047 (match_operand:ALLX 1 "register_operand" "r"))
2048 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2049 (match_operand:GPI 3 "register_operand" "r")))]
2051 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2052 [(set_attr "type" "alu_ext")]
2055 ;; zero_extend version of above
2056 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2057 [(set (match_operand:DI 0 "register_operand" "=rk")
2058 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2059 (match_operand:SHORT 1 "register_operand" "r"))
2060 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2061 (match_operand:SI 3 "register_operand" "r"))))]
2063 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2064 [(set_attr "type" "alu_ext")]
2067 (define_insn "*add_<optab><mode>_multp2"
2068 [(set (match_operand:GPI 0 "register_operand" "=rk")
2069 (plus:GPI (ANY_EXTRACT:GPI
2070 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2071 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2072 (match_operand 3 "const_int_operand" "n")
2074 (match_operand:GPI 4 "register_operand" "r")))]
2075 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2076 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2077 [(set_attr "type" "alu_ext")]
2080 ;; zero_extend version of above
2081 (define_insn "*add_<optab>si_multp2_uxtw"
2082 [(set (match_operand:DI 0 "register_operand" "=rk")
2084 (plus:SI (ANY_EXTRACT:SI
2085 (mult:SI (match_operand:SI 1 "register_operand" "r")
2086 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2087 (match_operand 3 "const_int_operand" "n")
2089 (match_operand:SI 4 "register_operand" "r"))))]
2090 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2091 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2092 [(set_attr "type" "alu_ext")]
2095 (define_expand "add<mode>3_carryin"
2096 [(set (match_operand:GPI 0 "register_operand")
2099 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2100 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2101 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2106 ;; Note that add with carry with two zero inputs is matched by cset,
2107 ;; and that add with carry with one zero input is matched by cinc.
2109 (define_insn "*add<mode>3_carryin"
2110 [(set (match_operand:GPI 0 "register_operand" "=r")
2113 (match_operand:GPI 3 "aarch64_carry_operation" "")
2114 (match_operand:GPI 1 "register_operand" "r"))
2115 (match_operand:GPI 2 "register_operand" "r")))]
2117 "adc\\t%<w>0, %<w>1, %<w>2"
2118 [(set_attr "type" "adc_reg")]
2121 ;; zero_extend version of above
2122 (define_insn "*addsi3_carryin_uxtw"
2123 [(set (match_operand:DI 0 "register_operand" "=r")
2127 (match_operand:SI 3 "aarch64_carry_operation" "")
2128 (match_operand:SI 1 "register_operand" "r"))
2129 (match_operand:SI 2 "register_operand" "r"))))]
2131 "adc\\t%w0, %w1, %w2"
2132 [(set_attr "type" "adc_reg")]
2135 (define_insn "*add_uxt<mode>_shift2"
2136 [(set (match_operand:GPI 0 "register_operand" "=rk")
2138 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2139 (match_operand 2 "aarch64_imm3" "Ui3"))
2140 (match_operand 3 "const_int_operand" "n"))
2141 (match_operand:GPI 4 "register_operand" "r")))]
2142 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2144 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2145 INTVAL (operands[3])));
2146 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2147 [(set_attr "type" "alu_ext")]
2150 ;; zero_extend version of above
2151 (define_insn "*add_uxtsi_shift2_uxtw"
2152 [(set (match_operand:DI 0 "register_operand" "=rk")
2155 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2156 (match_operand 2 "aarch64_imm3" "Ui3"))
2157 (match_operand 3 "const_int_operand" "n"))
2158 (match_operand:SI 4 "register_operand" "r"))))]
2159 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2161 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2162 INTVAL (operands[3])));
2163 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2164 [(set_attr "type" "alu_ext")]
2167 (define_insn "*add_uxt<mode>_multp2"
2168 [(set (match_operand:GPI 0 "register_operand" "=rk")
2170 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2171 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2172 (match_operand 3 "const_int_operand" "n"))
2173 (match_operand:GPI 4 "register_operand" "r")))]
2174 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2176 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2177 INTVAL (operands[3])));
2178 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2179 [(set_attr "type" "alu_ext")]
2182 ;; zero_extend version of above
2183 (define_insn "*add_uxtsi_multp2_uxtw"
2184 [(set (match_operand:DI 0 "register_operand" "=rk")
2187 (mult:SI (match_operand:SI 1 "register_operand" "r")
2188 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2189 (match_operand 3 "const_int_operand" "n"))
2190 (match_operand:SI 4 "register_operand" "r"))))]
2191 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2193 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2194 INTVAL (operands[3])));
2195 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2196 [(set_attr "type" "alu_ext")]
2199 (define_insn "subsi3"
2200 [(set (match_operand:SI 0 "register_operand" "=rk")
2201 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2202 (match_operand:SI 2 "register_operand" "r")))]
2204 "sub\\t%w0, %w1, %w2"
2205 [(set_attr "type" "alu_sreg")]
2208 ;; zero_extend version of above
2209 (define_insn "*subsi3_uxtw"
2210 [(set (match_operand:DI 0 "register_operand" "=rk")
2212 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2213 (match_operand:SI 2 "register_operand" "r"))))]
2215 "sub\\t%w0, %w1, %w2"
2216 [(set_attr "type" "alu_sreg")]
2219 (define_insn "subdi3"
2220 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2221 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2222 (match_operand:DI 2 "register_operand" "r,w")))]
2226 sub\\t%d0, %d1, %d2"
2227 [(set_attr "type" "alu_sreg, neon_sub")
2228 (set_attr "simd" "*,yes")]
2231 (define_expand "subti3"
2232 [(set (match_operand:TI 0 "register_operand" "")
2233 (minus:TI (match_operand:TI 1 "register_operand" "")
2234 (match_operand:TI 2 "register_operand" "")))]
2237 rtx low = gen_reg_rtx (DImode);
2238 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2239 gen_lowpart (DImode, operands[2])));
2241 rtx high = gen_reg_rtx (DImode);
2242 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2243 gen_highpart (DImode, operands[2])));
2245 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2246 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2250 (define_insn "*sub<mode>3_compare0"
2251 [(set (reg:CC_NZ CC_REGNUM)
2252 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2253 (match_operand:GPI 2 "register_operand" "r"))
2255 (set (match_operand:GPI 0 "register_operand" "=r")
2256 (minus:GPI (match_dup 1) (match_dup 2)))]
2258 "subs\\t%<w>0, %<w>1, %<w>2"
2259 [(set_attr "type" "alus_sreg")]
2262 ;; zero_extend version of above
2263 (define_insn "*subsi3_compare0_uxtw"
2264 [(set (reg:CC_NZ CC_REGNUM)
2265 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2266 (match_operand:SI 2 "register_operand" "r"))
2268 (set (match_operand:DI 0 "register_operand" "=r")
2269 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2271 "subs\\t%w0, %w1, %w2"
2272 [(set_attr "type" "alus_sreg")]
2275 (define_insn "sub<mode>3_compare1"
2276 [(set (reg:CC CC_REGNUM)
2278 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2279 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2280 (set (match_operand:GPI 0 "register_operand" "=r")
2281 (minus:GPI (match_dup 1) (match_dup 2)))]
2283 "subs\\t%<w>0, %<w>1, %<w>2"
2284 [(set_attr "type" "alus_sreg")]
2287 (define_insn "sub<mode>3_compare1_imm"
2288 [(set (reg:CC CC_REGNUM)
2290 (match_operand:GPI 1 "register_operand" "r")
2291 (match_operand:GPI 3 "const_int_operand" "n")))
2292 (set (match_operand:GPI 0 "register_operand" "=r")
2293 (plus:GPI (match_dup 1)
2294 (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2295 "INTVAL (operands[3]) == -INTVAL (operands[2])"
2296 "subs\\t%<w>0, %<w>1, #%n2"
2297 [(set_attr "type" "alus_sreg")]
2301 [(set (match_operand:GPI 0 "register_operand")
2302 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2303 (match_operand:GPI 2 "aarch64_reg_or_zero")))
2304 (set (reg:CC CC_REGNUM)
2308 "!reg_overlap_mentioned_p (operands[0], operands[1])
2309 && !reg_overlap_mentioned_p (operands[0], operands[2])"
2312 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2319 [(set (match_operand:GPI 0 "register_operand")
2320 (plus:GPI (match_operand:GPI 1 "register_operand")
2321 (match_operand:GPI 2 "aarch64_sub_immediate")))
2322 (set (reg:CC CC_REGNUM)
2325 (match_operand:GPI 3 "const_int_operand")))]
2326 "!reg_overlap_mentioned_p (operands[0], operands[1])
2327 && INTVAL (operands[3]) == -INTVAL (operands[2])"
2330 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2331 operands[2], operands[3]));
2336 (define_insn "*sub_<shift>_<mode>"
2337 [(set (match_operand:GPI 0 "register_operand" "=r")
2338 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2340 (match_operand:GPI 1 "register_operand" "r")
2341 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2343 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2344 [(set_attr "type" "alu_shift_imm")]
2347 ;; zero_extend version of above
2348 (define_insn "*sub_<shift>_si_uxtw"
2349 [(set (match_operand:DI 0 "register_operand" "=r")
2351 (minus:SI (match_operand:SI 3 "register_operand" "r")
2353 (match_operand:SI 1 "register_operand" "r")
2354 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2356 "sub\\t%w0, %w3, %w1, <shift> %2"
2357 [(set_attr "type" "alu_shift_imm")]
2360 (define_insn "*sub_mul_imm_<mode>"
2361 [(set (match_operand:GPI 0 "register_operand" "=r")
2362 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2364 (match_operand:GPI 1 "register_operand" "r")
2365 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2367 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2368 [(set_attr "type" "alu_shift_imm")]
2371 ;; zero_extend version of above
2372 (define_insn "*sub_mul_imm_si_uxtw"
2373 [(set (match_operand:DI 0 "register_operand" "=r")
2375 (minus:SI (match_operand:SI 3 "register_operand" "r")
2377 (match_operand:SI 1 "register_operand" "r")
2378 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2380 "sub\\t%w0, %w3, %w1, lsl %p2"
2381 [(set_attr "type" "alu_shift_imm")]
2384 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2385 [(set (match_operand:GPI 0 "register_operand" "=rk")
2386 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2388 (match_operand:ALLX 2 "register_operand" "r"))))]
2390 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2391 [(set_attr "type" "alu_ext")]
2394 ;; zero_extend version of above
2395 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2396 [(set (match_operand:DI 0 "register_operand" "=rk")
2398 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2400 (match_operand:SHORT 2 "register_operand" "r")))))]
2402 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2403 [(set_attr "type" "alu_ext")]
2406 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2407 [(set (match_operand:GPI 0 "register_operand" "=rk")
2408 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2409 (ashift:GPI (ANY_EXTEND:GPI
2410 (match_operand:ALLX 2 "register_operand" "r"))
2411 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2413 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2414 [(set_attr "type" "alu_ext")]
2417 ;; zero_extend version of above
2418 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2419 [(set (match_operand:DI 0 "register_operand" "=rk")
2421 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2422 (ashift:SI (ANY_EXTEND:SI
2423 (match_operand:SHORT 2 "register_operand" "r"))
2424 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2426 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2427 [(set_attr "type" "alu_ext")]
2430 (define_insn "*sub_<optab><mode>_multp2"
2431 [(set (match_operand:GPI 0 "register_operand" "=rk")
2432 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2434 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2435 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2436 (match_operand 3 "const_int_operand" "n")
2438 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2439 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2440 [(set_attr "type" "alu_ext")]
2443 ;; zero_extend version of above
2444 (define_insn "*sub_<optab>si_multp2_uxtw"
2445 [(set (match_operand:DI 0 "register_operand" "=rk")
2447 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2449 (mult:SI (match_operand:SI 1 "register_operand" "r")
2450 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2451 (match_operand 3 "const_int_operand" "n")
2453 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2454 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2455 [(set_attr "type" "alu_ext")]
2458 ;; The hardware description is op1 + ~op2 + C.
2459 ;; = op1 + (-op2 + 1) + (1 - !C)
2460 ;; = op1 - op2 - 1 + 1 - !C
2461 ;; = op1 - op2 - !C.
2462 ;; We describe the latter.
2464 (define_insn "*sub<mode>3_carryin0"
2465 [(set (match_operand:GPI 0 "register_operand" "=r")
2467 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2468 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2470 "sbc\\t%<w>0, %<w>1, <w>zr"
2471 [(set_attr "type" "adc_reg")]
2474 ;; zero_extend version of the above
2475 (define_insn "*subsi3_carryin_uxtw"
2476 [(set (match_operand:DI 0 "register_operand" "=r")
2479 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2480 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2482 "sbc\\t%w0, %w1, wzr"
2483 [(set_attr "type" "adc_reg")]
2486 (define_expand "sub<mode>3_carryin"
2487 [(set (match_operand:GPI 0 "register_operand")
2490 (match_operand:GPI 1 "aarch64_reg_or_zero")
2491 (match_operand:GPI 2 "register_operand"))
2492 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2497 (define_insn "*sub<mode>3_carryin"
2498 [(set (match_operand:GPI 0 "register_operand" "=r")
2501 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2502 (match_operand:GPI 2 "register_operand" "r"))
2503 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2506 "sbc\\t%<w>0, %<w>1, %<w>2"
2507 [(set_attr "type" "adc_reg")]
2510 ;; zero_extend version of the above
2511 (define_insn "*subsi3_carryin_uxtw"
2512 [(set (match_operand:DI 0 "register_operand" "=r")
2516 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2517 (match_operand:SI 2 "register_operand" "r"))
2518 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2521 "sbc\\t%w0, %w1, %w2"
2522 [(set_attr "type" "adc_reg")]
2525 (define_insn "*sub<mode>3_carryin_alt"
2526 [(set (match_operand:GPI 0 "register_operand" "=r")
2529 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2530 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2531 (match_operand:GPI 2 "register_operand" "r")))]
2533 "sbc\\t%<w>0, %<w>1, %<w>2"
2534 [(set_attr "type" "adc_reg")]
2537 ;; zero_extend version of the above
2538 (define_insn "*subsi3_carryin_alt_uxtw"
2539 [(set (match_operand:DI 0 "register_operand" "=r")
2543 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2544 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2545 (match_operand:SI 2 "register_operand" "r"))))]
2547 "sbc\\t%w0, %w1, %w2"
2548 [(set_attr "type" "adc_reg")]
2551 (define_insn "*sub_uxt<mode>_shift2"
2552 [(set (match_operand:GPI 0 "register_operand" "=rk")
2553 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2555 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2556 (match_operand 2 "aarch64_imm3" "Ui3"))
2557 (match_operand 3 "const_int_operand" "n"))))]
2558 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2560 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2561 INTVAL (operands[3])));
2562 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2563 [(set_attr "type" "alu_ext")]
2566 ;; zero_extend version of above
2567 (define_insn "*sub_uxtsi_shift2_uxtw"
2568 [(set (match_operand:DI 0 "register_operand" "=rk")
2570 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2572 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2573 (match_operand 2 "aarch64_imm3" "Ui3"))
2574 (match_operand 3 "const_int_operand" "n")))))]
2575 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2577 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2578 INTVAL (operands[3])));
2579 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2580 [(set_attr "type" "alu_ext")]
2583 (define_insn "*sub_uxt<mode>_multp2"
2584 [(set (match_operand:GPI 0 "register_operand" "=rk")
2585 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2587 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2588 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2589 (match_operand 3 "const_int_operand" "n"))))]
2590 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2592 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2593 INTVAL (operands[3])));
2594 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2595 [(set_attr "type" "alu_ext")]
2598 ;; zero_extend version of above
2599 (define_insn "*sub_uxtsi_multp2_uxtw"
2600 [(set (match_operand:DI 0 "register_operand" "=rk")
2602 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2604 (mult:SI (match_operand:SI 1 "register_operand" "r")
2605 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2606 (match_operand 3 "const_int_operand" "n")))))]
2607 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2609 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2610 INTVAL (operands[3])));
2611 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2612 [(set_attr "type" "alu_ext")]
2615 (define_expand "abs<mode>2"
2616 [(match_operand:GPI 0 "register_operand" "")
2617 (match_operand:GPI 1 "register_operand" "")]
2620 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2621 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2622 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2627 (define_insn "neg<mode>2"
2628 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2629 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2633 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2634 [(set_attr "type" "alu_sreg, neon_neg<q>")
2635 (set_attr "simd" "*,yes")]
2638 ;; zero_extend version of above
2639 (define_insn "*negsi2_uxtw"
2640 [(set (match_operand:DI 0 "register_operand" "=r")
2641 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2644 [(set_attr "type" "alu_sreg")]
2647 (define_insn "*ngc<mode>"
2648 [(set (match_operand:GPI 0 "register_operand" "=r")
2650 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2651 (match_operand:GPI 1 "register_operand" "r")))]
2653 "ngc\\t%<w>0, %<w>1"
2654 [(set_attr "type" "adc_reg")]
2657 (define_insn "*ngcsi_uxtw"
2658 [(set (match_operand:DI 0 "register_operand" "=r")
2661 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2662 (match_operand:SI 1 "register_operand" "r"))))]
2665 [(set_attr "type" "adc_reg")]
2668 (define_insn "neg<mode>2_compare0"
2669 [(set (reg:CC_NZ CC_REGNUM)
2670 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2672 (set (match_operand:GPI 0 "register_operand" "=r")
2673 (neg:GPI (match_dup 1)))]
2675 "negs\\t%<w>0, %<w>1"
2676 [(set_attr "type" "alus_sreg")]
2679 ;; zero_extend version of above
2680 (define_insn "*negsi2_compare0_uxtw"
2681 [(set (reg:CC_NZ CC_REGNUM)
2682 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2684 (set (match_operand:DI 0 "register_operand" "=r")
2685 (zero_extend:DI (neg:SI (match_dup 1))))]
2688 [(set_attr "type" "alus_sreg")]
2691 (define_insn "*neg_<shift><mode>3_compare0"
2692 [(set (reg:CC_NZ CC_REGNUM)
2694 (neg:GPI (ASHIFT:GPI
2695 (match_operand:GPI 1 "register_operand" "r")
2696 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2698 (set (match_operand:GPI 0 "register_operand" "=r")
2699 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2701 "negs\\t%<w>0, %<w>1, <shift> %2"
2702 [(set_attr "type" "alus_shift_imm")]
2705 (define_insn "*neg_<shift>_<mode>2"
2706 [(set (match_operand:GPI 0 "register_operand" "=r")
2707 (neg:GPI (ASHIFT:GPI
2708 (match_operand:GPI 1 "register_operand" "r")
2709 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2711 "neg\\t%<w>0, %<w>1, <shift> %2"
2712 [(set_attr "type" "alu_shift_imm")]
2715 ;; zero_extend version of above
2716 (define_insn "*neg_<shift>_si2_uxtw"
2717 [(set (match_operand:DI 0 "register_operand" "=r")
2720 (match_operand:SI 1 "register_operand" "r")
2721 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2723 "neg\\t%w0, %w1, <shift> %2"
2724 [(set_attr "type" "alu_shift_imm")]
2727 (define_insn "*neg_mul_imm_<mode>2"
2728 [(set (match_operand:GPI 0 "register_operand" "=r")
2730 (match_operand:GPI 1 "register_operand" "r")
2731 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2733 "neg\\t%<w>0, %<w>1, lsl %p2"
2734 [(set_attr "type" "alu_shift_imm")]
2737 ;; zero_extend version of above
2738 (define_insn "*neg_mul_imm_si2_uxtw"
2739 [(set (match_operand:DI 0 "register_operand" "=r")
2742 (match_operand:SI 1 "register_operand" "r")
2743 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2745 "neg\\t%w0, %w1, lsl %p2"
2746 [(set_attr "type" "alu_shift_imm")]
2749 (define_insn "mul<mode>3"
2750 [(set (match_operand:GPI 0 "register_operand" "=r")
2751 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2752 (match_operand:GPI 2 "register_operand" "r")))]
2754 "mul\\t%<w>0, %<w>1, %<w>2"
2755 [(set_attr "type" "mul")]
2758 ;; zero_extend version of above
2759 (define_insn "*mulsi3_uxtw"
2760 [(set (match_operand:DI 0 "register_operand" "=r")
2762 (mult:SI (match_operand:SI 1 "register_operand" "r")
2763 (match_operand:SI 2 "register_operand" "r"))))]
2765 "mul\\t%w0, %w1, %w2"
2766 [(set_attr "type" "mul")]
2769 (define_insn "madd<mode>"
2770 [(set (match_operand:GPI 0 "register_operand" "=r")
2771 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2772 (match_operand:GPI 2 "register_operand" "r"))
2773 (match_operand:GPI 3 "register_operand" "r")))]
2775 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2776 [(set_attr "type" "mla")]
2779 ;; zero_extend version of above
2780 (define_insn "*maddsi_uxtw"
2781 [(set (match_operand:DI 0 "register_operand" "=r")
2783 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2784 (match_operand:SI 2 "register_operand" "r"))
2785 (match_operand:SI 3 "register_operand" "r"))))]
2787 "madd\\t%w0, %w1, %w2, %w3"
2788 [(set_attr "type" "mla")]
2791 (define_insn "*msub<mode>"
2792 [(set (match_operand:GPI 0 "register_operand" "=r")
2793 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2794 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2795 (match_operand:GPI 2 "register_operand" "r"))))]
2798 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2799 [(set_attr "type" "mla")]
2802 ;; zero_extend version of above
2803 (define_insn "*msubsi_uxtw"
2804 [(set (match_operand:DI 0 "register_operand" "=r")
2806 (minus:SI (match_operand:SI 3 "register_operand" "r")
2807 (mult:SI (match_operand:SI 1 "register_operand" "r")
2808 (match_operand:SI 2 "register_operand" "r")))))]
2811 "msub\\t%w0, %w1, %w2, %w3"
2812 [(set_attr "type" "mla")]
2815 (define_insn "*mul<mode>_neg"
2816 [(set (match_operand:GPI 0 "register_operand" "=r")
2817 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2818 (match_operand:GPI 2 "register_operand" "r")))]
2821 "mneg\\t%<w>0, %<w>1, %<w>2"
2822 [(set_attr "type" "mul")]
2825 ;; zero_extend version of above
2826 (define_insn "*mulsi_neg_uxtw"
2827 [(set (match_operand:DI 0 "register_operand" "=r")
2829 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2830 (match_operand:SI 2 "register_operand" "r"))))]
2833 "mneg\\t%w0, %w1, %w2"
2834 [(set_attr "type" "mul")]
2837 (define_insn "<su_optab>mulsidi3"
2838 [(set (match_operand:DI 0 "register_operand" "=r")
2839 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2840 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2842 "<su>mull\\t%0, %w1, %w2"
2843 [(set_attr "type" "<su>mull")]
2846 (define_insn "<su_optab>maddsidi4"
2847 [(set (match_operand:DI 0 "register_operand" "=r")
2849 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2850 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2851 (match_operand:DI 3 "register_operand" "r")))]
2853 "<su>maddl\\t%0, %w1, %w2, %3"
2854 [(set_attr "type" "<su>mlal")]
2857 (define_insn "<su_optab>msubsidi4"
2858 [(set (match_operand:DI 0 "register_operand" "=r")
2860 (match_operand:DI 3 "register_operand" "r")
2861 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2863 (match_operand:SI 2 "register_operand" "r")))))]
2865 "<su>msubl\\t%0, %w1, %w2, %3"
2866 [(set_attr "type" "<su>mlal")]
2869 (define_insn "*<su_optab>mulsidi_neg"
2870 [(set (match_operand:DI 0 "register_operand" "=r")
2872 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2873 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2875 "<su>mnegl\\t%0, %w1, %w2"
2876 [(set_attr "type" "<su>mull")]
2879 (define_expand "<su_optab>mulditi3"
2880 [(set (match_operand:TI 0 "register_operand")
2881 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2882 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2885 rtx low = gen_reg_rtx (DImode);
2886 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2888 rtx high = gen_reg_rtx (DImode);
2889 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2891 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2892 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2896 ;; The default expansion of multi3 using umuldi3_highpart will perform
2897 ;; the additions in an order that fails to combine into two madd insns.
2898 (define_expand "multi3"
2899 [(set (match_operand:TI 0 "register_operand")
2900 (mult:TI (match_operand:TI 1 "register_operand")
2901 (match_operand:TI 2 "register_operand")))]
2904 rtx l0 = gen_reg_rtx (DImode);
2905 rtx l1 = gen_lowpart (DImode, operands[1]);
2906 rtx l2 = gen_lowpart (DImode, operands[2]);
2907 rtx h0 = gen_reg_rtx (DImode);
2908 rtx h1 = gen_highpart (DImode, operands[1]);
2909 rtx h2 = gen_highpart (DImode, operands[2]);
2911 emit_insn (gen_muldi3 (l0, l1, l2));
2912 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2913 emit_insn (gen_madddi (h0, h1, l2, h0));
2914 emit_insn (gen_madddi (h0, l1, h2, h0));
2916 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2917 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2921 (define_insn "<su>muldi3_highpart"
2922 [(set (match_operand:DI 0 "register_operand" "=r")
2926 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2927 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2930 "<su>mulh\\t%0, %1, %2"
2931 [(set_attr "type" "<su>mull")]
2934 (define_insn "<su_optab>div<mode>3"
2935 [(set (match_operand:GPI 0 "register_operand" "=r")
2936 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2937 (match_operand:GPI 2 "register_operand" "r")))]
2939 "<su>div\\t%<w>0, %<w>1, %<w>2"
2940 [(set_attr "type" "<su>div")]
2943 ;; zero_extend version of above
2944 (define_insn "*<su_optab>divsi3_uxtw"
2945 [(set (match_operand:DI 0 "register_operand" "=r")
2947 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2948 (match_operand:SI 2 "register_operand" "r"))))]
2950 "<su>div\\t%w0, %w1, %w2"
2951 [(set_attr "type" "<su>div")]
2954 ;; -------------------------------------------------------------------
2956 ;; -------------------------------------------------------------------
2958 (define_insn "cmp<mode>"
2959 [(set (reg:CC CC_REGNUM)
2960 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2961 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2967 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2970 (define_insn "fcmp<mode>"
2971 [(set (reg:CCFP CC_REGNUM)
2972 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2973 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2977 fcmp\\t%<s>0, %<s>1"
2978 [(set_attr "type" "fcmp<s>")]
2981 (define_insn "fcmpe<mode>"
2982 [(set (reg:CCFPE CC_REGNUM)
2983 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2984 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2988 fcmpe\\t%<s>0, %<s>1"
2989 [(set_attr "type" "fcmp<s>")]
2992 (define_insn "*cmp_swp_<shift>_reg<mode>"
2993 [(set (reg:CC_SWP CC_REGNUM)
2994 (compare:CC_SWP (ASHIFT:GPI
2995 (match_operand:GPI 0 "register_operand" "r")
2996 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2997 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2999 "cmp\\t%<w>2, %<w>0, <shift> %1"
3000 [(set_attr "type" "alus_shift_imm")]
3003 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3004 [(set (reg:CC_SWP CC_REGNUM)
3005 (compare:CC_SWP (ANY_EXTEND:GPI
3006 (match_operand:ALLX 0 "register_operand" "r"))
3007 (match_operand:GPI 1 "register_operand" "r")))]
3009 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3010 [(set_attr "type" "alus_ext")]
3013 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3014 [(set (reg:CC_SWP CC_REGNUM)
3015 (compare:CC_SWP (ashift:GPI
3017 (match_operand:ALLX 0 "register_operand" "r"))
3018 (match_operand 1 "aarch64_imm3" "Ui3"))
3019 (match_operand:GPI 2 "register_operand" "r")))]
3021 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3022 [(set_attr "type" "alus_ext")]
3025 ;; -------------------------------------------------------------------
3026 ;; Store-flag and conditional select insns
3027 ;; -------------------------------------------------------------------
3029 (define_expand "cstore<mode>4"
3030 [(set (match_operand:SI 0 "register_operand" "")
3031 (match_operator:SI 1 "aarch64_comparison_operator"
3032 [(match_operand:GPI 2 "register_operand" "")
3033 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3036 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3038 operands[3] = const0_rtx;
3042 (define_expand "cstorecc4"
3043 [(set (match_operand:SI 0 "register_operand")
3044 (match_operator 1 "aarch64_comparison_operator_mode"
3045 [(match_operand 2 "cc_register")
3046 (match_operand 3 "const0_operand")]))]
3049 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3054 (define_expand "cstore<mode>4"
3055 [(set (match_operand:SI 0 "register_operand" "")
3056 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3057 [(match_operand:GPF 2 "register_operand" "")
3058 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3061 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3063 operands[3] = const0_rtx;
3067 (define_insn "aarch64_cstore<mode>"
3068 [(set (match_operand:ALLI 0 "register_operand" "=r")
3069 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3070 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3073 [(set_attr "type" "csel")]
3076 ;; For a 24-bit immediate CST we can optimize the compare for equality
3077 ;; and branch sequence from:
3079 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3082 ;; into the shorter:
3083 ;; sub x0, x1, #(CST & 0xfff000)
3084 ;; subs x0, x0, #(CST & 0x000fff)
3085 ;; cset x2, <ne, eq>.
3086 (define_insn_and_split "*compare_cstore<mode>_insn"
3087 [(set (match_operand:GPI 0 "register_operand" "=r")
3088 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3089 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3090 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3091 && !aarch64_plus_operand (operands[2], <MODE>mode)
3092 && !reload_completed"
3097 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3098 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3099 rtx tmp = gen_reg_rtx (<MODE>mode);
3100 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3101 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3102 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3103 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3104 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3107 [(set_attr "type" "csel")]
3110 ;; zero_extend version of the above
3111 (define_insn "*cstoresi_insn_uxtw"
3112 [(set (match_operand:DI 0 "register_operand" "=r")
3114 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3115 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3118 [(set_attr "type" "csel")]
3121 (define_insn "cstore<mode>_neg"
3122 [(set (match_operand:ALLI 0 "register_operand" "=r")
3123 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3124 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3126 "csetm\\t%<w>0, %m1"
3127 [(set_attr "type" "csel")]
3130 ;; zero_extend version of the above
3131 (define_insn "*cstoresi_neg_uxtw"
3132 [(set (match_operand:DI 0 "register_operand" "=r")
3134 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3135 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3138 [(set_attr "type" "csel")]
3141 (define_expand "cmov<mode>6"
3142 [(set (match_operand:GPI 0 "register_operand" "")
3144 (match_operator 1 "aarch64_comparison_operator"
3145 [(match_operand:GPI 2 "register_operand" "")
3146 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3147 (match_operand:GPI 4 "register_operand" "")
3148 (match_operand:GPI 5 "register_operand" "")))]
3151 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3153 operands[3] = const0_rtx;
3157 (define_expand "cmov<mode>6"
3158 [(set (match_operand:GPF 0 "register_operand" "")
3160 (match_operator 1 "aarch64_comparison_operator"
3161 [(match_operand:GPF 2 "register_operand" "")
3162 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3163 (match_operand:GPF 4 "register_operand" "")
3164 (match_operand:GPF 5 "register_operand" "")))]
3167 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3169 operands[3] = const0_rtx;
3173 (define_insn "*cmov<mode>_insn"
3174 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3176 (match_operator 1 "aarch64_comparison_operator"
3177 [(match_operand 2 "cc_register" "") (const_int 0)])
3178 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3179 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3180 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3181 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3182 ;; Final two alternatives should be unreachable, but included for completeness
3184 csel\\t%<w>0, %<w>3, %<w>4, %m1
3185 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3186 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3187 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3188 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3191 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3194 ;; zero_extend version of above
3195 (define_insn "*cmovsi_insn_uxtw"
3196 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3199 (match_operator 1 "aarch64_comparison_operator"
3200 [(match_operand 2 "cc_register" "") (const_int 0)])
3201 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3202 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3203 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3204 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3205 ;; Final two alternatives should be unreachable, but included for completeness
3207 csel\\t%w0, %w3, %w4, %m1
3208 csinv\\t%w0, %w3, wzr, %m1
3209 csinv\\t%w0, %w4, wzr, %M1
3210 csinc\\t%w0, %w3, wzr, %m1
3211 csinc\\t%w0, %w4, wzr, %M1
3214 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3217 (define_insn "*cmovdi_insn_uxtw"
3218 [(set (match_operand:DI 0 "register_operand" "=r")
3220 (match_operator 1 "aarch64_comparison_operator"
3221 [(match_operand 2 "cc_register" "") (const_int 0)])
3222 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3223 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3225 "csel\\t%w0, %w3, %w4, %m1"
3226 [(set_attr "type" "csel")]
3229 (define_insn "*cmov<mode>_insn"
3230 [(set (match_operand:GPF 0 "register_operand" "=w")
3232 (match_operator 1 "aarch64_comparison_operator"
3233 [(match_operand 2 "cc_register" "") (const_int 0)])
3234 (match_operand:GPF 3 "register_operand" "w")
3235 (match_operand:GPF 4 "register_operand" "w")))]
3237 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3238 [(set_attr "type" "fcsel")]
3241 (define_expand "mov<mode>cc"
3242 [(set (match_operand:ALLI 0 "register_operand" "")
3243 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3244 (match_operand:ALLI 2 "register_operand" "")
3245 (match_operand:ALLI 3 "register_operand" "")))]
3249 enum rtx_code code = GET_CODE (operands[1]);
3251 if (code == UNEQ || code == LTGT)
3254 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3255 XEXP (operands[1], 1));
3256 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3260 (define_expand "mov<GPF:mode><GPI:mode>cc"
3261 [(set (match_operand:GPI 0 "register_operand" "")
3262 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3263 (match_operand:GPF 2 "register_operand" "")
3264 (match_operand:GPF 3 "register_operand" "")))]
3268 enum rtx_code code = GET_CODE (operands[1]);
3270 if (code == UNEQ || code == LTGT)
3273 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3274 XEXP (operands[1], 1));
3275 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3279 (define_expand "mov<mode>cc"
3280 [(set (match_operand:GPF 0 "register_operand" "")
3281 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3282 (match_operand:GPF 2 "register_operand" "")
3283 (match_operand:GPF 3 "register_operand" "")))]
3287 enum rtx_code code = GET_CODE (operands[1]);
3289 if (code == UNEQ || code == LTGT)
3292 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3293 XEXP (operands[1], 1));
3294 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3298 (define_expand "<neg_not_op><mode>cc"
3299 [(set (match_operand:GPI 0 "register_operand" "")
3300 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3301 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3302 (match_operand:GPI 3 "register_operand" "")))]
3306 enum rtx_code code = GET_CODE (operands[1]);
3308 if (code == UNEQ || code == LTGT)
3311 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3312 XEXP (operands[1], 1));
3313 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3317 ;; CRC32 instructions.
3318 (define_insn "aarch64_<crc_variant>"
3319 [(set (match_operand:SI 0 "register_operand" "=r")
3320 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3321 (match_operand:<crc_mode> 2 "register_operand" "r")]
3325 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3326 return "<crc_variant>\\t%w0, %w1, %x2";
3328 return "<crc_variant>\\t%w0, %w1, %w2";
3330 [(set_attr "type" "crc")]
3333 (define_insn "*csinc2<mode>_insn"
3334 [(set (match_operand:GPI 0 "register_operand" "=r")
3335 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3336 (match_operand:GPI 1 "register_operand" "r")))]
3338 "cinc\\t%<w>0, %<w>1, %m2"
3339 [(set_attr "type" "csel")]
3342 (define_insn "csinc3<mode>_insn"
3343 [(set (match_operand:GPI 0 "register_operand" "=r")
3345 (match_operand 1 "aarch64_comparison_operation" "")
3346 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3348 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3350 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3351 [(set_attr "type" "csel")]
3354 (define_insn "*csinv3<mode>_insn"
3355 [(set (match_operand:GPI 0 "register_operand" "=r")
3357 (match_operand 1 "aarch64_comparison_operation" "")
3358 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3359 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3361 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3362 [(set_attr "type" "csel")]
3365 (define_insn "csneg3_uxtw_insn"
3366 [(set (match_operand:DI 0 "register_operand" "=r")
3369 (match_operand 1 "aarch64_comparison_operation" "")
3370 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3371 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3373 "csneg\\t%w0, %w3, %w2, %M1"
3374 [(set_attr "type" "csel")]
3377 (define_insn "csneg3<mode>_insn"
3378 [(set (match_operand:GPI 0 "register_operand" "=r")
3380 (match_operand 1 "aarch64_comparison_operation" "")
3381 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3382 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3384 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3385 [(set_attr "type" "csel")]
3388 ;; -------------------------------------------------------------------
3389 ;; Logical operations
3390 ;; -------------------------------------------------------------------
3393 (define_insn_and_split "*aarch64_and<mode>_imm2"
3394 [(set (match_operand:GPI 0 "register_operand" "=rk")
3395 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3396 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3402 HOST_WIDE_INT val = INTVAL (operands[2]);
3403 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3404 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3406 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3407 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3412 (define_insn "<optab><mode>3"
3413 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3414 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3415 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3418 <logical>\\t%<w>0, %<w>1, %<w>2
3419 <logical>\\t%<w>0, %<w>1, %2
3420 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3421 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3422 (set_attr "simd" "*,*,yes")]
3425 ;; zero_extend version of above
3426 (define_insn "*<optab>si3_uxtw"
3427 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3429 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3430 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3433 <logical>\\t%w0, %w1, %w2
3434 <logical>\\t%w0, %w1, %2"
3435 [(set_attr "type" "logic_reg,logic_imm")]
3438 (define_insn "*and<mode>3_compare0"
3439 [(set (reg:CC_NZ CC_REGNUM)
3441 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3442 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3444 (set (match_operand:GPI 0 "register_operand" "=r,r")
3445 (and:GPI (match_dup 1) (match_dup 2)))]
3448 ands\\t%<w>0, %<w>1, %<w>2
3449 ands\\t%<w>0, %<w>1, %2"
3450 [(set_attr "type" "logics_reg,logics_imm")]
3453 ;; zero_extend version of above
3454 (define_insn "*andsi3_compare0_uxtw"
3455 [(set (reg:CC_NZ CC_REGNUM)
3457 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3458 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3460 (set (match_operand:DI 0 "register_operand" "=r,r")
3461 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3464 ands\\t%w0, %w1, %w2
3465 ands\\t%w0, %w1, %2"
3466 [(set_attr "type" "logics_reg,logics_imm")]
3469 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3470 [(set (reg:CC_NZ CC_REGNUM)
3473 (match_operand:GPI 1 "register_operand" "r")
3474 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3475 (match_operand:GPI 3 "register_operand" "r"))
3477 (set (match_operand:GPI 0 "register_operand" "=r")
3478 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3480 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3481 [(set_attr "type" "logics_shift_imm")]
3484 ;; zero_extend version of above
3485 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3486 [(set (reg:CC_NZ CC_REGNUM)
3489 (match_operand:SI 1 "register_operand" "r")
3490 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3491 (match_operand:SI 3 "register_operand" "r"))
3493 (set (match_operand:DI 0 "register_operand" "=r")
3494 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3497 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3498 [(set_attr "type" "logics_shift_imm")]
3501 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3502 [(set (match_operand:GPI 0 "register_operand" "=r")
3503 (LOGICAL:GPI (SHIFT:GPI
3504 (match_operand:GPI 1 "register_operand" "r")
3505 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3506 (match_operand:GPI 3 "register_operand" "r")))]
3508 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3509 [(set_attr "type" "logic_shift_imm")]
3512 (define_insn "*<optab>_rol<mode>3"
3513 [(set (match_operand:GPI 0 "register_operand" "=r")
3514 (LOGICAL:GPI (rotate: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>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3520 [(set_attr "type" "logic_shift_imm")]
3523 ;; zero_extend versions of above
3524 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3525 [(set (match_operand:DI 0 "register_operand" "=r")
3527 (LOGICAL:SI (SHIFT:SI
3528 (match_operand:SI 1 "register_operand" "r")
3529 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3530 (match_operand:SI 3 "register_operand" "r"))))]
3532 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3533 [(set_attr "type" "logic_shift_imm")]
3536 (define_insn "*<optab>_rolsi3_uxtw"
3537 [(set (match_operand:DI 0 "register_operand" "=r")
3539 (LOGICAL:SI (rotate:SI
3540 (match_operand:SI 1 "register_operand" "r")
3541 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3542 (match_operand:SI 3 "register_operand" "r"))))]
3544 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3545 [(set_attr "type" "logic_shift_imm")]
3548 (define_insn "one_cmpl<mode>2"
3549 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3550 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3555 [(set_attr "type" "logic_reg,neon_logic")
3556 (set_attr "simd" "*,yes")]
3559 (define_insn "*one_cmpl_<optab><mode>2"
3560 [(set (match_operand:GPI 0 "register_operand" "=r")
3561 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3562 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3564 "mvn\\t%<w>0, %<w>1, <shift> %2"
3565 [(set_attr "type" "logic_shift_imm")]
3568 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3570 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3571 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3572 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3573 (match_operand:GPI 2 "register_operand" "r,w")))]
3576 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3577 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3578 [(set_attr "type" "logic_reg,neon_logic")
3579 (set_attr "simd" "*,yes")]
3582 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3583 [(set (match_operand:DI 0 "register_operand" "=r")
3585 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3586 (match_operand:SI 2 "register_operand" "r"))))]
3588 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3589 [(set_attr "type" "logic_reg")]
3592 (define_insn "*xor_one_cmplsidi3_ze"
3593 [(set (match_operand:DI 0 "register_operand" "=r")
3595 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3596 (match_operand:SI 2 "register_operand" "r")))))]
3598 "eon\\t%w0, %w1, %w2"
3599 [(set_attr "type" "logic_reg")]
3602 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3603 ;; eon does not operate on SIMD registers so the vector variant must be split.
3604 (define_insn_and_split "*xor_one_cmpl<mode>3"
3605 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3606 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3607 (match_operand:GPI 2 "register_operand" "r,w"))))]
3610 eon\\t%<w>0, %<w>1, %<w>2
3612 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3613 [(set (match_operand:GPI 0 "register_operand" "=w")
3614 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3615 (match_operand:GPI 2 "register_operand" "w")))
3616 (set (match_dup 0) (not:GPI (match_dup 0)))]
3618 [(set_attr "type" "logic_reg,multiple")
3619 (set_attr "simd" "*,yes")]
3622 (define_insn "*and_one_cmpl<mode>3_compare0"
3623 [(set (reg:CC_NZ CC_REGNUM)
3626 (match_operand:GPI 1 "register_operand" "r"))
3627 (match_operand:GPI 2 "register_operand" "r"))
3629 (set (match_operand:GPI 0 "register_operand" "=r")
3630 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3632 "bics\\t%<w>0, %<w>2, %<w>1"
3633 [(set_attr "type" "logics_reg")]
3636 ;; zero_extend version of above
3637 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3638 [(set (reg:CC_NZ CC_REGNUM)
3641 (match_operand:SI 1 "register_operand" "r"))
3642 (match_operand:SI 2 "register_operand" "r"))
3644 (set (match_operand:DI 0 "register_operand" "=r")
3645 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3647 "bics\\t%w0, %w2, %w1"
3648 [(set_attr "type" "logics_reg")]
3651 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3652 [(set (reg:CC_NZ CC_REGNUM)
3655 (match_operand:GPI 0 "register_operand" "r"))
3656 (match_operand:GPI 1 "register_operand" "r"))
3659 "bics\\t<w>zr, %<w>1, %<w>0"
3660 [(set_attr "type" "logics_reg")]
3663 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3664 [(set (match_operand:GPI 0 "register_operand" "=r")
3665 (LOGICAL:GPI (not:GPI
3667 (match_operand:GPI 1 "register_operand" "r")
3668 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3669 (match_operand:GPI 3 "register_operand" "r")))]
3671 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3672 [(set_attr "type" "logic_shift_imm")]
3675 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3676 [(set (match_operand:GPI 0 "register_operand" "=r")
3679 (match_operand:GPI 1 "register_operand" "r")
3680 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3681 (match_operand:GPI 3 "register_operand" "r"))))]
3683 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3684 [(set_attr "type" "logic_shift_imm")]
3687 ;; Zero-extend version of the above.
3688 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3689 [(set (match_operand:DI 0 "register_operand" "=r")
3693 (match_operand:SI 1 "register_operand" "r")
3694 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3695 (match_operand:SI 3 "register_operand" "r")))))]
3697 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3698 [(set_attr "type" "logic_shift_imm")]
3701 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3702 [(set (reg:CC_NZ CC_REGNUM)
3706 (match_operand:GPI 1 "register_operand" "r")
3707 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3708 (match_operand:GPI 3 "register_operand" "r"))
3710 (set (match_operand:GPI 0 "register_operand" "=r")
3713 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3715 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3716 [(set_attr "type" "logics_shift_imm")]
3719 ;; zero_extend version of above
3720 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3721 [(set (reg:CC_NZ CC_REGNUM)
3725 (match_operand:SI 1 "register_operand" "r")
3726 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3727 (match_operand:SI 3 "register_operand" "r"))
3729 (set (match_operand:DI 0 "register_operand" "=r")
3730 (zero_extend:DI (and:SI
3732 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3734 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3735 [(set_attr "type" "logics_shift_imm")]
3738 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3739 [(set (reg:CC_NZ CC_REGNUM)
3743 (match_operand:GPI 0 "register_operand" "r")
3744 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3745 (match_operand:GPI 2 "register_operand" "r"))
3748 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3749 [(set_attr "type" "logics_shift_imm")]
3752 (define_insn "clz<mode>2"
3753 [(set (match_operand:GPI 0 "register_operand" "=r")
3754 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3756 "clz\\t%<w>0, %<w>1"
3757 [(set_attr "type" "clz")]
3760 (define_expand "ffs<mode>2"
3761 [(match_operand:GPI 0 "register_operand")
3762 (match_operand:GPI 1 "register_operand")]
3765 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3766 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3768 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3769 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3770 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3775 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3782 (define_expand "popcount<mode>2"
3783 [(match_operand:GPI 0 "register_operand")
3784 (match_operand:GPI 1 "register_operand")]
3787 rtx v = gen_reg_rtx (V8QImode);
3788 rtx v1 = gen_reg_rtx (V8QImode);
3789 rtx r = gen_reg_rtx (QImode);
3790 rtx in = operands[1];
3791 rtx out = operands[0];
3792 if(<MODE>mode == SImode)
3795 tmp = gen_reg_rtx (DImode);
3796 /* If we have SImode, zero extend to DImode, pop count does
3797 not change if we have extra zeros. */
3798 emit_insn (gen_zero_extendsidi2 (tmp, in));
3801 emit_move_insn (v, gen_lowpart (V8QImode, in));
3802 emit_insn (gen_popcountv8qi2 (v1, v));
3803 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3804 emit_insn (gen_zero_extendqi<mode>2 (out, r));
3808 (define_insn "clrsb<mode>2"
3809 [(set (match_operand:GPI 0 "register_operand" "=r")
3810 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3812 "cls\\t%<w>0, %<w>1"
3813 [(set_attr "type" "clz")]
3816 (define_insn "rbit<mode>2"
3817 [(set (match_operand:GPI 0 "register_operand" "=r")
3818 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3820 "rbit\\t%<w>0, %<w>1"
3821 [(set_attr "type" "rbit")]
3824 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3825 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3826 ;; expression and split after reload to enable scheduling them apart if
3829 (define_insn_and_split "ctz<mode>2"
3830 [(set (match_operand:GPI 0 "register_operand" "=r")
3831 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3837 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3838 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3842 (define_insn "*and<mode>_compare0"
3843 [(set (reg:CC_NZ CC_REGNUM)
3845 (match_operand:SHORT 0 "register_operand" "r")
3848 "tst\\t%<w>0, <short_mask>"
3849 [(set_attr "type" "alus_imm")]
3852 (define_insn "*ands<mode>_compare0"
3853 [(set (reg:CC_NZ CC_REGNUM)
3855 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3857 (set (match_operand:GPI 0 "register_operand" "=r")
3858 (zero_extend:GPI (match_dup 1)))]
3860 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3861 [(set_attr "type" "alus_imm")]
3864 (define_insn "*and<mode>3nr_compare0"
3865 [(set (reg:CC_NZ CC_REGNUM)
3867 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3868 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3874 [(set_attr "type" "logics_reg,logics_imm")]
3878 [(set (reg:CC_NZ CC_REGNUM)
3880 (and:GPI (match_operand:GPI 0 "register_operand")
3881 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
3883 (clobber (match_operand:SI 2 "register_operand"))]
3885 [(set (match_dup 2) (match_dup 1))
3886 (set (reg:CC_NZ CC_REGNUM)
3888 (and:GPI (match_dup 0)
3893 (define_insn "*and<mode>3nr_compare0_zextract"
3894 [(set (reg:CC_NZ CC_REGNUM)
3896 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3897 (match_operand:GPI 1 "const_int_operand" "n")
3898 (match_operand:GPI 2 "const_int_operand" "n"))
3900 "INTVAL (operands[1]) > 0
3901 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3902 <= GET_MODE_BITSIZE (<MODE>mode))
3903 && aarch64_bitmask_imm (
3904 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3909 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3910 return "tst\\t%<w>0, %1";
3912 [(set_attr "type" "logics_shift_imm")]
3915 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3916 [(set (reg:CC_NZ CC_REGNUM)
3919 (match_operand:GPI 0 "register_operand" "r")
3920 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3921 (match_operand:GPI 2 "register_operand" "r"))
3924 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3925 [(set_attr "type" "logics_shift_imm")]
3929 [(set (reg:CC_NZ CC_REGNUM)
3932 (match_operand:GPI 0 "register_operand")
3933 (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
3934 (match_operand:GPI 2 "aarch64_mov_imm_operand"))
3936 (clobber (match_operand:SI 3 "register_operand"))]
3938 [(set (match_dup 3) (match_dup 2))
3939 (set (reg:CC_NZ CC_REGNUM)
3948 ;; -------------------------------------------------------------------
3950 ;; -------------------------------------------------------------------
3952 (define_expand "<optab><mode>3"
3953 [(set (match_operand:GPI 0 "register_operand")
3954 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3955 (match_operand:QI 2 "nonmemory_operand")))]
3958 if (CONST_INT_P (operands[2]))
3960 operands[2] = GEN_INT (INTVAL (operands[2])
3961 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3963 if (operands[2] == const0_rtx)
3965 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3972 (define_expand "ashl<mode>3"
3973 [(set (match_operand:SHORT 0 "register_operand")
3974 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3975 (match_operand:QI 2 "const_int_operand")))]
3978 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3980 if (operands[2] == const0_rtx)
3982 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3988 (define_expand "rotr<mode>3"
3989 [(set (match_operand:GPI 0 "register_operand")
3990 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3991 (match_operand:QI 2 "nonmemory_operand")))]
3994 if (CONST_INT_P (operands[2]))
3996 operands[2] = GEN_INT (INTVAL (operands[2])
3997 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3999 if (operands[2] == const0_rtx)
4001 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4008 (define_expand "rotl<mode>3"
4009 [(set (match_operand:GPI 0 "register_operand")
4010 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4011 (match_operand:QI 2 "nonmemory_operand")))]
4014 /* (SZ - cnt) % SZ == -cnt % SZ */
4015 if (CONST_INT_P (operands[2]))
4017 operands[2] = GEN_INT ((-INTVAL (operands[2]))
4018 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4019 if (operands[2] == const0_rtx)
4021 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4026 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4031 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4032 ;; they truncate the shift/rotate amount by the size of the registers they
4033 ;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
4034 ;; such redundant masking instructions. GCC can do that automatically when
4035 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4036 ;; because some of the SISD shift alternatives don't perform this truncations.
4037 ;; So this pattern exists to catch such cases.
4039 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4040 [(set (match_operand:GPI 0 "register_operand" "=r")
4042 (match_operand:GPI 1 "register_operand" "r")
4043 (match_operator 4 "subreg_lowpart_operator"
4044 [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4045 (match_operand 3 "const_int_operand" "n"))])))]
4046 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4047 "<shift>\t%<w>0, %<w>1, %<w>2"
4048 [(set_attr "type" "shift_reg")]
4051 (define_insn_and_split "*aarch64_reg_<mode>3_neg_mask2"
4052 [(set (match_operand:GPI 0 "register_operand" "=&r")
4054 (match_operand:GPI 1 "register_operand" "r")
4055 (match_operator 4 "subreg_lowpart_operator"
4056 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4057 (match_operand 3 "const_int_operand" "n")))])))]
4058 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4063 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4065 emit_insn (gen_negsi2 (tmp, operands[2]));
4067 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4068 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4069 SUBREG_BYTE (operands[4]));
4070 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4075 (define_insn_and_split "*aarch64_reg_<mode>3_minus_mask"
4076 [(set (match_operand:GPI 0 "register_operand" "=&r")
4078 (match_operand:GPI 1 "register_operand" "r")
4079 (minus:QI (match_operand 2 "const_int_operand" "n")
4080 (match_operator 5 "subreg_lowpart_operator"
4081 [(and:SI (match_operand:SI 3 "register_operand" "r")
4082 (match_operand 4 "const_int_operand" "n"))]))))]
4083 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4084 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4089 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4092 emit_insn (gen_negsi2 (tmp, operands[3]));
4094 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
4095 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
4096 SUBREG_BYTE (operands[5]));
4098 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
4103 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4104 [(set (match_operand:DI 0 "register_operand" "=r")
4106 (match_operand:DI 1 "register_operand" "r")
4107 (match_operator 4 "subreg_lowpart_operator"
4108 [(and:SI (match_operand:SI 2 "register_operand" "r")
4109 (match_operand 3 "aarch64_shift_imm_di" "Usd"))])))]
4110 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1)) == 0)"
4113 xop[0] = operands[0];
4114 xop[1] = operands[1];
4115 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
4116 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
4119 [(set_attr "type" "shift_reg")]
4122 ;; Logical left shift using SISD or Integer instruction
4123 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4124 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4126 (match_operand:GPI 1 "register_operand" "r,r,w,w")
4127 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4130 lsl\t%<w>0, %<w>1, %2
4131 lsl\t%<w>0, %<w>1, %<w>2
4132 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4133 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4134 [(set_attr "simd" "no,no,yes,yes")
4135 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4138 ;; Logical right shift using SISD or Integer instruction
4139 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4140 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4142 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4143 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
4146 lsr\t%<w>0, %<w>1, %2
4147 lsr\t%<w>0, %<w>1, %<w>2
4148 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4151 [(set_attr "simd" "no,no,yes,yes,yes")
4152 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4156 [(set (match_operand:DI 0 "aarch64_simd_register")
4158 (match_operand:DI 1 "aarch64_simd_register")
4159 (match_operand:QI 2 "aarch64_simd_register")))]
4160 "TARGET_SIMD && reload_completed"
4162 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4164 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4166 operands[3] = gen_lowpart (QImode, operands[0]);
4171 [(set (match_operand:SI 0 "aarch64_simd_register")
4173 (match_operand:SI 1 "aarch64_simd_register")
4174 (match_operand:QI 2 "aarch64_simd_register")))]
4175 "TARGET_SIMD && reload_completed"
4177 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4179 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4181 operands[3] = gen_lowpart (QImode, operands[0]);
4185 ;; Arithmetic right shift using SISD or Integer instruction
4186 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4187 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4189 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4190 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4193 asr\t%<w>0, %<w>1, %2
4194 asr\t%<w>0, %<w>1, %<w>2
4195 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4198 [(set_attr "simd" "no,no,yes,yes,yes")
4199 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4203 [(set (match_operand:DI 0 "aarch64_simd_register")
4205 (match_operand:DI 1 "aarch64_simd_register")
4206 (match_operand:QI 2 "aarch64_simd_register")))]
4207 "TARGET_SIMD && reload_completed"
4209 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4211 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4213 operands[3] = gen_lowpart (QImode, operands[0]);
4218 [(set (match_operand:SI 0 "aarch64_simd_register")
4220 (match_operand:SI 1 "aarch64_simd_register")
4221 (match_operand:QI 2 "aarch64_simd_register")))]
4222 "TARGET_SIMD && reload_completed"
4224 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4226 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4228 operands[3] = gen_lowpart (QImode, operands[0]);
4232 (define_insn "*aarch64_sisd_ushl"
4233 [(set (match_operand:DI 0 "register_operand" "=w")
4234 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4235 (match_operand:QI 2 "register_operand" "w")]
4238 "ushl\t%d0, %d1, %d2"
4239 [(set_attr "simd" "yes")
4240 (set_attr "type" "neon_shift_reg")]
4243 (define_insn "*aarch64_ushl_2s"
4244 [(set (match_operand:SI 0 "register_operand" "=w")
4245 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4246 (match_operand:QI 2 "register_operand" "w")]
4249 "ushl\t%0.2s, %1.2s, %2.2s"
4250 [(set_attr "simd" "yes")
4251 (set_attr "type" "neon_shift_reg")]
4254 (define_insn "*aarch64_sisd_sshl"
4255 [(set (match_operand:DI 0 "register_operand" "=w")
4256 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4257 (match_operand:QI 2 "register_operand" "w")]
4260 "sshl\t%d0, %d1, %d2"
4261 [(set_attr "simd" "yes")
4262 (set_attr "type" "neon_shift_reg")]
4265 (define_insn "*aarch64_sshl_2s"
4266 [(set (match_operand:SI 0 "register_operand" "=w")
4267 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4268 (match_operand:QI 2 "register_operand" "w")]
4271 "sshl\t%0.2s, %1.2s, %2.2s"
4272 [(set_attr "simd" "yes")
4273 (set_attr "type" "neon_shift_reg")]
4276 (define_insn "*aarch64_sisd_neg_qi"
4277 [(set (match_operand:QI 0 "register_operand" "=w")
4278 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4282 [(set_attr "simd" "yes")
4283 (set_attr "type" "neon_neg")]
4287 (define_insn "*ror<mode>3_insn"
4288 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4290 (match_operand:GPI 1 "register_operand" "r,r")
4291 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4294 ror\\t%<w>0, %<w>1, %2
4295 ror\\t%<w>0, %<w>1, %<w>2"
4296 [(set_attr "type" "rotate_imm,shift_reg")]
4299 ;; zero_extend version of above
4300 (define_insn "*<optab>si3_insn_uxtw"
4301 [(set (match_operand:DI 0 "register_operand" "=r,r")
4302 (zero_extend:DI (SHIFT:SI
4303 (match_operand:SI 1 "register_operand" "r,r")
4304 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4307 <shift>\\t%w0, %w1, %2
4308 <shift>\\t%w0, %w1, %w2"
4309 [(set_attr "type" "bfx,shift_reg")]
4312 (define_insn "*<optab><mode>3_insn"
4313 [(set (match_operand:SHORT 0 "register_operand" "=r")
4314 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4315 (match_operand 2 "const_int_operand" "n")))]
4316 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4318 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4319 return "<bfshift>\t%w0, %w1, %2, %3";
4321 [(set_attr "type" "bfx")]
4324 (define_insn "*extr<mode>5_insn"
4325 [(set (match_operand:GPI 0 "register_operand" "=r")
4326 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4327 (match_operand 3 "const_int_operand" "n"))
4328 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4329 (match_operand 4 "const_int_operand" "n"))))]
4330 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4331 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4332 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4333 [(set_attr "type" "rotate_imm")]
4336 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4337 ;; so we have to match both orderings.
4338 (define_insn "*extr<mode>5_insn_alt"
4339 [(set (match_operand:GPI 0 "register_operand" "=r")
4340 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4341 (match_operand 4 "const_int_operand" "n"))
4342 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4343 (match_operand 3 "const_int_operand" "n"))))]
4344 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4345 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4346 == GET_MODE_BITSIZE (<MODE>mode))"
4347 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4348 [(set_attr "type" "rotate_imm")]
4351 ;; zero_extend version of the above
4352 (define_insn "*extrsi5_insn_uxtw"
4353 [(set (match_operand:DI 0 "register_operand" "=r")
4355 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4356 (match_operand 3 "const_int_operand" "n"))
4357 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4358 (match_operand 4 "const_int_operand" "n")))))]
4359 "UINTVAL (operands[3]) < 32 &&
4360 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4361 "extr\\t%w0, %w1, %w2, %4"
4362 [(set_attr "type" "rotate_imm")]
4365 (define_insn "*extrsi5_insn_uxtw_alt"
4366 [(set (match_operand:DI 0 "register_operand" "=r")
4368 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4369 (match_operand 4 "const_int_operand" "n"))
4370 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4371 (match_operand 3 "const_int_operand" "n")))))]
4372 "UINTVAL (operands[3]) < 32 &&
4373 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4374 "extr\\t%w0, %w1, %w2, %4"
4375 [(set_attr "type" "rotate_imm")]
4378 (define_insn "*ror<mode>3_insn"
4379 [(set (match_operand:GPI 0 "register_operand" "=r")
4380 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4381 (match_operand 2 "const_int_operand" "n")))]
4382 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4384 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4385 return "ror\\t%<w>0, %<w>1, %3";
4387 [(set_attr "type" "rotate_imm")]
4390 ;; zero_extend version of the above
4391 (define_insn "*rorsi3_insn_uxtw"
4392 [(set (match_operand:DI 0 "register_operand" "=r")
4394 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4395 (match_operand 2 "const_int_operand" "n"))))]
4396 "UINTVAL (operands[2]) < 32"
4398 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4399 return "ror\\t%w0, %w1, %3";
4401 [(set_attr "type" "rotate_imm")]
4404 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4405 [(set (match_operand:GPI 0 "register_operand" "=r")
4407 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4408 (match_operand 2 "const_int_operand" "n"))))]
4409 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4411 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4412 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4414 [(set_attr "type" "bfx")]
4417 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4418 [(set (match_operand:GPI 0 "register_operand" "=r")
4420 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4421 (match_operand 2 "const_int_operand" "n"))))]
4422 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4424 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4425 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4427 [(set_attr "type" "bfx")]
4430 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4431 [(set (match_operand:GPI 0 "register_operand" "=r")
4433 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4434 (match_operand 2 "const_int_operand" "n"))))]
4435 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4437 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4438 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4440 [(set_attr "type" "bfx")]
4443 ;; -------------------------------------------------------------------
4445 ;; -------------------------------------------------------------------
4447 (define_expand "<optab>"
4448 [(set (match_operand:DI 0 "register_operand" "=r")
4449 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4451 "aarch64_simd_shift_imm_offset_di")
4452 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4455 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4456 1, GET_MODE_BITSIZE (DImode) - 1))
4462 (define_insn "*<optab><mode>"
4463 [(set (match_operand:GPI 0 "register_operand" "=r")
4464 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4466 "aarch64_simd_shift_imm_offset_<mode>" "n")
4468 "aarch64_simd_shift_imm_<mode>" "n")))]
4469 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4470 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4471 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4472 [(set_attr "type" "bfx")]
4475 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4476 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4478 [(set (match_operand:DI 0 "register_operand")
4479 (zero_extract:DI (match_operand:DI 1 "register_operand")
4481 "aarch64_simd_shift_imm_offset_di")
4483 "aarch64_simd_shift_imm_di")))]
4484 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4485 GET_MODE_BITSIZE (DImode) - 1)
4486 && (INTVAL (operands[2]) + INTVAL (operands[3]))
4487 == GET_MODE_BITSIZE (SImode)"
4489 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4491 operands[4] = gen_lowpart (SImode, operands[1]);
4495 ;; Bitfield Insert (insv)
4496 (define_expand "insv<mode>"
4497 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4498 (match_operand 1 "const_int_operand")
4499 (match_operand 2 "const_int_operand"))
4500 (match_operand:GPI 3 "general_operand"))]
4503 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4504 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4505 rtx value = operands[3];
4507 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4510 if (CONST_INT_P (value))
4512 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4514 /* Prefer AND/OR for inserting all zeros or all ones. */
4515 if ((UINTVAL (value) & mask) == 0
4516 || (UINTVAL (value) & mask) == mask)
4519 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4520 if (width == 16 && (pos % 16) == 0)
4523 operands[3] = force_reg (<MODE>mode, value);
4526 (define_insn "*insv_reg<mode>"
4527 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4528 (match_operand 1 "const_int_operand" "n")
4529 (match_operand 2 "const_int_operand" "n"))
4530 (match_operand:GPI 3 "register_operand" "r"))]
4531 "!(UINTVAL (operands[1]) == 0
4532 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4533 > GET_MODE_BITSIZE (<MODE>mode)))"
4534 "bfi\\t%<w>0, %<w>3, %2, %1"
4535 [(set_attr "type" "bfm")]
4538 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4539 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4540 (match_operand 1 "const_int_operand" "n")
4541 (match_operand 2 "const_int_operand" "n"))
4542 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4543 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4544 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4545 [(set_attr "type" "bfm")]
4548 (define_insn "*extr_insv_lower_reg<mode>"
4549 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4550 (match_operand 1 "const_int_operand" "n")
4552 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4554 (match_operand 3 "const_int_operand" "n")))]
4555 "!(UINTVAL (operands[1]) == 0
4556 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4557 > GET_MODE_BITSIZE (<MODE>mode)))"
4558 "bfxil\\t%<w>0, %<w>2, %3, %1"
4559 [(set_attr "type" "bfm")]
4562 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4563 [(set (match_operand:GPI 0 "register_operand" "=r")
4564 (ashift:GPI (ANY_EXTEND:GPI
4565 (match_operand:ALLX 1 "register_operand" "r"))
4566 (match_operand 2 "const_int_operand" "n")))]
4567 "UINTVAL (operands[2]) < <GPI:sizen>"
4569 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4570 ? GEN_INT (<ALLX:sizen>)
4571 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4572 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4574 [(set_attr "type" "bfx")]
4577 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4579 (define_insn "*andim_ashift<mode>_bfiz"
4580 [(set (match_operand:GPI 0 "register_operand" "=r")
4581 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4582 (match_operand 2 "const_int_operand" "n"))
4583 (match_operand 3 "const_int_operand" "n")))]
4584 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4585 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4586 [(set_attr "type" "bfx")]
4589 ;; When the bit position and width of the equivalent extraction add up to 32
4590 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4591 ;; zero-extension of the X-reg.
4593 [(set (match_operand:DI 0 "register_operand")
4594 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4595 (match_operand 2 "const_int_operand"))
4596 (match_operand 3 "const_int_operand")))]
4597 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4598 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4599 == GET_MODE_BITSIZE (SImode)"
4601 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4603 operands[4] = gen_lowpart (SImode, operands[1]);
4607 (define_insn "bswap<mode>2"
4608 [(set (match_operand:GPI 0 "register_operand" "=r")
4609 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4611 "rev\\t%<w>0, %<w>1"
4612 [(set_attr "type" "rev")]
4615 (define_insn "bswaphi2"
4616 [(set (match_operand:HI 0 "register_operand" "=r")
4617 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4620 [(set_attr "type" "rev")]
4623 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4624 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4625 ;; each valid permutation.
4627 (define_insn "rev16<mode>2"
4628 [(set (match_operand:GPI 0 "register_operand" "=r")
4629 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4631 (match_operand:GPI 3 "const_int_operand" "n"))
4632 (and:GPI (lshiftrt:GPI (match_dup 1)
4634 (match_operand:GPI 2 "const_int_operand" "n"))))]
4635 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4636 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4637 "rev16\\t%<w>0, %<w>1"
4638 [(set_attr "type" "rev")]
4641 (define_insn "rev16<mode>2_alt"
4642 [(set (match_operand:GPI 0 "register_operand" "=r")
4643 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4645 (match_operand:GPI 2 "const_int_operand" "n"))
4646 (and:GPI (ashift:GPI (match_dup 1)
4648 (match_operand:GPI 3 "const_int_operand" "n"))))]
4649 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4650 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4651 "rev16\\t%<w>0, %<w>1"
4652 [(set_attr "type" "rev")]
4655 ;; zero_extend version of above
4656 (define_insn "*bswapsi2_uxtw"
4657 [(set (match_operand:DI 0 "register_operand" "=r")
4658 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4661 [(set_attr "type" "rev")]
4664 ;; -------------------------------------------------------------------
4665 ;; Floating-point intrinsics
4666 ;; -------------------------------------------------------------------
4668 ;; frint floating-point round to integral standard patterns.
4669 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4671 (define_insn "<frint_pattern><mode>2"
4672 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4673 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4676 "frint<frint_suffix>\\t%<s>0, %<s>1"
4677 [(set_attr "type" "f_rint<stype>")]
4680 ;; frcvt floating-point round to integer and convert standard patterns.
4681 ;; Expands to lbtrunc, lceil, lfloor, lround.
4682 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4683 [(set (match_operand:GPI 0 "register_operand" "=r")
4685 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4688 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4689 [(set_attr "type" "f_cvtf2i")]
4692 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4693 [(set (match_operand:GPI 0 "register_operand" "=r")
4696 (match_operand:GPF 1 "register_operand" "w")
4697 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4699 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4700 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4702 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4704 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4705 output_asm_insn (buf, operands);
4708 [(set_attr "type" "f_cvtf2i")]
4713 (define_insn "fma<mode>4"
4714 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4715 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4716 (match_operand:GPF_F16 2 "register_operand" "w")
4717 (match_operand:GPF_F16 3 "register_operand" "w")))]
4719 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4720 [(set_attr "type" "fmac<stype>")]
4723 (define_insn "fnma<mode>4"
4724 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4726 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4727 (match_operand:GPF_F16 2 "register_operand" "w")
4728 (match_operand:GPF_F16 3 "register_operand" "w")))]
4730 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4731 [(set_attr "type" "fmac<stype>")]
4734 (define_insn "fms<mode>4"
4735 [(set (match_operand:GPF 0 "register_operand" "=w")
4736 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4737 (match_operand:GPF 2 "register_operand" "w")
4738 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4740 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4741 [(set_attr "type" "fmac<s>")]
4744 (define_insn "fnms<mode>4"
4745 [(set (match_operand:GPF 0 "register_operand" "=w")
4746 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4747 (match_operand:GPF 2 "register_operand" "w")
4748 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4750 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4751 [(set_attr "type" "fmac<s>")]
4754 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4755 (define_insn "*fnmadd<mode>4"
4756 [(set (match_operand:GPF 0 "register_operand" "=w")
4757 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4758 (match_operand:GPF 2 "register_operand" "w")
4759 (match_operand:GPF 3 "register_operand" "w"))))]
4760 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4761 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4762 [(set_attr "type" "fmac<s>")]
4765 ;; -------------------------------------------------------------------
4766 ;; Floating-point conversions
4767 ;; -------------------------------------------------------------------
4769 (define_insn "extendsfdf2"
4770 [(set (match_operand:DF 0 "register_operand" "=w")
4771 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4774 [(set_attr "type" "f_cvt")]
4777 (define_insn "extendhfsf2"
4778 [(set (match_operand:SF 0 "register_operand" "=w")
4779 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4782 [(set_attr "type" "f_cvt")]
4785 (define_insn "extendhfdf2"
4786 [(set (match_operand:DF 0 "register_operand" "=w")
4787 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4790 [(set_attr "type" "f_cvt")]
4793 (define_insn "truncdfsf2"
4794 [(set (match_operand:SF 0 "register_operand" "=w")
4795 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4798 [(set_attr "type" "f_cvt")]
4801 (define_insn "truncsfhf2"
4802 [(set (match_operand:HF 0 "register_operand" "=w")
4803 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4806 [(set_attr "type" "f_cvt")]
4809 (define_insn "truncdfhf2"
4810 [(set (match_operand:HF 0 "register_operand" "=w")
4811 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4814 [(set_attr "type" "f_cvt")]
4817 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4818 [(set (match_operand:GPI 0 "register_operand" "=r")
4819 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4821 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4822 [(set_attr "type" "f_cvtf2i")]
4825 (define_insn "<optab><fcvt_target><GPF:mode>2"
4826 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4827 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4830 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4831 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4832 [(set_attr "simd" "yes,no")
4833 (set_attr "fp" "no,yes")
4834 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4837 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4838 [(set (match_operand:GPF 0 "register_operand" "=w")
4839 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4841 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4842 [(set_attr "type" "f_cvti2f")]
4845 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4846 ;; midend will arrange for an SImode conversion to HFmode to first go
4847 ;; through DFmode, then to HFmode. But first it will try converting
4848 ;; to DImode then down, which would match our DImode pattern below and
4849 ;; give very poor code-generation. So, we must provide our own emulation
4850 ;; of the mid-end logic.
4852 (define_insn "aarch64_fp16_<optab><mode>hf2"
4853 [(set (match_operand:HF 0 "register_operand" "=w")
4854 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4856 "<su_optab>cvtf\t%h0, %<w>1"
4857 [(set_attr "type" "f_cvti2f")]
4860 (define_expand "<optab>sihf2"
4861 [(set (match_operand:HF 0 "register_operand")
4862 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4865 if (TARGET_FP_F16INST)
4866 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4869 rtx convert_target = gen_reg_rtx (DFmode);
4870 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4871 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4877 ;; For DImode there is no wide enough floating-point mode that we
4878 ;; can convert through natively (TFmode would work, but requires a library
4879 ;; call). However, we know that any value >= 65504 will be rounded
4880 ;; to infinity on conversion. This is well within the range of SImode, so
4882 ;; Saturate to SImode.
4883 ;; Convert from that to DFmode
4884 ;; Convert from that to HFmode (phew!).
4885 ;; Note that the saturation to SImode requires the SIMD extensions. If
4886 ;; we ever need to provide this pattern where the SIMD extensions are not
4887 ;; available, we would need a different approach.
4889 (define_expand "<optab>dihf2"
4890 [(set (match_operand:HF 0 "register_operand")
4891 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4892 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4894 if (TARGET_FP_F16INST)
4895 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4898 rtx sat_target = gen_reg_rtx (SImode);
4899 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4900 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4907 ;; Convert between fixed-point and floating-point (scalar modes)
4909 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4910 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4911 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4912 (match_operand:SI 2 "immediate_operand" "i, i")]
4916 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4917 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4918 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4919 (set_attr "fp" "yes, *")
4920 (set_attr "simd" "*, yes")]
4923 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4924 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4925 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4926 (match_operand:SI 2 "immediate_operand" "i, i")]
4930 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4931 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4932 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4933 (set_attr "fp" "yes, *")
4934 (set_attr "simd" "*, yes")]
4937 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4938 [(set (match_operand:GPI 0 "register_operand" "=r")
4939 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4940 (match_operand:SI 2 "immediate_operand" "i")]
4943 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4944 [(set_attr "type" "f_cvtf2i")]
4947 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4948 [(set (match_operand:HF 0 "register_operand" "=w")
4949 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4950 (match_operand:SI 2 "immediate_operand" "i")]
4953 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4954 [(set_attr "type" "f_cvti2f")]
4957 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4958 [(set (match_operand:HI 0 "register_operand" "=w")
4959 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4960 (match_operand:SI 2 "immediate_operand" "i")]
4963 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4964 [(set_attr "type" "neon_fp_to_int_s")]
4967 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4968 [(set (match_operand:HF 0 "register_operand" "=w")
4969 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4970 (match_operand:SI 2 "immediate_operand" "i")]
4973 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4974 [(set_attr "type" "neon_int_to_fp_s")]
4977 ;; -------------------------------------------------------------------
4978 ;; Floating-point arithmetic
4979 ;; -------------------------------------------------------------------
4981 (define_insn "add<mode>3"
4982 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4984 (match_operand:GPF_F16 1 "register_operand" "w")
4985 (match_operand:GPF_F16 2 "register_operand" "w")))]
4987 "fadd\\t%<s>0, %<s>1, %<s>2"
4988 [(set_attr "type" "fadd<stype>")]
4991 (define_insn "sub<mode>3"
4992 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4994 (match_operand:GPF_F16 1 "register_operand" "w")
4995 (match_operand:GPF_F16 2 "register_operand" "w")))]
4997 "fsub\\t%<s>0, %<s>1, %<s>2"
4998 [(set_attr "type" "fadd<stype>")]
5001 (define_insn "mul<mode>3"
5002 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5004 (match_operand:GPF_F16 1 "register_operand" "w")
5005 (match_operand:GPF_F16 2 "register_operand" "w")))]
5007 "fmul\\t%<s>0, %<s>1, %<s>2"
5008 [(set_attr "type" "fmul<stype>")]
5011 (define_insn "*fnmul<mode>3"
5012 [(set (match_operand:GPF 0 "register_operand" "=w")
5014 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
5015 (match_operand:GPF 2 "register_operand" "w")))]
5016 "TARGET_FLOAT && !flag_rounding_math"
5017 "fnmul\\t%<s>0, %<s>1, %<s>2"
5018 [(set_attr "type" "fmul<s>")]
5021 (define_insn "*fnmul<mode>3"
5022 [(set (match_operand:GPF 0 "register_operand" "=w")
5024 (match_operand:GPF 1 "register_operand" "w")
5025 (match_operand:GPF 2 "register_operand" "w"))))]
5027 "fnmul\\t%<s>0, %<s>1, %<s>2"
5028 [(set_attr "type" "fmul<s>")]
5031 (define_expand "div<mode>3"
5032 [(set (match_operand:GPF_F16 0 "register_operand")
5033 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
5034 (match_operand:GPF_F16 2 "register_operand")))]
5037 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
5040 operands[1] = force_reg (<MODE>mode, operands[1]);
5043 (define_insn "*div<mode>3"
5044 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5045 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
5046 (match_operand:GPF_F16 2 "register_operand" "w")))]
5048 "fdiv\\t%<s>0, %<s>1, %<s>2"
5049 [(set_attr "type" "fdiv<stype>")]
5052 (define_insn "neg<mode>2"
5053 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5054 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5056 "fneg\\t%<s>0, %<s>1"
5057 [(set_attr "type" "ffarith<stype>")]
5060 (define_expand "sqrt<mode>2"
5061 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5062 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5065 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
5069 (define_insn "*sqrt<mode>2"
5070 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5071 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5073 "fsqrt\\t%<s>0, %<s>1"
5074 [(set_attr "type" "fsqrt<stype>")]
5077 (define_insn "abs<mode>2"
5078 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5079 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5081 "fabs\\t%<s>0, %<s>1"
5082 [(set_attr "type" "ffarith<stype>")]
5085 ;; Given that smax/smin do not specify the result when either input is NaN,
5086 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5089 (define_insn "smax<mode>3"
5090 [(set (match_operand:GPF 0 "register_operand" "=w")
5091 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
5092 (match_operand:GPF 2 "register_operand" "w")))]
5094 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
5095 [(set_attr "type" "f_minmax<s>")]
5098 (define_insn "smin<mode>3"
5099 [(set (match_operand:GPF 0 "register_operand" "=w")
5100 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
5101 (match_operand:GPF 2 "register_operand" "w")))]
5103 "fminnm\\t%<s>0, %<s>1, %<s>2"
5104 [(set_attr "type" "f_minmax<s>")]
5107 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5108 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
5109 ;; which implement the IEEE fmax ()/fmin () functions.
5110 (define_insn "<maxmin_uns><mode>3"
5111 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5112 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
5113 (match_operand:GPF_F16 2 "register_operand" "w")]
5116 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5117 [(set_attr "type" "f_minmax<stype>")]
5120 (define_expand "lrint<GPF:mode><GPI:mode>2"
5121 [(match_operand:GPI 0 "register_operand")
5122 (match_operand:GPF 1 "register_operand")]
5125 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5126 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
5127 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
5132 ;; For copysign (x, y), we want to generate:
5134 ;; LDR d2, #(1 << 63)
5135 ;; BSL v2.8b, [y], [x]
5137 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5138 ;; aarch64_simd_bsldf will select the best suited of these instructions
5139 ;; to generate based on register allocation, and knows how to partially
5140 ;; constant fold based on the values of X and Y, so expand through that.
5142 (define_expand "copysigndf3"
5143 [(match_operand:DF 0 "register_operand")
5144 (match_operand:DF 1 "register_operand")
5145 (match_operand:DF 2 "register_operand")]
5146 "TARGET_FLOAT && TARGET_SIMD"
5148 rtx mask = gen_reg_rtx (DImode);
5149 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5150 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5151 operands[2], operands[1]));
5156 ;; As above, but we must first get to a 64-bit value if we wish to use
5157 ;; aarch64_simd_bslv2sf.
5159 (define_expand "copysignsf3"
5160 [(match_operand:SF 0 "register_operand")
5161 (match_operand:SF 1 "register_operand")
5162 (match_operand:SF 2 "register_operand")]
5163 "TARGET_FLOAT && TARGET_SIMD"
5165 rtx v_bitmask = gen_reg_rtx (V2SImode);
5167 /* Juggle modes to get us in to a vector mode for BSL. */
5168 rtx op1 = lowpart_subreg (DImode, operands[1], SFmode);
5169 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5170 rtx tmp = gen_reg_rtx (V2SFmode);
5171 emit_move_insn (v_bitmask,
5172 aarch64_simd_gen_const_vector_dup (V2SImode,
5173 HOST_WIDE_INT_M1U << 31));
5174 emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5175 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5180 ;; -------------------------------------------------------------------
5182 ;; -------------------------------------------------------------------
5183 ;; Reload Scalar Floating point modes from constant pool.
5184 ;; The AArch64 port doesn't have __int128 constant move support.
5185 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5186 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5187 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5188 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5191 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5192 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5197 ;; Reload Vector modes from constant pool.
5198 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5199 [(set (match_operand:VALL 0 "register_operand" "=w")
5200 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5201 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5204 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5205 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5210 (define_expand "aarch64_reload_mov<mode>"
5211 [(set (match_operand:TX 0 "register_operand" "=w")
5212 (match_operand:TX 1 "register_operand" "w"))
5213 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5217 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5218 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5219 gen_aarch64_movtilow_tilow (op0, op1);
5220 gen_aarch64_movdi_tihigh (operands[2], op1);
5221 gen_aarch64_movtihigh_di (op0, operands[2]);
5226 ;; The following secondary reload helpers patterns are invoked
5227 ;; after or during reload as we don't want these patterns to start
5228 ;; kicking in during the combiner.
5230 (define_insn "aarch64_movdi_<mode>low"
5231 [(set (match_operand:DI 0 "register_operand" "=r")
5232 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5233 (const_int 64) (const_int 0)))]
5234 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5236 [(set_attr "type" "f_mrc")
5237 (set_attr "length" "4")
5240 (define_insn "aarch64_movdi_<mode>high"
5241 [(set (match_operand:DI 0 "register_operand" "=r")
5242 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5243 (const_int 64) (const_int 64)))]
5244 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5245 "fmov\\t%x0, %1.d[1]"
5246 [(set_attr "type" "f_mrc")
5247 (set_attr "length" "4")
5250 (define_insn "aarch64_mov<mode>high_di"
5251 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5252 (const_int 64) (const_int 64))
5253 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5254 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5255 "fmov\\t%0.d[1], %x1"
5256 [(set_attr "type" "f_mcr")
5257 (set_attr "length" "4")
5260 (define_insn "aarch64_mov<mode>low_di"
5261 [(set (match_operand:TX 0 "register_operand" "=w")
5262 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5263 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5265 [(set_attr "type" "f_mcr")
5266 (set_attr "length" "4")
5269 (define_insn "aarch64_movtilow_tilow"
5270 [(set (match_operand:TI 0 "register_operand" "=w")
5272 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5273 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5275 [(set_attr "type" "fmov")
5276 (set_attr "length" "4")
5279 ;; There is a deliberate reason why the parameters of high and lo_sum's
5280 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5281 ;; and lo_sum's to be used with the labels defining the jump tables in
5284 (define_expand "add_losym"
5285 [(set (match_operand 0 "register_operand" "=r")
5286 (lo_sum (match_operand 1 "register_operand" "r")
5287 (match_operand 2 "aarch64_valid_symref" "S")))]
5290 machine_mode mode = GET_MODE (operands[0]);
5292 emit_insn ((mode == DImode
5294 : gen_add_losym_si) (operands[0],
5300 (define_insn "add_losym_<mode>"
5301 [(set (match_operand:P 0 "register_operand" "=r")
5302 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5303 (match_operand 2 "aarch64_valid_symref" "S")))]
5305 "add\\t%<w>0, %<w>1, :lo12:%a2"
5306 [(set_attr "type" "alu_imm")]
5309 (define_insn "ldr_got_small_<mode>"
5310 [(set (match_operand:PTR 0 "register_operand" "=r")
5311 (unspec:PTR [(mem:PTR (lo_sum:PTR
5312 (match_operand:PTR 1 "register_operand" "r")
5313 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5314 UNSPEC_GOTSMALLPIC))]
5316 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5317 [(set_attr "type" "load1")]
5320 (define_insn "ldr_got_small_sidi"
5321 [(set (match_operand:DI 0 "register_operand" "=r")
5323 (unspec:SI [(mem:SI (lo_sum:DI
5324 (match_operand:DI 1 "register_operand" "r")
5325 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5326 UNSPEC_GOTSMALLPIC)))]
5328 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5329 [(set_attr "type" "load1")]
5332 (define_insn "ldr_got_small_28k_<mode>"
5333 [(set (match_operand:PTR 0 "register_operand" "=r")
5334 (unspec:PTR [(mem:PTR (lo_sum:PTR
5335 (match_operand:PTR 1 "register_operand" "r")
5336 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5337 UNSPEC_GOTSMALLPIC28K))]
5339 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5340 [(set_attr "type" "load1")]
5343 (define_insn "ldr_got_small_28k_sidi"
5344 [(set (match_operand:DI 0 "register_operand" "=r")
5346 (unspec:SI [(mem:SI (lo_sum:DI
5347 (match_operand:DI 1 "register_operand" "r")
5348 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5349 UNSPEC_GOTSMALLPIC28K)))]
5351 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5352 [(set_attr "type" "load1")]
5355 (define_insn "ldr_got_tiny"
5356 [(set (match_operand:DI 0 "register_operand" "=r")
5357 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5358 UNSPEC_GOTTINYPIC))]
5361 [(set_attr "type" "load1")]
5364 (define_insn "aarch64_load_tp_hard"
5365 [(set (match_operand:DI 0 "register_operand" "=r")
5366 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5368 "mrs\\t%0, tpidr_el0"
5369 [(set_attr "type" "mrs")]
5372 ;; The TLS ABI specifically requires that the compiler does not schedule
5373 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5374 ;; Therefore we treat the stubs as an atomic sequence.
5375 (define_expand "tlsgd_small_<mode>"
5376 [(parallel [(set (match_operand 0 "register_operand" "")
5377 (call (mem:DI (match_dup 2)) (const_int 1)))
5378 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5379 (clobber (reg:DI LR_REGNUM))])]
5382 operands[2] = aarch64_tls_get_addr ();
5385 (define_insn "*tlsgd_small_<mode>"
5386 [(set (match_operand 0 "register_operand" "")
5387 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5388 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5389 (clobber (reg:DI LR_REGNUM))
5392 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5393 [(set_attr "type" "call")
5394 (set_attr "length" "16")])
5396 (define_insn "tlsie_small_<mode>"
5397 [(set (match_operand:PTR 0 "register_operand" "=r")
5398 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5399 UNSPEC_GOTSMALLTLS))]
5401 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5402 [(set_attr "type" "load1")
5403 (set_attr "length" "8")]
5406 (define_insn "tlsie_small_sidi"
5407 [(set (match_operand:DI 0 "register_operand" "=r")
5409 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5410 UNSPEC_GOTSMALLTLS)))]
5412 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5413 [(set_attr "type" "load1")
5414 (set_attr "length" "8")]
5417 (define_insn "tlsie_tiny_<mode>"
5418 [(set (match_operand:PTR 0 "register_operand" "=&r")
5419 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5420 (match_operand:PTR 2 "register_operand" "r")]
5421 UNSPEC_GOTTINYTLS))]
5423 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5424 [(set_attr "type" "multiple")
5425 (set_attr "length" "8")]
5428 (define_insn "tlsie_tiny_sidi"
5429 [(set (match_operand:DI 0 "register_operand" "=&r")
5431 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5432 (match_operand:DI 2 "register_operand" "r")
5434 UNSPEC_GOTTINYTLS)))]
5436 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5437 [(set_attr "type" "multiple")
5438 (set_attr "length" "8")]
5441 (define_insn "tlsle12_<mode>"
5442 [(set (match_operand:P 0 "register_operand" "=r")
5443 (unspec:P [(match_operand:P 1 "register_operand" "r")
5444 (match_operand 2 "aarch64_tls_le_symref" "S")]
5447 "add\\t%<w>0, %<w>1, #%L2";
5448 [(set_attr "type" "alu_sreg")
5449 (set_attr "length" "4")]
5452 (define_insn "tlsle24_<mode>"
5453 [(set (match_operand:P 0 "register_operand" "=r")
5454 (unspec:P [(match_operand:P 1 "register_operand" "r")
5455 (match_operand 2 "aarch64_tls_le_symref" "S")]
5458 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5459 [(set_attr "type" "multiple")
5460 (set_attr "length" "8")]
5463 (define_insn "tlsle32_<mode>"
5464 [(set (match_operand:P 0 "register_operand" "=r")
5465 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5468 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5469 [(set_attr "type" "multiple")
5470 (set_attr "length" "8")]
5473 (define_insn "tlsle48_<mode>"
5474 [(set (match_operand:P 0 "register_operand" "=r")
5475 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5478 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5479 [(set_attr "type" "multiple")
5480 (set_attr "length" "12")]
5483 (define_insn "tlsdesc_small_<mode>"
5484 [(set (reg:PTR R0_REGNUM)
5485 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5487 (clobber (reg:DI LR_REGNUM))
5488 (clobber (reg:CC CC_REGNUM))
5489 (clobber (match_scratch:DI 1 "=r"))]
5491 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5492 [(set_attr "type" "call")
5493 (set_attr "length" "16")])
5495 (define_insn "stack_tie"
5496 [(set (mem:BLK (scratch))
5497 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5498 (match_operand:DI 1 "register_operand" "rk")]
5502 [(set_attr "length" "0")]
5505 ;; Pointer authentication patterns are always provided. In architecture
5506 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5507 ;; This lets the user write portable software which authenticates pointers
5508 ;; when run on something which implements ARMv8.3-A, and which runs
5509 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5512 ;; Signing/Authenticating R30 using SP as the salt.
5514 (define_insn "<pauth_mnem_prefix>sp"
5515 [(set (reg:DI R30_REGNUM)
5516 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5518 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5521 ;; Signing/Authenticating X17 using X16 as the salt.
5523 (define_insn "<pauth_mnem_prefix>1716"
5524 [(set (reg:DI R17_REGNUM)
5525 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5527 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5530 ;; Stripping the signature in R30.
5532 (define_insn "xpaclri"
5533 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5535 "hint\t7 // xpaclri"
5538 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5539 ;; all of memory. This blocks insns from being moved across this point.
5541 (define_insn "blockage"
5542 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5545 [(set_attr "length" "0")
5546 (set_attr "type" "block")]
5549 (define_insn "probe_stack_range"
5550 [(set (match_operand:DI 0 "register_operand" "=r")
5551 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5552 (match_operand:DI 2 "register_operand" "r")]
5553 UNSPECV_PROBE_STACK_RANGE))]
5556 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5558 [(set_attr "length" "32")]
5561 ;; Named pattern for expanding thread pointer reference.
5562 (define_expand "get_thread_pointerdi"
5563 [(match_operand:DI 0 "register_operand" "=r")]
5566 rtx tmp = aarch64_load_tp (operands[0]);
5567 if (tmp != operands[0])
5568 emit_move_insn (operands[0], tmp);
5572 ;; Named patterns for stack smashing protection.
5573 (define_expand "stack_protect_set"
5574 [(match_operand 0 "memory_operand")
5575 (match_operand 1 "memory_operand")]
5578 machine_mode mode = GET_MODE (operands[0]);
5580 emit_insn ((mode == DImode
5581 ? gen_stack_protect_set_di
5582 : gen_stack_protect_set_si) (operands[0], operands[1]));
5586 (define_insn "stack_protect_set_<mode>"
5587 [(set (match_operand:PTR 0 "memory_operand" "=m")
5588 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5590 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5592 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5593 [(set_attr "length" "12")
5594 (set_attr "type" "multiple")])
5596 (define_expand "stack_protect_test"
5597 [(match_operand 0 "memory_operand")
5598 (match_operand 1 "memory_operand")
5603 machine_mode mode = GET_MODE (operands[0]);
5605 result = gen_reg_rtx(mode);
5607 emit_insn ((mode == DImode
5608 ? gen_stack_protect_test_di
5609 : gen_stack_protect_test_si) (result,
5614 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5615 result, const0_rtx, operands[2]));
5617 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5618 result, const0_rtx, operands[2]));
5622 (define_insn "stack_protect_test_<mode>"
5623 [(set (match_operand:PTR 0 "register_operand" "=r")
5624 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5625 (match_operand:PTR 2 "memory_operand" "m")]
5627 (clobber (match_scratch:PTR 3 "=&r"))]
5629 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5630 [(set_attr "length" "12")
5631 (set_attr "type" "multiple")])
5633 ;; Write Floating-point Control Register.
5634 (define_insn "set_fpcr"
5635 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5638 [(set_attr "type" "mrs")])
5640 ;; Read Floating-point Control Register.
5641 (define_insn "get_fpcr"
5642 [(set (match_operand:SI 0 "register_operand" "=r")
5643 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5646 [(set_attr "type" "mrs")])
5648 ;; Write Floating-point Status Register.
5649 (define_insn "set_fpsr"
5650 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5653 [(set_attr "type" "mrs")])
5655 ;; Read Floating-point Status Register.
5656 (define_insn "get_fpsr"
5657 [(set (match_operand:SI 0 "register_operand" "=r")
5658 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5661 [(set_attr "type" "mrs")])
5664 ;; Define the subtract-one-and-jump insns so loop.c
5665 ;; knows what to generate.
5666 (define_expand "doloop_end"
5667 [(use (match_operand 0 "" "")) ; loop pseudo
5668 (use (match_operand 1 "" ""))] ; label
5669 "optimize > 0 && flag_modulo_sched"
5678 /* Currently SMS relies on the do-loop pattern to recognize loops
5679 where (1) the control part consists of all insns defining and/or
5680 using a certain 'count' register and (2) the loop count can be
5681 adjusted by modifying this register prior to the loop.
5682 ??? The possible introduction of a new block to initialize the
5683 new IV can potentially affect branch optimizations. */
5685 if (GET_MODE (operands[0]) != DImode)
5689 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5691 cmp = XVECEXP (PATTERN (insn), 0, 0);
5692 cc_reg = SET_DEST (cmp);
5693 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5694 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5695 emit_jump_insn (gen_rtx_SET (pc_rtx,
5696 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5702 (include "aarch64-simd.md")
5704 ;; Atomic Operations
5705 (include "atomics.md")
5707 ;; ldp/stp peephole patterns
5708 (include "aarch64-ldpstp.md")