1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
68 (define_c_enum "unspec" [
139 (define_c_enum "unspecv" [
140 UNSPECV_EH_RETURN ; Represent EH_RETURN
141 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
142 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
143 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
144 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
145 UNSPECV_BLOCKAGE ; Represent a blockage
146 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
150 ;; If further include files are added the defintion of MD_INCLUDES
153 (include "constraints.md")
154 (include "predicates.md")
155 (include "iterators.md")
157 ;; -------------------------------------------------------------------
158 ;; Instruction types and attributes
159 ;; -------------------------------------------------------------------
161 ; The "type" attribute is included here from AArch32 backend to be able
162 ; to share pipeline descriptions.
163 (include "../arm/types.md")
165 ;; It is important to set the fp or simd attributes to yes when a pattern
166 ;; alternative uses the FP or SIMD register files, usually signified by use of
167 ;; the 'w' constraint. This will ensure that the alternative will be
168 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
169 ;; architecture extensions. If all the alternatives in a pattern use the
170 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
173 ;; Attribute that specifies whether or not the instruction touches fp
174 ;; registers. When this is set to yes for an alternative, that alternative
175 ;; will be disabled when !TARGET_FLOAT.
176 (define_attr "fp" "no,yes" (const_string "no"))
178 ;; Attribute that specifies whether or not the instruction touches simd
179 ;; registers. When this is set to yes for an alternative, that alternative
180 ;; will be disabled when !TARGET_SIMD.
181 (define_attr "simd" "no,yes" (const_string "no"))
183 (define_attr "length" ""
186 ;; Attribute that controls whether an alternative is enabled or not.
187 ;; Currently it is only used to disable alternatives which touch fp or simd
188 ;; registers when -mgeneral-regs-only is specified.
189 (define_attr "enabled" "no,yes"
191 (and (eq_attr "fp" "yes")
192 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
193 (and (eq_attr "simd" "yes")
194 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
196 ] (const_string "yes")))
198 ;; Attribute that specifies whether we are dealing with a branch to a
199 ;; label that is far away, i.e. further away than the maximum/minimum
200 ;; representable in a signed 21-bits number.
203 (define_attr "far_branch" "" (const_int 0))
205 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
206 ;; no predicated insns.
207 (define_attr "predicated" "yes,no" (const_string "no"))
209 ;; -------------------------------------------------------------------
210 ;; Pipeline descriptions and scheduling
211 ;; -------------------------------------------------------------------
214 (include "aarch64-tune.md")
217 (include "../arm/cortex-a53.md")
218 (include "../arm/cortex-a57.md")
219 (include "../arm/exynos-m1.md")
220 (include "thunderx.md")
221 (include "../arm/xgene1.md")
223 ;; -------------------------------------------------------------------
224 ;; Jumps and other miscellaneous insns
225 ;; -------------------------------------------------------------------
227 (define_insn "indirect_jump"
228 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
231 [(set_attr "type" "branch")]
235 [(set (pc) (label_ref (match_operand 0 "" "")))]
238 [(set_attr "type" "branch")]
241 (define_expand "cbranch<mode>4"
242 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
243 [(match_operand:GPI 1 "register_operand" "")
244 (match_operand:GPI 2 "aarch64_plus_operand" "")])
245 (label_ref (match_operand 3 "" ""))
249 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
251 operands[2] = const0_rtx;
255 (define_expand "cbranch<mode>4"
256 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
257 [(match_operand:GPF 1 "register_operand" "")
258 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
259 (label_ref (match_operand 3 "" ""))
263 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
265 operands[2] = const0_rtx;
269 (define_expand "cbranchcc4"
270 [(set (pc) (if_then_else
271 (match_operator 0 "aarch64_comparison_operator"
272 [(match_operand 1 "cc_register" "")
273 (match_operand 2 "const0_operand")])
274 (label_ref (match_operand 3 "" ""))
279 (define_insn "ccmp<mode>"
280 [(set (match_operand:CC 1 "cc_register" "")
282 (match_operator 4 "aarch64_comparison_operator"
283 [(match_operand 0 "cc_register" "")
286 (match_operand:GPI 2 "register_operand" "r,r,r")
287 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
288 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
291 ccmp\\t%<w>2, %<w>3, %k5, %m4
292 ccmp\\t%<w>2, %3, %k5, %m4
293 ccmn\\t%<w>2, #%n3, %k5, %m4"
294 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
297 (define_insn "fccmp<mode>"
298 [(set (match_operand:CCFP 1 "cc_register" "")
300 (match_operator 4 "aarch64_comparison_operator"
301 [(match_operand 0 "cc_register" "")
304 (match_operand:GPF 2 "register_operand" "w")
305 (match_operand:GPF 3 "register_operand" "w"))
306 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
308 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
309 [(set_attr "type" "fccmp<s>")]
312 (define_insn "fccmpe<mode>"
313 [(set (match_operand:CCFPE 1 "cc_register" "")
315 (match_operator 4 "aarch64_comparison_operator"
316 [(match_operand 0 "cc_register" "")
319 (match_operand:GPF 2 "register_operand" "w")
320 (match_operand:GPF 3 "register_operand" "w"))
321 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
323 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
324 [(set_attr "type" "fccmp<s>")]
327 ;; Expansion of signed mod by a power of 2 using CSNEG.
328 ;; For x0 % n where n is a power of 2 produce:
330 ;; and x0, x0, #(n - 1)
331 ;; and x1, x1, #(n - 1)
332 ;; csneg x0, x0, x1, mi
334 (define_expand "mod<mode>3"
335 [(match_operand:GPI 0 "register_operand" "")
336 (match_operand:GPI 1 "register_operand" "")
337 (match_operand:GPI 2 "const_int_operand" "")]
340 HOST_WIDE_INT val = INTVAL (operands[2]);
343 || exact_log2 (val) <= 0
344 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
347 rtx mask = GEN_INT (val - 1);
349 /* In the special case of x0 % 2 we can do the even shorter:
355 rtx masked = gen_reg_rtx (<MODE>mode);
356 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
357 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
358 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
359 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
363 rtx neg_op = gen_reg_rtx (<MODE>mode);
364 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
366 /* Extract the condition register and mode. */
367 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
368 rtx cc_reg = SET_DEST (cmp);
369 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
371 rtx masked_pos = gen_reg_rtx (<MODE>mode);
372 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
374 rtx masked_neg = gen_reg_rtx (<MODE>mode);
375 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
377 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
378 masked_neg, masked_pos));
383 (define_insn "condjump"
384 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
385 [(match_operand 1 "cc_register" "") (const_int 0)])
386 (label_ref (match_operand 2 "" ""))
390 if (get_attr_length (insn) == 8)
391 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
395 [(set_attr "type" "branch")
397 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
398 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
401 (set (attr "far_branch")
402 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
403 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
408 ;; For a 24-bit immediate CST we can optimize the compare for equality
409 ;; and branch sequence from:
411 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
415 ;; sub x0, x1, #(CST & 0xfff000)
416 ;; subs x0, x0, #(CST & 0x000fff)
418 (define_insn_and_split "*compare_condjump<mode>"
419 [(set (pc) (if_then_else (EQL
420 (match_operand:GPI 0 "register_operand" "r")
421 (match_operand:GPI 1 "aarch64_imm24" "n"))
422 (label_ref:P (match_operand 2 "" ""))
424 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
425 && !aarch64_plus_operand (operands[1], <MODE>mode)
426 && !reload_completed"
431 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
432 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
433 rtx tmp = gen_reg_rtx (<MODE>mode);
434 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
435 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
436 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
437 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
438 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
443 (define_expand "casesi"
444 [(match_operand:SI 0 "register_operand" "") ; Index
445 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
446 (match_operand:SI 2 "const_int_operand" "") ; Total range
447 (match_operand:DI 3 "" "") ; Table label
448 (match_operand:DI 4 "" "")] ; Out of range label
451 if (operands[1] != const0_rtx)
453 rtx reg = gen_reg_rtx (SImode);
455 /* Canonical RTL says that if you have:
459 then this should be emitted as:
463 The use of trunc_int_for_mode ensures that the resulting
464 constant can be represented in SImode, this is important
465 for the corner case where operand[1] is INT_MIN. */
467 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
469 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
470 (operands[1], SImode))
471 operands[1] = force_reg (SImode, operands[1]);
472 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
476 if (!aarch64_plus_operand (operands[2], SImode))
477 operands[2] = force_reg (SImode, operands[2]);
478 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
480 operands[0], operands[2], operands[4]));
482 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
483 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
489 (define_insn "casesi_dispatch"
492 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
493 (match_operand:SI 1 "register_operand" "r")]
495 (clobber (reg:CC CC_REGNUM))
496 (clobber (match_scratch:DI 3 "=r"))
497 (clobber (match_scratch:DI 4 "=r"))
498 (use (label_ref (match_operand 2 "" "")))])]
501 return aarch64_output_casesi (operands);
503 [(set_attr "length" "16")
504 (set_attr "type" "branch")]
508 [(unspec[(const_int 0)] UNSPEC_NOP)]
511 [(set_attr "type" "no_insn")]
514 (define_insn "prefetch"
515 [(prefetch (match_operand:DI 0 "register_operand" "r")
516 (match_operand:QI 1 "const_int_operand" "")
517 (match_operand:QI 2 "const_int_operand" ""))]
520 const char * pftype[2][4] =
522 {"prfm\\tPLDL1STRM, %a0",
523 "prfm\\tPLDL3KEEP, %a0",
524 "prfm\\tPLDL2KEEP, %a0",
525 "prfm\\tPLDL1KEEP, %a0"},
526 {"prfm\\tPSTL1STRM, %a0",
527 "prfm\\tPSTL3KEEP, %a0",
528 "prfm\\tPSTL2KEEP, %a0",
529 "prfm\\tPSTL1KEEP, %a0"},
532 int locality = INTVAL (operands[2]);
534 gcc_assert (IN_RANGE (locality, 0, 3));
536 return pftype[INTVAL(operands[1])][locality];
538 [(set_attr "type" "load1")]
542 [(trap_if (const_int 1) (const_int 8))]
545 [(set_attr "type" "trap")])
547 (define_expand "prologue"
548 [(clobber (const_int 0))]
551 aarch64_expand_prologue ();
556 (define_expand "epilogue"
557 [(clobber (const_int 0))]
560 aarch64_expand_epilogue (false);
565 (define_expand "sibcall_epilogue"
566 [(clobber (const_int 0))]
569 aarch64_expand_epilogue (true);
574 (define_insn "*do_return"
578 [(set_attr "type" "branch")]
581 (define_expand "return"
583 "aarch64_use_return_insn_p ()"
587 (define_insn "simple_return"
591 [(set_attr "type" "branch")]
594 (define_insn "eh_return"
595 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
599 [(set_attr "type" "branch")]
604 [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
607 [(set (match_dup 1) (match_dup 0))]
609 operands[1] = aarch64_final_eh_return_addr ();
613 (define_insn "*cb<optab><mode>1"
614 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
616 (label_ref (match_operand 1 "" ""))
620 if (get_attr_length (insn) == 8)
621 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
623 return "<cbz>\\t%<w>0, %l1";
625 [(set_attr "type" "branch")
627 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
628 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
631 (set (attr "far_branch")
632 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
633 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
638 (define_insn "*tb<optab><mode>1"
639 [(set (pc) (if_then_else
640 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
643 "aarch64_simd_shift_imm_<mode>" "n"))
645 (label_ref (match_operand 2 "" ""))
647 (clobber (reg:CC CC_REGNUM))]
650 if (get_attr_length (insn) == 8)
652 if (get_attr_far_branch (insn) == 1)
653 return aarch64_gen_far_branch (operands, 2, "Ltb",
654 "<inv_tb>\\t%<w>0, %1, ");
657 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
658 return "tst\t%<w>0, %1\;<bcond>\t%l2";
662 return "<tbz>\t%<w>0, %1, %l2";
664 [(set_attr "type" "branch")
666 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
667 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
670 (set (attr "far_branch")
671 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
672 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
678 (define_insn "*cb<optab><mode>1"
679 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
681 (label_ref (match_operand 1 "" ""))
683 (clobber (reg:CC CC_REGNUM))]
686 if (get_attr_length (insn) == 8)
688 if (get_attr_far_branch (insn) == 1)
689 return aarch64_gen_far_branch (operands, 1, "Ltb",
690 "<inv_tb>\\t%<w>0, <sizem1>, ");
694 uint64_t val = ((uint64_t) 1)
695 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
696 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
697 output_asm_insn (buf, operands);
698 return "<bcond>\t%l1";
702 return "<tbz>\t%<w>0, <sizem1>, %l1";
704 [(set_attr "type" "branch")
706 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
707 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
710 (set (attr "far_branch")
711 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
712 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
717 ;; -------------------------------------------------------------------
718 ;; Subroutine calls and sibcalls
719 ;; -------------------------------------------------------------------
721 (define_expand "call_internal"
722 [(parallel [(call (match_operand 0 "memory_operand" "")
723 (match_operand 1 "general_operand" ""))
724 (use (match_operand 2 "" ""))
725 (clobber (reg:DI LR_REGNUM))])])
727 (define_expand "call"
728 [(parallel [(call (match_operand 0 "memory_operand" "")
729 (match_operand 1 "general_operand" ""))
730 (use (match_operand 2 "" ""))
731 (clobber (reg:DI LR_REGNUM))])]
737 /* In an untyped call, we can get NULL for operand 2. */
738 if (operands[2] == NULL)
739 operands[2] = const0_rtx;
741 /* Decide if we should generate indirect calls by loading the
742 64-bit address of the callee into a register before performing
743 the branch-and-link. */
744 callee = XEXP (operands[0], 0);
745 if (GET_CODE (callee) == SYMBOL_REF
746 ? (aarch64_is_long_call_p (callee)
747 || aarch64_is_noplt_call_p (callee))
749 XEXP (operands[0], 0) = force_reg (Pmode, callee);
751 pat = gen_call_internal (operands[0], operands[1], operands[2]);
752 aarch64_emit_call_insn (pat);
757 (define_insn "*call_reg"
758 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
759 (match_operand 1 "" ""))
760 (use (match_operand 2 "" ""))
761 (clobber (reg:DI LR_REGNUM))]
764 [(set_attr "type" "call")]
767 (define_insn "*call_symbol"
768 [(call (mem:DI (match_operand:DI 0 "" ""))
769 (match_operand 1 "" ""))
770 (use (match_operand 2 "" ""))
771 (clobber (reg:DI LR_REGNUM))]
772 "GET_CODE (operands[0]) == SYMBOL_REF
773 && !aarch64_is_long_call_p (operands[0])
774 && !aarch64_is_noplt_call_p (operands[0])"
776 [(set_attr "type" "call")]
779 (define_expand "call_value_internal"
780 [(parallel [(set (match_operand 0 "" "")
781 (call (match_operand 1 "memory_operand" "")
782 (match_operand 2 "general_operand" "")))
783 (use (match_operand 3 "" ""))
784 (clobber (reg:DI LR_REGNUM))])])
786 (define_expand "call_value"
787 [(parallel [(set (match_operand 0 "" "")
788 (call (match_operand 1 "memory_operand" "")
789 (match_operand 2 "general_operand" "")))
790 (use (match_operand 3 "" ""))
791 (clobber (reg:DI LR_REGNUM))])]
797 /* In an untyped call, we can get NULL for operand 3. */
798 if (operands[3] == NULL)
799 operands[3] = const0_rtx;
801 /* Decide if we should generate indirect calls by loading the
802 64-bit address of the callee into a register before performing
803 the branch-and-link. */
804 callee = XEXP (operands[1], 0);
805 if (GET_CODE (callee) == SYMBOL_REF
806 ? (aarch64_is_long_call_p (callee)
807 || aarch64_is_noplt_call_p (callee))
809 XEXP (operands[1], 0) = force_reg (Pmode, callee);
811 pat = gen_call_value_internal (operands[0], operands[1], operands[2],
813 aarch64_emit_call_insn (pat);
818 (define_insn "*call_value_reg"
819 [(set (match_operand 0 "" "")
820 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
821 (match_operand 2 "" "")))
822 (use (match_operand 3 "" ""))
823 (clobber (reg:DI LR_REGNUM))]
826 [(set_attr "type" "call")]
830 (define_insn "*call_value_symbol"
831 [(set (match_operand 0 "" "")
832 (call (mem:DI (match_operand:DI 1 "" ""))
833 (match_operand 2 "" "")))
834 (use (match_operand 3 "" ""))
835 (clobber (reg:DI LR_REGNUM))]
836 "GET_CODE (operands[1]) == SYMBOL_REF
837 && !aarch64_is_long_call_p (operands[1])
838 && !aarch64_is_noplt_call_p (operands[1])"
840 [(set_attr "type" "call")]
843 (define_expand "sibcall_internal"
844 [(parallel [(call (match_operand 0 "memory_operand" "")
845 (match_operand 1 "general_operand" ""))
847 (use (match_operand 2 "" ""))])])
849 (define_expand "sibcall"
850 [(parallel [(call (match_operand 0 "memory_operand" "")
851 (match_operand 1 "general_operand" ""))
853 (use (match_operand 2 "" ""))])]
857 rtx callee = XEXP (operands[0], 0);
859 && ((GET_CODE (callee) != SYMBOL_REF)
860 || aarch64_is_noplt_call_p (callee)))
861 XEXP (operands[0], 0) = force_reg (Pmode, callee);
863 if (operands[2] == NULL_RTX)
864 operands[2] = const0_rtx;
866 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
867 aarch64_emit_call_insn (pat);
872 (define_expand "sibcall_value_internal"
873 [(parallel [(set (match_operand 0 "" "")
874 (call (match_operand 1 "memory_operand" "")
875 (match_operand 2 "general_operand" "")))
877 (use (match_operand 3 "" ""))])])
879 (define_expand "sibcall_value"
880 [(parallel [(set (match_operand 0 "" "")
881 (call (match_operand 1 "memory_operand" "")
882 (match_operand 2 "general_operand" "")))
884 (use (match_operand 3 "" ""))])]
888 rtx callee = XEXP (operands[1], 0);
890 && ((GET_CODE (callee) != SYMBOL_REF)
891 || aarch64_is_noplt_call_p (callee)))
892 XEXP (operands[1], 0) = force_reg (Pmode, callee);
894 if (operands[3] == NULL_RTX)
895 operands[3] = const0_rtx;
897 pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
899 aarch64_emit_call_insn (pat);
904 (define_insn "*sibcall_insn"
905 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
906 (match_operand 1 "" ""))
908 (use (match_operand 2 "" ""))]
909 "SIBLING_CALL_P (insn)"
913 [(set_attr "type" "branch, branch")]
916 (define_insn "*sibcall_value_insn"
917 [(set (match_operand 0 "" "")
919 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
920 (match_operand 2 "" "")))
922 (use (match_operand 3 "" ""))]
923 "SIBLING_CALL_P (insn)"
927 [(set_attr "type" "branch, branch")]
930 ;; Call subroutine returning any type.
932 (define_expand "untyped_call"
933 [(parallel [(call (match_operand 0 "")
936 (match_operand 2 "")])]
941 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
943 for (i = 0; i < XVECLEN (operands[2], 0); i++)
945 rtx set = XVECEXP (operands[2], 0, i);
946 emit_move_insn (SET_DEST (set), SET_SRC (set));
949 /* The optimizer does not know that the call sets the function value
950 registers we stored in the result block. We avoid problems by
951 claiming that all hard registers are used and clobbered at this
953 emit_insn (gen_blockage ());
957 ;; -------------------------------------------------------------------
959 ;; -------------------------------------------------------------------
961 (define_expand "mov<mode>"
962 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
963 (match_operand:SHORT 1 "general_operand" ""))]
966 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
967 operands[1] = force_reg (<MODE>mode, operands[1]);
971 (define_insn "*mov<mode>_aarch64"
972 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
973 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
974 "(register_operand (operands[0], <MODE>mode)
975 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
977 switch (which_alternative)
980 return "mov\t%w0, %w1";
982 return "mov\t%w0, %1";
984 return aarch64_output_scalar_simd_mov_immediate (operands[1],
987 return "ldr<size>\t%w0, %1";
989 return "ldr\t%<size>0, %1";
991 return "str<size>\t%w1, %0";
993 return "str\t%<size>1, %0";
995 return "umov\t%w0, %1.<v>[0]";
997 return "dup\t%0.<Vallxd>, %w1";
999 return "dup\t%<Vetype>0, %1.<v>[0]";
1004 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1005 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1006 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1009 (define_expand "mov<mode>"
1010 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1011 (match_operand:GPI 1 "general_operand" ""))]
1014 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1015 && <MODE>mode == DImode
1016 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1019 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1020 operands[1] = force_reg (<MODE>mode, operands[1]);
1022 /* FIXME: RR we still need to fix up what we are doing with
1023 symbol_refs and other types of constants. */
1024 if (CONSTANT_P (operands[1])
1025 && !CONST_INT_P (operands[1]))
1027 aarch64_expand_mov_immediate (operands[0], operands[1]);
1033 (define_insn_and_split "*movsi_aarch64"
1034 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w")
1035 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1036 "(register_operand (operands[0], SImode)
1037 || aarch64_reg_or_zero (operands[1], SImode))"
1053 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1054 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1057 aarch64_expand_mov_immediate (operands[0], operands[1]);
1060 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1061 adr,adr,f_mcr,f_mrc,fmov")
1062 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1065 (define_insn_and_split "*movdi_aarch64"
1066 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w, r,*w,w")
1067 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1068 "(register_operand (operands[0], DImode)
1069 || aarch64_reg_or_zero (operands[1], DImode))"
1086 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1087 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1090 aarch64_expand_mov_immediate (operands[0], operands[1]);
1093 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1094 adr,adr,f_mcr,f_mrc,fmov,neon_move")
1095 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1096 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1099 (define_insn "insv_imm<mode>"
1100 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1102 (match_operand:GPI 1 "const_int_operand" "n"))
1103 (match_operand:GPI 2 "const_int_operand" "n"))]
1104 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1105 && UINTVAL (operands[1]) % 16 == 0"
1106 "movk\\t%<w>0, %X2, lsl %1"
1107 [(set_attr "type" "mov_imm")]
1110 (define_expand "movti"
1111 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1112 (match_operand:TI 1 "general_operand" ""))]
1115 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1116 operands[1] = force_reg (TImode, operands[1]);
1120 (define_insn "*movti_aarch64"
1121 [(set (match_operand:TI 0
1122 "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
1124 "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
1125 "(register_operand (operands[0], TImode)
1126 || aarch64_reg_or_zero (operands[1], TImode))"
1131 orr\\t%0.16b, %1.16b, %1.16b
1137 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1138 load2,store2,store2,f_loadd,f_stored")
1139 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1140 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1141 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1144 ;; Split a TImode register-register or register-immediate move into
1145 ;; its component DImode pieces, taking care to handle overlapping
1146 ;; source and dest registers.
1148 [(set (match_operand:TI 0 "register_operand" "")
1149 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1150 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1153 aarch64_split_128bit_move (operands[0], operands[1]);
1157 (define_expand "mov<mode>"
1158 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1159 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1164 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1168 if (GET_CODE (operands[0]) == MEM
1169 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1170 && aarch64_float_const_zero_rtx_p (operands[1])))
1171 operands[1] = force_reg (<MODE>mode, operands[1]);
1175 (define_insn "*movhf_aarch64"
1176 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
1177 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
1178 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1179 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1184 mov\\t%0.h[0], %1.h[0]
1190 [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1191 f_loads,f_stores,load1,store1,mov_reg")
1192 (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1195 (define_insn "*movsf_aarch64"
1196 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1197 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1198 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1199 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1211 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1212 f_loads,f_stores,load1,store1,mov_reg")
1213 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1216 (define_insn "*movdf_aarch64"
1217 [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
1218 (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1219 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1220 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1232 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1233 f_loadd,f_stored,load1,store1,mov_reg")
1234 (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1237 (define_insn "*movtf_aarch64"
1238 [(set (match_operand:TF 0
1239 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1241 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1242 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1243 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1245 orr\\t%0.16b, %1.16b, %1.16b
1256 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1257 f_loadd,f_stored,load2,store2,store2")
1258 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1259 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1263 [(set (match_operand:TF 0 "register_operand" "")
1264 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1265 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1268 aarch64_split_128bit_move (operands[0], operands[1]);
1275 ;; 2 is size of move in bytes
1278 (define_expand "movmemdi"
1279 [(match_operand:BLK 0 "memory_operand")
1280 (match_operand:BLK 1 "memory_operand")
1281 (match_operand:DI 2 "immediate_operand")
1282 (match_operand:DI 3 "immediate_operand")]
1285 if (aarch64_expand_movmem (operands))
1291 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1292 ;; fairly lax checking on the second memory operation.
1293 (define_insn "load_pairsi"
1294 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1295 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1296 (set (match_operand:SI 2 "register_operand" "=r,*w")
1297 (match_operand:SI 3 "memory_operand" "m,m"))]
1298 "rtx_equal_p (XEXP (operands[3], 0),
1299 plus_constant (Pmode,
1300 XEXP (operands[1], 0),
1301 GET_MODE_SIZE (SImode)))"
1305 [(set_attr "type" "load2,neon_load1_2reg")
1306 (set_attr "fp" "*,yes")]
1309 (define_insn "load_pairdi"
1310 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1311 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1312 (set (match_operand:DI 2 "register_operand" "=r,*w")
1313 (match_operand:DI 3 "memory_operand" "m,m"))]
1314 "rtx_equal_p (XEXP (operands[3], 0),
1315 plus_constant (Pmode,
1316 XEXP (operands[1], 0),
1317 GET_MODE_SIZE (DImode)))"
1321 [(set_attr "type" "load2,neon_load1_2reg")
1322 (set_attr "fp" "*,yes")]
1326 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1327 ;; fairly lax checking on the second memory operation.
1328 (define_insn "store_pairsi"
1329 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1330 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1331 (set (match_operand:SI 2 "memory_operand" "=m,m")
1332 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1333 "rtx_equal_p (XEXP (operands[2], 0),
1334 plus_constant (Pmode,
1335 XEXP (operands[0], 0),
1336 GET_MODE_SIZE (SImode)))"
1340 [(set_attr "type" "store2,neon_store1_2reg")
1341 (set_attr "fp" "*,yes")]
1344 (define_insn "store_pairdi"
1345 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1346 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1347 (set (match_operand:DI 2 "memory_operand" "=m,m")
1348 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1349 "rtx_equal_p (XEXP (operands[2], 0),
1350 plus_constant (Pmode,
1351 XEXP (operands[0], 0),
1352 GET_MODE_SIZE (DImode)))"
1356 [(set_attr "type" "store2,neon_store1_2reg")
1357 (set_attr "fp" "*,yes")]
1360 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1361 ;; fairly lax checking on the second memory operation.
1362 (define_insn "load_pairsf"
1363 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1364 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1365 (set (match_operand:SF 2 "register_operand" "=w,*r")
1366 (match_operand:SF 3 "memory_operand" "m,m"))]
1367 "rtx_equal_p (XEXP (operands[3], 0),
1368 plus_constant (Pmode,
1369 XEXP (operands[1], 0),
1370 GET_MODE_SIZE (SFmode)))"
1374 [(set_attr "type" "neon_load1_2reg,load2")
1375 (set_attr "fp" "yes,*")]
1378 (define_insn "load_pairdf"
1379 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1380 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1381 (set (match_operand:DF 2 "register_operand" "=w,*r")
1382 (match_operand:DF 3 "memory_operand" "m,m"))]
1383 "rtx_equal_p (XEXP (operands[3], 0),
1384 plus_constant (Pmode,
1385 XEXP (operands[1], 0),
1386 GET_MODE_SIZE (DFmode)))"
1390 [(set_attr "type" "neon_load1_2reg,load2")
1391 (set_attr "fp" "yes,*")]
1394 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1395 ;; fairly lax checking on the second memory operation.
1396 (define_insn "store_pairsf"
1397 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1398 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1399 (set (match_operand:SF 2 "memory_operand" "=m,m")
1400 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1401 "rtx_equal_p (XEXP (operands[2], 0),
1402 plus_constant (Pmode,
1403 XEXP (operands[0], 0),
1404 GET_MODE_SIZE (SFmode)))"
1408 [(set_attr "type" "neon_store1_2reg,store2")
1409 (set_attr "fp" "yes,*")]
1412 (define_insn "store_pairdf"
1413 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1414 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1415 (set (match_operand:DF 2 "memory_operand" "=m,m")
1416 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1417 "rtx_equal_p (XEXP (operands[2], 0),
1418 plus_constant (Pmode,
1419 XEXP (operands[0], 0),
1420 GET_MODE_SIZE (DFmode)))"
1424 [(set_attr "type" "neon_store1_2reg,store2")
1425 (set_attr "fp" "yes,*")]
1428 ;; Load pair with post-index writeback. This is primarily used in function
1430 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1432 [(set (match_operand:P 0 "register_operand" "=k")
1433 (plus:P (match_operand:P 1 "register_operand" "0")
1434 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1435 (set (match_operand:GPI 2 "register_operand" "=r")
1436 (mem:GPI (match_dup 1)))
1437 (set (match_operand:GPI 3 "register_operand" "=r")
1438 (mem:GPI (plus:P (match_dup 1)
1439 (match_operand:P 5 "const_int_operand" "n"))))])]
1440 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1441 "ldp\\t%<w>2, %<w>3, [%1], %4"
1442 [(set_attr "type" "load2")]
1445 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1447 [(set (match_operand:P 0 "register_operand" "=k")
1448 (plus:P (match_operand:P 1 "register_operand" "0")
1449 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1450 (set (match_operand:GPF 2 "register_operand" "=w")
1451 (mem:GPF (match_dup 1)))
1452 (set (match_operand:GPF 3 "register_operand" "=w")
1453 (mem:GPF (plus:P (match_dup 1)
1454 (match_operand:P 5 "const_int_operand" "n"))))])]
1455 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1456 "ldp\\t%<w>2, %<w>3, [%1], %4"
1457 [(set_attr "type" "neon_load1_2reg")]
1460 ;; Store pair with pre-index writeback. This is primarily used in function
1462 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1464 [(set (match_operand:P 0 "register_operand" "=&k")
1465 (plus:P (match_operand:P 1 "register_operand" "0")
1466 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1467 (set (mem:GPI (plus:P (match_dup 0)
1469 (match_operand:GPI 2 "register_operand" "r"))
1470 (set (mem:GPI (plus:P (match_dup 0)
1471 (match_operand:P 5 "const_int_operand" "n")))
1472 (match_operand:GPI 3 "register_operand" "r"))])]
1473 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1474 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1475 [(set_attr "type" "store2")]
1478 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1480 [(set (match_operand:P 0 "register_operand" "=&k")
1481 (plus:P (match_operand:P 1 "register_operand" "0")
1482 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1483 (set (mem:GPF (plus:P (match_dup 0)
1485 (match_operand:GPF 2 "register_operand" "w"))
1486 (set (mem:GPF (plus:P (match_dup 0)
1487 (match_operand:P 5 "const_int_operand" "n")))
1488 (match_operand:GPF 3 "register_operand" "w"))])]
1489 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1490 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1491 [(set_attr "type" "neon_store1_2reg<q>")]
1494 ;; -------------------------------------------------------------------
1495 ;; Sign/Zero extension
1496 ;; -------------------------------------------------------------------
1498 (define_expand "<optab>sidi2"
1499 [(set (match_operand:DI 0 "register_operand")
1500 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1504 (define_insn "*extendsidi2_aarch64"
1505 [(set (match_operand:DI 0 "register_operand" "=r,r")
1506 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1511 [(set_attr "type" "extend,load1")]
1514 (define_insn "*load_pair_extendsidi2_aarch64"
1515 [(set (match_operand:DI 0 "register_operand" "=r")
1516 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1517 (set (match_operand:DI 2 "register_operand" "=r")
1518 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1519 "rtx_equal_p (XEXP (operands[3], 0),
1520 plus_constant (Pmode,
1521 XEXP (operands[1], 0),
1522 GET_MODE_SIZE (SImode)))"
1523 "ldpsw\\t%0, %2, %1"
1524 [(set_attr "type" "load2")]
1527 (define_insn "*zero_extendsidi2_aarch64"
1528 [(set (match_operand:DI 0 "register_operand" "=r,r")
1529 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1534 [(set_attr "type" "extend,load1")]
1537 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1538 [(set (match_operand:DI 0 "register_operand" "=r")
1539 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1540 (set (match_operand:DI 2 "register_operand" "=r")
1541 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1542 "rtx_equal_p (XEXP (operands[3], 0),
1543 plus_constant (Pmode,
1544 XEXP (operands[1], 0),
1545 GET_MODE_SIZE (SImode)))"
1546 "ldp\\t%w0, %w2, %1"
1547 [(set_attr "type" "load2")]
1550 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1551 [(set (match_operand:GPI 0 "register_operand")
1552 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1556 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1557 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1558 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1561 sxt<SHORT:size>\t%<GPI:w>0, %w1
1562 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1563 [(set_attr "type" "extend,load1")]
1566 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1567 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1568 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1571 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1572 ldr<SHORT:size>\t%w0, %1
1573 ldr\t%<SHORT:size>0, %1"
1574 [(set_attr "type" "logic_imm,load1,load1")]
1577 (define_expand "<optab>qihi2"
1578 [(set (match_operand:HI 0 "register_operand")
1579 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1583 (define_insn "*extendqihi2_aarch64"
1584 [(set (match_operand:HI 0 "register_operand" "=r,r")
1585 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1590 [(set_attr "type" "extend,load1")]
1593 (define_insn "*zero_extendqihi2_aarch64"
1594 [(set (match_operand:HI 0 "register_operand" "=r,r")
1595 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1600 [(set_attr "type" "logic_imm,load1")]
1603 ;; -------------------------------------------------------------------
1604 ;; Simple arithmetic
1605 ;; -------------------------------------------------------------------
1607 (define_expand "add<mode>3"
1609 (match_operand:GPI 0 "register_operand" "")
1610 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1611 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1614 /* If operands[1] is a subreg extract the inner RTX. */
1615 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1617 /* If the constant is too large for a single instruction and isn't frame
1618 based, split off the immediate so it is available for CSE. */
1619 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1620 && can_create_pseudo_p ()
1622 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1623 operands[2] = force_reg (<MODE>mode, operands[2]);
1626 (define_insn "*add<mode>3_aarch64"
1628 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1630 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1631 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1634 add\\t%<w>0, %<w>1, %2
1635 add\\t%<w>0, %<w>1, %<w>2
1636 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1637 sub\\t%<w>0, %<w>1, #%n2
1639 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1640 (set_attr "simd" "*,*,yes,*,*")]
1643 ;; zero_extend version of above
1644 (define_insn "*addsi3_aarch64_uxtw"
1646 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1648 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1649 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1654 sub\\t%w0, %w1, #%n2
1656 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1659 ;; If there's a free register, and we can load the constant with a
1660 ;; single instruction, do so. This has a chance to improve scheduling.
1662 [(match_scratch:GPI 3 "r")
1663 (set (match_operand:GPI 0 "register_operand")
1665 (match_operand:GPI 1 "register_operand")
1666 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1667 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1668 [(set (match_dup 3) (match_dup 2))
1669 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1673 [(match_scratch:SI 3 "r")
1674 (set (match_operand:DI 0 "register_operand")
1677 (match_operand:SI 1 "register_operand")
1678 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1679 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1680 [(set (match_dup 3) (match_dup 2))
1681 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1684 ;; After peephole2 has had a chance to run, split any remaining long
1685 ;; additions into two add immediates.
1687 [(set (match_operand:GPI 0 "register_operand")
1689 (match_operand:GPI 1 "register_operand")
1690 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1691 "epilogue_completed"
1692 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1693 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1695 HOST_WIDE_INT i = INTVAL (operands[2]);
1696 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1697 operands[3] = GEN_INT (i - s);
1698 operands[4] = GEN_INT (s);
1703 [(set (match_operand:DI 0 "register_operand")
1706 (match_operand:SI 1 "register_operand")
1707 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1708 "epilogue_completed"
1709 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1710 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1712 HOST_WIDE_INT i = INTVAL (operands[2]);
1713 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1714 operands[3] = GEN_INT (i - s);
1715 operands[4] = GEN_INT (s);
1716 operands[5] = gen_lowpart (SImode, operands[0]);
1720 (define_expand "addti3"
1721 [(set (match_operand:TI 0 "register_operand" "")
1722 (plus:TI (match_operand:TI 1 "register_operand" "")
1723 (match_operand:TI 2 "register_operand" "")))]
1726 rtx low = gen_reg_rtx (DImode);
1727 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1728 gen_lowpart (DImode, operands[2])));
1730 rtx high = gen_reg_rtx (DImode);
1731 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1732 gen_highpart (DImode, operands[2])));
1734 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1735 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1739 (define_insn "add<mode>3_compare0"
1740 [(set (reg:CC_NZ CC_REGNUM)
1742 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1743 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1745 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1746 (plus:GPI (match_dup 1) (match_dup 2)))]
1749 adds\\t%<w>0, %<w>1, %<w>2
1750 adds\\t%<w>0, %<w>1, %2
1751 subs\\t%<w>0, %<w>1, #%n2"
1752 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1755 ;; zero_extend version of above
1756 (define_insn "*addsi3_compare0_uxtw"
1757 [(set (reg:CC_NZ CC_REGNUM)
1759 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1760 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1762 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1763 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1766 adds\\t%w0, %w1, %w2
1768 subs\\t%w0, %w1, #%n2"
1769 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1772 (define_insn "*add<mode>3_compareC_cconly_imm"
1773 [(set (reg:CC_C CC_REGNUM)
1776 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1777 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1781 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1782 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1783 <MODE>mode, operands[1])"
1787 [(set_attr "type" "alus_imm")]
1790 (define_insn "*add<mode>3_compareC_cconly"
1791 [(set (reg:CC_C CC_REGNUM)
1794 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1795 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1796 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1798 "cmn\\t%<w>0, %<w>1"
1799 [(set_attr "type" "alus_sreg")]
1802 (define_insn "*add<mode>3_compareC_imm"
1803 [(set (reg:CC_C CC_REGNUM)
1806 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1807 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1811 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1812 (set (match_operand:GPI 0 "register_operand" "=r,r")
1813 (plus:GPI (match_dup 1) (match_dup 2)))]
1814 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1815 <MODE>mode, operands[2])"
1817 adds\\t%<w>0, %<w>1, %2
1818 subs\\t%<w>0, %<w>1, #%n2"
1819 [(set_attr "type" "alus_imm")]
1822 (define_insn "add<mode>3_compareC"
1823 [(set (reg:CC_C CC_REGNUM)
1826 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1827 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1829 (plus:GPI (match_dup 1) (match_dup 2)))))
1830 (set (match_operand:GPI 0 "register_operand" "=r")
1831 (plus:GPI (match_dup 1) (match_dup 2)))]
1833 "adds\\t%<w>0, %<w>1, %<w>2"
1834 [(set_attr "type" "alus_sreg")]
1837 (define_insn "*adds_shift_imm_<mode>"
1838 [(set (reg:CC_NZ CC_REGNUM)
1840 (plus:GPI (ASHIFT:GPI
1841 (match_operand:GPI 1 "register_operand" "r")
1842 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1843 (match_operand:GPI 3 "register_operand" "r"))
1845 (set (match_operand:GPI 0 "register_operand" "=r")
1846 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1849 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1850 [(set_attr "type" "alus_shift_imm")]
1853 (define_insn "*subs_shift_imm_<mode>"
1854 [(set (reg:CC_NZ CC_REGNUM)
1856 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1858 (match_operand:GPI 2 "register_operand" "r")
1859 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1861 (set (match_operand:GPI 0 "register_operand" "=r")
1862 (minus:GPI (match_dup 1)
1863 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1865 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1866 [(set_attr "type" "alus_shift_imm")]
1869 (define_insn "*adds_mul_imm_<mode>"
1870 [(set (reg:CC_NZ CC_REGNUM)
1873 (match_operand:GPI 1 "register_operand" "r")
1874 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1875 (match_operand:GPI 3 "register_operand" "r"))
1877 (set (match_operand:GPI 0 "register_operand" "=r")
1878 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1881 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1882 [(set_attr "type" "alus_shift_imm")]
1885 (define_insn "*subs_mul_imm_<mode>"
1886 [(set (reg:CC_NZ CC_REGNUM)
1888 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1890 (match_operand:GPI 2 "register_operand" "r")
1891 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1893 (set (match_operand:GPI 0 "register_operand" "=r")
1894 (minus:GPI (match_dup 1)
1895 (mult:GPI (match_dup 2) (match_dup 3))))]
1897 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1898 [(set_attr "type" "alus_shift_imm")]
1901 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1902 [(set (reg:CC_NZ CC_REGNUM)
1905 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1906 (match_operand:GPI 2 "register_operand" "r"))
1908 (set (match_operand:GPI 0 "register_operand" "=r")
1909 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1911 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1912 [(set_attr "type" "alus_ext")]
1915 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1916 [(set (reg:CC_NZ CC_REGNUM)
1918 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1920 (match_operand:ALLX 2 "register_operand" "r")))
1922 (set (match_operand:GPI 0 "register_operand" "=r")
1923 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1925 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1926 [(set_attr "type" "alus_ext")]
1929 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1930 [(set (reg:CC_NZ CC_REGNUM)
1932 (plus:GPI (ashift:GPI
1934 (match_operand:ALLX 1 "register_operand" "r"))
1935 (match_operand 2 "aarch64_imm3" "Ui3"))
1936 (match_operand:GPI 3 "register_operand" "r"))
1938 (set (match_operand:GPI 0 "register_operand" "=rk")
1939 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1943 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1944 [(set_attr "type" "alus_ext")]
1947 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1948 [(set (reg:CC_NZ CC_REGNUM)
1950 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1953 (match_operand:ALLX 2 "register_operand" "r"))
1954 (match_operand 3 "aarch64_imm3" "Ui3")))
1956 (set (match_operand:GPI 0 "register_operand" "=rk")
1957 (minus:GPI (match_dup 1)
1958 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1961 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1962 [(set_attr "type" "alus_ext")]
1965 (define_insn "*adds_<optab><mode>_multp2"
1966 [(set (reg:CC_NZ CC_REGNUM)
1968 (plus:GPI (ANY_EXTRACT:GPI
1969 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1970 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1971 (match_operand 3 "const_int_operand" "n")
1973 (match_operand:GPI 4 "register_operand" "r"))
1975 (set (match_operand:GPI 0 "register_operand" "=r")
1976 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1980 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1981 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1982 [(set_attr "type" "alus_ext")]
1985 (define_insn "*subs_<optab><mode>_multp2"
1986 [(set (reg:CC_NZ CC_REGNUM)
1988 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1990 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1991 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1992 (match_operand 3 "const_int_operand" "n")
1995 (set (match_operand:GPI 0 "register_operand" "=r")
1996 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1997 (mult:GPI (match_dup 1) (match_dup 2))
2000 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2001 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2002 [(set_attr "type" "alus_ext")]
2005 (define_insn "*add<mode>3nr_compare0"
2006 [(set (reg:CC_NZ CC_REGNUM)
2008 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2009 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2016 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2019 (define_insn "*compare_neg<mode>"
2020 [(set (reg:CC_Z CC_REGNUM)
2022 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2023 (match_operand:GPI 1 "register_operand" "r")))]
2025 "cmn\\t%<w>1, %<w>0"
2026 [(set_attr "type" "alus_sreg")]
2029 (define_insn "*add_<shift>_<mode>"
2030 [(set (match_operand:GPI 0 "register_operand" "=r")
2031 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2032 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2033 (match_operand:GPI 3 "register_operand" "r")))]
2035 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2036 [(set_attr "type" "alu_shift_imm")]
2039 ;; zero_extend version of above
2040 (define_insn "*add_<shift>_si_uxtw"
2041 [(set (match_operand:DI 0 "register_operand" "=r")
2043 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2044 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2045 (match_operand:SI 3 "register_operand" "r"))))]
2047 "add\\t%w0, %w3, %w1, <shift> %2"
2048 [(set_attr "type" "alu_shift_imm")]
2051 (define_insn "*add_mul_imm_<mode>"
2052 [(set (match_operand:GPI 0 "register_operand" "=r")
2053 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2054 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2055 (match_operand:GPI 3 "register_operand" "r")))]
2057 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2058 [(set_attr "type" "alu_shift_imm")]
2061 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2062 [(set (match_operand:GPI 0 "register_operand" "=rk")
2063 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2064 (match_operand:GPI 2 "register_operand" "r")))]
2066 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2067 [(set_attr "type" "alu_ext")]
2070 ;; zero_extend version of above
2071 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2072 [(set (match_operand:DI 0 "register_operand" "=rk")
2074 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2075 (match_operand:GPI 2 "register_operand" "r"))))]
2077 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2078 [(set_attr "type" "alu_ext")]
2081 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2082 [(set (match_operand:GPI 0 "register_operand" "=rk")
2083 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2084 (match_operand:ALLX 1 "register_operand" "r"))
2085 (match_operand 2 "aarch64_imm3" "Ui3"))
2086 (match_operand:GPI 3 "register_operand" "r")))]
2088 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2089 [(set_attr "type" "alu_ext")]
2092 ;; zero_extend version of above
2093 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2094 [(set (match_operand:DI 0 "register_operand" "=rk")
2096 (plus:SI (ashift:SI (ANY_EXTEND:SI
2097 (match_operand:SHORT 1 "register_operand" "r"))
2098 (match_operand 2 "aarch64_imm3" "Ui3"))
2099 (match_operand:SI 3 "register_operand" "r"))))]
2101 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2102 [(set_attr "type" "alu_ext")]
2105 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2106 [(set (match_operand:GPI 0 "register_operand" "=rk")
2107 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2108 (match_operand:ALLX 1 "register_operand" "r"))
2109 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2110 (match_operand:GPI 3 "register_operand" "r")))]
2112 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2113 [(set_attr "type" "alu_ext")]
2116 ;; zero_extend version of above
2117 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2118 [(set (match_operand:DI 0 "register_operand" "=rk")
2119 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2120 (match_operand:SHORT 1 "register_operand" "r"))
2121 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2122 (match_operand:SI 3 "register_operand" "r"))))]
2124 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2125 [(set_attr "type" "alu_ext")]
2128 (define_insn "*add_<optab><mode>_multp2"
2129 [(set (match_operand:GPI 0 "register_operand" "=rk")
2130 (plus:GPI (ANY_EXTRACT:GPI
2131 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2132 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2133 (match_operand 3 "const_int_operand" "n")
2135 (match_operand:GPI 4 "register_operand" "r")))]
2136 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2137 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2138 [(set_attr "type" "alu_ext")]
2141 ;; zero_extend version of above
2142 (define_insn "*add_<optab>si_multp2_uxtw"
2143 [(set (match_operand:DI 0 "register_operand" "=rk")
2145 (plus:SI (ANY_EXTRACT:SI
2146 (mult:SI (match_operand:SI 1 "register_operand" "r")
2147 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2148 (match_operand 3 "const_int_operand" "n")
2150 (match_operand:SI 4 "register_operand" "r"))))]
2151 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2152 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2153 [(set_attr "type" "alu_ext")]
2156 (define_expand "add<mode>3_carryin"
2157 [(set (match_operand:GPI 0 "register_operand")
2160 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2161 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2162 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2167 ;; Note that add with carry with two zero inputs is matched by cset,
2168 ;; and that add with carry with one zero input is matched by cinc.
2170 (define_insn "*add<mode>3_carryin"
2171 [(set (match_operand:GPI 0 "register_operand" "=r")
2174 (match_operand:GPI 3 "aarch64_carry_operation" "")
2175 (match_operand:GPI 1 "register_operand" "r"))
2176 (match_operand:GPI 2 "register_operand" "r")))]
2178 "adc\\t%<w>0, %<w>1, %<w>2"
2179 [(set_attr "type" "adc_reg")]
2182 ;; zero_extend version of above
2183 (define_insn "*addsi3_carryin_uxtw"
2184 [(set (match_operand:DI 0 "register_operand" "=r")
2188 (match_operand:SI 3 "aarch64_carry_operation" "")
2189 (match_operand:SI 1 "register_operand" "r"))
2190 (match_operand:SI 2 "register_operand" "r"))))]
2192 "adc\\t%w0, %w1, %w2"
2193 [(set_attr "type" "adc_reg")]
2196 (define_insn "*add_uxt<mode>_shift2"
2197 [(set (match_operand:GPI 0 "register_operand" "=rk")
2199 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2200 (match_operand 2 "aarch64_imm3" "Ui3"))
2201 (match_operand 3 "const_int_operand" "n"))
2202 (match_operand:GPI 4 "register_operand" "r")))]
2203 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2205 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2206 INTVAL (operands[3])));
2207 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2208 [(set_attr "type" "alu_ext")]
2211 ;; zero_extend version of above
2212 (define_insn "*add_uxtsi_shift2_uxtw"
2213 [(set (match_operand:DI 0 "register_operand" "=rk")
2216 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2217 (match_operand 2 "aarch64_imm3" "Ui3"))
2218 (match_operand 3 "const_int_operand" "n"))
2219 (match_operand:SI 4 "register_operand" "r"))))]
2220 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2222 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2223 INTVAL (operands[3])));
2224 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2225 [(set_attr "type" "alu_ext")]
2228 (define_insn "*add_uxt<mode>_multp2"
2229 [(set (match_operand:GPI 0 "register_operand" "=rk")
2231 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2232 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2233 (match_operand 3 "const_int_operand" "n"))
2234 (match_operand:GPI 4 "register_operand" "r")))]
2235 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2237 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2238 INTVAL (operands[3])));
2239 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2240 [(set_attr "type" "alu_ext")]
2243 ;; zero_extend version of above
2244 (define_insn "*add_uxtsi_multp2_uxtw"
2245 [(set (match_operand:DI 0 "register_operand" "=rk")
2248 (mult:SI (match_operand:SI 1 "register_operand" "r")
2249 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2250 (match_operand 3 "const_int_operand" "n"))
2251 (match_operand:SI 4 "register_operand" "r"))))]
2252 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2254 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2255 INTVAL (operands[3])));
2256 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2257 [(set_attr "type" "alu_ext")]
2260 (define_insn "subsi3"
2261 [(set (match_operand:SI 0 "register_operand" "=rk")
2262 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2263 (match_operand:SI 2 "register_operand" "r")))]
2265 "sub\\t%w0, %w1, %w2"
2266 [(set_attr "type" "alu_sreg")]
2269 ;; zero_extend version of above
2270 (define_insn "*subsi3_uxtw"
2271 [(set (match_operand:DI 0 "register_operand" "=rk")
2273 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2274 (match_operand:SI 2 "register_operand" "r"))))]
2276 "sub\\t%w0, %w1, %w2"
2277 [(set_attr "type" "alu_sreg")]
2280 (define_insn "subdi3"
2281 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2282 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2283 (match_operand:DI 2 "register_operand" "r,w")))]
2287 sub\\t%d0, %d1, %d2"
2288 [(set_attr "type" "alu_sreg, neon_sub")
2289 (set_attr "simd" "*,yes")]
2292 (define_expand "subti3"
2293 [(set (match_operand:TI 0 "register_operand" "")
2294 (minus:TI (match_operand:TI 1 "register_operand" "")
2295 (match_operand:TI 2 "register_operand" "")))]
2298 rtx low = gen_reg_rtx (DImode);
2299 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2300 gen_lowpart (DImode, operands[2])));
2302 rtx high = gen_reg_rtx (DImode);
2303 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2304 gen_highpart (DImode, operands[2])));
2306 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2307 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2311 (define_insn "*sub<mode>3_compare0"
2312 [(set (reg:CC_NZ CC_REGNUM)
2313 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2314 (match_operand:GPI 2 "register_operand" "r"))
2316 (set (match_operand:GPI 0 "register_operand" "=r")
2317 (minus:GPI (match_dup 1) (match_dup 2)))]
2319 "subs\\t%<w>0, %<w>1, %<w>2"
2320 [(set_attr "type" "alus_sreg")]
2323 ;; zero_extend version of above
2324 (define_insn "*subsi3_compare0_uxtw"
2325 [(set (reg:CC_NZ CC_REGNUM)
2326 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2327 (match_operand:SI 2 "register_operand" "r"))
2329 (set (match_operand:DI 0 "register_operand" "=r")
2330 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2332 "subs\\t%w0, %w1, %w2"
2333 [(set_attr "type" "alus_sreg")]
2336 (define_insn "sub<mode>3_compare1"
2337 [(set (reg:CC CC_REGNUM)
2339 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2340 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2341 (set (match_operand:GPI 0 "register_operand" "=r")
2342 (minus:GPI (match_dup 1) (match_dup 2)))]
2344 "subs\\t%<w>0, %<w>1, %<w>2"
2345 [(set_attr "type" "alus_sreg")]
2348 (define_insn "*sub_<shift>_<mode>"
2349 [(set (match_operand:GPI 0 "register_operand" "=r")
2350 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2352 (match_operand:GPI 1 "register_operand" "r")
2353 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2355 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2356 [(set_attr "type" "alu_shift_imm")]
2359 ;; zero_extend version of above
2360 (define_insn "*sub_<shift>_si_uxtw"
2361 [(set (match_operand:DI 0 "register_operand" "=r")
2363 (minus:SI (match_operand:SI 3 "register_operand" "r")
2365 (match_operand:SI 1 "register_operand" "r")
2366 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2368 "sub\\t%w0, %w3, %w1, <shift> %2"
2369 [(set_attr "type" "alu_shift_imm")]
2372 (define_insn "*sub_mul_imm_<mode>"
2373 [(set (match_operand:GPI 0 "register_operand" "=r")
2374 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2376 (match_operand:GPI 1 "register_operand" "r")
2377 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2379 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2380 [(set_attr "type" "alu_shift_imm")]
2383 ;; zero_extend version of above
2384 (define_insn "*sub_mul_imm_si_uxtw"
2385 [(set (match_operand:DI 0 "register_operand" "=r")
2387 (minus:SI (match_operand:SI 3 "register_operand" "r")
2389 (match_operand:SI 1 "register_operand" "r")
2390 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2392 "sub\\t%w0, %w3, %w1, lsl %p2"
2393 [(set_attr "type" "alu_shift_imm")]
2396 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2397 [(set (match_operand:GPI 0 "register_operand" "=rk")
2398 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2400 (match_operand:ALLX 2 "register_operand" "r"))))]
2402 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2403 [(set_attr "type" "alu_ext")]
2406 ;; zero_extend version of above
2407 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2408 [(set (match_operand:DI 0 "register_operand" "=rk")
2410 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2412 (match_operand:SHORT 2 "register_operand" "r")))))]
2414 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2415 [(set_attr "type" "alu_ext")]
2418 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2419 [(set (match_operand:GPI 0 "register_operand" "=rk")
2420 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2421 (ashift:GPI (ANY_EXTEND:GPI
2422 (match_operand:ALLX 2 "register_operand" "r"))
2423 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2425 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2426 [(set_attr "type" "alu_ext")]
2429 ;; zero_extend version of above
2430 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2431 [(set (match_operand:DI 0 "register_operand" "=rk")
2433 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2434 (ashift:SI (ANY_EXTEND:SI
2435 (match_operand:SHORT 2 "register_operand" "r"))
2436 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2438 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2439 [(set_attr "type" "alu_ext")]
2442 (define_insn "*sub_<optab><mode>_multp2"
2443 [(set (match_operand:GPI 0 "register_operand" "=rk")
2444 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2446 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2447 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2448 (match_operand 3 "const_int_operand" "n")
2450 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2451 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2452 [(set_attr "type" "alu_ext")]
2455 ;; zero_extend version of above
2456 (define_insn "*sub_<optab>si_multp2_uxtw"
2457 [(set (match_operand:DI 0 "register_operand" "=rk")
2459 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2461 (mult:SI (match_operand:SI 1 "register_operand" "r")
2462 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2463 (match_operand 3 "const_int_operand" "n")
2465 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2466 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2467 [(set_attr "type" "alu_ext")]
2470 ;; The hardware description is op1 + ~op2 + C.
2471 ;; = op1 + (-op2 + 1) + (1 - !C)
2472 ;; = op1 - op2 - 1 + 1 - !C
2473 ;; = op1 - op2 - !C.
2474 ;; We describe the latter.
2476 (define_insn "*sub<mode>3_carryin0"
2477 [(set (match_operand:GPI 0 "register_operand" "=r")
2479 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2480 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2482 "sbc\\t%<w>0, %<w>1, <w>zr"
2483 [(set_attr "type" "adc_reg")]
2486 ;; zero_extend version of the above
2487 (define_insn "*subsi3_carryin_uxtw"
2488 [(set (match_operand:DI 0 "register_operand" "=r")
2491 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2492 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2494 "sbc\\t%w0, %w1, wzr"
2495 [(set_attr "type" "adc_reg")]
2498 (define_expand "sub<mode>3_carryin"
2499 [(set (match_operand:GPI 0 "register_operand")
2502 (match_operand:GPI 1 "aarch64_reg_or_zero")
2503 (match_operand:GPI 2 "register_operand"))
2504 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2509 (define_insn "*sub<mode>3_carryin"
2510 [(set (match_operand:GPI 0 "register_operand" "=r")
2513 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2514 (match_operand:GPI 2 "register_operand" "r"))
2515 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2518 "sbc\\t%<w>0, %<w>1, %<w>2"
2519 [(set_attr "type" "adc_reg")]
2522 ;; zero_extend version of the above
2523 (define_insn "*subsi3_carryin_uxtw"
2524 [(set (match_operand:DI 0 "register_operand" "=r")
2528 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2529 (match_operand:SI 2 "register_operand" "r"))
2530 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2533 "sbc\\t%w0, %w1, %w2"
2534 [(set_attr "type" "adc_reg")]
2537 (define_insn "*sub<mode>3_carryin_alt"
2538 [(set (match_operand:GPI 0 "register_operand" "=r")
2541 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2542 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2543 (match_operand:GPI 2 "register_operand" "r")))]
2545 "sbc\\t%<w>0, %<w>1, %<w>2"
2546 [(set_attr "type" "adc_reg")]
2549 ;; zero_extend version of the above
2550 (define_insn "*subsi3_carryin_alt_uxtw"
2551 [(set (match_operand:DI 0 "register_operand" "=r")
2555 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2556 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2557 (match_operand:SI 2 "register_operand" "r"))))]
2559 "sbc\\t%w0, %w1, %w2"
2560 [(set_attr "type" "adc_reg")]
2563 (define_insn "*sub_uxt<mode>_shift2"
2564 [(set (match_operand:GPI 0 "register_operand" "=rk")
2565 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2567 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2568 (match_operand 2 "aarch64_imm3" "Ui3"))
2569 (match_operand 3 "const_int_operand" "n"))))]
2570 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2572 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2573 INTVAL (operands[3])));
2574 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2575 [(set_attr "type" "alu_ext")]
2578 ;; zero_extend version of above
2579 (define_insn "*sub_uxtsi_shift2_uxtw"
2580 [(set (match_operand:DI 0 "register_operand" "=rk")
2582 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2584 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2585 (match_operand 2 "aarch64_imm3" "Ui3"))
2586 (match_operand 3 "const_int_operand" "n")))))]
2587 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2589 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2590 INTVAL (operands[3])));
2591 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2592 [(set_attr "type" "alu_ext")]
2595 (define_insn "*sub_uxt<mode>_multp2"
2596 [(set (match_operand:GPI 0 "register_operand" "=rk")
2597 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2599 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2600 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2601 (match_operand 3 "const_int_operand" "n"))))]
2602 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2604 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2605 INTVAL (operands[3])));
2606 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2607 [(set_attr "type" "alu_ext")]
2610 ;; zero_extend version of above
2611 (define_insn "*sub_uxtsi_multp2_uxtw"
2612 [(set (match_operand:DI 0 "register_operand" "=rk")
2614 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2616 (mult:SI (match_operand:SI 1 "register_operand" "r")
2617 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2618 (match_operand 3 "const_int_operand" "n")))))]
2619 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2621 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2622 INTVAL (operands[3])));
2623 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2624 [(set_attr "type" "alu_ext")]
2627 (define_expand "abs<mode>2"
2628 [(match_operand:GPI 0 "register_operand" "")
2629 (match_operand:GPI 1 "register_operand" "")]
2632 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2633 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2634 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2639 (define_insn "neg<mode>2"
2640 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2641 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2645 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2646 [(set_attr "type" "alu_sreg, neon_neg<q>")
2647 (set_attr "simd" "*,yes")]
2650 ;; zero_extend version of above
2651 (define_insn "*negsi2_uxtw"
2652 [(set (match_operand:DI 0 "register_operand" "=r")
2653 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2656 [(set_attr "type" "alu_sreg")]
2659 (define_insn "*ngc<mode>"
2660 [(set (match_operand:GPI 0 "register_operand" "=r")
2662 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2663 (match_operand:GPI 1 "register_operand" "r")))]
2665 "ngc\\t%<w>0, %<w>1"
2666 [(set_attr "type" "adc_reg")]
2669 (define_insn "*ngcsi_uxtw"
2670 [(set (match_operand:DI 0 "register_operand" "=r")
2673 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2674 (match_operand:SI 1 "register_operand" "r"))))]
2677 [(set_attr "type" "adc_reg")]
2680 (define_insn "neg<mode>2_compare0"
2681 [(set (reg:CC_NZ CC_REGNUM)
2682 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2684 (set (match_operand:GPI 0 "register_operand" "=r")
2685 (neg:GPI (match_dup 1)))]
2687 "negs\\t%<w>0, %<w>1"
2688 [(set_attr "type" "alus_sreg")]
2691 ;; zero_extend version of above
2692 (define_insn "*negsi2_compare0_uxtw"
2693 [(set (reg:CC_NZ CC_REGNUM)
2694 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2696 (set (match_operand:DI 0 "register_operand" "=r")
2697 (zero_extend:DI (neg:SI (match_dup 1))))]
2700 [(set_attr "type" "alus_sreg")]
2703 (define_insn "*neg_<shift><mode>3_compare0"
2704 [(set (reg:CC_NZ CC_REGNUM)
2706 (neg:GPI (ASHIFT:GPI
2707 (match_operand:GPI 1 "register_operand" "r")
2708 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2710 (set (match_operand:GPI 0 "register_operand" "=r")
2711 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2713 "negs\\t%<w>0, %<w>1, <shift> %2"
2714 [(set_attr "type" "alus_shift_imm")]
2717 (define_insn "*neg_<shift>_<mode>2"
2718 [(set (match_operand:GPI 0 "register_operand" "=r")
2719 (neg:GPI (ASHIFT:GPI
2720 (match_operand:GPI 1 "register_operand" "r")
2721 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2723 "neg\\t%<w>0, %<w>1, <shift> %2"
2724 [(set_attr "type" "alu_shift_imm")]
2727 ;; zero_extend version of above
2728 (define_insn "*neg_<shift>_si2_uxtw"
2729 [(set (match_operand:DI 0 "register_operand" "=r")
2732 (match_operand:SI 1 "register_operand" "r")
2733 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2735 "neg\\t%w0, %w1, <shift> %2"
2736 [(set_attr "type" "alu_shift_imm")]
2739 (define_insn "*neg_mul_imm_<mode>2"
2740 [(set (match_operand:GPI 0 "register_operand" "=r")
2742 (match_operand:GPI 1 "register_operand" "r")
2743 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2745 "neg\\t%<w>0, %<w>1, lsl %p2"
2746 [(set_attr "type" "alu_shift_imm")]
2749 ;; zero_extend version of above
2750 (define_insn "*neg_mul_imm_si2_uxtw"
2751 [(set (match_operand:DI 0 "register_operand" "=r")
2754 (match_operand:SI 1 "register_operand" "r")
2755 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2757 "neg\\t%w0, %w1, lsl %p2"
2758 [(set_attr "type" "alu_shift_imm")]
2761 (define_insn "mul<mode>3"
2762 [(set (match_operand:GPI 0 "register_operand" "=r")
2763 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2764 (match_operand:GPI 2 "register_operand" "r")))]
2766 "mul\\t%<w>0, %<w>1, %<w>2"
2767 [(set_attr "type" "mul")]
2770 ;; zero_extend version of above
2771 (define_insn "*mulsi3_uxtw"
2772 [(set (match_operand:DI 0 "register_operand" "=r")
2774 (mult:SI (match_operand:SI 1 "register_operand" "r")
2775 (match_operand:SI 2 "register_operand" "r"))))]
2777 "mul\\t%w0, %w1, %w2"
2778 [(set_attr "type" "mul")]
2781 (define_insn "madd<mode>"
2782 [(set (match_operand:GPI 0 "register_operand" "=r")
2783 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2784 (match_operand:GPI 2 "register_operand" "r"))
2785 (match_operand:GPI 3 "register_operand" "r")))]
2787 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2788 [(set_attr "type" "mla")]
2791 ;; zero_extend version of above
2792 (define_insn "*maddsi_uxtw"
2793 [(set (match_operand:DI 0 "register_operand" "=r")
2795 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2796 (match_operand:SI 2 "register_operand" "r"))
2797 (match_operand:SI 3 "register_operand" "r"))))]
2799 "madd\\t%w0, %w1, %w2, %w3"
2800 [(set_attr "type" "mla")]
2803 (define_insn "*msub<mode>"
2804 [(set (match_operand:GPI 0 "register_operand" "=r")
2805 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2806 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2807 (match_operand:GPI 2 "register_operand" "r"))))]
2810 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2811 [(set_attr "type" "mla")]
2814 ;; zero_extend version of above
2815 (define_insn "*msubsi_uxtw"
2816 [(set (match_operand:DI 0 "register_operand" "=r")
2818 (minus:SI (match_operand:SI 3 "register_operand" "r")
2819 (mult:SI (match_operand:SI 1 "register_operand" "r")
2820 (match_operand:SI 2 "register_operand" "r")))))]
2823 "msub\\t%w0, %w1, %w2, %w3"
2824 [(set_attr "type" "mla")]
2827 (define_insn "*mul<mode>_neg"
2828 [(set (match_operand:GPI 0 "register_operand" "=r")
2829 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2830 (match_operand:GPI 2 "register_operand" "r")))]
2833 "mneg\\t%<w>0, %<w>1, %<w>2"
2834 [(set_attr "type" "mul")]
2837 ;; zero_extend version of above
2838 (define_insn "*mulsi_neg_uxtw"
2839 [(set (match_operand:DI 0 "register_operand" "=r")
2841 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2842 (match_operand:SI 2 "register_operand" "r"))))]
2845 "mneg\\t%w0, %w1, %w2"
2846 [(set_attr "type" "mul")]
2849 (define_insn "<su_optab>mulsidi3"
2850 [(set (match_operand:DI 0 "register_operand" "=r")
2851 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2852 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2854 "<su>mull\\t%0, %w1, %w2"
2855 [(set_attr "type" "<su>mull")]
2858 (define_insn "<su_optab>maddsidi4"
2859 [(set (match_operand:DI 0 "register_operand" "=r")
2861 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2862 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2863 (match_operand:DI 3 "register_operand" "r")))]
2865 "<su>maddl\\t%0, %w1, %w2, %3"
2866 [(set_attr "type" "<su>mlal")]
2869 (define_insn "<su_optab>msubsidi4"
2870 [(set (match_operand:DI 0 "register_operand" "=r")
2872 (match_operand:DI 3 "register_operand" "r")
2873 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2875 (match_operand:SI 2 "register_operand" "r")))))]
2877 "<su>msubl\\t%0, %w1, %w2, %3"
2878 [(set_attr "type" "<su>mlal")]
2881 (define_insn "*<su_optab>mulsidi_neg"
2882 [(set (match_operand:DI 0 "register_operand" "=r")
2884 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2885 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2887 "<su>mnegl\\t%0, %w1, %w2"
2888 [(set_attr "type" "<su>mull")]
2891 (define_expand "<su_optab>mulditi3"
2892 [(set (match_operand:TI 0 "register_operand")
2893 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2894 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2897 rtx low = gen_reg_rtx (DImode);
2898 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2900 rtx high = gen_reg_rtx (DImode);
2901 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2903 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2904 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2908 ;; The default expansion of multi3 using umuldi3_highpart will perform
2909 ;; the additions in an order that fails to combine into two madd insns.
2910 (define_expand "multi3"
2911 [(set (match_operand:TI 0 "register_operand")
2912 (mult:TI (match_operand:TI 1 "register_operand")
2913 (match_operand:TI 2 "register_operand")))]
2916 rtx l0 = gen_reg_rtx (DImode);
2917 rtx l1 = gen_lowpart (DImode, operands[1]);
2918 rtx l2 = gen_lowpart (DImode, operands[2]);
2919 rtx h0 = gen_reg_rtx (DImode);
2920 rtx h1 = gen_highpart (DImode, operands[1]);
2921 rtx h2 = gen_highpart (DImode, operands[2]);
2923 emit_insn (gen_muldi3 (l0, l1, l2));
2924 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2925 emit_insn (gen_madddi (h0, h1, l2, h0));
2926 emit_insn (gen_madddi (h0, l1, h2, h0));
2928 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2929 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2933 (define_insn "<su>muldi3_highpart"
2934 [(set (match_operand:DI 0 "register_operand" "=r")
2938 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2939 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2942 "<su>mulh\\t%0, %1, %2"
2943 [(set_attr "type" "<su>mull")]
2946 (define_insn "<su_optab>div<mode>3"
2947 [(set (match_operand:GPI 0 "register_operand" "=r")
2948 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2949 (match_operand:GPI 2 "register_operand" "r")))]
2951 "<su>div\\t%<w>0, %<w>1, %<w>2"
2952 [(set_attr "type" "<su>div")]
2955 ;; zero_extend version of above
2956 (define_insn "*<su_optab>divsi3_uxtw"
2957 [(set (match_operand:DI 0 "register_operand" "=r")
2959 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2960 (match_operand:SI 2 "register_operand" "r"))))]
2962 "<su>div\\t%w0, %w1, %w2"
2963 [(set_attr "type" "<su>div")]
2966 ;; -------------------------------------------------------------------
2968 ;; -------------------------------------------------------------------
2970 (define_insn "cmp<mode>"
2971 [(set (reg:CC CC_REGNUM)
2972 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2973 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2979 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2982 (define_insn "fcmp<mode>"
2983 [(set (reg:CCFP CC_REGNUM)
2984 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2985 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2989 fcmp\\t%<s>0, %<s>1"
2990 [(set_attr "type" "fcmp<s>")]
2993 (define_insn "fcmpe<mode>"
2994 [(set (reg:CCFPE CC_REGNUM)
2995 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2996 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3000 fcmpe\\t%<s>0, %<s>1"
3001 [(set_attr "type" "fcmp<s>")]
3004 (define_insn "*cmp_swp_<shift>_reg<mode>"
3005 [(set (reg:CC_SWP CC_REGNUM)
3006 (compare:CC_SWP (ASHIFT:GPI
3007 (match_operand:GPI 0 "register_operand" "r")
3008 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3009 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3011 "cmp\\t%<w>2, %<w>0, <shift> %1"
3012 [(set_attr "type" "alus_shift_imm")]
3015 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3016 [(set (reg:CC_SWP CC_REGNUM)
3017 (compare:CC_SWP (ANY_EXTEND:GPI
3018 (match_operand:ALLX 0 "register_operand" "r"))
3019 (match_operand:GPI 1 "register_operand" "r")))]
3021 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3022 [(set_attr "type" "alus_ext")]
3025 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3026 [(set (reg:CC_SWP CC_REGNUM)
3027 (compare:CC_SWP (ashift:GPI
3029 (match_operand:ALLX 0 "register_operand" "r"))
3030 (match_operand 1 "aarch64_imm3" "Ui3"))
3031 (match_operand:GPI 2 "register_operand" "r")))]
3033 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3034 [(set_attr "type" "alus_ext")]
3037 ;; -------------------------------------------------------------------
3038 ;; Store-flag and conditional select insns
3039 ;; -------------------------------------------------------------------
3041 (define_expand "cstore<mode>4"
3042 [(set (match_operand:SI 0 "register_operand" "")
3043 (match_operator:SI 1 "aarch64_comparison_operator"
3044 [(match_operand:GPI 2 "register_operand" "")
3045 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3048 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3050 operands[3] = const0_rtx;
3054 (define_expand "cstorecc4"
3055 [(set (match_operand:SI 0 "register_operand")
3056 (match_operator 1 "aarch64_comparison_operator_mode"
3057 [(match_operand 2 "cc_register")
3058 (match_operand 3 "const0_operand")]))]
3061 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3066 (define_expand "cstore<mode>4"
3067 [(set (match_operand:SI 0 "register_operand" "")
3068 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3069 [(match_operand:GPF 2 "register_operand" "")
3070 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3073 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3075 operands[3] = const0_rtx;
3079 (define_insn "aarch64_cstore<mode>"
3080 [(set (match_operand:ALLI 0 "register_operand" "=r")
3081 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3082 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3085 [(set_attr "type" "csel")]
3088 ;; For a 24-bit immediate CST we can optimize the compare for equality
3089 ;; and branch sequence from:
3091 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3094 ;; into the shorter:
3095 ;; sub x0, x1, #(CST & 0xfff000)
3096 ;; subs x0, x0, #(CST & 0x000fff)
3097 ;; cset x2, <ne, eq>.
3098 (define_insn_and_split "*compare_cstore<mode>_insn"
3099 [(set (match_operand:GPI 0 "register_operand" "=r")
3100 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3101 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3102 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3103 && !aarch64_plus_operand (operands[2], <MODE>mode)
3104 && !reload_completed"
3109 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3110 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3111 rtx tmp = gen_reg_rtx (<MODE>mode);
3112 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3113 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3114 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3115 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3116 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3119 [(set_attr "type" "csel")]
3122 ;; zero_extend version of the above
3123 (define_insn "*cstoresi_insn_uxtw"
3124 [(set (match_operand:DI 0 "register_operand" "=r")
3126 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3127 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3130 [(set_attr "type" "csel")]
3133 (define_insn "cstore<mode>_neg"
3134 [(set (match_operand:ALLI 0 "register_operand" "=r")
3135 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3136 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3138 "csetm\\t%<w>0, %m1"
3139 [(set_attr "type" "csel")]
3142 ;; zero_extend version of the above
3143 (define_insn "*cstoresi_neg_uxtw"
3144 [(set (match_operand:DI 0 "register_operand" "=r")
3146 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3147 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3150 [(set_attr "type" "csel")]
3153 (define_expand "cmov<mode>6"
3154 [(set (match_operand:GPI 0 "register_operand" "")
3156 (match_operator 1 "aarch64_comparison_operator"
3157 [(match_operand:GPI 2 "register_operand" "")
3158 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3159 (match_operand:GPI 4 "register_operand" "")
3160 (match_operand:GPI 5 "register_operand" "")))]
3163 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3165 operands[3] = const0_rtx;
3169 (define_expand "cmov<mode>6"
3170 [(set (match_operand:GPF 0 "register_operand" "")
3172 (match_operator 1 "aarch64_comparison_operator"
3173 [(match_operand:GPF 2 "register_operand" "")
3174 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3175 (match_operand:GPF 4 "register_operand" "")
3176 (match_operand:GPF 5 "register_operand" "")))]
3179 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3181 operands[3] = const0_rtx;
3185 (define_insn "*cmov<mode>_insn"
3186 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3188 (match_operator 1 "aarch64_comparison_operator"
3189 [(match_operand 2 "cc_register" "") (const_int 0)])
3190 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3191 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3192 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3193 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3194 ;; Final two alternatives should be unreachable, but included for completeness
3196 csel\\t%<w>0, %<w>3, %<w>4, %m1
3197 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3198 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3199 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3200 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3203 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3206 ;; zero_extend version of above
3207 (define_insn "*cmovsi_insn_uxtw"
3208 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3211 (match_operator 1 "aarch64_comparison_operator"
3212 [(match_operand 2 "cc_register" "") (const_int 0)])
3213 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3214 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3215 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3216 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3217 ;; Final two alternatives should be unreachable, but included for completeness
3219 csel\\t%w0, %w3, %w4, %m1
3220 csinv\\t%w0, %w3, wzr, %m1
3221 csinv\\t%w0, %w4, wzr, %M1
3222 csinc\\t%w0, %w3, wzr, %m1
3223 csinc\\t%w0, %w4, wzr, %M1
3226 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3229 (define_insn "*cmovdi_insn_uxtw"
3230 [(set (match_operand:DI 0 "register_operand" "=r")
3232 (match_operator 1 "aarch64_comparison_operator"
3233 [(match_operand 2 "cc_register" "") (const_int 0)])
3234 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3235 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3237 "csel\\t%w0, %w3, %w4, %m1"
3238 [(set_attr "type" "csel")]
3241 (define_insn "*cmov<mode>_insn"
3242 [(set (match_operand:GPF 0 "register_operand" "=w")
3244 (match_operator 1 "aarch64_comparison_operator"
3245 [(match_operand 2 "cc_register" "") (const_int 0)])
3246 (match_operand:GPF 3 "register_operand" "w")
3247 (match_operand:GPF 4 "register_operand" "w")))]
3249 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3250 [(set_attr "type" "fcsel")]
3253 (define_expand "mov<mode>cc"
3254 [(set (match_operand:ALLI 0 "register_operand" "")
3255 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3256 (match_operand:ALLI 2 "register_operand" "")
3257 (match_operand:ALLI 3 "register_operand" "")))]
3261 enum rtx_code code = GET_CODE (operands[1]);
3263 if (code == UNEQ || code == LTGT)
3266 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3267 XEXP (operands[1], 1));
3268 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3272 (define_expand "mov<GPF:mode><GPI:mode>cc"
3273 [(set (match_operand:GPI 0 "register_operand" "")
3274 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3275 (match_operand:GPF 2 "register_operand" "")
3276 (match_operand:GPF 3 "register_operand" "")))]
3280 enum rtx_code code = GET_CODE (operands[1]);
3282 if (code == UNEQ || code == LTGT)
3285 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3286 XEXP (operands[1], 1));
3287 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3291 (define_expand "mov<mode>cc"
3292 [(set (match_operand:GPF 0 "register_operand" "")
3293 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3294 (match_operand:GPF 2 "register_operand" "")
3295 (match_operand:GPF 3 "register_operand" "")))]
3299 enum rtx_code code = GET_CODE (operands[1]);
3301 if (code == UNEQ || code == LTGT)
3304 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3305 XEXP (operands[1], 1));
3306 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3310 (define_expand "<neg_not_op><mode>cc"
3311 [(set (match_operand:GPI 0 "register_operand" "")
3312 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3313 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3314 (match_operand:GPI 3 "register_operand" "")))]
3318 enum rtx_code code = GET_CODE (operands[1]);
3320 if (code == UNEQ || code == LTGT)
3323 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3324 XEXP (operands[1], 1));
3325 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3329 ;; CRC32 instructions.
3330 (define_insn "aarch64_<crc_variant>"
3331 [(set (match_operand:SI 0 "register_operand" "=r")
3332 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3333 (match_operand:<crc_mode> 2 "register_operand" "r")]
3337 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3338 return "<crc_variant>\\t%w0, %w1, %x2";
3340 return "<crc_variant>\\t%w0, %w1, %w2";
3342 [(set_attr "type" "crc")]
3345 (define_insn "*csinc2<mode>_insn"
3346 [(set (match_operand:GPI 0 "register_operand" "=r")
3347 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3348 (match_operand:GPI 1 "register_operand" "r")))]
3350 "cinc\\t%<w>0, %<w>1, %m2"
3351 [(set_attr "type" "csel")]
3354 (define_insn "csinc3<mode>_insn"
3355 [(set (match_operand:GPI 0 "register_operand" "=r")
3357 (match_operand 1 "aarch64_comparison_operation" "")
3358 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3360 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3362 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3363 [(set_attr "type" "csel")]
3366 (define_insn "*csinv3<mode>_insn"
3367 [(set (match_operand:GPI 0 "register_operand" "=r")
3369 (match_operand 1 "aarch64_comparison_operation" "")
3370 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3371 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3373 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3374 [(set_attr "type" "csel")]
3377 (define_insn "csneg3_uxtw_insn"
3378 [(set (match_operand:DI 0 "register_operand" "=r")
3381 (match_operand 1 "aarch64_comparison_operation" "")
3382 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3383 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3385 "csneg\\t%w0, %w3, %w2, %M1"
3386 [(set_attr "type" "csel")]
3389 (define_insn "csneg3<mode>_insn"
3390 [(set (match_operand:GPI 0 "register_operand" "=r")
3392 (match_operand 1 "aarch64_comparison_operation" "")
3393 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3394 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3396 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3397 [(set_attr "type" "csel")]
3400 ;; -------------------------------------------------------------------
3401 ;; Logical operations
3402 ;; -------------------------------------------------------------------
3405 (define_insn_and_split "*aarch64_and<mode>_imm2"
3406 [(set (match_operand:GPI 0 "register_operand" "=rk")
3407 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3408 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3414 HOST_WIDE_INT val = INTVAL (operands[2]);
3415 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3416 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3418 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3419 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3424 (define_insn "<optab><mode>3"
3425 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3426 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3427 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3430 <logical>\\t%<w>0, %<w>1, %<w>2
3431 <logical>\\t%<w>0, %<w>1, %2
3432 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3433 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3434 (set_attr "simd" "*,*,yes")]
3437 ;; zero_extend version of above
3438 (define_insn "*<optab>si3_uxtw"
3439 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3441 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3442 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3445 <logical>\\t%w0, %w1, %w2
3446 <logical>\\t%w0, %w1, %2"
3447 [(set_attr "type" "logic_reg,logic_imm")]
3450 (define_insn "*and<mode>3_compare0"
3451 [(set (reg:CC_NZ CC_REGNUM)
3453 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3454 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3456 (set (match_operand:GPI 0 "register_operand" "=r,r")
3457 (and:GPI (match_dup 1) (match_dup 2)))]
3460 ands\\t%<w>0, %<w>1, %<w>2
3461 ands\\t%<w>0, %<w>1, %2"
3462 [(set_attr "type" "logics_reg,logics_imm")]
3465 ;; zero_extend version of above
3466 (define_insn "*andsi3_compare0_uxtw"
3467 [(set (reg:CC_NZ CC_REGNUM)
3469 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3470 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3472 (set (match_operand:DI 0 "register_operand" "=r,r")
3473 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3476 ands\\t%w0, %w1, %w2
3477 ands\\t%w0, %w1, %2"
3478 [(set_attr "type" "logics_reg,logics_imm")]
3481 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3482 [(set (reg:CC_NZ CC_REGNUM)
3485 (match_operand:GPI 1 "register_operand" "r")
3486 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3487 (match_operand:GPI 3 "register_operand" "r"))
3489 (set (match_operand:GPI 0 "register_operand" "=r")
3490 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3492 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3493 [(set_attr "type" "logics_shift_imm")]
3496 ;; zero_extend version of above
3497 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3498 [(set (reg:CC_NZ CC_REGNUM)
3501 (match_operand:SI 1 "register_operand" "r")
3502 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3503 (match_operand:SI 3 "register_operand" "r"))
3505 (set (match_operand:DI 0 "register_operand" "=r")
3506 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3509 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3510 [(set_attr "type" "logics_shift_imm")]
3513 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3514 [(set (match_operand:GPI 0 "register_operand" "=r")
3515 (LOGICAL:GPI (SHIFT:GPI
3516 (match_operand:GPI 1 "register_operand" "r")
3517 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3518 (match_operand:GPI 3 "register_operand" "r")))]
3520 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3521 [(set_attr "type" "logic_shift_imm")]
3524 (define_insn "*<optab>_rol<mode>3"
3525 [(set (match_operand:GPI 0 "register_operand" "=r")
3526 (LOGICAL:GPI (rotate:GPI
3527 (match_operand:GPI 1 "register_operand" "r")
3528 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3529 (match_operand:GPI 3 "register_operand" "r")))]
3531 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3532 [(set_attr "type" "logic_shift_imm")]
3535 ;; zero_extend versions of above
3536 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3537 [(set (match_operand:DI 0 "register_operand" "=r")
3539 (LOGICAL:SI (SHIFT:SI
3540 (match_operand:SI 1 "register_operand" "r")
3541 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3542 (match_operand:SI 3 "register_operand" "r"))))]
3544 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3545 [(set_attr "type" "logic_shift_imm")]
3548 (define_insn "*<optab>_rolsi3_uxtw"
3549 [(set (match_operand:DI 0 "register_operand" "=r")
3551 (LOGICAL:SI (rotate:SI
3552 (match_operand:SI 1 "register_operand" "r")
3553 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3554 (match_operand:SI 3 "register_operand" "r"))))]
3556 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3557 [(set_attr "type" "logic_shift_imm")]
3560 (define_insn "one_cmpl<mode>2"
3561 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3562 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3567 [(set_attr "type" "logic_reg,neon_logic")
3568 (set_attr "simd" "*,yes")]
3571 (define_insn "*one_cmpl_<optab><mode>2"
3572 [(set (match_operand:GPI 0 "register_operand" "=r")
3573 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3574 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3576 "mvn\\t%<w>0, %<w>1, <shift> %2"
3577 [(set_attr "type" "logic_shift_imm")]
3580 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3582 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3583 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3584 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3585 (match_operand:GPI 2 "register_operand" "r,w")))]
3588 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3589 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3590 [(set_attr "type" "logic_reg,neon_logic")
3591 (set_attr "simd" "*,yes")]
3594 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3595 [(set (match_operand:DI 0 "register_operand" "=r")
3597 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3598 (match_operand:SI 2 "register_operand" "r"))))]
3600 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3601 [(set_attr "type" "logic_reg")]
3604 (define_insn "*xor_one_cmplsidi3_ze"
3605 [(set (match_operand:DI 0 "register_operand" "=r")
3607 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3608 (match_operand:SI 2 "register_operand" "r")))))]
3610 "eon\\t%w0, %w1, %w2"
3611 [(set_attr "type" "logic_reg")]
3614 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3615 ;; eon does not operate on SIMD registers so the vector variant must be split.
3616 (define_insn_and_split "*xor_one_cmpl<mode>3"
3617 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3618 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3619 (match_operand:GPI 2 "register_operand" "r,w"))))]
3622 eon\\t%<w>0, %<w>1, %<w>2
3624 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3625 [(set (match_operand:GPI 0 "register_operand" "=w")
3626 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3627 (match_operand:GPI 2 "register_operand" "w")))
3628 (set (match_dup 0) (not:GPI (match_dup 0)))]
3630 [(set_attr "type" "logic_reg,multiple")
3631 (set_attr "simd" "*,yes")]
3634 (define_insn "*and_one_cmpl<mode>3_compare0"
3635 [(set (reg:CC_NZ CC_REGNUM)
3638 (match_operand:GPI 1 "register_operand" "r"))
3639 (match_operand:GPI 2 "register_operand" "r"))
3641 (set (match_operand:GPI 0 "register_operand" "=r")
3642 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3644 "bics\\t%<w>0, %<w>2, %<w>1"
3645 [(set_attr "type" "logics_reg")]
3648 ;; zero_extend version of above
3649 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3650 [(set (reg:CC_NZ CC_REGNUM)
3653 (match_operand:SI 1 "register_operand" "r"))
3654 (match_operand:SI 2 "register_operand" "r"))
3656 (set (match_operand:DI 0 "register_operand" "=r")
3657 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3659 "bics\\t%w0, %w2, %w1"
3660 [(set_attr "type" "logics_reg")]
3663 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3664 [(set (reg:CC_NZ CC_REGNUM)
3667 (match_operand:GPI 0 "register_operand" "r"))
3668 (match_operand:GPI 1 "register_operand" "r"))
3671 "bics\\t<w>zr, %<w>1, %<w>0"
3672 [(set_attr "type" "logics_reg")]
3675 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3676 [(set (match_operand:GPI 0 "register_operand" "=r")
3677 (LOGICAL:GPI (not:GPI
3679 (match_operand:GPI 1 "register_operand" "r")
3680 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3681 (match_operand:GPI 3 "register_operand" "r")))]
3683 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3684 [(set_attr "type" "logic_shift_imm")]
3687 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3688 [(set (match_operand:GPI 0 "register_operand" "=r")
3691 (match_operand:GPI 1 "register_operand" "r")
3692 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3693 (match_operand:GPI 3 "register_operand" "r"))))]
3695 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3696 [(set_attr "type" "logic_shift_imm")]
3699 ;; Zero-extend version of the above.
3700 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3701 [(set (match_operand:DI 0 "register_operand" "=r")
3705 (match_operand:SI 1 "register_operand" "r")
3706 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3707 (match_operand:SI 3 "register_operand" "r")))))]
3709 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3710 [(set_attr "type" "logic_shift_imm")]
3713 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3714 [(set (reg:CC_NZ CC_REGNUM)
3718 (match_operand:GPI 1 "register_operand" "r")
3719 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3720 (match_operand:GPI 3 "register_operand" "r"))
3722 (set (match_operand:GPI 0 "register_operand" "=r")
3725 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3727 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3728 [(set_attr "type" "logics_shift_imm")]
3731 ;; zero_extend version of above
3732 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3733 [(set (reg:CC_NZ CC_REGNUM)
3737 (match_operand:SI 1 "register_operand" "r")
3738 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3739 (match_operand:SI 3 "register_operand" "r"))
3741 (set (match_operand:DI 0 "register_operand" "=r")
3742 (zero_extend:DI (and:SI
3744 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3746 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3747 [(set_attr "type" "logics_shift_imm")]
3750 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3751 [(set (reg:CC_NZ CC_REGNUM)
3755 (match_operand:GPI 0 "register_operand" "r")
3756 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3757 (match_operand:GPI 2 "register_operand" "r"))
3760 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3761 [(set_attr "type" "logics_shift_imm")]
3764 (define_insn "clz<mode>2"
3765 [(set (match_operand:GPI 0 "register_operand" "=r")
3766 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3768 "clz\\t%<w>0, %<w>1"
3769 [(set_attr "type" "clz")]
3772 (define_expand "ffs<mode>2"
3773 [(match_operand:GPI 0 "register_operand")
3774 (match_operand:GPI 1 "register_operand")]
3777 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3778 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3780 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3781 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3782 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3787 (define_insn "clrsb<mode>2"
3788 [(set (match_operand:GPI 0 "register_operand" "=r")
3789 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3791 "cls\\t%<w>0, %<w>1"
3792 [(set_attr "type" "clz")]
3795 (define_insn "rbit<mode>2"
3796 [(set (match_operand:GPI 0 "register_operand" "=r")
3797 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3799 "rbit\\t%<w>0, %<w>1"
3800 [(set_attr "type" "rbit")]
3803 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3804 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3805 ;; expression and split after reload to enable scheduling them apart if
3808 (define_insn_and_split "ctz<mode>2"
3809 [(set (match_operand:GPI 0 "register_operand" "=r")
3810 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3816 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3817 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3821 (define_insn "*and<mode>_compare0"
3822 [(set (reg:CC_NZ CC_REGNUM)
3824 (match_operand:SHORT 0 "register_operand" "r")
3827 "tst\\t%<w>0, <short_mask>"
3828 [(set_attr "type" "alus_imm")]
3831 (define_insn "*ands<mode>_compare0"
3832 [(set (reg:CC_NZ CC_REGNUM)
3834 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3836 (set (match_operand:GPI 0 "register_operand" "=r")
3837 (zero_extend:GPI (match_dup 1)))]
3839 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3840 [(set_attr "type" "alus_imm")]
3843 (define_insn "*and<mode>3nr_compare0"
3844 [(set (reg:CC_NZ CC_REGNUM)
3846 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3847 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3853 [(set_attr "type" "logics_reg,logics_imm")]
3856 (define_insn "*and<mode>3nr_compare0_zextract"
3857 [(set (reg:CC_NZ CC_REGNUM)
3859 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3860 (match_operand:GPI 1 "const_int_operand" "n")
3861 (match_operand:GPI 2 "const_int_operand" "n"))
3863 "INTVAL (operands[1]) > 0
3864 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3865 <= GET_MODE_BITSIZE (<MODE>mode))
3866 && aarch64_bitmask_imm (
3867 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3872 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3873 return "tst\\t%<w>0, %1";
3875 [(set_attr "type" "logics_shift_imm")]
3878 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3879 [(set (reg:CC_NZ CC_REGNUM)
3882 (match_operand:GPI 0 "register_operand" "r")
3883 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3884 (match_operand:GPI 2 "register_operand" "r"))
3887 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3888 [(set_attr "type" "logics_shift_imm")]
3891 ;; -------------------------------------------------------------------
3893 ;; -------------------------------------------------------------------
3895 (define_expand "<optab><mode>3"
3896 [(set (match_operand:GPI 0 "register_operand")
3897 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3898 (match_operand:QI 2 "nonmemory_operand")))]
3901 if (CONST_INT_P (operands[2]))
3903 operands[2] = GEN_INT (INTVAL (operands[2])
3904 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3906 if (operands[2] == const0_rtx)
3908 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3915 (define_expand "ashl<mode>3"
3916 [(set (match_operand:SHORT 0 "register_operand")
3917 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3918 (match_operand:QI 2 "const_int_operand")))]
3921 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3923 if (operands[2] == const0_rtx)
3925 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3931 (define_expand "rotr<mode>3"
3932 [(set (match_operand:GPI 0 "register_operand")
3933 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3934 (match_operand:QI 2 "nonmemory_operand")))]
3937 if (CONST_INT_P (operands[2]))
3939 operands[2] = GEN_INT (INTVAL (operands[2])
3940 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3942 if (operands[2] == const0_rtx)
3944 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3951 (define_expand "rotl<mode>3"
3952 [(set (match_operand:GPI 0 "register_operand")
3953 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3954 (match_operand:QI 2 "nonmemory_operand")))]
3957 /* (SZ - cnt) % SZ == -cnt % SZ */
3958 if (CONST_INT_P (operands[2]))
3960 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3961 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3962 if (operands[2] == const0_rtx)
3964 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3969 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3974 ;; Logical left shift using SISD or Integer instruction
3975 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3976 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3978 (match_operand:GPI 1 "register_operand" "r,r,w,w")
3979 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3982 lsl\t%<w>0, %<w>1, %2
3983 lsl\t%<w>0, %<w>1, %<w>2
3984 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3985 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3986 [(set_attr "simd" "no,no,yes,yes")
3987 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3990 ;; Logical right shift using SISD or Integer instruction
3991 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3992 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3994 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3995 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3998 lsr\t%<w>0, %<w>1, %2
3999 lsr\t%<w>0, %<w>1, %<w>2
4000 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4003 [(set_attr "simd" "no,no,yes,yes,yes")
4004 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4008 [(set (match_operand:DI 0 "aarch64_simd_register")
4010 (match_operand:DI 1 "aarch64_simd_register")
4011 (match_operand:QI 2 "aarch64_simd_register")))]
4012 "TARGET_SIMD && reload_completed"
4014 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4016 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4018 operands[3] = gen_lowpart (QImode, operands[0]);
4023 [(set (match_operand:SI 0 "aarch64_simd_register")
4025 (match_operand:SI 1 "aarch64_simd_register")
4026 (match_operand:QI 2 "aarch64_simd_register")))]
4027 "TARGET_SIMD && reload_completed"
4029 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4031 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4033 operands[3] = gen_lowpart (QImode, operands[0]);
4037 ;; Arithmetic right shift using SISD or Integer instruction
4038 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4039 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4041 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4042 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4045 asr\t%<w>0, %<w>1, %2
4046 asr\t%<w>0, %<w>1, %<w>2
4047 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4050 [(set_attr "simd" "no,no,yes,yes,yes")
4051 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4055 [(set (match_operand:DI 0 "aarch64_simd_register")
4057 (match_operand:DI 1 "aarch64_simd_register")
4058 (match_operand:QI 2 "aarch64_simd_register")))]
4059 "TARGET_SIMD && reload_completed"
4061 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4063 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4065 operands[3] = gen_lowpart (QImode, operands[0]);
4070 [(set (match_operand:SI 0 "aarch64_simd_register")
4072 (match_operand:SI 1 "aarch64_simd_register")
4073 (match_operand:QI 2 "aarch64_simd_register")))]
4074 "TARGET_SIMD && reload_completed"
4076 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4078 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4080 operands[3] = gen_lowpart (QImode, operands[0]);
4084 (define_insn "*aarch64_sisd_ushl"
4085 [(set (match_operand:DI 0 "register_operand" "=w")
4086 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4087 (match_operand:QI 2 "register_operand" "w")]
4090 "ushl\t%d0, %d1, %d2"
4091 [(set_attr "simd" "yes")
4092 (set_attr "type" "neon_shift_reg")]
4095 (define_insn "*aarch64_ushl_2s"
4096 [(set (match_operand:SI 0 "register_operand" "=w")
4097 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4098 (match_operand:QI 2 "register_operand" "w")]
4101 "ushl\t%0.2s, %1.2s, %2.2s"
4102 [(set_attr "simd" "yes")
4103 (set_attr "type" "neon_shift_reg")]
4106 (define_insn "*aarch64_sisd_sshl"
4107 [(set (match_operand:DI 0 "register_operand" "=w")
4108 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4109 (match_operand:QI 2 "register_operand" "w")]
4112 "sshl\t%d0, %d1, %d2"
4113 [(set_attr "simd" "yes")
4114 (set_attr "type" "neon_shift_reg")]
4117 (define_insn "*aarch64_sshl_2s"
4118 [(set (match_operand:SI 0 "register_operand" "=w")
4119 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4120 (match_operand:QI 2 "register_operand" "w")]
4123 "sshl\t%0.2s, %1.2s, %2.2s"
4124 [(set_attr "simd" "yes")
4125 (set_attr "type" "neon_shift_reg")]
4128 (define_insn "*aarch64_sisd_neg_qi"
4129 [(set (match_operand:QI 0 "register_operand" "=w")
4130 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4134 [(set_attr "simd" "yes")
4135 (set_attr "type" "neon_neg")]
4139 (define_insn "*ror<mode>3_insn"
4140 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4142 (match_operand:GPI 1 "register_operand" "r,r")
4143 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4146 ror\\t%<w>0, %<w>1, %2
4147 ror\\t%<w>0, %<w>1, %<w>2"
4148 [(set_attr "type" "rotate_imm,shift_reg")]
4151 ;; zero_extend version of above
4152 (define_insn "*<optab>si3_insn_uxtw"
4153 [(set (match_operand:DI 0 "register_operand" "=r,r")
4154 (zero_extend:DI (SHIFT:SI
4155 (match_operand:SI 1 "register_operand" "r,r")
4156 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4159 <shift>\\t%w0, %w1, %2
4160 <shift>\\t%w0, %w1, %w2"
4161 [(set_attr "type" "bfx,shift_reg")]
4164 (define_insn "*<optab><mode>3_insn"
4165 [(set (match_operand:SHORT 0 "register_operand" "=r")
4166 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4167 (match_operand 2 "const_int_operand" "n")))]
4168 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4170 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4171 return "<bfshift>\t%w0, %w1, %2, %3";
4173 [(set_attr "type" "bfx")]
4176 (define_insn "*extr<mode>5_insn"
4177 [(set (match_operand:GPI 0 "register_operand" "=r")
4178 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4179 (match_operand 3 "const_int_operand" "n"))
4180 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4181 (match_operand 4 "const_int_operand" "n"))))]
4182 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4183 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4184 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4185 [(set_attr "type" "rotate_imm")]
4188 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4189 ;; so we have to match both orderings.
4190 (define_insn "*extr<mode>5_insn_alt"
4191 [(set (match_operand:GPI 0 "register_operand" "=r")
4192 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4193 (match_operand 4 "const_int_operand" "n"))
4194 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4195 (match_operand 3 "const_int_operand" "n"))))]
4196 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4197 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4198 == GET_MODE_BITSIZE (<MODE>mode))"
4199 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4200 [(set_attr "type" "rotate_imm")]
4203 ;; zero_extend version of the above
4204 (define_insn "*extrsi5_insn_uxtw"
4205 [(set (match_operand:DI 0 "register_operand" "=r")
4207 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4208 (match_operand 3 "const_int_operand" "n"))
4209 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4210 (match_operand 4 "const_int_operand" "n")))))]
4211 "UINTVAL (operands[3]) < 32 &&
4212 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4213 "extr\\t%w0, %w1, %w2, %4"
4214 [(set_attr "type" "rotate_imm")]
4217 (define_insn "*extrsi5_insn_uxtw_alt"
4218 [(set (match_operand:DI 0 "register_operand" "=r")
4220 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4221 (match_operand 4 "const_int_operand" "n"))
4222 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4223 (match_operand 3 "const_int_operand" "n")))))]
4224 "UINTVAL (operands[3]) < 32 &&
4225 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4226 "extr\\t%w0, %w1, %w2, %4"
4227 [(set_attr "type" "rotate_imm")]
4230 (define_insn "*ror<mode>3_insn"
4231 [(set (match_operand:GPI 0 "register_operand" "=r")
4232 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4233 (match_operand 2 "const_int_operand" "n")))]
4234 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4236 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4237 return "ror\\t%<w>0, %<w>1, %3";
4239 [(set_attr "type" "rotate_imm")]
4242 ;; zero_extend version of the above
4243 (define_insn "*rorsi3_insn_uxtw"
4244 [(set (match_operand:DI 0 "register_operand" "=r")
4246 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4247 (match_operand 2 "const_int_operand" "n"))))]
4248 "UINTVAL (operands[2]) < 32"
4250 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4251 return "ror\\t%w0, %w1, %3";
4253 [(set_attr "type" "rotate_imm")]
4256 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4257 [(set (match_operand:GPI 0 "register_operand" "=r")
4259 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4260 (match_operand 2 "const_int_operand" "n"))))]
4261 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4263 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4264 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4266 [(set_attr "type" "bfx")]
4269 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4270 [(set (match_operand:GPI 0 "register_operand" "=r")
4272 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4273 (match_operand 2 "const_int_operand" "n"))))]
4274 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4276 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4277 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4279 [(set_attr "type" "bfx")]
4282 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4283 [(set (match_operand:GPI 0 "register_operand" "=r")
4285 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4286 (match_operand 2 "const_int_operand" "n"))))]
4287 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4289 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4290 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4292 [(set_attr "type" "bfx")]
4295 ;; -------------------------------------------------------------------
4297 ;; -------------------------------------------------------------------
4299 (define_expand "<optab>"
4300 [(set (match_operand:DI 0 "register_operand" "=r")
4301 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4303 "aarch64_simd_shift_imm_offset_di")
4304 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4307 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4308 1, GET_MODE_BITSIZE (DImode) - 1))
4314 (define_insn "*<optab><mode>"
4315 [(set (match_operand:GPI 0 "register_operand" "=r")
4316 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4318 "aarch64_simd_shift_imm_offset_<mode>" "n")
4320 "aarch64_simd_shift_imm_<mode>" "n")))]
4321 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4322 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4323 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4324 [(set_attr "type" "bfx")]
4327 ;; Bitfield Insert (insv)
4328 (define_expand "insv<mode>"
4329 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4330 (match_operand 1 "const_int_operand")
4331 (match_operand 2 "const_int_operand"))
4332 (match_operand:GPI 3 "general_operand"))]
4335 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4336 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4337 rtx value = operands[3];
4339 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4342 if (CONST_INT_P (value))
4344 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4346 /* Prefer AND/OR for inserting all zeros or all ones. */
4347 if ((UINTVAL (value) & mask) == 0
4348 || (UINTVAL (value) & mask) == mask)
4351 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4352 if (width == 16 && (pos % 16) == 0)
4355 operands[3] = force_reg (<MODE>mode, value);
4358 (define_insn "*insv_reg<mode>"
4359 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4360 (match_operand 1 "const_int_operand" "n")
4361 (match_operand 2 "const_int_operand" "n"))
4362 (match_operand:GPI 3 "register_operand" "r"))]
4363 "!(UINTVAL (operands[1]) == 0
4364 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4365 > GET_MODE_BITSIZE (<MODE>mode)))"
4366 "bfi\\t%<w>0, %<w>3, %2, %1"
4367 [(set_attr "type" "bfm")]
4370 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4371 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4372 (match_operand 1 "const_int_operand" "n")
4373 (match_operand 2 "const_int_operand" "n"))
4374 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4375 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4376 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4377 [(set_attr "type" "bfm")]
4380 (define_insn "*extr_insv_lower_reg<mode>"
4381 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4382 (match_operand 1 "const_int_operand" "n")
4384 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4386 (match_operand 3 "const_int_operand" "n")))]
4387 "!(UINTVAL (operands[1]) == 0
4388 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4389 > GET_MODE_BITSIZE (<MODE>mode)))"
4390 "bfxil\\t%<w>0, %<w>2, %3, %1"
4391 [(set_attr "type" "bfm")]
4394 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4395 [(set (match_operand:GPI 0 "register_operand" "=r")
4396 (ashift:GPI (ANY_EXTEND:GPI
4397 (match_operand:ALLX 1 "register_operand" "r"))
4398 (match_operand 2 "const_int_operand" "n")))]
4399 "UINTVAL (operands[2]) < <GPI:sizen>"
4401 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4402 ? GEN_INT (<ALLX:sizen>)
4403 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4404 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4406 [(set_attr "type" "bfx")]
4409 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4411 (define_insn "*andim_ashift<mode>_bfiz"
4412 [(set (match_operand:GPI 0 "register_operand" "=r")
4413 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4414 (match_operand 2 "const_int_operand" "n"))
4415 (match_operand 3 "const_int_operand" "n")))]
4416 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4417 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4418 [(set_attr "type" "bfx")]
4421 (define_insn "bswap<mode>2"
4422 [(set (match_operand:GPI 0 "register_operand" "=r")
4423 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4425 "rev\\t%<w>0, %<w>1"
4426 [(set_attr "type" "rev")]
4429 (define_insn "bswaphi2"
4430 [(set (match_operand:HI 0 "register_operand" "=r")
4431 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4434 [(set_attr "type" "rev")]
4437 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4438 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4439 ;; each valid permutation.
4441 (define_insn "rev16<mode>2"
4442 [(set (match_operand:GPI 0 "register_operand" "=r")
4443 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4445 (match_operand:GPI 3 "const_int_operand" "n"))
4446 (and:GPI (lshiftrt:GPI (match_dup 1)
4448 (match_operand:GPI 2 "const_int_operand" "n"))))]
4449 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4450 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4451 "rev16\\t%<w>0, %<w>1"
4452 [(set_attr "type" "rev")]
4455 (define_insn "rev16<mode>2_alt"
4456 [(set (match_operand:GPI 0 "register_operand" "=r")
4457 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4459 (match_operand:GPI 2 "const_int_operand" "n"))
4460 (and:GPI (ashift:GPI (match_dup 1)
4462 (match_operand:GPI 3 "const_int_operand" "n"))))]
4463 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4464 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4465 "rev16\\t%<w>0, %<w>1"
4466 [(set_attr "type" "rev")]
4469 ;; zero_extend version of above
4470 (define_insn "*bswapsi2_uxtw"
4471 [(set (match_operand:DI 0 "register_operand" "=r")
4472 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4475 [(set_attr "type" "rev")]
4478 ;; -------------------------------------------------------------------
4479 ;; Floating-point intrinsics
4480 ;; -------------------------------------------------------------------
4482 ;; frint floating-point round to integral standard patterns.
4483 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4485 (define_insn "<frint_pattern><mode>2"
4486 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4487 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4490 "frint<frint_suffix>\\t%<s>0, %<s>1"
4491 [(set_attr "type" "f_rint<stype>")]
4494 ;; frcvt floating-point round to integer and convert standard patterns.
4495 ;; Expands to lbtrunc, lceil, lfloor, lround.
4496 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4497 [(set (match_operand:GPI 0 "register_operand" "=r")
4499 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4502 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4503 [(set_attr "type" "f_cvtf2i")]
4506 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4507 [(set (match_operand:GPI 0 "register_operand" "=r")
4510 (match_operand:GPF 1 "register_operand" "w")
4511 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4513 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4514 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4516 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4518 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4519 output_asm_insn (buf, operands);
4522 [(set_attr "type" "f_cvtf2i")]
4527 (define_insn "fma<mode>4"
4528 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4529 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4530 (match_operand:GPF_F16 2 "register_operand" "w")
4531 (match_operand:GPF_F16 3 "register_operand" "w")))]
4533 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4534 [(set_attr "type" "fmac<stype>")]
4537 (define_insn "fnma<mode>4"
4538 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4540 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4541 (match_operand:GPF_F16 2 "register_operand" "w")
4542 (match_operand:GPF_F16 3 "register_operand" "w")))]
4544 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4545 [(set_attr "type" "fmac<stype>")]
4548 (define_insn "fms<mode>4"
4549 [(set (match_operand:GPF 0 "register_operand" "=w")
4550 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4551 (match_operand:GPF 2 "register_operand" "w")
4552 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4554 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4555 [(set_attr "type" "fmac<s>")]
4558 (define_insn "fnms<mode>4"
4559 [(set (match_operand:GPF 0 "register_operand" "=w")
4560 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4561 (match_operand:GPF 2 "register_operand" "w")
4562 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4564 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4565 [(set_attr "type" "fmac<s>")]
4568 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4569 (define_insn "*fnmadd<mode>4"
4570 [(set (match_operand:GPF 0 "register_operand" "=w")
4571 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4572 (match_operand:GPF 2 "register_operand" "w")
4573 (match_operand:GPF 3 "register_operand" "w"))))]
4574 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4575 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4576 [(set_attr "type" "fmac<s>")]
4579 ;; -------------------------------------------------------------------
4580 ;; Floating-point conversions
4581 ;; -------------------------------------------------------------------
4583 (define_insn "extendsfdf2"
4584 [(set (match_operand:DF 0 "register_operand" "=w")
4585 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4588 [(set_attr "type" "f_cvt")]
4591 (define_insn "extendhfsf2"
4592 [(set (match_operand:SF 0 "register_operand" "=w")
4593 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4596 [(set_attr "type" "f_cvt")]
4599 (define_insn "extendhfdf2"
4600 [(set (match_operand:DF 0 "register_operand" "=w")
4601 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4604 [(set_attr "type" "f_cvt")]
4607 (define_insn "truncdfsf2"
4608 [(set (match_operand:SF 0 "register_operand" "=w")
4609 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4612 [(set_attr "type" "f_cvt")]
4615 (define_insn "truncsfhf2"
4616 [(set (match_operand:HF 0 "register_operand" "=w")
4617 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4620 [(set_attr "type" "f_cvt")]
4623 (define_insn "truncdfhf2"
4624 [(set (match_operand:HF 0 "register_operand" "=w")
4625 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4628 [(set_attr "type" "f_cvt")]
4631 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4632 [(set (match_operand:GPI 0 "register_operand" "=r")
4633 (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4635 "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4636 [(set_attr "type" "f_cvtf2i")]
4639 (define_insn "<optab><fcvt_target><GPF:mode>2"
4640 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4641 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4644 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4645 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4646 [(set_attr "simd" "yes,no")
4647 (set_attr "fp" "no,yes")
4648 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4651 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4652 [(set (match_operand:GPF 0 "register_operand" "=w")
4653 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4655 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4656 [(set_attr "type" "f_cvti2f")]
4659 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4660 ;; midend will arrange for an SImode conversion to HFmode to first go
4661 ;; through DFmode, then to HFmode. But first it will try converting
4662 ;; to DImode then down, which would match our DImode pattern below and
4663 ;; give very poor code-generation. So, we must provide our own emulation
4664 ;; of the mid-end logic.
4666 (define_insn "aarch64_fp16_<optab><mode>hf2"
4667 [(set (match_operand:HF 0 "register_operand" "=w")
4668 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4670 "<su_optab>cvtf\t%h0, %<w>1"
4671 [(set_attr "type" "f_cvti2f")]
4674 (define_expand "<optab>sihf2"
4675 [(set (match_operand:HF 0 "register_operand")
4676 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4679 if (TARGET_FP_F16INST)
4680 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4683 rtx convert_target = gen_reg_rtx (DFmode);
4684 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4685 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4691 ;; For DImode there is no wide enough floating-point mode that we
4692 ;; can convert through natively (TFmode would work, but requires a library
4693 ;; call). However, we know that any value >= 65504 will be rounded
4694 ;; to infinity on conversion. This is well within the range of SImode, so
4696 ;; Saturate to SImode.
4697 ;; Convert from that to DFmode
4698 ;; Convert from that to HFmode (phew!).
4699 ;; Note that the saturation to SImode requires the SIMD extensions. If
4700 ;; we ever need to provide this pattern where the SIMD extensions are not
4701 ;; available, we would need a different approach.
4703 (define_expand "<optab>dihf2"
4704 [(set (match_operand:HF 0 "register_operand")
4705 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4706 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4708 if (TARGET_FP_F16INST)
4709 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4712 rtx sat_target = gen_reg_rtx (SImode);
4713 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4714 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4721 ;; Convert between fixed-point and floating-point (scalar modes)
4723 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4724 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4725 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4726 (match_operand:SI 2 "immediate_operand" "i, i")]
4730 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4731 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4732 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4733 (set_attr "fp" "yes, *")
4734 (set_attr "simd" "*, yes")]
4737 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4738 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4739 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4740 (match_operand:SI 2 "immediate_operand" "i, i")]
4744 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4745 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4746 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4747 (set_attr "fp" "yes, *")
4748 (set_attr "simd" "*, yes")]
4751 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4752 [(set (match_operand:GPI 0 "register_operand" "=r")
4753 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4754 (match_operand:SI 2 "immediate_operand" "i")]
4757 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4758 [(set_attr "type" "f_cvtf2i")]
4761 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4762 [(set (match_operand:HF 0 "register_operand" "=w")
4763 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4764 (match_operand:SI 2 "immediate_operand" "i")]
4767 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4768 [(set_attr "type" "f_cvti2f")]
4771 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4772 [(set (match_operand:HI 0 "register_operand" "=w")
4773 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4774 (match_operand:SI 2 "immediate_operand" "i")]
4777 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4778 [(set_attr "type" "neon_fp_to_int_s")]
4781 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4782 [(set (match_operand:HF 0 "register_operand" "=w")
4783 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4784 (match_operand:SI 2 "immediate_operand" "i")]
4787 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4788 [(set_attr "type" "neon_int_to_fp_s")]
4791 ;; -------------------------------------------------------------------
4792 ;; Floating-point arithmetic
4793 ;; -------------------------------------------------------------------
4795 (define_insn "add<mode>3"
4796 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4798 (match_operand:GPF_F16 1 "register_operand" "w")
4799 (match_operand:GPF_F16 2 "register_operand" "w")))]
4801 "fadd\\t%<s>0, %<s>1, %<s>2"
4802 [(set_attr "type" "fadd<stype>")]
4805 (define_insn "sub<mode>3"
4806 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4808 (match_operand:GPF_F16 1 "register_operand" "w")
4809 (match_operand:GPF_F16 2 "register_operand" "w")))]
4811 "fsub\\t%<s>0, %<s>1, %<s>2"
4812 [(set_attr "type" "fadd<stype>")]
4815 (define_insn "mul<mode>3"
4816 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4818 (match_operand:GPF_F16 1 "register_operand" "w")
4819 (match_operand:GPF_F16 2 "register_operand" "w")))]
4821 "fmul\\t%<s>0, %<s>1, %<s>2"
4822 [(set_attr "type" "fmul<stype>")]
4825 (define_insn "*fnmul<mode>3"
4826 [(set (match_operand:GPF 0 "register_operand" "=w")
4828 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4829 (match_operand:GPF 2 "register_operand" "w")))]
4830 "TARGET_FLOAT && !flag_rounding_math"
4831 "fnmul\\t%<s>0, %<s>1, %<s>2"
4832 [(set_attr "type" "fmul<s>")]
4835 (define_insn "*fnmul<mode>3"
4836 [(set (match_operand:GPF 0 "register_operand" "=w")
4838 (match_operand:GPF 1 "register_operand" "w")
4839 (match_operand:GPF 2 "register_operand" "w"))))]
4841 "fnmul\\t%<s>0, %<s>1, %<s>2"
4842 [(set_attr "type" "fmul<s>")]
4845 (define_expand "div<mode>3"
4846 [(set (match_operand:GPF_F16 0 "register_operand")
4847 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4848 (match_operand:GPF_F16 2 "register_operand")))]
4851 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4854 operands[1] = force_reg (<MODE>mode, operands[1]);
4857 (define_insn "*div<mode>3"
4858 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4859 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4860 (match_operand:GPF_F16 2 "register_operand" "w")))]
4862 "fdiv\\t%<s>0, %<s>1, %<s>2"
4863 [(set_attr "type" "fdiv<stype>")]
4866 (define_insn "neg<mode>2"
4867 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4868 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4870 "fneg\\t%<s>0, %<s>1"
4871 [(set_attr "type" "ffarith<stype>")]
4874 (define_expand "sqrt<mode>2"
4875 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4876 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4879 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4883 (define_insn "*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")))]
4887 "fsqrt\\t%<s>0, %<s>1"
4888 [(set_attr "type" "fsqrt<stype>")]
4891 (define_insn "abs<mode>2"
4892 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4893 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4895 "fabs\\t%<s>0, %<s>1"
4896 [(set_attr "type" "ffarith<stype>")]
4899 ;; Given that smax/smin do not specify the result when either input is NaN,
4900 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4903 (define_insn "smax<mode>3"
4904 [(set (match_operand:GPF 0 "register_operand" "=w")
4905 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4906 (match_operand:GPF 2 "register_operand" "w")))]
4908 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4909 [(set_attr "type" "f_minmax<s>")]
4912 (define_insn "smin<mode>3"
4913 [(set (match_operand:GPF 0 "register_operand" "=w")
4914 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4915 (match_operand:GPF 2 "register_operand" "w")))]
4917 "fminnm\\t%<s>0, %<s>1, %<s>2"
4918 [(set_attr "type" "f_minmax<s>")]
4921 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4922 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4923 ;; which implement the IEEE fmax ()/fmin () functions.
4924 (define_insn "<maxmin_uns><mode>3"
4925 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4926 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4927 (match_operand:GPF_F16 2 "register_operand" "w")]
4930 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4931 [(set_attr "type" "f_minmax<stype>")]
4934 ;; For copysign (x, y), we want to generate:
4936 ;; LDR d2, #(1 << 63)
4937 ;; BSL v2.8b, [y], [x]
4939 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4940 ;; aarch64_simd_bsldf will select the best suited of these instructions
4941 ;; to generate based on register allocation, and knows how to partially
4942 ;; constant fold based on the values of X and Y, so expand through that.
4944 (define_expand "copysigndf3"
4945 [(match_operand:DF 0 "register_operand")
4946 (match_operand:DF 1 "register_operand")
4947 (match_operand:DF 2 "register_operand")]
4948 "TARGET_FLOAT && TARGET_SIMD"
4950 rtx mask = gen_reg_rtx (DImode);
4951 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4952 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4953 operands[2], operands[1]));
4958 ;; As above, but we must first get to a 64-bit value if we wish to use
4959 ;; aarch64_simd_bslv2sf.
4961 (define_expand "copysignsf3"
4962 [(match_operand:SF 0 "register_operand")
4963 (match_operand:SF 1 "register_operand")
4964 (match_operand:SF 2 "register_operand")]
4965 "TARGET_FLOAT && TARGET_SIMD"
4967 rtx mask = gen_reg_rtx (DImode);
4969 /* Juggle modes to get us in to a vector mode for BSL. */
4970 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4971 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4972 rtx tmp = gen_reg_rtx (V2SFmode);
4973 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4974 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4975 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4980 ;; -------------------------------------------------------------------
4982 ;; -------------------------------------------------------------------
4983 ;; Reload Scalar Floating point modes from constant pool.
4984 ;; The AArch64 port doesn't have __int128 constant move support.
4985 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4986 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4987 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4988 (clobber (match_operand:P 2 "register_operand" "=&r"))]
4989 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4991 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4992 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4997 ;; Reload Vector modes from constant pool.
4998 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
4999 [(set (match_operand:VALL 0 "register_operand" "=w")
5000 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5001 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5002 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
5004 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5005 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5010 (define_expand "aarch64_reload_mov<mode>"
5011 [(set (match_operand:TX 0 "register_operand" "=w")
5012 (match_operand:TX 1 "register_operand" "w"))
5013 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5017 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5018 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5019 gen_aarch64_movtilow_tilow (op0, op1);
5020 gen_aarch64_movdi_tihigh (operands[2], op1);
5021 gen_aarch64_movtihigh_di (op0, operands[2]);
5026 ;; The following secondary reload helpers patterns are invoked
5027 ;; after or during reload as we don't want these patterns to start
5028 ;; kicking in during the combiner.
5030 (define_insn "aarch64_movdi_<mode>low"
5031 [(set (match_operand:DI 0 "register_operand" "=r")
5032 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5033 (const_int 64) (const_int 0)))]
5034 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5036 [(set_attr "type" "f_mrc")
5037 (set_attr "length" "4")
5040 (define_insn "aarch64_movdi_<mode>high"
5041 [(set (match_operand:DI 0 "register_operand" "=r")
5042 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5043 (const_int 64) (const_int 64)))]
5044 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5045 "fmov\\t%x0, %1.d[1]"
5046 [(set_attr "type" "f_mrc")
5047 (set_attr "length" "4")
5050 (define_insn "aarch64_mov<mode>high_di"
5051 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5052 (const_int 64) (const_int 64))
5053 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5054 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5055 "fmov\\t%0.d[1], %x1"
5056 [(set_attr "type" "f_mcr")
5057 (set_attr "length" "4")
5060 (define_insn "aarch64_mov<mode>low_di"
5061 [(set (match_operand:TX 0 "register_operand" "=w")
5062 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5063 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5065 [(set_attr "type" "f_mcr")
5066 (set_attr "length" "4")
5069 (define_insn "aarch64_movtilow_tilow"
5070 [(set (match_operand:TI 0 "register_operand" "=w")
5072 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5073 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5075 [(set_attr "type" "fmov")
5076 (set_attr "length" "4")
5079 ;; There is a deliberate reason why the parameters of high and lo_sum's
5080 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5081 ;; and lo_sum's to be used with the labels defining the jump tables in
5084 (define_expand "add_losym"
5085 [(set (match_operand 0 "register_operand" "=r")
5086 (lo_sum (match_operand 1 "register_operand" "r")
5087 (match_operand 2 "aarch64_valid_symref" "S")))]
5090 machine_mode mode = GET_MODE (operands[0]);
5092 emit_insn ((mode == DImode
5094 : gen_add_losym_si) (operands[0],
5100 (define_insn "add_losym_<mode>"
5101 [(set (match_operand:P 0 "register_operand" "=r")
5102 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5103 (match_operand 2 "aarch64_valid_symref" "S")))]
5105 "add\\t%<w>0, %<w>1, :lo12:%a2"
5106 [(set_attr "type" "alu_imm")]
5109 (define_insn "ldr_got_small_<mode>"
5110 [(set (match_operand:PTR 0 "register_operand" "=r")
5111 (unspec:PTR [(mem:PTR (lo_sum:PTR
5112 (match_operand:PTR 1 "register_operand" "r")
5113 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5114 UNSPEC_GOTSMALLPIC))]
5116 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5117 [(set_attr "type" "load1")]
5120 (define_insn "ldr_got_small_sidi"
5121 [(set (match_operand:DI 0 "register_operand" "=r")
5123 (unspec:SI [(mem:SI (lo_sum:DI
5124 (match_operand:DI 1 "register_operand" "r")
5125 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5126 UNSPEC_GOTSMALLPIC)))]
5128 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5129 [(set_attr "type" "load1")]
5132 (define_insn "ldr_got_small_28k_<mode>"
5133 [(set (match_operand:PTR 0 "register_operand" "=r")
5134 (unspec:PTR [(mem:PTR (lo_sum:PTR
5135 (match_operand:PTR 1 "register_operand" "r")
5136 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5137 UNSPEC_GOTSMALLPIC28K))]
5139 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5140 [(set_attr "type" "load1")]
5143 (define_insn "ldr_got_small_28k_sidi"
5144 [(set (match_operand:DI 0 "register_operand" "=r")
5146 (unspec:SI [(mem:SI (lo_sum:DI
5147 (match_operand:DI 1 "register_operand" "r")
5148 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5149 UNSPEC_GOTSMALLPIC28K)))]
5151 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5152 [(set_attr "type" "load1")]
5155 (define_insn "ldr_got_tiny"
5156 [(set (match_operand:DI 0 "register_operand" "=r")
5157 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5158 UNSPEC_GOTTINYPIC))]
5161 [(set_attr "type" "load1")]
5164 (define_insn "aarch64_load_tp_hard"
5165 [(set (match_operand:DI 0 "register_operand" "=r")
5166 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5168 "mrs\\t%0, tpidr_el0"
5169 [(set_attr "type" "mrs")]
5172 ;; The TLS ABI specifically requires that the compiler does not schedule
5173 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5174 ;; Therefore we treat the stubs as an atomic sequence.
5175 (define_expand "tlsgd_small"
5176 [(parallel [(set (match_operand 0 "register_operand" "")
5177 (call (mem:DI (match_dup 2)) (const_int 1)))
5178 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5179 (clobber (reg:DI LR_REGNUM))])]
5182 operands[2] = aarch64_tls_get_addr ();
5185 (define_insn "*tlsgd_small"
5186 [(set (match_operand 0 "register_operand" "")
5187 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5188 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5189 (clobber (reg:DI LR_REGNUM))
5192 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5193 [(set_attr "type" "call")
5194 (set_attr "length" "16")])
5196 (define_insn "tlsie_small_<mode>"
5197 [(set (match_operand:PTR 0 "register_operand" "=r")
5198 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5199 UNSPEC_GOTSMALLTLS))]
5201 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5202 [(set_attr "type" "load1")
5203 (set_attr "length" "8")]
5206 (define_insn "tlsie_small_sidi"
5207 [(set (match_operand:DI 0 "register_operand" "=r")
5209 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5210 UNSPEC_GOTSMALLTLS)))]
5212 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5213 [(set_attr "type" "load1")
5214 (set_attr "length" "8")]
5217 (define_insn "tlsie_tiny_<mode>"
5218 [(set (match_operand:PTR 0 "register_operand" "=&r")
5219 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5220 (match_operand:PTR 2 "register_operand" "r")]
5221 UNSPEC_GOTTINYTLS))]
5223 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5224 [(set_attr "type" "multiple")
5225 (set_attr "length" "8")]
5228 (define_insn "tlsie_tiny_sidi"
5229 [(set (match_operand:DI 0 "register_operand" "=&r")
5231 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5232 (match_operand:DI 2 "register_operand" "r")
5234 UNSPEC_GOTTINYTLS)))]
5236 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5237 [(set_attr "type" "multiple")
5238 (set_attr "length" "8")]
5241 (define_insn "tlsle12_<mode>"
5242 [(set (match_operand:P 0 "register_operand" "=r")
5243 (unspec:P [(match_operand:P 1 "register_operand" "r")
5244 (match_operand 2 "aarch64_tls_le_symref" "S")]
5247 "add\\t%<w>0, %<w>1, #%L2";
5248 [(set_attr "type" "alu_sreg")
5249 (set_attr "length" "4")]
5252 (define_insn "tlsle24_<mode>"
5253 [(set (match_operand:P 0 "register_operand" "=r")
5254 (unspec:P [(match_operand:P 1 "register_operand" "r")
5255 (match_operand 2 "aarch64_tls_le_symref" "S")]
5258 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5259 [(set_attr "type" "multiple")
5260 (set_attr "length" "8")]
5263 (define_insn "tlsle32_<mode>"
5264 [(set (match_operand:P 0 "register_operand" "=r")
5265 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5268 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5269 [(set_attr "type" "multiple")
5270 (set_attr "length" "8")]
5273 (define_insn "tlsle48_<mode>"
5274 [(set (match_operand:P 0 "register_operand" "=r")
5275 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5278 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5279 [(set_attr "type" "multiple")
5280 (set_attr "length" "12")]
5283 (define_insn "tlsdesc_small_<mode>"
5284 [(set (reg:PTR R0_REGNUM)
5285 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5287 (clobber (reg:DI LR_REGNUM))
5288 (clobber (reg:CC CC_REGNUM))
5289 (clobber (match_scratch:DI 1 "=r"))]
5291 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5292 [(set_attr "type" "call")
5293 (set_attr "length" "16")])
5295 (define_insn "stack_tie"
5296 [(set (mem:BLK (scratch))
5297 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5298 (match_operand:DI 1 "register_operand" "rk")]
5302 [(set_attr "length" "0")]
5305 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5306 ;; all of memory. This blocks insns from being moved across this point.
5308 (define_insn "blockage"
5309 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5312 [(set_attr "length" "0")
5313 (set_attr "type" "block")]
5316 (define_insn "probe_stack_range_<PTR:mode>"
5317 [(set (match_operand:PTR 0 "register_operand" "=r")
5318 (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5319 (match_operand:PTR 2 "register_operand" "r")]
5320 UNSPECV_PROBE_STACK_RANGE))]
5323 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5325 [(set_attr "length" "32")]
5328 ;; Named pattern for expanding thread pointer reference.
5329 (define_expand "get_thread_pointerdi"
5330 [(match_operand:DI 0 "register_operand" "=r")]
5333 rtx tmp = aarch64_load_tp (operands[0]);
5334 if (tmp != operands[0])
5335 emit_move_insn (operands[0], tmp);
5339 ;; Named patterns for stack smashing protection.
5340 (define_expand "stack_protect_set"
5341 [(match_operand 0 "memory_operand")
5342 (match_operand 1 "memory_operand")]
5345 machine_mode mode = GET_MODE (operands[0]);
5347 emit_insn ((mode == DImode
5348 ? gen_stack_protect_set_di
5349 : gen_stack_protect_set_si) (operands[0], operands[1]));
5353 (define_insn "stack_protect_set_<mode>"
5354 [(set (match_operand:PTR 0 "memory_operand" "=m")
5355 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5357 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5359 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5360 [(set_attr "length" "12")
5361 (set_attr "type" "multiple")])
5363 (define_expand "stack_protect_test"
5364 [(match_operand 0 "memory_operand")
5365 (match_operand 1 "memory_operand")
5370 machine_mode mode = GET_MODE (operands[0]);
5372 result = gen_reg_rtx(mode);
5374 emit_insn ((mode == DImode
5375 ? gen_stack_protect_test_di
5376 : gen_stack_protect_test_si) (result,
5381 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5382 result, const0_rtx, operands[2]));
5384 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5385 result, const0_rtx, operands[2]));
5389 (define_insn "stack_protect_test_<mode>"
5390 [(set (match_operand:PTR 0 "register_operand" "=r")
5391 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5392 (match_operand:PTR 2 "memory_operand" "m")]
5394 (clobber (match_scratch:PTR 3 "=&r"))]
5396 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5397 [(set_attr "length" "12")
5398 (set_attr "type" "multiple")])
5400 ;; Write Floating-point Control Register.
5401 (define_insn "set_fpcr"
5402 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5405 [(set_attr "type" "mrs")])
5407 ;; Read Floating-point Control Register.
5408 (define_insn "get_fpcr"
5409 [(set (match_operand:SI 0 "register_operand" "=r")
5410 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5413 [(set_attr "type" "mrs")])
5415 ;; Write Floating-point Status Register.
5416 (define_insn "set_fpsr"
5417 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5420 [(set_attr "type" "mrs")])
5422 ;; Read Floating-point Status Register.
5423 (define_insn "get_fpsr"
5424 [(set (match_operand:SI 0 "register_operand" "=r")
5425 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5428 [(set_attr "type" "mrs")])
5431 ;; Define the subtract-one-and-jump insns so loop.c
5432 ;; knows what to generate.
5433 (define_expand "doloop_end"
5434 [(use (match_operand 0 "" "")) ; loop pseudo
5435 (use (match_operand 1 "" ""))] ; label
5436 "optimize > 0 && flag_modulo_sched"
5445 /* Currently SMS relies on the do-loop pattern to recognize loops
5446 where (1) the control part consists of all insns defining and/or
5447 using a certain 'count' register and (2) the loop count can be
5448 adjusted by modifying this register prior to the loop.
5449 ??? The possible introduction of a new block to initialize the
5450 new IV can potentially affect branch optimizations. */
5452 if (GET_MODE (operands[0]) != DImode)
5456 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5458 cmp = XVECEXP (PATTERN (insn), 0, 0);
5459 cc_reg = SET_DEST (cmp);
5460 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5461 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5462 emit_jump_insn (gen_rtx_SET (pc_rtx,
5463 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5469 (include "aarch64-simd.md")
5471 ;; Atomic Operations
5472 (include "atomics.md")
5474 ;; ldp/stp peephole patterns
5475 (include "aarch64-ldpstp.md")