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" [
135 (define_c_enum "unspecv" [
136 UNSPECV_EH_RETURN ; Represent EH_RETURN
137 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
138 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
139 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
140 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
141 UNSPECV_BLOCKAGE ; Represent a blockage
142 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
146 ;; If further include files are added the defintion of MD_INCLUDES
149 (include "constraints.md")
150 (include "predicates.md")
151 (include "iterators.md")
153 ;; -------------------------------------------------------------------
154 ;; Instruction types and attributes
155 ;; -------------------------------------------------------------------
157 ; The "type" attribute is included here from AArch32 backend to be able
158 ; to share pipeline descriptions.
159 (include "../arm/types.md")
161 ;; It is important to set the fp or simd attributes to yes when a pattern
162 ;; alternative uses the FP or SIMD register files, usually signified by use of
163 ;; the 'w' constraint. This will ensure that the alternative will be
164 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
165 ;; architecture extensions. If all the alternatives in a pattern use the
166 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
169 ;; Attribute that specifies whether or not the instruction touches fp
170 ;; registers. When this is set to yes for an alternative, that alternative
171 ;; will be disabled when !TARGET_FLOAT.
172 (define_attr "fp" "no,yes" (const_string "no"))
174 ;; Attribute that specifies whether or not the instruction touches simd
175 ;; registers. When this is set to yes for an alternative, that alternative
176 ;; will be disabled when !TARGET_SIMD.
177 (define_attr "simd" "no,yes" (const_string "no"))
179 (define_attr "length" ""
182 ;; Attribute that controls whether an alternative is enabled or not.
183 ;; Currently it is only used to disable alternatives which touch fp or simd
184 ;; registers when -mgeneral-regs-only is specified.
185 (define_attr "enabled" "no,yes"
187 (and (eq_attr "fp" "yes")
188 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
189 (and (eq_attr "simd" "yes")
190 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
192 ] (const_string "yes")))
194 ;; Attribute that specifies whether we are dealing with a branch to a
195 ;; label that is far away, i.e. further away than the maximum/minimum
196 ;; representable in a signed 21-bits number.
199 (define_attr "far_branch" "" (const_int 0))
201 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
202 ;; no predicated insns.
203 (define_attr "predicated" "yes,no" (const_string "no"))
205 ;; -------------------------------------------------------------------
206 ;; Pipeline descriptions and scheduling
207 ;; -------------------------------------------------------------------
210 (include "aarch64-tune.md")
213 (include "../arm/cortex-a53.md")
214 (include "../arm/cortex-a57.md")
215 (include "../arm/exynos-m1.md")
216 (include "thunderx.md")
217 (include "../arm/xgene1.md")
219 ;; -------------------------------------------------------------------
220 ;; Jumps and other miscellaneous insns
221 ;; -------------------------------------------------------------------
223 (define_insn "indirect_jump"
224 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
227 [(set_attr "type" "branch")]
231 [(set (pc) (label_ref (match_operand 0 "" "")))]
234 [(set_attr "type" "branch")]
237 (define_expand "cbranch<mode>4"
238 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
239 [(match_operand:GPI 1 "register_operand" "")
240 (match_operand:GPI 2 "aarch64_plus_operand" "")])
241 (label_ref (match_operand 3 "" ""))
245 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
247 operands[2] = const0_rtx;
251 (define_expand "cbranch<mode>4"
252 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
253 [(match_operand:GPF 1 "register_operand" "")
254 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
255 (label_ref (match_operand 3 "" ""))
259 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
261 operands[2] = const0_rtx;
265 (define_expand "cbranchcc4"
266 [(set (pc) (if_then_else
267 (match_operator 0 "aarch64_comparison_operator"
268 [(match_operand 1 "cc_register" "")
269 (match_operand 2 "const0_operand")])
270 (label_ref (match_operand 3 "" ""))
275 (define_insn "ccmp<mode>"
276 [(set (match_operand:CC 1 "cc_register" "")
278 (match_operator 4 "aarch64_comparison_operator"
279 [(match_operand 0 "cc_register" "")
282 (match_operand:GPI 2 "register_operand" "r,r,r")
283 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
284 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
287 ccmp\\t%<w>2, %<w>3, %k5, %m4
288 ccmp\\t%<w>2, %3, %k5, %m4
289 ccmn\\t%<w>2, #%n3, %k5, %m4"
290 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
293 (define_insn "fccmp<mode>"
294 [(set (match_operand:CCFP 1 "cc_register" "")
296 (match_operator 4 "aarch64_comparison_operator"
297 [(match_operand 0 "cc_register" "")
300 (match_operand:GPF 2 "register_operand" "w")
301 (match_operand:GPF 3 "register_operand" "w"))
302 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
304 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
305 [(set_attr "type" "fccmp<s>")]
308 (define_insn "fccmpe<mode>"
309 [(set (match_operand:CCFPE 1 "cc_register" "")
311 (match_operator 4 "aarch64_comparison_operator"
312 [(match_operand 0 "cc_register" "")
315 (match_operand:GPF 2 "register_operand" "w")
316 (match_operand:GPF 3 "register_operand" "w"))
317 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
319 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
320 [(set_attr "type" "fccmp<s>")]
323 ;; Expansion of signed mod by a power of 2 using CSNEG.
324 ;; For x0 % n where n is a power of 2 produce:
326 ;; and x0, x0, #(n - 1)
327 ;; and x1, x1, #(n - 1)
328 ;; csneg x0, x0, x1, mi
330 (define_expand "mod<mode>3"
331 [(match_operand:GPI 0 "register_operand" "")
332 (match_operand:GPI 1 "register_operand" "")
333 (match_operand:GPI 2 "const_int_operand" "")]
336 HOST_WIDE_INT val = INTVAL (operands[2]);
339 || exact_log2 (val) <= 0
340 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
343 rtx mask = GEN_INT (val - 1);
345 /* In the special case of x0 % 2 we can do the even shorter:
351 rtx masked = gen_reg_rtx (<MODE>mode);
352 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
353 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
354 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
355 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
359 rtx neg_op = gen_reg_rtx (<MODE>mode);
360 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
362 /* Extract the condition register and mode. */
363 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
364 rtx cc_reg = SET_DEST (cmp);
365 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
367 rtx masked_pos = gen_reg_rtx (<MODE>mode);
368 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
370 rtx masked_neg = gen_reg_rtx (<MODE>mode);
371 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
373 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
374 masked_neg, masked_pos));
379 (define_insn "condjump"
380 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
381 [(match_operand 1 "cc_register" "") (const_int 0)])
382 (label_ref (match_operand 2 "" ""))
386 if (get_attr_length (insn) == 8)
387 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
391 [(set_attr "type" "branch")
393 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
394 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
397 (set (attr "far_branch")
398 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
399 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
404 ;; For a 24-bit immediate CST we can optimize the compare for equality
405 ;; and branch sequence from:
407 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
411 ;; sub x0, x1, #(CST & 0xfff000)
412 ;; subs x0, x0, #(CST & 0x000fff)
414 (define_insn_and_split "*compare_condjump<mode>"
415 [(set (pc) (if_then_else (EQL
416 (match_operand:GPI 0 "register_operand" "r")
417 (match_operand:GPI 1 "aarch64_imm24" "n"))
418 (label_ref:P (match_operand 2 "" ""))
420 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
421 && !aarch64_plus_operand (operands[1], <MODE>mode)
422 && !reload_completed"
427 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
428 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
429 rtx tmp = gen_reg_rtx (<MODE>mode);
430 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
431 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
432 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
433 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
434 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
439 (define_expand "casesi"
440 [(match_operand:SI 0 "register_operand" "") ; Index
441 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
442 (match_operand:SI 2 "const_int_operand" "") ; Total range
443 (match_operand:DI 3 "" "") ; Table label
444 (match_operand:DI 4 "" "")] ; Out of range label
447 if (operands[1] != const0_rtx)
449 rtx reg = gen_reg_rtx (SImode);
451 /* Canonical RTL says that if you have:
455 then this should be emitted as:
459 The use of trunc_int_for_mode ensures that the resulting
460 constant can be represented in SImode, this is important
461 for the corner case where operand[1] is INT_MIN. */
463 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
465 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
466 (operands[1], SImode))
467 operands[1] = force_reg (SImode, operands[1]);
468 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
472 if (!aarch64_plus_operand (operands[2], SImode))
473 operands[2] = force_reg (SImode, operands[2]);
474 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
476 operands[0], operands[2], operands[4]));
478 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
479 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
485 (define_insn "casesi_dispatch"
488 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
489 (match_operand:SI 1 "register_operand" "r")]
491 (clobber (reg:CC CC_REGNUM))
492 (clobber (match_scratch:DI 3 "=r"))
493 (clobber (match_scratch:DI 4 "=r"))
494 (use (label_ref (match_operand 2 "" "")))])]
497 return aarch64_output_casesi (operands);
499 [(set_attr "length" "16")
500 (set_attr "type" "branch")]
504 [(unspec[(const_int 0)] UNSPEC_NOP)]
507 [(set_attr "type" "no_insn")]
510 (define_insn "prefetch"
511 [(prefetch (match_operand:DI 0 "register_operand" "r")
512 (match_operand:QI 1 "const_int_operand" "")
513 (match_operand:QI 2 "const_int_operand" ""))]
516 const char * pftype[2][4] =
518 {"prfm\\tPLDL1STRM, %a0",
519 "prfm\\tPLDL3KEEP, %a0",
520 "prfm\\tPLDL2KEEP, %a0",
521 "prfm\\tPLDL1KEEP, %a0"},
522 {"prfm\\tPSTL1STRM, %a0",
523 "prfm\\tPSTL3KEEP, %a0",
524 "prfm\\tPSTL2KEEP, %a0",
525 "prfm\\tPSTL1KEEP, %a0"},
528 int locality = INTVAL (operands[2]);
530 gcc_assert (IN_RANGE (locality, 0, 3));
532 return pftype[INTVAL(operands[1])][locality];
534 [(set_attr "type" "load1")]
538 [(trap_if (const_int 1) (const_int 8))]
541 [(set_attr "type" "trap")])
543 (define_expand "prologue"
544 [(clobber (const_int 0))]
547 aarch64_expand_prologue ();
552 (define_expand "epilogue"
553 [(clobber (const_int 0))]
556 aarch64_expand_epilogue (false);
561 (define_expand "sibcall_epilogue"
562 [(clobber (const_int 0))]
565 aarch64_expand_epilogue (true);
570 (define_insn "*do_return"
574 [(set_attr "type" "branch")]
577 (define_expand "return"
579 "aarch64_use_return_insn_p ()"
583 (define_insn "simple_return"
587 [(set_attr "type" "branch")]
590 (define_insn "eh_return"
591 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
595 [(set_attr "type" "branch")]
600 [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
603 [(set (match_dup 1) (match_dup 0))]
605 operands[1] = aarch64_final_eh_return_addr ();
609 (define_insn "*cb<optab><mode>1"
610 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
612 (label_ref (match_operand 1 "" ""))
616 if (get_attr_length (insn) == 8)
617 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
619 return "<cbz>\\t%<w>0, %l1";
621 [(set_attr "type" "branch")
623 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
624 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
627 (set (attr "far_branch")
628 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
629 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
634 (define_insn "*tb<optab><mode>1"
635 [(set (pc) (if_then_else
636 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
638 (match_operand 1 "const_int_operand" "n"))
640 (label_ref (match_operand 2 "" ""))
642 (clobber (reg:CC CC_REGNUM))]
645 if (get_attr_length (insn) == 8)
647 if (get_attr_far_branch (insn) == 1)
648 return aarch64_gen_far_branch (operands, 2, "Ltb",
649 "<inv_tb>\\t%<w>0, %1, ");
652 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
653 return "tst\t%<w>0, %1\;<bcond>\t%l2";
657 return "<tbz>\t%<w>0, %1, %l2";
659 [(set_attr "type" "branch")
661 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
662 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
665 (set (attr "far_branch")
666 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
667 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
673 (define_insn "*cb<optab><mode>1"
674 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
676 (label_ref (match_operand 1 "" ""))
678 (clobber (reg:CC CC_REGNUM))]
681 if (get_attr_length (insn) == 8)
683 if (get_attr_far_branch (insn) == 1)
684 return aarch64_gen_far_branch (operands, 1, "Ltb",
685 "<inv_tb>\\t%<w>0, <sizem1>, ");
689 uint64_t val = ((uint64_t) 1)
690 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
691 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
692 output_asm_insn (buf, operands);
693 return "<bcond>\t%l1";
697 return "<tbz>\t%<w>0, <sizem1>, %l1";
699 [(set_attr "type" "branch")
701 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
702 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
705 (set (attr "far_branch")
706 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
707 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
712 ;; -------------------------------------------------------------------
713 ;; Subroutine calls and sibcalls
714 ;; -------------------------------------------------------------------
716 (define_expand "call_internal"
717 [(parallel [(call (match_operand 0 "memory_operand" "")
718 (match_operand 1 "general_operand" ""))
719 (use (match_operand 2 "" ""))
720 (clobber (reg:DI LR_REGNUM))])])
722 (define_expand "call"
723 [(parallel [(call (match_operand 0 "memory_operand" "")
724 (match_operand 1 "general_operand" ""))
725 (use (match_operand 2 "" ""))
726 (clobber (reg:DI LR_REGNUM))])]
732 /* In an untyped call, we can get NULL for operand 2. */
733 if (operands[2] == NULL)
734 operands[2] = const0_rtx;
736 /* Decide if we should generate indirect calls by loading the
737 64-bit address of the callee into a register before performing
738 the branch-and-link. */
739 callee = XEXP (operands[0], 0);
740 if (GET_CODE (callee) == SYMBOL_REF
741 ? (aarch64_is_long_call_p (callee)
742 || aarch64_is_noplt_call_p (callee))
744 XEXP (operands[0], 0) = force_reg (Pmode, callee);
746 pat = gen_call_internal (operands[0], operands[1], operands[2]);
747 aarch64_emit_call_insn (pat);
752 (define_insn "*call_reg"
753 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
754 (match_operand 1 "" ""))
755 (use (match_operand 2 "" ""))
756 (clobber (reg:DI LR_REGNUM))]
759 [(set_attr "type" "call")]
762 (define_insn "*call_symbol"
763 [(call (mem:DI (match_operand:DI 0 "" ""))
764 (match_operand 1 "" ""))
765 (use (match_operand 2 "" ""))
766 (clobber (reg:DI LR_REGNUM))]
767 "GET_CODE (operands[0]) == SYMBOL_REF
768 && !aarch64_is_long_call_p (operands[0])
769 && !aarch64_is_noplt_call_p (operands[0])"
771 [(set_attr "type" "call")]
774 (define_expand "call_value_internal"
775 [(parallel [(set (match_operand 0 "" "")
776 (call (match_operand 1 "memory_operand" "")
777 (match_operand 2 "general_operand" "")))
778 (use (match_operand 3 "" ""))
779 (clobber (reg:DI LR_REGNUM))])])
781 (define_expand "call_value"
782 [(parallel [(set (match_operand 0 "" "")
783 (call (match_operand 1 "memory_operand" "")
784 (match_operand 2 "general_operand" "")))
785 (use (match_operand 3 "" ""))
786 (clobber (reg:DI LR_REGNUM))])]
792 /* In an untyped call, we can get NULL for operand 3. */
793 if (operands[3] == NULL)
794 operands[3] = const0_rtx;
796 /* Decide if we should generate indirect calls by loading the
797 64-bit address of the callee into a register before performing
798 the branch-and-link. */
799 callee = XEXP (operands[1], 0);
800 if (GET_CODE (callee) == SYMBOL_REF
801 ? (aarch64_is_long_call_p (callee)
802 || aarch64_is_noplt_call_p (callee))
804 XEXP (operands[1], 0) = force_reg (Pmode, callee);
806 pat = gen_call_value_internal (operands[0], operands[1], operands[2],
808 aarch64_emit_call_insn (pat);
813 (define_insn "*call_value_reg"
814 [(set (match_operand 0 "" "")
815 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
816 (match_operand 2 "" "")))
817 (use (match_operand 3 "" ""))
818 (clobber (reg:DI LR_REGNUM))]
821 [(set_attr "type" "call")]
825 (define_insn "*call_value_symbol"
826 [(set (match_operand 0 "" "")
827 (call (mem:DI (match_operand:DI 1 "" ""))
828 (match_operand 2 "" "")))
829 (use (match_operand 3 "" ""))
830 (clobber (reg:DI LR_REGNUM))]
831 "GET_CODE (operands[1]) == SYMBOL_REF
832 && !aarch64_is_long_call_p (operands[1])
833 && !aarch64_is_noplt_call_p (operands[1])"
835 [(set_attr "type" "call")]
838 (define_expand "sibcall_internal"
839 [(parallel [(call (match_operand 0 "memory_operand" "")
840 (match_operand 1 "general_operand" ""))
842 (use (match_operand 2 "" ""))])])
844 (define_expand "sibcall"
845 [(parallel [(call (match_operand 0 "memory_operand" "")
846 (match_operand 1 "general_operand" ""))
848 (use (match_operand 2 "" ""))])]
852 rtx callee = XEXP (operands[0], 0);
854 && ((GET_CODE (callee) != SYMBOL_REF)
855 || aarch64_is_noplt_call_p (callee)))
856 XEXP (operands[0], 0) = force_reg (Pmode, callee);
858 if (operands[2] == NULL_RTX)
859 operands[2] = const0_rtx;
861 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
862 aarch64_emit_call_insn (pat);
867 (define_expand "sibcall_value_internal"
868 [(parallel [(set (match_operand 0 "" "")
869 (call (match_operand 1 "memory_operand" "")
870 (match_operand 2 "general_operand" "")))
872 (use (match_operand 3 "" ""))])])
874 (define_expand "sibcall_value"
875 [(parallel [(set (match_operand 0 "" "")
876 (call (match_operand 1 "memory_operand" "")
877 (match_operand 2 "general_operand" "")))
879 (use (match_operand 3 "" ""))])]
883 rtx callee = XEXP (operands[1], 0);
885 && ((GET_CODE (callee) != SYMBOL_REF)
886 || aarch64_is_noplt_call_p (callee)))
887 XEXP (operands[1], 0) = force_reg (Pmode, callee);
889 if (operands[3] == NULL_RTX)
890 operands[3] = const0_rtx;
892 pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
894 aarch64_emit_call_insn (pat);
899 (define_insn "*sibcall_insn"
900 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
901 (match_operand 1 "" ""))
903 (use (match_operand 2 "" ""))]
904 "SIBLING_CALL_P (insn)"
908 [(set_attr "type" "branch, branch")]
911 (define_insn "*sibcall_value_insn"
912 [(set (match_operand 0 "" "")
914 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
915 (match_operand 2 "" "")))
917 (use (match_operand 3 "" ""))]
918 "SIBLING_CALL_P (insn)"
922 [(set_attr "type" "branch, branch")]
925 ;; Call subroutine returning any type.
927 (define_expand "untyped_call"
928 [(parallel [(call (match_operand 0 "")
931 (match_operand 2 "")])]
936 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
938 for (i = 0; i < XVECLEN (operands[2], 0); i++)
940 rtx set = XVECEXP (operands[2], 0, i);
941 emit_move_insn (SET_DEST (set), SET_SRC (set));
944 /* The optimizer does not know that the call sets the function value
945 registers we stored in the result block. We avoid problems by
946 claiming that all hard registers are used and clobbered at this
948 emit_insn (gen_blockage ());
952 ;; -------------------------------------------------------------------
954 ;; -------------------------------------------------------------------
956 (define_expand "mov<mode>"
957 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
958 (match_operand:SHORT 1 "general_operand" ""))]
961 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
962 operands[1] = force_reg (<MODE>mode, operands[1]);
966 (define_insn "*mov<mode>_aarch64"
967 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r,*w, m, m, r,*w,*w")
968 (match_operand:SHORT 1 "general_operand" " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
969 "(register_operand (operands[0], <MODE>mode)
970 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
972 switch (which_alternative)
975 return "mov\t%w0, %w1";
977 return "mov\t%w0, %1";
979 return aarch64_output_scalar_simd_mov_immediate (operands[1],
982 return "ldr<size>\t%w0, %1";
984 return "ldr\t%<size>0, %1";
986 return "str<size>\t%w1, %0";
988 return "str\t%<size>1, %0";
990 return "umov\t%w0, %1.<v>[0]";
992 return "dup\t%0.<Vallxd>, %w1";
994 return "dup\t%<Vetype>0, %1.<v>[0]";
999 [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1000 neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1001 (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1004 (define_expand "mov<mode>"
1005 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1006 (match_operand:GPI 1 "general_operand" ""))]
1009 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1010 operands[1] = force_reg (<MODE>mode, operands[1]);
1012 /* FIXME: RR we still need to fix up what we are doing with
1013 symbol_refs and other types of constants. */
1014 if (CONSTANT_P (operands[1])
1015 && !CONST_INT_P (operands[1]))
1017 aarch64_expand_mov_immediate (operands[0], operands[1]);
1023 (define_insn_and_split "*movsi_aarch64"
1024 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w")
1025 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1026 "(register_operand (operands[0], SImode)
1027 || aarch64_reg_or_zero (operands[1], SImode))"
1043 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1044 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1047 aarch64_expand_mov_immediate (operands[0], operands[1]);
1050 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1051 adr,adr,f_mcr,f_mrc,fmov")
1052 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1055 (define_insn_and_split "*movdi_aarch64"
1056 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w, r,*w,w")
1057 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1058 "(register_operand (operands[0], DImode)
1059 || aarch64_reg_or_zero (operands[1], DImode))"
1076 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1077 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1080 aarch64_expand_mov_immediate (operands[0], operands[1]);
1083 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1084 adr,adr,f_mcr,f_mrc,fmov,neon_move")
1085 (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1086 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1089 (define_insn "insv_imm<mode>"
1090 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1092 (match_operand:GPI 1 "const_int_operand" "n"))
1093 (match_operand:GPI 2 "const_int_operand" "n"))]
1094 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1095 && UINTVAL (operands[1]) % 16 == 0"
1096 "movk\\t%<w>0, %X2, lsl %1"
1097 [(set_attr "type" "mov_imm")]
1100 (define_expand "movti"
1101 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1102 (match_operand:TI 1 "general_operand" ""))]
1105 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1106 operands[1] = force_reg (TImode, operands[1]);
1110 (define_insn "*movti_aarch64"
1111 [(set (match_operand:TI 0
1112 "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
1114 "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
1115 "(register_operand (operands[0], TImode)
1116 || aarch64_reg_or_zero (operands[1], TImode))"
1121 orr\\t%0.16b, %1.16b, %1.16b
1127 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1128 load2,store2,store2,f_loadd,f_stored")
1129 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1130 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1131 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1134 ;; Split a TImode register-register or register-immediate move into
1135 ;; its component DImode pieces, taking care to handle overlapping
1136 ;; source and dest registers.
1138 [(set (match_operand:TI 0 "register_operand" "")
1139 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1140 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1143 aarch64_split_128bit_move (operands[0], operands[1]);
1147 (define_expand "mov<mode>"
1148 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1149 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1154 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1158 if (GET_CODE (operands[0]) == MEM
1159 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1160 && aarch64_float_const_zero_rtx_p (operands[1])))
1161 operands[1] = force_reg (<MODE>mode, operands[1]);
1165 (define_insn "*movhf_aarch64"
1166 [(set (match_operand:HF 0 "nonimmediate_operand" "=w, ?r,w,w,m,r,m ,r")
1167 (match_operand:HF 1 "general_operand" "?rY, w,w,m,w,m,rY,r"))]
1168 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1169 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1173 mov\\t%0.h[0], %1.h[0]
1179 [(set_attr "type" "neon_from_gp,neon_to_gp,neon_move,\
1180 f_loads,f_stores,load1,store1,mov_reg")
1181 (set_attr "simd" "yes,yes,yes,*,*,*,*,*")
1182 (set_attr "fp" "*,*,*,yes,yes,*,*,*")]
1185 (define_insn "*movsf_aarch64"
1186 [(set (match_operand:SF 0 "nonimmediate_operand" "=w, ?r,w,w ,w,m,r,m ,r")
1187 (match_operand:SF 1 "general_operand" "?rY, w,w,Ufc,m,w,m,rY,r"))]
1188 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1189 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1200 [(set_attr "type" "f_mcr,f_mrc,fmov,fconsts,\
1201 f_loads,f_stores,load1,store1,mov_reg")]
1204 (define_insn "*movdf_aarch64"
1205 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, ?r,w,w ,w,m,r,m ,r")
1206 (match_operand:DF 1 "general_operand" "?rY, w,w,Ufc,m,w,m,rY,r"))]
1207 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1208 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1219 [(set_attr "type" "f_mcr,f_mrc,fmov,fconstd,\
1220 f_loadd,f_stored,load1,store1,mov_reg")]
1223 (define_insn "*movtf_aarch64"
1224 [(set (match_operand:TF 0
1225 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1227 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1228 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1229 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1231 orr\\t%0.16b, %1.16b, %1.16b
1242 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1243 f_loadd,f_stored,load2,store2,store2")
1244 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1245 (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*,*")
1246 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1250 [(set (match_operand:TF 0 "register_operand" "")
1251 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1252 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1255 aarch64_split_128bit_move (operands[0], operands[1]);
1262 ;; 2 is size of move in bytes
1265 (define_expand "movmemdi"
1266 [(match_operand:BLK 0 "memory_operand")
1267 (match_operand:BLK 1 "memory_operand")
1268 (match_operand:DI 2 "immediate_operand")
1269 (match_operand:DI 3 "immediate_operand")]
1272 if (aarch64_expand_movmem (operands))
1278 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1279 ;; fairly lax checking on the second memory operation.
1280 (define_insn "load_pairsi"
1281 [(set (match_operand:SI 0 "register_operand" "=r,*w")
1282 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1283 (set (match_operand:SI 2 "register_operand" "=r,*w")
1284 (match_operand:SI 3 "memory_operand" "m,m"))]
1285 "rtx_equal_p (XEXP (operands[3], 0),
1286 plus_constant (Pmode,
1287 XEXP (operands[1], 0),
1288 GET_MODE_SIZE (SImode)))"
1292 [(set_attr "type" "load2,neon_load1_2reg")
1293 (set_attr "fp" "*,yes")]
1296 (define_insn "load_pairdi"
1297 [(set (match_operand:DI 0 "register_operand" "=r,*w")
1298 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1299 (set (match_operand:DI 2 "register_operand" "=r,*w")
1300 (match_operand:DI 3 "memory_operand" "m,m"))]
1301 "rtx_equal_p (XEXP (operands[3], 0),
1302 plus_constant (Pmode,
1303 XEXP (operands[1], 0),
1304 GET_MODE_SIZE (DImode)))"
1308 [(set_attr "type" "load2,neon_load1_2reg")
1309 (set_attr "fp" "*,yes")]
1313 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1314 ;; fairly lax checking on the second memory operation.
1315 (define_insn "store_pairsi"
1316 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1317 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1318 (set (match_operand:SI 2 "memory_operand" "=m,m")
1319 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1320 "rtx_equal_p (XEXP (operands[2], 0),
1321 plus_constant (Pmode,
1322 XEXP (operands[0], 0),
1323 GET_MODE_SIZE (SImode)))"
1327 [(set_attr "type" "store2,neon_store1_2reg")
1328 (set_attr "fp" "*,yes")]
1331 (define_insn "store_pairdi"
1332 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1333 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1334 (set (match_operand:DI 2 "memory_operand" "=m,m")
1335 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1336 "rtx_equal_p (XEXP (operands[2], 0),
1337 plus_constant (Pmode,
1338 XEXP (operands[0], 0),
1339 GET_MODE_SIZE (DImode)))"
1343 [(set_attr "type" "store2,neon_store1_2reg")
1344 (set_attr "fp" "*,yes")]
1347 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1348 ;; fairly lax checking on the second memory operation.
1349 (define_insn "load_pairsf"
1350 [(set (match_operand:SF 0 "register_operand" "=w,*r")
1351 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1352 (set (match_operand:SF 2 "register_operand" "=w,*r")
1353 (match_operand:SF 3 "memory_operand" "m,m"))]
1354 "rtx_equal_p (XEXP (operands[3], 0),
1355 plus_constant (Pmode,
1356 XEXP (operands[1], 0),
1357 GET_MODE_SIZE (SFmode)))"
1361 [(set_attr "type" "neon_load1_2reg,load2")
1362 (set_attr "fp" "yes,*")]
1365 (define_insn "load_pairdf"
1366 [(set (match_operand:DF 0 "register_operand" "=w,*r")
1367 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1368 (set (match_operand:DF 2 "register_operand" "=w,*r")
1369 (match_operand:DF 3 "memory_operand" "m,m"))]
1370 "rtx_equal_p (XEXP (operands[3], 0),
1371 plus_constant (Pmode,
1372 XEXP (operands[1], 0),
1373 GET_MODE_SIZE (DFmode)))"
1377 [(set_attr "type" "neon_load1_2reg,load2")
1378 (set_attr "fp" "yes,*")]
1381 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1382 ;; fairly lax checking on the second memory operation.
1383 (define_insn "store_pairsf"
1384 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1385 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1386 (set (match_operand:SF 2 "memory_operand" "=m,m")
1387 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1388 "rtx_equal_p (XEXP (operands[2], 0),
1389 plus_constant (Pmode,
1390 XEXP (operands[0], 0),
1391 GET_MODE_SIZE (SFmode)))"
1395 [(set_attr "type" "neon_store1_2reg,store2")
1396 (set_attr "fp" "yes,*")]
1399 (define_insn "store_pairdf"
1400 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1401 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1402 (set (match_operand:DF 2 "memory_operand" "=m,m")
1403 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1404 "rtx_equal_p (XEXP (operands[2], 0),
1405 plus_constant (Pmode,
1406 XEXP (operands[0], 0),
1407 GET_MODE_SIZE (DFmode)))"
1411 [(set_attr "type" "neon_store1_2reg,store2")
1412 (set_attr "fp" "yes,*")]
1415 ;; Load pair with post-index writeback. This is primarily used in function
1417 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1419 [(set (match_operand:P 0 "register_operand" "=k")
1420 (plus:P (match_operand:P 1 "register_operand" "0")
1421 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1422 (set (match_operand:GPI 2 "register_operand" "=r")
1423 (mem:GPI (match_dup 1)))
1424 (set (match_operand:GPI 3 "register_operand" "=r")
1425 (mem:GPI (plus:P (match_dup 1)
1426 (match_operand:P 5 "const_int_operand" "n"))))])]
1427 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1428 "ldp\\t%<w>2, %<w>3, [%1], %4"
1429 [(set_attr "type" "load2")]
1432 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1434 [(set (match_operand:P 0 "register_operand" "=k")
1435 (plus:P (match_operand:P 1 "register_operand" "0")
1436 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1437 (set (match_operand:GPF 2 "register_operand" "=w")
1438 (mem:GPF (match_dup 1)))
1439 (set (match_operand:GPF 3 "register_operand" "=w")
1440 (mem:GPF (plus:P (match_dup 1)
1441 (match_operand:P 5 "const_int_operand" "n"))))])]
1442 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1443 "ldp\\t%<w>2, %<w>3, [%1], %4"
1444 [(set_attr "type" "neon_load1_2reg")]
1447 ;; Store pair with pre-index writeback. This is primarily used in function
1449 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1451 [(set (match_operand:P 0 "register_operand" "=&k")
1452 (plus:P (match_operand:P 1 "register_operand" "0")
1453 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1454 (set (mem:GPI (plus:P (match_dup 0)
1456 (match_operand:GPI 2 "register_operand" "r"))
1457 (set (mem:GPI (plus:P (match_dup 0)
1458 (match_operand:P 5 "const_int_operand" "n")))
1459 (match_operand:GPI 3 "register_operand" "r"))])]
1460 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1461 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1462 [(set_attr "type" "store2")]
1465 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1467 [(set (match_operand:P 0 "register_operand" "=&k")
1468 (plus:P (match_operand:P 1 "register_operand" "0")
1469 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1470 (set (mem:GPF (plus:P (match_dup 0)
1472 (match_operand:GPF 2 "register_operand" "w"))
1473 (set (mem:GPF (plus:P (match_dup 0)
1474 (match_operand:P 5 "const_int_operand" "n")))
1475 (match_operand:GPF 3 "register_operand" "w"))])]
1476 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1477 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1478 [(set_attr "type" "neon_store1_2reg<q>")]
1481 ;; -------------------------------------------------------------------
1482 ;; Sign/Zero extension
1483 ;; -------------------------------------------------------------------
1485 (define_expand "<optab>sidi2"
1486 [(set (match_operand:DI 0 "register_operand")
1487 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1491 (define_insn "*extendsidi2_aarch64"
1492 [(set (match_operand:DI 0 "register_operand" "=r,r")
1493 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1498 [(set_attr "type" "extend,load1")]
1501 (define_insn "*load_pair_extendsidi2_aarch64"
1502 [(set (match_operand:DI 0 "register_operand" "=r")
1503 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1504 (set (match_operand:DI 2 "register_operand" "=r")
1505 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1506 "rtx_equal_p (XEXP (operands[3], 0),
1507 plus_constant (Pmode,
1508 XEXP (operands[1], 0),
1509 GET_MODE_SIZE (SImode)))"
1510 "ldpsw\\t%0, %2, %1"
1511 [(set_attr "type" "load2")]
1514 (define_insn "*zero_extendsidi2_aarch64"
1515 [(set (match_operand:DI 0 "register_operand" "=r,r")
1516 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1521 [(set_attr "type" "extend,load1")]
1524 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1525 [(set (match_operand:DI 0 "register_operand" "=r")
1526 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1527 (set (match_operand:DI 2 "register_operand" "=r")
1528 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1529 "rtx_equal_p (XEXP (operands[3], 0),
1530 plus_constant (Pmode,
1531 XEXP (operands[1], 0),
1532 GET_MODE_SIZE (SImode)))"
1533 "ldp\\t%w0, %w2, %1"
1534 [(set_attr "type" "load2")]
1537 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1538 [(set (match_operand:GPI 0 "register_operand")
1539 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1543 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1544 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1545 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1548 sxt<SHORT:size>\t%<GPI:w>0, %w1
1549 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1550 [(set_attr "type" "extend,load1")]
1553 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1554 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1555 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1558 uxt<SHORT:size>\t%<GPI:w>0, %w1
1559 ldr<SHORT:size>\t%w0, %1
1560 ldr\t%<SHORT:size>0, %1"
1561 [(set_attr "type" "extend,load1,load1")]
1564 (define_expand "<optab>qihi2"
1565 [(set (match_operand:HI 0 "register_operand")
1566 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1570 (define_insn "*<optab>qihi2_aarch64"
1571 [(set (match_operand:HI 0 "register_operand" "=r,r")
1572 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1577 [(set_attr "type" "extend,load1")]
1580 ;; -------------------------------------------------------------------
1581 ;; Simple arithmetic
1582 ;; -------------------------------------------------------------------
1584 (define_expand "add<mode>3"
1586 (match_operand:GPI 0 "register_operand" "")
1587 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1588 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1591 if (aarch64_pluslong_strict_immedate (operands[2], <MODE>mode))
1593 /* Give CSE the opportunity to share this constant across additions. */
1594 if (!cse_not_expected && can_create_pseudo_p ())
1595 operands[2] = force_reg (<MODE>mode, operands[2]);
1597 /* Split will refuse to operate on a modification to the stack pointer.
1598 Aid the prologue and epilogue expanders by splitting this now. */
1599 else if (reload_completed && operands[0] == stack_pointer_rtx)
1601 HOST_WIDE_INT i = INTVAL (operands[2]);
1602 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1603 emit_insn (gen_rtx_SET (operands[0],
1604 gen_rtx_PLUS (<MODE>mode, operands[1],
1606 operands[1] = operands[0];
1607 operands[2] = GEN_INT (s);
1612 (define_insn "*add<mode>3_aarch64"
1614 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1616 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1617 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1620 add\\t%<w>0, %<w>1, %2
1621 add\\t%<w>0, %<w>1, %<w>2
1622 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1623 sub\\t%<w>0, %<w>1, #%n2
1625 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1626 (set_attr "simd" "*,*,yes,*,*")]
1629 ;; zero_extend version of above
1630 (define_insn "*addsi3_aarch64_uxtw"
1632 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1634 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1635 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1640 sub\\t%w0, %w1, #%n2
1642 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1645 ;; If there's a free register, and we can load the constant with a
1646 ;; single instruction, do so. This has a chance to improve scheduling.
1648 [(match_scratch:GPI 3 "r")
1649 (set (match_operand:GPI 0 "register_operand")
1651 (match_operand:GPI 1 "register_operand")
1652 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1653 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1654 [(set (match_dup 3) (match_dup 2))
1655 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1659 [(match_scratch:SI 3 "r")
1660 (set (match_operand:DI 0 "register_operand")
1663 (match_operand:SI 1 "register_operand")
1664 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1665 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1666 [(set (match_dup 3) (match_dup 2))
1667 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1670 ;; After peephole2 has had a chance to run, split any remaining long
1671 ;; additions into two add immediates.
1673 [(set (match_operand:GPI 0 "register_operand")
1675 (match_operand:GPI 1 "register_operand")
1676 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1677 "epilogue_completed"
1678 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1679 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1681 HOST_WIDE_INT i = INTVAL (operands[2]);
1682 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1683 operands[3] = GEN_INT (i - s);
1684 operands[4] = GEN_INT (s);
1689 [(set (match_operand:DI 0 "register_operand")
1692 (match_operand:SI 1 "register_operand")
1693 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1694 "epilogue_completed"
1695 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1696 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1698 HOST_WIDE_INT i = INTVAL (operands[2]);
1699 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1700 operands[3] = GEN_INT (i - s);
1701 operands[4] = GEN_INT (s);
1702 operands[5] = gen_lowpart (SImode, operands[0]);
1706 (define_expand "addti3"
1707 [(set (match_operand:TI 0 "register_operand" "")
1708 (plus:TI (match_operand:TI 1 "register_operand" "")
1709 (match_operand:TI 2 "register_operand" "")))]
1712 rtx low = gen_reg_rtx (DImode);
1713 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1714 gen_lowpart (DImode, operands[2])));
1716 rtx high = gen_reg_rtx (DImode);
1717 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1718 gen_highpart (DImode, operands[2])));
1720 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1721 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1725 (define_insn "add<mode>3_compare0"
1726 [(set (reg:CC_NZ CC_REGNUM)
1728 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1729 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1731 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1732 (plus:GPI (match_dup 1) (match_dup 2)))]
1735 adds\\t%<w>0, %<w>1, %<w>2
1736 adds\\t%<w>0, %<w>1, %2
1737 subs\\t%<w>0, %<w>1, #%n2"
1738 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1741 ;; zero_extend version of above
1742 (define_insn "*addsi3_compare0_uxtw"
1743 [(set (reg:CC_NZ CC_REGNUM)
1745 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1746 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1748 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1749 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1752 adds\\t%w0, %w1, %w2
1754 subs\\t%w0, %w1, #%n2"
1755 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1758 (define_insn "*add<mode>3_compareC_cconly_imm"
1759 [(set (reg:CC_C CC_REGNUM)
1762 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1763 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1767 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1768 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1769 <MODE>mode, operands[1])"
1773 [(set_attr "type" "alus_imm")]
1776 (define_insn "*add<mode>3_compareC_cconly"
1777 [(set (reg:CC_C CC_REGNUM)
1780 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1781 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1782 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1784 "cmn\\t%<w>0, %<w>1"
1785 [(set_attr "type" "alus_sreg")]
1788 (define_insn "*add<mode>3_compareC_imm"
1789 [(set (reg:CC_C CC_REGNUM)
1792 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1793 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1797 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1798 (set (match_operand:GPI 0 "register_operand" "=r,r")
1799 (plus:GPI (match_dup 1) (match_dup 2)))]
1800 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1801 <MODE>mode, operands[2])"
1803 adds\\t%<w>0, %<w>1, %<w>2
1804 subs\\t%<w>0, %<w>1, #%n2"
1805 [(set_attr "type" "alus_imm")]
1808 (define_insn "add<mode>3_compareC"
1809 [(set (reg:CC_C CC_REGNUM)
1812 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1813 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1815 (plus:GPI (match_dup 1) (match_dup 2)))))
1816 (set (match_operand:GPI 0 "register_operand" "=r")
1817 (plus:GPI (match_dup 1) (match_dup 2)))]
1819 "adds\\t%<w>0, %<w>1, %<w>2"
1820 [(set_attr "type" "alus_sreg")]
1823 (define_insn "*adds_shift_imm_<mode>"
1824 [(set (reg:CC_NZ CC_REGNUM)
1826 (plus:GPI (ASHIFT:GPI
1827 (match_operand:GPI 1 "register_operand" "r")
1828 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1829 (match_operand:GPI 3 "register_operand" "r"))
1831 (set (match_operand:GPI 0 "register_operand" "=r")
1832 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1835 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1836 [(set_attr "type" "alus_shift_imm")]
1839 (define_insn "*subs_shift_imm_<mode>"
1840 [(set (reg:CC_NZ CC_REGNUM)
1842 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1844 (match_operand:GPI 2 "register_operand" "r")
1845 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1847 (set (match_operand:GPI 0 "register_operand" "=r")
1848 (minus:GPI (match_dup 1)
1849 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1851 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1852 [(set_attr "type" "alus_shift_imm")]
1855 (define_insn "*adds_mul_imm_<mode>"
1856 [(set (reg:CC_NZ CC_REGNUM)
1859 (match_operand:GPI 1 "register_operand" "r")
1860 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1861 (match_operand:GPI 3 "register_operand" "r"))
1863 (set (match_operand:GPI 0 "register_operand" "=r")
1864 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1867 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1868 [(set_attr "type" "alus_shift_imm")]
1871 (define_insn "*subs_mul_imm_<mode>"
1872 [(set (reg:CC_NZ CC_REGNUM)
1874 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1876 (match_operand:GPI 2 "register_operand" "r")
1877 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1879 (set (match_operand:GPI 0 "register_operand" "=r")
1880 (minus:GPI (match_dup 1)
1881 (mult:GPI (match_dup 2) (match_dup 3))))]
1883 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1884 [(set_attr "type" "alus_shift_imm")]
1887 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1888 [(set (reg:CC_NZ CC_REGNUM)
1891 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1892 (match_operand:GPI 2 "register_operand" "r"))
1894 (set (match_operand:GPI 0 "register_operand" "=r")
1895 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1897 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1898 [(set_attr "type" "alus_ext")]
1901 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1902 [(set (reg:CC_NZ CC_REGNUM)
1904 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1906 (match_operand:ALLX 2 "register_operand" "r")))
1908 (set (match_operand:GPI 0 "register_operand" "=r")
1909 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1911 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1912 [(set_attr "type" "alus_ext")]
1915 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1916 [(set (reg:CC_NZ CC_REGNUM)
1918 (plus:GPI (ashift:GPI
1920 (match_operand:ALLX 1 "register_operand" "r"))
1921 (match_operand 2 "aarch64_imm3" "Ui3"))
1922 (match_operand:GPI 3 "register_operand" "r"))
1924 (set (match_operand:GPI 0 "register_operand" "=rk")
1925 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1929 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1930 [(set_attr "type" "alus_ext")]
1933 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1934 [(set (reg:CC_NZ CC_REGNUM)
1936 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1939 (match_operand:ALLX 2 "register_operand" "r"))
1940 (match_operand 3 "aarch64_imm3" "Ui3")))
1942 (set (match_operand:GPI 0 "register_operand" "=rk")
1943 (minus:GPI (match_dup 1)
1944 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1947 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1948 [(set_attr "type" "alus_ext")]
1951 (define_insn "*adds_<optab><mode>_multp2"
1952 [(set (reg:CC_NZ CC_REGNUM)
1954 (plus:GPI (ANY_EXTRACT:GPI
1955 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1956 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1957 (match_operand 3 "const_int_operand" "n")
1959 (match_operand:GPI 4 "register_operand" "r"))
1961 (set (match_operand:GPI 0 "register_operand" "=r")
1962 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1966 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1967 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1968 [(set_attr "type" "alus_ext")]
1971 (define_insn "*subs_<optab><mode>_multp2"
1972 [(set (reg:CC_NZ CC_REGNUM)
1974 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1976 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1977 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1978 (match_operand 3 "const_int_operand" "n")
1981 (set (match_operand:GPI 0 "register_operand" "=r")
1982 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1983 (mult:GPI (match_dup 1) (match_dup 2))
1986 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1987 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1988 [(set_attr "type" "alus_ext")]
1991 (define_insn "*add<mode>3nr_compare0"
1992 [(set (reg:CC_NZ CC_REGNUM)
1994 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1995 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2002 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2005 (define_insn "*compare_neg<mode>"
2006 [(set (reg:CC_Z CC_REGNUM)
2008 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2009 (match_operand:GPI 1 "register_operand" "r")))]
2011 "cmn\\t%<w>1, %<w>0"
2012 [(set_attr "type" "alus_sreg")]
2015 (define_insn "*add_<shift>_<mode>"
2016 [(set (match_operand:GPI 0 "register_operand" "=r")
2017 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2018 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2019 (match_operand:GPI 3 "register_operand" "r")))]
2021 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2022 [(set_attr "type" "alu_shift_imm")]
2025 ;; zero_extend version of above
2026 (define_insn "*add_<shift>_si_uxtw"
2027 [(set (match_operand:DI 0 "register_operand" "=r")
2029 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2030 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2031 (match_operand:SI 3 "register_operand" "r"))))]
2033 "add\\t%w0, %w3, %w1, <shift> %2"
2034 [(set_attr "type" "alu_shift_imm")]
2037 (define_insn "*add_mul_imm_<mode>"
2038 [(set (match_operand:GPI 0 "register_operand" "=r")
2039 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2040 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2041 (match_operand:GPI 3 "register_operand" "r")))]
2043 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2044 [(set_attr "type" "alu_shift_imm")]
2047 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2048 [(set (match_operand:GPI 0 "register_operand" "=rk")
2049 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2050 (match_operand:GPI 2 "register_operand" "r")))]
2052 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2053 [(set_attr "type" "alu_ext")]
2056 ;; zero_extend version of above
2057 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2058 [(set (match_operand:DI 0 "register_operand" "=rk")
2060 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2061 (match_operand:GPI 2 "register_operand" "r"))))]
2063 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2064 [(set_attr "type" "alu_ext")]
2067 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2068 [(set (match_operand:GPI 0 "register_operand" "=rk")
2069 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2070 (match_operand:ALLX 1 "register_operand" "r"))
2071 (match_operand 2 "aarch64_imm3" "Ui3"))
2072 (match_operand:GPI 3 "register_operand" "r")))]
2074 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2075 [(set_attr "type" "alu_ext")]
2078 ;; zero_extend version of above
2079 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2080 [(set (match_operand:DI 0 "register_operand" "=rk")
2082 (plus:SI (ashift:SI (ANY_EXTEND:SI
2083 (match_operand:SHORT 1 "register_operand" "r"))
2084 (match_operand 2 "aarch64_imm3" "Ui3"))
2085 (match_operand:SI 3 "register_operand" "r"))))]
2087 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2088 [(set_attr "type" "alu_ext")]
2091 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2092 [(set (match_operand:GPI 0 "register_operand" "=rk")
2093 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2094 (match_operand:ALLX 1 "register_operand" "r"))
2095 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2096 (match_operand:GPI 3 "register_operand" "r")))]
2098 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2099 [(set_attr "type" "alu_ext")]
2102 ;; zero_extend version of above
2103 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2104 [(set (match_operand:DI 0 "register_operand" "=rk")
2105 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2106 (match_operand:SHORT 1 "register_operand" "r"))
2107 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2108 (match_operand:SI 3 "register_operand" "r"))))]
2110 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2111 [(set_attr "type" "alu_ext")]
2114 (define_insn "*add_<optab><mode>_multp2"
2115 [(set (match_operand:GPI 0 "register_operand" "=rk")
2116 (plus:GPI (ANY_EXTRACT:GPI
2117 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2118 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2119 (match_operand 3 "const_int_operand" "n")
2121 (match_operand:GPI 4 "register_operand" "r")))]
2122 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2123 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2124 [(set_attr "type" "alu_ext")]
2127 ;; zero_extend version of above
2128 (define_insn "*add_<optab>si_multp2_uxtw"
2129 [(set (match_operand:DI 0 "register_operand" "=rk")
2131 (plus:SI (ANY_EXTRACT:SI
2132 (mult:SI (match_operand:SI 1 "register_operand" "r")
2133 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2134 (match_operand 3 "const_int_operand" "n")
2136 (match_operand:SI 4 "register_operand" "r"))))]
2137 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2138 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2139 [(set_attr "type" "alu_ext")]
2142 (define_expand "add<mode>3_carryin"
2143 [(set (match_operand:GPI 0 "register_operand")
2146 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2147 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2148 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2153 ;; Note that add with carry with two zero inputs is matched by cset,
2154 ;; and that add with carry with one zero input is matched by cinc.
2156 (define_insn "*add<mode>3_carryin"
2157 [(set (match_operand:GPI 0 "register_operand" "=r")
2160 (match_operand:GPI 3 "aarch64_carry_operation" "")
2161 (match_operand:GPI 1 "register_operand" "r"))
2162 (match_operand:GPI 2 "register_operand" "r")))]
2164 "adc\\t%<w>0, %<w>1, %<w>2"
2165 [(set_attr "type" "adc_reg")]
2168 ;; zero_extend version of above
2169 (define_insn "*addsi3_carryin_uxtw"
2170 [(set (match_operand:DI 0 "register_operand" "=r")
2174 (match_operand:SI 3 "aarch64_carry_operation" "")
2175 (match_operand:SI 1 "register_operand" "r"))
2176 (match_operand:SI 2 "register_operand" "r"))))]
2178 "adc\\t%w0, %w1, %w2"
2179 [(set_attr "type" "adc_reg")]
2182 (define_insn "*add_uxt<mode>_shift2"
2183 [(set (match_operand:GPI 0 "register_operand" "=rk")
2185 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2186 (match_operand 2 "aarch64_imm3" "Ui3"))
2187 (match_operand 3 "const_int_operand" "n"))
2188 (match_operand:GPI 4 "register_operand" "r")))]
2189 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2191 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2192 INTVAL (operands[3])));
2193 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2194 [(set_attr "type" "alu_ext")]
2197 ;; zero_extend version of above
2198 (define_insn "*add_uxtsi_shift2_uxtw"
2199 [(set (match_operand:DI 0 "register_operand" "=rk")
2202 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2203 (match_operand 2 "aarch64_imm3" "Ui3"))
2204 (match_operand 3 "const_int_operand" "n"))
2205 (match_operand:SI 4 "register_operand" "r"))))]
2206 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2208 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2209 INTVAL (operands[3])));
2210 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2211 [(set_attr "type" "alu_ext")]
2214 (define_insn "*add_uxt<mode>_multp2"
2215 [(set (match_operand:GPI 0 "register_operand" "=rk")
2217 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2218 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2219 (match_operand 3 "const_int_operand" "n"))
2220 (match_operand:GPI 4 "register_operand" "r")))]
2221 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2223 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2224 INTVAL (operands[3])));
2225 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2226 [(set_attr "type" "alu_ext")]
2229 ;; zero_extend version of above
2230 (define_insn "*add_uxtsi_multp2_uxtw"
2231 [(set (match_operand:DI 0 "register_operand" "=rk")
2234 (mult:SI (match_operand:SI 1 "register_operand" "r")
2235 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2236 (match_operand 3 "const_int_operand" "n"))
2237 (match_operand:SI 4 "register_operand" "r"))))]
2238 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2240 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2241 INTVAL (operands[3])));
2242 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2243 [(set_attr "type" "alu_ext")]
2246 (define_insn "subsi3"
2247 [(set (match_operand:SI 0 "register_operand" "=rk")
2248 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2249 (match_operand:SI 2 "register_operand" "r")))]
2251 "sub\\t%w0, %w1, %w2"
2252 [(set_attr "type" "alu_sreg")]
2255 ;; zero_extend version of above
2256 (define_insn "*subsi3_uxtw"
2257 [(set (match_operand:DI 0 "register_operand" "=rk")
2259 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2260 (match_operand:SI 2 "register_operand" "r"))))]
2262 "sub\\t%w0, %w1, %w2"
2263 [(set_attr "type" "alu_sreg")]
2266 (define_insn "subdi3"
2267 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2268 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2269 (match_operand:DI 2 "register_operand" "r,w")))]
2273 sub\\t%d0, %d1, %d2"
2274 [(set_attr "type" "alu_sreg, neon_sub")
2275 (set_attr "simd" "*,yes")]
2278 (define_expand "subti3"
2279 [(set (match_operand:TI 0 "register_operand" "")
2280 (minus:TI (match_operand:TI 1 "register_operand" "")
2281 (match_operand:TI 2 "register_operand" "")))]
2284 rtx low = gen_reg_rtx (DImode);
2285 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2286 gen_lowpart (DImode, operands[2])));
2288 rtx high = gen_reg_rtx (DImode);
2289 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2290 gen_highpart (DImode, operands[2])));
2292 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2293 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2297 (define_insn "*sub<mode>3_compare0"
2298 [(set (reg:CC_NZ CC_REGNUM)
2299 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2300 (match_operand:GPI 2 "register_operand" "r"))
2302 (set (match_operand:GPI 0 "register_operand" "=r")
2303 (minus:GPI (match_dup 1) (match_dup 2)))]
2305 "subs\\t%<w>0, %<w>1, %<w>2"
2306 [(set_attr "type" "alus_sreg")]
2309 ;; zero_extend version of above
2310 (define_insn "*subsi3_compare0_uxtw"
2311 [(set (reg:CC_NZ CC_REGNUM)
2312 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2313 (match_operand:SI 2 "register_operand" "r"))
2315 (set (match_operand:DI 0 "register_operand" "=r")
2316 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2318 "subs\\t%w0, %w1, %w2"
2319 [(set_attr "type" "alus_sreg")]
2322 (define_insn "sub<mode>3_compare1"
2323 [(set (reg:CC CC_REGNUM)
2325 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2326 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2327 (set (match_operand:GPI 0 "register_operand" "=r")
2328 (minus:GPI (match_dup 1) (match_dup 2)))]
2330 "subs\\t%<w>0, %<w>1, %<w>2"
2331 [(set_attr "type" "alus_sreg")]
2334 (define_insn "*sub_<shift>_<mode>"
2335 [(set (match_operand:GPI 0 "register_operand" "=r")
2336 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2338 (match_operand:GPI 1 "register_operand" "r")
2339 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2341 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2342 [(set_attr "type" "alu_shift_imm")]
2345 ;; zero_extend version of above
2346 (define_insn "*sub_<shift>_si_uxtw"
2347 [(set (match_operand:DI 0 "register_operand" "=r")
2349 (minus:SI (match_operand:SI 3 "register_operand" "r")
2351 (match_operand:SI 1 "register_operand" "r")
2352 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2354 "sub\\t%w0, %w3, %w1, <shift> %2"
2355 [(set_attr "type" "alu_shift_imm")]
2358 (define_insn "*sub_mul_imm_<mode>"
2359 [(set (match_operand:GPI 0 "register_operand" "=r")
2360 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2362 (match_operand:GPI 1 "register_operand" "r")
2363 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2365 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2366 [(set_attr "type" "alu_shift_imm")]
2369 ;; zero_extend version of above
2370 (define_insn "*sub_mul_imm_si_uxtw"
2371 [(set (match_operand:DI 0 "register_operand" "=r")
2373 (minus:SI (match_operand:SI 3 "register_operand" "r")
2375 (match_operand:SI 1 "register_operand" "r")
2376 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2378 "sub\\t%w0, %w3, %w1, lsl %p2"
2379 [(set_attr "type" "alu_shift_imm")]
2382 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2383 [(set (match_operand:GPI 0 "register_operand" "=rk")
2384 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2386 (match_operand:ALLX 2 "register_operand" "r"))))]
2388 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2389 [(set_attr "type" "alu_ext")]
2392 ;; zero_extend version of above
2393 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2394 [(set (match_operand:DI 0 "register_operand" "=rk")
2396 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2398 (match_operand:SHORT 2 "register_operand" "r")))))]
2400 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2401 [(set_attr "type" "alu_ext")]
2404 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2405 [(set (match_operand:GPI 0 "register_operand" "=rk")
2406 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2407 (ashift:GPI (ANY_EXTEND:GPI
2408 (match_operand:ALLX 2 "register_operand" "r"))
2409 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2411 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2412 [(set_attr "type" "alu_ext")]
2415 ;; zero_extend version of above
2416 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2417 [(set (match_operand:DI 0 "register_operand" "=rk")
2419 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2420 (ashift:SI (ANY_EXTEND:SI
2421 (match_operand:SHORT 2 "register_operand" "r"))
2422 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2424 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2425 [(set_attr "type" "alu_ext")]
2428 (define_insn "*sub_<optab><mode>_multp2"
2429 [(set (match_operand:GPI 0 "register_operand" "=rk")
2430 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2432 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2433 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2434 (match_operand 3 "const_int_operand" "n")
2436 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2437 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2438 [(set_attr "type" "alu_ext")]
2441 ;; zero_extend version of above
2442 (define_insn "*sub_<optab>si_multp2_uxtw"
2443 [(set (match_operand:DI 0 "register_operand" "=rk")
2445 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2447 (mult:SI (match_operand:SI 1 "register_operand" "r")
2448 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2449 (match_operand 3 "const_int_operand" "n")
2451 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2452 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2453 [(set_attr "type" "alu_ext")]
2456 ;; The hardware description is op1 + ~op2 + C.
2457 ;; = op1 + (-op2 + 1) + (1 - !C)
2458 ;; = op1 - op2 - 1 + 1 - !C
2459 ;; = op1 - op2 - !C.
2460 ;; We describe the latter.
2462 (define_insn "*sub<mode>3_carryin0"
2463 [(set (match_operand:GPI 0 "register_operand" "=r")
2465 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2466 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2468 "sbc\\t%<w>0, %<w>1, <w>zr"
2469 [(set_attr "type" "adc_reg")]
2472 ;; zero_extend version of the above
2473 (define_insn "*subsi3_carryin_uxtw"
2474 [(set (match_operand:DI 0 "register_operand" "=r")
2477 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2478 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2480 "sbc\\t%w0, %w1, wzr"
2481 [(set_attr "type" "adc_reg")]
2484 (define_expand "sub<mode>3_carryin"
2485 [(set (match_operand:GPI 0 "register_operand")
2488 (match_operand:GPI 1 "aarch64_reg_or_zero")
2489 (match_operand:GPI 2 "register_operand"))
2490 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2495 (define_insn "*sub<mode>3_carryin"
2496 [(set (match_operand:GPI 0 "register_operand" "=r")
2499 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2500 (match_operand:GPI 2 "register_operand" "r"))
2501 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2504 "sbc\\t%<w>0, %<w>1, %<w>2"
2505 [(set_attr "type" "adc_reg")]
2508 ;; zero_extend version of the above
2509 (define_insn "*subsi3_carryin_uxtw"
2510 [(set (match_operand:DI 0 "register_operand" "=r")
2514 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2515 (match_operand:SI 2 "register_operand" "r"))
2516 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2519 "sbc\\t%w0, %w1, %w2"
2520 [(set_attr "type" "adc_reg")]
2523 (define_insn "*sub<mode>3_carryin_alt"
2524 [(set (match_operand:GPI 0 "register_operand" "=r")
2527 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2528 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2529 (match_operand:GPI 2 "register_operand" "r")))]
2531 "sbc\\t%<w>0, %<w>1, %<w>2"
2532 [(set_attr "type" "adc_reg")]
2535 ;; zero_extend version of the above
2536 (define_insn "*subsi3_carryin_alt_uxtw"
2537 [(set (match_operand:DI 0 "register_operand" "=r")
2541 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2542 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2543 (match_operand:SI 2 "register_operand" "r"))))]
2545 "sbc\\t%w0, %w1, %w2"
2546 [(set_attr "type" "adc_reg")]
2549 (define_insn "*sub_uxt<mode>_shift2"
2550 [(set (match_operand:GPI 0 "register_operand" "=rk")
2551 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2553 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2554 (match_operand 2 "aarch64_imm3" "Ui3"))
2555 (match_operand 3 "const_int_operand" "n"))))]
2556 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2558 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2559 INTVAL (operands[3])));
2560 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2561 [(set_attr "type" "alu_ext")]
2564 ;; zero_extend version of above
2565 (define_insn "*sub_uxtsi_shift2_uxtw"
2566 [(set (match_operand:DI 0 "register_operand" "=rk")
2568 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2570 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2571 (match_operand 2 "aarch64_imm3" "Ui3"))
2572 (match_operand 3 "const_int_operand" "n")))))]
2573 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2575 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2576 INTVAL (operands[3])));
2577 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2578 [(set_attr "type" "alu_ext")]
2581 (define_insn "*sub_uxt<mode>_multp2"
2582 [(set (match_operand:GPI 0 "register_operand" "=rk")
2583 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2585 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2586 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2587 (match_operand 3 "const_int_operand" "n"))))]
2588 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2590 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2591 INTVAL (operands[3])));
2592 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2593 [(set_attr "type" "alu_ext")]
2596 ;; zero_extend version of above
2597 (define_insn "*sub_uxtsi_multp2_uxtw"
2598 [(set (match_operand:DI 0 "register_operand" "=rk")
2600 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2602 (mult:SI (match_operand:SI 1 "register_operand" "r")
2603 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2604 (match_operand 3 "const_int_operand" "n")))))]
2605 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2607 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2608 INTVAL (operands[3])));
2609 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2610 [(set_attr "type" "alu_ext")]
2613 (define_expand "abs<mode>2"
2614 [(match_operand:GPI 0 "register_operand" "")
2615 (match_operand:GPI 1 "register_operand" "")]
2618 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2619 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2620 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2625 (define_insn "neg<mode>2"
2626 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2627 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2631 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2632 [(set_attr "type" "alu_sreg, neon_neg<q>")
2633 (set_attr "simd" "*,yes")]
2636 ;; zero_extend version of above
2637 (define_insn "*negsi2_uxtw"
2638 [(set (match_operand:DI 0 "register_operand" "=r")
2639 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2642 [(set_attr "type" "alu_sreg")]
2645 (define_insn "*ngc<mode>"
2646 [(set (match_operand:GPI 0 "register_operand" "=r")
2648 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2649 (match_operand:GPI 1 "register_operand" "r")))]
2651 "ngc\\t%<w>0, %<w>1"
2652 [(set_attr "type" "adc_reg")]
2655 (define_insn "*ngcsi_uxtw"
2656 [(set (match_operand:DI 0 "register_operand" "=r")
2659 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2660 (match_operand:SI 1 "register_operand" "r"))))]
2663 [(set_attr "type" "adc_reg")]
2666 (define_insn "neg<mode>2_compare0"
2667 [(set (reg:CC_NZ CC_REGNUM)
2668 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2670 (set (match_operand:GPI 0 "register_operand" "=r")
2671 (neg:GPI (match_dup 1)))]
2673 "negs\\t%<w>0, %<w>1"
2674 [(set_attr "type" "alus_sreg")]
2677 ;; zero_extend version of above
2678 (define_insn "*negsi2_compare0_uxtw"
2679 [(set (reg:CC_NZ CC_REGNUM)
2680 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2682 (set (match_operand:DI 0 "register_operand" "=r")
2683 (zero_extend:DI (neg:SI (match_dup 1))))]
2686 [(set_attr "type" "alus_sreg")]
2689 (define_insn "*neg_<shift><mode>3_compare0"
2690 [(set (reg:CC_NZ CC_REGNUM)
2692 (neg:GPI (ASHIFT:GPI
2693 (match_operand:GPI 1 "register_operand" "r")
2694 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2696 (set (match_operand:GPI 0 "register_operand" "=r")
2697 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2699 "negs\\t%<w>0, %<w>1, <shift> %2"
2700 [(set_attr "type" "alus_shift_imm")]
2703 (define_insn "*neg_<shift>_<mode>2"
2704 [(set (match_operand:GPI 0 "register_operand" "=r")
2705 (neg:GPI (ASHIFT:GPI
2706 (match_operand:GPI 1 "register_operand" "r")
2707 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2709 "neg\\t%<w>0, %<w>1, <shift> %2"
2710 [(set_attr "type" "alu_shift_imm")]
2713 ;; zero_extend version of above
2714 (define_insn "*neg_<shift>_si2_uxtw"
2715 [(set (match_operand:DI 0 "register_operand" "=r")
2718 (match_operand:SI 1 "register_operand" "r")
2719 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2721 "neg\\t%w0, %w1, <shift> %2"
2722 [(set_attr "type" "alu_shift_imm")]
2725 (define_insn "*neg_mul_imm_<mode>2"
2726 [(set (match_operand:GPI 0 "register_operand" "=r")
2728 (match_operand:GPI 1 "register_operand" "r")
2729 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2731 "neg\\t%<w>0, %<w>1, lsl %p2"
2732 [(set_attr "type" "alu_shift_imm")]
2735 ;; zero_extend version of above
2736 (define_insn "*neg_mul_imm_si2_uxtw"
2737 [(set (match_operand:DI 0 "register_operand" "=r")
2740 (match_operand:SI 1 "register_operand" "r")
2741 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2743 "neg\\t%w0, %w1, lsl %p2"
2744 [(set_attr "type" "alu_shift_imm")]
2747 (define_insn "mul<mode>3"
2748 [(set (match_operand:GPI 0 "register_operand" "=r")
2749 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2750 (match_operand:GPI 2 "register_operand" "r")))]
2752 "mul\\t%<w>0, %<w>1, %<w>2"
2753 [(set_attr "type" "mul")]
2756 ;; zero_extend version of above
2757 (define_insn "*mulsi3_uxtw"
2758 [(set (match_operand:DI 0 "register_operand" "=r")
2760 (mult:SI (match_operand:SI 1 "register_operand" "r")
2761 (match_operand:SI 2 "register_operand" "r"))))]
2763 "mul\\t%w0, %w1, %w2"
2764 [(set_attr "type" "mul")]
2767 (define_insn "madd<mode>"
2768 [(set (match_operand:GPI 0 "register_operand" "=r")
2769 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2770 (match_operand:GPI 2 "register_operand" "r"))
2771 (match_operand:GPI 3 "register_operand" "r")))]
2773 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2774 [(set_attr "type" "mla")]
2777 ;; zero_extend version of above
2778 (define_insn "*maddsi_uxtw"
2779 [(set (match_operand:DI 0 "register_operand" "=r")
2781 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2782 (match_operand:SI 2 "register_operand" "r"))
2783 (match_operand:SI 3 "register_operand" "r"))))]
2785 "madd\\t%w0, %w1, %w2, %w3"
2786 [(set_attr "type" "mla")]
2789 (define_insn "*msub<mode>"
2790 [(set (match_operand:GPI 0 "register_operand" "=r")
2791 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2792 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2793 (match_operand:GPI 2 "register_operand" "r"))))]
2796 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2797 [(set_attr "type" "mla")]
2800 ;; zero_extend version of above
2801 (define_insn "*msubsi_uxtw"
2802 [(set (match_operand:DI 0 "register_operand" "=r")
2804 (minus:SI (match_operand:SI 3 "register_operand" "r")
2805 (mult:SI (match_operand:SI 1 "register_operand" "r")
2806 (match_operand:SI 2 "register_operand" "r")))))]
2809 "msub\\t%w0, %w1, %w2, %w3"
2810 [(set_attr "type" "mla")]
2813 (define_insn "*mul<mode>_neg"
2814 [(set (match_operand:GPI 0 "register_operand" "=r")
2815 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2816 (match_operand:GPI 2 "register_operand" "r")))]
2819 "mneg\\t%<w>0, %<w>1, %<w>2"
2820 [(set_attr "type" "mul")]
2823 ;; zero_extend version of above
2824 (define_insn "*mulsi_neg_uxtw"
2825 [(set (match_operand:DI 0 "register_operand" "=r")
2827 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2828 (match_operand:SI 2 "register_operand" "r"))))]
2831 "mneg\\t%w0, %w1, %w2"
2832 [(set_attr "type" "mul")]
2835 (define_insn "<su_optab>mulsidi3"
2836 [(set (match_operand:DI 0 "register_operand" "=r")
2837 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2838 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2840 "<su>mull\\t%0, %w1, %w2"
2841 [(set_attr "type" "<su>mull")]
2844 (define_insn "<su_optab>maddsidi4"
2845 [(set (match_operand:DI 0 "register_operand" "=r")
2847 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2848 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2849 (match_operand:DI 3 "register_operand" "r")))]
2851 "<su>maddl\\t%0, %w1, %w2, %3"
2852 [(set_attr "type" "<su>mlal")]
2855 (define_insn "<su_optab>msubsidi4"
2856 [(set (match_operand:DI 0 "register_operand" "=r")
2858 (match_operand:DI 3 "register_operand" "r")
2859 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2861 (match_operand:SI 2 "register_operand" "r")))))]
2863 "<su>msubl\\t%0, %w1, %w2, %3"
2864 [(set_attr "type" "<su>mlal")]
2867 (define_insn "*<su_optab>mulsidi_neg"
2868 [(set (match_operand:DI 0 "register_operand" "=r")
2870 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2871 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2873 "<su>mnegl\\t%0, %w1, %w2"
2874 [(set_attr "type" "<su>mull")]
2877 (define_expand "<su_optab>mulditi3"
2878 [(set (match_operand:TI 0 "register_operand")
2879 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2880 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2883 rtx low = gen_reg_rtx (DImode);
2884 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2886 rtx high = gen_reg_rtx (DImode);
2887 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2889 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2890 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2894 ;; The default expansion of multi3 using umuldi3_highpart will perform
2895 ;; the additions in an order that fails to combine into two madd insns.
2896 (define_expand "multi3"
2897 [(set (match_operand:TI 0 "register_operand")
2898 (mult:TI (match_operand:TI 1 "register_operand")
2899 (match_operand:TI 2 "register_operand")))]
2902 rtx l0 = gen_reg_rtx (DImode);
2903 rtx l1 = gen_lowpart (DImode, operands[1]);
2904 rtx l2 = gen_lowpart (DImode, operands[2]);
2905 rtx h0 = gen_reg_rtx (DImode);
2906 rtx h1 = gen_highpart (DImode, operands[1]);
2907 rtx h2 = gen_highpart (DImode, operands[2]);
2909 emit_insn (gen_muldi3 (l0, l1, l2));
2910 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2911 emit_insn (gen_madddi (h0, h1, l2, h0));
2912 emit_insn (gen_madddi (h0, l1, h2, h0));
2914 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2915 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2919 (define_insn "<su>muldi3_highpart"
2920 [(set (match_operand:DI 0 "register_operand" "=r")
2924 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2925 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2928 "<su>mulh\\t%0, %1, %2"
2929 [(set_attr "type" "<su>mull")]
2932 (define_insn "<su_optab>div<mode>3"
2933 [(set (match_operand:GPI 0 "register_operand" "=r")
2934 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2935 (match_operand:GPI 2 "register_operand" "r")))]
2937 "<su>div\\t%<w>0, %<w>1, %<w>2"
2938 [(set_attr "type" "<su>div")]
2941 ;; zero_extend version of above
2942 (define_insn "*<su_optab>divsi3_uxtw"
2943 [(set (match_operand:DI 0 "register_operand" "=r")
2945 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2946 (match_operand:SI 2 "register_operand" "r"))))]
2948 "<su>div\\t%w0, %w1, %w2"
2949 [(set_attr "type" "<su>div")]
2952 ;; -------------------------------------------------------------------
2954 ;; -------------------------------------------------------------------
2956 (define_insn "cmp<mode>"
2957 [(set (reg:CC CC_REGNUM)
2958 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2959 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2965 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2968 (define_insn "fcmp<mode>"
2969 [(set (reg:CCFP CC_REGNUM)
2970 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2971 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2975 fcmp\\t%<s>0, %<s>1"
2976 [(set_attr "type" "fcmp<s>")]
2979 (define_insn "fcmpe<mode>"
2980 [(set (reg:CCFPE CC_REGNUM)
2981 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2982 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2986 fcmpe\\t%<s>0, %<s>1"
2987 [(set_attr "type" "fcmp<s>")]
2990 (define_insn "*cmp_swp_<shift>_reg<mode>"
2991 [(set (reg:CC_SWP CC_REGNUM)
2992 (compare:CC_SWP (ASHIFT:GPI
2993 (match_operand:GPI 0 "register_operand" "r")
2994 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2995 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2997 "cmp\\t%<w>2, %<w>0, <shift> %1"
2998 [(set_attr "type" "alus_shift_imm")]
3001 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3002 [(set (reg:CC_SWP CC_REGNUM)
3003 (compare:CC_SWP (ANY_EXTEND:GPI
3004 (match_operand:ALLX 0 "register_operand" "r"))
3005 (match_operand:GPI 1 "register_operand" "r")))]
3007 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3008 [(set_attr "type" "alus_ext")]
3011 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3012 [(set (reg:CC_SWP CC_REGNUM)
3013 (compare:CC_SWP (ashift:GPI
3015 (match_operand:ALLX 0 "register_operand" "r"))
3016 (match_operand 1 "aarch64_imm3" "Ui3"))
3017 (match_operand:GPI 2 "register_operand" "r")))]
3019 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3020 [(set_attr "type" "alus_ext")]
3023 ;; -------------------------------------------------------------------
3024 ;; Store-flag and conditional select insns
3025 ;; -------------------------------------------------------------------
3027 (define_expand "cstore<mode>4"
3028 [(set (match_operand:SI 0 "register_operand" "")
3029 (match_operator:SI 1 "aarch64_comparison_operator"
3030 [(match_operand:GPI 2 "register_operand" "")
3031 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3034 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3036 operands[3] = const0_rtx;
3040 (define_expand "cstorecc4"
3041 [(set (match_operand:SI 0 "register_operand")
3042 (match_operator 1 "aarch64_comparison_operator_mode"
3043 [(match_operand 2 "cc_register")
3044 (match_operand 3 "const0_operand")]))]
3047 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3052 (define_expand "cstore<mode>4"
3053 [(set (match_operand:SI 0 "register_operand" "")
3054 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3055 [(match_operand:GPF 2 "register_operand" "")
3056 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3059 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3061 operands[3] = const0_rtx;
3065 (define_insn "aarch64_cstore<mode>"
3066 [(set (match_operand:ALLI 0 "register_operand" "=r")
3067 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3068 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3071 [(set_attr "type" "csel")]
3074 ;; For a 24-bit immediate CST we can optimize the compare for equality
3075 ;; and branch sequence from:
3077 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3080 ;; into the shorter:
3081 ;; sub x0, x1, #(CST & 0xfff000)
3082 ;; subs x0, x0, #(CST & 0x000fff)
3083 ;; cset x2, <ne, eq>.
3084 (define_insn_and_split "*compare_cstore<mode>_insn"
3085 [(set (match_operand:GPI 0 "register_operand" "=r")
3086 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3087 (match_operand:GPI 2 "aarch64_imm24" "n")))]
3088 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3089 && !aarch64_plus_operand (operands[2], <MODE>mode)
3090 && !reload_completed"
3095 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3096 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3097 rtx tmp = gen_reg_rtx (<MODE>mode);
3098 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3099 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3100 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3101 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3102 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3105 [(set_attr "type" "csel")]
3108 ;; zero_extend version of the above
3109 (define_insn "*cstoresi_insn_uxtw"
3110 [(set (match_operand:DI 0 "register_operand" "=r")
3112 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3113 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3116 [(set_attr "type" "csel")]
3119 (define_insn "cstore<mode>_neg"
3120 [(set (match_operand:ALLI 0 "register_operand" "=r")
3121 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3122 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3124 "csetm\\t%<w>0, %m1"
3125 [(set_attr "type" "csel")]
3128 ;; zero_extend version of the above
3129 (define_insn "*cstoresi_neg_uxtw"
3130 [(set (match_operand:DI 0 "register_operand" "=r")
3132 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3133 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3136 [(set_attr "type" "csel")]
3139 (define_expand "cmov<mode>6"
3140 [(set (match_operand:GPI 0 "register_operand" "")
3142 (match_operator 1 "aarch64_comparison_operator"
3143 [(match_operand:GPI 2 "register_operand" "")
3144 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3145 (match_operand:GPI 4 "register_operand" "")
3146 (match_operand:GPI 5 "register_operand" "")))]
3149 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3151 operands[3] = const0_rtx;
3155 (define_expand "cmov<mode>6"
3156 [(set (match_operand:GPF 0 "register_operand" "")
3158 (match_operator 1 "aarch64_comparison_operator"
3159 [(match_operand:GPF 2 "register_operand" "")
3160 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3161 (match_operand:GPF 4 "register_operand" "")
3162 (match_operand:GPF 5 "register_operand" "")))]
3165 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3167 operands[3] = const0_rtx;
3171 (define_insn "*cmov<mode>_insn"
3172 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3174 (match_operator 1 "aarch64_comparison_operator"
3175 [(match_operand 2 "cc_register" "") (const_int 0)])
3176 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3177 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3178 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3179 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3180 ;; Final two alternatives should be unreachable, but included for completeness
3182 csel\\t%<w>0, %<w>3, %<w>4, %m1
3183 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3184 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3185 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3186 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3189 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3192 ;; zero_extend version of above
3193 (define_insn "*cmovsi_insn_uxtw"
3194 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3197 (match_operator 1 "aarch64_comparison_operator"
3198 [(match_operand 2 "cc_register" "") (const_int 0)])
3199 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3200 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3201 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3202 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3203 ;; Final two alternatives should be unreachable, but included for completeness
3205 csel\\t%w0, %w3, %w4, %m1
3206 csinv\\t%w0, %w3, wzr, %m1
3207 csinv\\t%w0, %w4, wzr, %M1
3208 csinc\\t%w0, %w3, wzr, %m1
3209 csinc\\t%w0, %w4, wzr, %M1
3212 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3215 (define_insn "*cmovdi_insn_uxtw"
3216 [(set (match_operand:DI 0 "register_operand" "=r")
3218 (match_operator 1 "aarch64_comparison_operator"
3219 [(match_operand 2 "cc_register" "") (const_int 0)])
3220 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3221 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3223 "csel\\t%w0, %w3, %w4, %m1"
3224 [(set_attr "type" "csel")]
3227 (define_insn "*cmov<mode>_insn"
3228 [(set (match_operand:GPF 0 "register_operand" "=w")
3230 (match_operator 1 "aarch64_comparison_operator"
3231 [(match_operand 2 "cc_register" "") (const_int 0)])
3232 (match_operand:GPF 3 "register_operand" "w")
3233 (match_operand:GPF 4 "register_operand" "w")))]
3235 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3236 [(set_attr "type" "fcsel")]
3239 (define_expand "mov<mode>cc"
3240 [(set (match_operand:ALLI 0 "register_operand" "")
3241 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3242 (match_operand:ALLI 2 "register_operand" "")
3243 (match_operand:ALLI 3 "register_operand" "")))]
3247 enum rtx_code code = GET_CODE (operands[1]);
3249 if (code == UNEQ || code == LTGT)
3252 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3253 XEXP (operands[1], 1));
3254 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3258 (define_expand "mov<GPF:mode><GPI:mode>cc"
3259 [(set (match_operand:GPI 0 "register_operand" "")
3260 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3261 (match_operand:GPF 2 "register_operand" "")
3262 (match_operand:GPF 3 "register_operand" "")))]
3266 enum rtx_code code = GET_CODE (operands[1]);
3268 if (code == UNEQ || code == LTGT)
3271 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3272 XEXP (operands[1], 1));
3273 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3277 (define_expand "mov<mode>cc"
3278 [(set (match_operand:GPF 0 "register_operand" "")
3279 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3280 (match_operand:GPF 2 "register_operand" "")
3281 (match_operand:GPF 3 "register_operand" "")))]
3285 enum rtx_code code = GET_CODE (operands[1]);
3287 if (code == UNEQ || code == LTGT)
3290 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3291 XEXP (operands[1], 1));
3292 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3296 (define_expand "<neg_not_op><mode>cc"
3297 [(set (match_operand:GPI 0 "register_operand" "")
3298 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3299 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3300 (match_operand:GPI 3 "register_operand" "")))]
3304 enum rtx_code code = GET_CODE (operands[1]);
3306 if (code == UNEQ || code == LTGT)
3309 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3310 XEXP (operands[1], 1));
3311 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3315 ;; CRC32 instructions.
3316 (define_insn "aarch64_<crc_variant>"
3317 [(set (match_operand:SI 0 "register_operand" "=r")
3318 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3319 (match_operand:<crc_mode> 2 "register_operand" "r")]
3323 if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3324 return "<crc_variant>\\t%w0, %w1, %x2";
3326 return "<crc_variant>\\t%w0, %w1, %w2";
3328 [(set_attr "type" "crc")]
3331 (define_insn "*csinc2<mode>_insn"
3332 [(set (match_operand:GPI 0 "register_operand" "=r")
3333 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3334 (match_operand:GPI 1 "register_operand" "r")))]
3336 "cinc\\t%<w>0, %<w>1, %m2"
3337 [(set_attr "type" "csel")]
3340 (define_insn "csinc3<mode>_insn"
3341 [(set (match_operand:GPI 0 "register_operand" "=r")
3343 (match_operand 1 "aarch64_comparison_operation" "")
3344 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3346 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3348 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3349 [(set_attr "type" "csel")]
3352 (define_insn "*csinv3<mode>_insn"
3353 [(set (match_operand:GPI 0 "register_operand" "=r")
3355 (match_operand 1 "aarch64_comparison_operation" "")
3356 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3357 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3359 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3360 [(set_attr "type" "csel")]
3363 (define_insn "csneg3_uxtw_insn"
3364 [(set (match_operand:DI 0 "register_operand" "=r")
3367 (match_operand 1 "aarch64_comparison_operation" "")
3368 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3369 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3371 "csneg\\t%w0, %w3, %w2, %M1"
3372 [(set_attr "type" "csel")]
3375 (define_insn "csneg3<mode>_insn"
3376 [(set (match_operand:GPI 0 "register_operand" "=r")
3378 (match_operand 1 "aarch64_comparison_operation" "")
3379 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3380 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3382 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3383 [(set_attr "type" "csel")]
3386 ;; -------------------------------------------------------------------
3387 ;; Logical operations
3388 ;; -------------------------------------------------------------------
3390 (define_insn "<optab><mode>3"
3391 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3392 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3393 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3396 <logical>\\t%<w>0, %<w>1, %<w>2
3397 <logical>\\t%<w>0, %<w>1, %2
3398 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3399 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3400 (set_attr "simd" "*,*,yes")]
3403 ;; zero_extend version of above
3404 (define_insn "*<optab>si3_uxtw"
3405 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3407 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3408 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3410 "<logical>\\t%w0, %w1, %w2"
3411 [(set_attr "type" "logic_reg,logic_imm")]
3414 (define_insn "*and<mode>3_compare0"
3415 [(set (reg:CC_NZ CC_REGNUM)
3417 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3418 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3420 (set (match_operand:GPI 0 "register_operand" "=r,r")
3421 (and:GPI (match_dup 1) (match_dup 2)))]
3423 "ands\\t%<w>0, %<w>1, %<w>2"
3424 [(set_attr "type" "logics_reg,logics_imm")]
3427 ;; zero_extend version of above
3428 (define_insn "*andsi3_compare0_uxtw"
3429 [(set (reg:CC_NZ CC_REGNUM)
3431 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3432 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3434 (set (match_operand:DI 0 "register_operand" "=r,r")
3435 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3437 "ands\\t%w0, %w1, %w2"
3438 [(set_attr "type" "logics_reg,logics_imm")]
3441 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3442 [(set (reg:CC_NZ CC_REGNUM)
3445 (match_operand:GPI 1 "register_operand" "r")
3446 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3447 (match_operand:GPI 3 "register_operand" "r"))
3449 (set (match_operand:GPI 0 "register_operand" "=r")
3450 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3452 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3453 [(set_attr "type" "logics_shift_imm")]
3456 ;; zero_extend version of above
3457 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3458 [(set (reg:CC_NZ CC_REGNUM)
3461 (match_operand:SI 1 "register_operand" "r")
3462 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3463 (match_operand:SI 3 "register_operand" "r"))
3465 (set (match_operand:DI 0 "register_operand" "=r")
3466 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3469 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3470 [(set_attr "type" "logics_shift_imm")]
3473 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3474 [(set (match_operand:GPI 0 "register_operand" "=r")
3475 (LOGICAL:GPI (SHIFT:GPI
3476 (match_operand:GPI 1 "register_operand" "r")
3477 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3478 (match_operand:GPI 3 "register_operand" "r")))]
3480 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3481 [(set_attr "type" "logic_shift_imm")]
3484 (define_insn "*<optab>_rol<mode>3"
3485 [(set (match_operand:GPI 0 "register_operand" "=r")
3486 (LOGICAL:GPI (rotate:GPI
3487 (match_operand:GPI 1 "register_operand" "r")
3488 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3489 (match_operand:GPI 3 "register_operand" "r")))]
3491 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3492 [(set_attr "type" "logic_shift_imm")]
3495 ;; zero_extend versions of above
3496 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3497 [(set (match_operand:DI 0 "register_operand" "=r")
3499 (LOGICAL:SI (SHIFT:SI
3500 (match_operand:SI 1 "register_operand" "r")
3501 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3502 (match_operand:SI 3 "register_operand" "r"))))]
3504 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3505 [(set_attr "type" "logic_shift_imm")]
3508 (define_insn "*<optab>_rolsi3_uxtw"
3509 [(set (match_operand:DI 0 "register_operand" "=r")
3511 (LOGICAL:SI (rotate:SI
3512 (match_operand:SI 1 "register_operand" "r")
3513 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3514 (match_operand:SI 3 "register_operand" "r"))))]
3516 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3517 [(set_attr "type" "logic_shift_imm")]
3520 (define_insn "one_cmpl<mode>2"
3521 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3522 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3527 [(set_attr "type" "logic_reg,neon_logic")
3528 (set_attr "simd" "*,yes")]
3531 (define_insn "*one_cmpl_<optab><mode>2"
3532 [(set (match_operand:GPI 0 "register_operand" "=r")
3533 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3534 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3536 "mvn\\t%<w>0, %<w>1, <shift> %2"
3537 [(set_attr "type" "logic_shift_imm")]
3540 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3542 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3543 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3544 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3545 (match_operand:GPI 2 "register_operand" "r,w")))]
3548 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3549 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3550 [(set_attr "type" "logic_reg,neon_logic")
3551 (set_attr "simd" "*,yes")]
3554 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3555 [(set (match_operand:DI 0 "register_operand" "=r")
3557 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3558 (match_operand:SI 2 "register_operand" "r"))))]
3560 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3561 [(set_attr "type" "logic_reg")]
3564 (define_insn "*xor_one_cmplsidi3_ze"
3565 [(set (match_operand:DI 0 "register_operand" "=r")
3567 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3568 (match_operand:SI 2 "register_operand" "r")))))]
3570 "eon\\t%w0, %w1, %w2"
3571 [(set_attr "type" "logic_reg")]
3574 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3575 ;; eon does not operate on SIMD registers so the vector variant must be split.
3576 (define_insn_and_split "*xor_one_cmpl<mode>3"
3577 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3578 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3579 (match_operand:GPI 2 "register_operand" "r,w"))))]
3582 eon\\t%<w>0, %<w>1, %<w>2
3584 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3585 [(set (match_operand:GPI 0 "register_operand" "=w")
3586 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3587 (match_operand:GPI 2 "register_operand" "w")))
3588 (set (match_dup 0) (not:GPI (match_dup 0)))]
3590 [(set_attr "type" "logic_reg,multiple")
3591 (set_attr "simd" "*,yes")]
3594 (define_insn "*and_one_cmpl<mode>3_compare0"
3595 [(set (reg:CC_NZ CC_REGNUM)
3598 (match_operand:GPI 1 "register_operand" "r"))
3599 (match_operand:GPI 2 "register_operand" "r"))
3601 (set (match_operand:GPI 0 "register_operand" "=r")
3602 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3604 "bics\\t%<w>0, %<w>2, %<w>1"
3605 [(set_attr "type" "logics_reg")]
3608 ;; zero_extend version of above
3609 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3610 [(set (reg:CC_NZ CC_REGNUM)
3613 (match_operand:SI 1 "register_operand" "r"))
3614 (match_operand:SI 2 "register_operand" "r"))
3616 (set (match_operand:DI 0 "register_operand" "=r")
3617 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3619 "bics\\t%w0, %w2, %w1"
3620 [(set_attr "type" "logics_reg")]
3623 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3624 [(set (reg:CC_NZ CC_REGNUM)
3627 (match_operand:GPI 0 "register_operand" "r"))
3628 (match_operand:GPI 1 "register_operand" "r"))
3631 "bics\\t<w>zr, %<w>1, %<w>0"
3632 [(set_attr "type" "logics_reg")]
3635 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3636 [(set (match_operand:GPI 0 "register_operand" "=r")
3637 (LOGICAL:GPI (not:GPI
3639 (match_operand:GPI 1 "register_operand" "r")
3640 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3641 (match_operand:GPI 3 "register_operand" "r")))]
3643 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3644 [(set_attr "type" "logic_shift_imm")]
3647 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3648 [(set (match_operand:GPI 0 "register_operand" "=r")
3651 (match_operand:GPI 1 "register_operand" "r")
3652 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3653 (match_operand:GPI 3 "register_operand" "r"))))]
3655 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3656 [(set_attr "type" "logic_shift_imm")]
3659 ;; Zero-extend version of the above.
3660 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3661 [(set (match_operand:DI 0 "register_operand" "=r")
3665 (match_operand:SI 1 "register_operand" "r")
3666 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3667 (match_operand:SI 3 "register_operand" "r")))))]
3669 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3670 [(set_attr "type" "logic_shift_imm")]
3673 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3674 [(set (reg:CC_NZ CC_REGNUM)
3678 (match_operand:GPI 1 "register_operand" "r")
3679 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3680 (match_operand:GPI 3 "register_operand" "r"))
3682 (set (match_operand:GPI 0 "register_operand" "=r")
3685 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3687 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3688 [(set_attr "type" "logics_shift_imm")]
3691 ;; zero_extend version of above
3692 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3693 [(set (reg:CC_NZ CC_REGNUM)
3697 (match_operand:SI 1 "register_operand" "r")
3698 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3699 (match_operand:SI 3 "register_operand" "r"))
3701 (set (match_operand:DI 0 "register_operand" "=r")
3702 (zero_extend:DI (and:SI
3704 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3706 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3707 [(set_attr "type" "logics_shift_imm")]
3710 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3711 [(set (reg:CC_NZ CC_REGNUM)
3715 (match_operand:GPI 0 "register_operand" "r")
3716 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3717 (match_operand:GPI 2 "register_operand" "r"))
3720 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3721 [(set_attr "type" "logics_shift_imm")]
3724 (define_insn "clz<mode>2"
3725 [(set (match_operand:GPI 0 "register_operand" "=r")
3726 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3728 "clz\\t%<w>0, %<w>1"
3729 [(set_attr "type" "clz")]
3732 (define_expand "ffs<mode>2"
3733 [(match_operand:GPI 0 "register_operand")
3734 (match_operand:GPI 1 "register_operand")]
3737 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3738 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3740 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3741 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3742 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3747 (define_insn "clrsb<mode>2"
3748 [(set (match_operand:GPI 0 "register_operand" "=r")
3749 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3751 "cls\\t%<w>0, %<w>1"
3752 [(set_attr "type" "clz")]
3755 (define_insn "rbit<mode>2"
3756 [(set (match_operand:GPI 0 "register_operand" "=r")
3757 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3759 "rbit\\t%<w>0, %<w>1"
3760 [(set_attr "type" "rbit")]
3763 (define_expand "ctz<mode>2"
3764 [(match_operand:GPI 0 "register_operand")
3765 (match_operand:GPI 1 "register_operand")]
3768 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3769 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3774 (define_insn "*and<mode>_compare0"
3775 [(set (reg:CC_NZ CC_REGNUM)
3777 (match_operand:SHORT 0 "register_operand" "r")
3780 "tst\\t%<w>0, <short_mask>"
3781 [(set_attr "type" "alus_imm")]
3784 (define_insn "*and<mode>3nr_compare0"
3785 [(set (reg:CC_NZ CC_REGNUM)
3787 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3788 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3791 "tst\\t%<w>0, %<w>1"
3792 [(set_attr "type" "logics_reg,logics_imm")]
3795 (define_insn "*and<mode>3nr_compare0_zextract"
3796 [(set (reg:CC_NZ CC_REGNUM)
3798 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3799 (match_operand:GPI 1 "const_int_operand" "n")
3800 (match_operand:GPI 2 "const_int_operand" "n"))
3802 "INTVAL (operands[1]) > 0
3803 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3804 <= GET_MODE_BITSIZE (<MODE>mode))
3805 && aarch64_bitmask_imm (
3806 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3811 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3812 return "tst\\t%<w>0, %1";
3814 [(set_attr "type" "logics_shift_imm")]
3817 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3818 [(set (reg:CC_NZ CC_REGNUM)
3821 (match_operand:GPI 0 "register_operand" "r")
3822 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3823 (match_operand:GPI 2 "register_operand" "r"))
3826 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3827 [(set_attr "type" "logics_shift_imm")]
3830 ;; -------------------------------------------------------------------
3832 ;; -------------------------------------------------------------------
3834 (define_expand "<optab><mode>3"
3835 [(set (match_operand:GPI 0 "register_operand")
3836 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3837 (match_operand:QI 2 "nonmemory_operand")))]
3840 if (CONST_INT_P (operands[2]))
3842 operands[2] = GEN_INT (INTVAL (operands[2])
3843 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3845 if (operands[2] == const0_rtx)
3847 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3854 (define_expand "ashl<mode>3"
3855 [(set (match_operand:SHORT 0 "register_operand")
3856 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3857 (match_operand:QI 2 "nonmemory_operand")))]
3860 if (CONST_INT_P (operands[2]))
3862 operands[2] = GEN_INT (INTVAL (operands[2])
3863 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3865 if (operands[2] == const0_rtx)
3867 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3876 (define_expand "rotr<mode>3"
3877 [(set (match_operand:GPI 0 "register_operand")
3878 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3879 (match_operand:QI 2 "nonmemory_operand")))]
3882 if (CONST_INT_P (operands[2]))
3884 operands[2] = GEN_INT (INTVAL (operands[2])
3885 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3887 if (operands[2] == const0_rtx)
3889 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3896 (define_expand "rotl<mode>3"
3897 [(set (match_operand:GPI 0 "register_operand")
3898 (rotatert:GPI (match_operand:GPI 1 "register_operand")
3899 (match_operand:QI 2 "nonmemory_operand")))]
3902 /* (SZ - cnt) % SZ == -cnt % SZ */
3903 if (CONST_INT_P (operands[2]))
3905 operands[2] = GEN_INT ((-INTVAL (operands[2]))
3906 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3907 if (operands[2] == const0_rtx)
3909 emit_insn (gen_mov<mode> (operands[0], operands[1]));
3914 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3919 ;; Logical left shift using SISD or Integer instruction
3920 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3921 [(set (match_operand:GPI 0 "register_operand" "=r,w,w")
3923 (match_operand:GPI 1 "register_operand" "r,w,w")
3924 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>,Us<cmode>,w")))]
3927 lsl\t%<w>0, %<w>1, %<w>2
3928 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3929 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3930 [(set_attr "simd" "no,yes,yes")
3931 (set_attr "type" "shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3934 ;; Logical right shift using SISD or Integer instruction
3935 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3936 [(set (match_operand:GPI 0 "register_operand" "=r,w,&w,&w")
3938 (match_operand:GPI 1 "register_operand" "r,w,w,w")
3939 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>,Us<cmode>,w,0")))]
3942 lsr\t%<w>0, %<w>1, %<w>2
3943 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3946 [(set_attr "simd" "no,yes,yes,yes")
3947 (set_attr "type" "shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3951 [(set (match_operand:DI 0 "aarch64_simd_register")
3953 (match_operand:DI 1 "aarch64_simd_register")
3954 (match_operand:QI 2 "aarch64_simd_register")))]
3955 "TARGET_SIMD && reload_completed"
3957 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3959 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3961 operands[3] = gen_lowpart (QImode, operands[0]);
3966 [(set (match_operand:SI 0 "aarch64_simd_register")
3968 (match_operand:SI 1 "aarch64_simd_register")
3969 (match_operand:QI 2 "aarch64_simd_register")))]
3970 "TARGET_SIMD && reload_completed"
3972 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3974 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
3976 operands[3] = gen_lowpart (QImode, operands[0]);
3980 ;; Arithmetic right shift using SISD or Integer instruction
3981 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
3982 [(set (match_operand:GPI 0 "register_operand" "=r,w,&w,&w")
3984 (match_operand:GPI 1 "register_operand" "r,w,w,w")
3985 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "rUs<cmode>,Us<cmode>,w,0")))]
3988 asr\t%<w>0, %<w>1, %<w>2
3989 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3992 [(set_attr "simd" "no,yes,yes,yes")
3993 (set_attr "type" "shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3997 [(set (match_operand:DI 0 "aarch64_simd_register")
3999 (match_operand:DI 1 "aarch64_simd_register")
4000 (match_operand:QI 2 "aarch64_simd_register")))]
4001 "TARGET_SIMD && reload_completed"
4003 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4005 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4007 operands[3] = gen_lowpart (QImode, operands[0]);
4012 [(set (match_operand:SI 0 "aarch64_simd_register")
4014 (match_operand:SI 1 "aarch64_simd_register")
4015 (match_operand:QI 2 "aarch64_simd_register")))]
4016 "TARGET_SIMD && reload_completed"
4018 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4020 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4022 operands[3] = gen_lowpart (QImode, operands[0]);
4026 (define_insn "*aarch64_sisd_ushl"
4027 [(set (match_operand:DI 0 "register_operand" "=w")
4028 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4029 (match_operand:QI 2 "register_operand" "w")]
4032 "ushl\t%d0, %d1, %d2"
4033 [(set_attr "simd" "yes")
4034 (set_attr "type" "neon_shift_reg")]
4037 (define_insn "*aarch64_ushl_2s"
4038 [(set (match_operand:SI 0 "register_operand" "=w")
4039 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4040 (match_operand:QI 2 "register_operand" "w")]
4043 "ushl\t%0.2s, %1.2s, %2.2s"
4044 [(set_attr "simd" "yes")
4045 (set_attr "type" "neon_shift_reg")]
4048 (define_insn "*aarch64_sisd_sshl"
4049 [(set (match_operand:DI 0 "register_operand" "=w")
4050 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4051 (match_operand:QI 2 "register_operand" "w")]
4054 "sshl\t%d0, %d1, %d2"
4055 [(set_attr "simd" "yes")
4056 (set_attr "type" "neon_shift_reg")]
4059 (define_insn "*aarch64_sshl_2s"
4060 [(set (match_operand:SI 0 "register_operand" "=w")
4061 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4062 (match_operand:QI 2 "register_operand" "w")]
4065 "sshl\t%0.2s, %1.2s, %2.2s"
4066 [(set_attr "simd" "yes")
4067 (set_attr "type" "neon_shift_reg")]
4070 (define_insn "*aarch64_sisd_neg_qi"
4071 [(set (match_operand:QI 0 "register_operand" "=w")
4072 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4076 [(set_attr "simd" "yes")
4077 (set_attr "type" "neon_neg")]
4081 (define_insn "*ror<mode>3_insn"
4082 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4084 (match_operand:GPI 1 "register_operand" "r,r")
4085 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "r,Us<cmode>")))]
4087 "ror\\t%<w>0, %<w>1, %<w>2"
4088 [(set_attr "type" "shift_reg, rotate_imm")]
4091 ;; zero_extend version of above
4092 (define_insn "*<optab>si3_insn_uxtw"
4093 [(set (match_operand:DI 0 "register_operand" "=r")
4094 (zero_extend:DI (SHIFT:SI
4095 (match_operand:SI 1 "register_operand" "r")
4096 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss"))))]
4098 "<shift>\\t%w0, %w1, %w2"
4099 [(set_attr "type" "shift_reg")]
4102 (define_insn "*<optab><mode>3_insn"
4103 [(set (match_operand:SHORT 0 "register_operand" "=r")
4104 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4105 (match_operand 2 "const_int_operand" "n")))]
4106 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4108 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4109 return "<bfshift>\t%w0, %w1, %2, %3";
4111 [(set_attr "type" "bfm")]
4114 (define_insn "*extr<mode>5_insn"
4115 [(set (match_operand:GPI 0 "register_operand" "=r")
4116 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4117 (match_operand 3 "const_int_operand" "n"))
4118 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4119 (match_operand 4 "const_int_operand" "n"))))]
4120 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4121 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4122 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4123 [(set_attr "type" "shift_imm")]
4126 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4127 ;; so we have to match both orderings.
4128 (define_insn "*extr<mode>5_insn_alt"
4129 [(set (match_operand:GPI 0 "register_operand" "=r")
4130 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4131 (match_operand 4 "const_int_operand" "n"))
4132 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4133 (match_operand 3 "const_int_operand" "n"))))]
4134 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4135 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4136 == GET_MODE_BITSIZE (<MODE>mode))"
4137 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4138 [(set_attr "type" "shift_imm")]
4141 ;; zero_extend version of the above
4142 (define_insn "*extrsi5_insn_uxtw"
4143 [(set (match_operand:DI 0 "register_operand" "=r")
4145 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4146 (match_operand 3 "const_int_operand" "n"))
4147 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4148 (match_operand 4 "const_int_operand" "n")))))]
4149 "UINTVAL (operands[3]) < 32 &&
4150 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4151 "extr\\t%w0, %w1, %w2, %4"
4152 [(set_attr "type" "shift_imm")]
4155 (define_insn "*extrsi5_insn_uxtw_alt"
4156 [(set (match_operand:DI 0 "register_operand" "=r")
4158 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4159 (match_operand 4 "const_int_operand" "n"))
4160 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4161 (match_operand 3 "const_int_operand" "n")))))]
4162 "UINTVAL (operands[3]) < 32 &&
4163 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4164 "extr\\t%w0, %w1, %w2, %4"
4165 [(set_attr "type" "shift_imm")]
4168 (define_insn "*ror<mode>3_insn"
4169 [(set (match_operand:GPI 0 "register_operand" "=r")
4170 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4171 (match_operand 2 "const_int_operand" "n")))]
4172 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4174 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4175 return "ror\\t%<w>0, %<w>1, %3";
4177 [(set_attr "type" "rotate_imm")]
4180 ;; zero_extend version of the above
4181 (define_insn "*rorsi3_insn_uxtw"
4182 [(set (match_operand:DI 0 "register_operand" "=r")
4184 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4185 (match_operand 2 "const_int_operand" "n"))))]
4186 "UINTVAL (operands[2]) < 32"
4188 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4189 return "ror\\t%w0, %w1, %3";
4191 [(set_attr "type" "rotate_imm")]
4194 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4195 [(set (match_operand:GPI 0 "register_operand" "=r")
4197 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4198 (match_operand 2 "const_int_operand" "n"))))]
4199 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4201 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4202 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4204 [(set_attr "type" "bfm")]
4207 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4208 [(set (match_operand:GPI 0 "register_operand" "=r")
4210 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4211 (match_operand 2 "const_int_operand" "n"))))]
4212 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4214 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4215 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4217 [(set_attr "type" "bfm")]
4220 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4221 [(set (match_operand:GPI 0 "register_operand" "=r")
4223 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4224 (match_operand 2 "const_int_operand" "n"))))]
4225 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4227 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4228 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4230 [(set_attr "type" "bfm")]
4233 ;; -------------------------------------------------------------------
4235 ;; -------------------------------------------------------------------
4237 (define_expand "<optab>"
4238 [(set (match_operand:DI 0 "register_operand" "=r")
4239 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
4240 (match_operand 2 "const_int_operand" "n")
4241 (match_operand 3 "const_int_operand" "n")))]
4246 (define_insn "*<optab><mode>"
4247 [(set (match_operand:GPI 0 "register_operand" "=r")
4248 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4249 (match_operand 2 "const_int_operand" "n")
4250 (match_operand 3 "const_int_operand" "n")))]
4252 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4253 [(set_attr "type" "bfm")]
4256 ;; Bitfield Insert (insv)
4257 (define_expand "insv<mode>"
4258 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4259 (match_operand 1 "const_int_operand")
4260 (match_operand 2 "const_int_operand"))
4261 (match_operand:GPI 3 "general_operand"))]
4264 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4265 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4266 rtx value = operands[3];
4268 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4271 if (CONST_INT_P (value))
4273 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4275 /* Prefer AND/OR for inserting all zeros or all ones. */
4276 if ((UINTVAL (value) & mask) == 0
4277 || (UINTVAL (value) & mask) == mask)
4280 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4281 if (width == 16 && (pos % 16) == 0)
4284 operands[3] = force_reg (<MODE>mode, value);
4287 (define_insn "*insv_reg<mode>"
4288 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4289 (match_operand 1 "const_int_operand" "n")
4290 (match_operand 2 "const_int_operand" "n"))
4291 (match_operand:GPI 3 "register_operand" "r"))]
4292 "!(UINTVAL (operands[1]) == 0
4293 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4294 > GET_MODE_BITSIZE (<MODE>mode)))"
4295 "bfi\\t%<w>0, %<w>3, %2, %1"
4296 [(set_attr "type" "bfm")]
4299 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4300 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4301 (match_operand 1 "const_int_operand" "n")
4302 (match_operand 2 "const_int_operand" "n"))
4303 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4304 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4305 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4306 [(set_attr "type" "bfm")]
4309 (define_insn "*extr_insv_lower_reg<mode>"
4310 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4311 (match_operand 1 "const_int_operand" "n")
4313 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4315 (match_operand 3 "const_int_operand" "n")))]
4316 "!(UINTVAL (operands[1]) == 0
4317 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4318 > GET_MODE_BITSIZE (<MODE>mode)))"
4319 "bfxil\\t%<w>0, %<w>2, %3, %1"
4320 [(set_attr "type" "bfm")]
4323 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4324 [(set (match_operand:GPI 0 "register_operand" "=r")
4325 (ashift:GPI (ANY_EXTEND:GPI
4326 (match_operand:ALLX 1 "register_operand" "r"))
4327 (match_operand 2 "const_int_operand" "n")))]
4328 "UINTVAL (operands[2]) < <GPI:sizen>"
4330 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4331 ? GEN_INT (<ALLX:sizen>)
4332 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4333 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4335 [(set_attr "type" "bfm")]
4338 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4340 (define_insn "*andim_ashift<mode>_bfiz"
4341 [(set (match_operand:GPI 0 "register_operand" "=r")
4342 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4343 (match_operand 2 "const_int_operand" "n"))
4344 (match_operand 3 "const_int_operand" "n")))]
4345 "(INTVAL (operands[2]) < (<GPI:sizen>))
4346 && exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
4347 && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
4348 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4349 [(set_attr "type" "bfm")]
4352 (define_insn "bswap<mode>2"
4353 [(set (match_operand:GPI 0 "register_operand" "=r")
4354 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4356 "rev\\t%<w>0, %<w>1"
4357 [(set_attr "type" "rev")]
4360 (define_insn "bswaphi2"
4361 [(set (match_operand:HI 0 "register_operand" "=r")
4362 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4365 [(set_attr "type" "rev")]
4368 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4369 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4370 ;; each valid permutation.
4372 (define_insn "rev16<mode>2"
4373 [(set (match_operand:GPI 0 "register_operand" "=r")
4374 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4376 (match_operand:GPI 3 "const_int_operand" "n"))
4377 (and:GPI (lshiftrt:GPI (match_dup 1)
4379 (match_operand:GPI 2 "const_int_operand" "n"))))]
4380 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4381 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4382 "rev16\\t%<w>0, %<w>1"
4383 [(set_attr "type" "rev")]
4386 (define_insn "rev16<mode>2_alt"
4387 [(set (match_operand:GPI 0 "register_operand" "=r")
4388 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4390 (match_operand:GPI 2 "const_int_operand" "n"))
4391 (and:GPI (ashift:GPI (match_dup 1)
4393 (match_operand:GPI 3 "const_int_operand" "n"))))]
4394 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4395 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4396 "rev16\\t%<w>0, %<w>1"
4397 [(set_attr "type" "rev")]
4400 ;; zero_extend version of above
4401 (define_insn "*bswapsi2_uxtw"
4402 [(set (match_operand:DI 0 "register_operand" "=r")
4403 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4406 [(set_attr "type" "rev")]
4409 ;; -------------------------------------------------------------------
4410 ;; Floating-point intrinsics
4411 ;; -------------------------------------------------------------------
4413 ;; frint floating-point round to integral standard patterns.
4414 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4416 (define_insn "<frint_pattern><mode>2"
4417 [(set (match_operand:GPF 0 "register_operand" "=w")
4418 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
4421 "frint<frint_suffix>\\t%<s>0, %<s>1"
4422 [(set_attr "type" "f_rint<s>")]
4425 ;; frcvt floating-point round to integer and convert standard patterns.
4426 ;; Expands to lbtrunc, lceil, lfloor, lround.
4427 (define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
4428 [(set (match_operand:GPI 0 "register_operand" "=r")
4429 (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
4432 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
4433 [(set_attr "type" "f_cvtf2i")]
4436 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4437 [(set (match_operand:GPI 0 "register_operand" "=r")
4440 (match_operand:GPF 1 "register_operand" "w")
4441 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4443 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4444 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4446 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4448 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4449 output_asm_insn (buf, operands);
4452 [(set_attr "type" "f_cvtf2i")]
4457 (define_insn "fma<mode>4"
4458 [(set (match_operand:GPF 0 "register_operand" "=w")
4459 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4460 (match_operand:GPF 2 "register_operand" "w")
4461 (match_operand:GPF 3 "register_operand" "w")))]
4463 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4464 [(set_attr "type" "fmac<s>")]
4467 (define_insn "fnma<mode>4"
4468 [(set (match_operand:GPF 0 "register_operand" "=w")
4469 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4470 (match_operand:GPF 2 "register_operand" "w")
4471 (match_operand:GPF 3 "register_operand" "w")))]
4473 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4474 [(set_attr "type" "fmac<s>")]
4477 (define_insn "fms<mode>4"
4478 [(set (match_operand:GPF 0 "register_operand" "=w")
4479 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4480 (match_operand:GPF 2 "register_operand" "w")
4481 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4483 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4484 [(set_attr "type" "fmac<s>")]
4487 (define_insn "fnms<mode>4"
4488 [(set (match_operand:GPF 0 "register_operand" "=w")
4489 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4490 (match_operand:GPF 2 "register_operand" "w")
4491 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4493 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4494 [(set_attr "type" "fmac<s>")]
4497 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4498 (define_insn "*fnmadd<mode>4"
4499 [(set (match_operand:GPF 0 "register_operand" "=w")
4500 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4501 (match_operand:GPF 2 "register_operand" "w")
4502 (match_operand:GPF 3 "register_operand" "w"))))]
4503 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4504 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4505 [(set_attr "type" "fmac<s>")]
4508 ;; -------------------------------------------------------------------
4509 ;; Floating-point conversions
4510 ;; -------------------------------------------------------------------
4512 (define_insn "extendsfdf2"
4513 [(set (match_operand:DF 0 "register_operand" "=w")
4514 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4517 [(set_attr "type" "f_cvt")]
4520 (define_insn "extendhfsf2"
4521 [(set (match_operand:SF 0 "register_operand" "=w")
4522 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4525 [(set_attr "type" "f_cvt")]
4528 (define_insn "extendhfdf2"
4529 [(set (match_operand:DF 0 "register_operand" "=w")
4530 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4533 [(set_attr "type" "f_cvt")]
4536 (define_insn "truncdfsf2"
4537 [(set (match_operand:SF 0 "register_operand" "=w")
4538 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4541 [(set_attr "type" "f_cvt")]
4544 (define_insn "truncsfhf2"
4545 [(set (match_operand:HF 0 "register_operand" "=w")
4546 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4549 [(set_attr "type" "f_cvt")]
4552 (define_insn "truncdfhf2"
4553 [(set (match_operand:HF 0 "register_operand" "=w")
4554 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4557 [(set_attr "type" "f_cvt")]
4560 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
4561 [(set (match_operand:GPI 0 "register_operand" "=r")
4562 (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
4564 "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
4565 [(set_attr "type" "f_cvtf2i")]
4568 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
4569 [(set (match_operand:GPI 0 "register_operand" "=r")
4570 (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
4572 "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
4573 [(set_attr "type" "f_cvtf2i")]
4576 (define_insn "<optab><fcvt_target><GPF:mode>2"
4577 [(set (match_operand:GPF 0 "register_operand" "=w,w")
4578 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4581 <su_optab>cvtf\t%<GPF:s>0, %<s>1
4582 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4583 [(set_attr "simd" "yes,no")
4584 (set_attr "fp" "no,yes")
4585 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4588 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4589 [(set (match_operand:GPF 0 "register_operand" "=w")
4590 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4592 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4593 [(set_attr "type" "f_cvti2f")]
4596 ;; -------------------------------------------------------------------
4597 ;; Floating-point arithmetic
4598 ;; -------------------------------------------------------------------
4600 (define_insn "add<mode>3"
4601 [(set (match_operand:GPF 0 "register_operand" "=w")
4603 (match_operand:GPF 1 "register_operand" "w")
4604 (match_operand:GPF 2 "register_operand" "w")))]
4606 "fadd\\t%<s>0, %<s>1, %<s>2"
4607 [(set_attr "type" "fadd<s>")]
4610 (define_insn "sub<mode>3"
4611 [(set (match_operand:GPF 0 "register_operand" "=w")
4613 (match_operand:GPF 1 "register_operand" "w")
4614 (match_operand:GPF 2 "register_operand" "w")))]
4616 "fsub\\t%<s>0, %<s>1, %<s>2"
4617 [(set_attr "type" "fadd<s>")]
4620 (define_insn "mul<mode>3"
4621 [(set (match_operand:GPF 0 "register_operand" "=w")
4623 (match_operand:GPF 1 "register_operand" "w")
4624 (match_operand:GPF 2 "register_operand" "w")))]
4626 "fmul\\t%<s>0, %<s>1, %<s>2"
4627 [(set_attr "type" "fmul<s>")]
4630 (define_insn "*fnmul<mode>3"
4631 [(set (match_operand:GPF 0 "register_operand" "=w")
4633 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4634 (match_operand:GPF 2 "register_operand" "w")))]
4635 "TARGET_FLOAT && !flag_rounding_math"
4636 "fnmul\\t%<s>0, %<s>1, %<s>2"
4637 [(set_attr "type" "fmul<s>")]
4640 (define_insn "*fnmul<mode>3"
4641 [(set (match_operand:GPF 0 "register_operand" "=w")
4643 (match_operand:GPF 1 "register_operand" "w")
4644 (match_operand:GPF 2 "register_operand" "w"))))]
4646 "fnmul\\t%<s>0, %<s>1, %<s>2"
4647 [(set_attr "type" "fmul<s>")]
4650 (define_insn "div<mode>3"
4651 [(set (match_operand:GPF 0 "register_operand" "=w")
4653 (match_operand:GPF 1 "register_operand" "w")
4654 (match_operand:GPF 2 "register_operand" "w")))]
4656 "fdiv\\t%<s>0, %<s>1, %<s>2"
4657 [(set_attr "type" "fdiv<s>")]
4660 (define_insn "neg<mode>2"
4661 [(set (match_operand:GPF 0 "register_operand" "=w")
4662 (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
4664 "fneg\\t%<s>0, %<s>1"
4665 [(set_attr "type" "ffarith<s>")]
4668 (define_insn "sqrt<mode>2"
4669 [(set (match_operand:GPF 0 "register_operand" "=w")
4670 (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
4672 "fsqrt\\t%<s>0, %<s>1"
4673 [(set_attr "type" "fsqrt<s>")]
4676 (define_insn "abs<mode>2"
4677 [(set (match_operand:GPF 0 "register_operand" "=w")
4678 (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
4680 "fabs\\t%<s>0, %<s>1"
4681 [(set_attr "type" "ffarith<s>")]
4684 ;; Given that smax/smin do not specify the result when either input is NaN,
4685 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4688 (define_insn "smax<mode>3"
4689 [(set (match_operand:GPF 0 "register_operand" "=w")
4690 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4691 (match_operand:GPF 2 "register_operand" "w")))]
4693 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4694 [(set_attr "type" "f_minmax<s>")]
4697 (define_insn "smin<mode>3"
4698 [(set (match_operand:GPF 0 "register_operand" "=w")
4699 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4700 (match_operand:GPF 2 "register_operand" "w")))]
4702 "fminnm\\t%<s>0, %<s>1, %<s>2"
4703 [(set_attr "type" "f_minmax<s>")]
4706 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
4707 (define_insn "<fmaxmin><mode>3"
4708 [(set (match_operand:GPF 0 "register_operand" "=w")
4709 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")
4710 (match_operand:GPF 2 "register_operand" "w")]
4713 "<fmaxmin_op>\\t%<s>0, %<s>1, %<s>2"
4714 [(set_attr "type" "f_minmax<s>")]
4717 ;; For copysign (x, y), we want to generate:
4719 ;; LDR d2, #(1 << 63)
4720 ;; BSL v2.8b, [y], [x]
4722 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4723 ;; aarch64_simd_bsldf will select the best suited of these instructions
4724 ;; to generate based on register allocation, and knows how to partially
4725 ;; constant fold based on the values of X and Y, so expand through that.
4727 (define_expand "copysigndf3"
4728 [(match_operand:DF 0 "register_operand")
4729 (match_operand:DF 1 "register_operand")
4730 (match_operand:DF 2 "register_operand")]
4731 "TARGET_FLOAT && TARGET_SIMD"
4733 rtx mask = gen_reg_rtx (DImode);
4734 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4735 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4736 operands[2], operands[1]));
4741 ;; As above, but we must first get to a 64-bit value if we wish to use
4742 ;; aarch64_simd_bslv2sf.
4744 (define_expand "copysignsf3"
4745 [(match_operand:SF 0 "register_operand")
4746 (match_operand:SF 1 "register_operand")
4747 (match_operand:SF 2 "register_operand")]
4748 "TARGET_FLOAT && TARGET_SIMD"
4750 rtx mask = gen_reg_rtx (DImode);
4752 /* Juggle modes to get us in to a vector mode for BSL. */
4753 rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4754 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4755 rtx tmp = gen_reg_rtx (V2SFmode);
4756 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4757 emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4758 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4763 ;; -------------------------------------------------------------------
4765 ;; -------------------------------------------------------------------
4766 ;; Reload Scalar Floating point modes from constant pool.
4767 ;; The AArch64 port doesn't have __int128 constant move support.
4768 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4769 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4770 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4771 (clobber (match_operand:P 2 "register_operand" "=&r"))]
4772 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4774 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4775 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4780 ;; Reload Vector modes from constant pool.
4781 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
4782 [(set (match_operand:VALL 0 "register_operand" "=w")
4783 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
4784 (clobber (match_operand:P 2 "register_operand" "=&r"))]
4785 "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4787 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4788 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
4793 (define_expand "aarch64_reload_mov<mode>"
4794 [(set (match_operand:TX 0 "register_operand" "=w")
4795 (match_operand:TX 1 "register_operand" "w"))
4796 (clobber (match_operand:DI 2 "register_operand" "=&r"))
4800 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
4801 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
4802 gen_aarch64_movtilow_tilow (op0, op1);
4803 gen_aarch64_movdi_tihigh (operands[2], op1);
4804 gen_aarch64_movtihigh_di (op0, operands[2]);
4809 ;; The following secondary reload helpers patterns are invoked
4810 ;; after or during reload as we don't want these patterns to start
4811 ;; kicking in during the combiner.
4813 (define_insn "aarch64_movdi_<mode>low"
4814 [(set (match_operand:DI 0 "register_operand" "=r")
4815 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
4816 (const_int 64) (const_int 0)))]
4817 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4819 [(set_attr "type" "f_mrc")
4820 (set_attr "length" "4")
4823 (define_insn "aarch64_movdi_<mode>high"
4824 [(set (match_operand:DI 0 "register_operand" "=r")
4825 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
4826 (const_int 64) (const_int 64)))]
4827 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4828 "fmov\\t%x0, %1.d[1]"
4829 [(set_attr "type" "f_mrc")
4830 (set_attr "length" "4")
4833 (define_insn "aarch64_mov<mode>high_di"
4834 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
4835 (const_int 64) (const_int 64))
4836 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4837 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4838 "fmov\\t%0.d[1], %x1"
4839 [(set_attr "type" "f_mcr")
4840 (set_attr "length" "4")
4843 (define_insn "aarch64_mov<mode>low_di"
4844 [(set (match_operand:TX 0 "register_operand" "=w")
4845 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4846 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4848 [(set_attr "type" "f_mcr")
4849 (set_attr "length" "4")
4852 (define_insn "aarch64_movtilow_tilow"
4853 [(set (match_operand:TI 0 "register_operand" "=w")
4855 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
4856 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4858 [(set_attr "type" "fmov")
4859 (set_attr "length" "4")
4862 ;; There is a deliberate reason why the parameters of high and lo_sum's
4863 ;; don't have modes for ADRP and ADD instructions. This is to allow high
4864 ;; and lo_sum's to be used with the labels defining the jump tables in
4867 (define_expand "add_losym"
4868 [(set (match_operand 0 "register_operand" "=r")
4869 (lo_sum (match_operand 1 "register_operand" "r")
4870 (match_operand 2 "aarch64_valid_symref" "S")))]
4873 machine_mode mode = GET_MODE (operands[0]);
4875 emit_insn ((mode == DImode
4877 : gen_add_losym_si) (operands[0],
4883 (define_insn "add_losym_<mode>"
4884 [(set (match_operand:P 0 "register_operand" "=r")
4885 (lo_sum:P (match_operand:P 1 "register_operand" "r")
4886 (match_operand 2 "aarch64_valid_symref" "S")))]
4888 "add\\t%<w>0, %<w>1, :lo12:%a2"
4889 [(set_attr "type" "alu_imm")]
4892 (define_insn "ldr_got_small_<mode>"
4893 [(set (match_operand:PTR 0 "register_operand" "=r")
4894 (unspec:PTR [(mem:PTR (lo_sum:PTR
4895 (match_operand:PTR 1 "register_operand" "r")
4896 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
4897 UNSPEC_GOTSMALLPIC))]
4899 "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
4900 [(set_attr "type" "load1")]
4903 (define_insn "ldr_got_small_sidi"
4904 [(set (match_operand:DI 0 "register_operand" "=r")
4906 (unspec:SI [(mem:SI (lo_sum:DI
4907 (match_operand:DI 1 "register_operand" "r")
4908 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
4909 UNSPEC_GOTSMALLPIC)))]
4911 "ldr\\t%w0, [%1, #:got_lo12:%a2]"
4912 [(set_attr "type" "load1")]
4915 (define_insn "ldr_got_small_28k_<mode>"
4916 [(set (match_operand:PTR 0 "register_operand" "=r")
4917 (unspec:PTR [(mem:PTR (lo_sum:PTR
4918 (match_operand:PTR 1 "register_operand" "r")
4919 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
4920 UNSPEC_GOTSMALLPIC28K))]
4922 "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
4923 [(set_attr "type" "load1")]
4926 (define_insn "ldr_got_small_28k_sidi"
4927 [(set (match_operand:DI 0 "register_operand" "=r")
4929 (unspec:SI [(mem:SI (lo_sum:DI
4930 (match_operand:DI 1 "register_operand" "r")
4931 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
4932 UNSPEC_GOTSMALLPIC28K)))]
4934 "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
4935 [(set_attr "type" "load1")]
4938 (define_insn "ldr_got_tiny"
4939 [(set (match_operand:DI 0 "register_operand" "=r")
4940 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
4941 UNSPEC_GOTTINYPIC))]
4944 [(set_attr "type" "load1")]
4947 (define_insn "aarch64_load_tp_hard"
4948 [(set (match_operand:DI 0 "register_operand" "=r")
4949 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
4951 "mrs\\t%0, tpidr_el0"
4952 [(set_attr "type" "mrs")]
4955 ;; The TLS ABI specifically requires that the compiler does not schedule
4956 ;; instructions in the TLS stubs, in order to enable linker relaxation.
4957 ;; Therefore we treat the stubs as an atomic sequence.
4958 (define_expand "tlsgd_small"
4959 [(parallel [(set (match_operand 0 "register_operand" "")
4960 (call (mem:DI (match_dup 2)) (const_int 1)))
4961 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
4962 (clobber (reg:DI LR_REGNUM))])]
4965 operands[2] = aarch64_tls_get_addr ();
4968 (define_insn "*tlsgd_small"
4969 [(set (match_operand 0 "register_operand" "")
4970 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
4971 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
4972 (clobber (reg:DI LR_REGNUM))
4975 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
4976 [(set_attr "type" "call")
4977 (set_attr "length" "16")])
4979 (define_insn "tlsie_small_<mode>"
4980 [(set (match_operand:PTR 0 "register_operand" "=r")
4981 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4982 UNSPEC_GOTSMALLTLS))]
4984 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
4985 [(set_attr "type" "load1")
4986 (set_attr "length" "8")]
4989 (define_insn "tlsie_small_sidi"
4990 [(set (match_operand:DI 0 "register_operand" "=r")
4992 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4993 UNSPEC_GOTSMALLTLS)))]
4995 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
4996 [(set_attr "type" "load1")
4997 (set_attr "length" "8")]
5000 (define_insn "tlsie_tiny_<mode>"
5001 [(set (match_operand:PTR 0 "register_operand" "=&r")
5002 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5003 (match_operand:PTR 2 "register_operand" "r")]
5004 UNSPEC_GOTTINYTLS))]
5006 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5007 [(set_attr "type" "multiple")
5008 (set_attr "length" "8")]
5011 (define_insn "tlsie_tiny_sidi"
5012 [(set (match_operand:DI 0 "register_operand" "=&r")
5014 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5015 (match_operand:DI 2 "register_operand" "r")
5017 UNSPEC_GOTTINYTLS)))]
5019 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5020 [(set_attr "type" "multiple")
5021 (set_attr "length" "8")]
5024 (define_insn "tlsle12_<mode>"
5025 [(set (match_operand:P 0 "register_operand" "=r")
5026 (unspec:P [(match_operand:P 1 "register_operand" "r")
5027 (match_operand 2 "aarch64_tls_le_symref" "S")]
5030 "add\\t%<w>0, %<w>1, #%L2";
5031 [(set_attr "type" "alu_sreg")
5032 (set_attr "length" "4")]
5035 (define_insn "tlsle24_<mode>"
5036 [(set (match_operand:P 0 "register_operand" "=r")
5037 (unspec:P [(match_operand:P 1 "register_operand" "r")
5038 (match_operand 2 "aarch64_tls_le_symref" "S")]
5041 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5042 [(set_attr "type" "multiple")
5043 (set_attr "length" "8")]
5046 (define_insn "tlsle32_<mode>"
5047 [(set (match_operand:P 0 "register_operand" "=r")
5048 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5051 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5052 [(set_attr "type" "multiple")
5053 (set_attr "length" "8")]
5056 (define_insn "tlsle48_<mode>"
5057 [(set (match_operand:P 0 "register_operand" "=r")
5058 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5061 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5062 [(set_attr "type" "multiple")
5063 (set_attr "length" "12")]
5066 (define_insn "tlsdesc_small_<mode>"
5067 [(set (reg:PTR R0_REGNUM)
5068 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5070 (clobber (reg:DI LR_REGNUM))
5071 (clobber (reg:CC CC_REGNUM))
5072 (clobber (match_scratch:DI 1 "=r"))]
5074 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5075 [(set_attr "type" "call")
5076 (set_attr "length" "16")])
5078 (define_insn "stack_tie"
5079 [(set (mem:BLK (scratch))
5080 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5081 (match_operand:DI 1 "register_operand" "rk")]
5085 [(set_attr "length" "0")]
5088 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5089 ;; all of memory. This blocks insns from being moved across this point.
5091 (define_insn "blockage"
5092 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5095 [(set_attr "length" "0")
5096 (set_attr "type" "block")]
5099 (define_insn "probe_stack_range_<PTR:mode>"
5100 [(set (match_operand:PTR 0 "register_operand" "=r")
5101 (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5102 (match_operand:PTR 2 "register_operand" "r")]
5103 UNSPECV_PROBE_STACK_RANGE))]
5106 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5108 [(set_attr "length" "32")]
5111 ;; Named pattern for expanding thread pointer reference.
5112 (define_expand "get_thread_pointerdi"
5113 [(match_operand:DI 0 "register_operand" "=r")]
5116 rtx tmp = aarch64_load_tp (operands[0]);
5117 if (tmp != operands[0])
5118 emit_move_insn (operands[0], tmp);
5122 ;; Named patterns for stack smashing protection.
5123 (define_expand "stack_protect_set"
5124 [(match_operand 0 "memory_operand")
5125 (match_operand 1 "memory_operand")]
5128 machine_mode mode = GET_MODE (operands[0]);
5130 emit_insn ((mode == DImode
5131 ? gen_stack_protect_set_di
5132 : gen_stack_protect_set_si) (operands[0], operands[1]));
5136 (define_insn "stack_protect_set_<mode>"
5137 [(set (match_operand:PTR 0 "memory_operand" "=m")
5138 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5140 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5142 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5143 [(set_attr "length" "12")
5144 (set_attr "type" "multiple")])
5146 (define_expand "stack_protect_test"
5147 [(match_operand 0 "memory_operand")
5148 (match_operand 1 "memory_operand")
5153 machine_mode mode = GET_MODE (operands[0]);
5155 result = gen_reg_rtx(mode);
5157 emit_insn ((mode == DImode
5158 ? gen_stack_protect_test_di
5159 : gen_stack_protect_test_si) (result,
5164 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5165 result, const0_rtx, operands[2]));
5167 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5168 result, const0_rtx, operands[2]));
5172 (define_insn "stack_protect_test_<mode>"
5173 [(set (match_operand:PTR 0 "register_operand" "=r")
5174 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5175 (match_operand:PTR 2 "memory_operand" "m")]
5177 (clobber (match_scratch:PTR 3 "=&r"))]
5179 "ldr\t%<w>3, %x1\;ldr\t%<w>0, %x2\;eor\t%<w>0, %<w>3, %<w>0"
5180 [(set_attr "length" "12")
5181 (set_attr "type" "multiple")])
5183 ;; Write Floating-point Control Register.
5184 (define_insn "set_fpcr"
5185 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5188 [(set_attr "type" "mrs")])
5190 ;; Read Floating-point Control Register.
5191 (define_insn "get_fpcr"
5192 [(set (match_operand:SI 0 "register_operand" "=r")
5193 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5196 [(set_attr "type" "mrs")])
5198 ;; Write Floating-point Status Register.
5199 (define_insn "set_fpsr"
5200 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5203 [(set_attr "type" "mrs")])
5205 ;; Read Floating-point Status Register.
5206 (define_insn "get_fpsr"
5207 [(set (match_operand:SI 0 "register_operand" "=r")
5208 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5211 [(set_attr "type" "mrs")])
5214 ;; Define the subtract-one-and-jump insns so loop.c
5215 ;; knows what to generate.
5216 (define_expand "doloop_end"
5217 [(use (match_operand 0 "" "")) ; loop pseudo
5218 (use (match_operand 1 "" ""))] ; label
5219 "optimize > 0 && flag_modulo_sched"
5228 /* Currently SMS relies on the do-loop pattern to recognize loops
5229 where (1) the control part consists of all insns defining and/or
5230 using a certain 'count' register and (2) the loop count can be
5231 adjusted by modifying this register prior to the loop.
5232 ??? The possible introduction of a new block to initialize the
5233 new IV can potentially affect branch optimizations. */
5235 if (GET_MODE (operands[0]) != DImode)
5239 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5241 cmp = XVECEXP (PATTERN (insn), 0, 0);
5242 cc_reg = SET_DEST (cmp);
5243 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5244 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5245 emit_jump_insn (gen_rtx_SET (pc_rtx,
5246 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5252 (include "aarch64-simd.md")
5254 ;; Atomic Operations
5255 (include "atomics.md")
5257 ;; ldp/stp peephole patterns
5258 (include "aarch64-ldpstp.md")