1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
62 (LAST_SAVED_REGNUM 63)
69 (define_c_enum "unspec" [
145 (define_c_enum "unspecv" [
146 UNSPECV_EH_RETURN ; Represent EH_RETURN
147 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
148 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
149 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
150 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
151 UNSPECV_BLOCKAGE ; Represent a blockage
152 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
156 ;; If further include files are added the defintion of MD_INCLUDES
159 (include "constraints.md")
160 (include "predicates.md")
161 (include "iterators.md")
163 ;; -------------------------------------------------------------------
164 ;; Instruction types and attributes
165 ;; -------------------------------------------------------------------
167 ; The "type" attribute is included here from AArch32 backend to be able
168 ; to share pipeline descriptions.
169 (include "../arm/types.md")
171 ;; It is important to set the fp or simd attributes to yes when a pattern
172 ;; alternative uses the FP or SIMD register files, usually signified by use of
173 ;; the 'w' constraint. This will ensure that the alternative will be
174 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
175 ;; architecture extensions. If all the alternatives in a pattern use the
176 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
179 ;; Attribute that specifies whether or not the instruction touches fp
180 ;; registers. When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_FLOAT.
182 (define_attr "fp" "no,yes" (const_string "no"))
184 ;; Attribute that specifies whether or not the instruction touches simd
185 ;; registers. When this is set to yes for an alternative, that alternative
186 ;; will be disabled when !TARGET_SIMD.
187 (define_attr "simd" "no,yes" (const_string "no"))
189 (define_attr "length" ""
192 ;; Attribute that controls whether an alternative is enabled or not.
193 ;; Currently it is only used to disable alternatives which touch fp or simd
194 ;; registers when -mgeneral-regs-only is specified.
195 (define_attr "enabled" "no,yes"
197 (and (eq_attr "fp" "yes")
198 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
199 (and (eq_attr "simd" "yes")
200 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
202 ] (const_string "yes")))
204 ;; Attribute that specifies whether we are dealing with a branch to a
205 ;; label that is far away, i.e. further away than the maximum/minimum
206 ;; representable in a signed 21-bits number.
209 (define_attr "far_branch" "" (const_int 0))
211 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
212 ;; no predicated insns.
213 (define_attr "predicated" "yes,no" (const_string "no"))
215 ;; -------------------------------------------------------------------
216 ;; Pipeline descriptions and scheduling
217 ;; -------------------------------------------------------------------
220 (include "aarch64-tune.md")
223 (include "../arm/cortex-a53.md")
224 (include "../arm/cortex-a57.md")
225 (include "../arm/exynos-m1.md")
226 (include "thunderx.md")
227 (include "../arm/xgene1.md")
228 (include "thunderx2t99.md")
230 ;; -------------------------------------------------------------------
231 ;; Jumps and other miscellaneous insns
232 ;; -------------------------------------------------------------------
234 (define_insn "indirect_jump"
235 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
238 [(set_attr "type" "branch")]
242 [(set (pc) (label_ref (match_operand 0 "" "")))]
245 [(set_attr "type" "branch")]
248 (define_expand "cbranch<mode>4"
249 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
250 [(match_operand:GPI 1 "register_operand" "")
251 (match_operand:GPI 2 "aarch64_plus_operand" "")])
252 (label_ref (match_operand 3 "" ""))
256 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
258 operands[2] = const0_rtx;
262 (define_expand "cbranch<mode>4"
263 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
264 [(match_operand:GPF 1 "register_operand" "")
265 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
266 (label_ref (match_operand 3 "" ""))
270 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
272 operands[2] = const0_rtx;
276 (define_expand "cbranchcc4"
277 [(set (pc) (if_then_else
278 (match_operator 0 "aarch64_comparison_operator"
279 [(match_operand 1 "cc_register" "")
280 (match_operand 2 "const0_operand")])
281 (label_ref (match_operand 3 "" ""))
286 (define_insn "ccmp<mode>"
287 [(set (match_operand:CC 1 "cc_register" "")
289 (match_operator 4 "aarch64_comparison_operator"
290 [(match_operand 0 "cc_register" "")
293 (match_operand:GPI 2 "register_operand" "r,r,r")
294 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
295 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
298 ccmp\\t%<w>2, %<w>3, %k5, %m4
299 ccmp\\t%<w>2, %3, %k5, %m4
300 ccmn\\t%<w>2, #%n3, %k5, %m4"
301 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
304 (define_insn "fccmp<mode>"
305 [(set (match_operand:CCFP 1 "cc_register" "")
307 (match_operator 4 "aarch64_comparison_operator"
308 [(match_operand 0 "cc_register" "")
311 (match_operand:GPF 2 "register_operand" "w")
312 (match_operand:GPF 3 "register_operand" "w"))
313 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
315 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
316 [(set_attr "type" "fccmp<s>")]
319 (define_insn "fccmpe<mode>"
320 [(set (match_operand:CCFPE 1 "cc_register" "")
322 (match_operator 4 "aarch64_comparison_operator"
323 [(match_operand 0 "cc_register" "")
326 (match_operand:GPF 2 "register_operand" "w")
327 (match_operand:GPF 3 "register_operand" "w"))
328 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
330 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
331 [(set_attr "type" "fccmp<s>")]
334 ;; Expansion of signed mod by a power of 2 using CSNEG.
335 ;; For x0 % n where n is a power of 2 produce:
337 ;; and x0, x0, #(n - 1)
338 ;; and x1, x1, #(n - 1)
339 ;; csneg x0, x0, x1, mi
341 (define_expand "mod<mode>3"
342 [(match_operand:GPI 0 "register_operand" "")
343 (match_operand:GPI 1 "register_operand" "")
344 (match_operand:GPI 2 "const_int_operand" "")]
347 HOST_WIDE_INT val = INTVAL (operands[2]);
350 || exact_log2 (val) <= 0
351 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
354 rtx mask = GEN_INT (val - 1);
356 /* In the special case of x0 % 2 we can do the even shorter:
362 rtx masked = gen_reg_rtx (<MODE>mode);
363 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
364 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
365 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
366 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
370 rtx neg_op = gen_reg_rtx (<MODE>mode);
371 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
373 /* Extract the condition register and mode. */
374 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
375 rtx cc_reg = SET_DEST (cmp);
376 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
378 rtx masked_pos = gen_reg_rtx (<MODE>mode);
379 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
381 rtx masked_neg = gen_reg_rtx (<MODE>mode);
382 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
384 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
385 masked_neg, masked_pos));
390 (define_insn "condjump"
391 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
392 [(match_operand 1 "cc_register" "") (const_int 0)])
393 (label_ref (match_operand 2 "" ""))
397 if (get_attr_length (insn) == 8)
398 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
402 [(set_attr "type" "branch")
404 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
405 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
408 (set (attr "far_branch")
409 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
410 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
415 ;; For a 24-bit immediate CST we can optimize the compare for equality
416 ;; and branch sequence from:
418 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
422 ;; sub x0, x1, #(CST & 0xfff000)
423 ;; subs x0, x0, #(CST & 0x000fff)
425 (define_insn_and_split "*compare_condjump<mode>"
426 [(set (pc) (if_then_else (EQL
427 (match_operand:GPI 0 "register_operand" "r")
428 (match_operand:GPI 1 "aarch64_imm24" "n"))
429 (label_ref:P (match_operand 2 "" ""))
431 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
432 && !aarch64_plus_operand (operands[1], <MODE>mode)
433 && !reload_completed"
438 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
439 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
440 rtx tmp = gen_reg_rtx (<MODE>mode);
441 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
442 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
443 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
444 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
445 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
450 (define_expand "casesi"
451 [(match_operand:SI 0 "register_operand" "") ; Index
452 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
453 (match_operand:SI 2 "const_int_operand" "") ; Total range
454 (match_operand:DI 3 "" "") ; Table label
455 (match_operand:DI 4 "" "")] ; Out of range label
458 if (operands[1] != const0_rtx)
460 rtx reg = gen_reg_rtx (SImode);
462 /* Canonical RTL says that if you have:
466 then this should be emitted as:
470 The use of trunc_int_for_mode ensures that the resulting
471 constant can be represented in SImode, this is important
472 for the corner case where operand[1] is INT_MIN. */
474 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
476 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
477 (operands[1], SImode))
478 operands[1] = force_reg (SImode, operands[1]);
479 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
483 if (!aarch64_plus_operand (operands[2], SImode))
484 operands[2] = force_reg (SImode, operands[2]);
485 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
487 operands[0], operands[2], operands[4]));
489 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
490 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
496 (define_insn "casesi_dispatch"
499 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
500 (match_operand:SI 1 "register_operand" "r")]
502 (clobber (reg:CC CC_REGNUM))
503 (clobber (match_scratch:DI 3 "=r"))
504 (clobber (match_scratch:DI 4 "=r"))
505 (use (label_ref (match_operand 2 "" "")))])]
508 return aarch64_output_casesi (operands);
510 [(set_attr "length" "16")
511 (set_attr "type" "branch")]
515 [(unspec[(const_int 0)] UNSPEC_NOP)]
518 [(set_attr "type" "no_insn")]
521 (define_insn "prefetch"
522 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
523 (match_operand:QI 1 "const_int_operand" "")
524 (match_operand:QI 2 "const_int_operand" ""))]
527 const char * pftype[2][4] =
529 {"prfm\\tPLDL1STRM, %0",
530 "prfm\\tPLDL3KEEP, %0",
531 "prfm\\tPLDL2KEEP, %0",
532 "prfm\\tPLDL1KEEP, %0"},
533 {"prfm\\tPSTL1STRM, %0",
534 "prfm\\tPSTL3KEEP, %0",
535 "prfm\\tPSTL2KEEP, %0",
536 "prfm\\tPSTL1KEEP, %0"},
539 int locality = INTVAL (operands[2]);
541 gcc_assert (IN_RANGE (locality, 0, 3));
543 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
544 the address into a DImode MEM so that aarch64_print_operand knows
546 operands[0] = gen_rtx_MEM (DImode, operands[0]);
547 return pftype[INTVAL(operands[1])][locality];
549 [(set_attr "type" "load1")]
553 [(trap_if (const_int 1) (const_int 8))]
556 [(set_attr "type" "trap")])
558 (define_expand "prologue"
559 [(clobber (const_int 0))]
562 aarch64_expand_prologue ();
567 (define_expand "epilogue"
568 [(clobber (const_int 0))]
571 aarch64_expand_epilogue (false);
576 (define_expand "sibcall_epilogue"
577 [(clobber (const_int 0))]
580 aarch64_expand_epilogue (true);
585 (define_insn "*do_return"
589 if (aarch64_return_address_signing_enabled ()
591 && !crtl->calls_eh_return)
596 [(set_attr "type" "branch")]
599 (define_expand "return"
601 "aarch64_use_return_insn_p ()"
605 (define_insn "simple_return"
609 [(set_attr "type" "branch")]
612 (define_insn "*cb<optab><mode>1"
613 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
615 (label_ref (match_operand 1 "" ""))
619 if (get_attr_length (insn) == 8)
620 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
622 return "<cbz>\\t%<w>0, %l1";
624 [(set_attr "type" "branch")
626 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
627 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
630 (set (attr "far_branch")
631 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
632 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
637 (define_insn "*tb<optab><mode>1"
638 [(set (pc) (if_then_else
639 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
642 "aarch64_simd_shift_imm_<mode>" "n"))
644 (label_ref (match_operand 2 "" ""))
646 (clobber (reg:CC CC_REGNUM))]
649 if (get_attr_length (insn) == 8)
651 if (get_attr_far_branch (insn) == 1)
652 return aarch64_gen_far_branch (operands, 2, "Ltb",
653 "<inv_tb>\\t%<w>0, %1, ");
656 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
657 return "tst\t%<w>0, %1\;<bcond>\t%l2";
661 return "<tbz>\t%<w>0, %1, %l2";
663 [(set_attr "type" "branch")
665 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
666 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
669 (set (attr "far_branch")
670 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
671 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
677 (define_insn "*cb<optab><mode>1"
678 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
680 (label_ref (match_operand 1 "" ""))
682 (clobber (reg:CC CC_REGNUM))]
685 if (get_attr_length (insn) == 8)
687 if (get_attr_far_branch (insn) == 1)
688 return aarch64_gen_far_branch (operands, 1, "Ltb",
689 "<inv_tb>\\t%<w>0, <sizem1>, ");
693 uint64_t val = ((uint64_t) 1)
694 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
695 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
696 output_asm_insn (buf, operands);
697 return "<bcond>\t%l1";
701 return "<tbz>\t%<w>0, <sizem1>, %l1";
703 [(set_attr "type" "branch")
705 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
706 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
709 (set (attr "far_branch")
710 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
711 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
716 ;; -------------------------------------------------------------------
717 ;; Subroutine calls and sibcalls
718 ;; -------------------------------------------------------------------
720 (define_expand "call"
721 [(parallel [(call (match_operand 0 "memory_operand" "")
722 (match_operand 1 "general_operand" ""))
723 (use (match_operand 2 "" ""))
724 (clobber (reg:DI LR_REGNUM))])]
728 aarch64_expand_call (NULL_RTX, operands[0], false);
733 (define_insn "*call_insn"
734 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
735 (match_operand 1 "" ""))
736 (clobber (reg:DI LR_REGNUM))]
741 [(set_attr "type" "call, call")]
744 (define_expand "call_value"
745 [(parallel [(set (match_operand 0 "" "")
746 (call (match_operand 1 "memory_operand" "")
747 (match_operand 2 "general_operand" "")))
748 (use (match_operand 3 "" ""))
749 (clobber (reg:DI LR_REGNUM))])]
753 aarch64_expand_call (operands[0], operands[1], false);
758 (define_insn "*call_value_insn"
759 [(set (match_operand 0 "" "")
760 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
761 (match_operand 2 "" "")))
762 (clobber (reg:DI LR_REGNUM))]
767 [(set_attr "type" "call, call")]
770 (define_expand "sibcall"
771 [(parallel [(call (match_operand 0 "memory_operand" "")
772 (match_operand 1 "general_operand" ""))
774 (use (match_operand 2 "" ""))])]
777 aarch64_expand_call (NULL_RTX, operands[0], true);
782 (define_expand "sibcall_value"
783 [(parallel [(set (match_operand 0 "" "")
784 (call (match_operand 1 "memory_operand" "")
785 (match_operand 2 "general_operand" "")))
787 (use (match_operand 3 "" ""))])]
790 aarch64_expand_call (operands[0], operands[1], true);
795 (define_insn "*sibcall_insn"
796 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
797 (match_operand 1 "" ""))
799 "SIBLING_CALL_P (insn)"
803 [(set_attr "type" "branch, branch")]
806 (define_insn "*sibcall_value_insn"
807 [(set (match_operand 0 "" "")
809 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
810 (match_operand 2 "" "")))
812 "SIBLING_CALL_P (insn)"
816 [(set_attr "type" "branch, branch")]
819 ;; Call subroutine returning any type.
821 (define_expand "untyped_call"
822 [(parallel [(call (match_operand 0 "")
825 (match_operand 2 "")])]
830 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
832 for (i = 0; i < XVECLEN (operands[2], 0); i++)
834 rtx set = XVECEXP (operands[2], 0, i);
835 emit_move_insn (SET_DEST (set), SET_SRC (set));
838 /* The optimizer does not know that the call sets the function value
839 registers we stored in the result block. We avoid problems by
840 claiming that all hard registers are used and clobbered at this
842 emit_insn (gen_blockage ());
846 ;; -------------------------------------------------------------------
848 ;; -------------------------------------------------------------------
850 (define_expand "mov<mode>"
851 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
852 (match_operand:SHORT 1 "general_operand" ""))]
855 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
856 operands[1] = force_reg (<MODE>mode, operands[1]);
860 (define_insn "*mov<mode>_aarch64"
861 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
862 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
863 "(register_operand (operands[0], <MODE>mode)
864 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
866 switch (which_alternative)
869 return "mov\t%w0, %w1";
871 return "mov\t%w0, %1";
873 return aarch64_output_scalar_simd_mov_immediate (operands[1],
876 return "ldr<size>\t%w0, %1";
878 return "ldr\t%<size>0, %1";
880 return "str<size>\t%w1, %0";
882 return "str\t%<size>1, %0";
884 return "umov\t%w0, %1.<v>[0]";
886 return "dup\t%0.<Vallxd>, %w1";
888 return "dup\t%<Vetype>0, %1.<v>[0]";
893 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
894 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
895 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
898 (define_expand "mov<mode>"
899 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
900 (match_operand:GPI 1 "general_operand" ""))]
903 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
904 && <MODE>mode == DImode
905 && aarch64_split_dimode_const_store (operands[0], operands[1]))
908 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
909 operands[1] = force_reg (<MODE>mode, operands[1]);
911 /* FIXME: RR we still need to fix up what we are doing with
912 symbol_refs and other types of constants. */
913 if (CONSTANT_P (operands[1])
914 && !CONST_INT_P (operands[1]))
916 aarch64_expand_mov_immediate (operands[0], operands[1]);
922 (define_insn_and_split "*movsi_aarch64"
923 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w,r,*w")
924 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w"))]
925 "(register_operand (operands[0], SImode)
926 || aarch64_reg_or_zero (operands[1], SImode))"
942 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
943 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
946 aarch64_expand_mov_immediate (operands[0], operands[1]);
949 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
950 adr,adr,f_mcr,f_mrc,fmov")
951 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
954 (define_insn_and_split "*movdi_aarch64"
955 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w,r,*w,w")
956 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
957 "(register_operand (operands[0], DImode)
958 || aarch64_reg_or_zero (operands[1], DImode))"
975 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
976 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
979 aarch64_expand_mov_immediate (operands[0], operands[1]);
982 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
983 adr,adr,f_mcr,f_mrc,fmov,neon_move")
984 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
985 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
988 (define_insn "insv_imm<mode>"
989 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
991 (match_operand:GPI 1 "const_int_operand" "n"))
992 (match_operand:GPI 2 "const_int_operand" "n"))]
993 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
994 && UINTVAL (operands[1]) % 16 == 0"
995 "movk\\t%<w>0, %X2, lsl %1"
996 [(set_attr "type" "mov_imm")]
999 (define_expand "movti"
1000 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1001 (match_operand:TI 1 "general_operand" ""))]
1004 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1005 operands[1] = force_reg (TImode, operands[1]);
1009 (define_insn "*movti_aarch64"
1010 [(set (match_operand:TI 0
1011 "nonimmediate_operand" "=r, *w,r ,*w,r,m,m,*w,m")
1013 "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1014 "(register_operand (operands[0], TImode)
1015 || aarch64_reg_or_zero (operands[1], TImode))"
1020 orr\\t%0.16b, %1.16b, %1.16b
1026 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1027 load2,store2,store2,f_loadd,f_stored")
1028 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1029 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1030 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1033 ;; Split a TImode register-register or register-immediate move into
1034 ;; its component DImode pieces, taking care to handle overlapping
1035 ;; source and dest registers.
1037 [(set (match_operand:TI 0 "register_operand" "")
1038 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1039 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1042 aarch64_split_128bit_move (operands[0], operands[1]);
1046 (define_expand "mov<mode>"
1047 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1048 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1053 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1057 if (GET_CODE (operands[0]) == MEM
1058 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1059 && aarch64_float_const_zero_rtx_p (operands[1])))
1060 operands[1] = force_reg (<MODE>mode, operands[1]);
1064 (define_insn "*movhf_aarch64"
1065 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
1066 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
1067 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1068 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1073 mov\\t%0.h[0], %1.h[0]
1079 [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1080 f_loads,f_stores,load1,store1,mov_reg")
1081 (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1084 (define_insn "*movsf_aarch64"
1085 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1086 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1087 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1088 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1100 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1101 f_loads,f_stores,load1,store1,mov_reg")
1102 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1105 (define_insn "*movdf_aarch64"
1106 [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1107 (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1108 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1109 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1121 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1122 f_loadd,f_stored,load1,store1,mov_reg")
1123 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1126 (define_insn "*movtf_aarch64"
1127 [(set (match_operand:TF 0
1128 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1130 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1131 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1132 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1134 orr\\t%0.16b, %1.16b, %1.16b
1145 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1146 f_loadd,f_stored,load2,store2,store2")
1147 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1148 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1152 [(set (match_operand:TF 0 "register_operand" "")
1153 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1154 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1157 aarch64_split_128bit_move (operands[0], operands[1]);
1164 ;; 2 is size of move in bytes
1167 (define_expand "movmemdi"
1168 [(match_operand:BLK 0 "memory_operand")
1169 (match_operand:BLK 1 "memory_operand")
1170 (match_operand:DI 2 "immediate_operand")
1171 (match_operand:DI 3 "immediate_operand")]
1174 if (aarch64_expand_movmem (operands))
1180 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1181 ;; fairly lax checking on the second memory operation.
1182 (define_insn "load_pairsi"
1183 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1184 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1185 (set (match_operand:SI 2 "register_operand" "=r,*w")
1186 (match_operand:SI 3 "memory_operand" "m,m"))]
1187 "rtx_equal_p (XEXP (operands[3], 0),
1188 plus_constant (Pmode,
1189 XEXP (operands[1], 0),
1190 GET_MODE_SIZE (SImode)))"
1194 [(set_attr "type" "load2,neon_load1_2reg")
1195 (set_attr "fp" "*,yes")]
1198 (define_insn "load_pairdi"
1199 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1200 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1201 (set (match_operand:DI 2 "register_operand" "=r,*w")
1202 (match_operand:DI 3 "memory_operand" "m,m"))]
1203 "rtx_equal_p (XEXP (operands[3], 0),
1204 plus_constant (Pmode,
1205 XEXP (operands[1], 0),
1206 GET_MODE_SIZE (DImode)))"
1210 [(set_attr "type" "load2,neon_load1_2reg")
1211 (set_attr "fp" "*,yes")]
1215 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1216 ;; fairly lax checking on the second memory operation.
1217 (define_insn "store_pairsi"
1218 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1219 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1220 (set (match_operand:SI 2 "memory_operand" "=m,m")
1221 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1222 "rtx_equal_p (XEXP (operands[2], 0),
1223 plus_constant (Pmode,
1224 XEXP (operands[0], 0),
1225 GET_MODE_SIZE (SImode)))"
1229 [(set_attr "type" "store2,neon_store1_2reg")
1230 (set_attr "fp" "*,yes")]
1233 (define_insn "store_pairdi"
1234 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1235 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1236 (set (match_operand:DI 2 "memory_operand" "=m,m")
1237 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1238 "rtx_equal_p (XEXP (operands[2], 0),
1239 plus_constant (Pmode,
1240 XEXP (operands[0], 0),
1241 GET_MODE_SIZE (DImode)))"
1245 [(set_attr "type" "store2,neon_store1_2reg")
1246 (set_attr "fp" "*,yes")]
1249 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1250 ;; fairly lax checking on the second memory operation.
1251 (define_insn "load_pairsf"
1252 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1253 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1254 (set (match_operand:SF 2 "register_operand" "=w,*r")
1255 (match_operand:SF 3 "memory_operand" "m,m"))]
1256 "rtx_equal_p (XEXP (operands[3], 0),
1257 plus_constant (Pmode,
1258 XEXP (operands[1], 0),
1259 GET_MODE_SIZE (SFmode)))"
1263 [(set_attr "type" "neon_load1_2reg,load2")
1264 (set_attr "fp" "yes,*")]
1267 (define_insn "load_pairdf"
1268 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1269 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1270 (set (match_operand:DF 2 "register_operand" "=w,*r")
1271 (match_operand:DF 3 "memory_operand" "m,m"))]
1272 "rtx_equal_p (XEXP (operands[3], 0),
1273 plus_constant (Pmode,
1274 XEXP (operands[1], 0),
1275 GET_MODE_SIZE (DFmode)))"
1279 [(set_attr "type" "neon_load1_2reg,load2")
1280 (set_attr "fp" "yes,*")]
1283 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1284 ;; fairly lax checking on the second memory operation.
1285 (define_insn "store_pairsf"
1286 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1287 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1288 (set (match_operand:SF 2 "memory_operand" "=m,m")
1289 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1290 "rtx_equal_p (XEXP (operands[2], 0),
1291 plus_constant (Pmode,
1292 XEXP (operands[0], 0),
1293 GET_MODE_SIZE (SFmode)))"
1297 [(set_attr "type" "neon_store1_2reg,store2")
1298 (set_attr "fp" "yes,*")]
1301 (define_insn "store_pairdf"
1302 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1303 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1304 (set (match_operand:DF 2 "memory_operand" "=m,m")
1305 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1306 "rtx_equal_p (XEXP (operands[2], 0),
1307 plus_constant (Pmode,
1308 XEXP (operands[0], 0),
1309 GET_MODE_SIZE (DFmode)))"
1313 [(set_attr "type" "neon_store1_2reg,store2")
1314 (set_attr "fp" "yes,*")]
1317 ;; Load pair with post-index writeback. This is primarily used in function
1319 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1321 [(set (match_operand:P 0 "register_operand" "=k")
1322 (plus:P (match_operand:P 1 "register_operand" "0")
1323 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1324 (set (match_operand:GPI 2 "register_operand" "=r")
1325 (mem:GPI (match_dup 1)))
1326 (set (match_operand:GPI 3 "register_operand" "=r")
1327 (mem:GPI (plus:P (match_dup 1)
1328 (match_operand:P 5 "const_int_operand" "n"))))])]
1329 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1330 "ldp\\t%<w>2, %<w>3, [%1], %4"
1331 [(set_attr "type" "load2")]
1334 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1336 [(set (match_operand:P 0 "register_operand" "=k")
1337 (plus:P (match_operand:P 1 "register_operand" "0")
1338 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1339 (set (match_operand:GPF 2 "register_operand" "=w")
1340 (mem:GPF (match_dup 1)))
1341 (set (match_operand:GPF 3 "register_operand" "=w")
1342 (mem:GPF (plus:P (match_dup 1)
1343 (match_operand:P 5 "const_int_operand" "n"))))])]
1344 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1345 "ldp\\t%<w>2, %<w>3, [%1], %4"
1346 [(set_attr "type" "neon_load1_2reg")]
1349 ;; Store pair with pre-index writeback. This is primarily used in function
1351 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1353 [(set (match_operand:P 0 "register_operand" "=&k")
1354 (plus:P (match_operand:P 1 "register_operand" "0")
1355 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1356 (set (mem:GPI (plus:P (match_dup 0)
1358 (match_operand:GPI 2 "register_operand" "r"))
1359 (set (mem:GPI (plus:P (match_dup 0)
1360 (match_operand:P 5 "const_int_operand" "n")))
1361 (match_operand:GPI 3 "register_operand" "r"))])]
1362 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1363 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1364 [(set_attr "type" "store2")]
1367 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1369 [(set (match_operand:P 0 "register_operand" "=&k")
1370 (plus:P (match_operand:P 1 "register_operand" "0")
1371 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1372 (set (mem:GPF (plus:P (match_dup 0)
1374 (match_operand:GPF 2 "register_operand" "w"))
1375 (set (mem:GPF (plus:P (match_dup 0)
1376 (match_operand:P 5 "const_int_operand" "n")))
1377 (match_operand:GPF 3 "register_operand" "w"))])]
1378 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1379 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1380 [(set_attr "type" "neon_store1_2reg<q>")]
1383 ;; -------------------------------------------------------------------
1384 ;; Sign/Zero extension
1385 ;; -------------------------------------------------------------------
1387 (define_expand "<optab>sidi2"
1388 [(set (match_operand:DI 0 "register_operand")
1389 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1393 (define_insn "*extendsidi2_aarch64"
1394 [(set (match_operand:DI 0 "register_operand" "=r,r")
1395 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1400 [(set_attr "type" "extend,load1")]
1403 (define_insn "*load_pair_extendsidi2_aarch64"
1404 [(set (match_operand:DI 0 "register_operand" "=r")
1405 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1406 (set (match_operand:DI 2 "register_operand" "=r")
1407 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1408 "rtx_equal_p (XEXP (operands[3], 0),
1409 plus_constant (Pmode,
1410 XEXP (operands[1], 0),
1411 GET_MODE_SIZE (SImode)))"
1412 "ldpsw\\t%0, %2, %1"
1413 [(set_attr "type" "load2")]
1416 (define_insn "*zero_extendsidi2_aarch64"
1417 [(set (match_operand:DI 0 "register_operand" "=r,r")
1418 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1423 [(set_attr "type" "extend,load1")]
1426 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1427 [(set (match_operand:DI 0 "register_operand" "=r")
1428 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1429 (set (match_operand:DI 2 "register_operand" "=r")
1430 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1431 "rtx_equal_p (XEXP (operands[3], 0),
1432 plus_constant (Pmode,
1433 XEXP (operands[1], 0),
1434 GET_MODE_SIZE (SImode)))"
1435 "ldp\\t%w0, %w2, %1"
1436 [(set_attr "type" "load2")]
1439 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1440 [(set (match_operand:GPI 0 "register_operand")
1441 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1445 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1446 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1447 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1450 sxt<SHORT:size>\t%<GPI:w>0, %w1
1451 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1452 [(set_attr "type" "extend,load1")]
1455 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1456 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1457 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1460 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1461 ldr<SHORT:size>\t%w0, %1
1462 ldr\t%<SHORT:size>0, %1"
1463 [(set_attr "type" "logic_imm,load1,load1")]
1466 (define_expand "<optab>qihi2"
1467 [(set (match_operand:HI 0 "register_operand")
1468 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1472 (define_insn "*extendqihi2_aarch64"
1473 [(set (match_operand:HI 0 "register_operand" "=r,r")
1474 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1479 [(set_attr "type" "extend,load1")]
1482 (define_insn "*zero_extendqihi2_aarch64"
1483 [(set (match_operand:HI 0 "register_operand" "=r,r")
1484 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1489 [(set_attr "type" "logic_imm,load1")]
1492 ;; -------------------------------------------------------------------
1493 ;; Simple arithmetic
1494 ;; -------------------------------------------------------------------
1496 (define_expand "add<mode>3"
1498 (match_operand:GPI 0 "register_operand" "")
1499 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1500 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1503 /* If operands[1] is a subreg extract the inner RTX. */
1504 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1506 /* If the constant is too large for a single instruction and isn't frame
1507 based, split off the immediate so it is available for CSE. */
1508 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1509 && can_create_pseudo_p ()
1511 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1512 operands[2] = force_reg (<MODE>mode, operands[2]);
1515 (define_insn "*add<mode>3_aarch64"
1517 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1519 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1520 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1523 add\\t%<w>0, %<w>1, %2
1524 add\\t%<w>0, %<w>1, %<w>2
1525 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1526 sub\\t%<w>0, %<w>1, #%n2
1528 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1529 (set_attr "simd" "*,*,yes,*,*")]
1532 ;; zero_extend version of above
1533 (define_insn "*addsi3_aarch64_uxtw"
1535 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1537 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1538 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1543 sub\\t%w0, %w1, #%n2
1545 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1548 ;; If there's a free register, and we can load the constant with a
1549 ;; single instruction, do so. This has a chance to improve scheduling.
1551 [(match_scratch:GPI 3 "r")
1552 (set (match_operand:GPI 0 "register_operand")
1554 (match_operand:GPI 1 "register_operand")
1555 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1556 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1557 [(set (match_dup 3) (match_dup 2))
1558 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1562 [(match_scratch:SI 3 "r")
1563 (set (match_operand:DI 0 "register_operand")
1566 (match_operand:SI 1 "register_operand")
1567 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1568 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1569 [(set (match_dup 3) (match_dup 2))
1570 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1573 ;; After peephole2 has had a chance to run, split any remaining long
1574 ;; additions into two add immediates.
1576 [(set (match_operand:GPI 0 "register_operand")
1578 (match_operand:GPI 1 "register_operand")
1579 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1580 "epilogue_completed"
1581 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1582 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1584 HOST_WIDE_INT i = INTVAL (operands[2]);
1585 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1586 operands[3] = GEN_INT (i - s);
1587 operands[4] = GEN_INT (s);
1592 [(set (match_operand:DI 0 "register_operand")
1595 (match_operand:SI 1 "register_operand")
1596 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1597 "epilogue_completed"
1598 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1599 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1601 HOST_WIDE_INT i = INTVAL (operands[2]);
1602 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1603 operands[3] = GEN_INT (i - s);
1604 operands[4] = GEN_INT (s);
1605 operands[5] = gen_lowpart (SImode, operands[0]);
1609 (define_expand "addti3"
1610 [(set (match_operand:TI 0 "register_operand" "")
1611 (plus:TI (match_operand:TI 1 "register_operand" "")
1612 (match_operand:TI 2 "register_operand" "")))]
1615 rtx low = gen_reg_rtx (DImode);
1616 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1617 gen_lowpart (DImode, operands[2])));
1619 rtx high = gen_reg_rtx (DImode);
1620 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1621 gen_highpart (DImode, operands[2])));
1623 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1624 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1628 (define_insn "add<mode>3_compare0"
1629 [(set (reg:CC_NZ CC_REGNUM)
1631 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1632 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1634 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1635 (plus:GPI (match_dup 1) (match_dup 2)))]
1638 adds\\t%<w>0, %<w>1, %<w>2
1639 adds\\t%<w>0, %<w>1, %2
1640 subs\\t%<w>0, %<w>1, #%n2"
1641 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1644 ;; zero_extend version of above
1645 (define_insn "*addsi3_compare0_uxtw"
1646 [(set (reg:CC_NZ CC_REGNUM)
1648 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1649 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1651 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1652 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1655 adds\\t%w0, %w1, %w2
1657 subs\\t%w0, %w1, #%n2"
1658 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1661 (define_insn "*add<mode>3_compareC_cconly_imm"
1662 [(set (reg:CC_C CC_REGNUM)
1665 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1666 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1670 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1671 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1672 <MODE>mode, operands[1])"
1676 [(set_attr "type" "alus_imm")]
1679 (define_insn "*add<mode>3_compareC_cconly"
1680 [(set (reg:CC_C CC_REGNUM)
1683 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1684 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1685 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1687 "cmn\\t%<w>0, %<w>1"
1688 [(set_attr "type" "alus_sreg")]
1691 (define_insn "*add<mode>3_compareC_imm"
1692 [(set (reg:CC_C CC_REGNUM)
1695 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1696 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1700 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1701 (set (match_operand:GPI 0 "register_operand" "=r,r")
1702 (plus:GPI (match_dup 1) (match_dup 2)))]
1703 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1704 <MODE>mode, operands[2])"
1706 adds\\t%<w>0, %<w>1, %2
1707 subs\\t%<w>0, %<w>1, #%n2"
1708 [(set_attr "type" "alus_imm")]
1711 (define_insn "add<mode>3_compareC"
1712 [(set (reg:CC_C CC_REGNUM)
1715 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1716 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1718 (plus:GPI (match_dup 1) (match_dup 2)))))
1719 (set (match_operand:GPI 0 "register_operand" "=r")
1720 (plus:GPI (match_dup 1) (match_dup 2)))]
1722 "adds\\t%<w>0, %<w>1, %<w>2"
1723 [(set_attr "type" "alus_sreg")]
1726 (define_insn "*adds_shift_imm_<mode>"
1727 [(set (reg:CC_NZ CC_REGNUM)
1729 (plus:GPI (ASHIFT:GPI
1730 (match_operand:GPI 1 "register_operand" "r")
1731 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1732 (match_operand:GPI 3 "register_operand" "r"))
1734 (set (match_operand:GPI 0 "register_operand" "=r")
1735 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1738 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1739 [(set_attr "type" "alus_shift_imm")]
1742 (define_insn "*subs_shift_imm_<mode>"
1743 [(set (reg:CC_NZ CC_REGNUM)
1745 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1747 (match_operand:GPI 2 "register_operand" "r")
1748 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1750 (set (match_operand:GPI 0 "register_operand" "=r")
1751 (minus:GPI (match_dup 1)
1752 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1754 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1755 [(set_attr "type" "alus_shift_imm")]
1758 (define_insn "*adds_mul_imm_<mode>"
1759 [(set (reg:CC_NZ CC_REGNUM)
1762 (match_operand:GPI 1 "register_operand" "r")
1763 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1764 (match_operand:GPI 3 "register_operand" "r"))
1766 (set (match_operand:GPI 0 "register_operand" "=r")
1767 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1770 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1771 [(set_attr "type" "alus_shift_imm")]
1774 (define_insn "*subs_mul_imm_<mode>"
1775 [(set (reg:CC_NZ CC_REGNUM)
1777 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1779 (match_operand:GPI 2 "register_operand" "r")
1780 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1782 (set (match_operand:GPI 0 "register_operand" "=r")
1783 (minus:GPI (match_dup 1)
1784 (mult:GPI (match_dup 2) (match_dup 3))))]
1786 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1787 [(set_attr "type" "alus_shift_imm")]
1790 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1791 [(set (reg:CC_NZ CC_REGNUM)
1794 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1795 (match_operand:GPI 2 "register_operand" "r"))
1797 (set (match_operand:GPI 0 "register_operand" "=r")
1798 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1800 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1801 [(set_attr "type" "alus_ext")]
1804 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1805 [(set (reg:CC_NZ CC_REGNUM)
1807 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1809 (match_operand:ALLX 2 "register_operand" "r")))
1811 (set (match_operand:GPI 0 "register_operand" "=r")
1812 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1814 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1815 [(set_attr "type" "alus_ext")]
1818 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1819 [(set (reg:CC_NZ CC_REGNUM)
1821 (plus:GPI (ashift:GPI
1823 (match_operand:ALLX 1 "register_operand" "r"))
1824 (match_operand 2 "aarch64_imm3" "Ui3"))
1825 (match_operand:GPI 3 "register_operand" "r"))
1827 (set (match_operand:GPI 0 "register_operand" "=rk")
1828 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1832 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1833 [(set_attr "type" "alus_ext")]
1836 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1837 [(set (reg:CC_NZ CC_REGNUM)
1839 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1842 (match_operand:ALLX 2 "register_operand" "r"))
1843 (match_operand 3 "aarch64_imm3" "Ui3")))
1845 (set (match_operand:GPI 0 "register_operand" "=rk")
1846 (minus:GPI (match_dup 1)
1847 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1850 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1851 [(set_attr "type" "alus_ext")]
1854 (define_insn "*adds_<optab><mode>_multp2"
1855 [(set (reg:CC_NZ CC_REGNUM)
1857 (plus:GPI (ANY_EXTRACT:GPI
1858 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1859 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1860 (match_operand 3 "const_int_operand" "n")
1862 (match_operand:GPI 4 "register_operand" "r"))
1864 (set (match_operand:GPI 0 "register_operand" "=r")
1865 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1869 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1870 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1871 [(set_attr "type" "alus_ext")]
1874 (define_insn "*subs_<optab><mode>_multp2"
1875 [(set (reg:CC_NZ CC_REGNUM)
1877 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1879 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1880 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1881 (match_operand 3 "const_int_operand" "n")
1884 (set (match_operand:GPI 0 "register_operand" "=r")
1885 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1886 (mult:GPI (match_dup 1) (match_dup 2))
1889 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1890 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1891 [(set_attr "type" "alus_ext")]
1894 (define_insn "*add<mode>3nr_compare0"
1895 [(set (reg:CC_NZ CC_REGNUM)
1897 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1898 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1905 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1908 (define_insn "*compare_neg<mode>"
1909 [(set (reg:CC_Z CC_REGNUM)
1911 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1912 (match_operand:GPI 1 "register_operand" "r")))]
1914 "cmn\\t%<w>1, %<w>0"
1915 [(set_attr "type" "alus_sreg")]
1918 (define_insn "*add_<shift>_<mode>"
1919 [(set (match_operand:GPI 0 "register_operand" "=r")
1920 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1921 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1922 (match_operand:GPI 3 "register_operand" "r")))]
1924 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1925 [(set_attr "type" "alu_shift_imm")]
1928 ;; zero_extend version of above
1929 (define_insn "*add_<shift>_si_uxtw"
1930 [(set (match_operand:DI 0 "register_operand" "=r")
1932 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1933 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1934 (match_operand:SI 3 "register_operand" "r"))))]
1936 "add\\t%w0, %w3, %w1, <shift> %2"
1937 [(set_attr "type" "alu_shift_imm")]
1940 (define_insn "*add_mul_imm_<mode>"
1941 [(set (match_operand:GPI 0 "register_operand" "=r")
1942 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1943 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1944 (match_operand:GPI 3 "register_operand" "r")))]
1946 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1947 [(set_attr "type" "alu_shift_imm")]
1950 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1951 [(set (match_operand:GPI 0 "register_operand" "=rk")
1952 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1953 (match_operand:GPI 2 "register_operand" "r")))]
1955 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1956 [(set_attr "type" "alu_ext")]
1959 ;; zero_extend version of above
1960 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
1961 [(set (match_operand:DI 0 "register_operand" "=rk")
1963 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
1964 (match_operand:GPI 2 "register_operand" "r"))))]
1966 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
1967 [(set_attr "type" "alu_ext")]
1970 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1971 [(set (match_operand:GPI 0 "register_operand" "=rk")
1972 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1973 (match_operand:ALLX 1 "register_operand" "r"))
1974 (match_operand 2 "aarch64_imm3" "Ui3"))
1975 (match_operand:GPI 3 "register_operand" "r")))]
1977 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1978 [(set_attr "type" "alu_ext")]
1981 ;; zero_extend version of above
1982 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
1983 [(set (match_operand:DI 0 "register_operand" "=rk")
1985 (plus:SI (ashift:SI (ANY_EXTEND:SI
1986 (match_operand:SHORT 1 "register_operand" "r"))
1987 (match_operand 2 "aarch64_imm3" "Ui3"))
1988 (match_operand:SI 3 "register_operand" "r"))))]
1990 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
1991 [(set_attr "type" "alu_ext")]
1994 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1995 [(set (match_operand:GPI 0 "register_operand" "=rk")
1996 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1997 (match_operand:ALLX 1 "register_operand" "r"))
1998 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1999 (match_operand:GPI 3 "register_operand" "r")))]
2001 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2002 [(set_attr "type" "alu_ext")]
2005 ;; zero_extend version of above
2006 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2007 [(set (match_operand:DI 0 "register_operand" "=rk")
2008 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2009 (match_operand:SHORT 1 "register_operand" "r"))
2010 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2011 (match_operand:SI 3 "register_operand" "r"))))]
2013 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2014 [(set_attr "type" "alu_ext")]
2017 (define_insn "*add_<optab><mode>_multp2"
2018 [(set (match_operand:GPI 0 "register_operand" "=rk")
2019 (plus:GPI (ANY_EXTRACT:GPI
2020 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2021 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2022 (match_operand 3 "const_int_operand" "n")
2024 (match_operand:GPI 4 "register_operand" "r")))]
2025 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2026 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2027 [(set_attr "type" "alu_ext")]
2030 ;; zero_extend version of above
2031 (define_insn "*add_<optab>si_multp2_uxtw"
2032 [(set (match_operand:DI 0 "register_operand" "=rk")
2034 (plus:SI (ANY_EXTRACT:SI
2035 (mult:SI (match_operand:SI 1 "register_operand" "r")
2036 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2037 (match_operand 3 "const_int_operand" "n")
2039 (match_operand:SI 4 "register_operand" "r"))))]
2040 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2041 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2042 [(set_attr "type" "alu_ext")]
2045 (define_expand "add<mode>3_carryin"
2046 [(set (match_operand:GPI 0 "register_operand")
2049 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2050 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2051 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2056 ;; Note that add with carry with two zero inputs is matched by cset,
2057 ;; and that add with carry with one zero input is matched by cinc.
2059 (define_insn "*add<mode>3_carryin"
2060 [(set (match_operand:GPI 0 "register_operand" "=r")
2063 (match_operand:GPI 3 "aarch64_carry_operation" "")
2064 (match_operand:GPI 1 "register_operand" "r"))
2065 (match_operand:GPI 2 "register_operand" "r")))]
2067 "adc\\t%<w>0, %<w>1, %<w>2"
2068 [(set_attr "type" "adc_reg")]
2071 ;; zero_extend version of above
2072 (define_insn "*addsi3_carryin_uxtw"
2073 [(set (match_operand:DI 0 "register_operand" "=r")
2077 (match_operand:SI 3 "aarch64_carry_operation" "")
2078 (match_operand:SI 1 "register_operand" "r"))
2079 (match_operand:SI 2 "register_operand" "r"))))]
2081 "adc\\t%w0, %w1, %w2"
2082 [(set_attr "type" "adc_reg")]
2085 (define_insn "*add_uxt<mode>_shift2"
2086 [(set (match_operand:GPI 0 "register_operand" "=rk")
2088 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2089 (match_operand 2 "aarch64_imm3" "Ui3"))
2090 (match_operand 3 "const_int_operand" "n"))
2091 (match_operand:GPI 4 "register_operand" "r")))]
2092 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2094 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2095 INTVAL (operands[3])));
2096 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2097 [(set_attr "type" "alu_ext")]
2100 ;; zero_extend version of above
2101 (define_insn "*add_uxtsi_shift2_uxtw"
2102 [(set (match_operand:DI 0 "register_operand" "=rk")
2105 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2106 (match_operand 2 "aarch64_imm3" "Ui3"))
2107 (match_operand 3 "const_int_operand" "n"))
2108 (match_operand:SI 4 "register_operand" "r"))))]
2109 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2111 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2112 INTVAL (operands[3])));
2113 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2114 [(set_attr "type" "alu_ext")]
2117 (define_insn "*add_uxt<mode>_multp2"
2118 [(set (match_operand:GPI 0 "register_operand" "=rk")
2120 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2121 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2122 (match_operand 3 "const_int_operand" "n"))
2123 (match_operand:GPI 4 "register_operand" "r")))]
2124 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2126 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2127 INTVAL (operands[3])));
2128 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2129 [(set_attr "type" "alu_ext")]
2132 ;; zero_extend version of above
2133 (define_insn "*add_uxtsi_multp2_uxtw"
2134 [(set (match_operand:DI 0 "register_operand" "=rk")
2137 (mult:SI (match_operand:SI 1 "register_operand" "r")
2138 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2139 (match_operand 3 "const_int_operand" "n"))
2140 (match_operand:SI 4 "register_operand" "r"))))]
2141 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2143 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2144 INTVAL (operands[3])));
2145 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2146 [(set_attr "type" "alu_ext")]
2149 (define_insn "subsi3"
2150 [(set (match_operand:SI 0 "register_operand" "=rk")
2151 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2152 (match_operand:SI 2 "register_operand" "r")))]
2154 "sub\\t%w0, %w1, %w2"
2155 [(set_attr "type" "alu_sreg")]
2158 ;; zero_extend version of above
2159 (define_insn "*subsi3_uxtw"
2160 [(set (match_operand:DI 0 "register_operand" "=rk")
2162 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2163 (match_operand:SI 2 "register_operand" "r"))))]
2165 "sub\\t%w0, %w1, %w2"
2166 [(set_attr "type" "alu_sreg")]
2169 (define_insn "subdi3"
2170 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2171 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2172 (match_operand:DI 2 "register_operand" "r,w")))]
2176 sub\\t%d0, %d1, %d2"
2177 [(set_attr "type" "alu_sreg, neon_sub")
2178 (set_attr "simd" "*,yes")]
2181 (define_expand "subti3"
2182 [(set (match_operand:TI 0 "register_operand" "")
2183 (minus:TI (match_operand:TI 1 "register_operand" "")
2184 (match_operand:TI 2 "register_operand" "")))]
2187 rtx low = gen_reg_rtx (DImode);
2188 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2189 gen_lowpart (DImode, operands[2])));
2191 rtx high = gen_reg_rtx (DImode);
2192 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2193 gen_highpart (DImode, operands[2])));
2195 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2196 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2200 (define_insn "*sub<mode>3_compare0"
2201 [(set (reg:CC_NZ CC_REGNUM)
2202 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2203 (match_operand:GPI 2 "register_operand" "r"))
2205 (set (match_operand:GPI 0 "register_operand" "=r")
2206 (minus:GPI (match_dup 1) (match_dup 2)))]
2208 "subs\\t%<w>0, %<w>1, %<w>2"
2209 [(set_attr "type" "alus_sreg")]
2212 ;; zero_extend version of above
2213 (define_insn "*subsi3_compare0_uxtw"
2214 [(set (reg:CC_NZ CC_REGNUM)
2215 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2216 (match_operand:SI 2 "register_operand" "r"))
2218 (set (match_operand:DI 0 "register_operand" "=r")
2219 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2221 "subs\\t%w0, %w1, %w2"
2222 [(set_attr "type" "alus_sreg")]
2225 (define_insn "sub<mode>3_compare1"
2226 [(set (reg:CC CC_REGNUM)
2228 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2229 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2230 (set (match_operand:GPI 0 "register_operand" "=r")
2231 (minus:GPI (match_dup 1) (match_dup 2)))]
2233 "subs\\t%<w>0, %<w>1, %<w>2"
2234 [(set_attr "type" "alus_sreg")]
2237 (define_insn "sub<mode>3_compare1_imm"
2238 [(set (reg:CC CC_REGNUM)
2240 (match_operand:GPI 1 "register_operand" "r")
2241 (match_operand:GPI 3 "const_int_operand" "n")))
2242 (set (match_operand:GPI 0 "register_operand" "=r")
2243 (plus:GPI (match_dup 1)
2244 (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2245 "INTVAL (operands[3]) == -INTVAL (operands[2])"
2246 "subs\\t%<w>0, %<w>1, #%n2"
2247 [(set_attr "type" "alus_sreg")]
2251 [(set (match_operand:GPI 0 "register_operand")
2252 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2253 (match_operand:GPI 2 "aarch64_reg_or_zero")))
2254 (set (reg:CC CC_REGNUM)
2258 "!reg_overlap_mentioned_p (operands[0], operands[1])
2259 && !reg_overlap_mentioned_p (operands[0], operands[2])"
2262 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2269 [(set (match_operand:GPI 0 "register_operand")
2270 (plus:GPI (match_operand:GPI 1 "register_operand")
2271 (match_operand:GPI 2 "aarch64_sub_immediate")))
2272 (set (reg:CC CC_REGNUM)
2275 (match_operand:GPI 3 "const_int_operand")))]
2276 "!reg_overlap_mentioned_p (operands[0], operands[1])
2277 && INTVAL (operands[3]) == -INTVAL (operands[2])"
2280 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2281 operands[2], operands[3]));
2286 (define_insn "*sub_<shift>_<mode>"
2287 [(set (match_operand:GPI 0 "register_operand" "=r")
2288 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2290 (match_operand:GPI 1 "register_operand" "r")
2291 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2293 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2294 [(set_attr "type" "alu_shift_imm")]
2297 ;; zero_extend version of above
2298 (define_insn "*sub_<shift>_si_uxtw"
2299 [(set (match_operand:DI 0 "register_operand" "=r")
2301 (minus:SI (match_operand:SI 3 "register_operand" "r")
2303 (match_operand:SI 1 "register_operand" "r")
2304 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2306 "sub\\t%w0, %w3, %w1, <shift> %2"
2307 [(set_attr "type" "alu_shift_imm")]
2310 (define_insn "*sub_mul_imm_<mode>"
2311 [(set (match_operand:GPI 0 "register_operand" "=r")
2312 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2314 (match_operand:GPI 1 "register_operand" "r")
2315 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2317 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2318 [(set_attr "type" "alu_shift_imm")]
2321 ;; zero_extend version of above
2322 (define_insn "*sub_mul_imm_si_uxtw"
2323 [(set (match_operand:DI 0 "register_operand" "=r")
2325 (minus:SI (match_operand:SI 3 "register_operand" "r")
2327 (match_operand:SI 1 "register_operand" "r")
2328 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2330 "sub\\t%w0, %w3, %w1, lsl %p2"
2331 [(set_attr "type" "alu_shift_imm")]
2334 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2335 [(set (match_operand:GPI 0 "register_operand" "=rk")
2336 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2338 (match_operand:ALLX 2 "register_operand" "r"))))]
2340 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2341 [(set_attr "type" "alu_ext")]
2344 ;; zero_extend version of above
2345 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2346 [(set (match_operand:DI 0 "register_operand" "=rk")
2348 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2350 (match_operand:SHORT 2 "register_operand" "r")))))]
2352 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2353 [(set_attr "type" "alu_ext")]
2356 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2357 [(set (match_operand:GPI 0 "register_operand" "=rk")
2358 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2359 (ashift:GPI (ANY_EXTEND:GPI
2360 (match_operand:ALLX 2 "register_operand" "r"))
2361 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2363 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2364 [(set_attr "type" "alu_ext")]
2367 ;; zero_extend version of above
2368 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2369 [(set (match_operand:DI 0 "register_operand" "=rk")
2371 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2372 (ashift:SI (ANY_EXTEND:SI
2373 (match_operand:SHORT 2 "register_operand" "r"))
2374 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2376 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2377 [(set_attr "type" "alu_ext")]
2380 (define_insn "*sub_<optab><mode>_multp2"
2381 [(set (match_operand:GPI 0 "register_operand" "=rk")
2382 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2384 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2385 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2386 (match_operand 3 "const_int_operand" "n")
2388 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2389 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2390 [(set_attr "type" "alu_ext")]
2393 ;; zero_extend version of above
2394 (define_insn "*sub_<optab>si_multp2_uxtw"
2395 [(set (match_operand:DI 0 "register_operand" "=rk")
2397 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2399 (mult:SI (match_operand:SI 1 "register_operand" "r")
2400 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2401 (match_operand 3 "const_int_operand" "n")
2403 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2404 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2405 [(set_attr "type" "alu_ext")]
2408 ;; The hardware description is op1 + ~op2 + C.
2409 ;; = op1 + (-op2 + 1) + (1 - !C)
2410 ;; = op1 - op2 - 1 + 1 - !C
2411 ;; = op1 - op2 - !C.
2412 ;; We describe the latter.
2414 (define_insn "*sub<mode>3_carryin0"
2415 [(set (match_operand:GPI 0 "register_operand" "=r")
2417 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2418 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2420 "sbc\\t%<w>0, %<w>1, <w>zr"
2421 [(set_attr "type" "adc_reg")]
2424 ;; zero_extend version of the above
2425 (define_insn "*subsi3_carryin_uxtw"
2426 [(set (match_operand:DI 0 "register_operand" "=r")
2429 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2430 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2432 "sbc\\t%w0, %w1, wzr"
2433 [(set_attr "type" "adc_reg")]
2436 (define_expand "sub<mode>3_carryin"
2437 [(set (match_operand:GPI 0 "register_operand")
2440 (match_operand:GPI 1 "aarch64_reg_or_zero")
2441 (match_operand:GPI 2 "register_operand"))
2442 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2447 (define_insn "*sub<mode>3_carryin"
2448 [(set (match_operand:GPI 0 "register_operand" "=r")
2451 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2452 (match_operand:GPI 2 "register_operand" "r"))
2453 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2456 "sbc\\t%<w>0, %<w>1, %<w>2"
2457 [(set_attr "type" "adc_reg")]
2460 ;; zero_extend version of the above
2461 (define_insn "*subsi3_carryin_uxtw"
2462 [(set (match_operand:DI 0 "register_operand" "=r")
2466 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2467 (match_operand:SI 2 "register_operand" "r"))
2468 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2471 "sbc\\t%w0, %w1, %w2"
2472 [(set_attr "type" "adc_reg")]
2475 (define_insn "*sub<mode>3_carryin_alt"
2476 [(set (match_operand:GPI 0 "register_operand" "=r")
2479 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2480 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2481 (match_operand:GPI 2 "register_operand" "r")))]
2483 "sbc\\t%<w>0, %<w>1, %<w>2"
2484 [(set_attr "type" "adc_reg")]
2487 ;; zero_extend version of the above
2488 (define_insn "*subsi3_carryin_alt_uxtw"
2489 [(set (match_operand:DI 0 "register_operand" "=r")
2493 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2494 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2495 (match_operand:SI 2 "register_operand" "r"))))]
2497 "sbc\\t%w0, %w1, %w2"
2498 [(set_attr "type" "adc_reg")]
2501 (define_insn "*sub_uxt<mode>_shift2"
2502 [(set (match_operand:GPI 0 "register_operand" "=rk")
2503 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2505 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2506 (match_operand 2 "aarch64_imm3" "Ui3"))
2507 (match_operand 3 "const_int_operand" "n"))))]
2508 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2510 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2511 INTVAL (operands[3])));
2512 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2513 [(set_attr "type" "alu_ext")]
2516 ;; zero_extend version of above
2517 (define_insn "*sub_uxtsi_shift2_uxtw"
2518 [(set (match_operand:DI 0 "register_operand" "=rk")
2520 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2522 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2523 (match_operand 2 "aarch64_imm3" "Ui3"))
2524 (match_operand 3 "const_int_operand" "n")))))]
2525 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2527 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2528 INTVAL (operands[3])));
2529 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2530 [(set_attr "type" "alu_ext")]
2533 (define_insn "*sub_uxt<mode>_multp2"
2534 [(set (match_operand:GPI 0 "register_operand" "=rk")
2535 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2537 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2538 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2539 (match_operand 3 "const_int_operand" "n"))))]
2540 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2542 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2543 INTVAL (operands[3])));
2544 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2545 [(set_attr "type" "alu_ext")]
2548 ;; zero_extend version of above
2549 (define_insn "*sub_uxtsi_multp2_uxtw"
2550 [(set (match_operand:DI 0 "register_operand" "=rk")
2552 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2554 (mult:SI (match_operand:SI 1 "register_operand" "r")
2555 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2556 (match_operand 3 "const_int_operand" "n")))))]
2557 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2559 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2560 INTVAL (operands[3])));
2561 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2562 [(set_attr "type" "alu_ext")]
2565 (define_expand "abs<mode>2"
2566 [(match_operand:GPI 0 "register_operand" "")
2567 (match_operand:GPI 1 "register_operand" "")]
2570 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2571 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2572 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2577 (define_insn "neg<mode>2"
2578 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2579 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2583 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2584 [(set_attr "type" "alu_sreg, neon_neg<q>")
2585 (set_attr "simd" "*,yes")]
2588 ;; zero_extend version of above
2589 (define_insn "*negsi2_uxtw"
2590 [(set (match_operand:DI 0 "register_operand" "=r")
2591 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2594 [(set_attr "type" "alu_sreg")]
2597 (define_insn "*ngc<mode>"
2598 [(set (match_operand:GPI 0 "register_operand" "=r")
2600 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2601 (match_operand:GPI 1 "register_operand" "r")))]
2603 "ngc\\t%<w>0, %<w>1"
2604 [(set_attr "type" "adc_reg")]
2607 (define_insn "*ngcsi_uxtw"
2608 [(set (match_operand:DI 0 "register_operand" "=r")
2611 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2612 (match_operand:SI 1 "register_operand" "r"))))]
2615 [(set_attr "type" "adc_reg")]
2618 (define_insn "neg<mode>2_compare0"
2619 [(set (reg:CC_NZ CC_REGNUM)
2620 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2622 (set (match_operand:GPI 0 "register_operand" "=r")
2623 (neg:GPI (match_dup 1)))]
2625 "negs\\t%<w>0, %<w>1"
2626 [(set_attr "type" "alus_sreg")]
2629 ;; zero_extend version of above
2630 (define_insn "*negsi2_compare0_uxtw"
2631 [(set (reg:CC_NZ CC_REGNUM)
2632 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2634 (set (match_operand:DI 0 "register_operand" "=r")
2635 (zero_extend:DI (neg:SI (match_dup 1))))]
2638 [(set_attr "type" "alus_sreg")]
2641 (define_insn "*neg_<shift><mode>3_compare0"
2642 [(set (reg:CC_NZ CC_REGNUM)
2644 (neg:GPI (ASHIFT:GPI
2645 (match_operand:GPI 1 "register_operand" "r")
2646 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2648 (set (match_operand:GPI 0 "register_operand" "=r")
2649 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2651 "negs\\t%<w>0, %<w>1, <shift> %2"
2652 [(set_attr "type" "alus_shift_imm")]
2655 (define_insn "*neg_<shift>_<mode>2"
2656 [(set (match_operand:GPI 0 "register_operand" "=r")
2657 (neg:GPI (ASHIFT:GPI
2658 (match_operand:GPI 1 "register_operand" "r")
2659 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2661 "neg\\t%<w>0, %<w>1, <shift> %2"
2662 [(set_attr "type" "alu_shift_imm")]
2665 ;; zero_extend version of above
2666 (define_insn "*neg_<shift>_si2_uxtw"
2667 [(set (match_operand:DI 0 "register_operand" "=r")
2670 (match_operand:SI 1 "register_operand" "r")
2671 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2673 "neg\\t%w0, %w1, <shift> %2"
2674 [(set_attr "type" "alu_shift_imm")]
2677 (define_insn "*neg_mul_imm_<mode>2"
2678 [(set (match_operand:GPI 0 "register_operand" "=r")
2680 (match_operand:GPI 1 "register_operand" "r")
2681 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2683 "neg\\t%<w>0, %<w>1, lsl %p2"
2684 [(set_attr "type" "alu_shift_imm")]
2687 ;; zero_extend version of above
2688 (define_insn "*neg_mul_imm_si2_uxtw"
2689 [(set (match_operand:DI 0 "register_operand" "=r")
2692 (match_operand:SI 1 "register_operand" "r")
2693 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2695 "neg\\t%w0, %w1, lsl %p2"
2696 [(set_attr "type" "alu_shift_imm")]
2699 (define_insn "mul<mode>3"
2700 [(set (match_operand:GPI 0 "register_operand" "=r")
2701 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2702 (match_operand:GPI 2 "register_operand" "r")))]
2704 "mul\\t%<w>0, %<w>1, %<w>2"
2705 [(set_attr "type" "mul")]
2708 ;; zero_extend version of above
2709 (define_insn "*mulsi3_uxtw"
2710 [(set (match_operand:DI 0 "register_operand" "=r")
2712 (mult:SI (match_operand:SI 1 "register_operand" "r")
2713 (match_operand:SI 2 "register_operand" "r"))))]
2715 "mul\\t%w0, %w1, %w2"
2716 [(set_attr "type" "mul")]
2719 (define_insn "madd<mode>"
2720 [(set (match_operand:GPI 0 "register_operand" "=r")
2721 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2722 (match_operand:GPI 2 "register_operand" "r"))
2723 (match_operand:GPI 3 "register_operand" "r")))]
2725 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2726 [(set_attr "type" "mla")]
2729 ;; zero_extend version of above
2730 (define_insn "*maddsi_uxtw"
2731 [(set (match_operand:DI 0 "register_operand" "=r")
2733 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2734 (match_operand:SI 2 "register_operand" "r"))
2735 (match_operand:SI 3 "register_operand" "r"))))]
2737 "madd\\t%w0, %w1, %w2, %w3"
2738 [(set_attr "type" "mla")]
2741 (define_insn "*msub<mode>"
2742 [(set (match_operand:GPI 0 "register_operand" "=r")
2743 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2744 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2745 (match_operand:GPI 2 "register_operand" "r"))))]
2748 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2749 [(set_attr "type" "mla")]
2752 ;; zero_extend version of above
2753 (define_insn "*msubsi_uxtw"
2754 [(set (match_operand:DI 0 "register_operand" "=r")
2756 (minus:SI (match_operand:SI 3 "register_operand" "r")
2757 (mult:SI (match_operand:SI 1 "register_operand" "r")
2758 (match_operand:SI 2 "register_operand" "r")))))]
2761 "msub\\t%w0, %w1, %w2, %w3"
2762 [(set_attr "type" "mla")]
2765 (define_insn "*mul<mode>_neg"
2766 [(set (match_operand:GPI 0 "register_operand" "=r")
2767 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2768 (match_operand:GPI 2 "register_operand" "r")))]
2771 "mneg\\t%<w>0, %<w>1, %<w>2"
2772 [(set_attr "type" "mul")]
2775 ;; zero_extend version of above
2776 (define_insn "*mulsi_neg_uxtw"
2777 [(set (match_operand:DI 0 "register_operand" "=r")
2779 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2780 (match_operand:SI 2 "register_operand" "r"))))]
2783 "mneg\\t%w0, %w1, %w2"
2784 [(set_attr "type" "mul")]
2787 (define_insn "<su_optab>mulsidi3"
2788 [(set (match_operand:DI 0 "register_operand" "=r")
2789 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2790 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2792 "<su>mull\\t%0, %w1, %w2"
2793 [(set_attr "type" "<su>mull")]
2796 (define_insn "<su_optab>maddsidi4"
2797 [(set (match_operand:DI 0 "register_operand" "=r")
2799 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2800 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2801 (match_operand:DI 3 "register_operand" "r")))]
2803 "<su>maddl\\t%0, %w1, %w2, %3"
2804 [(set_attr "type" "<su>mlal")]
2807 (define_insn "<su_optab>msubsidi4"
2808 [(set (match_operand:DI 0 "register_operand" "=r")
2810 (match_operand:DI 3 "register_operand" "r")
2811 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2813 (match_operand:SI 2 "register_operand" "r")))))]
2815 "<su>msubl\\t%0, %w1, %w2, %3"
2816 [(set_attr "type" "<su>mlal")]
2819 (define_insn "*<su_optab>mulsidi_neg"
2820 [(set (match_operand:DI 0 "register_operand" "=r")
2822 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2823 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2825 "<su>mnegl\\t%0, %w1, %w2"
2826 [(set_attr "type" "<su>mull")]
2829 (define_expand "<su_optab>mulditi3"
2830 [(set (match_operand:TI 0 "register_operand")
2831 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2832 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2835 rtx low = gen_reg_rtx (DImode);
2836 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2838 rtx high = gen_reg_rtx (DImode);
2839 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2841 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2842 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2846 ;; The default expansion of multi3 using umuldi3_highpart will perform
2847 ;; the additions in an order that fails to combine into two madd insns.
2848 (define_expand "multi3"
2849 [(set (match_operand:TI 0 "register_operand")
2850 (mult:TI (match_operand:TI 1 "register_operand")
2851 (match_operand:TI 2 "register_operand")))]
2854 rtx l0 = gen_reg_rtx (DImode);
2855 rtx l1 = gen_lowpart (DImode, operands[1]);
2856 rtx l2 = gen_lowpart (DImode, operands[2]);
2857 rtx h0 = gen_reg_rtx (DImode);
2858 rtx h1 = gen_highpart (DImode, operands[1]);
2859 rtx h2 = gen_highpart (DImode, operands[2]);
2861 emit_insn (gen_muldi3 (l0, l1, l2));
2862 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2863 emit_insn (gen_madddi (h0, h1, l2, h0));
2864 emit_insn (gen_madddi (h0, l1, h2, h0));
2866 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2867 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2871 (define_insn "<su>muldi3_highpart"
2872 [(set (match_operand:DI 0 "register_operand" "=r")
2876 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2877 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2880 "<su>mulh\\t%0, %1, %2"
2881 [(set_attr "type" "<su>mull")]
2884 (define_insn "<su_optab>div<mode>3"
2885 [(set (match_operand:GPI 0 "register_operand" "=r")
2886 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2887 (match_operand:GPI 2 "register_operand" "r")))]
2889 "<su>div\\t%<w>0, %<w>1, %<w>2"
2890 [(set_attr "type" "<su>div")]
2893 ;; zero_extend version of above
2894 (define_insn "*<su_optab>divsi3_uxtw"
2895 [(set (match_operand:DI 0 "register_operand" "=r")
2897 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2898 (match_operand:SI 2 "register_operand" "r"))))]
2900 "<su>div\\t%w0, %w1, %w2"
2901 [(set_attr "type" "<su>div")]
2904 ;; -------------------------------------------------------------------
2906 ;; -------------------------------------------------------------------
2908 (define_insn "cmp<mode>"
2909 [(set (reg:CC CC_REGNUM)
2910 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2911 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2917 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2920 (define_insn "fcmp<mode>"
2921 [(set (reg:CCFP CC_REGNUM)
2922 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2923 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2927 fcmp\\t%<s>0, %<s>1"
2928 [(set_attr "type" "fcmp<s>")]
2931 (define_insn "fcmpe<mode>"
2932 [(set (reg:CCFPE CC_REGNUM)
2933 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2934 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2938 fcmpe\\t%<s>0, %<s>1"
2939 [(set_attr "type" "fcmp<s>")]
2942 (define_insn "*cmp_swp_<shift>_reg<mode>"
2943 [(set (reg:CC_SWP CC_REGNUM)
2944 (compare:CC_SWP (ASHIFT:GPI
2945 (match_operand:GPI 0 "register_operand" "r")
2946 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2947 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2949 "cmp\\t%<w>2, %<w>0, <shift> %1"
2950 [(set_attr "type" "alus_shift_imm")]
2953 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2954 [(set (reg:CC_SWP CC_REGNUM)
2955 (compare:CC_SWP (ANY_EXTEND:GPI
2956 (match_operand:ALLX 0 "register_operand" "r"))
2957 (match_operand:GPI 1 "register_operand" "r")))]
2959 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
2960 [(set_attr "type" "alus_ext")]
2963 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
2964 [(set (reg:CC_SWP CC_REGNUM)
2965 (compare:CC_SWP (ashift:GPI
2967 (match_operand:ALLX 0 "register_operand" "r"))
2968 (match_operand 1 "aarch64_imm3" "Ui3"))
2969 (match_operand:GPI 2 "register_operand" "r")))]
2971 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
2972 [(set_attr "type" "alus_ext")]
2975 ;; -------------------------------------------------------------------
2976 ;; Store-flag and conditional select insns
2977 ;; -------------------------------------------------------------------
2979 (define_expand "cstore<mode>4"
2980 [(set (match_operand:SI 0 "register_operand" "")
2981 (match_operator:SI 1 "aarch64_comparison_operator"
2982 [(match_operand:GPI 2 "register_operand" "")
2983 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
2986 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2988 operands[3] = const0_rtx;
2992 (define_expand "cstorecc4"
2993 [(set (match_operand:SI 0 "register_operand")
2994 (match_operator 1 "aarch64_comparison_operator_mode"
2995 [(match_operand 2 "cc_register")
2996 (match_operand 3 "const0_operand")]))]
2999 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3004 (define_expand "cstore<mode>4"
3005 [(set (match_operand:SI 0 "register_operand" "")
3006 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3007 [(match_operand:GPF 2 "register_operand" "")
3008 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3011 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3013 operands[3] = const0_rtx;
3017 (define_insn "aarch64_cstore<mode>"
3018 [(set (match_operand:ALLI 0 "register_operand" "=r")
3019 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3020 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3023 [(set_attr "type" "csel")]
3026 ;; For a 24-bit immediate CST we can optimize the compare for equality
3027 ;; and branch sequence from:
3029 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3032 ;; into the shorter:
3033 ;; sub x0, x1, #(CST & 0xfff000)
3034 ;; subs x0, x0, #(CST & 0x000fff)
3035 ;; cset x2, <ne, eq>.
3036 (define_insn_and_split "*compare_cstore<mode>_insn"
3037 [(set (match_operand:GPI 0 "register_operand" "=r")
3038 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3039 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3040 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3041 && !aarch64_plus_operand (operands[2], <MODE>mode)
3042 && !reload_completed"
3047 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3048 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3049 rtx tmp = gen_reg_rtx (<MODE>mode);
3050 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3051 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3052 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3053 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3054 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3057 [(set_attr "type" "csel")]
3060 ;; zero_extend version of the above
3061 (define_insn "*cstoresi_insn_uxtw"
3062 [(set (match_operand:DI 0 "register_operand" "=r")
3064 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3065 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3068 [(set_attr "type" "csel")]
3071 (define_insn "cstore<mode>_neg"
3072 [(set (match_operand:ALLI 0 "register_operand" "=r")
3073 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3074 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3076 "csetm\\t%<w>0, %m1"
3077 [(set_attr "type" "csel")]
3080 ;; zero_extend version of the above
3081 (define_insn "*cstoresi_neg_uxtw"
3082 [(set (match_operand:DI 0 "register_operand" "=r")
3084 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3085 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3088 [(set_attr "type" "csel")]
3091 (define_expand "cmov<mode>6"
3092 [(set (match_operand:GPI 0 "register_operand" "")
3094 (match_operator 1 "aarch64_comparison_operator"
3095 [(match_operand:GPI 2 "register_operand" "")
3096 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3097 (match_operand:GPI 4 "register_operand" "")
3098 (match_operand:GPI 5 "register_operand" "")))]
3101 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3103 operands[3] = const0_rtx;
3107 (define_expand "cmov<mode>6"
3108 [(set (match_operand:GPF 0 "register_operand" "")
3110 (match_operator 1 "aarch64_comparison_operator"
3111 [(match_operand:GPF 2 "register_operand" "")
3112 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3113 (match_operand:GPF 4 "register_operand" "")
3114 (match_operand:GPF 5 "register_operand" "")))]
3117 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3119 operands[3] = const0_rtx;
3123 (define_insn "*cmov<mode>_insn"
3124 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3126 (match_operator 1 "aarch64_comparison_operator"
3127 [(match_operand 2 "cc_register" "") (const_int 0)])
3128 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3129 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3130 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3131 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3132 ;; Final two alternatives should be unreachable, but included for completeness
3134 csel\\t%<w>0, %<w>3, %<w>4, %m1
3135 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3136 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3137 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3138 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3141 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3144 ;; zero_extend version of above
3145 (define_insn "*cmovsi_insn_uxtw"
3146 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3149 (match_operator 1 "aarch64_comparison_operator"
3150 [(match_operand 2 "cc_register" "") (const_int 0)])
3151 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3152 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3153 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3154 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3155 ;; Final two alternatives should be unreachable, but included for completeness
3157 csel\\t%w0, %w3, %w4, %m1
3158 csinv\\t%w0, %w3, wzr, %m1
3159 csinv\\t%w0, %w4, wzr, %M1
3160 csinc\\t%w0, %w3, wzr, %m1
3161 csinc\\t%w0, %w4, wzr, %M1
3164 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3167 (define_insn "*cmovdi_insn_uxtw"
3168 [(set (match_operand:DI 0 "register_operand" "=r")
3170 (match_operator 1 "aarch64_comparison_operator"
3171 [(match_operand 2 "cc_register" "") (const_int 0)])
3172 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3173 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3175 "csel\\t%w0, %w3, %w4, %m1"
3176 [(set_attr "type" "csel")]
3179 (define_insn "*cmov<mode>_insn"
3180 [(set (match_operand:GPF 0 "register_operand" "=w")
3182 (match_operator 1 "aarch64_comparison_operator"
3183 [(match_operand 2 "cc_register" "") (const_int 0)])
3184 (match_operand:GPF 3 "register_operand" "w")
3185 (match_operand:GPF 4 "register_operand" "w")))]
3187 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3188 [(set_attr "type" "fcsel")]
3191 (define_expand "mov<mode>cc"
3192 [(set (match_operand:ALLI 0 "register_operand" "")
3193 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3194 (match_operand:ALLI 2 "register_operand" "")
3195 (match_operand:ALLI 3 "register_operand" "")))]
3199 enum rtx_code code = GET_CODE (operands[1]);
3201 if (code == UNEQ || code == LTGT)
3204 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3205 XEXP (operands[1], 1));
3206 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3210 (define_expand "mov<GPF:mode><GPI:mode>cc"
3211 [(set (match_operand:GPI 0 "register_operand" "")
3212 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3213 (match_operand:GPF 2 "register_operand" "")
3214 (match_operand:GPF 3 "register_operand" "")))]
3218 enum rtx_code code = GET_CODE (operands[1]);
3220 if (code == UNEQ || code == LTGT)
3223 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3224 XEXP (operands[1], 1));
3225 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3229 (define_expand "mov<mode>cc"
3230 [(set (match_operand:GPF 0 "register_operand" "")
3231 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3232 (match_operand:GPF 2 "register_operand" "")
3233 (match_operand:GPF 3 "register_operand" "")))]
3237 enum rtx_code code = GET_CODE (operands[1]);
3239 if (code == UNEQ || code == LTGT)
3242 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3243 XEXP (operands[1], 1));
3244 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3248 (define_expand "<neg_not_op><mode>cc"
3249 [(set (match_operand:GPI 0 "register_operand" "")
3250 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3251 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3252 (match_operand:GPI 3 "register_operand" "")))]
3256 enum rtx_code code = GET_CODE (operands[1]);
3258 if (code == UNEQ || code == LTGT)
3261 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3262 XEXP (operands[1], 1));
3263 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3267 ;; CRC32 instructions.
3268 (define_insn "aarch64_<crc_variant>"
3269 [(set (match_operand:SI 0 "register_operand" "=r")
3270 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3271 (match_operand:<crc_mode> 2 "register_operand" "r")]
3275 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3276 return "<crc_variant>\\t%w0, %w1, %x2";
3278 return "<crc_variant>\\t%w0, %w1, %w2";
3280 [(set_attr "type" "crc")]
3283 (define_insn "*csinc2<mode>_insn"
3284 [(set (match_operand:GPI 0 "register_operand" "=r")
3285 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3286 (match_operand:GPI 1 "register_operand" "r")))]
3288 "cinc\\t%<w>0, %<w>1, %m2"
3289 [(set_attr "type" "csel")]
3292 (define_insn "csinc3<mode>_insn"
3293 [(set (match_operand:GPI 0 "register_operand" "=r")
3295 (match_operand 1 "aarch64_comparison_operation" "")
3296 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3298 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3300 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3301 [(set_attr "type" "csel")]
3304 (define_insn "*csinv3<mode>_insn"
3305 [(set (match_operand:GPI 0 "register_operand" "=r")
3307 (match_operand 1 "aarch64_comparison_operation" "")
3308 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3309 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3311 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3312 [(set_attr "type" "csel")]
3315 (define_insn "csneg3_uxtw_insn"
3316 [(set (match_operand:DI 0 "register_operand" "=r")
3319 (match_operand 1 "aarch64_comparison_operation" "")
3320 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3321 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3323 "csneg\\t%w0, %w3, %w2, %M1"
3324 [(set_attr "type" "csel")]
3327 (define_insn "csneg3<mode>_insn"
3328 [(set (match_operand:GPI 0 "register_operand" "=r")
3330 (match_operand 1 "aarch64_comparison_operation" "")
3331 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3332 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3334 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3335 [(set_attr "type" "csel")]
3338 ;; -------------------------------------------------------------------
3339 ;; Logical operations
3340 ;; -------------------------------------------------------------------
3343 (define_insn_and_split "*aarch64_and<mode>_imm2"
3344 [(set (match_operand:GPI 0 "register_operand" "=rk")
3345 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3346 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3352 HOST_WIDE_INT val = INTVAL (operands[2]);
3353 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3354 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3356 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3357 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3362 (define_insn "<optab><mode>3"
3363 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3364 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3365 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3368 <logical>\\t%<w>0, %<w>1, %<w>2
3369 <logical>\\t%<w>0, %<w>1, %2
3370 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3371 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3372 (set_attr "simd" "*,*,yes")]
3375 ;; zero_extend version of above
3376 (define_insn "*<optab>si3_uxtw"
3377 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3379 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3380 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3383 <logical>\\t%w0, %w1, %w2
3384 <logical>\\t%w0, %w1, %2"
3385 [(set_attr "type" "logic_reg,logic_imm")]
3388 (define_insn "*and<mode>3_compare0"
3389 [(set (reg:CC_NZ CC_REGNUM)
3391 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3392 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3394 (set (match_operand:GPI 0 "register_operand" "=r,r")
3395 (and:GPI (match_dup 1) (match_dup 2)))]
3398 ands\\t%<w>0, %<w>1, %<w>2
3399 ands\\t%<w>0, %<w>1, %2"
3400 [(set_attr "type" "logics_reg,logics_imm")]
3403 ;; zero_extend version of above
3404 (define_insn "*andsi3_compare0_uxtw"
3405 [(set (reg:CC_NZ CC_REGNUM)
3407 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3408 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3410 (set (match_operand:DI 0 "register_operand" "=r,r")
3411 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3414 ands\\t%w0, %w1, %w2
3415 ands\\t%w0, %w1, %2"
3416 [(set_attr "type" "logics_reg,logics_imm")]
3419 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3420 [(set (reg:CC_NZ CC_REGNUM)
3423 (match_operand:GPI 1 "register_operand" "r")
3424 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3425 (match_operand:GPI 3 "register_operand" "r"))
3427 (set (match_operand:GPI 0 "register_operand" "=r")
3428 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3430 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3431 [(set_attr "type" "logics_shift_imm")]
3434 ;; zero_extend version of above
3435 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3436 [(set (reg:CC_NZ CC_REGNUM)
3439 (match_operand:SI 1 "register_operand" "r")
3440 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3441 (match_operand:SI 3 "register_operand" "r"))
3443 (set (match_operand:DI 0 "register_operand" "=r")
3444 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3447 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3448 [(set_attr "type" "logics_shift_imm")]
3451 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3452 [(set (match_operand:GPI 0 "register_operand" "=r")
3453 (LOGICAL:GPI (SHIFT:GPI
3454 (match_operand:GPI 1 "register_operand" "r")
3455 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3456 (match_operand:GPI 3 "register_operand" "r")))]
3458 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3459 [(set_attr "type" "logic_shift_imm")]
3462 (define_insn "*<optab>_rol<mode>3"
3463 [(set (match_operand:GPI 0 "register_operand" "=r")
3464 (LOGICAL:GPI (rotate:GPI
3465 (match_operand:GPI 1 "register_operand" "r")
3466 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3467 (match_operand:GPI 3 "register_operand" "r")))]
3469 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3470 [(set_attr "type" "logic_shift_imm")]
3473 ;; zero_extend versions of above
3474 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3475 [(set (match_operand:DI 0 "register_operand" "=r")
3477 (LOGICAL:SI (SHIFT:SI
3478 (match_operand:SI 1 "register_operand" "r")
3479 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3480 (match_operand:SI 3 "register_operand" "r"))))]
3482 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3483 [(set_attr "type" "logic_shift_imm")]
3486 (define_insn "*<optab>_rolsi3_uxtw"
3487 [(set (match_operand:DI 0 "register_operand" "=r")
3489 (LOGICAL:SI (rotate:SI
3490 (match_operand:SI 1 "register_operand" "r")
3491 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3492 (match_operand:SI 3 "register_operand" "r"))))]
3494 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3495 [(set_attr "type" "logic_shift_imm")]
3498 (define_insn "one_cmpl<mode>2"
3499 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3500 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3505 [(set_attr "type" "logic_reg,neon_logic")
3506 (set_attr "simd" "*,yes")]
3509 (define_insn "*one_cmpl_<optab><mode>2"
3510 [(set (match_operand:GPI 0 "register_operand" "=r")
3511 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3512 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3514 "mvn\\t%<w>0, %<w>1, <shift> %2"
3515 [(set_attr "type" "logic_shift_imm")]
3518 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3520 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3521 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3522 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3523 (match_operand:GPI 2 "register_operand" "r,w")))]
3526 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3527 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3528 [(set_attr "type" "logic_reg,neon_logic")
3529 (set_attr "simd" "*,yes")]
3532 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3533 [(set (match_operand:DI 0 "register_operand" "=r")
3535 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3536 (match_operand:SI 2 "register_operand" "r"))))]
3538 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3539 [(set_attr "type" "logic_reg")]
3542 (define_insn "*xor_one_cmplsidi3_ze"
3543 [(set (match_operand:DI 0 "register_operand" "=r")
3545 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3546 (match_operand:SI 2 "register_operand" "r")))))]
3548 "eon\\t%w0, %w1, %w2"
3549 [(set_attr "type" "logic_reg")]
3552 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3553 ;; eon does not operate on SIMD registers so the vector variant must be split.
3554 (define_insn_and_split "*xor_one_cmpl<mode>3"
3555 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3556 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3557 (match_operand:GPI 2 "register_operand" "r,w"))))]
3560 eon\\t%<w>0, %<w>1, %<w>2
3562 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3563 [(set (match_operand:GPI 0 "register_operand" "=w")
3564 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3565 (match_operand:GPI 2 "register_operand" "w")))
3566 (set (match_dup 0) (not:GPI (match_dup 0)))]
3568 [(set_attr "type" "logic_reg,multiple")
3569 (set_attr "simd" "*,yes")]
3572 (define_insn "*and_one_cmpl<mode>3_compare0"
3573 [(set (reg:CC_NZ CC_REGNUM)
3576 (match_operand:GPI 1 "register_operand" "r"))
3577 (match_operand:GPI 2 "register_operand" "r"))
3579 (set (match_operand:GPI 0 "register_operand" "=r")
3580 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3582 "bics\\t%<w>0, %<w>2, %<w>1"
3583 [(set_attr "type" "logics_reg")]
3586 ;; zero_extend version of above
3587 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3588 [(set (reg:CC_NZ CC_REGNUM)
3591 (match_operand:SI 1 "register_operand" "r"))
3592 (match_operand:SI 2 "register_operand" "r"))
3594 (set (match_operand:DI 0 "register_operand" "=r")
3595 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3597 "bics\\t%w0, %w2, %w1"
3598 [(set_attr "type" "logics_reg")]
3601 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3602 [(set (reg:CC_NZ CC_REGNUM)
3605 (match_operand:GPI 0 "register_operand" "r"))
3606 (match_operand:GPI 1 "register_operand" "r"))
3609 "bics\\t<w>zr, %<w>1, %<w>0"
3610 [(set_attr "type" "logics_reg")]
3613 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3614 [(set (match_operand:GPI 0 "register_operand" "=r")
3615 (LOGICAL:GPI (not:GPI
3617 (match_operand:GPI 1 "register_operand" "r")
3618 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3619 (match_operand:GPI 3 "register_operand" "r")))]
3621 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3622 [(set_attr "type" "logic_shift_imm")]
3625 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3626 [(set (match_operand:GPI 0 "register_operand" "=r")
3629 (match_operand:GPI 1 "register_operand" "r")
3630 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3631 (match_operand:GPI 3 "register_operand" "r"))))]
3633 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3634 [(set_attr "type" "logic_shift_imm")]
3637 ;; Zero-extend version of the above.
3638 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3639 [(set (match_operand:DI 0 "register_operand" "=r")
3643 (match_operand:SI 1 "register_operand" "r")
3644 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3645 (match_operand:SI 3 "register_operand" "r")))))]
3647 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3648 [(set_attr "type" "logic_shift_imm")]
3651 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3652 [(set (reg:CC_NZ CC_REGNUM)
3656 (match_operand:GPI 1 "register_operand" "r")
3657 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3658 (match_operand:GPI 3 "register_operand" "r"))
3660 (set (match_operand:GPI 0 "register_operand" "=r")
3663 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3665 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3666 [(set_attr "type" "logics_shift_imm")]
3669 ;; zero_extend version of above
3670 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3671 [(set (reg:CC_NZ CC_REGNUM)
3675 (match_operand:SI 1 "register_operand" "r")
3676 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3677 (match_operand:SI 3 "register_operand" "r"))
3679 (set (match_operand:DI 0 "register_operand" "=r")
3680 (zero_extend:DI (and:SI
3682 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3684 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3685 [(set_attr "type" "logics_shift_imm")]
3688 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3689 [(set (reg:CC_NZ CC_REGNUM)
3693 (match_operand:GPI 0 "register_operand" "r")
3694 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3695 (match_operand:GPI 2 "register_operand" "r"))
3698 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3699 [(set_attr "type" "logics_shift_imm")]
3702 (define_insn "clz<mode>2"
3703 [(set (match_operand:GPI 0 "register_operand" "=r")
3704 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3706 "clz\\t%<w>0, %<w>1"
3707 [(set_attr "type" "clz")]
3710 (define_expand "ffs<mode>2"
3711 [(match_operand:GPI 0 "register_operand")
3712 (match_operand:GPI 1 "register_operand")]
3715 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3716 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3718 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3719 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3720 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3725 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3732 (define_expand "popcount<mode>2"
3733 [(match_operand:GPI 0 "register_operand")
3734 (match_operand:GPI 1 "register_operand")]
3737 rtx v = gen_reg_rtx (V8QImode);
3738 rtx v1 = gen_reg_rtx (V8QImode);
3739 rtx r = gen_reg_rtx (QImode);
3740 rtx in = operands[1];
3741 rtx out = operands[0];
3742 if(<MODE>mode == SImode)
3745 tmp = gen_reg_rtx (DImode);
3746 /* If we have SImode, zero extend to DImode, pop count does
3747 not change if we have extra zeros. */
3748 emit_insn (gen_zero_extendsidi2 (tmp, in));
3751 emit_move_insn (v, gen_lowpart (V8QImode, in));
3752 emit_insn (gen_popcountv8qi2 (v1, v));
3753 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3754 emit_insn (gen_zero_extendqi<mode>2 (out, r));
3758 (define_insn "clrsb<mode>2"
3759 [(set (match_operand:GPI 0 "register_operand" "=r")
3760 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3762 "cls\\t%<w>0, %<w>1"
3763 [(set_attr "type" "clz")]
3766 (define_insn "rbit<mode>2"
3767 [(set (match_operand:GPI 0 "register_operand" "=r")
3768 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3770 "rbit\\t%<w>0, %<w>1"
3771 [(set_attr "type" "rbit")]
3774 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3775 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3776 ;; expression and split after reload to enable scheduling them apart if
3779 (define_insn_and_split "ctz<mode>2"
3780 [(set (match_operand:GPI 0 "register_operand" "=r")
3781 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3787 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3788 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3792 (define_insn "*and<mode>_compare0"
3793 [(set (reg:CC_NZ CC_REGNUM)
3795 (match_operand:SHORT 0 "register_operand" "r")
3798 "tst\\t%<w>0, <short_mask>"
3799 [(set_attr "type" "alus_imm")]
3802 (define_insn "*ands<mode>_compare0"
3803 [(set (reg:CC_NZ CC_REGNUM)
3805 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3807 (set (match_operand:GPI 0 "register_operand" "=r")
3808 (zero_extend:GPI (match_dup 1)))]
3810 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3811 [(set_attr "type" "alus_imm")]
3814 (define_insn "*and<mode>3nr_compare0"
3815 [(set (reg:CC_NZ CC_REGNUM)
3817 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3818 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3824 [(set_attr "type" "logics_reg,logics_imm")]
3827 (define_insn "*and<mode>3nr_compare0_zextract"
3828 [(set (reg:CC_NZ CC_REGNUM)
3830 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3831 (match_operand:GPI 1 "const_int_operand" "n")
3832 (match_operand:GPI 2 "const_int_operand" "n"))
3834 "INTVAL (operands[1]) > 0
3835 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3836 <= GET_MODE_BITSIZE (<MODE>mode))
3837 && aarch64_bitmask_imm (
3838 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3843 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3844 return "tst\\t%<w>0, %1";
3846 [(set_attr "type" "logics_shift_imm")]
3849 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3850 [(set (reg:CC_NZ CC_REGNUM)
3853 (match_operand:GPI 0 "register_operand" "r")
3854 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3855 (match_operand:GPI 2 "register_operand" "r"))
3858 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3859 [(set_attr "type" "logics_shift_imm")]
3862 ;; -------------------------------------------------------------------
3864 ;; -------------------------------------------------------------------
3866 (define_expand "<optab><mode>3"
3867 [(set (match_operand:GPI 0 "register_operand")
3868 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3869 (match_operand:QI 2 "nonmemory_operand")))]
3872 if (CONST_INT_P (operands[2]))
3874 operands[2] = GEN_INT (INTVAL (operands[2])
3875 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3877 if (operands[2] == const0_rtx)
3879 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3886 (define_expand "ashl<mode>3"
3887 [(set (match_operand:SHORT 0 "register_operand")
3888 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3889 (match_operand:QI 2 "const_int_operand")))]
3892 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3894 if (operands[2] == const0_rtx)
3896 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3902 (define_expand "rotr<mode>3"
3903 [(set (match_operand:GPI 0 "register_operand")
3904 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3905 (match_operand:QI 2 "nonmemory_operand")))]
3908 if (CONST_INT_P (operands[2]))
3910 operands[2] = GEN_INT (INTVAL (operands[2])
3911 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3913 if (operands[2] == const0_rtx)
3915 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3922 (define_expand "rotl<mode>3"
3923 [(set (match_operand:GPI 0 "register_operand")
3924 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3925 (match_operand:QI 2 "nonmemory_operand")))]
3928 /* (SZ - cnt) % SZ == -cnt % SZ */
3929 if (CONST_INT_P (operands[2]))
3931 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3932 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3933 if (operands[2] == const0_rtx)
3935 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3940 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3945 ;; Logical left shift using SISD or Integer instruction
3946 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3947 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3949 (match_operand:GPI 1 "register_operand" "r,r,w,w")
3950 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3953 lsl\t%<w>0, %<w>1, %2
3954 lsl\t%<w>0, %<w>1, %<w>2
3955 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3956 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3957 [(set_attr "simd" "no,no,yes,yes")
3958 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3961 ;; Logical right shift using SISD or Integer instruction
3962 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3963 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3965 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3966 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3969 lsr\t%<w>0, %<w>1, %2
3970 lsr\t%<w>0, %<w>1, %<w>2
3971 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3974 [(set_attr "simd" "no,no,yes,yes,yes")
3975 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3979 [(set (match_operand:DI 0 "aarch64_simd_register")
3981 (match_operand:DI 1 "aarch64_simd_register")
3982 (match_operand:QI 2 "aarch64_simd_register")))]
3983 "TARGET_SIMD && reload_completed"
3985 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3987 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3989 operands[3] = gen_lowpart (QImode, operands[0]);
3994 [(set (match_operand:SI 0 "aarch64_simd_register")
3996 (match_operand:SI 1 "aarch64_simd_register")
3997 (match_operand:QI 2 "aarch64_simd_register")))]
3998 "TARGET_SIMD && reload_completed"
4000 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4002 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4004 operands[3] = gen_lowpart (QImode, operands[0]);
4008 ;; Arithmetic right shift using SISD or Integer instruction
4009 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4010 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4012 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4013 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4016 asr\t%<w>0, %<w>1, %2
4017 asr\t%<w>0, %<w>1, %<w>2
4018 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4021 [(set_attr "simd" "no,no,yes,yes,yes")
4022 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4026 [(set (match_operand:DI 0 "aarch64_simd_register")
4028 (match_operand:DI 1 "aarch64_simd_register")
4029 (match_operand:QI 2 "aarch64_simd_register")))]
4030 "TARGET_SIMD && reload_completed"
4032 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4034 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4036 operands[3] = gen_lowpart (QImode, operands[0]);
4041 [(set (match_operand:SI 0 "aarch64_simd_register")
4043 (match_operand:SI 1 "aarch64_simd_register")
4044 (match_operand:QI 2 "aarch64_simd_register")))]
4045 "TARGET_SIMD && reload_completed"
4047 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4049 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4051 operands[3] = gen_lowpart (QImode, operands[0]);
4055 (define_insn "*aarch64_sisd_ushl"
4056 [(set (match_operand:DI 0 "register_operand" "=w")
4057 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4058 (match_operand:QI 2 "register_operand" "w")]
4061 "ushl\t%d0, %d1, %d2"
4062 [(set_attr "simd" "yes")
4063 (set_attr "type" "neon_shift_reg")]
4066 (define_insn "*aarch64_ushl_2s"
4067 [(set (match_operand:SI 0 "register_operand" "=w")
4068 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4069 (match_operand:QI 2 "register_operand" "w")]
4072 "ushl\t%0.2s, %1.2s, %2.2s"
4073 [(set_attr "simd" "yes")
4074 (set_attr "type" "neon_shift_reg")]
4077 (define_insn "*aarch64_sisd_sshl"
4078 [(set (match_operand:DI 0 "register_operand" "=w")
4079 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4080 (match_operand:QI 2 "register_operand" "w")]
4083 "sshl\t%d0, %d1, %d2"
4084 [(set_attr "simd" "yes")
4085 (set_attr "type" "neon_shift_reg")]
4088 (define_insn "*aarch64_sshl_2s"
4089 [(set (match_operand:SI 0 "register_operand" "=w")
4090 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4091 (match_operand:QI 2 "register_operand" "w")]
4094 "sshl\t%0.2s, %1.2s, %2.2s"
4095 [(set_attr "simd" "yes")
4096 (set_attr "type" "neon_shift_reg")]
4099 (define_insn "*aarch64_sisd_neg_qi"
4100 [(set (match_operand:QI 0 "register_operand" "=w")
4101 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4105 [(set_attr "simd" "yes")
4106 (set_attr "type" "neon_neg")]
4110 (define_insn "*ror<mode>3_insn"
4111 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4113 (match_operand:GPI 1 "register_operand" "r,r")
4114 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4117 ror\\t%<w>0, %<w>1, %2
4118 ror\\t%<w>0, %<w>1, %<w>2"
4119 [(set_attr "type" "rotate_imm,shift_reg")]
4122 ;; zero_extend version of above
4123 (define_insn "*<optab>si3_insn_uxtw"
4124 [(set (match_operand:DI 0 "register_operand" "=r,r")
4125 (zero_extend:DI (SHIFT:SI
4126 (match_operand:SI 1 "register_operand" "r,r")
4127 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4130 <shift>\\t%w0, %w1, %2
4131 <shift>\\t%w0, %w1, %w2"
4132 [(set_attr "type" "bfx,shift_reg")]
4135 (define_insn "*<optab><mode>3_insn"
4136 [(set (match_operand:SHORT 0 "register_operand" "=r")
4137 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4138 (match_operand 2 "const_int_operand" "n")))]
4139 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4141 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4142 return "<bfshift>\t%w0, %w1, %2, %3";
4144 [(set_attr "type" "bfx")]
4147 (define_insn "*extr<mode>5_insn"
4148 [(set (match_operand:GPI 0 "register_operand" "=r")
4149 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4150 (match_operand 3 "const_int_operand" "n"))
4151 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4152 (match_operand 4 "const_int_operand" "n"))))]
4153 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4154 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4155 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4156 [(set_attr "type" "rotate_imm")]
4159 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4160 ;; so we have to match both orderings.
4161 (define_insn "*extr<mode>5_insn_alt"
4162 [(set (match_operand:GPI 0 "register_operand" "=r")
4163 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4164 (match_operand 4 "const_int_operand" "n"))
4165 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4166 (match_operand 3 "const_int_operand" "n"))))]
4167 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4168 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4169 == GET_MODE_BITSIZE (<MODE>mode))"
4170 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4171 [(set_attr "type" "rotate_imm")]
4174 ;; zero_extend version of the above
4175 (define_insn "*extrsi5_insn_uxtw"
4176 [(set (match_operand:DI 0 "register_operand" "=r")
4178 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4179 (match_operand 3 "const_int_operand" "n"))
4180 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4181 (match_operand 4 "const_int_operand" "n")))))]
4182 "UINTVAL (operands[3]) < 32 &&
4183 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4184 "extr\\t%w0, %w1, %w2, %4"
4185 [(set_attr "type" "rotate_imm")]
4188 (define_insn "*extrsi5_insn_uxtw_alt"
4189 [(set (match_operand:DI 0 "register_operand" "=r")
4191 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4192 (match_operand 4 "const_int_operand" "n"))
4193 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4194 (match_operand 3 "const_int_operand" "n")))))]
4195 "UINTVAL (operands[3]) < 32 &&
4196 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4197 "extr\\t%w0, %w1, %w2, %4"
4198 [(set_attr "type" "rotate_imm")]
4201 (define_insn "*ror<mode>3_insn"
4202 [(set (match_operand:GPI 0 "register_operand" "=r")
4203 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4204 (match_operand 2 "const_int_operand" "n")))]
4205 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4207 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4208 return "ror\\t%<w>0, %<w>1, %3";
4210 [(set_attr "type" "rotate_imm")]
4213 ;; zero_extend version of the above
4214 (define_insn "*rorsi3_insn_uxtw"
4215 [(set (match_operand:DI 0 "register_operand" "=r")
4217 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4218 (match_operand 2 "const_int_operand" "n"))))]
4219 "UINTVAL (operands[2]) < 32"
4221 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4222 return "ror\\t%w0, %w1, %3";
4224 [(set_attr "type" "rotate_imm")]
4227 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4228 [(set (match_operand:GPI 0 "register_operand" "=r")
4230 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4231 (match_operand 2 "const_int_operand" "n"))))]
4232 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4234 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4235 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4237 [(set_attr "type" "bfx")]
4240 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4241 [(set (match_operand:GPI 0 "register_operand" "=r")
4243 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4244 (match_operand 2 "const_int_operand" "n"))))]
4245 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4247 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4248 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4250 [(set_attr "type" "bfx")]
4253 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4254 [(set (match_operand:GPI 0 "register_operand" "=r")
4256 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4257 (match_operand 2 "const_int_operand" "n"))))]
4258 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4260 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4261 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4263 [(set_attr "type" "bfx")]
4266 ;; -------------------------------------------------------------------
4268 ;; -------------------------------------------------------------------
4270 (define_expand "<optab>"
4271 [(set (match_operand:DI 0 "register_operand" "=r")
4272 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4274 "aarch64_simd_shift_imm_offset_di")
4275 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4278 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4279 1, GET_MODE_BITSIZE (DImode) - 1))
4285 (define_insn "*<optab><mode>"
4286 [(set (match_operand:GPI 0 "register_operand" "=r")
4287 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4289 "aarch64_simd_shift_imm_offset_<mode>" "n")
4291 "aarch64_simd_shift_imm_<mode>" "n")))]
4292 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4293 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4294 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4295 [(set_attr "type" "bfx")]
4298 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4299 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4301 [(set (match_operand:DI 0 "register_operand")
4302 (zero_extract:DI (match_operand:DI 1 "register_operand")
4304 "aarch64_simd_shift_imm_offset_di")
4306 "aarch64_simd_shift_imm_di")))]
4307 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4308 GET_MODE_BITSIZE (DImode) - 1)
4309 && (INTVAL (operands[2]) + INTVAL (operands[3]))
4310 == GET_MODE_BITSIZE (SImode)"
4312 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4314 operands[4] = gen_lowpart (SImode, operands[1]);
4318 ;; Bitfield Insert (insv)
4319 (define_expand "insv<mode>"
4320 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4321 (match_operand 1 "const_int_operand")
4322 (match_operand 2 "const_int_operand"))
4323 (match_operand:GPI 3 "general_operand"))]
4326 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4327 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4328 rtx value = operands[3];
4330 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4333 if (CONST_INT_P (value))
4335 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4337 /* Prefer AND/OR for inserting all zeros or all ones. */
4338 if ((UINTVAL (value) & mask) == 0
4339 || (UINTVAL (value) & mask) == mask)
4342 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4343 if (width == 16 && (pos % 16) == 0)
4346 operands[3] = force_reg (<MODE>mode, value);
4349 (define_insn "*insv_reg<mode>"
4350 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4351 (match_operand 1 "const_int_operand" "n")
4352 (match_operand 2 "const_int_operand" "n"))
4353 (match_operand:GPI 3 "register_operand" "r"))]
4354 "!(UINTVAL (operands[1]) == 0
4355 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4356 > GET_MODE_BITSIZE (<MODE>mode)))"
4357 "bfi\\t%<w>0, %<w>3, %2, %1"
4358 [(set_attr "type" "bfm")]
4361 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4362 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4363 (match_operand 1 "const_int_operand" "n")
4364 (match_operand 2 "const_int_operand" "n"))
4365 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4366 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4367 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4368 [(set_attr "type" "bfm")]
4371 (define_insn "*extr_insv_lower_reg<mode>"
4372 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4373 (match_operand 1 "const_int_operand" "n")
4375 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4377 (match_operand 3 "const_int_operand" "n")))]
4378 "!(UINTVAL (operands[1]) == 0
4379 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4380 > GET_MODE_BITSIZE (<MODE>mode)))"
4381 "bfxil\\t%<w>0, %<w>2, %3, %1"
4382 [(set_attr "type" "bfm")]
4385 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4386 [(set (match_operand:GPI 0 "register_operand" "=r")
4387 (ashift:GPI (ANY_EXTEND:GPI
4388 (match_operand:ALLX 1 "register_operand" "r"))
4389 (match_operand 2 "const_int_operand" "n")))]
4390 "UINTVAL (operands[2]) < <GPI:sizen>"
4392 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4393 ? GEN_INT (<ALLX:sizen>)
4394 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4395 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4397 [(set_attr "type" "bfx")]
4400 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4402 (define_insn "*andim_ashift<mode>_bfiz"
4403 [(set (match_operand:GPI 0 "register_operand" "=r")
4404 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4405 (match_operand 2 "const_int_operand" "n"))
4406 (match_operand 3 "const_int_operand" "n")))]
4407 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4408 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4409 [(set_attr "type" "bfx")]
4412 ;; When the bit position and width of the equivalent extraction add up to 32
4413 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4414 ;; zero-extension of the X-reg.
4416 [(set (match_operand:DI 0 "register_operand")
4417 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4418 (match_operand 2 "const_int_operand"))
4419 (match_operand 3 "const_int_operand")))]
4420 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4421 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4422 == GET_MODE_BITSIZE (SImode)"
4424 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4426 operands[4] = gen_lowpart (SImode, operands[1]);
4430 (define_insn "bswap<mode>2"
4431 [(set (match_operand:GPI 0 "register_operand" "=r")
4432 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4434 "rev\\t%<w>0, %<w>1"
4435 [(set_attr "type" "rev")]
4438 (define_insn "bswaphi2"
4439 [(set (match_operand:HI 0 "register_operand" "=r")
4440 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4443 [(set_attr "type" "rev")]
4446 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4447 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4448 ;; each valid permutation.
4450 (define_insn "rev16<mode>2"
4451 [(set (match_operand:GPI 0 "register_operand" "=r")
4452 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4454 (match_operand:GPI 3 "const_int_operand" "n"))
4455 (and:GPI (lshiftrt:GPI (match_dup 1)
4457 (match_operand:GPI 2 "const_int_operand" "n"))))]
4458 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4459 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4460 "rev16\\t%<w>0, %<w>1"
4461 [(set_attr "type" "rev")]
4464 (define_insn "rev16<mode>2_alt"
4465 [(set (match_operand:GPI 0 "register_operand" "=r")
4466 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4468 (match_operand:GPI 2 "const_int_operand" "n"))
4469 (and:GPI (ashift:GPI (match_dup 1)
4471 (match_operand:GPI 3 "const_int_operand" "n"))))]
4472 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4473 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4474 "rev16\\t%<w>0, %<w>1"
4475 [(set_attr "type" "rev")]
4478 ;; zero_extend version of above
4479 (define_insn "*bswapsi2_uxtw"
4480 [(set (match_operand:DI 0 "register_operand" "=r")
4481 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4484 [(set_attr "type" "rev")]
4487 ;; -------------------------------------------------------------------
4488 ;; Floating-point intrinsics
4489 ;; -------------------------------------------------------------------
4491 ;; frint floating-point round to integral standard patterns.
4492 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4494 (define_insn "<frint_pattern><mode>2"
4495 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4496 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4499 "frint<frint_suffix>\\t%<s>0, %<s>1"
4500 [(set_attr "type" "f_rint<stype>")]
4503 ;; frcvt floating-point round to integer and convert standard patterns.
4504 ;; Expands to lbtrunc, lceil, lfloor, lround.
4505 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4506 [(set (match_operand:GPI 0 "register_operand" "=r")
4508 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4511 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4512 [(set_attr "type" "f_cvtf2i")]
4515 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4516 [(set (match_operand:GPI 0 "register_operand" "=r")
4519 (match_operand:GPF 1 "register_operand" "w")
4520 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4522 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4523 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4525 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4527 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4528 output_asm_insn (buf, operands);
4531 [(set_attr "type" "f_cvtf2i")]
4536 (define_insn "fma<mode>4"
4537 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4538 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4539 (match_operand:GPF_F16 2 "register_operand" "w")
4540 (match_operand:GPF_F16 3 "register_operand" "w")))]
4542 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4543 [(set_attr "type" "fmac<stype>")]
4546 (define_insn "fnma<mode>4"
4547 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4549 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4550 (match_operand:GPF_F16 2 "register_operand" "w")
4551 (match_operand:GPF_F16 3 "register_operand" "w")))]
4553 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4554 [(set_attr "type" "fmac<stype>")]
4557 (define_insn "fms<mode>4"
4558 [(set (match_operand:GPF 0 "register_operand" "=w")
4559 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4560 (match_operand:GPF 2 "register_operand" "w")
4561 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4563 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4564 [(set_attr "type" "fmac<s>")]
4567 (define_insn "fnms<mode>4"
4568 [(set (match_operand:GPF 0 "register_operand" "=w")
4569 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4570 (match_operand:GPF 2 "register_operand" "w")
4571 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4573 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4574 [(set_attr "type" "fmac<s>")]
4577 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4578 (define_insn "*fnmadd<mode>4"
4579 [(set (match_operand:GPF 0 "register_operand" "=w")
4580 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4581 (match_operand:GPF 2 "register_operand" "w")
4582 (match_operand:GPF 3 "register_operand" "w"))))]
4583 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4584 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4585 [(set_attr "type" "fmac<s>")]
4588 ;; -------------------------------------------------------------------
4589 ;; Floating-point conversions
4590 ;; -------------------------------------------------------------------
4592 (define_insn "extendsfdf2"
4593 [(set (match_operand:DF 0 "register_operand" "=w")
4594 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4597 [(set_attr "type" "f_cvt")]
4600 (define_insn "extendhfsf2"
4601 [(set (match_operand:SF 0 "register_operand" "=w")
4602 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4605 [(set_attr "type" "f_cvt")]
4608 (define_insn "extendhfdf2"
4609 [(set (match_operand:DF 0 "register_operand" "=w")
4610 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4613 [(set_attr "type" "f_cvt")]
4616 (define_insn "truncdfsf2"
4617 [(set (match_operand:SF 0 "register_operand" "=w")
4618 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4621 [(set_attr "type" "f_cvt")]
4624 (define_insn "truncsfhf2"
4625 [(set (match_operand:HF 0 "register_operand" "=w")
4626 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4629 [(set_attr "type" "f_cvt")]
4632 (define_insn "truncdfhf2"
4633 [(set (match_operand:HF 0 "register_operand" "=w")
4634 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4637 [(set_attr "type" "f_cvt")]
4640 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4641 [(set (match_operand:GPI 0 "register_operand" "=r")
4642 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4644 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4645 [(set_attr "type" "f_cvtf2i")]
4648 (define_insn "<optab><fcvt_target><GPF:mode>2"
4649 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4650 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4653 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4654 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4655 [(set_attr "simd" "yes,no")
4656 (set_attr "fp" "no,yes")
4657 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4660 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4661 [(set (match_operand:GPF 0 "register_operand" "=w")
4662 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4664 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4665 [(set_attr "type" "f_cvti2f")]
4668 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4669 ;; midend will arrange for an SImode conversion to HFmode to first go
4670 ;; through DFmode, then to HFmode. But first it will try converting
4671 ;; to DImode then down, which would match our DImode pattern below and
4672 ;; give very poor code-generation. So, we must provide our own emulation
4673 ;; of the mid-end logic.
4675 (define_insn "aarch64_fp16_<optab><mode>hf2"
4676 [(set (match_operand:HF 0 "register_operand" "=w")
4677 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4679 "<su_optab>cvtf\t%h0, %<w>1"
4680 [(set_attr "type" "f_cvti2f")]
4683 (define_expand "<optab>sihf2"
4684 [(set (match_operand:HF 0 "register_operand")
4685 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4688 if (TARGET_FP_F16INST)
4689 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4692 rtx convert_target = gen_reg_rtx (DFmode);
4693 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4694 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4700 ;; For DImode there is no wide enough floating-point mode that we
4701 ;; can convert through natively (TFmode would work, but requires a library
4702 ;; call). However, we know that any value >= 65504 will be rounded
4703 ;; to infinity on conversion. This is well within the range of SImode, so
4705 ;; Saturate to SImode.
4706 ;; Convert from that to DFmode
4707 ;; Convert from that to HFmode (phew!).
4708 ;; Note that the saturation to SImode requires the SIMD extensions. If
4709 ;; we ever need to provide this pattern where the SIMD extensions are not
4710 ;; available, we would need a different approach.
4712 (define_expand "<optab>dihf2"
4713 [(set (match_operand:HF 0 "register_operand")
4714 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4715 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4717 if (TARGET_FP_F16INST)
4718 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4721 rtx sat_target = gen_reg_rtx (SImode);
4722 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4723 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4730 ;; Convert between fixed-point and floating-point (scalar modes)
4732 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4733 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4734 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4735 (match_operand:SI 2 "immediate_operand" "i, i")]
4739 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4740 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4741 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4742 (set_attr "fp" "yes, *")
4743 (set_attr "simd" "*, yes")]
4746 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4747 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4748 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4749 (match_operand:SI 2 "immediate_operand" "i, i")]
4753 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4754 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4755 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4756 (set_attr "fp" "yes, *")
4757 (set_attr "simd" "*, yes")]
4760 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4761 [(set (match_operand:GPI 0 "register_operand" "=r")
4762 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4763 (match_operand:SI 2 "immediate_operand" "i")]
4766 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4767 [(set_attr "type" "f_cvtf2i")]
4770 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4771 [(set (match_operand:HF 0 "register_operand" "=w")
4772 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4773 (match_operand:SI 2 "immediate_operand" "i")]
4776 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4777 [(set_attr "type" "f_cvti2f")]
4780 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4781 [(set (match_operand:HI 0 "register_operand" "=w")
4782 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4783 (match_operand:SI 2 "immediate_operand" "i")]
4786 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4787 [(set_attr "type" "neon_fp_to_int_s")]
4790 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4791 [(set (match_operand:HF 0 "register_operand" "=w")
4792 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4793 (match_operand:SI 2 "immediate_operand" "i")]
4796 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4797 [(set_attr "type" "neon_int_to_fp_s")]
4800 ;; -------------------------------------------------------------------
4801 ;; Floating-point arithmetic
4802 ;; -------------------------------------------------------------------
4804 (define_insn "add<mode>3"
4805 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4807 (match_operand:GPF_F16 1 "register_operand" "w")
4808 (match_operand:GPF_F16 2 "register_operand" "w")))]
4810 "fadd\\t%<s>0, %<s>1, %<s>2"
4811 [(set_attr "type" "fadd<stype>")]
4814 (define_insn "sub<mode>3"
4815 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4817 (match_operand:GPF_F16 1 "register_operand" "w")
4818 (match_operand:GPF_F16 2 "register_operand" "w")))]
4820 "fsub\\t%<s>0, %<s>1, %<s>2"
4821 [(set_attr "type" "fadd<stype>")]
4824 (define_insn "mul<mode>3"
4825 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4827 (match_operand:GPF_F16 1 "register_operand" "w")
4828 (match_operand:GPF_F16 2 "register_operand" "w")))]
4830 "fmul\\t%<s>0, %<s>1, %<s>2"
4831 [(set_attr "type" "fmul<stype>")]
4834 (define_insn "*fnmul<mode>3"
4835 [(set (match_operand:GPF 0 "register_operand" "=w")
4837 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4838 (match_operand:GPF 2 "register_operand" "w")))]
4839 "TARGET_FLOAT && !flag_rounding_math"
4840 "fnmul\\t%<s>0, %<s>1, %<s>2"
4841 [(set_attr "type" "fmul<s>")]
4844 (define_insn "*fnmul<mode>3"
4845 [(set (match_operand:GPF 0 "register_operand" "=w")
4847 (match_operand:GPF 1 "register_operand" "w")
4848 (match_operand:GPF 2 "register_operand" "w"))))]
4850 "fnmul\\t%<s>0, %<s>1, %<s>2"
4851 [(set_attr "type" "fmul<s>")]
4854 (define_expand "div<mode>3"
4855 [(set (match_operand:GPF_F16 0 "register_operand")
4856 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4857 (match_operand:GPF_F16 2 "register_operand")))]
4860 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4863 operands[1] = force_reg (<MODE>mode, operands[1]);
4866 (define_insn "*div<mode>3"
4867 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4868 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4869 (match_operand:GPF_F16 2 "register_operand" "w")))]
4871 "fdiv\\t%<s>0, %<s>1, %<s>2"
4872 [(set_attr "type" "fdiv<stype>")]
4875 (define_insn "neg<mode>2"
4876 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4879 "fneg\\t%<s>0, %<s>1"
4880 [(set_attr "type" "ffarith<stype>")]
4883 (define_expand "sqrt<mode>2"
4884 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4885 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4888 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4892 (define_insn "*sqrt<mode>2"
4893 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4894 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4896 "fsqrt\\t%<s>0, %<s>1"
4897 [(set_attr "type" "fsqrt<stype>")]
4900 (define_insn "abs<mode>2"
4901 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4902 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4904 "fabs\\t%<s>0, %<s>1"
4905 [(set_attr "type" "ffarith<stype>")]
4908 ;; Given that smax/smin do not specify the result when either input is NaN,
4909 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4912 (define_insn "smax<mode>3"
4913 [(set (match_operand:GPF 0 "register_operand" "=w")
4914 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4915 (match_operand:GPF 2 "register_operand" "w")))]
4917 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4918 [(set_attr "type" "f_minmax<s>")]
4921 (define_insn "smin<mode>3"
4922 [(set (match_operand:GPF 0 "register_operand" "=w")
4923 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4924 (match_operand:GPF 2 "register_operand" "w")))]
4926 "fminnm\\t%<s>0, %<s>1, %<s>2"
4927 [(set_attr "type" "f_minmax<s>")]
4930 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4931 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4932 ;; which implement the IEEE fmax ()/fmin () functions.
4933 (define_insn "<maxmin_uns><mode>3"
4934 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4935 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4936 (match_operand:GPF_F16 2 "register_operand" "w")]
4939 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4940 [(set_attr "type" "f_minmax<stype>")]
4943 ;; For copysign (x, y), we want to generate:
4945 ;; LDR d2, #(1 << 63)
4946 ;; BSL v2.8b, [y], [x]
4948 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4949 ;; aarch64_simd_bsldf will select the best suited of these instructions
4950 ;; to generate based on register allocation, and knows how to partially
4951 ;; constant fold based on the values of X and Y, so expand through that.
4953 (define_expand "copysigndf3"
4954 [(match_operand:DF 0 "register_operand")
4955 (match_operand:DF 1 "register_operand")
4956 (match_operand:DF 2 "register_operand")]
4957 "TARGET_FLOAT && TARGET_SIMD"
4959 rtx mask = gen_reg_rtx (DImode);
4960 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4961 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4962 operands[2], operands[1]));
4967 ;; As above, but we must first get to a 64-bit value if we wish to use
4968 ;; aarch64_simd_bslv2sf.
4970 (define_expand "copysignsf3"
4971 [(match_operand:SF 0 "register_operand")
4972 (match_operand:SF 1 "register_operand")
4973 (match_operand:SF 2 "register_operand")]
4974 "TARGET_FLOAT && TARGET_SIMD"
4976 rtx mask = gen_reg_rtx (DImode);
4978 /* Juggle modes to get us in to a vector mode for BSL. */
4979 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4980 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4981 rtx tmp = gen_reg_rtx (V2SFmode);
4982 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4983 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4984 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4989 ;; -------------------------------------------------------------------
4991 ;; -------------------------------------------------------------------
4992 ;; Reload Scalar Floating point modes from constant pool.
4993 ;; The AArch64 port doesn't have __int128 constant move support.
4994 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4995 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4996 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4997 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5000 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5001 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5006 ;; Reload Vector modes from constant pool.
5007 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5008 [(set (match_operand:VALL 0 "register_operand" "=w")
5009 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5010 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5013 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5014 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5019 (define_expand "aarch64_reload_mov<mode>"
5020 [(set (match_operand:TX 0 "register_operand" "=w")
5021 (match_operand:TX 1 "register_operand" "w"))
5022 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5026 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5027 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5028 gen_aarch64_movtilow_tilow (op0, op1);
5029 gen_aarch64_movdi_tihigh (operands[2], op1);
5030 gen_aarch64_movtihigh_di (op0, operands[2]);
5035 ;; The following secondary reload helpers patterns are invoked
5036 ;; after or during reload as we don't want these patterns to start
5037 ;; kicking in during the combiner.
5039 (define_insn "aarch64_movdi_<mode>low"
5040 [(set (match_operand:DI 0 "register_operand" "=r")
5041 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5042 (const_int 64) (const_int 0)))]
5043 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5045 [(set_attr "type" "f_mrc")
5046 (set_attr "length" "4")
5049 (define_insn "aarch64_movdi_<mode>high"
5050 [(set (match_operand:DI 0 "register_operand" "=r")
5051 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5052 (const_int 64) (const_int 64)))]
5053 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5054 "fmov\\t%x0, %1.d[1]"
5055 [(set_attr "type" "f_mrc")
5056 (set_attr "length" "4")
5059 (define_insn "aarch64_mov<mode>high_di"
5060 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5061 (const_int 64) (const_int 64))
5062 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5063 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5064 "fmov\\t%0.d[1], %x1"
5065 [(set_attr "type" "f_mcr")
5066 (set_attr "length" "4")
5069 (define_insn "aarch64_mov<mode>low_di"
5070 [(set (match_operand:TX 0 "register_operand" "=w")
5071 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5072 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5074 [(set_attr "type" "f_mcr")
5075 (set_attr "length" "4")
5078 (define_insn "aarch64_movtilow_tilow"
5079 [(set (match_operand:TI 0 "register_operand" "=w")
5081 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5082 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5084 [(set_attr "type" "fmov")
5085 (set_attr "length" "4")
5088 ;; There is a deliberate reason why the parameters of high and lo_sum's
5089 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5090 ;; and lo_sum's to be used with the labels defining the jump tables in
5093 (define_expand "add_losym"
5094 [(set (match_operand 0 "register_operand" "=r")
5095 (lo_sum (match_operand 1 "register_operand" "r")
5096 (match_operand 2 "aarch64_valid_symref" "S")))]
5099 machine_mode mode = GET_MODE (operands[0]);
5101 emit_insn ((mode == DImode
5103 : gen_add_losym_si) (operands[0],
5109 (define_insn "add_losym_<mode>"
5110 [(set (match_operand:P 0 "register_operand" "=r")
5111 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5112 (match_operand 2 "aarch64_valid_symref" "S")))]
5114 "add\\t%<w>0, %<w>1, :lo12:%a2"
5115 [(set_attr "type" "alu_imm")]
5118 (define_insn "ldr_got_small_<mode>"
5119 [(set (match_operand:PTR 0 "register_operand" "=r")
5120 (unspec:PTR [(mem:PTR (lo_sum:PTR
5121 (match_operand:PTR 1 "register_operand" "r")
5122 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5123 UNSPEC_GOTSMALLPIC))]
5125 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5126 [(set_attr "type" "load1")]
5129 (define_insn "ldr_got_small_sidi"
5130 [(set (match_operand:DI 0 "register_operand" "=r")
5132 (unspec:SI [(mem:SI (lo_sum:DI
5133 (match_operand:DI 1 "register_operand" "r")
5134 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5135 UNSPEC_GOTSMALLPIC)))]
5137 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5138 [(set_attr "type" "load1")]
5141 (define_insn "ldr_got_small_28k_<mode>"
5142 [(set (match_operand:PTR 0 "register_operand" "=r")
5143 (unspec:PTR [(mem:PTR (lo_sum:PTR
5144 (match_operand:PTR 1 "register_operand" "r")
5145 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5146 UNSPEC_GOTSMALLPIC28K))]
5148 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5149 [(set_attr "type" "load1")]
5152 (define_insn "ldr_got_small_28k_sidi"
5153 [(set (match_operand:DI 0 "register_operand" "=r")
5155 (unspec:SI [(mem:SI (lo_sum:DI
5156 (match_operand:DI 1 "register_operand" "r")
5157 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5158 UNSPEC_GOTSMALLPIC28K)))]
5160 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5161 [(set_attr "type" "load1")]
5164 (define_insn "ldr_got_tiny"
5165 [(set (match_operand:DI 0 "register_operand" "=r")
5166 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5167 UNSPEC_GOTTINYPIC))]
5170 [(set_attr "type" "load1")]
5173 (define_insn "aarch64_load_tp_hard"
5174 [(set (match_operand:DI 0 "register_operand" "=r")
5175 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5177 "mrs\\t%0, tpidr_el0"
5178 [(set_attr "type" "mrs")]
5181 ;; The TLS ABI specifically requires that the compiler does not schedule
5182 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5183 ;; Therefore we treat the stubs as an atomic sequence.
5184 (define_expand "tlsgd_small_<mode>"
5185 [(parallel [(set (match_operand 0 "register_operand" "")
5186 (call (mem:DI (match_dup 2)) (const_int 1)))
5187 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5188 (clobber (reg:DI LR_REGNUM))])]
5191 operands[2] = aarch64_tls_get_addr ();
5194 (define_insn "*tlsgd_small_<mode>"
5195 [(set (match_operand 0 "register_operand" "")
5196 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5197 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5198 (clobber (reg:DI LR_REGNUM))
5201 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5202 [(set_attr "type" "call")
5203 (set_attr "length" "16")])
5205 (define_insn "tlsie_small_<mode>"
5206 [(set (match_operand:PTR 0 "register_operand" "=r")
5207 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5208 UNSPEC_GOTSMALLTLS))]
5210 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5211 [(set_attr "type" "load1")
5212 (set_attr "length" "8")]
5215 (define_insn "tlsie_small_sidi"
5216 [(set (match_operand:DI 0 "register_operand" "=r")
5218 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5219 UNSPEC_GOTSMALLTLS)))]
5221 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5222 [(set_attr "type" "load1")
5223 (set_attr "length" "8")]
5226 (define_insn "tlsie_tiny_<mode>"
5227 [(set (match_operand:PTR 0 "register_operand" "=&r")
5228 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5229 (match_operand:PTR 2 "register_operand" "r")]
5230 UNSPEC_GOTTINYTLS))]
5232 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5233 [(set_attr "type" "multiple")
5234 (set_attr "length" "8")]
5237 (define_insn "tlsie_tiny_sidi"
5238 [(set (match_operand:DI 0 "register_operand" "=&r")
5240 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5241 (match_operand:DI 2 "register_operand" "r")
5243 UNSPEC_GOTTINYTLS)))]
5245 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5246 [(set_attr "type" "multiple")
5247 (set_attr "length" "8")]
5250 (define_insn "tlsle12_<mode>"
5251 [(set (match_operand:P 0 "register_operand" "=r")
5252 (unspec:P [(match_operand:P 1 "register_operand" "r")
5253 (match_operand 2 "aarch64_tls_le_symref" "S")]
5256 "add\\t%<w>0, %<w>1, #%L2";
5257 [(set_attr "type" "alu_sreg")
5258 (set_attr "length" "4")]
5261 (define_insn "tlsle24_<mode>"
5262 [(set (match_operand:P 0 "register_operand" "=r")
5263 (unspec:P [(match_operand:P 1 "register_operand" "r")
5264 (match_operand 2 "aarch64_tls_le_symref" "S")]
5267 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5268 [(set_attr "type" "multiple")
5269 (set_attr "length" "8")]
5272 (define_insn "tlsle32_<mode>"
5273 [(set (match_operand:P 0 "register_operand" "=r")
5274 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5277 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5278 [(set_attr "type" "multiple")
5279 (set_attr "length" "8")]
5282 (define_insn "tlsle48_<mode>"
5283 [(set (match_operand:P 0 "register_operand" "=r")
5284 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5287 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5288 [(set_attr "type" "multiple")
5289 (set_attr "length" "12")]
5292 (define_insn "tlsdesc_small_<mode>"
5293 [(set (reg:PTR R0_REGNUM)
5294 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5296 (clobber (reg:DI LR_REGNUM))
5297 (clobber (reg:CC CC_REGNUM))
5298 (clobber (match_scratch:DI 1 "=r"))]
5300 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5301 [(set_attr "type" "call")
5302 (set_attr "length" "16")])
5304 (define_insn "stack_tie"
5305 [(set (mem:BLK (scratch))
5306 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5307 (match_operand:DI 1 "register_operand" "rk")]
5311 [(set_attr "length" "0")]
5314 ;; Pointer authentication patterns are always provided. In architecture
5315 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5316 ;; This lets the user write portable software which authenticates pointers
5317 ;; when run on something which implements ARMv8.3-A, and which runs
5318 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5321 ;; Signing/Authenticating R30 using SP as the salt.
5323 (define_insn "<pauth_mnem_prefix>sp"
5324 [(set (reg:DI R30_REGNUM)
5325 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5327 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5330 ;; Signing/Authenticating X17 using X16 as the salt.
5332 (define_insn "<pauth_mnem_prefix>1716"
5333 [(set (reg:DI R17_REGNUM)
5334 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5336 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5339 ;; Stripping the signature in R30.
5341 (define_insn "xpaclri"
5342 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5344 "hint\t7 // xpaclri"
5347 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5348 ;; all of memory. This blocks insns from being moved across this point.
5350 (define_insn "blockage"
5351 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5354 [(set_attr "length" "0")
5355 (set_attr "type" "block")]
5358 (define_insn "probe_stack_range"
5359 [(set (match_operand:DI 0 "register_operand" "=r")
5360 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5361 (match_operand:DI 2 "register_operand" "r")]
5362 UNSPECV_PROBE_STACK_RANGE))]
5365 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5367 [(set_attr "length" "32")]
5370 ;; Named pattern for expanding thread pointer reference.
5371 (define_expand "get_thread_pointerdi"
5372 [(match_operand:DI 0 "register_operand" "=r")]
5375 rtx tmp = aarch64_load_tp (operands[0]);
5376 if (tmp != operands[0])
5377 emit_move_insn (operands[0], tmp);
5381 ;; Named patterns for stack smashing protection.
5382 (define_expand "stack_protect_set"
5383 [(match_operand 0 "memory_operand")
5384 (match_operand 1 "memory_operand")]
5387 machine_mode mode = GET_MODE (operands[0]);
5389 emit_insn ((mode == DImode
5390 ? gen_stack_protect_set_di
5391 : gen_stack_protect_set_si) (operands[0], operands[1]));
5395 (define_insn "stack_protect_set_<mode>"
5396 [(set (match_operand:PTR 0 "memory_operand" "=m")
5397 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5399 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5401 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5402 [(set_attr "length" "12")
5403 (set_attr "type" "multiple")])
5405 (define_expand "stack_protect_test"
5406 [(match_operand 0 "memory_operand")
5407 (match_operand 1 "memory_operand")
5412 machine_mode mode = GET_MODE (operands[0]);
5414 result = gen_reg_rtx(mode);
5416 emit_insn ((mode == DImode
5417 ? gen_stack_protect_test_di
5418 : gen_stack_protect_test_si) (result,
5423 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5424 result, const0_rtx, operands[2]));
5426 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5427 result, const0_rtx, operands[2]));
5431 (define_insn "stack_protect_test_<mode>"
5432 [(set (match_operand:PTR 0 "register_operand" "=r")
5433 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5434 (match_operand:PTR 2 "memory_operand" "m")]
5436 (clobber (match_scratch:PTR 3 "=&r"))]
5438 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5439 [(set_attr "length" "12")
5440 (set_attr "type" "multiple")])
5442 ;; Write Floating-point Control Register.
5443 (define_insn "set_fpcr"
5444 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5447 [(set_attr "type" "mrs")])
5449 ;; Read Floating-point Control Register.
5450 (define_insn "get_fpcr"
5451 [(set (match_operand:SI 0 "register_operand" "=r")
5452 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5455 [(set_attr "type" "mrs")])
5457 ;; Write Floating-point Status Register.
5458 (define_insn "set_fpsr"
5459 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5462 [(set_attr "type" "mrs")])
5464 ;; Read Floating-point Status Register.
5465 (define_insn "get_fpsr"
5466 [(set (match_operand:SI 0 "register_operand" "=r")
5467 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5470 [(set_attr "type" "mrs")])
5473 ;; Define the subtract-one-and-jump insns so loop.c
5474 ;; knows what to generate.
5475 (define_expand "doloop_end"
5476 [(use (match_operand 0 "" "")) ; loop pseudo
5477 (use (match_operand 1 "" ""))] ; label
5478 "optimize > 0 && flag_modulo_sched"
5487 /* Currently SMS relies on the do-loop pattern to recognize loops
5488 where (1) the control part consists of all insns defining and/or
5489 using a certain 'count' register and (2) the loop count can be
5490 adjusted by modifying this register prior to the loop.
5491 ??? The possible introduction of a new block to initialize the
5492 new IV can potentially affect branch optimizations. */
5494 if (GET_MODE (operands[0]) != DImode)
5498 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5500 cmp = XVECEXP (PATTERN (insn), 0, 0);
5501 cc_reg = SET_DEST (cmp);
5502 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5503 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5504 emit_jump_insn (gen_rtx_SET (pc_rtx,
5505 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5511 (include "aarch64-simd.md")
5513 ;; Atomic Operations
5514 (include "atomics.md")
5516 ;; ldp/stp peephole patterns
5517 (include "aarch64-ldpstp.md")