[AArch64] Separate shrink wrapping hooks implementation
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob1e6b6f5ba7cd20778cb9550f58d4771970a59a6d
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
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)
10 ;; any later version.
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/>.
21 ;; Register numbers
22 (define_constants
23   [
24     (R0_REGNUM          0)
25     (R1_REGNUM          1)
26     (R2_REGNUM          2)
27     (R3_REGNUM          3)
28     (R4_REGNUM          4)
29     (R5_REGNUM          5)
30     (R6_REGNUM          6)
31     (R7_REGNUM          7)
32     (R8_REGNUM          8)
33     (R9_REGNUM          9)
34     (R10_REGNUM         10)
35     (R11_REGNUM         11)
36     (R12_REGNUM         12)
37     (R13_REGNUM         13)
38     (R14_REGNUM         14)
39     (R15_REGNUM         15)
40     (R16_REGNUM         16)
41     (IP0_REGNUM         16)
42     (R17_REGNUM         17)
43     (IP1_REGNUM         17)
44     (R18_REGNUM         18)
45     (R19_REGNUM         19)
46     (R20_REGNUM         20)
47     (R21_REGNUM         21)
48     (R22_REGNUM         22)
49     (R23_REGNUM         23)
50     (R24_REGNUM         24)
51     (R25_REGNUM         25)
52     (R26_REGNUM         26)
53     (R27_REGNUM         27)
54     (R28_REGNUM         28)
55     (R29_REGNUM         29)
56     (R30_REGNUM         30)
57     (LR_REGNUM          30)
58     (SP_REGNUM          31)
59     (V0_REGNUM          32)
60     (V15_REGNUM         47)
61     (V31_REGNUM         63)
62     (LAST_SAVED_REGNUM  63)
63     (SFP_REGNUM         64)
64     (AP_REGNUM          65)
65     (CC_REGNUM          66)
66   ]
69 (define_c_enum "unspec" [
70     UNSPEC_CASESI
71     UNSPEC_CRC32B
72     UNSPEC_CRC32CB
73     UNSPEC_CRC32CH
74     UNSPEC_CRC32CW
75     UNSPEC_CRC32CX
76     UNSPEC_CRC32H
77     UNSPEC_CRC32W
78     UNSPEC_CRC32X
79     UNSPEC_FCVTZS
80     UNSPEC_FCVTZU
81     UNSPEC_URECPE
82     UNSPEC_FRECPE
83     UNSPEC_FRECPS
84     UNSPEC_FRECPX
85     UNSPEC_FRINTA
86     UNSPEC_FRINTI
87     UNSPEC_FRINTM
88     UNSPEC_FRINTN
89     UNSPEC_FRINTP
90     UNSPEC_FRINTX
91     UNSPEC_FRINTZ
92     UNSPEC_GOTSMALLPIC
93     UNSPEC_GOTSMALLPIC28K
94     UNSPEC_GOTSMALLTLS
95     UNSPEC_GOTTINYPIC
96     UNSPEC_GOTTINYTLS
97     UNSPEC_LD1
98     UNSPEC_LD2
99     UNSPEC_LD2_DUP
100     UNSPEC_LD3
101     UNSPEC_LD3_DUP
102     UNSPEC_LD4
103     UNSPEC_LD4_DUP
104     UNSPEC_LD2_LANE
105     UNSPEC_LD3_LANE
106     UNSPEC_LD4_LANE
107     UNSPEC_MB
108     UNSPEC_NOP
109     UNSPEC_PRLG_STK
110     UNSPEC_RBIT
111     UNSPEC_SCVTF
112     UNSPEC_SISD_NEG
113     UNSPEC_SISD_SSHL
114     UNSPEC_SISD_USHL
115     UNSPEC_SSHL_2S
116     UNSPEC_ST1
117     UNSPEC_ST2
118     UNSPEC_ST3
119     UNSPEC_ST4
120     UNSPEC_ST2_LANE
121     UNSPEC_ST3_LANE
122     UNSPEC_ST4_LANE
123     UNSPEC_TLS
124     UNSPEC_TLSDESC
125     UNSPEC_TLSLE12
126     UNSPEC_TLSLE24
127     UNSPEC_TLSLE32
128     UNSPEC_TLSLE48
129     UNSPEC_UCVTF
130     UNSPEC_USHL_2S
131     UNSPEC_VSTRUCTDUMMY
132     UNSPEC_SP_SET
133     UNSPEC_SP_TEST
134     UNSPEC_RSQRT
135     UNSPEC_RSQRTE
136     UNSPEC_RSQRTS
137     UNSPEC_NZCV
140 (define_c_enum "unspecv" [
141     UNSPECV_EH_RETURN           ; Represent EH_RETURN
142     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
143     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
144     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
145     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
146     UNSPECV_BLOCKAGE            ; Represent a blockage
147     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
148   ]
151 ;; If further include files are added the defintion of MD_INCLUDES
152 ;; must be updated.
154 (include "constraints.md")
155 (include "predicates.md")
156 (include "iterators.md")
158 ;; -------------------------------------------------------------------
159 ;; Instruction types and attributes
160 ;; -------------------------------------------------------------------
162 ; The "type" attribute is included here from AArch32 backend to be able
163 ; to share pipeline descriptions.
164 (include "../arm/types.md")
166 ;; It is important to set the fp or simd attributes to yes when a pattern
167 ;; alternative uses the FP or SIMD register files, usually signified by use of
168 ;; the 'w' constraint.  This will ensure that the alternative will be
169 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
170 ;; architecture extensions.  If all the alternatives in a pattern use the
171 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
172 ;; or TARGET_SIMD.
174 ;; Attribute that specifies whether or not the instruction touches fp
175 ;; registers.  When this is set to yes for an alternative, that alternative
176 ;; will be disabled when !TARGET_FLOAT.
177 (define_attr "fp" "no,yes" (const_string "no"))
179 ;; Attribute that specifies whether or not the instruction touches simd
180 ;; registers.  When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_SIMD.
182 (define_attr "simd" "no,yes" (const_string "no"))
184 (define_attr "length" ""
185   (const_int 4))
187 ;; Attribute that controls whether an alternative is enabled or not.
188 ;; Currently it is only used to disable alternatives which touch fp or simd
189 ;; registers when -mgeneral-regs-only is specified.
190 (define_attr "enabled" "no,yes"
191   (cond [(ior
192         (and (eq_attr "fp" "yes")
193              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
194         (and (eq_attr "simd" "yes")
195              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
196              (const_string "no")
197         ] (const_string "yes")))
199 ;; Attribute that specifies whether we are dealing with a branch to a
200 ;; label that is far away, i.e. further away than the maximum/minimum
201 ;; representable in a signed 21-bits number.
202 ;; 0 :=: no
203 ;; 1 :=: yes
204 (define_attr "far_branch" "" (const_int 0))
206 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
207 ;; no predicated insns.
208 (define_attr "predicated" "yes,no" (const_string "no"))
210 ;; -------------------------------------------------------------------
211 ;; Pipeline descriptions and scheduling
212 ;; -------------------------------------------------------------------
214 ;; Processor types.
215 (include "aarch64-tune.md")
217 ;; Scheduling
218 (include "../arm/cortex-a53.md")
219 (include "../arm/cortex-a57.md")
220 (include "../arm/exynos-m1.md")
221 (include "thunderx.md")
222 (include "../arm/xgene1.md")
224 ;; -------------------------------------------------------------------
225 ;; Jumps and other miscellaneous insns
226 ;; -------------------------------------------------------------------
228 (define_insn "indirect_jump"
229   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
230   ""
231   "br\\t%0"
232   [(set_attr "type" "branch")]
235 (define_insn "jump"
236   [(set (pc) (label_ref (match_operand 0 "" "")))]
237   ""
238   "b\\t%l0"
239   [(set_attr "type" "branch")]
242 (define_expand "cbranch<mode>4"
243   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
244                             [(match_operand:GPI 1 "register_operand" "")
245                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
246                            (label_ref (match_operand 3 "" ""))
247                            (pc)))]
248   ""
249   "
250   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
251                                          operands[2]);
252   operands[2] = const0_rtx;
253   "
256 (define_expand "cbranch<mode>4"
257   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
258                             [(match_operand:GPF 1 "register_operand" "")
259                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
260                            (label_ref (match_operand 3 "" ""))
261                            (pc)))]
262   ""
263   "
264   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
265                                          operands[2]);
266   operands[2] = const0_rtx;
267   "
270 (define_expand "cbranchcc4"
271   [(set (pc) (if_then_else
272               (match_operator 0 "aarch64_comparison_operator"
273                [(match_operand 1 "cc_register" "")
274                 (match_operand 2 "const0_operand")])
275               (label_ref (match_operand 3 "" ""))
276               (pc)))]
277   ""
278   "")
280 (define_insn "ccmp<mode>"
281   [(set (match_operand:CC 1 "cc_register" "")
282         (if_then_else:CC
283           (match_operator 4 "aarch64_comparison_operator"
284            [(match_operand 0 "cc_register" "")
285             (const_int 0)])
286           (compare:CC
287             (match_operand:GPI 2 "register_operand" "r,r,r")
288             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
289           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
290   ""
291   "@
292    ccmp\\t%<w>2, %<w>3, %k5, %m4
293    ccmp\\t%<w>2, %3, %k5, %m4
294    ccmn\\t%<w>2, #%n3, %k5, %m4"
295   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
298 (define_insn "fccmp<mode>"
299   [(set (match_operand:CCFP 1 "cc_register" "")
300         (if_then_else:CCFP
301           (match_operator 4 "aarch64_comparison_operator"
302            [(match_operand 0 "cc_register" "")
303             (const_int 0)])
304           (compare:CCFP
305             (match_operand:GPF 2 "register_operand" "w")
306             (match_operand:GPF 3 "register_operand" "w"))
307           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
308   "TARGET_FLOAT"
309   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
310   [(set_attr "type" "fccmp<s>")]
313 (define_insn "fccmpe<mode>"
314   [(set (match_operand:CCFPE 1 "cc_register" "")
315          (if_then_else:CCFPE
316           (match_operator 4 "aarch64_comparison_operator"
317            [(match_operand 0 "cc_register" "")
318           (const_int 0)])
319            (compare:CCFPE
320             (match_operand:GPF 2 "register_operand" "w")
321             (match_operand:GPF 3 "register_operand" "w"))
322           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
323   "TARGET_FLOAT"
324   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
325   [(set_attr "type" "fccmp<s>")]
328 ;; Expansion of signed mod by a power of 2 using CSNEG.
329 ;; For x0 % n where n is a power of 2 produce:
330 ;; negs   x1, x0
331 ;; and    x0, x0, #(n - 1)
332 ;; and    x1, x1, #(n - 1)
333 ;; csneg  x0, x0, x1, mi
335 (define_expand "mod<mode>3"
336   [(match_operand:GPI 0 "register_operand" "")
337    (match_operand:GPI 1 "register_operand" "")
338    (match_operand:GPI 2 "const_int_operand" "")]
339   ""
340   {
341     HOST_WIDE_INT val = INTVAL (operands[2]);
343     if (val <= 0
344        || exact_log2 (val) <= 0
345        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
346       FAIL;
348     rtx mask = GEN_INT (val - 1);
350     /* In the special case of x0 % 2 we can do the even shorter:
351         cmp    x0, xzr
352         and    x0, x0, 1
353         cneg   x0, x0, lt.  */
354     if (val == 2)
355       {
356         rtx masked = gen_reg_rtx (<MODE>mode);
357         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
358         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
359         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
360         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
361         DONE;
362       }
364     rtx neg_op = gen_reg_rtx (<MODE>mode);
365     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
367     /* Extract the condition register and mode.  */
368     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
369     rtx cc_reg = SET_DEST (cmp);
370     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
372     rtx masked_pos = gen_reg_rtx (<MODE>mode);
373     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
375     rtx masked_neg = gen_reg_rtx (<MODE>mode);
376     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
378     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
379                                        masked_neg, masked_pos));
380     DONE;
381   }
384 (define_insn "condjump"
385   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
386                             [(match_operand 1 "cc_register" "") (const_int 0)])
387                            (label_ref (match_operand 2 "" ""))
388                            (pc)))]
389   ""
390   {
391     if (get_attr_length (insn) == 8)
392       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
393     else
394       return  "b%m0\\t%l2";
395   }
396   [(set_attr "type" "branch")
397    (set (attr "length")
398         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
399                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
400                       (const_int 4)
401                       (const_int 8)))
402    (set (attr "far_branch")
403         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
404                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
405                       (const_int 0)
406                       (const_int 1)))]
409 ;; For a 24-bit immediate CST we can optimize the compare for equality
410 ;; and branch sequence from:
411 ;;      mov     x0, #imm1
412 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
413 ;;      cmp     x1, x0
414 ;;      b<ne,eq> .Label
415 ;; into the shorter:
416 ;;      sub     x0, x1, #(CST & 0xfff000)
417 ;;      subs    x0, x0, #(CST & 0x000fff)
418 ;;      b<ne,eq> .Label
419 (define_insn_and_split "*compare_condjump<mode>"
420   [(set (pc) (if_then_else (EQL
421                               (match_operand:GPI 0 "register_operand" "r")
422                               (match_operand:GPI 1 "aarch64_imm24" "n"))
423                            (label_ref:P (match_operand 2 "" ""))
424                            (pc)))]
425   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
426    && !aarch64_plus_operand (operands[1], <MODE>mode)
427    && !reload_completed"
428   "#"
429   "&& true"
430   [(const_int 0)]
431   {
432     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
433     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
434     rtx tmp = gen_reg_rtx (<MODE>mode);
435     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
436     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
437     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
438     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
439     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
440     DONE;
441   }
444 (define_expand "casesi"
445   [(match_operand:SI 0 "register_operand" "")   ; Index
446    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
447    (match_operand:SI 2 "const_int_operand" "")  ; Total range
448    (match_operand:DI 3 "" "")                   ; Table label
449    (match_operand:DI 4 "" "")]                  ; Out of range label
450   ""
451   {
452     if (operands[1] != const0_rtx)
453       {
454         rtx reg = gen_reg_rtx (SImode);
456         /* Canonical RTL says that if you have:
458            (minus (X) (CONST))
460            then this should be emitted as:
462            (plus (X) (-CONST))
464            The use of trunc_int_for_mode ensures that the resulting
465            constant can be represented in SImode, this is important
466            for the corner case where operand[1] is INT_MIN.  */
468         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
470         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
471               (operands[1], SImode))
472           operands[1] = force_reg (SImode, operands[1]);
473         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
474         operands[0] = reg;
475       }
477     if (!aarch64_plus_operand (operands[2], SImode))
478       operands[2] = force_reg (SImode, operands[2]);
479     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
480                                                  const0_rtx),
481                                     operands[0], operands[2], operands[4]));
483     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
484     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
485                                          operands[3]));
486     DONE;
487   }
490 (define_insn "casesi_dispatch"
491   [(parallel
492     [(set (pc)
493           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
494                            (match_operand:SI 1 "register_operand" "r")]
495                         UNSPEC_CASESI)))
496      (clobber (reg:CC CC_REGNUM))
497      (clobber (match_scratch:DI 3 "=r"))
498      (clobber (match_scratch:DI 4 "=r"))
499      (use (label_ref (match_operand 2 "" "")))])]
500   ""
501   "*
502   return aarch64_output_casesi (operands);
503   "
504   [(set_attr "length" "16")
505    (set_attr "type" "branch")]
508 (define_insn "nop"
509   [(unspec[(const_int 0)] UNSPEC_NOP)]
510   ""
511   "nop"
512   [(set_attr "type" "no_insn")]
515 (define_insn "prefetch"
516   [(prefetch (match_operand:DI 0 "register_operand" "r")
517             (match_operand:QI 1 "const_int_operand" "")
518             (match_operand:QI 2 "const_int_operand" ""))]
519   ""
520   {
521     const char * pftype[2][4] = 
522     {
523       {"prfm\\tPLDL1STRM, %a0",
524        "prfm\\tPLDL3KEEP, %a0",
525        "prfm\\tPLDL2KEEP, %a0",
526        "prfm\\tPLDL1KEEP, %a0"},
527       {"prfm\\tPSTL1STRM, %a0",
528        "prfm\\tPSTL3KEEP, %a0",
529        "prfm\\tPSTL2KEEP, %a0",
530        "prfm\\tPSTL1KEEP, %a0"},
531     };
533     int locality = INTVAL (operands[2]);
535     gcc_assert (IN_RANGE (locality, 0, 3));
537     return pftype[INTVAL(operands[1])][locality];
538   }
539   [(set_attr "type" "load1")]
542 (define_insn "trap"
543   [(trap_if (const_int 1) (const_int 8))]
544   ""
545   "brk #1000"
546   [(set_attr "type" "trap")])
548 (define_expand "prologue"
549   [(clobber (const_int 0))]
550   ""
551   "
552   aarch64_expand_prologue ();
553   DONE;
554   "
557 (define_expand "epilogue"
558   [(clobber (const_int 0))]
559   ""
560   "
561   aarch64_expand_epilogue (false);
562   DONE;
563   "
566 (define_expand "sibcall_epilogue"
567   [(clobber (const_int 0))]
568   ""
569   "
570   aarch64_expand_epilogue (true);
571   DONE;
572   "
575 (define_insn "*do_return"
576   [(return)]
577   ""
578   "ret"
579   [(set_attr "type" "branch")]
582 (define_expand "return"
583   [(simple_return)]
584   "aarch64_use_return_insn_p ()"
585   ""
588 (define_insn "simple_return"
589   [(simple_return)]
590   ""
591   "ret"
592   [(set_attr "type" "branch")]
595 (define_insn "eh_return"
596   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
597     UNSPECV_EH_RETURN)]
598   ""
599   "#"
600   [(set_attr "type" "branch")]
604 (define_split
605   [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
606     UNSPECV_EH_RETURN)]
607   "reload_completed"
608   [(set (match_dup 1) (match_dup 0))]
609   {
610     operands[1] = aarch64_final_eh_return_addr ();
611   }
614 (define_insn "*cb<optab><mode>1"
615   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
616                                 (const_int 0))
617                            (label_ref (match_operand 1 "" ""))
618                            (pc)))]
619   ""
620   {
621     if (get_attr_length (insn) == 8)
622       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
623     else
624       return "<cbz>\\t%<w>0, %l1";
625   }
626   [(set_attr "type" "branch")
627    (set (attr "length")
628         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
629                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
630                       (const_int 4)
631                       (const_int 8)))
632    (set (attr "far_branch")
633         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
634                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
635                       (const_int 0)
636                       (const_int 1)))]
639 (define_insn "*tb<optab><mode>1"
640   [(set (pc) (if_then_else
641               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
642                                     (const_int 1)
643                                     (match_operand 1
644                                       "aarch64_simd_shift_imm_<mode>" "n"))
645                    (const_int 0))
646              (label_ref (match_operand 2 "" ""))
647              (pc)))
648    (clobber (reg:CC CC_REGNUM))]
649   ""
650   {
651     if (get_attr_length (insn) == 8)
652       {
653         if (get_attr_far_branch (insn) == 1)
654           return aarch64_gen_far_branch (operands, 2, "Ltb",
655                                          "<inv_tb>\\t%<w>0, %1, ");
656         else
657           {
658             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
659             return "tst\t%<w>0, %1\;<bcond>\t%l2";
660           }
661       }
662     else
663       return "<tbz>\t%<w>0, %1, %l2";
664   }
665   [(set_attr "type" "branch")
666    (set (attr "length")
667         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
668                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
669                       (const_int 4)
670                       (const_int 8)))
671    (set (attr "far_branch")
672         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
673                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
674                       (const_int 0)
675                       (const_int 1)))]
679 (define_insn "*cb<optab><mode>1"
680   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
681                                  (const_int 0))
682                            (label_ref (match_operand 1 "" ""))
683                            (pc)))
684    (clobber (reg:CC CC_REGNUM))]
685   ""
686   {
687     if (get_attr_length (insn) == 8)
688       {
689         if (get_attr_far_branch (insn) == 1)
690           return aarch64_gen_far_branch (operands, 1, "Ltb",
691                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
692         else
693           {
694             char buf[64];
695             uint64_t val = ((uint64_t) 1)
696                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
697             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
698             output_asm_insn (buf, operands);
699             return "<bcond>\t%l1";
700           }
701       }
702     else
703       return "<tbz>\t%<w>0, <sizem1>, %l1";
704   }
705   [(set_attr "type" "branch")
706    (set (attr "length")
707         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
708                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
709                       (const_int 4)
710                       (const_int 8)))
711    (set (attr "far_branch")
712         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
713                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
714                       (const_int 0)
715                       (const_int 1)))]
718 ;; -------------------------------------------------------------------
719 ;; Subroutine calls and sibcalls
720 ;; -------------------------------------------------------------------
722 (define_expand "call_internal"
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))])])
728 (define_expand "call"
729   [(parallel [(call (match_operand 0 "memory_operand" "")
730                     (match_operand 1 "general_operand" ""))
731               (use (match_operand 2 "" ""))
732               (clobber (reg:DI LR_REGNUM))])]
733   ""
734   "
735   {
736     rtx callee, pat;
738     /* In an untyped call, we can get NULL for operand 2.  */
739     if (operands[2] == NULL)
740       operands[2] = const0_rtx;
742     /* Decide if we should generate indirect calls by loading the
743        64-bit address of the callee into a register before performing
744        the branch-and-link.  */
745     callee = XEXP (operands[0], 0);
746     if (GET_CODE (callee) == SYMBOL_REF
747         ? (aarch64_is_long_call_p (callee)
748            || aarch64_is_noplt_call_p (callee))
749         : !REG_P (callee))
750       XEXP (operands[0], 0) = force_reg (Pmode, callee);
752     pat = gen_call_internal (operands[0], operands[1], operands[2]);
753     aarch64_emit_call_insn (pat);
754     DONE;
755   }"
758 (define_insn "*call_reg"
759   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
760          (match_operand 1 "" ""))
761    (use (match_operand 2 "" ""))
762    (clobber (reg:DI LR_REGNUM))]
763   ""
764   "blr\\t%0"
765   [(set_attr "type" "call")]
768 (define_insn "*call_symbol"
769   [(call (mem:DI (match_operand:DI 0 "" ""))
770          (match_operand 1 "" ""))
771    (use (match_operand 2 "" ""))
772    (clobber (reg:DI LR_REGNUM))]
773   "GET_CODE (operands[0]) == SYMBOL_REF
774    && !aarch64_is_long_call_p (operands[0])
775    && !aarch64_is_noplt_call_p (operands[0])"
776   "bl\\t%a0"
777   [(set_attr "type" "call")]
780 (define_expand "call_value_internal"
781   [(parallel [(set (match_operand 0 "" "")
782                    (call (match_operand 1 "memory_operand" "")
783                          (match_operand 2 "general_operand" "")))
784               (use (match_operand 3 "" ""))
785               (clobber (reg:DI LR_REGNUM))])])
787 (define_expand "call_value"
788   [(parallel [(set (match_operand 0 "" "")
789                    (call (match_operand 1 "memory_operand" "")
790                          (match_operand 2 "general_operand" "")))
791               (use (match_operand 3 "" ""))
792               (clobber (reg:DI LR_REGNUM))])]
793   ""
794   "
795   {
796     rtx callee, pat;
798     /* In an untyped call, we can get NULL for operand 3.  */
799     if (operands[3] == NULL)
800       operands[3] = const0_rtx;
802     /* Decide if we should generate indirect calls by loading the
803        64-bit address of the callee into a register before performing
804        the branch-and-link.  */
805     callee = XEXP (operands[1], 0);
806     if (GET_CODE (callee) == SYMBOL_REF
807         ? (aarch64_is_long_call_p (callee)
808            || aarch64_is_noplt_call_p (callee))
809         : !REG_P (callee))
810       XEXP (operands[1], 0) = force_reg (Pmode, callee);
812     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
813                                    operands[3]);
814     aarch64_emit_call_insn (pat);
815     DONE;
816   }"
819 (define_insn "*call_value_reg"
820   [(set (match_operand 0 "" "")
821         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
822                       (match_operand 2 "" "")))
823    (use (match_operand 3 "" ""))
824    (clobber (reg:DI LR_REGNUM))]
825   ""
826   "blr\\t%1"
827   [(set_attr "type" "call")]
831 (define_insn "*call_value_symbol"
832   [(set (match_operand 0 "" "")
833         (call (mem:DI (match_operand:DI 1 "" ""))
834               (match_operand 2 "" "")))
835    (use (match_operand 3 "" ""))
836    (clobber (reg:DI LR_REGNUM))]
837   "GET_CODE (operands[1]) == SYMBOL_REF
838    && !aarch64_is_long_call_p (operands[1])
839    && !aarch64_is_noplt_call_p (operands[1])"
840   "bl\\t%a1"
841   [(set_attr "type" "call")]
844 (define_expand "sibcall_internal"
845   [(parallel [(call (match_operand 0 "memory_operand" "")
846                     (match_operand 1 "general_operand" ""))
847               (return)
848               (use (match_operand 2 "" ""))])])
850 (define_expand "sibcall"
851   [(parallel [(call (match_operand 0 "memory_operand" "")
852                     (match_operand 1 "general_operand" ""))
853               (return)
854               (use (match_operand 2 "" ""))])]
855   ""
856   {
857     rtx pat;
858     rtx callee = XEXP (operands[0], 0);
859     if (!REG_P (callee)
860        && ((GET_CODE (callee) != SYMBOL_REF)
861            || aarch64_is_noplt_call_p (callee)))
862       XEXP (operands[0], 0) = force_reg (Pmode, callee);
864     if (operands[2] == NULL_RTX)
865       operands[2] = const0_rtx;
867     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
868     aarch64_emit_call_insn (pat);
869     DONE;
870   }
873 (define_expand "sibcall_value_internal"
874   [(parallel [(set (match_operand 0 "" "")
875                    (call (match_operand 1 "memory_operand" "")
876                          (match_operand 2 "general_operand" "")))
877               (return)
878               (use (match_operand 3 "" ""))])])
880 (define_expand "sibcall_value"
881   [(parallel [(set (match_operand 0 "" "")
882                    (call (match_operand 1 "memory_operand" "")
883                          (match_operand 2 "general_operand" "")))
884               (return)
885               (use (match_operand 3 "" ""))])]
886   ""
887   {
888     rtx pat;
889     rtx callee = XEXP (operands[1], 0);
890     if (!REG_P (callee)
891        && ((GET_CODE (callee) != SYMBOL_REF)
892            || aarch64_is_noplt_call_p (callee)))
893       XEXP (operands[1], 0) = force_reg (Pmode, callee);
895     if (operands[3] == NULL_RTX)
896       operands[3] = const0_rtx;
898     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
899                                       operands[3]);
900     aarch64_emit_call_insn (pat);
901     DONE;
902   }
905 (define_insn "*sibcall_insn"
906   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
907          (match_operand 1 "" ""))
908    (return)
909    (use (match_operand 2 "" ""))]
910   "SIBLING_CALL_P (insn)"
911   "@
912    br\\t%0
913    b\\t%a0"
914   [(set_attr "type" "branch, branch")]
917 (define_insn "*sibcall_value_insn"
918   [(set (match_operand 0 "" "")
919         (call (mem:DI
920                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
921               (match_operand 2 "" "")))
922    (return)
923    (use (match_operand 3 "" ""))]
924   "SIBLING_CALL_P (insn)"
925   "@
926    br\\t%1
927    b\\t%a1"
928   [(set_attr "type" "branch, branch")]
931 ;; Call subroutine returning any type.
933 (define_expand "untyped_call"
934   [(parallel [(call (match_operand 0 "")
935                     (const_int 0))
936               (match_operand 1 "")
937               (match_operand 2 "")])]
938   ""
940   int i;
942   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
944   for (i = 0; i < XVECLEN (operands[2], 0); i++)
945     {
946       rtx set = XVECEXP (operands[2], 0, i);
947       emit_move_insn (SET_DEST (set), SET_SRC (set));
948     }
950   /* The optimizer does not know that the call sets the function value
951      registers we stored in the result block.  We avoid problems by
952      claiming that all hard registers are used and clobbered at this
953      point.  */
954   emit_insn (gen_blockage ());
955   DONE;
958 ;; -------------------------------------------------------------------
959 ;; Moves
960 ;; -------------------------------------------------------------------
962 (define_expand "mov<mode>"
963   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
964         (match_operand:SHORT 1 "general_operand" ""))]
965   ""
966   "
967     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
968       operands[1] = force_reg (<MODE>mode, operands[1]);
969   "
972 (define_insn "*mov<mode>_aarch64"
973   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
974         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
975   "(register_operand (operands[0], <MODE>mode)
976     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
978    switch (which_alternative)
979      {
980      case 0:
981        return "mov\t%w0, %w1";
982      case 1:
983        return "mov\t%w0, %1";
984      case 2:
985        return aarch64_output_scalar_simd_mov_immediate (operands[1],
986                                                         <MODE>mode);
987      case 3:
988        return "ldr<size>\t%w0, %1";
989      case 4:
990        return "ldr\t%<size>0, %1";
991      case 5:
992        return "str<size>\t%w1, %0";
993      case 6:
994        return "str\t%<size>1, %0";
995      case 7:
996        return "umov\t%w0, %1.<v>[0]";
997      case 8:
998        return "dup\t%0.<Vallxd>, %w1";
999      case 9:
1000        return "dup\t%<Vetype>0, %1.<v>[0]";
1001      default:
1002        gcc_unreachable ();
1003      }
1005   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1006                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1007    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1010 (define_expand "mov<mode>"
1011   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1012         (match_operand:GPI 1 "general_operand" ""))]
1013   ""
1014   "
1015     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1016         && <MODE>mode == DImode
1017         && aarch64_split_dimode_const_store (operands[0], operands[1]))
1018       DONE;
1020     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1021       operands[1] = force_reg (<MODE>mode, operands[1]);
1023     /* FIXME: RR we still need to fix up what we are doing with
1024        symbol_refs and other types of constants.  */
1025     if (CONSTANT_P (operands[1])
1026         && !CONST_INT_P (operands[1]))
1027      {
1028        aarch64_expand_mov_immediate (operands[0], operands[1]);
1029        DONE;
1030      }
1031   "
1034 (define_insn_and_split "*movsi_aarch64"
1035   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
1036         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1037   "(register_operand (operands[0], SImode)
1038     || aarch64_reg_or_zero (operands[1], SImode))"
1039   "@
1040    mov\\t%w0, %w1
1041    mov\\t%w0, %w1
1042    mov\\t%w0, %w1
1043    mov\\t%w0, %1
1044    #
1045    ldr\\t%w0, %1
1046    ldr\\t%s0, %1
1047    str\\t%w1, %0
1048    str\\t%s1, %0
1049    adr\\t%x0, %a1
1050    adrp\\t%x0, %A1
1051    fmov\\t%s0, %w1
1052    fmov\\t%w0, %s1
1053    fmov\\t%s0, %s1"
1054    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1055     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1056    [(const_int 0)]
1057    "{
1058        aarch64_expand_mov_immediate (operands[0], operands[1]);
1059        DONE;
1060     }"
1061   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1062                      adr,adr,f_mcr,f_mrc,fmov")
1063    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1066 (define_insn_and_split "*movdi_aarch64"
1067   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
1068         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1069   "(register_operand (operands[0], DImode)
1070     || aarch64_reg_or_zero (operands[1], DImode))"
1071   "@
1072    mov\\t%x0, %x1
1073    mov\\t%0, %x1
1074    mov\\t%x0, %1
1075    mov\\t%x0, %1
1076    #
1077    ldr\\t%x0, %1
1078    ldr\\t%d0, %1
1079    str\\t%x1, %0
1080    str\\t%d1, %0
1081    adr\\t%x0, %a1
1082    adrp\\t%x0, %A1
1083    fmov\\t%d0, %x1
1084    fmov\\t%x0, %d1
1085    fmov\\t%d0, %d1
1086    movi\\t%d0, %1"
1087    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1088     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1089    [(const_int 0)]
1090    "{
1091        aarch64_expand_mov_immediate (operands[0], operands[1]);
1092        DONE;
1093     }"
1094   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1095                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
1096    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1097    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1100 (define_insn "insv_imm<mode>"
1101   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1102                           (const_int 16)
1103                           (match_operand:GPI 1 "const_int_operand" "n"))
1104         (match_operand:GPI 2 "const_int_operand" "n"))]
1105   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1106    && UINTVAL (operands[1]) % 16 == 0"
1107   "movk\\t%<w>0, %X2, lsl %1"
1108   [(set_attr "type" "mov_imm")]
1111 (define_expand "movti"
1112   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1113         (match_operand:TI 1 "general_operand" ""))]
1114   ""
1115   "
1116     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1117       operands[1] = force_reg (TImode, operands[1]);
1118   "
1121 (define_insn "*movti_aarch64"
1122   [(set (match_operand:TI 0
1123          "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
1124         (match_operand:TI 1
1125          "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
1126   "(register_operand (operands[0], TImode)
1127     || aarch64_reg_or_zero (operands[1], TImode))"
1128   "@
1129    #
1130    #
1131    #
1132    orr\\t%0.16b, %1.16b, %1.16b
1133    ldp\\t%0, %H0, %1
1134    stp\\t%1, %H1, %0
1135    stp\\txzr, xzr, %0
1136    ldr\\t%q0, %1
1137    str\\t%q1, %0"
1138   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1139                              load2,store2,store2,f_loadd,f_stored")
1140    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1141    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1142    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1145 ;; Split a TImode register-register or register-immediate move into
1146 ;; its component DImode pieces, taking care to handle overlapping
1147 ;; source and dest registers.
1148 (define_split
1149    [(set (match_operand:TI 0 "register_operand" "")
1150          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1151   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1152   [(const_int 0)]
1154   aarch64_split_128bit_move (operands[0], operands[1]);
1155   DONE;
1158 (define_expand "mov<mode>"
1159   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1160         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1161   ""
1162   {
1163     if (!TARGET_FLOAT)
1164       {
1165         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1166         FAIL;
1167       }
1169     if (GET_CODE (operands[0]) == MEM
1170         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1171               && aarch64_float_const_zero_rtx_p (operands[1])))
1172       operands[1] = force_reg (<MODE>mode, operands[1]);
1173   }
1176 (define_insn "*movhf_aarch64"
1177   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w,m,r,m ,r")
1178         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,m,w,m,rY,r"))]
1179   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1180     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1181   "@
1182    movi\\t%0.4h, #0
1183    mov\\t%0.h[0], %w1
1184    umov\\t%w0, %1.h[0]
1185    mov\\t%0.h[0], %1.h[0]
1186    ldr\\t%h0, %1
1187    str\\t%h1, %0
1188    ldrh\\t%w0, %1
1189    strh\\t%w1, %0
1190    mov\\t%w0, %w1"
1191   [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1192                      f_loads,f_stores,load1,store1,mov_reg")
1193    (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1196 (define_insn "*movsf_aarch64"
1197   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1198         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1199   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1200     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1201   "@
1202    movi\\t%0.2s, #0
1203    fmov\\t%s0, %w1
1204    fmov\\t%w0, %s1
1205    fmov\\t%s0, %s1
1206    fmov\\t%s0, %1
1207    ldr\\t%s0, %1
1208    str\\t%s1, %0
1209    ldr\\t%w0, %1
1210    str\\t%w1, %0
1211    mov\\t%w0, %w1"
1212   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1213                      f_loads,f_stores,load1,store1,mov_reg")
1214    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1217 (define_insn "*movdf_aarch64"
1218   [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1219         (match_operand:DF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1220   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1221     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1222   "@
1223    movi\\t%d0, #0
1224    fmov\\t%d0, %x1
1225    fmov\\t%x0, %d1
1226    fmov\\t%d0, %d1
1227    fmov\\t%d0, %1
1228    ldr\\t%d0, %1
1229    str\\t%d1, %0
1230    ldr\\t%x0, %1
1231    str\\t%x1, %0
1232    mov\\t%x0, %x1"
1233   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1234                      f_loadd,f_stored,load1,store1,mov_reg")
1235    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1238 (define_insn "*movtf_aarch64"
1239   [(set (match_operand:TF 0
1240          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1241         (match_operand:TF 1
1242          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1243   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1244     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1245   "@
1246    orr\\t%0.16b, %1.16b, %1.16b
1247    #
1248    #
1249    #
1250    movi\\t%0.2d, #0
1251    fmov\\t%s0, wzr
1252    ldr\\t%q0, %1
1253    str\\t%q1, %0
1254    ldp\\t%0, %H0, %1
1255    stp\\t%1, %H1, %0
1256    stp\\txzr, xzr, %0"
1257   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1258                      f_loadd,f_stored,load2,store2,store2")
1259    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1260    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1263 (define_split
1264    [(set (match_operand:TF 0 "register_operand" "")
1265          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1266   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1267   [(const_int 0)]
1268   {
1269     aarch64_split_128bit_move (operands[0], operands[1]);
1270     DONE;
1271   }
1274 ;; 0 is dst
1275 ;; 1 is src
1276 ;; 2 is size of move in bytes
1277 ;; 3 is alignment
1279 (define_expand "movmemdi"
1280   [(match_operand:BLK 0 "memory_operand")
1281    (match_operand:BLK 1 "memory_operand")
1282    (match_operand:DI 2 "immediate_operand")
1283    (match_operand:DI 3 "immediate_operand")]
1284    "!STRICT_ALIGNMENT"
1286   if (aarch64_expand_movmem (operands))
1287     DONE;
1288   FAIL;
1292 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1293 ;; fairly lax checking on the second memory operation.
1294 (define_insn "load_pairsi"
1295   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1296         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1297    (set (match_operand:SI 2 "register_operand" "=r,*w")
1298         (match_operand:SI 3 "memory_operand" "m,m"))]
1299   "rtx_equal_p (XEXP (operands[3], 0),
1300                 plus_constant (Pmode,
1301                                XEXP (operands[1], 0),
1302                                GET_MODE_SIZE (SImode)))"
1303   "@
1304    ldp\\t%w0, %w2, %1
1305    ldp\\t%s0, %s2, %1"
1306   [(set_attr "type" "load2,neon_load1_2reg")
1307    (set_attr "fp" "*,yes")]
1310 (define_insn "load_pairdi"
1311   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1312         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1313    (set (match_operand:DI 2 "register_operand" "=r,*w")
1314         (match_operand:DI 3 "memory_operand" "m,m"))]
1315   "rtx_equal_p (XEXP (operands[3], 0),
1316                 plus_constant (Pmode,
1317                                XEXP (operands[1], 0),
1318                                GET_MODE_SIZE (DImode)))"
1319   "@
1320    ldp\\t%x0, %x2, %1
1321    ldp\\t%d0, %d2, %1"
1322   [(set_attr "type" "load2,neon_load1_2reg")
1323    (set_attr "fp" "*,yes")]
1327 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1328 ;; fairly lax checking on the second memory operation.
1329 (define_insn "store_pairsi"
1330   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1331         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1332    (set (match_operand:SI 2 "memory_operand" "=m,m")
1333         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1334   "rtx_equal_p (XEXP (operands[2], 0),
1335                 plus_constant (Pmode,
1336                                XEXP (operands[0], 0),
1337                                GET_MODE_SIZE (SImode)))"
1338   "@
1339    stp\\t%w1, %w3, %0
1340    stp\\t%s1, %s3, %0"
1341   [(set_attr "type" "store2,neon_store1_2reg")
1342    (set_attr "fp" "*,yes")]
1345 (define_insn "store_pairdi"
1346   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1347         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1348    (set (match_operand:DI 2 "memory_operand" "=m,m")
1349         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1350   "rtx_equal_p (XEXP (operands[2], 0),
1351                 plus_constant (Pmode,
1352                                XEXP (operands[0], 0),
1353                                GET_MODE_SIZE (DImode)))"
1354   "@
1355    stp\\t%x1, %x3, %0
1356    stp\\t%d1, %d3, %0"
1357   [(set_attr "type" "store2,neon_store1_2reg")
1358    (set_attr "fp" "*,yes")]
1361 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1362 ;; fairly lax checking on the second memory operation.
1363 (define_insn "load_pairsf"
1364   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1365         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1366    (set (match_operand:SF 2 "register_operand" "=w,*r")
1367         (match_operand:SF 3 "memory_operand" "m,m"))]
1368   "rtx_equal_p (XEXP (operands[3], 0),
1369                 plus_constant (Pmode,
1370                                XEXP (operands[1], 0),
1371                                GET_MODE_SIZE (SFmode)))"
1372   "@
1373    ldp\\t%s0, %s2, %1
1374    ldp\\t%w0, %w2, %1"
1375   [(set_attr "type" "neon_load1_2reg,load2")
1376    (set_attr "fp" "yes,*")]
1379 (define_insn "load_pairdf"
1380   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1381         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1382    (set (match_operand:DF 2 "register_operand" "=w,*r")
1383         (match_operand:DF 3 "memory_operand" "m,m"))]
1384   "rtx_equal_p (XEXP (operands[3], 0),
1385                 plus_constant (Pmode,
1386                                XEXP (operands[1], 0),
1387                                GET_MODE_SIZE (DFmode)))"
1388   "@
1389    ldp\\t%d0, %d2, %1
1390    ldp\\t%x0, %x2, %1"
1391   [(set_attr "type" "neon_load1_2reg,load2")
1392    (set_attr "fp" "yes,*")]
1395 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1396 ;; fairly lax checking on the second memory operation.
1397 (define_insn "store_pairsf"
1398   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1399         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1400    (set (match_operand:SF 2 "memory_operand" "=m,m")
1401         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1402   "rtx_equal_p (XEXP (operands[2], 0),
1403                 plus_constant (Pmode,
1404                                XEXP (operands[0], 0),
1405                                GET_MODE_SIZE (SFmode)))"
1406   "@
1407    stp\\t%s1, %s3, %0
1408    stp\\t%w1, %w3, %0"
1409   [(set_attr "type" "neon_store1_2reg,store2")
1410    (set_attr "fp" "yes,*")]
1413 (define_insn "store_pairdf"
1414   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1415         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1416    (set (match_operand:DF 2 "memory_operand" "=m,m")
1417         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1418   "rtx_equal_p (XEXP (operands[2], 0),
1419                 plus_constant (Pmode,
1420                                XEXP (operands[0], 0),
1421                                GET_MODE_SIZE (DFmode)))"
1422   "@
1423    stp\\t%d1, %d3, %0
1424    stp\\t%x1, %x3, %0"
1425   [(set_attr "type" "neon_store1_2reg,store2")
1426    (set_attr "fp" "yes,*")]
1429 ;; Load pair with post-index writeback.  This is primarily used in function
1430 ;; epilogues.
1431 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1432   [(parallel
1433     [(set (match_operand:P 0 "register_operand" "=k")
1434           (plus:P (match_operand:P 1 "register_operand" "0")
1435                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1436      (set (match_operand:GPI 2 "register_operand" "=r")
1437           (mem:GPI (match_dup 1)))
1438      (set (match_operand:GPI 3 "register_operand" "=r")
1439           (mem:GPI (plus:P (match_dup 1)
1440                    (match_operand:P 5 "const_int_operand" "n"))))])]
1441   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1442   "ldp\\t%<w>2, %<w>3, [%1], %4"
1443   [(set_attr "type" "load2")]
1446 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1447   [(parallel
1448     [(set (match_operand:P 0 "register_operand" "=k")
1449           (plus:P (match_operand:P 1 "register_operand" "0")
1450                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1451      (set (match_operand:GPF 2 "register_operand" "=w")
1452           (mem:GPF (match_dup 1)))
1453      (set (match_operand:GPF 3 "register_operand" "=w")
1454           (mem:GPF (plus:P (match_dup 1)
1455                    (match_operand:P 5 "const_int_operand" "n"))))])]
1456   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1457   "ldp\\t%<w>2, %<w>3, [%1], %4"
1458   [(set_attr "type" "neon_load1_2reg")]
1461 ;; Store pair with pre-index writeback.  This is primarily used in function
1462 ;; prologues.
1463 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1464   [(parallel
1465     [(set (match_operand:P 0 "register_operand" "=&k")
1466           (plus:P (match_operand:P 1 "register_operand" "0")
1467                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1468      (set (mem:GPI (plus:P (match_dup 0)
1469                    (match_dup 4)))
1470           (match_operand:GPI 2 "register_operand" "r"))
1471      (set (mem:GPI (plus:P (match_dup 0)
1472                    (match_operand:P 5 "const_int_operand" "n")))
1473           (match_operand:GPI 3 "register_operand" "r"))])]
1474   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1475   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1476   [(set_attr "type" "store2")]
1479 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1480   [(parallel
1481     [(set (match_operand:P 0 "register_operand" "=&k")
1482           (plus:P (match_operand:P 1 "register_operand" "0")
1483                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1484      (set (mem:GPF (plus:P (match_dup 0)
1485                    (match_dup 4)))
1486           (match_operand:GPF 2 "register_operand" "w"))
1487      (set (mem:GPF (plus:P (match_dup 0)
1488                    (match_operand:P 5 "const_int_operand" "n")))
1489           (match_operand:GPF 3 "register_operand" "w"))])]
1490   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1491   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1492   [(set_attr "type" "neon_store1_2reg<q>")]
1495 ;; -------------------------------------------------------------------
1496 ;; Sign/Zero extension
1497 ;; -------------------------------------------------------------------
1499 (define_expand "<optab>sidi2"
1500   [(set (match_operand:DI 0 "register_operand")
1501         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1502   ""
1505 (define_insn "*extendsidi2_aarch64"
1506   [(set (match_operand:DI 0 "register_operand" "=r,r")
1507         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1508   ""
1509   "@
1510    sxtw\t%0, %w1
1511    ldrsw\t%0, %1"
1512   [(set_attr "type" "extend,load1")]
1515 (define_insn "*load_pair_extendsidi2_aarch64"
1516   [(set (match_operand:DI 0 "register_operand" "=r")
1517         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1518    (set (match_operand:DI 2 "register_operand" "=r")
1519         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1520   "rtx_equal_p (XEXP (operands[3], 0),
1521                 plus_constant (Pmode,
1522                                XEXP (operands[1], 0),
1523                                GET_MODE_SIZE (SImode)))"
1524   "ldpsw\\t%0, %2, %1"
1525   [(set_attr "type" "load2")]
1528 (define_insn "*zero_extendsidi2_aarch64"
1529   [(set (match_operand:DI 0 "register_operand" "=r,r")
1530         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1531   ""
1532   "@
1533    uxtw\t%0, %w1
1534    ldr\t%w0, %1"
1535   [(set_attr "type" "extend,load1")]
1538 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1539   [(set (match_operand:DI 0 "register_operand" "=r")
1540         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1541    (set (match_operand:DI 2 "register_operand" "=r")
1542         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1543   "rtx_equal_p (XEXP (operands[3], 0),
1544                 plus_constant (Pmode,
1545                                XEXP (operands[1], 0),
1546                                GET_MODE_SIZE (SImode)))"
1547   "ldp\\t%w0, %w2, %1"
1548   [(set_attr "type" "load2")]
1551 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1552   [(set (match_operand:GPI 0 "register_operand")
1553         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1554   ""
1557 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1558   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1559         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1560   ""
1561   "@
1562    sxt<SHORT:size>\t%<GPI:w>0, %w1
1563    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1564   [(set_attr "type" "extend,load1")]
1567 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1568   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1569         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1570   ""
1571   "@
1572    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1573    ldr<SHORT:size>\t%w0, %1
1574    ldr\t%<SHORT:size>0, %1"
1575   [(set_attr "type" "logic_imm,load1,load1")]
1578 (define_expand "<optab>qihi2"
1579   [(set (match_operand:HI 0 "register_operand")
1580         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1581   ""
1584 (define_insn "*extendqihi2_aarch64"
1585   [(set (match_operand:HI 0 "register_operand" "=r,r")
1586         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1587   ""
1588   "@
1589    sxtb\t%w0, %w1
1590    ldrsb\t%w0, %1"
1591   [(set_attr "type" "extend,load1")]
1594 (define_insn "*zero_extendqihi2_aarch64"
1595   [(set (match_operand:HI 0 "register_operand" "=r,r")
1596         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1597   ""
1598   "@
1599    and\t%w0, %w1, 255
1600    ldrb\t%w0, %1"
1601   [(set_attr "type" "logic_imm,load1")]
1604 ;; -------------------------------------------------------------------
1605 ;; Simple arithmetic
1606 ;; -------------------------------------------------------------------
1608 (define_expand "add<mode>3"
1609   [(set
1610     (match_operand:GPI 0 "register_operand" "")
1611     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1612               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1613   ""
1615   /* If operands[1] is a subreg extract the inner RTX.  */
1616   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1618   /* If the constant is too large for a single instruction and isn't frame
1619      based, split off the immediate so it is available for CSE.  */
1620   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1621       && can_create_pseudo_p ()
1622       && (!REG_P (op1)
1623          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1624     operands[2] = force_reg (<MODE>mode, operands[2]);
1627 (define_insn "*add<mode>3_aarch64"
1628   [(set
1629     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1630     (plus:GPI
1631      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1632      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1633   ""
1634   "@
1635   add\\t%<w>0, %<w>1, %2
1636   add\\t%<w>0, %<w>1, %<w>2
1637   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1638   sub\\t%<w>0, %<w>1, #%n2
1639   #"
1640   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1641    (set_attr "simd" "*,*,yes,*,*")]
1644 ;; zero_extend version of above
1645 (define_insn "*addsi3_aarch64_uxtw"
1646   [(set
1647     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1648     (zero_extend:DI
1649      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1650               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1651   ""
1652   "@
1653   add\\t%w0, %w1, %2
1654   add\\t%w0, %w1, %w2
1655   sub\\t%w0, %w1, #%n2
1656   #"
1657   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1660 ;; If there's a free register, and we can load the constant with a
1661 ;; single instruction, do so.  This has a chance to improve scheduling.
1662 (define_peephole2
1663   [(match_scratch:GPI 3 "r")
1664    (set (match_operand:GPI 0 "register_operand")
1665         (plus:GPI
1666           (match_operand:GPI 1 "register_operand")
1667           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1668   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1669   [(set (match_dup 3) (match_dup 2))
1670    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1673 (define_peephole2
1674   [(match_scratch:SI 3 "r")
1675    (set (match_operand:DI 0 "register_operand")
1676         (zero_extend:DI
1677           (plus:SI
1678             (match_operand:SI 1 "register_operand")
1679             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1680   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1681   [(set (match_dup 3) (match_dup 2))
1682    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1685 ;; After peephole2 has had a chance to run, split any remaining long
1686 ;; additions into two add immediates.
1687 (define_split
1688   [(set (match_operand:GPI 0 "register_operand")
1689         (plus:GPI
1690           (match_operand:GPI 1 "register_operand")
1691           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1692   "epilogue_completed"
1693   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1694    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1695   {
1696     HOST_WIDE_INT i = INTVAL (operands[2]);
1697     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1698     operands[3] = GEN_INT (i - s);
1699     operands[4] = GEN_INT (s);
1700   }
1703 (define_split
1704   [(set (match_operand:DI 0 "register_operand")
1705         (zero_extend:DI
1706           (plus:SI
1707             (match_operand:SI 1 "register_operand")
1708             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1709   "epilogue_completed"
1710   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1711    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1712   {
1713     HOST_WIDE_INT i = INTVAL (operands[2]);
1714     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1715     operands[3] = GEN_INT (i - s);
1716     operands[4] = GEN_INT (s);
1717     operands[5] = gen_lowpart (SImode, operands[0]);
1718   }
1721 (define_expand "addti3"
1722   [(set (match_operand:TI 0 "register_operand" "")
1723         (plus:TI (match_operand:TI 1 "register_operand" "")
1724                  (match_operand:TI 2 "register_operand" "")))]
1725   ""
1727   rtx low = gen_reg_rtx (DImode);
1728   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1729                                   gen_lowpart (DImode, operands[2])));
1731   rtx high = gen_reg_rtx (DImode);
1732   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1733                                  gen_highpart (DImode, operands[2])));
1735   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1736   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1737   DONE;
1740 (define_insn "add<mode>3_compare0"
1741   [(set (reg:CC_NZ CC_REGNUM)
1742         (compare:CC_NZ
1743          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1744                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1745          (const_int 0)))
1746    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1747         (plus:GPI (match_dup 1) (match_dup 2)))]
1748   ""
1749   "@
1750   adds\\t%<w>0, %<w>1, %<w>2
1751   adds\\t%<w>0, %<w>1, %2
1752   subs\\t%<w>0, %<w>1, #%n2"
1753   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1756 ;; zero_extend version of above
1757 (define_insn "*addsi3_compare0_uxtw"
1758   [(set (reg:CC_NZ CC_REGNUM)
1759         (compare:CC_NZ
1760          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1761                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1762          (const_int 0)))
1763    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1764         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1765   ""
1766   "@
1767   adds\\t%w0, %w1, %w2
1768   adds\\t%w0, %w1, %2
1769   subs\\t%w0, %w1, #%n2"
1770   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1773 (define_insn "*add<mode>3_compareC_cconly_imm"
1774   [(set (reg:CC_C CC_REGNUM)
1775         (ne:CC_C
1776           (plus:<DWI>
1777             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1778             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1779           (zero_extend:<DWI>
1780             (plus:GPI
1781               (match_dup 0)
1782               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1783   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1784                                  <MODE>mode, operands[1])"
1785   "@
1786   cmn\\t%<w>0, %1
1787   cmp\\t%<w>0, #%n1"
1788   [(set_attr "type" "alus_imm")]
1791 (define_insn "*add<mode>3_compareC_cconly"
1792   [(set (reg:CC_C CC_REGNUM)
1793         (ne:CC_C
1794           (plus:<DWI>
1795             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1796             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1797           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1798   ""
1799   "cmn\\t%<w>0, %<w>1"
1800   [(set_attr "type" "alus_sreg")]
1803 (define_insn "*add<mode>3_compareC_imm"
1804   [(set (reg:CC_C CC_REGNUM)
1805         (ne:CC_C
1806           (plus:<DWI>
1807             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1808             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1809           (zero_extend:<DWI>
1810             (plus:GPI
1811               (match_dup 1)
1812               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1813    (set (match_operand:GPI 0 "register_operand" "=r,r")
1814         (plus:GPI (match_dup 1) (match_dup 2)))]
1815   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1816                                  <MODE>mode, operands[2])"
1817   "@
1818   adds\\t%<w>0, %<w>1, %2
1819   subs\\t%<w>0, %<w>1, #%n2"
1820   [(set_attr "type" "alus_imm")]
1823 (define_insn "add<mode>3_compareC"
1824   [(set (reg:CC_C CC_REGNUM)
1825         (ne:CC_C
1826           (plus:<DWI>
1827             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1828             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1829           (zero_extend:<DWI>
1830             (plus:GPI (match_dup 1) (match_dup 2)))))
1831    (set (match_operand:GPI 0 "register_operand" "=r")
1832         (plus:GPI (match_dup 1) (match_dup 2)))]
1833   ""
1834   "adds\\t%<w>0, %<w>1, %<w>2"
1835   [(set_attr "type" "alus_sreg")]
1838 (define_insn "*adds_shift_imm_<mode>"
1839   [(set (reg:CC_NZ CC_REGNUM)
1840         (compare:CC_NZ
1841          (plus:GPI (ASHIFT:GPI 
1842                     (match_operand:GPI 1 "register_operand" "r")
1843                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1844                    (match_operand:GPI 3 "register_operand" "r"))
1845          (const_int 0)))
1846    (set (match_operand:GPI 0 "register_operand" "=r")
1847         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1848                   (match_dup 3)))]
1849   ""
1850   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1851   [(set_attr "type" "alus_shift_imm")]
1854 (define_insn "*subs_shift_imm_<mode>"
1855   [(set (reg:CC_NZ CC_REGNUM)
1856         (compare:CC_NZ
1857          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1858                     (ASHIFT:GPI
1859                      (match_operand:GPI 2 "register_operand" "r")
1860                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1861          (const_int 0)))
1862    (set (match_operand:GPI 0 "register_operand" "=r")
1863         (minus:GPI (match_dup 1)
1864                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1865   ""
1866   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1867   [(set_attr "type" "alus_shift_imm")]
1870 (define_insn "*adds_mul_imm_<mode>"
1871   [(set (reg:CC_NZ CC_REGNUM)
1872         (compare:CC_NZ
1873          (plus:GPI (mult:GPI
1874                     (match_operand:GPI 1 "register_operand" "r")
1875                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1876                    (match_operand:GPI 3 "register_operand" "r"))
1877          (const_int 0)))
1878    (set (match_operand:GPI 0 "register_operand" "=r")
1879         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1880                   (match_dup 3)))]
1881   ""
1882   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1883   [(set_attr "type" "alus_shift_imm")]
1886 (define_insn "*subs_mul_imm_<mode>"
1887   [(set (reg:CC_NZ CC_REGNUM)
1888         (compare:CC_NZ
1889          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1890                     (mult:GPI
1891                      (match_operand:GPI 2 "register_operand" "r")
1892                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1893          (const_int 0)))
1894    (set (match_operand:GPI 0 "register_operand" "=r")
1895         (minus:GPI (match_dup 1)
1896                    (mult:GPI (match_dup 2) (match_dup 3))))]
1897   ""
1898   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1899   [(set_attr "type" "alus_shift_imm")]
1902 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1903   [(set (reg:CC_NZ CC_REGNUM)
1904         (compare:CC_NZ
1905          (plus:GPI
1906           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1907           (match_operand:GPI 2 "register_operand" "r"))
1908         (const_int 0)))
1909    (set (match_operand:GPI 0 "register_operand" "=r")
1910         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1911   ""
1912   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1913   [(set_attr "type" "alus_ext")]
1916 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1917   [(set (reg:CC_NZ CC_REGNUM)
1918         (compare:CC_NZ
1919          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1920                     (ANY_EXTEND:GPI
1921                      (match_operand:ALLX 2 "register_operand" "r")))
1922         (const_int 0)))
1923    (set (match_operand:GPI 0 "register_operand" "=r")
1924         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1925   ""
1926   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1927   [(set_attr "type" "alus_ext")]
1930 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1931   [(set (reg:CC_NZ CC_REGNUM)
1932         (compare:CC_NZ
1933          (plus:GPI (ashift:GPI 
1934                     (ANY_EXTEND:GPI 
1935                      (match_operand:ALLX 1 "register_operand" "r"))
1936                     (match_operand 2 "aarch64_imm3" "Ui3"))
1937                    (match_operand:GPI 3 "register_operand" "r"))
1938          (const_int 0)))
1939    (set (match_operand:GPI 0 "register_operand" "=rk")
1940         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1941                               (match_dup 2))
1942                   (match_dup 3)))]
1943   ""
1944   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1945   [(set_attr "type" "alus_ext")]
1948 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1949   [(set (reg:CC_NZ CC_REGNUM)
1950         (compare:CC_NZ
1951          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1952                     (ashift:GPI 
1953                      (ANY_EXTEND:GPI
1954                       (match_operand:ALLX 2 "register_operand" "r"))
1955                      (match_operand 3 "aarch64_imm3" "Ui3")))
1956          (const_int 0)))
1957    (set (match_operand:GPI 0 "register_operand" "=rk")
1958         (minus:GPI (match_dup 1)
1959                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1960                                (match_dup 3))))]
1961   ""
1962   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1963   [(set_attr "type" "alus_ext")]
1966 (define_insn "*adds_<optab><mode>_multp2"
1967   [(set (reg:CC_NZ CC_REGNUM)
1968         (compare:CC_NZ
1969          (plus:GPI (ANY_EXTRACT:GPI
1970                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1971                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1972                     (match_operand 3 "const_int_operand" "n")
1973                     (const_int 0))
1974                    (match_operand:GPI 4 "register_operand" "r"))
1975         (const_int 0)))
1976    (set (match_operand:GPI 0 "register_operand" "=r")
1977         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1978                                    (match_dup 3)
1979                                    (const_int 0))
1980                   (match_dup 4)))]
1981   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1982   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1983   [(set_attr "type" "alus_ext")]
1986 (define_insn "*subs_<optab><mode>_multp2"
1987   [(set (reg:CC_NZ CC_REGNUM)
1988         (compare:CC_NZ
1989          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1990                     (ANY_EXTRACT:GPI
1991                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1992                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1993                      (match_operand 3 "const_int_operand" "n")
1994                      (const_int 0)))
1995         (const_int 0)))
1996    (set (match_operand:GPI 0 "register_operand" "=r")
1997         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1998                                   (mult:GPI (match_dup 1) (match_dup 2))
1999                                   (match_dup 3)
2000                                   (const_int 0))))]
2001   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2002   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2003   [(set_attr "type" "alus_ext")]
2006 (define_insn "*add<mode>3nr_compare0"
2007   [(set (reg:CC_NZ CC_REGNUM)
2008         (compare:CC_NZ
2009          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2010                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2011          (const_int 0)))]
2012   ""
2013   "@
2014   cmn\\t%<w>0, %<w>1
2015   cmn\\t%<w>0, %1
2016   cmp\\t%<w>0, #%n1"
2017   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2020 (define_insn "*compare_neg<mode>"
2021   [(set (reg:CC_Z CC_REGNUM)
2022         (compare:CC_Z
2023          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2024          (match_operand:GPI 1 "register_operand" "r")))]
2025   ""
2026   "cmn\\t%<w>1, %<w>0"
2027   [(set_attr "type" "alus_sreg")]
2030 (define_insn "*add_<shift>_<mode>"
2031   [(set (match_operand:GPI 0 "register_operand" "=r")
2032         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2033                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2034                   (match_operand:GPI 3 "register_operand" "r")))]
2035   ""
2036   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2037   [(set_attr "type" "alu_shift_imm")]
2040 ;; zero_extend version of above
2041 (define_insn "*add_<shift>_si_uxtw"
2042   [(set (match_operand:DI 0 "register_operand" "=r")
2043         (zero_extend:DI
2044          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2045                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2046                   (match_operand:SI 3 "register_operand" "r"))))]
2047   ""
2048   "add\\t%w0, %w3, %w1, <shift> %2"
2049   [(set_attr "type" "alu_shift_imm")]
2052 (define_insn "*add_mul_imm_<mode>"
2053   [(set (match_operand:GPI 0 "register_operand" "=r")
2054         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2055                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2056                   (match_operand:GPI 3 "register_operand" "r")))]
2057   ""
2058   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2059   [(set_attr "type" "alu_shift_imm")]
2062 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2063   [(set (match_operand:GPI 0 "register_operand" "=rk")
2064         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2065                   (match_operand:GPI 2 "register_operand" "r")))]
2066   ""
2067   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2068   [(set_attr "type" "alu_ext")]
2071 ;; zero_extend version of above
2072 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2073   [(set (match_operand:DI 0 "register_operand" "=rk")
2074         (zero_extend:DI
2075          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2076                   (match_operand:GPI 2 "register_operand" "r"))))]
2077   ""
2078   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2079   [(set_attr "type" "alu_ext")]
2082 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2083   [(set (match_operand:GPI 0 "register_operand" "=rk")
2084         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2085                                (match_operand:ALLX 1 "register_operand" "r"))
2086                               (match_operand 2 "aarch64_imm3" "Ui3"))
2087                   (match_operand:GPI 3 "register_operand" "r")))]
2088   ""
2089   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2090   [(set_attr "type" "alu_ext")]
2093 ;; zero_extend version of above
2094 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2095   [(set (match_operand:DI 0 "register_operand" "=rk")
2096         (zero_extend:DI
2097          (plus:SI (ashift:SI (ANY_EXTEND:SI
2098                               (match_operand:SHORT 1 "register_operand" "r"))
2099                              (match_operand 2 "aarch64_imm3" "Ui3"))
2100                   (match_operand:SI 3 "register_operand" "r"))))]
2101   ""
2102   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2103   [(set_attr "type" "alu_ext")]
2106 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2107   [(set (match_operand:GPI 0 "register_operand" "=rk")
2108         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2109                              (match_operand:ALLX 1 "register_operand" "r"))
2110                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2111                   (match_operand:GPI 3 "register_operand" "r")))]
2112   ""
2113   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2114   [(set_attr "type" "alu_ext")]
2117 ;; zero_extend version of above
2118 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2119   [(set (match_operand:DI 0 "register_operand" "=rk")
2120         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2121                              (match_operand:SHORT 1 "register_operand" "r"))
2122                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2123                   (match_operand:SI 3 "register_operand" "r"))))]
2124   ""
2125   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2126   [(set_attr "type" "alu_ext")]
2129 (define_insn "*add_<optab><mode>_multp2"
2130   [(set (match_operand:GPI 0 "register_operand" "=rk")
2131         (plus:GPI (ANY_EXTRACT:GPI
2132                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2133                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2134                    (match_operand 3 "const_int_operand" "n")
2135                    (const_int 0))
2136                   (match_operand:GPI 4 "register_operand" "r")))]
2137   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2138   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2139   [(set_attr "type" "alu_ext")]
2142 ;; zero_extend version of above
2143 (define_insn "*add_<optab>si_multp2_uxtw"
2144   [(set (match_operand:DI 0 "register_operand" "=rk")
2145         (zero_extend:DI
2146          (plus:SI (ANY_EXTRACT:SI
2147                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2148                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2149                    (match_operand 3 "const_int_operand" "n")
2150                    (const_int 0))
2151                   (match_operand:SI 4 "register_operand" "r"))))]
2152   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2153   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2154   [(set_attr "type" "alu_ext")]
2157 (define_expand "add<mode>3_carryin"
2158   [(set (match_operand:GPI 0 "register_operand")
2159         (plus:GPI
2160           (plus:GPI
2161             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2162             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2163           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2164    ""
2165    ""
2168 ;; Note that add with carry with two zero inputs is matched by cset,
2169 ;; and that add with carry with one zero input is matched by cinc.
2171 (define_insn "*add<mode>3_carryin"
2172   [(set (match_operand:GPI 0 "register_operand" "=r")
2173         (plus:GPI
2174           (plus:GPI
2175             (match_operand:GPI 3 "aarch64_carry_operation" "")
2176             (match_operand:GPI 1 "register_operand" "r"))
2177           (match_operand:GPI 2 "register_operand" "r")))]
2178    ""
2179    "adc\\t%<w>0, %<w>1, %<w>2"
2180   [(set_attr "type" "adc_reg")]
2183 ;; zero_extend version of above
2184 (define_insn "*addsi3_carryin_uxtw"
2185   [(set (match_operand:DI 0 "register_operand" "=r")
2186         (zero_extend:DI
2187           (plus:SI
2188             (plus:SI
2189               (match_operand:SI 3 "aarch64_carry_operation" "")
2190               (match_operand:SI 1 "register_operand" "r"))
2191             (match_operand:SI 2 "register_operand" "r"))))]
2192    ""
2193    "adc\\t%w0, %w1, %w2"
2194   [(set_attr "type" "adc_reg")]
2197 (define_insn "*add_uxt<mode>_shift2"
2198   [(set (match_operand:GPI 0 "register_operand" "=rk")
2199         (plus:GPI (and:GPI
2200                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2201                                (match_operand 2 "aarch64_imm3" "Ui3"))
2202                    (match_operand 3 "const_int_operand" "n"))
2203                   (match_operand:GPI 4 "register_operand" "r")))]
2204   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2205   "*
2206   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2207                                            INTVAL (operands[3])));
2208   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2209   [(set_attr "type" "alu_ext")]
2212 ;; zero_extend version of above
2213 (define_insn "*add_uxtsi_shift2_uxtw"
2214   [(set (match_operand:DI 0 "register_operand" "=rk")
2215         (zero_extend:DI
2216          (plus:SI (and:SI
2217                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2218                               (match_operand 2 "aarch64_imm3" "Ui3"))
2219                    (match_operand 3 "const_int_operand" "n"))
2220                   (match_operand:SI 4 "register_operand" "r"))))]
2221   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2222   "*
2223   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2224                                            INTVAL (operands[3])));
2225   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2226   [(set_attr "type" "alu_ext")]
2229 (define_insn "*add_uxt<mode>_multp2"
2230   [(set (match_operand:GPI 0 "register_operand" "=rk")
2231         (plus:GPI (and:GPI
2232                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2233                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2234                    (match_operand 3 "const_int_operand" "n"))
2235                   (match_operand:GPI 4 "register_operand" "r")))]
2236   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2237   "*
2238   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2239                                            INTVAL (operands[3])));
2240   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2241   [(set_attr "type" "alu_ext")]
2244 ;; zero_extend version of above
2245 (define_insn "*add_uxtsi_multp2_uxtw"
2246   [(set (match_operand:DI 0 "register_operand" "=rk")
2247         (zero_extend:DI
2248          (plus:SI (and:SI
2249                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2250                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2251                    (match_operand 3 "const_int_operand" "n"))
2252                   (match_operand:SI 4 "register_operand" "r"))))]
2253   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2254   "*
2255   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2256                                            INTVAL (operands[3])));
2257   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2258   [(set_attr "type" "alu_ext")]
2261 (define_insn "subsi3"
2262   [(set (match_operand:SI 0 "register_operand" "=rk")
2263         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2264                   (match_operand:SI 2 "register_operand" "r")))]
2265   ""
2266   "sub\\t%w0, %w1, %w2"
2267   [(set_attr "type" "alu_sreg")]
2270 ;; zero_extend version of above
2271 (define_insn "*subsi3_uxtw"
2272   [(set (match_operand:DI 0 "register_operand" "=rk")
2273         (zero_extend:DI
2274          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2275                    (match_operand:SI 2 "register_operand" "r"))))]
2276   ""
2277   "sub\\t%w0, %w1, %w2"
2278   [(set_attr "type" "alu_sreg")]
2281 (define_insn "subdi3"
2282   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2283         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2284                   (match_operand:DI 2 "register_operand" "r,w")))]
2285   ""
2286   "@
2287    sub\\t%x0, %x1, %x2
2288    sub\\t%d0, %d1, %d2"
2289   [(set_attr "type" "alu_sreg, neon_sub")
2290    (set_attr "simd" "*,yes")]
2293 (define_expand "subti3"
2294   [(set (match_operand:TI 0 "register_operand" "")
2295         (minus:TI (match_operand:TI 1 "register_operand" "")
2296                   (match_operand:TI 2 "register_operand" "")))]
2297   ""
2299   rtx low = gen_reg_rtx (DImode);
2300   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2301                                   gen_lowpart (DImode, operands[2])));
2303   rtx high = gen_reg_rtx (DImode);
2304   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2305                                  gen_highpart (DImode, operands[2])));
2307   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2308   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2309   DONE;
2312 (define_insn "*sub<mode>3_compare0"
2313   [(set (reg:CC_NZ CC_REGNUM)
2314         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2315                                   (match_operand:GPI 2 "register_operand" "r"))
2316                        (const_int 0)))
2317    (set (match_operand:GPI 0 "register_operand" "=r")
2318         (minus:GPI (match_dup 1) (match_dup 2)))]
2319   ""
2320   "subs\\t%<w>0, %<w>1, %<w>2"
2321   [(set_attr "type" "alus_sreg")]
2324 ;; zero_extend version of above
2325 (define_insn "*subsi3_compare0_uxtw"
2326   [(set (reg:CC_NZ CC_REGNUM)
2327         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2328                                  (match_operand:SI 2 "register_operand" "r"))
2329                        (const_int 0)))
2330    (set (match_operand:DI 0 "register_operand" "=r")
2331         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2332   ""
2333   "subs\\t%w0, %w1, %w2"
2334   [(set_attr "type" "alus_sreg")]
2337 (define_insn "sub<mode>3_compare1"
2338   [(set (reg:CC CC_REGNUM)
2339         (compare:CC
2340           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2341           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2342    (set (match_operand:GPI 0 "register_operand" "=r")
2343         (minus:GPI (match_dup 1) (match_dup 2)))]
2344   ""
2345   "subs\\t%<w>0, %<w>1, %<w>2"
2346   [(set_attr "type" "alus_sreg")]
2349 (define_insn "*sub_<shift>_<mode>"
2350   [(set (match_operand:GPI 0 "register_operand" "=r")
2351         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2352                    (ASHIFT:GPI
2353                     (match_operand:GPI 1 "register_operand" "r")
2354                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2355   ""
2356   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2357   [(set_attr "type" "alu_shift_imm")]
2360 ;; zero_extend version of above
2361 (define_insn "*sub_<shift>_si_uxtw"
2362   [(set (match_operand:DI 0 "register_operand" "=r")
2363         (zero_extend:DI
2364          (minus:SI (match_operand:SI 3 "register_operand" "r")
2365                    (ASHIFT:SI
2366                     (match_operand:SI 1 "register_operand" "r")
2367                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2368   ""
2369   "sub\\t%w0, %w3, %w1, <shift> %2"
2370   [(set_attr "type" "alu_shift_imm")]
2373 (define_insn "*sub_mul_imm_<mode>"
2374   [(set (match_operand:GPI 0 "register_operand" "=r")
2375         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2376                    (mult:GPI
2377                     (match_operand:GPI 1 "register_operand" "r")
2378                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2379   ""
2380   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2381   [(set_attr "type" "alu_shift_imm")]
2384 ;; zero_extend version of above
2385 (define_insn "*sub_mul_imm_si_uxtw"
2386   [(set (match_operand:DI 0 "register_operand" "=r")
2387         (zero_extend:DI
2388          (minus:SI (match_operand:SI 3 "register_operand" "r")
2389                    (mult:SI
2390                     (match_operand:SI 1 "register_operand" "r")
2391                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2392   ""
2393   "sub\\t%w0, %w3, %w1, lsl %p2"
2394   [(set_attr "type" "alu_shift_imm")]
2397 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2398   [(set (match_operand:GPI 0 "register_operand" "=rk")
2399         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2400                    (ANY_EXTEND:GPI
2401                     (match_operand:ALLX 2 "register_operand" "r"))))]
2402   ""
2403   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2404   [(set_attr "type" "alu_ext")]
2407 ;; zero_extend version of above
2408 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2409   [(set (match_operand:DI 0 "register_operand" "=rk")
2410         (zero_extend:DI
2411          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2412                    (ANY_EXTEND:SI
2413                     (match_operand:SHORT 2 "register_operand" "r")))))]
2414   ""
2415   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2416   [(set_attr "type" "alu_ext")]
2419 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2420   [(set (match_operand:GPI 0 "register_operand" "=rk")
2421         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2422                    (ashift:GPI (ANY_EXTEND:GPI
2423                                 (match_operand:ALLX 2 "register_operand" "r"))
2424                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2425   ""
2426   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2427   [(set_attr "type" "alu_ext")]
2430 ;; zero_extend version of above
2431 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2432   [(set (match_operand:DI 0 "register_operand" "=rk")
2433         (zero_extend:DI
2434          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2435                    (ashift:SI (ANY_EXTEND:SI
2436                                (match_operand:SHORT 2 "register_operand" "r"))
2437                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2438   ""
2439   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2440   [(set_attr "type" "alu_ext")]
2443 (define_insn "*sub_<optab><mode>_multp2"
2444   [(set (match_operand:GPI 0 "register_operand" "=rk")
2445         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2446                    (ANY_EXTRACT:GPI
2447                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2448                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2449                     (match_operand 3 "const_int_operand" "n")
2450                     (const_int 0))))]
2451   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2452   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2453   [(set_attr "type" "alu_ext")]
2456 ;; zero_extend version of above
2457 (define_insn "*sub_<optab>si_multp2_uxtw"
2458   [(set (match_operand:DI 0 "register_operand" "=rk")
2459         (zero_extend:DI
2460          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2461                    (ANY_EXTRACT:SI
2462                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2463                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2464                     (match_operand 3 "const_int_operand" "n")
2465                     (const_int 0)))))]
2466   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2467   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2468   [(set_attr "type" "alu_ext")]
2471 ;; The hardware description is op1 + ~op2 + C.
2472 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2473 ;;                           = op1 - op2 - 1 + 1 - !C
2474 ;;                           = op1 - op2 - !C.
2475 ;; We describe the latter.
2477 (define_insn "*sub<mode>3_carryin0"
2478   [(set (match_operand:GPI 0 "register_operand" "=r")
2479         (minus:GPI
2480           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2481           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2482    ""
2483    "sbc\\t%<w>0, %<w>1, <w>zr"
2484   [(set_attr "type" "adc_reg")]
2487 ;; zero_extend version of the above
2488 (define_insn "*subsi3_carryin_uxtw"
2489   [(set (match_operand:DI 0 "register_operand" "=r")
2490         (zero_extend:DI
2491           (minus:SI
2492             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2493             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2494    ""
2495    "sbc\\t%w0, %w1, wzr"
2496   [(set_attr "type" "adc_reg")]
2499 (define_expand "sub<mode>3_carryin"
2500   [(set (match_operand:GPI 0 "register_operand")
2501         (minus:GPI
2502           (minus:GPI
2503             (match_operand:GPI 1 "aarch64_reg_or_zero")
2504             (match_operand:GPI 2 "register_operand"))
2505           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2506    ""
2507    ""
2510 (define_insn "*sub<mode>3_carryin"
2511   [(set (match_operand:GPI 0 "register_operand" "=r")
2512         (minus:GPI
2513           (minus:GPI
2514             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2515             (match_operand:GPI 2 "register_operand" "r"))
2516           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2518    ""
2519    "sbc\\t%<w>0, %<w>1, %<w>2"
2520   [(set_attr "type" "adc_reg")]
2523 ;; zero_extend version of the above
2524 (define_insn "*subsi3_carryin_uxtw"
2525   [(set (match_operand:DI 0 "register_operand" "=r")
2526         (zero_extend:DI
2527           (minus:SI
2528             (minus:SI
2529               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2530               (match_operand:SI 2 "register_operand" "r"))
2531             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2533    ""
2534    "sbc\\t%w0, %w1, %w2"
2535   [(set_attr "type" "adc_reg")]
2538 (define_insn "*sub<mode>3_carryin_alt"
2539   [(set (match_operand:GPI 0 "register_operand" "=r")
2540         (minus:GPI
2541           (minus:GPI
2542             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2543             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2544           (match_operand:GPI 2 "register_operand" "r")))]
2545    ""
2546    "sbc\\t%<w>0, %<w>1, %<w>2"
2547   [(set_attr "type" "adc_reg")]
2550 ;; zero_extend version of the above
2551 (define_insn "*subsi3_carryin_alt_uxtw"
2552   [(set (match_operand:DI 0 "register_operand" "=r")
2553         (zero_extend:DI
2554           (minus:SI
2555             (minus:SI
2556               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2557               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2558             (match_operand:SI 2 "register_operand" "r"))))]
2559    ""
2560    "sbc\\t%w0, %w1, %w2"
2561   [(set_attr "type" "adc_reg")]
2564 (define_insn "*sub_uxt<mode>_shift2"
2565   [(set (match_operand:GPI 0 "register_operand" "=rk")
2566         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2567                    (and:GPI
2568                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2569                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2570                     (match_operand 3 "const_int_operand" "n"))))]
2571   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2572   "*
2573   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2574                                            INTVAL (operands[3])));
2575   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2576   [(set_attr "type" "alu_ext")]
2579 ;; zero_extend version of above
2580 (define_insn "*sub_uxtsi_shift2_uxtw"
2581   [(set (match_operand:DI 0 "register_operand" "=rk")
2582         (zero_extend:DI
2583          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2584                    (and:SI
2585                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2586                                (match_operand 2 "aarch64_imm3" "Ui3"))
2587                     (match_operand 3 "const_int_operand" "n")))))]
2588   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2589   "*
2590   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2591                                            INTVAL (operands[3])));
2592   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2593   [(set_attr "type" "alu_ext")]
2596 (define_insn "*sub_uxt<mode>_multp2"
2597   [(set (match_operand:GPI 0 "register_operand" "=rk")
2598         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2599                    (and:GPI
2600                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2601                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2602                     (match_operand 3 "const_int_operand" "n"))))]
2603   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2604   "*
2605   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2606                                            INTVAL (operands[3])));
2607   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2608   [(set_attr "type" "alu_ext")]
2611 ;; zero_extend version of above
2612 (define_insn "*sub_uxtsi_multp2_uxtw"
2613   [(set (match_operand:DI 0 "register_operand" "=rk")
2614         (zero_extend:DI
2615          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2616                    (and:SI
2617                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2618                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2619                     (match_operand 3 "const_int_operand" "n")))))]
2620   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2621   "*
2622   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2623                                            INTVAL (operands[3])));
2624   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2625   [(set_attr "type" "alu_ext")]
2628 (define_expand "abs<mode>2"
2629   [(match_operand:GPI 0 "register_operand" "")
2630    (match_operand:GPI 1 "register_operand" "")]
2631   ""
2632   {
2633     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2634     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2635     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2636     DONE;
2637   }
2640 (define_insn "neg<mode>2"
2641   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2642         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2643   ""
2644   "@
2645    neg\\t%<w>0, %<w>1
2646    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2647   [(set_attr "type" "alu_sreg, neon_neg<q>")
2648    (set_attr "simd" "*,yes")]
2651 ;; zero_extend version of above
2652 (define_insn "*negsi2_uxtw"
2653   [(set (match_operand:DI 0 "register_operand" "=r")
2654         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2655   ""
2656   "neg\\t%w0, %w1"
2657   [(set_attr "type" "alu_sreg")]
2660 (define_insn "*ngc<mode>"
2661   [(set (match_operand:GPI 0 "register_operand" "=r")
2662         (minus:GPI
2663           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2664           (match_operand:GPI 1 "register_operand" "r")))]
2665   ""
2666   "ngc\\t%<w>0, %<w>1"
2667   [(set_attr "type" "adc_reg")]
2670 (define_insn "*ngcsi_uxtw"
2671   [(set (match_operand:DI 0 "register_operand" "=r")
2672         (zero_extend:DI
2673           (minus:SI
2674             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2675             (match_operand:SI 1 "register_operand" "r"))))]
2676   ""
2677   "ngc\\t%w0, %w1"
2678   [(set_attr "type" "adc_reg")]
2681 (define_insn "neg<mode>2_compare0"
2682   [(set (reg:CC_NZ CC_REGNUM)
2683         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2684                        (const_int 0)))
2685    (set (match_operand:GPI 0 "register_operand" "=r")
2686         (neg:GPI (match_dup 1)))]
2687   ""
2688   "negs\\t%<w>0, %<w>1"
2689   [(set_attr "type" "alus_sreg")]
2692 ;; zero_extend version of above
2693 (define_insn "*negsi2_compare0_uxtw"
2694   [(set (reg:CC_NZ CC_REGNUM)
2695         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2696                        (const_int 0)))
2697    (set (match_operand:DI 0 "register_operand" "=r")
2698         (zero_extend:DI (neg:SI (match_dup 1))))]
2699   ""
2700   "negs\\t%w0, %w1"
2701   [(set_attr "type" "alus_sreg")]
2704 (define_insn "*neg_<shift><mode>3_compare0"
2705   [(set (reg:CC_NZ CC_REGNUM)
2706         (compare:CC_NZ
2707          (neg:GPI (ASHIFT:GPI
2708                    (match_operand:GPI 1 "register_operand" "r")
2709                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2710          (const_int 0)))
2711    (set (match_operand:GPI 0 "register_operand" "=r")
2712         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2713   ""
2714   "negs\\t%<w>0, %<w>1, <shift> %2"
2715   [(set_attr "type" "alus_shift_imm")]
2718 (define_insn "*neg_<shift>_<mode>2"
2719   [(set (match_operand:GPI 0 "register_operand" "=r")
2720         (neg:GPI (ASHIFT:GPI
2721                   (match_operand:GPI 1 "register_operand" "r")
2722                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2723   ""
2724   "neg\\t%<w>0, %<w>1, <shift> %2"
2725   [(set_attr "type" "alu_shift_imm")]
2728 ;; zero_extend version of above
2729 (define_insn "*neg_<shift>_si2_uxtw"
2730   [(set (match_operand:DI 0 "register_operand" "=r")
2731         (zero_extend:DI
2732          (neg:SI (ASHIFT:SI
2733                   (match_operand:SI 1 "register_operand" "r")
2734                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2735   ""
2736   "neg\\t%w0, %w1, <shift> %2"
2737   [(set_attr "type" "alu_shift_imm")]
2740 (define_insn "*neg_mul_imm_<mode>2"
2741   [(set (match_operand:GPI 0 "register_operand" "=r")
2742         (neg:GPI (mult:GPI
2743                   (match_operand:GPI 1 "register_operand" "r")
2744                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2745   ""
2746   "neg\\t%<w>0, %<w>1, lsl %p2"
2747   [(set_attr "type" "alu_shift_imm")]
2750 ;; zero_extend version of above
2751 (define_insn "*neg_mul_imm_si2_uxtw"
2752   [(set (match_operand:DI 0 "register_operand" "=r")
2753         (zero_extend:DI
2754          (neg:SI (mult:SI
2755                   (match_operand:SI 1 "register_operand" "r")
2756                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2757   ""
2758   "neg\\t%w0, %w1, lsl %p2"
2759   [(set_attr "type" "alu_shift_imm")]
2762 (define_insn "mul<mode>3"
2763   [(set (match_operand:GPI 0 "register_operand" "=r")
2764         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2765                   (match_operand:GPI 2 "register_operand" "r")))]
2766   ""
2767   "mul\\t%<w>0, %<w>1, %<w>2"
2768   [(set_attr "type" "mul")]
2771 ;; zero_extend version of above
2772 (define_insn "*mulsi3_uxtw"
2773   [(set (match_operand:DI 0 "register_operand" "=r")
2774         (zero_extend:DI
2775          (mult:SI (match_operand:SI 1 "register_operand" "r")
2776                   (match_operand:SI 2 "register_operand" "r"))))]
2777   ""
2778   "mul\\t%w0, %w1, %w2"
2779   [(set_attr "type" "mul")]
2782 (define_insn "madd<mode>"
2783   [(set (match_operand:GPI 0 "register_operand" "=r")
2784         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2785                             (match_operand:GPI 2 "register_operand" "r"))
2786                   (match_operand:GPI 3 "register_operand" "r")))]
2787   ""
2788   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2789   [(set_attr "type" "mla")]
2792 ;; zero_extend version of above
2793 (define_insn "*maddsi_uxtw"
2794   [(set (match_operand:DI 0 "register_operand" "=r")
2795         (zero_extend:DI
2796          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2797                            (match_operand:SI 2 "register_operand" "r"))
2798                   (match_operand:SI 3 "register_operand" "r"))))]
2799   ""
2800   "madd\\t%w0, %w1, %w2, %w3"
2801   [(set_attr "type" "mla")]
2804 (define_insn "*msub<mode>"
2805   [(set (match_operand:GPI 0 "register_operand" "=r")
2806         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2807                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2808                              (match_operand:GPI 2 "register_operand" "r"))))]
2810   ""
2811   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2812   [(set_attr "type" "mla")]
2815 ;; zero_extend version of above
2816 (define_insn "*msubsi_uxtw"
2817   [(set (match_operand:DI 0 "register_operand" "=r")
2818         (zero_extend:DI
2819          (minus:SI (match_operand:SI 3 "register_operand" "r")
2820                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2821                             (match_operand:SI 2 "register_operand" "r")))))]
2823   ""
2824   "msub\\t%w0, %w1, %w2, %w3"
2825   [(set_attr "type" "mla")]
2828 (define_insn "*mul<mode>_neg"
2829   [(set (match_operand:GPI 0 "register_operand" "=r")
2830         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2831                   (match_operand:GPI 2 "register_operand" "r")))]
2833   ""
2834   "mneg\\t%<w>0, %<w>1, %<w>2"
2835   [(set_attr "type" "mul")]
2838 ;; zero_extend version of above
2839 (define_insn "*mulsi_neg_uxtw"
2840   [(set (match_operand:DI 0 "register_operand" "=r")
2841         (zero_extend:DI
2842          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2843                   (match_operand:SI 2 "register_operand" "r"))))]
2845   ""
2846   "mneg\\t%w0, %w1, %w2"
2847   [(set_attr "type" "mul")]
2850 (define_insn "<su_optab>mulsidi3"
2851   [(set (match_operand:DI 0 "register_operand" "=r")
2852         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2853                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2854   ""
2855   "<su>mull\\t%0, %w1, %w2"
2856   [(set_attr "type" "<su>mull")]
2859 (define_insn "<su_optab>maddsidi4"
2860   [(set (match_operand:DI 0 "register_operand" "=r")
2861         (plus:DI (mult:DI
2862                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2863                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2864                  (match_operand:DI 3 "register_operand" "r")))]
2865   ""
2866   "<su>maddl\\t%0, %w1, %w2, %3"
2867   [(set_attr "type" "<su>mlal")]
2870 (define_insn "<su_optab>msubsidi4"
2871   [(set (match_operand:DI 0 "register_operand" "=r")
2872         (minus:DI
2873          (match_operand:DI 3 "register_operand" "r")
2874          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2875                   (ANY_EXTEND:DI
2876                    (match_operand:SI 2 "register_operand" "r")))))]
2877   ""
2878   "<su>msubl\\t%0, %w1, %w2, %3"
2879   [(set_attr "type" "<su>mlal")]
2882 (define_insn "*<su_optab>mulsidi_neg"
2883   [(set (match_operand:DI 0 "register_operand" "=r")
2884         (mult:DI (neg:DI
2885                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2886                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2887   ""
2888   "<su>mnegl\\t%0, %w1, %w2"
2889   [(set_attr "type" "<su>mull")]
2892 (define_expand "<su_optab>mulditi3"
2893   [(set (match_operand:TI 0 "register_operand")
2894         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2895                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2896   ""
2898   rtx low = gen_reg_rtx (DImode);
2899   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2901   rtx high = gen_reg_rtx (DImode);
2902   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2904   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2905   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2906   DONE;
2909 ;; The default expansion of multi3 using umuldi3_highpart will perform
2910 ;; the additions in an order that fails to combine into two madd insns.
2911 (define_expand "multi3"
2912   [(set (match_operand:TI 0 "register_operand")
2913         (mult:TI (match_operand:TI 1 "register_operand")
2914                  (match_operand:TI 2 "register_operand")))]
2915   ""
2917   rtx l0 = gen_reg_rtx (DImode);
2918   rtx l1 = gen_lowpart (DImode, operands[1]);
2919   rtx l2 = gen_lowpart (DImode, operands[2]);
2920   rtx h0 = gen_reg_rtx (DImode);
2921   rtx h1 = gen_highpart (DImode, operands[1]);
2922   rtx h2 = gen_highpart (DImode, operands[2]);
2924   emit_insn (gen_muldi3 (l0, l1, l2));
2925   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2926   emit_insn (gen_madddi (h0, h1, l2, h0));
2927   emit_insn (gen_madddi (h0, l1, h2, h0));
2929   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2930   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2931   DONE;
2934 (define_insn "<su>muldi3_highpart"
2935   [(set (match_operand:DI 0 "register_operand" "=r")
2936         (truncate:DI
2937          (lshiftrt:TI
2938           (mult:TI
2939            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2940            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2941           (const_int 64))))]
2942   ""
2943   "<su>mulh\\t%0, %1, %2"
2944   [(set_attr "type" "<su>mull")]
2947 (define_insn "<su_optab>div<mode>3"
2948   [(set (match_operand:GPI 0 "register_operand" "=r")
2949         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2950                      (match_operand:GPI 2 "register_operand" "r")))]
2951   ""
2952   "<su>div\\t%<w>0, %<w>1, %<w>2"
2953   [(set_attr "type" "<su>div")]
2956 ;; zero_extend version of above
2957 (define_insn "*<su_optab>divsi3_uxtw"
2958   [(set (match_operand:DI 0 "register_operand" "=r")
2959         (zero_extend:DI
2960          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2961                      (match_operand:SI 2 "register_operand" "r"))))]
2962   ""
2963   "<su>div\\t%w0, %w1, %w2"
2964   [(set_attr "type" "<su>div")]
2967 ;; -------------------------------------------------------------------
2968 ;; Comparison insns
2969 ;; -------------------------------------------------------------------
2971 (define_insn "cmp<mode>"
2972   [(set (reg:CC CC_REGNUM)
2973         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2974                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2975   ""
2976   "@
2977    cmp\\t%<w>0, %<w>1
2978    cmp\\t%<w>0, %1
2979    cmn\\t%<w>0, #%n1"
2980   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2983 (define_insn "fcmp<mode>"
2984   [(set (reg:CCFP CC_REGNUM)
2985         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2986                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2987    "TARGET_FLOAT"
2988    "@
2989     fcmp\\t%<s>0, #0.0
2990     fcmp\\t%<s>0, %<s>1"
2991   [(set_attr "type" "fcmp<s>")]
2994 (define_insn "fcmpe<mode>"
2995   [(set (reg:CCFPE CC_REGNUM)
2996         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2997                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2998    "TARGET_FLOAT"
2999    "@
3000     fcmpe\\t%<s>0, #0.0
3001     fcmpe\\t%<s>0, %<s>1"
3002   [(set_attr "type" "fcmp<s>")]
3005 (define_insn "*cmp_swp_<shift>_reg<mode>"
3006   [(set (reg:CC_SWP CC_REGNUM)
3007         (compare:CC_SWP (ASHIFT:GPI
3008                          (match_operand:GPI 0 "register_operand" "r")
3009                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3010                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3011   ""
3012   "cmp\\t%<w>2, %<w>0, <shift> %1"
3013   [(set_attr "type" "alus_shift_imm")]
3016 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3017   [(set (reg:CC_SWP CC_REGNUM)
3018         (compare:CC_SWP (ANY_EXTEND:GPI
3019                          (match_operand:ALLX 0 "register_operand" "r"))
3020                         (match_operand:GPI 1 "register_operand" "r")))]
3021   ""
3022   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3023   [(set_attr "type" "alus_ext")]
3026 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3027   [(set (reg:CC_SWP CC_REGNUM)
3028         (compare:CC_SWP (ashift:GPI
3029                          (ANY_EXTEND:GPI
3030                           (match_operand:ALLX 0 "register_operand" "r"))
3031                          (match_operand 1 "aarch64_imm3" "Ui3"))
3032         (match_operand:GPI 2 "register_operand" "r")))]
3033   ""
3034   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3035   [(set_attr "type" "alus_ext")]
3038 ;; -------------------------------------------------------------------
3039 ;; Store-flag and conditional select insns
3040 ;; -------------------------------------------------------------------
3042 (define_expand "cstore<mode>4"
3043   [(set (match_operand:SI 0 "register_operand" "")
3044         (match_operator:SI 1 "aarch64_comparison_operator"
3045          [(match_operand:GPI 2 "register_operand" "")
3046           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3047   ""
3048   "
3049   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3050                                       operands[3]);
3051   operands[3] = const0_rtx;
3052   "
3055 (define_expand "cstorecc4"
3056   [(set (match_operand:SI 0 "register_operand")
3057        (match_operator 1 "aarch64_comparison_operator_mode"
3058         [(match_operand 2 "cc_register")
3059          (match_operand 3 "const0_operand")]))]
3060   ""
3062   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3063   DONE;
3067 (define_expand "cstore<mode>4"
3068   [(set (match_operand:SI 0 "register_operand" "")
3069         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3070          [(match_operand:GPF 2 "register_operand" "")
3071           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3072   ""
3073   "
3074   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3075                                       operands[3]);
3076   operands[3] = const0_rtx;
3077   "
3080 (define_insn "aarch64_cstore<mode>"
3081   [(set (match_operand:ALLI 0 "register_operand" "=r")
3082         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3083          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3084   ""
3085   "cset\\t%<w>0, %m1"
3086   [(set_attr "type" "csel")]
3089 ;; For a 24-bit immediate CST we can optimize the compare for equality
3090 ;; and branch sequence from:
3091 ;;      mov     x0, #imm1
3092 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3093 ;;      cmp     x1, x0
3094 ;;      cset    x2, <ne,eq>
3095 ;; into the shorter:
3096 ;;      sub     x0, x1, #(CST & 0xfff000)
3097 ;;      subs    x0, x0, #(CST & 0x000fff)
3098 ;;      cset x2, <ne, eq>.
3099 (define_insn_and_split "*compare_cstore<mode>_insn"
3100   [(set (match_operand:GPI 0 "register_operand" "=r")
3101          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3102                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3103   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3104    && !aarch64_plus_operand (operands[2], <MODE>mode)
3105    && !reload_completed"
3106   "#"
3107   "&& true"
3108   [(const_int 0)]
3109   {
3110     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3111     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3112     rtx tmp = gen_reg_rtx (<MODE>mode);
3113     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3114     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3115     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3116     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3117     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3118     DONE;
3119   }
3120   [(set_attr "type" "csel")]
3123 ;; zero_extend version of the above
3124 (define_insn "*cstoresi_insn_uxtw"
3125   [(set (match_operand:DI 0 "register_operand" "=r")
3126         (zero_extend:DI
3127          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3128           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3129   ""
3130   "cset\\t%w0, %m1"
3131   [(set_attr "type" "csel")]
3134 (define_insn "cstore<mode>_neg"
3135   [(set (match_operand:ALLI 0 "register_operand" "=r")
3136         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3137                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3138   ""
3139   "csetm\\t%<w>0, %m1"
3140   [(set_attr "type" "csel")]
3143 ;; zero_extend version of the above
3144 (define_insn "*cstoresi_neg_uxtw"
3145   [(set (match_operand:DI 0 "register_operand" "=r")
3146         (zero_extend:DI
3147          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3148                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3149   ""
3150   "csetm\\t%w0, %m1"
3151   [(set_attr "type" "csel")]
3154 (define_expand "cmov<mode>6"
3155   [(set (match_operand:GPI 0 "register_operand" "")
3156         (if_then_else:GPI
3157          (match_operator 1 "aarch64_comparison_operator"
3158           [(match_operand:GPI 2 "register_operand" "")
3159            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3160          (match_operand:GPI 4 "register_operand" "")
3161          (match_operand:GPI 5 "register_operand" "")))]
3162   ""
3163   "
3164   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3165                                       operands[3]);
3166   operands[3] = const0_rtx;
3167   "
3170 (define_expand "cmov<mode>6"
3171   [(set (match_operand:GPF 0 "register_operand" "")
3172         (if_then_else:GPF
3173          (match_operator 1 "aarch64_comparison_operator"
3174           [(match_operand:GPF 2 "register_operand" "")
3175            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3176          (match_operand:GPF 4 "register_operand" "")
3177          (match_operand:GPF 5 "register_operand" "")))]
3178   ""
3179   "
3180   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3181                                       operands[3]);
3182   operands[3] = const0_rtx;
3183   "
3186 (define_insn "*cmov<mode>_insn"
3187   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3188         (if_then_else:ALLI
3189          (match_operator 1 "aarch64_comparison_operator"
3190           [(match_operand 2 "cc_register" "") (const_int 0)])
3191          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3192          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3193   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3194      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3195   ;; Final two alternatives should be unreachable, but included for completeness
3196   "@
3197    csel\\t%<w>0, %<w>3, %<w>4, %m1
3198    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3199    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3200    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3201    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3202    mov\\t%<w>0, -1
3203    mov\\t%<w>0, 1"
3204   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3207 ;; zero_extend version of above
3208 (define_insn "*cmovsi_insn_uxtw"
3209   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3210         (zero_extend:DI
3211          (if_then_else:SI
3212           (match_operator 1 "aarch64_comparison_operator"
3213            [(match_operand 2 "cc_register" "") (const_int 0)])
3214           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3215           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3216   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3217      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3218   ;; Final two alternatives should be unreachable, but included for completeness
3219   "@
3220    csel\\t%w0, %w3, %w4, %m1
3221    csinv\\t%w0, %w3, wzr, %m1
3222    csinv\\t%w0, %w4, wzr, %M1
3223    csinc\\t%w0, %w3, wzr, %m1
3224    csinc\\t%w0, %w4, wzr, %M1
3225    mov\\t%w0, -1
3226    mov\\t%w0, 1"
3227   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3230 (define_insn "*cmovdi_insn_uxtw"
3231   [(set (match_operand:DI 0 "register_operand" "=r")
3232         (if_then_else:DI
3233          (match_operator 1 "aarch64_comparison_operator"
3234           [(match_operand 2 "cc_register" "") (const_int 0)])
3235          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3236          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3237   ""
3238   "csel\\t%w0, %w3, %w4, %m1"
3239   [(set_attr "type" "csel")]
3242 (define_insn "*cmov<mode>_insn"
3243   [(set (match_operand:GPF 0 "register_operand" "=w")
3244         (if_then_else:GPF
3245          (match_operator 1 "aarch64_comparison_operator"
3246           [(match_operand 2 "cc_register" "") (const_int 0)])
3247          (match_operand:GPF 3 "register_operand" "w")
3248          (match_operand:GPF 4 "register_operand" "w")))]
3249   "TARGET_FLOAT"
3250   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3251   [(set_attr "type" "fcsel")]
3254 (define_expand "mov<mode>cc"
3255   [(set (match_operand:ALLI 0 "register_operand" "")
3256         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3257                            (match_operand:ALLI 2 "register_operand" "")
3258                            (match_operand:ALLI 3 "register_operand" "")))]
3259   ""
3260   {
3261     rtx ccreg;
3262     enum rtx_code code = GET_CODE (operands[1]);
3264     if (code == UNEQ || code == LTGT)
3265       FAIL;
3267     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3268                                      XEXP (operands[1], 1));
3269     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3270   }
3273 (define_expand "mov<GPF:mode><GPI:mode>cc"
3274   [(set (match_operand:GPI 0 "register_operand" "")
3275         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3276                           (match_operand:GPF 2 "register_operand" "")
3277                           (match_operand:GPF 3 "register_operand" "")))]
3278   ""
3279   {
3280     rtx ccreg;
3281     enum rtx_code code = GET_CODE (operands[1]);
3283     if (code == UNEQ || code == LTGT)
3284       FAIL;
3286     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3287                                   XEXP (operands[1], 1));
3288     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3289   }
3292 (define_expand "mov<mode>cc"
3293   [(set (match_operand:GPF 0 "register_operand" "")
3294         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3295                           (match_operand:GPF 2 "register_operand" "")
3296                           (match_operand:GPF 3 "register_operand" "")))]
3297   ""
3298   {
3299     rtx ccreg;
3300     enum rtx_code code = GET_CODE (operands[1]);
3302     if (code == UNEQ || code == LTGT)
3303       FAIL;
3305     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3306                                   XEXP (operands[1], 1));
3307     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3308   }
3311 (define_expand "<neg_not_op><mode>cc"
3312   [(set (match_operand:GPI 0 "register_operand" "")
3313         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3314                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3315                           (match_operand:GPI 3 "register_operand" "")))]
3316   ""
3317   {
3318     rtx ccreg;
3319     enum rtx_code code = GET_CODE (operands[1]);
3321     if (code == UNEQ || code == LTGT)
3322       FAIL;
3324     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3325                                       XEXP (operands[1], 1));
3326     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3327   }
3330 ;; CRC32 instructions.
3331 (define_insn "aarch64_<crc_variant>"
3332   [(set (match_operand:SI 0 "register_operand" "=r")
3333         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3334                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3335          CRC))]
3336   "TARGET_CRC32"
3337   {
3338     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3339       return "<crc_variant>\\t%w0, %w1, %x2";
3340     else
3341       return "<crc_variant>\\t%w0, %w1, %w2";
3342   }
3343   [(set_attr "type" "crc")]
3346 (define_insn "*csinc2<mode>_insn"
3347   [(set (match_operand:GPI 0 "register_operand" "=r")
3348         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3349                   (match_operand:GPI 1 "register_operand" "r")))]
3350   ""
3351   "cinc\\t%<w>0, %<w>1, %m2"
3352   [(set_attr "type" "csel")]
3355 (define_insn "csinc3<mode>_insn"
3356   [(set (match_operand:GPI 0 "register_operand" "=r")
3357         (if_then_else:GPI
3358           (match_operand 1 "aarch64_comparison_operation" "")
3359           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3360                     (const_int 1))
3361           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3362   ""
3363   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3364   [(set_attr "type" "csel")]
3367 (define_insn "*csinv3<mode>_insn"
3368   [(set (match_operand:GPI 0 "register_operand" "=r")
3369         (if_then_else:GPI
3370           (match_operand 1 "aarch64_comparison_operation" "")
3371           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3372           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3373   ""
3374   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3375   [(set_attr "type" "csel")]
3378 (define_insn "csneg3_uxtw_insn"
3379   [(set (match_operand:DI 0 "register_operand" "=r")
3380         (zero_extend:DI
3381           (if_then_else:SI
3382             (match_operand 1 "aarch64_comparison_operation" "")
3383             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3384             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3385   ""
3386   "csneg\\t%w0, %w3, %w2, %M1"
3387   [(set_attr "type" "csel")]
3390 (define_insn "csneg3<mode>_insn"
3391   [(set (match_operand:GPI 0 "register_operand" "=r")
3392         (if_then_else:GPI
3393           (match_operand 1 "aarch64_comparison_operation" "")
3394           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3395           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3396   ""
3397   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3398   [(set_attr "type" "csel")]
3401 ;; -------------------------------------------------------------------
3402 ;; Logical operations
3403 ;; -------------------------------------------------------------------
3406 (define_insn_and_split "*aarch64_and<mode>_imm2"
3407   [(set (match_operand:GPI 0 "register_operand" "=rk")
3408         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3409                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3410   ""
3411   "#"
3412   "true"
3413   [(const_int 0)]
3414   {
3415      HOST_WIDE_INT val = INTVAL (operands[2]);
3416      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3417      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3419      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3420      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3421      DONE;
3422   }
3425 (define_insn "<optab><mode>3"
3426   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3427         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3428                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3429   ""
3430   "@
3431   <logical>\\t%<w>0, %<w>1, %<w>2
3432   <logical>\\t%<w>0, %<w>1, %2
3433   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3434   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3435    (set_attr "simd" "*,*,yes")]
3438 ;; zero_extend version of above
3439 (define_insn "*<optab>si3_uxtw"
3440   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3441         (zero_extend:DI
3442          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3443                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3444   ""
3445   "@
3446    <logical>\\t%w0, %w1, %w2
3447    <logical>\\t%w0, %w1, %2"
3448   [(set_attr "type" "logic_reg,logic_imm")]
3451 (define_insn "*and<mode>3_compare0"
3452   [(set (reg:CC_NZ CC_REGNUM)
3453         (compare:CC_NZ
3454          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3455                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3456          (const_int 0)))
3457    (set (match_operand:GPI 0 "register_operand" "=r,r")
3458         (and:GPI (match_dup 1) (match_dup 2)))]
3459   ""
3460   "@
3461    ands\\t%<w>0, %<w>1, %<w>2
3462    ands\\t%<w>0, %<w>1, %2"
3463   [(set_attr "type" "logics_reg,logics_imm")]
3466 ;; zero_extend version of above
3467 (define_insn "*andsi3_compare0_uxtw"
3468   [(set (reg:CC_NZ CC_REGNUM)
3469         (compare:CC_NZ
3470          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3471                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3472          (const_int 0)))
3473    (set (match_operand:DI 0 "register_operand" "=r,r")
3474         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3475   ""
3476   "@
3477    ands\\t%w0, %w1, %w2
3478    ands\\t%w0, %w1, %2"
3479   [(set_attr "type" "logics_reg,logics_imm")]
3482 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3483   [(set (reg:CC_NZ CC_REGNUM)
3484         (compare:CC_NZ
3485          (and:GPI (SHIFT:GPI
3486                    (match_operand:GPI 1 "register_operand" "r")
3487                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3488                   (match_operand:GPI 3 "register_operand" "r"))
3489          (const_int 0)))
3490    (set (match_operand:GPI 0 "register_operand" "=r")
3491         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3492   ""
3493   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3494   [(set_attr "type" "logics_shift_imm")]
3497 ;; zero_extend version of above
3498 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3499   [(set (reg:CC_NZ CC_REGNUM)
3500         (compare:CC_NZ
3501          (and:SI (SHIFT:SI
3502                   (match_operand:SI 1 "register_operand" "r")
3503                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3504                  (match_operand:SI 3 "register_operand" "r"))
3505          (const_int 0)))
3506    (set (match_operand:DI 0 "register_operand" "=r")
3507         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3508                                 (match_dup 3))))]
3509   ""
3510   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3511   [(set_attr "type" "logics_shift_imm")]
3514 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3515   [(set (match_operand:GPI 0 "register_operand" "=r")
3516         (LOGICAL:GPI (SHIFT:GPI
3517                       (match_operand:GPI 1 "register_operand" "r")
3518                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3519                      (match_operand:GPI 3 "register_operand" "r")))]
3520   ""
3521   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3522   [(set_attr "type" "logic_shift_imm")]
3525 (define_insn "*<optab>_rol<mode>3"
3526   [(set (match_operand:GPI 0 "register_operand" "=r")
3527         (LOGICAL:GPI (rotate:GPI
3528                       (match_operand:GPI 1 "register_operand" "r")
3529                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3530                      (match_operand:GPI 3 "register_operand" "r")))]
3531   ""
3532   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3533   [(set_attr "type" "logic_shift_imm")]
3536 ;; zero_extend versions of above
3537 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3538   [(set (match_operand:DI 0 "register_operand" "=r")
3539         (zero_extend:DI
3540          (LOGICAL:SI (SHIFT:SI
3541                       (match_operand:SI 1 "register_operand" "r")
3542                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3543                      (match_operand:SI 3 "register_operand" "r"))))]
3544   ""
3545   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3546   [(set_attr "type" "logic_shift_imm")]
3549 (define_insn "*<optab>_rolsi3_uxtw"
3550   [(set (match_operand:DI 0 "register_operand" "=r")
3551         (zero_extend:DI
3552          (LOGICAL:SI (rotate:SI
3553                       (match_operand:SI 1 "register_operand" "r")
3554                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3555                      (match_operand:SI 3 "register_operand" "r"))))]
3556   ""
3557   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3558   [(set_attr "type" "logic_shift_imm")]
3561 (define_insn "one_cmpl<mode>2"
3562   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3563         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3564   ""
3565   "@
3566   mvn\\t%<w>0, %<w>1
3567   mvn\\t%0.8b, %1.8b"
3568   [(set_attr "type" "logic_reg,neon_logic")
3569    (set_attr "simd" "*,yes")]
3572 (define_insn "*one_cmpl_<optab><mode>2"
3573   [(set (match_operand:GPI 0 "register_operand" "=r")
3574         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3575                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3576   ""
3577   "mvn\\t%<w>0, %<w>1, <shift> %2"
3578   [(set_attr "type" "logic_shift_imm")]
3581 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3583 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3584   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3585         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3586                      (match_operand:GPI 2 "register_operand" "r,w")))]
3587   ""
3588   "@
3589   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3590   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3591   [(set_attr "type" "logic_reg,neon_logic")
3592    (set_attr "simd" "*,yes")]
3595 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3596   [(set (match_operand:DI 0 "register_operand" "=r")
3597         (zero_extend:DI
3598           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3599                        (match_operand:SI 2 "register_operand" "r"))))]
3600   ""
3601   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3602   [(set_attr "type" "logic_reg")]
3605 (define_insn "*xor_one_cmplsidi3_ze"
3606   [(set (match_operand:DI 0 "register_operand" "=r")
3607         (zero_extend:DI
3608           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3609                           (match_operand:SI 2 "register_operand" "r")))))]
3610   ""
3611   "eon\\t%w0, %w1, %w2"
3612   [(set_attr "type" "logic_reg")]
3615 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3616 ;; eon does not operate on SIMD registers so the vector variant must be split.
3617 (define_insn_and_split "*xor_one_cmpl<mode>3"
3618   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3619         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3620                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3621   ""
3622   "@
3623   eon\\t%<w>0, %<w>1, %<w>2
3624   #"
3625   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3626   [(set (match_operand:GPI 0 "register_operand" "=w")
3627         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3628                  (match_operand:GPI 2 "register_operand" "w")))
3629    (set (match_dup 0) (not:GPI (match_dup 0)))]
3630   ""
3631   [(set_attr "type" "logic_reg,multiple")
3632    (set_attr "simd" "*,yes")]
3635 (define_insn "*and_one_cmpl<mode>3_compare0"
3636   [(set (reg:CC_NZ CC_REGNUM)
3637         (compare:CC_NZ
3638          (and:GPI (not:GPI
3639                    (match_operand:GPI 1 "register_operand" "r"))
3640                   (match_operand:GPI 2 "register_operand" "r"))
3641          (const_int 0)))
3642    (set (match_operand:GPI 0 "register_operand" "=r")
3643         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3644   ""
3645   "bics\\t%<w>0, %<w>2, %<w>1"
3646   [(set_attr "type" "logics_reg")]
3649 ;; zero_extend version of above
3650 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3651   [(set (reg:CC_NZ CC_REGNUM)
3652         (compare:CC_NZ
3653          (and:SI (not:SI
3654                   (match_operand:SI 1 "register_operand" "r"))
3655                  (match_operand:SI 2 "register_operand" "r"))
3656          (const_int 0)))
3657    (set (match_operand:DI 0 "register_operand" "=r")
3658         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3659   ""
3660   "bics\\t%w0, %w2, %w1"
3661   [(set_attr "type" "logics_reg")]
3664 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3665   [(set (reg:CC_NZ CC_REGNUM)
3666     (compare:CC_NZ
3667      (and:GPI (not:GPI
3668            (match_operand:GPI 0 "register_operand" "r"))
3669           (match_operand:GPI 1 "register_operand" "r"))
3670      (const_int 0)))]
3671   ""
3672   "bics\\t<w>zr, %<w>1, %<w>0"
3673   [(set_attr "type" "logics_reg")]
3676 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3677   [(set (match_operand:GPI 0 "register_operand" "=r")
3678         (LOGICAL:GPI (not:GPI
3679                       (SHIFT:GPI
3680                        (match_operand:GPI 1 "register_operand" "r")
3681                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3682                      (match_operand:GPI 3 "register_operand" "r")))]
3683   ""
3684   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3685   [(set_attr "type" "logic_shift_imm")]
3688 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3689   [(set (match_operand:GPI 0 "register_operand" "=r")
3690         (not:GPI (xor:GPI
3691                       (SHIFT:GPI
3692                        (match_operand:GPI 1 "register_operand" "r")
3693                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3694                      (match_operand:GPI 3 "register_operand" "r"))))]
3695   ""
3696   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3697   [(set_attr "type" "logic_shift_imm")]
3700 ;; Zero-extend version of the above.
3701 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3702   [(set (match_operand:DI 0 "register_operand" "=r")
3703         (zero_extend:DI
3704           (not:SI (xor:SI
3705                     (SHIFT:SI
3706                       (match_operand:SI 1 "register_operand" "r")
3707                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3708                     (match_operand:SI 3 "register_operand" "r")))))]
3709   ""
3710   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3711   [(set_attr "type" "logic_shift_imm")]
3714 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3715   [(set (reg:CC_NZ CC_REGNUM)
3716         (compare:CC_NZ
3717          (and:GPI (not:GPI
3718                    (SHIFT:GPI
3719                     (match_operand:GPI 1 "register_operand" "r")
3720                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3721                   (match_operand:GPI 3 "register_operand" "r"))
3722          (const_int 0)))
3723    (set (match_operand:GPI 0 "register_operand" "=r")
3724         (and:GPI (not:GPI
3725                   (SHIFT:GPI
3726                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3727   ""
3728   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3729   [(set_attr "type" "logics_shift_imm")]
3732 ;; zero_extend version of above
3733 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3734   [(set (reg:CC_NZ CC_REGNUM)
3735         (compare:CC_NZ
3736          (and:SI (not:SI
3737                   (SHIFT:SI
3738                    (match_operand:SI 1 "register_operand" "r")
3739                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3740                  (match_operand:SI 3 "register_operand" "r"))
3741          (const_int 0)))
3742    (set (match_operand:DI 0 "register_operand" "=r")
3743         (zero_extend:DI (and:SI
3744                          (not:SI
3745                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3746   ""
3747   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3748   [(set_attr "type" "logics_shift_imm")]
3751 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3752   [(set (reg:CC_NZ CC_REGNUM)
3753     (compare:CC_NZ
3754      (and:GPI (not:GPI
3755            (SHIFT:GPI
3756             (match_operand:GPI 0 "register_operand" "r")
3757             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3758           (match_operand:GPI 2 "register_operand" "r"))
3759      (const_int 0)))]
3760   ""
3761   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3762   [(set_attr "type" "logics_shift_imm")]
3765 (define_insn "clz<mode>2"
3766   [(set (match_operand:GPI 0 "register_operand" "=r")
3767         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3768   ""
3769   "clz\\t%<w>0, %<w>1"
3770   [(set_attr "type" "clz")]
3773 (define_expand "ffs<mode>2"
3774   [(match_operand:GPI 0 "register_operand")
3775    (match_operand:GPI 1 "register_operand")]
3776   ""
3777   {
3778     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3779     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3781     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3782     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3783     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3784     DONE;
3785   }
3788 (define_insn "clrsb<mode>2"
3789   [(set (match_operand:GPI 0 "register_operand" "=r")
3790         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3791   ""
3792   "cls\\t%<w>0, %<w>1"
3793   [(set_attr "type" "clz")]
3796 (define_insn "rbit<mode>2"
3797   [(set (match_operand:GPI 0 "register_operand" "=r")
3798         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3799   ""
3800   "rbit\\t%<w>0, %<w>1"
3801   [(set_attr "type" "rbit")]
3804 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3805 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3806 ;; expression and split after reload to enable scheduling them apart if
3807 ;; needed.
3809 (define_insn_and_split "ctz<mode>2"
3810  [(set (match_operand:GPI           0 "register_operand" "=r")
3811        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3812   ""
3813   "#"
3814   "reload_completed"
3815   [(const_int 0)]
3816   "
3817   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3818   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3819   DONE;
3822 (define_insn "*and<mode>_compare0"
3823   [(set (reg:CC_NZ CC_REGNUM)
3824         (compare:CC_NZ
3825          (match_operand:SHORT 0 "register_operand" "r")
3826          (const_int 0)))]
3827   ""
3828   "tst\\t%<w>0, <short_mask>"
3829   [(set_attr "type" "alus_imm")]
3832 (define_insn "*ands<mode>_compare0"
3833   [(set (reg:CC_NZ CC_REGNUM)
3834         (compare:CC_NZ
3835          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3836          (const_int 0)))
3837    (set (match_operand:GPI 0 "register_operand" "=r")
3838         (zero_extend:GPI (match_dup 1)))]
3839   ""
3840   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3841   [(set_attr "type" "alus_imm")]
3844 (define_insn "*and<mode>3nr_compare0"
3845   [(set (reg:CC_NZ CC_REGNUM)
3846         (compare:CC_NZ
3847          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3848                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3849          (const_int 0)))]
3850   ""
3851   "@
3852    tst\\t%<w>0, %<w>1
3853    tst\\t%<w>0, %1"
3854   [(set_attr "type" "logics_reg,logics_imm")]
3857 (define_insn "*and<mode>3nr_compare0_zextract"
3858   [(set (reg:CC_NZ CC_REGNUM)
3859         (compare:CC_NZ
3860          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3861                   (match_operand:GPI 1 "const_int_operand" "n")
3862                   (match_operand:GPI 2 "const_int_operand" "n"))
3863          (const_int 0)))]
3864   "INTVAL (operands[1]) > 0
3865    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3866         <= GET_MODE_BITSIZE (<MODE>mode))
3867    && aarch64_bitmask_imm (
3868         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3869                                                  operands[2])),
3870         <MODE>mode)"
3871   {
3872     operands[1]
3873       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3874     return "tst\\t%<w>0, %1";
3875   }
3876   [(set_attr "type" "logics_shift_imm")]
3879 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3880   [(set (reg:CC_NZ CC_REGNUM)
3881         (compare:CC_NZ
3882          (and:GPI (SHIFT:GPI
3883                    (match_operand:GPI 0 "register_operand" "r")
3884                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3885                   (match_operand:GPI 2 "register_operand" "r"))
3886         (const_int 0)))]
3887   ""
3888   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3889   [(set_attr "type" "logics_shift_imm")]
3892 ;; -------------------------------------------------------------------
3893 ;; Shifts
3894 ;; -------------------------------------------------------------------
3896 (define_expand "<optab><mode>3"
3897   [(set (match_operand:GPI 0 "register_operand")
3898         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3899                     (match_operand:QI 2 "nonmemory_operand")))]
3900   ""
3901   {
3902     if (CONST_INT_P (operands[2]))
3903       {
3904         operands[2] = GEN_INT (INTVAL (operands[2])
3905                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3907         if (operands[2] == const0_rtx)
3908           {
3909             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3910             DONE;
3911           }
3912       }
3913   }
3916 (define_expand "ashl<mode>3"
3917   [(set (match_operand:SHORT 0 "register_operand")
3918         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3919                       (match_operand:QI 2 "const_int_operand")))]
3920   ""
3921   {
3922     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3924     if (operands[2] == const0_rtx)
3925       {
3926         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3927         DONE;
3928       }
3929   }
3932 (define_expand "rotr<mode>3"
3933   [(set (match_operand:GPI 0 "register_operand")
3934         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3935                       (match_operand:QI 2 "nonmemory_operand")))]
3936   ""
3937   {
3938     if (CONST_INT_P (operands[2]))
3939       {
3940         operands[2] = GEN_INT (INTVAL (operands[2])
3941                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3943         if (operands[2] == const0_rtx)
3944           {
3945             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3946             DONE;
3947           }
3948       }
3949   }
3952 (define_expand "rotl<mode>3"
3953   [(set (match_operand:GPI 0 "register_operand")
3954         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3955                       (match_operand:QI 2 "nonmemory_operand")))]
3956   ""
3957   {
3958     /* (SZ - cnt) % SZ == -cnt % SZ */
3959     if (CONST_INT_P (operands[2]))
3960       {
3961         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3962                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3963         if (operands[2] == const0_rtx)
3964           {
3965             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3966             DONE;
3967           }
3968       }
3969     else
3970       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3971                                         NULL_RTX, 1);
3972   }
3975 ;; Logical left shift using SISD or Integer instruction
3976 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3977   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3978         (ashift:GPI
3979           (match_operand:GPI 1 "register_operand" "r,r,w,w")
3980           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3981   ""
3982   "@
3983    lsl\t%<w>0, %<w>1, %2
3984    lsl\t%<w>0, %<w>1, %<w>2
3985    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3986    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3987   [(set_attr "simd" "no,no,yes,yes")
3988    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3991 ;; Logical right shift using SISD or Integer instruction
3992 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3993   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3994         (lshiftrt:GPI
3995          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3996          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3997   ""
3998   "@
3999    lsr\t%<w>0, %<w>1, %2
4000    lsr\t%<w>0, %<w>1, %<w>2
4001    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4002    #
4003    #"
4004   [(set_attr "simd" "no,no,yes,yes,yes")
4005    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4008 (define_split
4009   [(set (match_operand:DI 0 "aarch64_simd_register")
4010         (lshiftrt:DI
4011            (match_operand:DI 1 "aarch64_simd_register")
4012            (match_operand:QI 2 "aarch64_simd_register")))]
4013   "TARGET_SIMD && reload_completed"
4014   [(set (match_dup 3)
4015         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4016    (set (match_dup 0)
4017         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4018   {
4019     operands[3] = gen_lowpart (QImode, operands[0]);
4020   }
4023 (define_split
4024   [(set (match_operand:SI 0 "aarch64_simd_register")
4025         (lshiftrt:SI
4026            (match_operand:SI 1 "aarch64_simd_register")
4027            (match_operand:QI 2 "aarch64_simd_register")))]
4028   "TARGET_SIMD && reload_completed"
4029   [(set (match_dup 3)
4030         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4031    (set (match_dup 0)
4032         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4033   {
4034     operands[3] = gen_lowpart (QImode, operands[0]);
4035   }
4038 ;; Arithmetic right shift using SISD or Integer instruction
4039 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4040   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4041         (ashiftrt:GPI
4042           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4043           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4044   ""
4045   "@
4046    asr\t%<w>0, %<w>1, %2
4047    asr\t%<w>0, %<w>1, %<w>2
4048    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4049    #
4050    #"
4051   [(set_attr "simd" "no,no,yes,yes,yes")
4052    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4055 (define_split
4056   [(set (match_operand:DI 0 "aarch64_simd_register")
4057         (ashiftrt:DI
4058            (match_operand:DI 1 "aarch64_simd_register")
4059            (match_operand:QI 2 "aarch64_simd_register")))]
4060   "TARGET_SIMD && reload_completed"
4061   [(set (match_dup 3)
4062         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4063    (set (match_dup 0)
4064         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4066   operands[3] = gen_lowpart (QImode, operands[0]);
4070 (define_split
4071   [(set (match_operand:SI 0 "aarch64_simd_register")
4072         (ashiftrt:SI
4073            (match_operand:SI 1 "aarch64_simd_register")
4074            (match_operand:QI 2 "aarch64_simd_register")))]
4075   "TARGET_SIMD && reload_completed"
4076   [(set (match_dup 3)
4077         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4078    (set (match_dup 0)
4079         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4081   operands[3] = gen_lowpart (QImode, operands[0]);
4085 (define_insn "*aarch64_sisd_ushl"
4086   [(set (match_operand:DI 0 "register_operand" "=w")
4087         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4088                     (match_operand:QI 2 "register_operand" "w")]
4089                    UNSPEC_SISD_USHL))]
4090   "TARGET_SIMD"
4091   "ushl\t%d0, %d1, %d2"
4092   [(set_attr "simd" "yes")
4093    (set_attr "type" "neon_shift_reg")]
4096 (define_insn "*aarch64_ushl_2s"
4097   [(set (match_operand:SI 0 "register_operand" "=w")
4098         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4099                     (match_operand:QI 2 "register_operand" "w")]
4100                    UNSPEC_USHL_2S))]
4101   "TARGET_SIMD"
4102   "ushl\t%0.2s, %1.2s, %2.2s"
4103   [(set_attr "simd" "yes")
4104    (set_attr "type" "neon_shift_reg")]
4107 (define_insn "*aarch64_sisd_sshl"
4108   [(set (match_operand:DI 0 "register_operand" "=w")
4109         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4110                     (match_operand:QI 2 "register_operand" "w")]
4111                    UNSPEC_SISD_SSHL))]
4112   "TARGET_SIMD"
4113   "sshl\t%d0, %d1, %d2"
4114   [(set_attr "simd" "yes")
4115    (set_attr "type" "neon_shift_reg")]
4118 (define_insn "*aarch64_sshl_2s"
4119   [(set (match_operand:SI 0 "register_operand" "=w")
4120         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4121                     (match_operand:QI 2 "register_operand" "w")]
4122                    UNSPEC_SSHL_2S))]
4123   "TARGET_SIMD"
4124   "sshl\t%0.2s, %1.2s, %2.2s"
4125   [(set_attr "simd" "yes")
4126    (set_attr "type" "neon_shift_reg")]
4129 (define_insn "*aarch64_sisd_neg_qi"
4130   [(set (match_operand:QI 0 "register_operand" "=w")
4131         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4132                    UNSPEC_SISD_NEG))]
4133   "TARGET_SIMD"
4134   "neg\t%d0, %d1"
4135   [(set_attr "simd" "yes")
4136    (set_attr "type" "neon_neg")]
4139 ;; Rotate right
4140 (define_insn "*ror<mode>3_insn"
4141   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4142      (rotatert:GPI
4143        (match_operand:GPI 1 "register_operand" "r,r")
4144        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4145   ""
4146   "@
4147    ror\\t%<w>0, %<w>1, %2
4148    ror\\t%<w>0, %<w>1, %<w>2"
4149   [(set_attr "type" "rotate_imm,shift_reg")]
4152 ;; zero_extend version of above
4153 (define_insn "*<optab>si3_insn_uxtw"
4154   [(set (match_operand:DI 0 "register_operand" "=r,r")
4155         (zero_extend:DI (SHIFT:SI
4156          (match_operand:SI 1 "register_operand" "r,r")
4157          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4158   ""
4159   "@
4160    <shift>\\t%w0, %w1, %2
4161    <shift>\\t%w0, %w1, %w2"
4162   [(set_attr "type" "bfx,shift_reg")]
4165 (define_insn "*<optab><mode>3_insn"
4166   [(set (match_operand:SHORT 0 "register_operand" "=r")
4167         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4168                       (match_operand 2 "const_int_operand" "n")))]
4169   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4171   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4172   return "<bfshift>\t%w0, %w1, %2, %3";
4174   [(set_attr "type" "bfx")]
4177 (define_insn "*extr<mode>5_insn"
4178   [(set (match_operand:GPI 0 "register_operand" "=r")
4179         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4180                              (match_operand 3 "const_int_operand" "n"))
4181                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4182                                (match_operand 4 "const_int_operand" "n"))))]
4183   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4184    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4185   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4186   [(set_attr "type" "rotate_imm")]
4189 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4190 ;; so we have to match both orderings.
4191 (define_insn "*extr<mode>5_insn_alt"
4192   [(set (match_operand:GPI 0 "register_operand" "=r")
4193         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4194                                 (match_operand 4 "const_int_operand" "n"))
4195                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4196                               (match_operand 3 "const_int_operand" "n"))))]
4197   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4198    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4199        == GET_MODE_BITSIZE (<MODE>mode))"
4200   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4201   [(set_attr "type" "rotate_imm")]
4204 ;; zero_extend version of the above
4205 (define_insn "*extrsi5_insn_uxtw"
4206   [(set (match_operand:DI 0 "register_operand" "=r")
4207         (zero_extend:DI
4208          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4209                             (match_operand 3 "const_int_operand" "n"))
4210                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4211                               (match_operand 4 "const_int_operand" "n")))))]
4212   "UINTVAL (operands[3]) < 32 &&
4213    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4214   "extr\\t%w0, %w1, %w2, %4"
4215   [(set_attr "type" "rotate_imm")]
4218 (define_insn "*extrsi5_insn_uxtw_alt"
4219   [(set (match_operand:DI 0 "register_operand" "=r")
4220         (zero_extend:DI
4221          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4222                                (match_operand 4 "const_int_operand" "n"))
4223                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4224                             (match_operand 3 "const_int_operand" "n")))))]
4225   "UINTVAL (operands[3]) < 32 &&
4226    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4227   "extr\\t%w0, %w1, %w2, %4"
4228   [(set_attr "type" "rotate_imm")]
4231 (define_insn "*ror<mode>3_insn"
4232   [(set (match_operand:GPI 0 "register_operand" "=r")
4233         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4234                     (match_operand 2 "const_int_operand" "n")))]
4235   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4237   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4238   return "ror\\t%<w>0, %<w>1, %3";
4240   [(set_attr "type" "rotate_imm")]
4243 ;; zero_extend version of the above
4244 (define_insn "*rorsi3_insn_uxtw"
4245   [(set (match_operand:DI 0 "register_operand" "=r")
4246         (zero_extend:DI
4247          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4248                     (match_operand 2 "const_int_operand" "n"))))]
4249   "UINTVAL (operands[2]) < 32"
4251   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4252   return "ror\\t%w0, %w1, %3";
4254   [(set_attr "type" "rotate_imm")]
4257 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4258   [(set (match_operand:GPI 0 "register_operand" "=r")
4259         (ANY_EXTEND:GPI
4260          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4261                        (match_operand 2 "const_int_operand" "n"))))]
4262   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4264   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4265   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4267   [(set_attr "type" "bfx")]
4270 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4271   [(set (match_operand:GPI 0 "register_operand" "=r")
4272         (zero_extend:GPI
4273          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4274                          (match_operand 2 "const_int_operand" "n"))))]
4275   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4277   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4278   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4280   [(set_attr "type" "bfx")]
4283 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4284   [(set (match_operand:GPI 0 "register_operand" "=r")
4285         (sign_extend:GPI
4286          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4287                          (match_operand 2 "const_int_operand" "n"))))]
4288   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4290   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4291   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4293   [(set_attr "type" "bfx")]
4296 ;; -------------------------------------------------------------------
4297 ;; Bitfields
4298 ;; -------------------------------------------------------------------
4300 (define_expand "<optab>"
4301   [(set (match_operand:DI 0 "register_operand" "=r")
4302         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4303                         (match_operand 2
4304                           "aarch64_simd_shift_imm_offset_di")
4305                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4306   ""
4307   {
4308     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4309                    1, GET_MODE_BITSIZE (DImode) - 1))
4310      FAIL;
4311   }
4315 (define_insn "*<optab><mode>"
4316   [(set (match_operand:GPI 0 "register_operand" "=r")
4317         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4318                          (match_operand 2
4319                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4320                          (match_operand 3
4321                            "aarch64_simd_shift_imm_<mode>" "n")))]
4322   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4323              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4324   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4325   [(set_attr "type" "bfx")]
4328 ;; Bitfield Insert (insv)
4329 (define_expand "insv<mode>"
4330   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4331                           (match_operand 1 "const_int_operand")
4332                           (match_operand 2 "const_int_operand"))
4333         (match_operand:GPI 3 "general_operand"))]
4334   ""
4336   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4337   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4338   rtx value = operands[3];
4340   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4341     FAIL;
4343   if (CONST_INT_P (value))
4344     {
4345       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4347       /* Prefer AND/OR for inserting all zeros or all ones.  */
4348       if ((UINTVAL (value) & mask) == 0
4349            || (UINTVAL (value) & mask) == mask)
4350         FAIL;
4352       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4353       if (width == 16 && (pos % 16) == 0)
4354         DONE;
4355     }
4356   operands[3] = force_reg (<MODE>mode, value);
4359 (define_insn "*insv_reg<mode>"
4360   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4361                           (match_operand 1 "const_int_operand" "n")
4362                           (match_operand 2 "const_int_operand" "n"))
4363         (match_operand:GPI 3 "register_operand" "r"))]
4364   "!(UINTVAL (operands[1]) == 0
4365      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4366          > GET_MODE_BITSIZE (<MODE>mode)))"
4367   "bfi\\t%<w>0, %<w>3, %2, %1"
4368   [(set_attr "type" "bfm")]
4371 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4372   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4373                           (match_operand 1 "const_int_operand" "n")
4374                           (match_operand 2 "const_int_operand" "n"))
4375         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4376   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4377   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4378   [(set_attr "type" "bfm")]
4381 (define_insn "*extr_insv_lower_reg<mode>"
4382   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4383                           (match_operand 1 "const_int_operand" "n")
4384                           (const_int 0))
4385         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4386                           (match_dup 1)
4387                           (match_operand 3 "const_int_operand" "n")))]
4388   "!(UINTVAL (operands[1]) == 0
4389      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4390          > GET_MODE_BITSIZE (<MODE>mode)))"
4391   "bfxil\\t%<w>0, %<w>2, %3, %1"
4392   [(set_attr "type" "bfm")]
4395 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4396   [(set (match_operand:GPI 0 "register_operand" "=r")
4397         (ashift:GPI (ANY_EXTEND:GPI
4398                      (match_operand:ALLX 1 "register_operand" "r"))
4399                     (match_operand 2 "const_int_operand" "n")))]
4400   "UINTVAL (operands[2]) < <GPI:sizen>"
4402   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4403               ? GEN_INT (<ALLX:sizen>)
4404               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4405   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4407   [(set_attr "type" "bfx")]
4410 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4412 (define_insn "*andim_ashift<mode>_bfiz"
4413   [(set (match_operand:GPI 0 "register_operand" "=r")
4414         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4415                              (match_operand 2 "const_int_operand" "n"))
4416                  (match_operand 3 "const_int_operand" "n")))]
4417   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4418   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4419   [(set_attr "type" "bfx")]
4422 (define_insn "bswap<mode>2"
4423   [(set (match_operand:GPI 0 "register_operand" "=r")
4424         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4425   ""
4426   "rev\\t%<w>0, %<w>1"
4427   [(set_attr "type" "rev")]
4430 (define_insn "bswaphi2"
4431   [(set (match_operand:HI 0 "register_operand" "=r")
4432         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4433   ""
4434   "rev16\\t%w0, %w1"
4435   [(set_attr "type" "rev")]
4438 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4439 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4440 ;; each valid permutation.
4442 (define_insn "rev16<mode>2"
4443   [(set (match_operand:GPI 0 "register_operand" "=r")
4444         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4445                                       (const_int 8))
4446                           (match_operand:GPI 3 "const_int_operand" "n"))
4447                  (and:GPI (lshiftrt:GPI (match_dup 1)
4448                                         (const_int 8))
4449                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4450   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4451    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4452   "rev16\\t%<w>0, %<w>1"
4453   [(set_attr "type" "rev")]
4456 (define_insn "rev16<mode>2_alt"
4457   [(set (match_operand:GPI 0 "register_operand" "=r")
4458         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4459                                         (const_int 8))
4460                           (match_operand:GPI 2 "const_int_operand" "n"))
4461                  (and:GPI (ashift:GPI (match_dup 1)
4462                                       (const_int 8))
4463                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4464   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4465    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4466   "rev16\\t%<w>0, %<w>1"
4467   [(set_attr "type" "rev")]
4470 ;; zero_extend version of above
4471 (define_insn "*bswapsi2_uxtw"
4472   [(set (match_operand:DI 0 "register_operand" "=r")
4473         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4474   ""
4475   "rev\\t%w0, %w1"
4476   [(set_attr "type" "rev")]
4479 ;; -------------------------------------------------------------------
4480 ;; Floating-point intrinsics
4481 ;; -------------------------------------------------------------------
4483 ;; frint floating-point round to integral standard patterns.
4484 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4486 (define_insn "<frint_pattern><mode>2"
4487   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4488         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4489          FRINT))]
4490   "TARGET_FLOAT"
4491   "frint<frint_suffix>\\t%<s>0, %<s>1"
4492   [(set_attr "type" "f_rint<stype>")]
4495 ;; frcvt floating-point round to integer and convert standard patterns.
4496 ;; Expands to lbtrunc, lceil, lfloor, lround.
4497 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4498   [(set (match_operand:GPI 0 "register_operand" "=r")
4499         (FIXUORS:GPI
4500           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4501            FCVT)))]
4502   "TARGET_FLOAT"
4503   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4504   [(set_attr "type" "f_cvtf2i")]
4507 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4508   [(set (match_operand:GPI 0 "register_operand" "=r")
4509         (FIXUORS:GPI
4510           (mult:GPF
4511             (match_operand:GPF 1 "register_operand" "w")
4512             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4513   "TARGET_FLOAT
4514    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4515                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4516   {
4517     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4518     char buf[64];
4519     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4520     output_asm_insn (buf, operands);
4521     return "";
4522   }
4523   [(set_attr "type" "f_cvtf2i")]
4526 ;; fma - no throw
4528 (define_insn "fma<mode>4"
4529   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4530         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4531                      (match_operand:GPF_F16 2 "register_operand" "w")
4532                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4533   "TARGET_FLOAT"
4534   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4535   [(set_attr "type" "fmac<stype>")]
4538 (define_insn "fnma<mode>4"
4539   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4540         (fma:GPF_F16
4541           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4542           (match_operand:GPF_F16 2 "register_operand" "w")
4543           (match_operand:GPF_F16 3 "register_operand" "w")))]
4544   "TARGET_FLOAT"
4545   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4546   [(set_attr "type" "fmac<stype>")]
4549 (define_insn "fms<mode>4"
4550   [(set (match_operand:GPF 0 "register_operand" "=w")
4551         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4552                  (match_operand:GPF 2 "register_operand" "w")
4553                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4554   "TARGET_FLOAT"
4555   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4556   [(set_attr "type" "fmac<s>")]
4559 (define_insn "fnms<mode>4"
4560   [(set (match_operand:GPF 0 "register_operand" "=w")
4561         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4562                  (match_operand:GPF 2 "register_operand" "w")
4563                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4564   "TARGET_FLOAT"
4565   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4566   [(set_attr "type" "fmac<s>")]
4569 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4570 (define_insn "*fnmadd<mode>4"
4571   [(set (match_operand:GPF 0 "register_operand" "=w")
4572         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4573                           (match_operand:GPF 2 "register_operand" "w")
4574                           (match_operand:GPF 3 "register_operand" "w"))))]
4575   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4576   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4577   [(set_attr "type" "fmac<s>")]
4580 ;; -------------------------------------------------------------------
4581 ;; Floating-point conversions
4582 ;; -------------------------------------------------------------------
4584 (define_insn "extendsfdf2"
4585   [(set (match_operand:DF 0 "register_operand" "=w")
4586         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4587   "TARGET_FLOAT"
4588   "fcvt\\t%d0, %s1"
4589   [(set_attr "type" "f_cvt")]
4592 (define_insn "extendhfsf2"
4593   [(set (match_operand:SF 0 "register_operand" "=w")
4594         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4595   "TARGET_FLOAT"
4596   "fcvt\\t%s0, %h1"
4597   [(set_attr "type" "f_cvt")]
4600 (define_insn "extendhfdf2"
4601   [(set (match_operand:DF 0 "register_operand" "=w")
4602         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4603   "TARGET_FLOAT"
4604   "fcvt\\t%d0, %h1"
4605   [(set_attr "type" "f_cvt")]
4608 (define_insn "truncdfsf2"
4609   [(set (match_operand:SF 0 "register_operand" "=w")
4610         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4611   "TARGET_FLOAT"
4612   "fcvt\\t%s0, %d1"
4613   [(set_attr "type" "f_cvt")]
4616 (define_insn "truncsfhf2"
4617   [(set (match_operand:HF 0 "register_operand" "=w")
4618         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4619   "TARGET_FLOAT"
4620   "fcvt\\t%h0, %s1"
4621   [(set_attr "type" "f_cvt")]
4624 (define_insn "truncdfhf2"
4625   [(set (match_operand:HF 0 "register_operand" "=w")
4626         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4627   "TARGET_FLOAT"
4628   "fcvt\\t%h0, %d1"
4629   [(set_attr "type" "f_cvt")]
4632 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4633   [(set (match_operand:GPI 0 "register_operand" "=r")
4634         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4635   "TARGET_FLOAT"
4636   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4637   [(set_attr "type" "f_cvtf2i")]
4640 (define_insn "<optab><fcvt_target><GPF:mode>2"
4641   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4642         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4643   "TARGET_FLOAT"
4644   "@
4645    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4646    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4647   [(set_attr "simd" "yes,no")
4648    (set_attr "fp" "no,yes")
4649    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4652 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4653   [(set (match_operand:GPF 0 "register_operand" "=w")
4654         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4655   "TARGET_FLOAT"
4656   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4657   [(set_attr "type" "f_cvti2f")]
4660 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4661 ;; midend will arrange for an SImode conversion to HFmode to first go
4662 ;; through DFmode, then to HFmode.  But first it will try converting
4663 ;; to DImode then down, which would match our DImode pattern below and
4664 ;; give very poor code-generation.  So, we must provide our own emulation
4665 ;; of the mid-end logic.
4667 (define_insn "aarch64_fp16_<optab><mode>hf2"
4668   [(set (match_operand:HF 0 "register_operand" "=w")
4669         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4670   "TARGET_FP_F16INST"
4671   "<su_optab>cvtf\t%h0, %<w>1"
4672   [(set_attr "type" "f_cvti2f")]
4675 (define_expand "<optab>sihf2"
4676   [(set (match_operand:HF 0 "register_operand")
4677         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4678   "TARGET_FLOAT"
4680   if (TARGET_FP_F16INST)
4681     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4682   else
4683     {
4684       rtx convert_target = gen_reg_rtx (DFmode);
4685       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4686       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4687     }
4688   DONE;
4692 ;; For DImode there is no wide enough floating-point mode that we
4693 ;; can convert through natively (TFmode would work, but requires a library
4694 ;; call).  However, we know that any value >= 65504 will be rounded
4695 ;; to infinity on conversion.  This is well within the range of SImode, so
4696 ;; we can:
4697 ;;   Saturate to SImode.
4698 ;;   Convert from that to DFmode
4699 ;;   Convert from that to HFmode (phew!).
4700 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4701 ;; we ever need to provide this pattern where the SIMD extensions are not
4702 ;; available, we would need a different approach.
4704 (define_expand "<optab>dihf2"
4705   [(set (match_operand:HF 0 "register_operand")
4706         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4707   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4709   if (TARGET_FP_F16INST)
4710     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4711   else
4712     {
4713       rtx sat_target = gen_reg_rtx (SImode);
4714       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4715       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4716     }
4718   DONE;
4722 ;; Convert between fixed-point and floating-point (scalar modes)
4724 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4725   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4726         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4727                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4728          FCVT_F2FIXED))]
4729   ""
4730   "@
4731    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4732    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4733   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4734    (set_attr "fp" "yes, *")
4735    (set_attr "simd" "*, yes")]
4738 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4739   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4740         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4741                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4742          FCVT_FIXED2F))]
4743   ""
4744   "@
4745    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4746    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4747   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4748    (set_attr "fp" "yes, *")
4749    (set_attr "simd" "*, yes")]
4752 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4753   [(set (match_operand:GPI 0 "register_operand" "=r")
4754         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4755                      (match_operand:SI 2 "immediate_operand" "i")]
4756          FCVT_F2FIXED))]
4757   "TARGET_FP_F16INST"
4758    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4759   [(set_attr "type" "f_cvtf2i")]
4762 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4763   [(set (match_operand:HF 0 "register_operand" "=w")
4764         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4765                     (match_operand:SI 2 "immediate_operand" "i")]
4766          FCVT_FIXED2F))]
4767   "TARGET_FP_F16INST"
4768   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4769   [(set_attr "type" "f_cvti2f")]
4772 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4773   [(set (match_operand:HI 0 "register_operand" "=w")
4774         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4775                     (match_operand:SI 2 "immediate_operand" "i")]
4776          FCVT_F2FIXED))]
4777   "TARGET_SIMD"
4778   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4779   [(set_attr "type" "neon_fp_to_int_s")]
4782 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4783   [(set (match_operand:HF 0 "register_operand" "=w")
4784         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4785                     (match_operand:SI 2 "immediate_operand" "i")]
4786          FCVT_FIXED2F))]
4787   "TARGET_SIMD"
4788   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4789   [(set_attr "type" "neon_int_to_fp_s")]
4792 ;; -------------------------------------------------------------------
4793 ;; Floating-point arithmetic
4794 ;; -------------------------------------------------------------------
4796 (define_insn "add<mode>3"
4797   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4798         (plus:GPF_F16
4799          (match_operand:GPF_F16 1 "register_operand" "w")
4800          (match_operand:GPF_F16 2 "register_operand" "w")))]
4801   "TARGET_FLOAT"
4802   "fadd\\t%<s>0, %<s>1, %<s>2"
4803   [(set_attr "type" "fadd<stype>")]
4806 (define_insn "sub<mode>3"
4807   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4808         (minus:GPF_F16
4809          (match_operand:GPF_F16 1 "register_operand" "w")
4810          (match_operand:GPF_F16 2 "register_operand" "w")))]
4811   "TARGET_FLOAT"
4812   "fsub\\t%<s>0, %<s>1, %<s>2"
4813   [(set_attr "type" "fadd<stype>")]
4816 (define_insn "mul<mode>3"
4817   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4818         (mult:GPF_F16
4819          (match_operand:GPF_F16 1 "register_operand" "w")
4820          (match_operand:GPF_F16 2 "register_operand" "w")))]
4821   "TARGET_FLOAT"
4822   "fmul\\t%<s>0, %<s>1, %<s>2"
4823   [(set_attr "type" "fmul<stype>")]
4826 (define_insn "*fnmul<mode>3"
4827   [(set (match_operand:GPF 0 "register_operand" "=w")
4828         (mult:GPF
4829                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4830                  (match_operand:GPF 2 "register_operand" "w")))]
4831   "TARGET_FLOAT && !flag_rounding_math"
4832   "fnmul\\t%<s>0, %<s>1, %<s>2"
4833   [(set_attr "type" "fmul<s>")]
4836 (define_insn "*fnmul<mode>3"
4837   [(set (match_operand:GPF 0 "register_operand" "=w")
4838         (neg:GPF (mult:GPF
4839                  (match_operand:GPF 1 "register_operand" "w")
4840                  (match_operand:GPF 2 "register_operand" "w"))))]
4841   "TARGET_FLOAT"
4842   "fnmul\\t%<s>0, %<s>1, %<s>2"
4843   [(set_attr "type" "fmul<s>")]
4846 (define_expand "div<mode>3"
4847  [(set (match_operand:GPF_F16 0 "register_operand")
4848        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4849                     (match_operand:GPF_F16 2 "register_operand")))]
4850  "TARGET_SIMD"
4852   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4853     DONE;
4855   operands[1] = force_reg (<MODE>mode, operands[1]);
4858 (define_insn "*div<mode>3"
4859   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4860         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4861                      (match_operand:GPF_F16 2 "register_operand" "w")))]
4862   "TARGET_FLOAT"
4863   "fdiv\\t%<s>0, %<s>1, %<s>2"
4864   [(set_attr "type" "fdiv<stype>")]
4867 (define_insn "neg<mode>2"
4868   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4869         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4870   "TARGET_FLOAT"
4871   "fneg\\t%<s>0, %<s>1"
4872   [(set_attr "type" "ffarith<stype>")]
4875 (define_expand "sqrt<mode>2"
4876   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4878   "TARGET_FLOAT"
4880   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4881     DONE;
4884 (define_insn "*sqrt<mode>2"
4885   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4886         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4887   "TARGET_FLOAT"
4888   "fsqrt\\t%<s>0, %<s>1"
4889   [(set_attr "type" "fsqrt<stype>")]
4892 (define_insn "abs<mode>2"
4893   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4894         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4895   "TARGET_FLOAT"
4896   "fabs\\t%<s>0, %<s>1"
4897   [(set_attr "type" "ffarith<stype>")]
4900 ;; Given that smax/smin do not specify the result when either input is NaN,
4901 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4902 ;; for smin.
4904 (define_insn "smax<mode>3"
4905   [(set (match_operand:GPF 0 "register_operand" "=w")
4906         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4907                   (match_operand:GPF 2 "register_operand" "w")))]
4908   "TARGET_FLOAT"
4909   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4910   [(set_attr "type" "f_minmax<s>")]
4913 (define_insn "smin<mode>3"
4914   [(set (match_operand:GPF 0 "register_operand" "=w")
4915         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4916                   (match_operand:GPF 2 "register_operand" "w")))]
4917   "TARGET_FLOAT"
4918   "fminnm\\t%<s>0, %<s>1, %<s>2"
4919   [(set_attr "type" "f_minmax<s>")]
4922 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4923 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4924 ;; which implement the IEEE fmax ()/fmin () functions.
4925 (define_insn "<maxmin_uns><mode>3"
4926   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4927         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4928                      (match_operand:GPF_F16 2 "register_operand" "w")]
4929                      FMAXMIN_UNS))]
4930   "TARGET_FLOAT"
4931   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4932   [(set_attr "type" "f_minmax<stype>")]
4935 ;; For copysign (x, y), we want to generate:
4937 ;;   LDR d2, #(1 << 63)
4938 ;;   BSL v2.8b, [y], [x]
4940 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4941 ;; aarch64_simd_bsldf will select the best suited of these instructions
4942 ;; to generate based on register allocation, and knows how to partially
4943 ;; constant fold based on the values of X and Y, so expand through that.
4945 (define_expand "copysigndf3"
4946   [(match_operand:DF 0 "register_operand")
4947    (match_operand:DF 1 "register_operand")
4948    (match_operand:DF 2 "register_operand")]
4949   "TARGET_FLOAT && TARGET_SIMD"
4951   rtx mask = gen_reg_rtx (DImode);
4952   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4953   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4954                                      operands[2], operands[1]));
4955   DONE;
4959 ;; As above, but we must first get to a 64-bit value if we wish to use
4960 ;; aarch64_simd_bslv2sf.
4962 (define_expand "copysignsf3"
4963   [(match_operand:SF 0 "register_operand")
4964    (match_operand:SF 1 "register_operand")
4965    (match_operand:SF 2 "register_operand")]
4966   "TARGET_FLOAT && TARGET_SIMD"
4968   rtx mask = gen_reg_rtx (DImode);
4970   /* Juggle modes to get us in to a vector mode for BSL.  */
4971   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4972   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4973   rtx tmp = gen_reg_rtx (V2SFmode);
4974   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4975   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4976   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4977   DONE;
4981 ;; -------------------------------------------------------------------
4982 ;; Reload support
4983 ;; -------------------------------------------------------------------
4984 ;; Reload Scalar Floating point modes from constant pool.
4985 ;; The AArch64 port doesn't have __int128 constant move support.
4986 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4987  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4988        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4989   (clobber (match_operand:P 2 "register_operand" "=&r"))]
4990  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4992    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4993    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4994    DONE;
4998 ;; Reload Vector modes from constant pool.
4999 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5000  [(set (match_operand:VALL 0 "register_operand" "=w")
5001        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5002   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5003  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
5005    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5006    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5007    DONE;
5011 (define_expand "aarch64_reload_mov<mode>"
5012   [(set (match_operand:TX 0 "register_operand" "=w")
5013         (match_operand:TX 1 "register_operand" "w"))
5014    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5015   ]
5016   "TARGET_FLOAT"
5017   {
5018     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5019     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5020     gen_aarch64_movtilow_tilow (op0, op1);
5021     gen_aarch64_movdi_tihigh (operands[2], op1);
5022     gen_aarch64_movtihigh_di (op0, operands[2]);
5023     DONE;
5024   }
5027 ;; The following secondary reload helpers patterns are invoked
5028 ;; after or during reload as we don't want these patterns to start
5029 ;; kicking in during the combiner.
5031 (define_insn "aarch64_movdi_<mode>low"
5032   [(set (match_operand:DI 0 "register_operand" "=r")
5033         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5034                          (const_int 64) (const_int 0)))]
5035   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5036   "fmov\\t%x0, %d1"
5037   [(set_attr "type" "f_mrc")
5038    (set_attr "length" "4")
5039   ])
5041 (define_insn "aarch64_movdi_<mode>high"
5042   [(set (match_operand:DI 0 "register_operand" "=r")
5043         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5044                          (const_int 64) (const_int 64)))]
5045   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5046   "fmov\\t%x0, %1.d[1]"
5047   [(set_attr "type" "f_mrc")
5048    (set_attr "length" "4")
5049   ])
5051 (define_insn "aarch64_mov<mode>high_di"
5052   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5053                          (const_int 64) (const_int 64))
5054         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5055   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5056   "fmov\\t%0.d[1], %x1"
5057   [(set_attr "type" "f_mcr")
5058    (set_attr "length" "4")
5059   ])
5061 (define_insn "aarch64_mov<mode>low_di"
5062   [(set (match_operand:TX 0 "register_operand" "=w")
5063         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5064   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5065   "fmov\\t%d0, %x1"
5066   [(set_attr "type" "f_mcr")
5067    (set_attr "length" "4")
5068   ])
5070 (define_insn "aarch64_movtilow_tilow"
5071   [(set (match_operand:TI 0 "register_operand" "=w")
5072         (zero_extend:TI
5073           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5074   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5075   "fmov\\t%d0, %d1"
5076   [(set_attr "type" "fmov")
5077    (set_attr "length" "4")
5078   ])
5080 ;; There is a deliberate reason why the parameters of high and lo_sum's
5081 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5082 ;; and lo_sum's to be used with the labels defining the jump tables in
5083 ;; rodata section.
5085 (define_expand "add_losym"
5086   [(set (match_operand 0 "register_operand" "=r")
5087         (lo_sum (match_operand 1 "register_operand" "r")
5088                 (match_operand 2 "aarch64_valid_symref" "S")))]
5089   ""
5091   machine_mode mode = GET_MODE (operands[0]);
5093   emit_insn ((mode == DImode
5094               ? gen_add_losym_di
5095               : gen_add_losym_si) (operands[0],
5096                                    operands[1],
5097                                    operands[2]));
5098   DONE;
5101 (define_insn "add_losym_<mode>"
5102   [(set (match_operand:P 0 "register_operand" "=r")
5103         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5104                   (match_operand 2 "aarch64_valid_symref" "S")))]
5105   ""
5106   "add\\t%<w>0, %<w>1, :lo12:%a2"
5107   [(set_attr "type" "alu_imm")]
5110 (define_insn "ldr_got_small_<mode>"
5111   [(set (match_operand:PTR 0 "register_operand" "=r")
5112         (unspec:PTR [(mem:PTR (lo_sum:PTR
5113                               (match_operand:PTR 1 "register_operand" "r")
5114                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5115                     UNSPEC_GOTSMALLPIC))]
5116   ""
5117   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5118   [(set_attr "type" "load1")]
5121 (define_insn "ldr_got_small_sidi"
5122   [(set (match_operand:DI 0 "register_operand" "=r")
5123         (zero_extend:DI
5124          (unspec:SI [(mem:SI (lo_sum:DI
5125                              (match_operand:DI 1 "register_operand" "r")
5126                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5127                     UNSPEC_GOTSMALLPIC)))]
5128   "TARGET_ILP32"
5129   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5130   [(set_attr "type" "load1")]
5133 (define_insn "ldr_got_small_28k_<mode>"
5134   [(set (match_operand:PTR 0 "register_operand" "=r")
5135         (unspec:PTR [(mem:PTR (lo_sum:PTR
5136                               (match_operand:PTR 1 "register_operand" "r")
5137                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5138                     UNSPEC_GOTSMALLPIC28K))]
5139   ""
5140   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5141   [(set_attr "type" "load1")]
5144 (define_insn "ldr_got_small_28k_sidi"
5145   [(set (match_operand:DI 0 "register_operand" "=r")
5146         (zero_extend:DI
5147          (unspec:SI [(mem:SI (lo_sum:DI
5148                              (match_operand:DI 1 "register_operand" "r")
5149                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5150                     UNSPEC_GOTSMALLPIC28K)))]
5151   "TARGET_ILP32"
5152   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5153   [(set_attr "type" "load1")]
5156 (define_insn "ldr_got_tiny"
5157   [(set (match_operand:DI 0 "register_operand" "=r")
5158         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5159                    UNSPEC_GOTTINYPIC))]
5160   ""
5161   "ldr\\t%0, %L1"
5162   [(set_attr "type" "load1")]
5165 (define_insn "aarch64_load_tp_hard"
5166   [(set (match_operand:DI 0 "register_operand" "=r")
5167         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5168   ""
5169   "mrs\\t%0, tpidr_el0"
5170   [(set_attr "type" "mrs")]
5173 ;; The TLS ABI specifically requires that the compiler does not schedule
5174 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5175 ;; Therefore we treat the stubs as an atomic sequence.
5176 (define_expand "tlsgd_small"
5177  [(parallel [(set (match_operand 0 "register_operand" "")
5178                   (call (mem:DI (match_dup 2)) (const_int 1)))
5179              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5180              (clobber (reg:DI LR_REGNUM))])]
5181  ""
5183   operands[2] = aarch64_tls_get_addr ();
5186 (define_insn "*tlsgd_small"
5187   [(set (match_operand 0 "register_operand" "")
5188         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5189    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5190    (clobber (reg:DI LR_REGNUM))
5191   ]
5192   ""
5193   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5194   [(set_attr "type" "call")
5195    (set_attr "length" "16")])
5197 (define_insn "tlsie_small_<mode>"
5198   [(set (match_operand:PTR 0 "register_operand" "=r")
5199         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5200                    UNSPEC_GOTSMALLTLS))]
5201   ""
5202   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5203   [(set_attr "type" "load1")
5204    (set_attr "length" "8")]
5207 (define_insn "tlsie_small_sidi"
5208   [(set (match_operand:DI 0 "register_operand" "=r")
5209         (zero_extend:DI
5210           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5211                       UNSPEC_GOTSMALLTLS)))]
5212   ""
5213   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5214   [(set_attr "type" "load1")
5215    (set_attr "length" "8")]
5218 (define_insn "tlsie_tiny_<mode>"
5219   [(set (match_operand:PTR 0 "register_operand" "=&r")
5220         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5221                      (match_operand:PTR 2 "register_operand" "r")]
5222                    UNSPEC_GOTTINYTLS))]
5223   ""
5224   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5225   [(set_attr "type" "multiple")
5226    (set_attr "length" "8")]
5229 (define_insn "tlsie_tiny_sidi"
5230   [(set (match_operand:DI 0 "register_operand" "=&r")
5231         (zero_extend:DI
5232           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5233                       (match_operand:DI 2 "register_operand" "r")
5234                       ]
5235                       UNSPEC_GOTTINYTLS)))]
5236   ""
5237   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5238   [(set_attr "type" "multiple")
5239    (set_attr "length" "8")]
5242 (define_insn "tlsle12_<mode>"
5243   [(set (match_operand:P 0 "register_operand" "=r")
5244         (unspec:P [(match_operand:P 1 "register_operand" "r")
5245                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5246                    UNSPEC_TLSLE12))]
5247   ""
5248   "add\\t%<w>0, %<w>1, #%L2";
5249   [(set_attr "type" "alu_sreg")
5250    (set_attr "length" "4")]
5253 (define_insn "tlsle24_<mode>"
5254   [(set (match_operand:P 0 "register_operand" "=r")
5255         (unspec:P [(match_operand:P 1 "register_operand" "r")
5256                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5257                    UNSPEC_TLSLE24))]
5258   ""
5259   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5260   [(set_attr "type" "multiple")
5261    (set_attr "length" "8")]
5264 (define_insn "tlsle32_<mode>"
5265   [(set (match_operand:P 0 "register_operand" "=r")
5266         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5267                    UNSPEC_TLSLE32))]
5268   ""
5269   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5270   [(set_attr "type" "multiple")
5271    (set_attr "length" "8")]
5274 (define_insn "tlsle48_<mode>"
5275   [(set (match_operand:P 0 "register_operand" "=r")
5276         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5277                    UNSPEC_TLSLE48))]
5278   ""
5279   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5280   [(set_attr "type" "multiple")
5281    (set_attr "length" "12")]
5284 (define_insn "tlsdesc_small_<mode>"
5285   [(set (reg:PTR R0_REGNUM)
5286         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5287                    UNSPEC_TLSDESC))
5288    (clobber (reg:DI LR_REGNUM))
5289    (clobber (reg:CC CC_REGNUM))
5290    (clobber (match_scratch:DI 1 "=r"))]
5291   "TARGET_TLS_DESC"
5292   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5293   [(set_attr "type" "call")
5294    (set_attr "length" "16")])
5296 (define_insn "stack_tie"
5297   [(set (mem:BLK (scratch))
5298         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5299                      (match_operand:DI 1 "register_operand" "rk")]
5300                     UNSPEC_PRLG_STK))]
5301   ""
5302   ""
5303   [(set_attr "length" "0")]
5306 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5307 ;; all of memory.  This blocks insns from being moved across this point.
5309 (define_insn "blockage"
5310   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5311   ""
5312   ""
5313   [(set_attr "length" "0")
5314    (set_attr "type" "block")]
5317 (define_insn "probe_stack_range_<PTR:mode>"
5318   [(set (match_operand:PTR 0 "register_operand" "=r")
5319         (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5320                               (match_operand:PTR 2 "register_operand" "r")]
5321                                UNSPECV_PROBE_STACK_RANGE))]
5322   ""
5324   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5326   [(set_attr "length" "32")]
5329 ;; Named pattern for expanding thread pointer reference.
5330 (define_expand "get_thread_pointerdi"
5331   [(match_operand:DI 0 "register_operand" "=r")]
5332   ""
5334   rtx tmp = aarch64_load_tp (operands[0]);
5335   if (tmp != operands[0])
5336     emit_move_insn (operands[0], tmp);
5337   DONE;
5340 ;; Named patterns for stack smashing protection.
5341 (define_expand "stack_protect_set"
5342   [(match_operand 0 "memory_operand")
5343    (match_operand 1 "memory_operand")]
5344   ""
5346   machine_mode mode = GET_MODE (operands[0]);
5348   emit_insn ((mode == DImode
5349               ? gen_stack_protect_set_di
5350               : gen_stack_protect_set_si) (operands[0], operands[1]));
5351   DONE;
5354 (define_insn "stack_protect_set_<mode>"
5355   [(set (match_operand:PTR 0 "memory_operand" "=m")
5356         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5357          UNSPEC_SP_SET))
5358    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5359   ""
5360   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5361   [(set_attr "length" "12")
5362    (set_attr "type" "multiple")])
5364 (define_expand "stack_protect_test"
5365   [(match_operand 0 "memory_operand")
5366    (match_operand 1 "memory_operand")
5367    (match_operand 2)]
5368   ""
5370   rtx result;
5371   machine_mode mode = GET_MODE (operands[0]);
5373   result = gen_reg_rtx(mode);
5375   emit_insn ((mode == DImode
5376               ? gen_stack_protect_test_di
5377               : gen_stack_protect_test_si) (result,
5378                                             operands[0],
5379                                             operands[1]));
5381   if (mode == DImode)
5382     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5383                                     result, const0_rtx, operands[2]));
5384   else
5385     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5386                                     result, const0_rtx, operands[2]));
5387   DONE;
5390 (define_insn "stack_protect_test_<mode>"
5391   [(set (match_operand:PTR 0 "register_operand" "=r")
5392         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5393                      (match_operand:PTR 2 "memory_operand" "m")]
5394          UNSPEC_SP_TEST))
5395    (clobber (match_scratch:PTR 3 "=&r"))]
5396   ""
5397   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5398   [(set_attr "length" "12")
5399    (set_attr "type" "multiple")])
5401 ;; Write Floating-point Control Register.
5402 (define_insn "set_fpcr"
5403   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5404   ""
5405   "msr\\tfpcr, %0"
5406   [(set_attr "type" "mrs")])
5408 ;; Read Floating-point Control Register.
5409 (define_insn "get_fpcr"
5410   [(set (match_operand:SI 0 "register_operand" "=r")
5411         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5412   ""
5413   "mrs\\t%0, fpcr"
5414   [(set_attr "type" "mrs")])
5416 ;; Write Floating-point Status Register.
5417 (define_insn "set_fpsr"
5418   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5419   ""
5420   "msr\\tfpsr, %0"
5421   [(set_attr "type" "mrs")])
5423 ;; Read Floating-point Status Register.
5424 (define_insn "get_fpsr"
5425   [(set (match_operand:SI 0 "register_operand" "=r")
5426         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5427   ""
5428   "mrs\\t%0, fpsr"
5429   [(set_attr "type" "mrs")])
5432 ;; Define the subtract-one-and-jump insns so loop.c
5433 ;; knows what to generate.
5434 (define_expand "doloop_end"
5435   [(use (match_operand 0 "" ""))      ; loop pseudo
5436    (use (match_operand 1 "" ""))]     ; label
5437   "optimize > 0 && flag_modulo_sched"
5439   rtx s0;
5440   rtx bcomp;
5441   rtx loc_ref;
5442   rtx cc_reg;
5443   rtx insn;
5444   rtx cmp;
5446   /* Currently SMS relies on the do-loop pattern to recognize loops
5447      where (1) the control part consists of all insns defining and/or
5448      using a certain 'count' register and (2) the loop count can be
5449      adjusted by modifying this register prior to the loop.
5450      ??? The possible introduction of a new block to initialize the
5451      new IV can potentially affect branch optimizations.  */
5453   if (GET_MODE (operands[0]) != DImode)
5454     FAIL;
5456   s0 = operands [0];
5457   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5459   cmp = XVECEXP (PATTERN (insn), 0, 0);
5460   cc_reg = SET_DEST (cmp);
5461   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5462   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5463   emit_jump_insn (gen_rtx_SET (pc_rtx,
5464                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5465                                                      loc_ref, pc_rtx)));
5466   DONE;
5469 ;; AdvSIMD Stuff
5470 (include "aarch64-simd.md")
5472 ;; Atomic Operations
5473 (include "atomics.md")
5475 ;; ldp/stp peephole patterns
5476 (include "aarch64-ldpstp.md")