[AArch64] Purge leftover occurrences of aarch64_nopcrelative_literal_loads
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
bloba3be2b999c86177b47c628cc8b472eea672773f2
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2017 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 "*cb<optab><mode>1"
596   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
597                                 (const_int 0))
598                            (label_ref (match_operand 1 "" ""))
599                            (pc)))]
600   ""
601   {
602     if (get_attr_length (insn) == 8)
603       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
604     else
605       return "<cbz>\\t%<w>0, %l1";
606   }
607   [(set_attr "type" "branch")
608    (set (attr "length")
609         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
610                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
611                       (const_int 4)
612                       (const_int 8)))
613    (set (attr "far_branch")
614         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
615                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
616                       (const_int 0)
617                       (const_int 1)))]
620 (define_insn "*tb<optab><mode>1"
621   [(set (pc) (if_then_else
622               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
623                                     (const_int 1)
624                                     (match_operand 1
625                                       "aarch64_simd_shift_imm_<mode>" "n"))
626                    (const_int 0))
627              (label_ref (match_operand 2 "" ""))
628              (pc)))
629    (clobber (reg:CC CC_REGNUM))]
630   ""
631   {
632     if (get_attr_length (insn) == 8)
633       {
634         if (get_attr_far_branch (insn) == 1)
635           return aarch64_gen_far_branch (operands, 2, "Ltb",
636                                          "<inv_tb>\\t%<w>0, %1, ");
637         else
638           {
639             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
640             return "tst\t%<w>0, %1\;<bcond>\t%l2";
641           }
642       }
643     else
644       return "<tbz>\t%<w>0, %1, %l2";
645   }
646   [(set_attr "type" "branch")
647    (set (attr "length")
648         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
649                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
650                       (const_int 4)
651                       (const_int 8)))
652    (set (attr "far_branch")
653         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
654                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
655                       (const_int 0)
656                       (const_int 1)))]
660 (define_insn "*cb<optab><mode>1"
661   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
662                                  (const_int 0))
663                            (label_ref (match_operand 1 "" ""))
664                            (pc)))
665    (clobber (reg:CC CC_REGNUM))]
666   ""
667   {
668     if (get_attr_length (insn) == 8)
669       {
670         if (get_attr_far_branch (insn) == 1)
671           return aarch64_gen_far_branch (operands, 1, "Ltb",
672                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
673         else
674           {
675             char buf[64];
676             uint64_t val = ((uint64_t) 1)
677                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
678             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
679             output_asm_insn (buf, operands);
680             return "<bcond>\t%l1";
681           }
682       }
683     else
684       return "<tbz>\t%<w>0, <sizem1>, %l1";
685   }
686   [(set_attr "type" "branch")
687    (set (attr "length")
688         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
689                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
690                       (const_int 4)
691                       (const_int 8)))
692    (set (attr "far_branch")
693         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
694                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
695                       (const_int 0)
696                       (const_int 1)))]
699 ;; -------------------------------------------------------------------
700 ;; Subroutine calls and sibcalls
701 ;; -------------------------------------------------------------------
703 (define_expand "call_internal"
704   [(parallel [(call (match_operand 0 "memory_operand" "")
705                     (match_operand 1 "general_operand" ""))
706               (use (match_operand 2 "" ""))
707               (clobber (reg:DI LR_REGNUM))])])
709 (define_expand "call"
710   [(parallel [(call (match_operand 0 "memory_operand" "")
711                     (match_operand 1 "general_operand" ""))
712               (use (match_operand 2 "" ""))
713               (clobber (reg:DI LR_REGNUM))])]
714   ""
715   "
716   {
717     rtx callee, pat;
719     /* In an untyped call, we can get NULL for operand 2.  */
720     if (operands[2] == NULL)
721       operands[2] = const0_rtx;
723     /* Decide if we should generate indirect calls by loading the
724        64-bit address of the callee into a register before performing
725        the branch-and-link.  */
726     callee = XEXP (operands[0], 0);
727     if (GET_CODE (callee) == SYMBOL_REF
728         ? (aarch64_is_long_call_p (callee)
729            || aarch64_is_noplt_call_p (callee))
730         : !REG_P (callee))
731       XEXP (operands[0], 0) = force_reg (Pmode, callee);
733     pat = gen_call_internal (operands[0], operands[1], operands[2]);
734     aarch64_emit_call_insn (pat);
735     DONE;
736   }"
739 (define_insn "*call_reg"
740   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
741          (match_operand 1 "" ""))
742    (use (match_operand 2 "" ""))
743    (clobber (reg:DI LR_REGNUM))]
744   ""
745   "blr\\t%0"
746   [(set_attr "type" "call")]
749 (define_insn "*call_symbol"
750   [(call (mem:DI (match_operand:DI 0 "" ""))
751          (match_operand 1 "" ""))
752    (use (match_operand 2 "" ""))
753    (clobber (reg:DI LR_REGNUM))]
754   "GET_CODE (operands[0]) == SYMBOL_REF
755    && !aarch64_is_long_call_p (operands[0])
756    && !aarch64_is_noplt_call_p (operands[0])"
757   "bl\\t%a0"
758   [(set_attr "type" "call")]
761 (define_expand "call_value_internal"
762   [(parallel [(set (match_operand 0 "" "")
763                    (call (match_operand 1 "memory_operand" "")
764                          (match_operand 2 "general_operand" "")))
765               (use (match_operand 3 "" ""))
766               (clobber (reg:DI LR_REGNUM))])])
768 (define_expand "call_value"
769   [(parallel [(set (match_operand 0 "" "")
770                    (call (match_operand 1 "memory_operand" "")
771                          (match_operand 2 "general_operand" "")))
772               (use (match_operand 3 "" ""))
773               (clobber (reg:DI LR_REGNUM))])]
774   ""
775   "
776   {
777     rtx callee, pat;
779     /* In an untyped call, we can get NULL for operand 3.  */
780     if (operands[3] == NULL)
781       operands[3] = const0_rtx;
783     /* Decide if we should generate indirect calls by loading the
784        64-bit address of the callee into a register before performing
785        the branch-and-link.  */
786     callee = XEXP (operands[1], 0);
787     if (GET_CODE (callee) == SYMBOL_REF
788         ? (aarch64_is_long_call_p (callee)
789            || aarch64_is_noplt_call_p (callee))
790         : !REG_P (callee))
791       XEXP (operands[1], 0) = force_reg (Pmode, callee);
793     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
794                                    operands[3]);
795     aarch64_emit_call_insn (pat);
796     DONE;
797   }"
800 (define_insn "*call_value_reg"
801   [(set (match_operand 0 "" "")
802         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
803                       (match_operand 2 "" "")))
804    (use (match_operand 3 "" ""))
805    (clobber (reg:DI LR_REGNUM))]
806   ""
807   "blr\\t%1"
808   [(set_attr "type" "call")]
812 (define_insn "*call_value_symbol"
813   [(set (match_operand 0 "" "")
814         (call (mem:DI (match_operand:DI 1 "" ""))
815               (match_operand 2 "" "")))
816    (use (match_operand 3 "" ""))
817    (clobber (reg:DI LR_REGNUM))]
818   "GET_CODE (operands[1]) == SYMBOL_REF
819    && !aarch64_is_long_call_p (operands[1])
820    && !aarch64_is_noplt_call_p (operands[1])"
821   "bl\\t%a1"
822   [(set_attr "type" "call")]
825 (define_expand "sibcall_internal"
826   [(parallel [(call (match_operand 0 "memory_operand" "")
827                     (match_operand 1 "general_operand" ""))
828               (return)
829               (use (match_operand 2 "" ""))])])
831 (define_expand "sibcall"
832   [(parallel [(call (match_operand 0 "memory_operand" "")
833                     (match_operand 1 "general_operand" ""))
834               (return)
835               (use (match_operand 2 "" ""))])]
836   ""
837   {
838     rtx pat;
839     rtx callee = XEXP (operands[0], 0);
840     if (!REG_P (callee)
841        && ((GET_CODE (callee) != SYMBOL_REF)
842            || aarch64_is_noplt_call_p (callee)))
843       XEXP (operands[0], 0) = force_reg (Pmode, callee);
845     if (operands[2] == NULL_RTX)
846       operands[2] = const0_rtx;
848     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
849     aarch64_emit_call_insn (pat);
850     DONE;
851   }
854 (define_expand "sibcall_value_internal"
855   [(parallel [(set (match_operand 0 "" "")
856                    (call (match_operand 1 "memory_operand" "")
857                          (match_operand 2 "general_operand" "")))
858               (return)
859               (use (match_operand 3 "" ""))])])
861 (define_expand "sibcall_value"
862   [(parallel [(set (match_operand 0 "" "")
863                    (call (match_operand 1 "memory_operand" "")
864                          (match_operand 2 "general_operand" "")))
865               (return)
866               (use (match_operand 3 "" ""))])]
867   ""
868   {
869     rtx pat;
870     rtx callee = XEXP (operands[1], 0);
871     if (!REG_P (callee)
872        && ((GET_CODE (callee) != SYMBOL_REF)
873            || aarch64_is_noplt_call_p (callee)))
874       XEXP (operands[1], 0) = force_reg (Pmode, callee);
876     if (operands[3] == NULL_RTX)
877       operands[3] = const0_rtx;
879     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
880                                       operands[3]);
881     aarch64_emit_call_insn (pat);
882     DONE;
883   }
886 (define_insn "*sibcall_insn"
887   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
888          (match_operand 1 "" ""))
889    (return)
890    (use (match_operand 2 "" ""))]
891   "SIBLING_CALL_P (insn)"
892   "@
893    br\\t%0
894    b\\t%a0"
895   [(set_attr "type" "branch, branch")]
898 (define_insn "*sibcall_value_insn"
899   [(set (match_operand 0 "" "")
900         (call (mem:DI
901                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
902               (match_operand 2 "" "")))
903    (return)
904    (use (match_operand 3 "" ""))]
905   "SIBLING_CALL_P (insn)"
906   "@
907    br\\t%1
908    b\\t%a1"
909   [(set_attr "type" "branch, branch")]
912 ;; Call subroutine returning any type.
914 (define_expand "untyped_call"
915   [(parallel [(call (match_operand 0 "")
916                     (const_int 0))
917               (match_operand 1 "")
918               (match_operand 2 "")])]
919   ""
921   int i;
923   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
925   for (i = 0; i < XVECLEN (operands[2], 0); i++)
926     {
927       rtx set = XVECEXP (operands[2], 0, i);
928       emit_move_insn (SET_DEST (set), SET_SRC (set));
929     }
931   /* The optimizer does not know that the call sets the function value
932      registers we stored in the result block.  We avoid problems by
933      claiming that all hard registers are used and clobbered at this
934      point.  */
935   emit_insn (gen_blockage ());
936   DONE;
939 ;; -------------------------------------------------------------------
940 ;; Moves
941 ;; -------------------------------------------------------------------
943 (define_expand "mov<mode>"
944   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
945         (match_operand:SHORT 1 "general_operand" ""))]
946   ""
947   "
948     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
949       operands[1] = force_reg (<MODE>mode, operands[1]);
950   "
953 (define_insn "*mov<mode>_aarch64"
954   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
955         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
956   "(register_operand (operands[0], <MODE>mode)
957     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
959    switch (which_alternative)
960      {
961      case 0:
962        return "mov\t%w0, %w1";
963      case 1:
964        return "mov\t%w0, %1";
965      case 2:
966        return aarch64_output_scalar_simd_mov_immediate (operands[1],
967                                                         <MODE>mode);
968      case 3:
969        return "ldr<size>\t%w0, %1";
970      case 4:
971        return "ldr\t%<size>0, %1";
972      case 5:
973        return "str<size>\t%w1, %0";
974      case 6:
975        return "str\t%<size>1, %0";
976      case 7:
977        return "umov\t%w0, %1.<v>[0]";
978      case 8:
979        return "dup\t%0.<Vallxd>, %w1";
980      case 9:
981        return "dup\t%<Vetype>0, %1.<v>[0]";
982      default:
983        gcc_unreachable ();
984      }
986   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
987                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
988    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
991 (define_expand "mov<mode>"
992   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
993         (match_operand:GPI 1 "general_operand" ""))]
994   ""
995   "
996     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
997         && <MODE>mode == DImode
998         && aarch64_split_dimode_const_store (operands[0], operands[1]))
999       DONE;
1001     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1002       operands[1] = force_reg (<MODE>mode, operands[1]);
1004     /* FIXME: RR we still need to fix up what we are doing with
1005        symbol_refs and other types of constants.  */
1006     if (CONSTANT_P (operands[1])
1007         && !CONST_INT_P (operands[1]))
1008      {
1009        aarch64_expand_mov_immediate (operands[0], operands[1]);
1010        DONE;
1011      }
1012   "
1015 (define_insn_and_split "*movsi_aarch64"
1016   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
1017         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1018   "(register_operand (operands[0], SImode)
1019     || aarch64_reg_or_zero (operands[1], SImode))"
1020   "@
1021    mov\\t%w0, %w1
1022    mov\\t%w0, %w1
1023    mov\\t%w0, %w1
1024    mov\\t%w0, %1
1025    #
1026    ldr\\t%w0, %1
1027    ldr\\t%s0, %1
1028    str\\t%w1, %0
1029    str\\t%s1, %0
1030    adr\\t%x0, %a1
1031    adrp\\t%x0, %A1
1032    fmov\\t%s0, %w1
1033    fmov\\t%w0, %s1
1034    fmov\\t%s0, %s1"
1035    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1036     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1037    [(const_int 0)]
1038    "{
1039        aarch64_expand_mov_immediate (operands[0], operands[1]);
1040        DONE;
1041     }"
1042   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1043                      adr,adr,f_mcr,f_mrc,fmov")
1044    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1047 (define_insn_and_split "*movdi_aarch64"
1048   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
1049         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1050   "(register_operand (operands[0], DImode)
1051     || aarch64_reg_or_zero (operands[1], DImode))"
1052   "@
1053    mov\\t%x0, %x1
1054    mov\\t%0, %x1
1055    mov\\t%x0, %1
1056    mov\\t%x0, %1
1057    #
1058    ldr\\t%x0, %1
1059    ldr\\t%d0, %1
1060    str\\t%x1, %0
1061    str\\t%d1, %0
1062    adr\\t%x0, %a1
1063    adrp\\t%x0, %A1
1064    fmov\\t%d0, %x1
1065    fmov\\t%x0, %d1
1066    fmov\\t%d0, %d1
1067    movi\\t%d0, %1"
1068    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1069     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1070    [(const_int 0)]
1071    "{
1072        aarch64_expand_mov_immediate (operands[0], operands[1]);
1073        DONE;
1074     }"
1075   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1076                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
1077    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1078    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1081 (define_insn "insv_imm<mode>"
1082   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1083                           (const_int 16)
1084                           (match_operand:GPI 1 "const_int_operand" "n"))
1085         (match_operand:GPI 2 "const_int_operand" "n"))]
1086   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1087    && UINTVAL (operands[1]) % 16 == 0"
1088   "movk\\t%<w>0, %X2, lsl %1"
1089   [(set_attr "type" "mov_imm")]
1092 (define_expand "movti"
1093   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1094         (match_operand:TI 1 "general_operand" ""))]
1095   ""
1096   "
1097     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1098       operands[1] = force_reg (TImode, operands[1]);
1099   "
1102 (define_insn "*movti_aarch64"
1103   [(set (match_operand:TI 0
1104          "nonimmediate_operand"  "=r, *w,r ,*w,r,m,m,*w,m")
1105         (match_operand:TI 1
1106          "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1107   "(register_operand (operands[0], TImode)
1108     || aarch64_reg_or_zero (operands[1], TImode))"
1109   "@
1110    #
1111    #
1112    #
1113    orr\\t%0.16b, %1.16b, %1.16b
1114    ldp\\t%0, %H0, %1
1115    stp\\t%1, %H1, %0
1116    stp\\txzr, xzr, %0
1117    ldr\\t%q0, %1
1118    str\\t%q1, %0"
1119   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1120                              load2,store2,store2,f_loadd,f_stored")
1121    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1122    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1123    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1126 ;; Split a TImode register-register or register-immediate move into
1127 ;; its component DImode pieces, taking care to handle overlapping
1128 ;; source and dest registers.
1129 (define_split
1130    [(set (match_operand:TI 0 "register_operand" "")
1131          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1132   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1133   [(const_int 0)]
1135   aarch64_split_128bit_move (operands[0], operands[1]);
1136   DONE;
1139 (define_expand "mov<mode>"
1140   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1141         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1142   ""
1143   {
1144     if (!TARGET_FLOAT)
1145       {
1146         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1147         FAIL;
1148       }
1150     if (GET_CODE (operands[0]) == MEM
1151         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1152               && aarch64_float_const_zero_rtx_p (operands[1])))
1153       operands[1] = force_reg (<MODE>mode, operands[1]);
1154   }
1157 (define_insn "*movhf_aarch64"
1158   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w,m,r,m ,r")
1159         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,m,w,m,rY,r"))]
1160   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1161     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1162   "@
1163    movi\\t%0.4h, #0
1164    mov\\t%0.h[0], %w1
1165    umov\\t%w0, %1.h[0]
1166    mov\\t%0.h[0], %1.h[0]
1167    ldr\\t%h0, %1
1168    str\\t%h1, %0
1169    ldrh\\t%w0, %1
1170    strh\\t%w1, %0
1171    mov\\t%w0, %w1"
1172   [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1173                      f_loads,f_stores,load1,store1,mov_reg")
1174    (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1177 (define_insn "*movsf_aarch64"
1178   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1179         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1180   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1181     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1182   "@
1183    movi\\t%0.2s, #0
1184    fmov\\t%s0, %w1
1185    fmov\\t%w0, %s1
1186    fmov\\t%s0, %s1
1187    fmov\\t%s0, %1
1188    ldr\\t%s0, %1
1189    str\\t%s1, %0
1190    ldr\\t%w0, %1
1191    str\\t%w1, %0
1192    mov\\t%w0, %w1"
1193   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1194                      f_loads,f_stores,load1,store1,mov_reg")
1195    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1198 (define_insn "*movdf_aarch64"
1199   [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1200         (match_operand:DF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1201   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1202     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1203   "@
1204    movi\\t%d0, #0
1205    fmov\\t%d0, %x1
1206    fmov\\t%x0, %d1
1207    fmov\\t%d0, %d1
1208    fmov\\t%d0, %1
1209    ldr\\t%d0, %1
1210    str\\t%d1, %0
1211    ldr\\t%x0, %1
1212    str\\t%x1, %0
1213    mov\\t%x0, %x1"
1214   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1215                      f_loadd,f_stored,load1,store1,mov_reg")
1216    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1219 (define_insn "*movtf_aarch64"
1220   [(set (match_operand:TF 0
1221          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1222         (match_operand:TF 1
1223          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1224   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1225     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1226   "@
1227    orr\\t%0.16b, %1.16b, %1.16b
1228    #
1229    #
1230    #
1231    movi\\t%0.2d, #0
1232    fmov\\t%s0, wzr
1233    ldr\\t%q0, %1
1234    str\\t%q1, %0
1235    ldp\\t%0, %H0, %1
1236    stp\\t%1, %H1, %0
1237    stp\\txzr, xzr, %0"
1238   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1239                      f_loadd,f_stored,load2,store2,store2")
1240    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1241    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1244 (define_split
1245    [(set (match_operand:TF 0 "register_operand" "")
1246          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1247   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1248   [(const_int 0)]
1249   {
1250     aarch64_split_128bit_move (operands[0], operands[1]);
1251     DONE;
1252   }
1255 ;; 0 is dst
1256 ;; 1 is src
1257 ;; 2 is size of move in bytes
1258 ;; 3 is alignment
1260 (define_expand "movmemdi"
1261   [(match_operand:BLK 0 "memory_operand")
1262    (match_operand:BLK 1 "memory_operand")
1263    (match_operand:DI 2 "immediate_operand")
1264    (match_operand:DI 3 "immediate_operand")]
1265    "!STRICT_ALIGNMENT"
1267   if (aarch64_expand_movmem (operands))
1268     DONE;
1269   FAIL;
1273 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1274 ;; fairly lax checking on the second memory operation.
1275 (define_insn "load_pairsi"
1276   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1277         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1278    (set (match_operand:SI 2 "register_operand" "=r,*w")
1279         (match_operand:SI 3 "memory_operand" "m,m"))]
1280   "rtx_equal_p (XEXP (operands[3], 0),
1281                 plus_constant (Pmode,
1282                                XEXP (operands[1], 0),
1283                                GET_MODE_SIZE (SImode)))"
1284   "@
1285    ldp\\t%w0, %w2, %1
1286    ldp\\t%s0, %s2, %1"
1287   [(set_attr "type" "load2,neon_load1_2reg")
1288    (set_attr "fp" "*,yes")]
1291 (define_insn "load_pairdi"
1292   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1293         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1294    (set (match_operand:DI 2 "register_operand" "=r,*w")
1295         (match_operand:DI 3 "memory_operand" "m,m"))]
1296   "rtx_equal_p (XEXP (operands[3], 0),
1297                 plus_constant (Pmode,
1298                                XEXP (operands[1], 0),
1299                                GET_MODE_SIZE (DImode)))"
1300   "@
1301    ldp\\t%x0, %x2, %1
1302    ldp\\t%d0, %d2, %1"
1303   [(set_attr "type" "load2,neon_load1_2reg")
1304    (set_attr "fp" "*,yes")]
1308 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1309 ;; fairly lax checking on the second memory operation.
1310 (define_insn "store_pairsi"
1311   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1312         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1313    (set (match_operand:SI 2 "memory_operand" "=m,m")
1314         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1315   "rtx_equal_p (XEXP (operands[2], 0),
1316                 plus_constant (Pmode,
1317                                XEXP (operands[0], 0),
1318                                GET_MODE_SIZE (SImode)))"
1319   "@
1320    stp\\t%w1, %w3, %0
1321    stp\\t%s1, %s3, %0"
1322   [(set_attr "type" "store2,neon_store1_2reg")
1323    (set_attr "fp" "*,yes")]
1326 (define_insn "store_pairdi"
1327   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1328         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1329    (set (match_operand:DI 2 "memory_operand" "=m,m")
1330         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1331   "rtx_equal_p (XEXP (operands[2], 0),
1332                 plus_constant (Pmode,
1333                                XEXP (operands[0], 0),
1334                                GET_MODE_SIZE (DImode)))"
1335   "@
1336    stp\\t%x1, %x3, %0
1337    stp\\t%d1, %d3, %0"
1338   [(set_attr "type" "store2,neon_store1_2reg")
1339    (set_attr "fp" "*,yes")]
1342 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1343 ;; fairly lax checking on the second memory operation.
1344 (define_insn "load_pairsf"
1345   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1346         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1347    (set (match_operand:SF 2 "register_operand" "=w,*r")
1348         (match_operand:SF 3 "memory_operand" "m,m"))]
1349   "rtx_equal_p (XEXP (operands[3], 0),
1350                 plus_constant (Pmode,
1351                                XEXP (operands[1], 0),
1352                                GET_MODE_SIZE (SFmode)))"
1353   "@
1354    ldp\\t%s0, %s2, %1
1355    ldp\\t%w0, %w2, %1"
1356   [(set_attr "type" "neon_load1_2reg,load2")
1357    (set_attr "fp" "yes,*")]
1360 (define_insn "load_pairdf"
1361   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1362         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1363    (set (match_operand:DF 2 "register_operand" "=w,*r")
1364         (match_operand:DF 3 "memory_operand" "m,m"))]
1365   "rtx_equal_p (XEXP (operands[3], 0),
1366                 plus_constant (Pmode,
1367                                XEXP (operands[1], 0),
1368                                GET_MODE_SIZE (DFmode)))"
1369   "@
1370    ldp\\t%d0, %d2, %1
1371    ldp\\t%x0, %x2, %1"
1372   [(set_attr "type" "neon_load1_2reg,load2")
1373    (set_attr "fp" "yes,*")]
1376 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1377 ;; fairly lax checking on the second memory operation.
1378 (define_insn "store_pairsf"
1379   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1380         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1381    (set (match_operand:SF 2 "memory_operand" "=m,m")
1382         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1383   "rtx_equal_p (XEXP (operands[2], 0),
1384                 plus_constant (Pmode,
1385                                XEXP (operands[0], 0),
1386                                GET_MODE_SIZE (SFmode)))"
1387   "@
1388    stp\\t%s1, %s3, %0
1389    stp\\t%w1, %w3, %0"
1390   [(set_attr "type" "neon_store1_2reg,store2")
1391    (set_attr "fp" "yes,*")]
1394 (define_insn "store_pairdf"
1395   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1396         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1397    (set (match_operand:DF 2 "memory_operand" "=m,m")
1398         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1399   "rtx_equal_p (XEXP (operands[2], 0),
1400                 plus_constant (Pmode,
1401                                XEXP (operands[0], 0),
1402                                GET_MODE_SIZE (DFmode)))"
1403   "@
1404    stp\\t%d1, %d3, %0
1405    stp\\t%x1, %x3, %0"
1406   [(set_attr "type" "neon_store1_2reg,store2")
1407    (set_attr "fp" "yes,*")]
1410 ;; Load pair with post-index writeback.  This is primarily used in function
1411 ;; epilogues.
1412 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1413   [(parallel
1414     [(set (match_operand:P 0 "register_operand" "=k")
1415           (plus:P (match_operand:P 1 "register_operand" "0")
1416                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1417      (set (match_operand:GPI 2 "register_operand" "=r")
1418           (mem:GPI (match_dup 1)))
1419      (set (match_operand:GPI 3 "register_operand" "=r")
1420           (mem:GPI (plus:P (match_dup 1)
1421                    (match_operand:P 5 "const_int_operand" "n"))))])]
1422   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1423   "ldp\\t%<w>2, %<w>3, [%1], %4"
1424   [(set_attr "type" "load2")]
1427 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1428   [(parallel
1429     [(set (match_operand:P 0 "register_operand" "=k")
1430           (plus:P (match_operand:P 1 "register_operand" "0")
1431                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1432      (set (match_operand:GPF 2 "register_operand" "=w")
1433           (mem:GPF (match_dup 1)))
1434      (set (match_operand:GPF 3 "register_operand" "=w")
1435           (mem:GPF (plus:P (match_dup 1)
1436                    (match_operand:P 5 "const_int_operand" "n"))))])]
1437   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1438   "ldp\\t%<w>2, %<w>3, [%1], %4"
1439   [(set_attr "type" "neon_load1_2reg")]
1442 ;; Store pair with pre-index writeback.  This is primarily used in function
1443 ;; prologues.
1444 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1445   [(parallel
1446     [(set (match_operand:P 0 "register_operand" "=&k")
1447           (plus:P (match_operand:P 1 "register_operand" "0")
1448                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1449      (set (mem:GPI (plus:P (match_dup 0)
1450                    (match_dup 4)))
1451           (match_operand:GPI 2 "register_operand" "r"))
1452      (set (mem:GPI (plus:P (match_dup 0)
1453                    (match_operand:P 5 "const_int_operand" "n")))
1454           (match_operand:GPI 3 "register_operand" "r"))])]
1455   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1456   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1457   [(set_attr "type" "store2")]
1460 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1461   [(parallel
1462     [(set (match_operand:P 0 "register_operand" "=&k")
1463           (plus:P (match_operand:P 1 "register_operand" "0")
1464                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1465      (set (mem:GPF (plus:P (match_dup 0)
1466                    (match_dup 4)))
1467           (match_operand:GPF 2 "register_operand" "w"))
1468      (set (mem:GPF (plus:P (match_dup 0)
1469                    (match_operand:P 5 "const_int_operand" "n")))
1470           (match_operand:GPF 3 "register_operand" "w"))])]
1471   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1472   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1473   [(set_attr "type" "neon_store1_2reg<q>")]
1476 ;; -------------------------------------------------------------------
1477 ;; Sign/Zero extension
1478 ;; -------------------------------------------------------------------
1480 (define_expand "<optab>sidi2"
1481   [(set (match_operand:DI 0 "register_operand")
1482         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1483   ""
1486 (define_insn "*extendsidi2_aarch64"
1487   [(set (match_operand:DI 0 "register_operand" "=r,r")
1488         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1489   ""
1490   "@
1491    sxtw\t%0, %w1
1492    ldrsw\t%0, %1"
1493   [(set_attr "type" "extend,load1")]
1496 (define_insn "*load_pair_extendsidi2_aarch64"
1497   [(set (match_operand:DI 0 "register_operand" "=r")
1498         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1499    (set (match_operand:DI 2 "register_operand" "=r")
1500         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1501   "rtx_equal_p (XEXP (operands[3], 0),
1502                 plus_constant (Pmode,
1503                                XEXP (operands[1], 0),
1504                                GET_MODE_SIZE (SImode)))"
1505   "ldpsw\\t%0, %2, %1"
1506   [(set_attr "type" "load2")]
1509 (define_insn "*zero_extendsidi2_aarch64"
1510   [(set (match_operand:DI 0 "register_operand" "=r,r")
1511         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1512   ""
1513   "@
1514    uxtw\t%0, %w1
1515    ldr\t%w0, %1"
1516   [(set_attr "type" "extend,load1")]
1519 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1520   [(set (match_operand:DI 0 "register_operand" "=r")
1521         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1522    (set (match_operand:DI 2 "register_operand" "=r")
1523         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1524   "rtx_equal_p (XEXP (operands[3], 0),
1525                 plus_constant (Pmode,
1526                                XEXP (operands[1], 0),
1527                                GET_MODE_SIZE (SImode)))"
1528   "ldp\\t%w0, %w2, %1"
1529   [(set_attr "type" "load2")]
1532 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1533   [(set (match_operand:GPI 0 "register_operand")
1534         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1535   ""
1538 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1539   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1540         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1541   ""
1542   "@
1543    sxt<SHORT:size>\t%<GPI:w>0, %w1
1544    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1545   [(set_attr "type" "extend,load1")]
1548 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1549   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1550         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1551   ""
1552   "@
1553    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1554    ldr<SHORT:size>\t%w0, %1
1555    ldr\t%<SHORT:size>0, %1"
1556   [(set_attr "type" "logic_imm,load1,load1")]
1559 (define_expand "<optab>qihi2"
1560   [(set (match_operand:HI 0 "register_operand")
1561         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1562   ""
1565 (define_insn "*extendqihi2_aarch64"
1566   [(set (match_operand:HI 0 "register_operand" "=r,r")
1567         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1568   ""
1569   "@
1570    sxtb\t%w0, %w1
1571    ldrsb\t%w0, %1"
1572   [(set_attr "type" "extend,load1")]
1575 (define_insn "*zero_extendqihi2_aarch64"
1576   [(set (match_operand:HI 0 "register_operand" "=r,r")
1577         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1578   ""
1579   "@
1580    and\t%w0, %w1, 255
1581    ldrb\t%w0, %1"
1582   [(set_attr "type" "logic_imm,load1")]
1585 ;; -------------------------------------------------------------------
1586 ;; Simple arithmetic
1587 ;; -------------------------------------------------------------------
1589 (define_expand "add<mode>3"
1590   [(set
1591     (match_operand:GPI 0 "register_operand" "")
1592     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1593               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1594   ""
1596   /* If operands[1] is a subreg extract the inner RTX.  */
1597   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1599   /* If the constant is too large for a single instruction and isn't frame
1600      based, split off the immediate so it is available for CSE.  */
1601   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1602       && can_create_pseudo_p ()
1603       && (!REG_P (op1)
1604          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1605     operands[2] = force_reg (<MODE>mode, operands[2]);
1608 (define_insn "*add<mode>3_aarch64"
1609   [(set
1610     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1611     (plus:GPI
1612      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1613      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1614   ""
1615   "@
1616   add\\t%<w>0, %<w>1, %2
1617   add\\t%<w>0, %<w>1, %<w>2
1618   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1619   sub\\t%<w>0, %<w>1, #%n2
1620   #"
1621   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1622    (set_attr "simd" "*,*,yes,*,*")]
1625 ;; zero_extend version of above
1626 (define_insn "*addsi3_aarch64_uxtw"
1627   [(set
1628     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1629     (zero_extend:DI
1630      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1631               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1632   ""
1633   "@
1634   add\\t%w0, %w1, %2
1635   add\\t%w0, %w1, %w2
1636   sub\\t%w0, %w1, #%n2
1637   #"
1638   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1641 ;; If there's a free register, and we can load the constant with a
1642 ;; single instruction, do so.  This has a chance to improve scheduling.
1643 (define_peephole2
1644   [(match_scratch:GPI 3 "r")
1645    (set (match_operand:GPI 0 "register_operand")
1646         (plus:GPI
1647           (match_operand:GPI 1 "register_operand")
1648           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1649   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1650   [(set (match_dup 3) (match_dup 2))
1651    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1654 (define_peephole2
1655   [(match_scratch:SI 3 "r")
1656    (set (match_operand:DI 0 "register_operand")
1657         (zero_extend:DI
1658           (plus:SI
1659             (match_operand:SI 1 "register_operand")
1660             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1661   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1662   [(set (match_dup 3) (match_dup 2))
1663    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1666 ;; After peephole2 has had a chance to run, split any remaining long
1667 ;; additions into two add immediates.
1668 (define_split
1669   [(set (match_operand:GPI 0 "register_operand")
1670         (plus:GPI
1671           (match_operand:GPI 1 "register_operand")
1672           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1673   "epilogue_completed"
1674   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1675    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1676   {
1677     HOST_WIDE_INT i = INTVAL (operands[2]);
1678     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1679     operands[3] = GEN_INT (i - s);
1680     operands[4] = GEN_INT (s);
1681   }
1684 (define_split
1685   [(set (match_operand:DI 0 "register_operand")
1686         (zero_extend:DI
1687           (plus:SI
1688             (match_operand:SI 1 "register_operand")
1689             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1690   "epilogue_completed"
1691   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1692    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1693   {
1694     HOST_WIDE_INT i = INTVAL (operands[2]);
1695     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1696     operands[3] = GEN_INT (i - s);
1697     operands[4] = GEN_INT (s);
1698     operands[5] = gen_lowpart (SImode, operands[0]);
1699   }
1702 (define_expand "addti3"
1703   [(set (match_operand:TI 0 "register_operand" "")
1704         (plus:TI (match_operand:TI 1 "register_operand" "")
1705                  (match_operand:TI 2 "register_operand" "")))]
1706   ""
1708   rtx low = gen_reg_rtx (DImode);
1709   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1710                                   gen_lowpart (DImode, operands[2])));
1712   rtx high = gen_reg_rtx (DImode);
1713   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1714                                  gen_highpart (DImode, operands[2])));
1716   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1717   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1718   DONE;
1721 (define_insn "add<mode>3_compare0"
1722   [(set (reg:CC_NZ CC_REGNUM)
1723         (compare:CC_NZ
1724          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1725                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1726          (const_int 0)))
1727    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1728         (plus:GPI (match_dup 1) (match_dup 2)))]
1729   ""
1730   "@
1731   adds\\t%<w>0, %<w>1, %<w>2
1732   adds\\t%<w>0, %<w>1, %2
1733   subs\\t%<w>0, %<w>1, #%n2"
1734   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1737 ;; zero_extend version of above
1738 (define_insn "*addsi3_compare0_uxtw"
1739   [(set (reg:CC_NZ CC_REGNUM)
1740         (compare:CC_NZ
1741          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1742                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1743          (const_int 0)))
1744    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1745         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1746   ""
1747   "@
1748   adds\\t%w0, %w1, %w2
1749   adds\\t%w0, %w1, %2
1750   subs\\t%w0, %w1, #%n2"
1751   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1754 (define_insn "*add<mode>3_compareC_cconly_imm"
1755   [(set (reg:CC_C CC_REGNUM)
1756         (ne:CC_C
1757           (plus:<DWI>
1758             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1759             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1760           (zero_extend:<DWI>
1761             (plus:GPI
1762               (match_dup 0)
1763               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1764   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1765                                  <MODE>mode, operands[1])"
1766   "@
1767   cmn\\t%<w>0, %1
1768   cmp\\t%<w>0, #%n1"
1769   [(set_attr "type" "alus_imm")]
1772 (define_insn "*add<mode>3_compareC_cconly"
1773   [(set (reg:CC_C CC_REGNUM)
1774         (ne:CC_C
1775           (plus:<DWI>
1776             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1777             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1778           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1779   ""
1780   "cmn\\t%<w>0, %<w>1"
1781   [(set_attr "type" "alus_sreg")]
1784 (define_insn "*add<mode>3_compareC_imm"
1785   [(set (reg:CC_C CC_REGNUM)
1786         (ne:CC_C
1787           (plus:<DWI>
1788             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1789             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1790           (zero_extend:<DWI>
1791             (plus:GPI
1792               (match_dup 1)
1793               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1794    (set (match_operand:GPI 0 "register_operand" "=r,r")
1795         (plus:GPI (match_dup 1) (match_dup 2)))]
1796   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1797                                  <MODE>mode, operands[2])"
1798   "@
1799   adds\\t%<w>0, %<w>1, %2
1800   subs\\t%<w>0, %<w>1, #%n2"
1801   [(set_attr "type" "alus_imm")]
1804 (define_insn "add<mode>3_compareC"
1805   [(set (reg:CC_C CC_REGNUM)
1806         (ne:CC_C
1807           (plus:<DWI>
1808             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1809             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1810           (zero_extend:<DWI>
1811             (plus:GPI (match_dup 1) (match_dup 2)))))
1812    (set (match_operand:GPI 0 "register_operand" "=r")
1813         (plus:GPI (match_dup 1) (match_dup 2)))]
1814   ""
1815   "adds\\t%<w>0, %<w>1, %<w>2"
1816   [(set_attr "type" "alus_sreg")]
1819 (define_insn "*adds_shift_imm_<mode>"
1820   [(set (reg:CC_NZ CC_REGNUM)
1821         (compare:CC_NZ
1822          (plus:GPI (ASHIFT:GPI 
1823                     (match_operand:GPI 1 "register_operand" "r")
1824                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1825                    (match_operand:GPI 3 "register_operand" "r"))
1826          (const_int 0)))
1827    (set (match_operand:GPI 0 "register_operand" "=r")
1828         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1829                   (match_dup 3)))]
1830   ""
1831   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1832   [(set_attr "type" "alus_shift_imm")]
1835 (define_insn "*subs_shift_imm_<mode>"
1836   [(set (reg:CC_NZ CC_REGNUM)
1837         (compare:CC_NZ
1838          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1839                     (ASHIFT:GPI
1840                      (match_operand:GPI 2 "register_operand" "r")
1841                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1842          (const_int 0)))
1843    (set (match_operand:GPI 0 "register_operand" "=r")
1844         (minus:GPI (match_dup 1)
1845                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1846   ""
1847   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1848   [(set_attr "type" "alus_shift_imm")]
1851 (define_insn "*adds_mul_imm_<mode>"
1852   [(set (reg:CC_NZ CC_REGNUM)
1853         (compare:CC_NZ
1854          (plus:GPI (mult:GPI
1855                     (match_operand:GPI 1 "register_operand" "r")
1856                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1857                    (match_operand:GPI 3 "register_operand" "r"))
1858          (const_int 0)))
1859    (set (match_operand:GPI 0 "register_operand" "=r")
1860         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1861                   (match_dup 3)))]
1862   ""
1863   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1864   [(set_attr "type" "alus_shift_imm")]
1867 (define_insn "*subs_mul_imm_<mode>"
1868   [(set (reg:CC_NZ CC_REGNUM)
1869         (compare:CC_NZ
1870          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1871                     (mult:GPI
1872                      (match_operand:GPI 2 "register_operand" "r")
1873                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1874          (const_int 0)))
1875    (set (match_operand:GPI 0 "register_operand" "=r")
1876         (minus:GPI (match_dup 1)
1877                    (mult:GPI (match_dup 2) (match_dup 3))))]
1878   ""
1879   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1880   [(set_attr "type" "alus_shift_imm")]
1883 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1884   [(set (reg:CC_NZ CC_REGNUM)
1885         (compare:CC_NZ
1886          (plus:GPI
1887           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1888           (match_operand:GPI 2 "register_operand" "r"))
1889         (const_int 0)))
1890    (set (match_operand:GPI 0 "register_operand" "=r")
1891         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1892   ""
1893   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1894   [(set_attr "type" "alus_ext")]
1897 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1898   [(set (reg:CC_NZ CC_REGNUM)
1899         (compare:CC_NZ
1900          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1901                     (ANY_EXTEND:GPI
1902                      (match_operand:ALLX 2 "register_operand" "r")))
1903         (const_int 0)))
1904    (set (match_operand:GPI 0 "register_operand" "=r")
1905         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1906   ""
1907   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1908   [(set_attr "type" "alus_ext")]
1911 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1912   [(set (reg:CC_NZ CC_REGNUM)
1913         (compare:CC_NZ
1914          (plus:GPI (ashift:GPI 
1915                     (ANY_EXTEND:GPI 
1916                      (match_operand:ALLX 1 "register_operand" "r"))
1917                     (match_operand 2 "aarch64_imm3" "Ui3"))
1918                    (match_operand:GPI 3 "register_operand" "r"))
1919          (const_int 0)))
1920    (set (match_operand:GPI 0 "register_operand" "=rk")
1921         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1922                               (match_dup 2))
1923                   (match_dup 3)))]
1924   ""
1925   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1926   [(set_attr "type" "alus_ext")]
1929 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1930   [(set (reg:CC_NZ CC_REGNUM)
1931         (compare:CC_NZ
1932          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1933                     (ashift:GPI 
1934                      (ANY_EXTEND:GPI
1935                       (match_operand:ALLX 2 "register_operand" "r"))
1936                      (match_operand 3 "aarch64_imm3" "Ui3")))
1937          (const_int 0)))
1938    (set (match_operand:GPI 0 "register_operand" "=rk")
1939         (minus:GPI (match_dup 1)
1940                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1941                                (match_dup 3))))]
1942   ""
1943   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1944   [(set_attr "type" "alus_ext")]
1947 (define_insn "*adds_<optab><mode>_multp2"
1948   [(set (reg:CC_NZ CC_REGNUM)
1949         (compare:CC_NZ
1950          (plus:GPI (ANY_EXTRACT:GPI
1951                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1952                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1953                     (match_operand 3 "const_int_operand" "n")
1954                     (const_int 0))
1955                    (match_operand:GPI 4 "register_operand" "r"))
1956         (const_int 0)))
1957    (set (match_operand:GPI 0 "register_operand" "=r")
1958         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1959                                    (match_dup 3)
1960                                    (const_int 0))
1961                   (match_dup 4)))]
1962   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1963   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1964   [(set_attr "type" "alus_ext")]
1967 (define_insn "*subs_<optab><mode>_multp2"
1968   [(set (reg:CC_NZ CC_REGNUM)
1969         (compare:CC_NZ
1970          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1971                     (ANY_EXTRACT:GPI
1972                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1973                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1974                      (match_operand 3 "const_int_operand" "n")
1975                      (const_int 0)))
1976         (const_int 0)))
1977    (set (match_operand:GPI 0 "register_operand" "=r")
1978         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1979                                   (mult:GPI (match_dup 1) (match_dup 2))
1980                                   (match_dup 3)
1981                                   (const_int 0))))]
1982   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1983   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1984   [(set_attr "type" "alus_ext")]
1987 (define_insn "*add<mode>3nr_compare0"
1988   [(set (reg:CC_NZ CC_REGNUM)
1989         (compare:CC_NZ
1990          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1991                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1992          (const_int 0)))]
1993   ""
1994   "@
1995   cmn\\t%<w>0, %<w>1
1996   cmn\\t%<w>0, %1
1997   cmp\\t%<w>0, #%n1"
1998   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2001 (define_insn "*compare_neg<mode>"
2002   [(set (reg:CC_Z CC_REGNUM)
2003         (compare:CC_Z
2004          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2005          (match_operand:GPI 1 "register_operand" "r")))]
2006   ""
2007   "cmn\\t%<w>1, %<w>0"
2008   [(set_attr "type" "alus_sreg")]
2011 (define_insn "*add_<shift>_<mode>"
2012   [(set (match_operand:GPI 0 "register_operand" "=r")
2013         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2014                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2015                   (match_operand:GPI 3 "register_operand" "r")))]
2016   ""
2017   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2018   [(set_attr "type" "alu_shift_imm")]
2021 ;; zero_extend version of above
2022 (define_insn "*add_<shift>_si_uxtw"
2023   [(set (match_operand:DI 0 "register_operand" "=r")
2024         (zero_extend:DI
2025          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2026                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2027                   (match_operand:SI 3 "register_operand" "r"))))]
2028   ""
2029   "add\\t%w0, %w3, %w1, <shift> %2"
2030   [(set_attr "type" "alu_shift_imm")]
2033 (define_insn "*add_mul_imm_<mode>"
2034   [(set (match_operand:GPI 0 "register_operand" "=r")
2035         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2036                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2037                   (match_operand:GPI 3 "register_operand" "r")))]
2038   ""
2039   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2040   [(set_attr "type" "alu_shift_imm")]
2043 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2044   [(set (match_operand:GPI 0 "register_operand" "=rk")
2045         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2046                   (match_operand:GPI 2 "register_operand" "r")))]
2047   ""
2048   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2049   [(set_attr "type" "alu_ext")]
2052 ;; zero_extend version of above
2053 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2054   [(set (match_operand:DI 0 "register_operand" "=rk")
2055         (zero_extend:DI
2056          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2057                   (match_operand:GPI 2 "register_operand" "r"))))]
2058   ""
2059   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2060   [(set_attr "type" "alu_ext")]
2063 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2064   [(set (match_operand:GPI 0 "register_operand" "=rk")
2065         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2066                                (match_operand:ALLX 1 "register_operand" "r"))
2067                               (match_operand 2 "aarch64_imm3" "Ui3"))
2068                   (match_operand:GPI 3 "register_operand" "r")))]
2069   ""
2070   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2071   [(set_attr "type" "alu_ext")]
2074 ;; zero_extend version of above
2075 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2076   [(set (match_operand:DI 0 "register_operand" "=rk")
2077         (zero_extend:DI
2078          (plus:SI (ashift:SI (ANY_EXTEND:SI
2079                               (match_operand:SHORT 1 "register_operand" "r"))
2080                              (match_operand 2 "aarch64_imm3" "Ui3"))
2081                   (match_operand:SI 3 "register_operand" "r"))))]
2082   ""
2083   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2084   [(set_attr "type" "alu_ext")]
2087 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2088   [(set (match_operand:GPI 0 "register_operand" "=rk")
2089         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2090                              (match_operand:ALLX 1 "register_operand" "r"))
2091                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2092                   (match_operand:GPI 3 "register_operand" "r")))]
2093   ""
2094   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2095   [(set_attr "type" "alu_ext")]
2098 ;; zero_extend version of above
2099 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2100   [(set (match_operand:DI 0 "register_operand" "=rk")
2101         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2102                              (match_operand:SHORT 1 "register_operand" "r"))
2103                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2104                   (match_operand:SI 3 "register_operand" "r"))))]
2105   ""
2106   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2107   [(set_attr "type" "alu_ext")]
2110 (define_insn "*add_<optab><mode>_multp2"
2111   [(set (match_operand:GPI 0 "register_operand" "=rk")
2112         (plus:GPI (ANY_EXTRACT:GPI
2113                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2114                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2115                    (match_operand 3 "const_int_operand" "n")
2116                    (const_int 0))
2117                   (match_operand:GPI 4 "register_operand" "r")))]
2118   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2119   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2120   [(set_attr "type" "alu_ext")]
2123 ;; zero_extend version of above
2124 (define_insn "*add_<optab>si_multp2_uxtw"
2125   [(set (match_operand:DI 0 "register_operand" "=rk")
2126         (zero_extend:DI
2127          (plus:SI (ANY_EXTRACT:SI
2128                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2129                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2130                    (match_operand 3 "const_int_operand" "n")
2131                    (const_int 0))
2132                   (match_operand:SI 4 "register_operand" "r"))))]
2133   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2134   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2135   [(set_attr "type" "alu_ext")]
2138 (define_expand "add<mode>3_carryin"
2139   [(set (match_operand:GPI 0 "register_operand")
2140         (plus:GPI
2141           (plus:GPI
2142             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2143             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2144           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2145    ""
2146    ""
2149 ;; Note that add with carry with two zero inputs is matched by cset,
2150 ;; and that add with carry with one zero input is matched by cinc.
2152 (define_insn "*add<mode>3_carryin"
2153   [(set (match_operand:GPI 0 "register_operand" "=r")
2154         (plus:GPI
2155           (plus:GPI
2156             (match_operand:GPI 3 "aarch64_carry_operation" "")
2157             (match_operand:GPI 1 "register_operand" "r"))
2158           (match_operand:GPI 2 "register_operand" "r")))]
2159    ""
2160    "adc\\t%<w>0, %<w>1, %<w>2"
2161   [(set_attr "type" "adc_reg")]
2164 ;; zero_extend version of above
2165 (define_insn "*addsi3_carryin_uxtw"
2166   [(set (match_operand:DI 0 "register_operand" "=r")
2167         (zero_extend:DI
2168           (plus:SI
2169             (plus:SI
2170               (match_operand:SI 3 "aarch64_carry_operation" "")
2171               (match_operand:SI 1 "register_operand" "r"))
2172             (match_operand:SI 2 "register_operand" "r"))))]
2173    ""
2174    "adc\\t%w0, %w1, %w2"
2175   [(set_attr "type" "adc_reg")]
2178 (define_insn "*add_uxt<mode>_shift2"
2179   [(set (match_operand:GPI 0 "register_operand" "=rk")
2180         (plus:GPI (and:GPI
2181                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2182                                (match_operand 2 "aarch64_imm3" "Ui3"))
2183                    (match_operand 3 "const_int_operand" "n"))
2184                   (match_operand:GPI 4 "register_operand" "r")))]
2185   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2186   "*
2187   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2188                                            INTVAL (operands[3])));
2189   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2190   [(set_attr "type" "alu_ext")]
2193 ;; zero_extend version of above
2194 (define_insn "*add_uxtsi_shift2_uxtw"
2195   [(set (match_operand:DI 0 "register_operand" "=rk")
2196         (zero_extend:DI
2197          (plus:SI (and:SI
2198                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2199                               (match_operand 2 "aarch64_imm3" "Ui3"))
2200                    (match_operand 3 "const_int_operand" "n"))
2201                   (match_operand:SI 4 "register_operand" "r"))))]
2202   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2203   "*
2204   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2205                                            INTVAL (operands[3])));
2206   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2207   [(set_attr "type" "alu_ext")]
2210 (define_insn "*add_uxt<mode>_multp2"
2211   [(set (match_operand:GPI 0 "register_operand" "=rk")
2212         (plus:GPI (and:GPI
2213                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2214                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2215                    (match_operand 3 "const_int_operand" "n"))
2216                   (match_operand:GPI 4 "register_operand" "r")))]
2217   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2218   "*
2219   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2220                                            INTVAL (operands[3])));
2221   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2222   [(set_attr "type" "alu_ext")]
2225 ;; zero_extend version of above
2226 (define_insn "*add_uxtsi_multp2_uxtw"
2227   [(set (match_operand:DI 0 "register_operand" "=rk")
2228         (zero_extend:DI
2229          (plus:SI (and:SI
2230                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2231                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2232                    (match_operand 3 "const_int_operand" "n"))
2233                   (match_operand:SI 4 "register_operand" "r"))))]
2234   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2235   "*
2236   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2237                                            INTVAL (operands[3])));
2238   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2239   [(set_attr "type" "alu_ext")]
2242 (define_insn "subsi3"
2243   [(set (match_operand:SI 0 "register_operand" "=rk")
2244         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2245                   (match_operand:SI 2 "register_operand" "r")))]
2246   ""
2247   "sub\\t%w0, %w1, %w2"
2248   [(set_attr "type" "alu_sreg")]
2251 ;; zero_extend version of above
2252 (define_insn "*subsi3_uxtw"
2253   [(set (match_operand:DI 0 "register_operand" "=rk")
2254         (zero_extend:DI
2255          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2256                    (match_operand:SI 2 "register_operand" "r"))))]
2257   ""
2258   "sub\\t%w0, %w1, %w2"
2259   [(set_attr "type" "alu_sreg")]
2262 (define_insn "subdi3"
2263   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2264         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2265                   (match_operand:DI 2 "register_operand" "r,w")))]
2266   ""
2267   "@
2268    sub\\t%x0, %x1, %x2
2269    sub\\t%d0, %d1, %d2"
2270   [(set_attr "type" "alu_sreg, neon_sub")
2271    (set_attr "simd" "*,yes")]
2274 (define_expand "subti3"
2275   [(set (match_operand:TI 0 "register_operand" "")
2276         (minus:TI (match_operand:TI 1 "register_operand" "")
2277                   (match_operand:TI 2 "register_operand" "")))]
2278   ""
2280   rtx low = gen_reg_rtx (DImode);
2281   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2282                                   gen_lowpart (DImode, operands[2])));
2284   rtx high = gen_reg_rtx (DImode);
2285   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2286                                  gen_highpart (DImode, operands[2])));
2288   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2289   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2290   DONE;
2293 (define_insn "*sub<mode>3_compare0"
2294   [(set (reg:CC_NZ CC_REGNUM)
2295         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2296                                   (match_operand:GPI 2 "register_operand" "r"))
2297                        (const_int 0)))
2298    (set (match_operand:GPI 0 "register_operand" "=r")
2299         (minus:GPI (match_dup 1) (match_dup 2)))]
2300   ""
2301   "subs\\t%<w>0, %<w>1, %<w>2"
2302   [(set_attr "type" "alus_sreg")]
2305 ;; zero_extend version of above
2306 (define_insn "*subsi3_compare0_uxtw"
2307   [(set (reg:CC_NZ CC_REGNUM)
2308         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2309                                  (match_operand:SI 2 "register_operand" "r"))
2310                        (const_int 0)))
2311    (set (match_operand:DI 0 "register_operand" "=r")
2312         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2313   ""
2314   "subs\\t%w0, %w1, %w2"
2315   [(set_attr "type" "alus_sreg")]
2318 (define_insn "sub<mode>3_compare1"
2319   [(set (reg:CC CC_REGNUM)
2320         (compare:CC
2321           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2322           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2323    (set (match_operand:GPI 0 "register_operand" "=r")
2324         (minus:GPI (match_dup 1) (match_dup 2)))]
2325   ""
2326   "subs\\t%<w>0, %<w>1, %<w>2"
2327   [(set_attr "type" "alus_sreg")]
2330 (define_insn "*sub_<shift>_<mode>"
2331   [(set (match_operand:GPI 0 "register_operand" "=r")
2332         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2333                    (ASHIFT:GPI
2334                     (match_operand:GPI 1 "register_operand" "r")
2335                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2336   ""
2337   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2338   [(set_attr "type" "alu_shift_imm")]
2341 ;; zero_extend version of above
2342 (define_insn "*sub_<shift>_si_uxtw"
2343   [(set (match_operand:DI 0 "register_operand" "=r")
2344         (zero_extend:DI
2345          (minus:SI (match_operand:SI 3 "register_operand" "r")
2346                    (ASHIFT:SI
2347                     (match_operand:SI 1 "register_operand" "r")
2348                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2349   ""
2350   "sub\\t%w0, %w3, %w1, <shift> %2"
2351   [(set_attr "type" "alu_shift_imm")]
2354 (define_insn "*sub_mul_imm_<mode>"
2355   [(set (match_operand:GPI 0 "register_operand" "=r")
2356         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2357                    (mult:GPI
2358                     (match_operand:GPI 1 "register_operand" "r")
2359                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2360   ""
2361   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2362   [(set_attr "type" "alu_shift_imm")]
2365 ;; zero_extend version of above
2366 (define_insn "*sub_mul_imm_si_uxtw"
2367   [(set (match_operand:DI 0 "register_operand" "=r")
2368         (zero_extend:DI
2369          (minus:SI (match_operand:SI 3 "register_operand" "r")
2370                    (mult:SI
2371                     (match_operand:SI 1 "register_operand" "r")
2372                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2373   ""
2374   "sub\\t%w0, %w3, %w1, lsl %p2"
2375   [(set_attr "type" "alu_shift_imm")]
2378 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2379   [(set (match_operand:GPI 0 "register_operand" "=rk")
2380         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2381                    (ANY_EXTEND:GPI
2382                     (match_operand:ALLX 2 "register_operand" "r"))))]
2383   ""
2384   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2385   [(set_attr "type" "alu_ext")]
2388 ;; zero_extend version of above
2389 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2390   [(set (match_operand:DI 0 "register_operand" "=rk")
2391         (zero_extend:DI
2392          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2393                    (ANY_EXTEND:SI
2394                     (match_operand:SHORT 2 "register_operand" "r")))))]
2395   ""
2396   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2397   [(set_attr "type" "alu_ext")]
2400 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2401   [(set (match_operand:GPI 0 "register_operand" "=rk")
2402         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2403                    (ashift:GPI (ANY_EXTEND:GPI
2404                                 (match_operand:ALLX 2 "register_operand" "r"))
2405                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2406   ""
2407   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2408   [(set_attr "type" "alu_ext")]
2411 ;; zero_extend version of above
2412 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2413   [(set (match_operand:DI 0 "register_operand" "=rk")
2414         (zero_extend:DI
2415          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2416                    (ashift:SI (ANY_EXTEND:SI
2417                                (match_operand:SHORT 2 "register_operand" "r"))
2418                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2419   ""
2420   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2421   [(set_attr "type" "alu_ext")]
2424 (define_insn "*sub_<optab><mode>_multp2"
2425   [(set (match_operand:GPI 0 "register_operand" "=rk")
2426         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2427                    (ANY_EXTRACT:GPI
2428                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2429                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2430                     (match_operand 3 "const_int_operand" "n")
2431                     (const_int 0))))]
2432   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2433   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2434   [(set_attr "type" "alu_ext")]
2437 ;; zero_extend version of above
2438 (define_insn "*sub_<optab>si_multp2_uxtw"
2439   [(set (match_operand:DI 0 "register_operand" "=rk")
2440         (zero_extend:DI
2441          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2442                    (ANY_EXTRACT:SI
2443                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2444                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2445                     (match_operand 3 "const_int_operand" "n")
2446                     (const_int 0)))))]
2447   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2448   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2449   [(set_attr "type" "alu_ext")]
2452 ;; The hardware description is op1 + ~op2 + C.
2453 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2454 ;;                           = op1 - op2 - 1 + 1 - !C
2455 ;;                           = op1 - op2 - !C.
2456 ;; We describe the latter.
2458 (define_insn "*sub<mode>3_carryin0"
2459   [(set (match_operand:GPI 0 "register_operand" "=r")
2460         (minus:GPI
2461           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2462           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2463    ""
2464    "sbc\\t%<w>0, %<w>1, <w>zr"
2465   [(set_attr "type" "adc_reg")]
2468 ;; zero_extend version of the above
2469 (define_insn "*subsi3_carryin_uxtw"
2470   [(set (match_operand:DI 0 "register_operand" "=r")
2471         (zero_extend:DI
2472           (minus:SI
2473             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2474             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2475    ""
2476    "sbc\\t%w0, %w1, wzr"
2477   [(set_attr "type" "adc_reg")]
2480 (define_expand "sub<mode>3_carryin"
2481   [(set (match_operand:GPI 0 "register_operand")
2482         (minus:GPI
2483           (minus:GPI
2484             (match_operand:GPI 1 "aarch64_reg_or_zero")
2485             (match_operand:GPI 2 "register_operand"))
2486           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2487    ""
2488    ""
2491 (define_insn "*sub<mode>3_carryin"
2492   [(set (match_operand:GPI 0 "register_operand" "=r")
2493         (minus:GPI
2494           (minus:GPI
2495             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2496             (match_operand:GPI 2 "register_operand" "r"))
2497           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2499    ""
2500    "sbc\\t%<w>0, %<w>1, %<w>2"
2501   [(set_attr "type" "adc_reg")]
2504 ;; zero_extend version of the above
2505 (define_insn "*subsi3_carryin_uxtw"
2506   [(set (match_operand:DI 0 "register_operand" "=r")
2507         (zero_extend:DI
2508           (minus:SI
2509             (minus:SI
2510               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2511               (match_operand:SI 2 "register_operand" "r"))
2512             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2514    ""
2515    "sbc\\t%w0, %w1, %w2"
2516   [(set_attr "type" "adc_reg")]
2519 (define_insn "*sub<mode>3_carryin_alt"
2520   [(set (match_operand:GPI 0 "register_operand" "=r")
2521         (minus:GPI
2522           (minus:GPI
2523             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2524             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2525           (match_operand:GPI 2 "register_operand" "r")))]
2526    ""
2527    "sbc\\t%<w>0, %<w>1, %<w>2"
2528   [(set_attr "type" "adc_reg")]
2531 ;; zero_extend version of the above
2532 (define_insn "*subsi3_carryin_alt_uxtw"
2533   [(set (match_operand:DI 0 "register_operand" "=r")
2534         (zero_extend:DI
2535           (minus:SI
2536             (minus:SI
2537               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2538               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2539             (match_operand:SI 2 "register_operand" "r"))))]
2540    ""
2541    "sbc\\t%w0, %w1, %w2"
2542   [(set_attr "type" "adc_reg")]
2545 (define_insn "*sub_uxt<mode>_shift2"
2546   [(set (match_operand:GPI 0 "register_operand" "=rk")
2547         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2548                    (and:GPI
2549                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2550                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2551                     (match_operand 3 "const_int_operand" "n"))))]
2552   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2553   "*
2554   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2555                                            INTVAL (operands[3])));
2556   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2557   [(set_attr "type" "alu_ext")]
2560 ;; zero_extend version of above
2561 (define_insn "*sub_uxtsi_shift2_uxtw"
2562   [(set (match_operand:DI 0 "register_operand" "=rk")
2563         (zero_extend:DI
2564          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2565                    (and:SI
2566                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2567                                (match_operand 2 "aarch64_imm3" "Ui3"))
2568                     (match_operand 3 "const_int_operand" "n")))))]
2569   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2570   "*
2571   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2572                                            INTVAL (operands[3])));
2573   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2574   [(set_attr "type" "alu_ext")]
2577 (define_insn "*sub_uxt<mode>_multp2"
2578   [(set (match_operand:GPI 0 "register_operand" "=rk")
2579         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2580                    (and:GPI
2581                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2582                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2583                     (match_operand 3 "const_int_operand" "n"))))]
2584   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2585   "*
2586   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2587                                            INTVAL (operands[3])));
2588   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2589   [(set_attr "type" "alu_ext")]
2592 ;; zero_extend version of above
2593 (define_insn "*sub_uxtsi_multp2_uxtw"
2594   [(set (match_operand:DI 0 "register_operand" "=rk")
2595         (zero_extend:DI
2596          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2597                    (and:SI
2598                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2599                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2600                     (match_operand 3 "const_int_operand" "n")))))]
2601   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2602   "*
2603   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2604                                            INTVAL (operands[3])));
2605   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2606   [(set_attr "type" "alu_ext")]
2609 (define_expand "abs<mode>2"
2610   [(match_operand:GPI 0 "register_operand" "")
2611    (match_operand:GPI 1 "register_operand" "")]
2612   ""
2613   {
2614     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2615     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2616     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2617     DONE;
2618   }
2621 (define_insn "neg<mode>2"
2622   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2623         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2624   ""
2625   "@
2626    neg\\t%<w>0, %<w>1
2627    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2628   [(set_attr "type" "alu_sreg, neon_neg<q>")
2629    (set_attr "simd" "*,yes")]
2632 ;; zero_extend version of above
2633 (define_insn "*negsi2_uxtw"
2634   [(set (match_operand:DI 0 "register_operand" "=r")
2635         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2636   ""
2637   "neg\\t%w0, %w1"
2638   [(set_attr "type" "alu_sreg")]
2641 (define_insn "*ngc<mode>"
2642   [(set (match_operand:GPI 0 "register_operand" "=r")
2643         (minus:GPI
2644           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2645           (match_operand:GPI 1 "register_operand" "r")))]
2646   ""
2647   "ngc\\t%<w>0, %<w>1"
2648   [(set_attr "type" "adc_reg")]
2651 (define_insn "*ngcsi_uxtw"
2652   [(set (match_operand:DI 0 "register_operand" "=r")
2653         (zero_extend:DI
2654           (minus:SI
2655             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2656             (match_operand:SI 1 "register_operand" "r"))))]
2657   ""
2658   "ngc\\t%w0, %w1"
2659   [(set_attr "type" "adc_reg")]
2662 (define_insn "neg<mode>2_compare0"
2663   [(set (reg:CC_NZ CC_REGNUM)
2664         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2665                        (const_int 0)))
2666    (set (match_operand:GPI 0 "register_operand" "=r")
2667         (neg:GPI (match_dup 1)))]
2668   ""
2669   "negs\\t%<w>0, %<w>1"
2670   [(set_attr "type" "alus_sreg")]
2673 ;; zero_extend version of above
2674 (define_insn "*negsi2_compare0_uxtw"
2675   [(set (reg:CC_NZ CC_REGNUM)
2676         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2677                        (const_int 0)))
2678    (set (match_operand:DI 0 "register_operand" "=r")
2679         (zero_extend:DI (neg:SI (match_dup 1))))]
2680   ""
2681   "negs\\t%w0, %w1"
2682   [(set_attr "type" "alus_sreg")]
2685 (define_insn "*neg_<shift><mode>3_compare0"
2686   [(set (reg:CC_NZ CC_REGNUM)
2687         (compare:CC_NZ
2688          (neg:GPI (ASHIFT:GPI
2689                    (match_operand:GPI 1 "register_operand" "r")
2690                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2691          (const_int 0)))
2692    (set (match_operand:GPI 0 "register_operand" "=r")
2693         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2694   ""
2695   "negs\\t%<w>0, %<w>1, <shift> %2"
2696   [(set_attr "type" "alus_shift_imm")]
2699 (define_insn "*neg_<shift>_<mode>2"
2700   [(set (match_operand:GPI 0 "register_operand" "=r")
2701         (neg:GPI (ASHIFT:GPI
2702                   (match_operand:GPI 1 "register_operand" "r")
2703                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2704   ""
2705   "neg\\t%<w>0, %<w>1, <shift> %2"
2706   [(set_attr "type" "alu_shift_imm")]
2709 ;; zero_extend version of above
2710 (define_insn "*neg_<shift>_si2_uxtw"
2711   [(set (match_operand:DI 0 "register_operand" "=r")
2712         (zero_extend:DI
2713          (neg:SI (ASHIFT:SI
2714                   (match_operand:SI 1 "register_operand" "r")
2715                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2716   ""
2717   "neg\\t%w0, %w1, <shift> %2"
2718   [(set_attr "type" "alu_shift_imm")]
2721 (define_insn "*neg_mul_imm_<mode>2"
2722   [(set (match_operand:GPI 0 "register_operand" "=r")
2723         (neg:GPI (mult:GPI
2724                   (match_operand:GPI 1 "register_operand" "r")
2725                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2726   ""
2727   "neg\\t%<w>0, %<w>1, lsl %p2"
2728   [(set_attr "type" "alu_shift_imm")]
2731 ;; zero_extend version of above
2732 (define_insn "*neg_mul_imm_si2_uxtw"
2733   [(set (match_operand:DI 0 "register_operand" "=r")
2734         (zero_extend:DI
2735          (neg:SI (mult:SI
2736                   (match_operand:SI 1 "register_operand" "r")
2737                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2738   ""
2739   "neg\\t%w0, %w1, lsl %p2"
2740   [(set_attr "type" "alu_shift_imm")]
2743 (define_insn "mul<mode>3"
2744   [(set (match_operand:GPI 0 "register_operand" "=r")
2745         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2746                   (match_operand:GPI 2 "register_operand" "r")))]
2747   ""
2748   "mul\\t%<w>0, %<w>1, %<w>2"
2749   [(set_attr "type" "mul")]
2752 ;; zero_extend version of above
2753 (define_insn "*mulsi3_uxtw"
2754   [(set (match_operand:DI 0 "register_operand" "=r")
2755         (zero_extend:DI
2756          (mult:SI (match_operand:SI 1 "register_operand" "r")
2757                   (match_operand:SI 2 "register_operand" "r"))))]
2758   ""
2759   "mul\\t%w0, %w1, %w2"
2760   [(set_attr "type" "mul")]
2763 (define_insn "madd<mode>"
2764   [(set (match_operand:GPI 0 "register_operand" "=r")
2765         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2766                             (match_operand:GPI 2 "register_operand" "r"))
2767                   (match_operand:GPI 3 "register_operand" "r")))]
2768   ""
2769   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2770   [(set_attr "type" "mla")]
2773 ;; zero_extend version of above
2774 (define_insn "*maddsi_uxtw"
2775   [(set (match_operand:DI 0 "register_operand" "=r")
2776         (zero_extend:DI
2777          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2778                            (match_operand:SI 2 "register_operand" "r"))
2779                   (match_operand:SI 3 "register_operand" "r"))))]
2780   ""
2781   "madd\\t%w0, %w1, %w2, %w3"
2782   [(set_attr "type" "mla")]
2785 (define_insn "*msub<mode>"
2786   [(set (match_operand:GPI 0 "register_operand" "=r")
2787         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2788                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2789                              (match_operand:GPI 2 "register_operand" "r"))))]
2791   ""
2792   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2793   [(set_attr "type" "mla")]
2796 ;; zero_extend version of above
2797 (define_insn "*msubsi_uxtw"
2798   [(set (match_operand:DI 0 "register_operand" "=r")
2799         (zero_extend:DI
2800          (minus:SI (match_operand:SI 3 "register_operand" "r")
2801                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2802                             (match_operand:SI 2 "register_operand" "r")))))]
2804   ""
2805   "msub\\t%w0, %w1, %w2, %w3"
2806   [(set_attr "type" "mla")]
2809 (define_insn "*mul<mode>_neg"
2810   [(set (match_operand:GPI 0 "register_operand" "=r")
2811         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2812                   (match_operand:GPI 2 "register_operand" "r")))]
2814   ""
2815   "mneg\\t%<w>0, %<w>1, %<w>2"
2816   [(set_attr "type" "mul")]
2819 ;; zero_extend version of above
2820 (define_insn "*mulsi_neg_uxtw"
2821   [(set (match_operand:DI 0 "register_operand" "=r")
2822         (zero_extend:DI
2823          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2824                   (match_operand:SI 2 "register_operand" "r"))))]
2826   ""
2827   "mneg\\t%w0, %w1, %w2"
2828   [(set_attr "type" "mul")]
2831 (define_insn "<su_optab>mulsidi3"
2832   [(set (match_operand:DI 0 "register_operand" "=r")
2833         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2834                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2835   ""
2836   "<su>mull\\t%0, %w1, %w2"
2837   [(set_attr "type" "<su>mull")]
2840 (define_insn "<su_optab>maddsidi4"
2841   [(set (match_operand:DI 0 "register_operand" "=r")
2842         (plus:DI (mult:DI
2843                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2844                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2845                  (match_operand:DI 3 "register_operand" "r")))]
2846   ""
2847   "<su>maddl\\t%0, %w1, %w2, %3"
2848   [(set_attr "type" "<su>mlal")]
2851 (define_insn "<su_optab>msubsidi4"
2852   [(set (match_operand:DI 0 "register_operand" "=r")
2853         (minus:DI
2854          (match_operand:DI 3 "register_operand" "r")
2855          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2856                   (ANY_EXTEND:DI
2857                    (match_operand:SI 2 "register_operand" "r")))))]
2858   ""
2859   "<su>msubl\\t%0, %w1, %w2, %3"
2860   [(set_attr "type" "<su>mlal")]
2863 (define_insn "*<su_optab>mulsidi_neg"
2864   [(set (match_operand:DI 0 "register_operand" "=r")
2865         (mult:DI (neg:DI
2866                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2867                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2868   ""
2869   "<su>mnegl\\t%0, %w1, %w2"
2870   [(set_attr "type" "<su>mull")]
2873 (define_expand "<su_optab>mulditi3"
2874   [(set (match_operand:TI 0 "register_operand")
2875         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2876                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2877   ""
2879   rtx low = gen_reg_rtx (DImode);
2880   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2882   rtx high = gen_reg_rtx (DImode);
2883   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2885   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2886   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2887   DONE;
2890 ;; The default expansion of multi3 using umuldi3_highpart will perform
2891 ;; the additions in an order that fails to combine into two madd insns.
2892 (define_expand "multi3"
2893   [(set (match_operand:TI 0 "register_operand")
2894         (mult:TI (match_operand:TI 1 "register_operand")
2895                  (match_operand:TI 2 "register_operand")))]
2896   ""
2898   rtx l0 = gen_reg_rtx (DImode);
2899   rtx l1 = gen_lowpart (DImode, operands[1]);
2900   rtx l2 = gen_lowpart (DImode, operands[2]);
2901   rtx h0 = gen_reg_rtx (DImode);
2902   rtx h1 = gen_highpart (DImode, operands[1]);
2903   rtx h2 = gen_highpart (DImode, operands[2]);
2905   emit_insn (gen_muldi3 (l0, l1, l2));
2906   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2907   emit_insn (gen_madddi (h0, h1, l2, h0));
2908   emit_insn (gen_madddi (h0, l1, h2, h0));
2910   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2911   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2912   DONE;
2915 (define_insn "<su>muldi3_highpart"
2916   [(set (match_operand:DI 0 "register_operand" "=r")
2917         (truncate:DI
2918          (lshiftrt:TI
2919           (mult:TI
2920            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2921            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2922           (const_int 64))))]
2923   ""
2924   "<su>mulh\\t%0, %1, %2"
2925   [(set_attr "type" "<su>mull")]
2928 (define_insn "<su_optab>div<mode>3"
2929   [(set (match_operand:GPI 0 "register_operand" "=r")
2930         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2931                      (match_operand:GPI 2 "register_operand" "r")))]
2932   ""
2933   "<su>div\\t%<w>0, %<w>1, %<w>2"
2934   [(set_attr "type" "<su>div")]
2937 ;; zero_extend version of above
2938 (define_insn "*<su_optab>divsi3_uxtw"
2939   [(set (match_operand:DI 0 "register_operand" "=r")
2940         (zero_extend:DI
2941          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2942                      (match_operand:SI 2 "register_operand" "r"))))]
2943   ""
2944   "<su>div\\t%w0, %w1, %w2"
2945   [(set_attr "type" "<su>div")]
2948 ;; -------------------------------------------------------------------
2949 ;; Comparison insns
2950 ;; -------------------------------------------------------------------
2952 (define_insn "cmp<mode>"
2953   [(set (reg:CC CC_REGNUM)
2954         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2955                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2956   ""
2957   "@
2958    cmp\\t%<w>0, %<w>1
2959    cmp\\t%<w>0, %1
2960    cmn\\t%<w>0, #%n1"
2961   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2964 (define_insn "fcmp<mode>"
2965   [(set (reg:CCFP CC_REGNUM)
2966         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2967                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2968    "TARGET_FLOAT"
2969    "@
2970     fcmp\\t%<s>0, #0.0
2971     fcmp\\t%<s>0, %<s>1"
2972   [(set_attr "type" "fcmp<s>")]
2975 (define_insn "fcmpe<mode>"
2976   [(set (reg:CCFPE CC_REGNUM)
2977         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2978                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2979    "TARGET_FLOAT"
2980    "@
2981     fcmpe\\t%<s>0, #0.0
2982     fcmpe\\t%<s>0, %<s>1"
2983   [(set_attr "type" "fcmp<s>")]
2986 (define_insn "*cmp_swp_<shift>_reg<mode>"
2987   [(set (reg:CC_SWP CC_REGNUM)
2988         (compare:CC_SWP (ASHIFT:GPI
2989                          (match_operand:GPI 0 "register_operand" "r")
2990                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2991                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2992   ""
2993   "cmp\\t%<w>2, %<w>0, <shift> %1"
2994   [(set_attr "type" "alus_shift_imm")]
2997 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2998   [(set (reg:CC_SWP CC_REGNUM)
2999         (compare:CC_SWP (ANY_EXTEND:GPI
3000                          (match_operand:ALLX 0 "register_operand" "r"))
3001                         (match_operand:GPI 1 "register_operand" "r")))]
3002   ""
3003   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3004   [(set_attr "type" "alus_ext")]
3007 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3008   [(set (reg:CC_SWP CC_REGNUM)
3009         (compare:CC_SWP (ashift:GPI
3010                          (ANY_EXTEND:GPI
3011                           (match_operand:ALLX 0 "register_operand" "r"))
3012                          (match_operand 1 "aarch64_imm3" "Ui3"))
3013         (match_operand:GPI 2 "register_operand" "r")))]
3014   ""
3015   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3016   [(set_attr "type" "alus_ext")]
3019 ;; -------------------------------------------------------------------
3020 ;; Store-flag and conditional select insns
3021 ;; -------------------------------------------------------------------
3023 (define_expand "cstore<mode>4"
3024   [(set (match_operand:SI 0 "register_operand" "")
3025         (match_operator:SI 1 "aarch64_comparison_operator"
3026          [(match_operand:GPI 2 "register_operand" "")
3027           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3028   ""
3029   "
3030   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3031                                       operands[3]);
3032   operands[3] = const0_rtx;
3033   "
3036 (define_expand "cstorecc4"
3037   [(set (match_operand:SI 0 "register_operand")
3038        (match_operator 1 "aarch64_comparison_operator_mode"
3039         [(match_operand 2 "cc_register")
3040          (match_operand 3 "const0_operand")]))]
3041   ""
3043   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3044   DONE;
3048 (define_expand "cstore<mode>4"
3049   [(set (match_operand:SI 0 "register_operand" "")
3050         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3051          [(match_operand:GPF 2 "register_operand" "")
3052           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3053   ""
3054   "
3055   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3056                                       operands[3]);
3057   operands[3] = const0_rtx;
3058   "
3061 (define_insn "aarch64_cstore<mode>"
3062   [(set (match_operand:ALLI 0 "register_operand" "=r")
3063         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3064          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3065   ""
3066   "cset\\t%<w>0, %m1"
3067   [(set_attr "type" "csel")]
3070 ;; For a 24-bit immediate CST we can optimize the compare for equality
3071 ;; and branch sequence from:
3072 ;;      mov     x0, #imm1
3073 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3074 ;;      cmp     x1, x0
3075 ;;      cset    x2, <ne,eq>
3076 ;; into the shorter:
3077 ;;      sub     x0, x1, #(CST & 0xfff000)
3078 ;;      subs    x0, x0, #(CST & 0x000fff)
3079 ;;      cset x2, <ne, eq>.
3080 (define_insn_and_split "*compare_cstore<mode>_insn"
3081   [(set (match_operand:GPI 0 "register_operand" "=r")
3082          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3083                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3084   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3085    && !aarch64_plus_operand (operands[2], <MODE>mode)
3086    && !reload_completed"
3087   "#"
3088   "&& true"
3089   [(const_int 0)]
3090   {
3091     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3092     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3093     rtx tmp = gen_reg_rtx (<MODE>mode);
3094     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3095     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3096     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3097     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3098     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3099     DONE;
3100   }
3101   [(set_attr "type" "csel")]
3104 ;; zero_extend version of the above
3105 (define_insn "*cstoresi_insn_uxtw"
3106   [(set (match_operand:DI 0 "register_operand" "=r")
3107         (zero_extend:DI
3108          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3109           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3110   ""
3111   "cset\\t%w0, %m1"
3112   [(set_attr "type" "csel")]
3115 (define_insn "cstore<mode>_neg"
3116   [(set (match_operand:ALLI 0 "register_operand" "=r")
3117         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3118                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3119   ""
3120   "csetm\\t%<w>0, %m1"
3121   [(set_attr "type" "csel")]
3124 ;; zero_extend version of the above
3125 (define_insn "*cstoresi_neg_uxtw"
3126   [(set (match_operand:DI 0 "register_operand" "=r")
3127         (zero_extend:DI
3128          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3129                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3130   ""
3131   "csetm\\t%w0, %m1"
3132   [(set_attr "type" "csel")]
3135 (define_expand "cmov<mode>6"
3136   [(set (match_operand:GPI 0 "register_operand" "")
3137         (if_then_else:GPI
3138          (match_operator 1 "aarch64_comparison_operator"
3139           [(match_operand:GPI 2 "register_operand" "")
3140            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3141          (match_operand:GPI 4 "register_operand" "")
3142          (match_operand:GPI 5 "register_operand" "")))]
3143   ""
3144   "
3145   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3146                                       operands[3]);
3147   operands[3] = const0_rtx;
3148   "
3151 (define_expand "cmov<mode>6"
3152   [(set (match_operand:GPF 0 "register_operand" "")
3153         (if_then_else:GPF
3154          (match_operator 1 "aarch64_comparison_operator"
3155           [(match_operand:GPF 2 "register_operand" "")
3156            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3157          (match_operand:GPF 4 "register_operand" "")
3158          (match_operand:GPF 5 "register_operand" "")))]
3159   ""
3160   "
3161   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3162                                       operands[3]);
3163   operands[3] = const0_rtx;
3164   "
3167 (define_insn "*cmov<mode>_insn"
3168   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3169         (if_then_else:ALLI
3170          (match_operator 1 "aarch64_comparison_operator"
3171           [(match_operand 2 "cc_register" "") (const_int 0)])
3172          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3173          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3174   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3175      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3176   ;; Final two alternatives should be unreachable, but included for completeness
3177   "@
3178    csel\\t%<w>0, %<w>3, %<w>4, %m1
3179    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3180    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3181    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3182    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3183    mov\\t%<w>0, -1
3184    mov\\t%<w>0, 1"
3185   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3188 ;; zero_extend version of above
3189 (define_insn "*cmovsi_insn_uxtw"
3190   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3191         (zero_extend:DI
3192          (if_then_else:SI
3193           (match_operator 1 "aarch64_comparison_operator"
3194            [(match_operand 2 "cc_register" "") (const_int 0)])
3195           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3196           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3197   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3198      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3199   ;; Final two alternatives should be unreachable, but included for completeness
3200   "@
3201    csel\\t%w0, %w3, %w4, %m1
3202    csinv\\t%w0, %w3, wzr, %m1
3203    csinv\\t%w0, %w4, wzr, %M1
3204    csinc\\t%w0, %w3, wzr, %m1
3205    csinc\\t%w0, %w4, wzr, %M1
3206    mov\\t%w0, -1
3207    mov\\t%w0, 1"
3208   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3211 (define_insn "*cmovdi_insn_uxtw"
3212   [(set (match_operand:DI 0 "register_operand" "=r")
3213         (if_then_else:DI
3214          (match_operator 1 "aarch64_comparison_operator"
3215           [(match_operand 2 "cc_register" "") (const_int 0)])
3216          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3217          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3218   ""
3219   "csel\\t%w0, %w3, %w4, %m1"
3220   [(set_attr "type" "csel")]
3223 (define_insn "*cmov<mode>_insn"
3224   [(set (match_operand:GPF 0 "register_operand" "=w")
3225         (if_then_else:GPF
3226          (match_operator 1 "aarch64_comparison_operator"
3227           [(match_operand 2 "cc_register" "") (const_int 0)])
3228          (match_operand:GPF 3 "register_operand" "w")
3229          (match_operand:GPF 4 "register_operand" "w")))]
3230   "TARGET_FLOAT"
3231   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3232   [(set_attr "type" "fcsel")]
3235 (define_expand "mov<mode>cc"
3236   [(set (match_operand:ALLI 0 "register_operand" "")
3237         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3238                            (match_operand:ALLI 2 "register_operand" "")
3239                            (match_operand:ALLI 3 "register_operand" "")))]
3240   ""
3241   {
3242     rtx ccreg;
3243     enum rtx_code code = GET_CODE (operands[1]);
3245     if (code == UNEQ || code == LTGT)
3246       FAIL;
3248     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3249                                      XEXP (operands[1], 1));
3250     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3251   }
3254 (define_expand "mov<GPF:mode><GPI:mode>cc"
3255   [(set (match_operand:GPI 0 "register_operand" "")
3256         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3257                           (match_operand:GPF 2 "register_operand" "")
3258                           (match_operand:GPF 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<mode>cc"
3274   [(set (match_operand:GPF 0 "register_operand" "")
3275         (if_then_else:GPF (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 "<neg_not_op><mode>cc"
3293   [(set (match_operand:GPI 0 "register_operand" "")
3294         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3295                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3296                           (match_operand:GPI 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 ;; CRC32 instructions.
3312 (define_insn "aarch64_<crc_variant>"
3313   [(set (match_operand:SI 0 "register_operand" "=r")
3314         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3315                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3316          CRC))]
3317   "TARGET_CRC32"
3318   {
3319     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3320       return "<crc_variant>\\t%w0, %w1, %x2";
3321     else
3322       return "<crc_variant>\\t%w0, %w1, %w2";
3323   }
3324   [(set_attr "type" "crc")]
3327 (define_insn "*csinc2<mode>_insn"
3328   [(set (match_operand:GPI 0 "register_operand" "=r")
3329         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3330                   (match_operand:GPI 1 "register_operand" "r")))]
3331   ""
3332   "cinc\\t%<w>0, %<w>1, %m2"
3333   [(set_attr "type" "csel")]
3336 (define_insn "csinc3<mode>_insn"
3337   [(set (match_operand:GPI 0 "register_operand" "=r")
3338         (if_then_else:GPI
3339           (match_operand 1 "aarch64_comparison_operation" "")
3340           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3341                     (const_int 1))
3342           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3343   ""
3344   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3345   [(set_attr "type" "csel")]
3348 (define_insn "*csinv3<mode>_insn"
3349   [(set (match_operand:GPI 0 "register_operand" "=r")
3350         (if_then_else:GPI
3351           (match_operand 1 "aarch64_comparison_operation" "")
3352           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3353           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3354   ""
3355   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3356   [(set_attr "type" "csel")]
3359 (define_insn "csneg3_uxtw_insn"
3360   [(set (match_operand:DI 0 "register_operand" "=r")
3361         (zero_extend:DI
3362           (if_then_else:SI
3363             (match_operand 1 "aarch64_comparison_operation" "")
3364             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3365             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3366   ""
3367   "csneg\\t%w0, %w3, %w2, %M1"
3368   [(set_attr "type" "csel")]
3371 (define_insn "csneg3<mode>_insn"
3372   [(set (match_operand:GPI 0 "register_operand" "=r")
3373         (if_then_else:GPI
3374           (match_operand 1 "aarch64_comparison_operation" "")
3375           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3376           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3377   ""
3378   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3379   [(set_attr "type" "csel")]
3382 ;; -------------------------------------------------------------------
3383 ;; Logical operations
3384 ;; -------------------------------------------------------------------
3387 (define_insn_and_split "*aarch64_and<mode>_imm2"
3388   [(set (match_operand:GPI 0 "register_operand" "=rk")
3389         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3390                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3391   ""
3392   "#"
3393   "true"
3394   [(const_int 0)]
3395   {
3396      HOST_WIDE_INT val = INTVAL (operands[2]);
3397      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3398      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3400      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3401      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3402      DONE;
3403   }
3406 (define_insn "<optab><mode>3"
3407   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3408         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3409                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3410   ""
3411   "@
3412   <logical>\\t%<w>0, %<w>1, %<w>2
3413   <logical>\\t%<w>0, %<w>1, %2
3414   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3415   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3416    (set_attr "simd" "*,*,yes")]
3419 ;; zero_extend version of above
3420 (define_insn "*<optab>si3_uxtw"
3421   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3422         (zero_extend:DI
3423          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3424                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3425   ""
3426   "@
3427    <logical>\\t%w0, %w1, %w2
3428    <logical>\\t%w0, %w1, %2"
3429   [(set_attr "type" "logic_reg,logic_imm")]
3432 (define_insn "*and<mode>3_compare0"
3433   [(set (reg:CC_NZ CC_REGNUM)
3434         (compare:CC_NZ
3435          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3436                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3437          (const_int 0)))
3438    (set (match_operand:GPI 0 "register_operand" "=r,r")
3439         (and:GPI (match_dup 1) (match_dup 2)))]
3440   ""
3441   "@
3442    ands\\t%<w>0, %<w>1, %<w>2
3443    ands\\t%<w>0, %<w>1, %2"
3444   [(set_attr "type" "logics_reg,logics_imm")]
3447 ;; zero_extend version of above
3448 (define_insn "*andsi3_compare0_uxtw"
3449   [(set (reg:CC_NZ CC_REGNUM)
3450         (compare:CC_NZ
3451          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3452                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3453          (const_int 0)))
3454    (set (match_operand:DI 0 "register_operand" "=r,r")
3455         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3456   ""
3457   "@
3458    ands\\t%w0, %w1, %w2
3459    ands\\t%w0, %w1, %2"
3460   [(set_attr "type" "logics_reg,logics_imm")]
3463 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3464   [(set (reg:CC_NZ CC_REGNUM)
3465         (compare:CC_NZ
3466          (and:GPI (SHIFT:GPI
3467                    (match_operand:GPI 1 "register_operand" "r")
3468                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3469                   (match_operand:GPI 3 "register_operand" "r"))
3470          (const_int 0)))
3471    (set (match_operand:GPI 0 "register_operand" "=r")
3472         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3473   ""
3474   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3475   [(set_attr "type" "logics_shift_imm")]
3478 ;; zero_extend version of above
3479 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3480   [(set (reg:CC_NZ CC_REGNUM)
3481         (compare:CC_NZ
3482          (and:SI (SHIFT:SI
3483                   (match_operand:SI 1 "register_operand" "r")
3484                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3485                  (match_operand:SI 3 "register_operand" "r"))
3486          (const_int 0)))
3487    (set (match_operand:DI 0 "register_operand" "=r")
3488         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3489                                 (match_dup 3))))]
3490   ""
3491   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3492   [(set_attr "type" "logics_shift_imm")]
3495 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3496   [(set (match_operand:GPI 0 "register_operand" "=r")
3497         (LOGICAL:GPI (SHIFT:GPI
3498                       (match_operand:GPI 1 "register_operand" "r")
3499                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3500                      (match_operand:GPI 3 "register_operand" "r")))]
3501   ""
3502   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3503   [(set_attr "type" "logic_shift_imm")]
3506 (define_insn "*<optab>_rol<mode>3"
3507   [(set (match_operand:GPI 0 "register_operand" "=r")
3508         (LOGICAL:GPI (rotate:GPI
3509                       (match_operand:GPI 1 "register_operand" "r")
3510                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3511                      (match_operand:GPI 3 "register_operand" "r")))]
3512   ""
3513   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3514   [(set_attr "type" "logic_shift_imm")]
3517 ;; zero_extend versions of above
3518 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3519   [(set (match_operand:DI 0 "register_operand" "=r")
3520         (zero_extend:DI
3521          (LOGICAL:SI (SHIFT:SI
3522                       (match_operand:SI 1 "register_operand" "r")
3523                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3524                      (match_operand:SI 3 "register_operand" "r"))))]
3525   ""
3526   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3527   [(set_attr "type" "logic_shift_imm")]
3530 (define_insn "*<optab>_rolsi3_uxtw"
3531   [(set (match_operand:DI 0 "register_operand" "=r")
3532         (zero_extend:DI
3533          (LOGICAL:SI (rotate:SI
3534                       (match_operand:SI 1 "register_operand" "r")
3535                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3536                      (match_operand:SI 3 "register_operand" "r"))))]
3537   ""
3538   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3539   [(set_attr "type" "logic_shift_imm")]
3542 (define_insn "one_cmpl<mode>2"
3543   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3544         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3545   ""
3546   "@
3547   mvn\\t%<w>0, %<w>1
3548   mvn\\t%0.8b, %1.8b"
3549   [(set_attr "type" "logic_reg,neon_logic")
3550    (set_attr "simd" "*,yes")]
3553 (define_insn "*one_cmpl_<optab><mode>2"
3554   [(set (match_operand:GPI 0 "register_operand" "=r")
3555         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3556                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3557   ""
3558   "mvn\\t%<w>0, %<w>1, <shift> %2"
3559   [(set_attr "type" "logic_shift_imm")]
3562 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3564 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3565   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3566         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3567                      (match_operand:GPI 2 "register_operand" "r,w")))]
3568   ""
3569   "@
3570   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3571   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3572   [(set_attr "type" "logic_reg,neon_logic")
3573    (set_attr "simd" "*,yes")]
3576 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3577   [(set (match_operand:DI 0 "register_operand" "=r")
3578         (zero_extend:DI
3579           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3580                        (match_operand:SI 2 "register_operand" "r"))))]
3581   ""
3582   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3583   [(set_attr "type" "logic_reg")]
3586 (define_insn "*xor_one_cmplsidi3_ze"
3587   [(set (match_operand:DI 0 "register_operand" "=r")
3588         (zero_extend:DI
3589           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3590                           (match_operand:SI 2 "register_operand" "r")))))]
3591   ""
3592   "eon\\t%w0, %w1, %w2"
3593   [(set_attr "type" "logic_reg")]
3596 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3597 ;; eon does not operate on SIMD registers so the vector variant must be split.
3598 (define_insn_and_split "*xor_one_cmpl<mode>3"
3599   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3600         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3601                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3602   ""
3603   "@
3604   eon\\t%<w>0, %<w>1, %<w>2
3605   #"
3606   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3607   [(set (match_operand:GPI 0 "register_operand" "=w")
3608         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3609                  (match_operand:GPI 2 "register_operand" "w")))
3610    (set (match_dup 0) (not:GPI (match_dup 0)))]
3611   ""
3612   [(set_attr "type" "logic_reg,multiple")
3613    (set_attr "simd" "*,yes")]
3616 (define_insn "*and_one_cmpl<mode>3_compare0"
3617   [(set (reg:CC_NZ CC_REGNUM)
3618         (compare:CC_NZ
3619          (and:GPI (not:GPI
3620                    (match_operand:GPI 1 "register_operand" "r"))
3621                   (match_operand:GPI 2 "register_operand" "r"))
3622          (const_int 0)))
3623    (set (match_operand:GPI 0 "register_operand" "=r")
3624         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3625   ""
3626   "bics\\t%<w>0, %<w>2, %<w>1"
3627   [(set_attr "type" "logics_reg")]
3630 ;; zero_extend version of above
3631 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3632   [(set (reg:CC_NZ CC_REGNUM)
3633         (compare:CC_NZ
3634          (and:SI (not:SI
3635                   (match_operand:SI 1 "register_operand" "r"))
3636                  (match_operand:SI 2 "register_operand" "r"))
3637          (const_int 0)))
3638    (set (match_operand:DI 0 "register_operand" "=r")
3639         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3640   ""
3641   "bics\\t%w0, %w2, %w1"
3642   [(set_attr "type" "logics_reg")]
3645 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3646   [(set (reg:CC_NZ CC_REGNUM)
3647     (compare:CC_NZ
3648      (and:GPI (not:GPI
3649            (match_operand:GPI 0 "register_operand" "r"))
3650           (match_operand:GPI 1 "register_operand" "r"))
3651      (const_int 0)))]
3652   ""
3653   "bics\\t<w>zr, %<w>1, %<w>0"
3654   [(set_attr "type" "logics_reg")]
3657 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3658   [(set (match_operand:GPI 0 "register_operand" "=r")
3659         (LOGICAL:GPI (not:GPI
3660                       (SHIFT:GPI
3661                        (match_operand:GPI 1 "register_operand" "r")
3662                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3663                      (match_operand:GPI 3 "register_operand" "r")))]
3664   ""
3665   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3666   [(set_attr "type" "logic_shift_imm")]
3669 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3670   [(set (match_operand:GPI 0 "register_operand" "=r")
3671         (not:GPI (xor:GPI
3672                       (SHIFT:GPI
3673                        (match_operand:GPI 1 "register_operand" "r")
3674                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3675                      (match_operand:GPI 3 "register_operand" "r"))))]
3676   ""
3677   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3678   [(set_attr "type" "logic_shift_imm")]
3681 ;; Zero-extend version of the above.
3682 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3683   [(set (match_operand:DI 0 "register_operand" "=r")
3684         (zero_extend:DI
3685           (not:SI (xor:SI
3686                     (SHIFT:SI
3687                       (match_operand:SI 1 "register_operand" "r")
3688                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3689                     (match_operand:SI 3 "register_operand" "r")))))]
3690   ""
3691   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3692   [(set_attr "type" "logic_shift_imm")]
3695 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3696   [(set (reg:CC_NZ CC_REGNUM)
3697         (compare:CC_NZ
3698          (and:GPI (not:GPI
3699                    (SHIFT:GPI
3700                     (match_operand:GPI 1 "register_operand" "r")
3701                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3702                   (match_operand:GPI 3 "register_operand" "r"))
3703          (const_int 0)))
3704    (set (match_operand:GPI 0 "register_operand" "=r")
3705         (and:GPI (not:GPI
3706                   (SHIFT:GPI
3707                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3708   ""
3709   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3710   [(set_attr "type" "logics_shift_imm")]
3713 ;; zero_extend version of above
3714 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3715   [(set (reg:CC_NZ CC_REGNUM)
3716         (compare:CC_NZ
3717          (and:SI (not:SI
3718                   (SHIFT:SI
3719                    (match_operand:SI 1 "register_operand" "r")
3720                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3721                  (match_operand:SI 3 "register_operand" "r"))
3722          (const_int 0)))
3723    (set (match_operand:DI 0 "register_operand" "=r")
3724         (zero_extend:DI (and:SI
3725                          (not:SI
3726                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3727   ""
3728   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3729   [(set_attr "type" "logics_shift_imm")]
3732 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3733   [(set (reg:CC_NZ CC_REGNUM)
3734     (compare:CC_NZ
3735      (and:GPI (not:GPI
3736            (SHIFT:GPI
3737             (match_operand:GPI 0 "register_operand" "r")
3738             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3739           (match_operand:GPI 2 "register_operand" "r"))
3740      (const_int 0)))]
3741   ""
3742   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3743   [(set_attr "type" "logics_shift_imm")]
3746 (define_insn "clz<mode>2"
3747   [(set (match_operand:GPI 0 "register_operand" "=r")
3748         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3749   ""
3750   "clz\\t%<w>0, %<w>1"
3751   [(set_attr "type" "clz")]
3754 (define_expand "ffs<mode>2"
3755   [(match_operand:GPI 0 "register_operand")
3756    (match_operand:GPI 1 "register_operand")]
3757   ""
3758   {
3759     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3760     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3762     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3763     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3764     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3765     DONE;
3766   }
3769 (define_insn "clrsb<mode>2"
3770   [(set (match_operand:GPI 0 "register_operand" "=r")
3771         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3772   ""
3773   "cls\\t%<w>0, %<w>1"
3774   [(set_attr "type" "clz")]
3777 (define_insn "rbit<mode>2"
3778   [(set (match_operand:GPI 0 "register_operand" "=r")
3779         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3780   ""
3781   "rbit\\t%<w>0, %<w>1"
3782   [(set_attr "type" "rbit")]
3785 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3786 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3787 ;; expression and split after reload to enable scheduling them apart if
3788 ;; needed.
3790 (define_insn_and_split "ctz<mode>2"
3791  [(set (match_operand:GPI           0 "register_operand" "=r")
3792        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3793   ""
3794   "#"
3795   "reload_completed"
3796   [(const_int 0)]
3797   "
3798   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3799   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3800   DONE;
3803 (define_insn "*and<mode>_compare0"
3804   [(set (reg:CC_NZ CC_REGNUM)
3805         (compare:CC_NZ
3806          (match_operand:SHORT 0 "register_operand" "r")
3807          (const_int 0)))]
3808   ""
3809   "tst\\t%<w>0, <short_mask>"
3810   [(set_attr "type" "alus_imm")]
3813 (define_insn "*ands<mode>_compare0"
3814   [(set (reg:CC_NZ CC_REGNUM)
3815         (compare:CC_NZ
3816          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3817          (const_int 0)))
3818    (set (match_operand:GPI 0 "register_operand" "=r")
3819         (zero_extend:GPI (match_dup 1)))]
3820   ""
3821   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3822   [(set_attr "type" "alus_imm")]
3825 (define_insn "*and<mode>3nr_compare0"
3826   [(set (reg:CC_NZ CC_REGNUM)
3827         (compare:CC_NZ
3828          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3829                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3830          (const_int 0)))]
3831   ""
3832   "@
3833    tst\\t%<w>0, %<w>1
3834    tst\\t%<w>0, %1"
3835   [(set_attr "type" "logics_reg,logics_imm")]
3838 (define_insn "*and<mode>3nr_compare0_zextract"
3839   [(set (reg:CC_NZ CC_REGNUM)
3840         (compare:CC_NZ
3841          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3842                   (match_operand:GPI 1 "const_int_operand" "n")
3843                   (match_operand:GPI 2 "const_int_operand" "n"))
3844          (const_int 0)))]
3845   "INTVAL (operands[1]) > 0
3846    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3847         <= GET_MODE_BITSIZE (<MODE>mode))
3848    && aarch64_bitmask_imm (
3849         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3850                                                  operands[2])),
3851         <MODE>mode)"
3852   {
3853     operands[1]
3854       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3855     return "tst\\t%<w>0, %1";
3856   }
3857   [(set_attr "type" "logics_shift_imm")]
3860 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3861   [(set (reg:CC_NZ CC_REGNUM)
3862         (compare:CC_NZ
3863          (and:GPI (SHIFT:GPI
3864                    (match_operand:GPI 0 "register_operand" "r")
3865                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3866                   (match_operand:GPI 2 "register_operand" "r"))
3867         (const_int 0)))]
3868   ""
3869   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3870   [(set_attr "type" "logics_shift_imm")]
3873 ;; -------------------------------------------------------------------
3874 ;; Shifts
3875 ;; -------------------------------------------------------------------
3877 (define_expand "<optab><mode>3"
3878   [(set (match_operand:GPI 0 "register_operand")
3879         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3880                     (match_operand:QI 2 "nonmemory_operand")))]
3881   ""
3882   {
3883     if (CONST_INT_P (operands[2]))
3884       {
3885         operands[2] = GEN_INT (INTVAL (operands[2])
3886                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3888         if (operands[2] == const0_rtx)
3889           {
3890             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3891             DONE;
3892           }
3893       }
3894   }
3897 (define_expand "ashl<mode>3"
3898   [(set (match_operand:SHORT 0 "register_operand")
3899         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3900                       (match_operand:QI 2 "const_int_operand")))]
3901   ""
3902   {
3903     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3905     if (operands[2] == const0_rtx)
3906       {
3907         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3908         DONE;
3909       }
3910   }
3913 (define_expand "rotr<mode>3"
3914   [(set (match_operand:GPI 0 "register_operand")
3915         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3916                       (match_operand:QI 2 "nonmemory_operand")))]
3917   ""
3918   {
3919     if (CONST_INT_P (operands[2]))
3920       {
3921         operands[2] = GEN_INT (INTVAL (operands[2])
3922                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3924         if (operands[2] == const0_rtx)
3925           {
3926             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3927             DONE;
3928           }
3929       }
3930   }
3933 (define_expand "rotl<mode>3"
3934   [(set (match_operand:GPI 0 "register_operand")
3935         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3936                       (match_operand:QI 2 "nonmemory_operand")))]
3937   ""
3938   {
3939     /* (SZ - cnt) % SZ == -cnt % SZ */
3940     if (CONST_INT_P (operands[2]))
3941       {
3942         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3943                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3944         if (operands[2] == const0_rtx)
3945           {
3946             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3947             DONE;
3948           }
3949       }
3950     else
3951       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3952                                         NULL_RTX, 1);
3953   }
3956 ;; Logical left shift using SISD or Integer instruction
3957 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3958   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3959         (ashift:GPI
3960           (match_operand:GPI 1 "register_operand" "r,r,w,w")
3961           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3962   ""
3963   "@
3964    lsl\t%<w>0, %<w>1, %2
3965    lsl\t%<w>0, %<w>1, %<w>2
3966    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3967    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3968   [(set_attr "simd" "no,no,yes,yes")
3969    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3972 ;; Logical right shift using SISD or Integer instruction
3973 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3974   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3975         (lshiftrt:GPI
3976          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3977          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3978   ""
3979   "@
3980    lsr\t%<w>0, %<w>1, %2
3981    lsr\t%<w>0, %<w>1, %<w>2
3982    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3983    #
3984    #"
3985   [(set_attr "simd" "no,no,yes,yes,yes")
3986    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3989 (define_split
3990   [(set (match_operand:DI 0 "aarch64_simd_register")
3991         (lshiftrt:DI
3992            (match_operand:DI 1 "aarch64_simd_register")
3993            (match_operand:QI 2 "aarch64_simd_register")))]
3994   "TARGET_SIMD && reload_completed"
3995   [(set (match_dup 3)
3996         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3997    (set (match_dup 0)
3998         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3999   {
4000     operands[3] = gen_lowpart (QImode, operands[0]);
4001   }
4004 (define_split
4005   [(set (match_operand:SI 0 "aarch64_simd_register")
4006         (lshiftrt:SI
4007            (match_operand:SI 1 "aarch64_simd_register")
4008            (match_operand:QI 2 "aarch64_simd_register")))]
4009   "TARGET_SIMD && reload_completed"
4010   [(set (match_dup 3)
4011         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4012    (set (match_dup 0)
4013         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4014   {
4015     operands[3] = gen_lowpart (QImode, operands[0]);
4016   }
4019 ;; Arithmetic right shift using SISD or Integer instruction
4020 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4021   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4022         (ashiftrt:GPI
4023           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4024           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4025   ""
4026   "@
4027    asr\t%<w>0, %<w>1, %2
4028    asr\t%<w>0, %<w>1, %<w>2
4029    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4030    #
4031    #"
4032   [(set_attr "simd" "no,no,yes,yes,yes")
4033    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4036 (define_split
4037   [(set (match_operand:DI 0 "aarch64_simd_register")
4038         (ashiftrt:DI
4039            (match_operand:DI 1 "aarch64_simd_register")
4040            (match_operand:QI 2 "aarch64_simd_register")))]
4041   "TARGET_SIMD && reload_completed"
4042   [(set (match_dup 3)
4043         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4044    (set (match_dup 0)
4045         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4047   operands[3] = gen_lowpart (QImode, operands[0]);
4051 (define_split
4052   [(set (match_operand:SI 0 "aarch64_simd_register")
4053         (ashiftrt:SI
4054            (match_operand:SI 1 "aarch64_simd_register")
4055            (match_operand:QI 2 "aarch64_simd_register")))]
4056   "TARGET_SIMD && reload_completed"
4057   [(set (match_dup 3)
4058         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4059    (set (match_dup 0)
4060         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4062   operands[3] = gen_lowpart (QImode, operands[0]);
4066 (define_insn "*aarch64_sisd_ushl"
4067   [(set (match_operand:DI 0 "register_operand" "=w")
4068         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4069                     (match_operand:QI 2 "register_operand" "w")]
4070                    UNSPEC_SISD_USHL))]
4071   "TARGET_SIMD"
4072   "ushl\t%d0, %d1, %d2"
4073   [(set_attr "simd" "yes")
4074    (set_attr "type" "neon_shift_reg")]
4077 (define_insn "*aarch64_ushl_2s"
4078   [(set (match_operand:SI 0 "register_operand" "=w")
4079         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4080                     (match_operand:QI 2 "register_operand" "w")]
4081                    UNSPEC_USHL_2S))]
4082   "TARGET_SIMD"
4083   "ushl\t%0.2s, %1.2s, %2.2s"
4084   [(set_attr "simd" "yes")
4085    (set_attr "type" "neon_shift_reg")]
4088 (define_insn "*aarch64_sisd_sshl"
4089   [(set (match_operand:DI 0 "register_operand" "=w")
4090         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4091                     (match_operand:QI 2 "register_operand" "w")]
4092                    UNSPEC_SISD_SSHL))]
4093   "TARGET_SIMD"
4094   "sshl\t%d0, %d1, %d2"
4095   [(set_attr "simd" "yes")
4096    (set_attr "type" "neon_shift_reg")]
4099 (define_insn "*aarch64_sshl_2s"
4100   [(set (match_operand:SI 0 "register_operand" "=w")
4101         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4102                     (match_operand:QI 2 "register_operand" "w")]
4103                    UNSPEC_SSHL_2S))]
4104   "TARGET_SIMD"
4105   "sshl\t%0.2s, %1.2s, %2.2s"
4106   [(set_attr "simd" "yes")
4107    (set_attr "type" "neon_shift_reg")]
4110 (define_insn "*aarch64_sisd_neg_qi"
4111   [(set (match_operand:QI 0 "register_operand" "=w")
4112         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4113                    UNSPEC_SISD_NEG))]
4114   "TARGET_SIMD"
4115   "neg\t%d0, %d1"
4116   [(set_attr "simd" "yes")
4117    (set_attr "type" "neon_neg")]
4120 ;; Rotate right
4121 (define_insn "*ror<mode>3_insn"
4122   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4123      (rotatert:GPI
4124        (match_operand:GPI 1 "register_operand" "r,r")
4125        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4126   ""
4127   "@
4128    ror\\t%<w>0, %<w>1, %2
4129    ror\\t%<w>0, %<w>1, %<w>2"
4130   [(set_attr "type" "rotate_imm,shift_reg")]
4133 ;; zero_extend version of above
4134 (define_insn "*<optab>si3_insn_uxtw"
4135   [(set (match_operand:DI 0 "register_operand" "=r,r")
4136         (zero_extend:DI (SHIFT:SI
4137          (match_operand:SI 1 "register_operand" "r,r")
4138          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4139   ""
4140   "@
4141    <shift>\\t%w0, %w1, %2
4142    <shift>\\t%w0, %w1, %w2"
4143   [(set_attr "type" "bfx,shift_reg")]
4146 (define_insn "*<optab><mode>3_insn"
4147   [(set (match_operand:SHORT 0 "register_operand" "=r")
4148         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4149                       (match_operand 2 "const_int_operand" "n")))]
4150   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4152   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4153   return "<bfshift>\t%w0, %w1, %2, %3";
4155   [(set_attr "type" "bfx")]
4158 (define_insn "*extr<mode>5_insn"
4159   [(set (match_operand:GPI 0 "register_operand" "=r")
4160         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4161                              (match_operand 3 "const_int_operand" "n"))
4162                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4163                                (match_operand 4 "const_int_operand" "n"))))]
4164   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4165    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4166   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4167   [(set_attr "type" "rotate_imm")]
4170 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4171 ;; so we have to match both orderings.
4172 (define_insn "*extr<mode>5_insn_alt"
4173   [(set (match_operand:GPI 0 "register_operand" "=r")
4174         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4175                                 (match_operand 4 "const_int_operand" "n"))
4176                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4177                               (match_operand 3 "const_int_operand" "n"))))]
4178   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4179    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4180        == GET_MODE_BITSIZE (<MODE>mode))"
4181   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4182   [(set_attr "type" "rotate_imm")]
4185 ;; zero_extend version of the above
4186 (define_insn "*extrsi5_insn_uxtw"
4187   [(set (match_operand:DI 0 "register_operand" "=r")
4188         (zero_extend:DI
4189          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4190                             (match_operand 3 "const_int_operand" "n"))
4191                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4192                               (match_operand 4 "const_int_operand" "n")))))]
4193   "UINTVAL (operands[3]) < 32 &&
4194    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4195   "extr\\t%w0, %w1, %w2, %4"
4196   [(set_attr "type" "rotate_imm")]
4199 (define_insn "*extrsi5_insn_uxtw_alt"
4200   [(set (match_operand:DI 0 "register_operand" "=r")
4201         (zero_extend:DI
4202          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4203                                (match_operand 4 "const_int_operand" "n"))
4204                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4205                             (match_operand 3 "const_int_operand" "n")))))]
4206   "UINTVAL (operands[3]) < 32 &&
4207    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4208   "extr\\t%w0, %w1, %w2, %4"
4209   [(set_attr "type" "rotate_imm")]
4212 (define_insn "*ror<mode>3_insn"
4213   [(set (match_operand:GPI 0 "register_operand" "=r")
4214         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4215                     (match_operand 2 "const_int_operand" "n")))]
4216   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4218   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4219   return "ror\\t%<w>0, %<w>1, %3";
4221   [(set_attr "type" "rotate_imm")]
4224 ;; zero_extend version of the above
4225 (define_insn "*rorsi3_insn_uxtw"
4226   [(set (match_operand:DI 0 "register_operand" "=r")
4227         (zero_extend:DI
4228          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4229                     (match_operand 2 "const_int_operand" "n"))))]
4230   "UINTVAL (operands[2]) < 32"
4232   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4233   return "ror\\t%w0, %w1, %3";
4235   [(set_attr "type" "rotate_imm")]
4238 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4239   [(set (match_operand:GPI 0 "register_operand" "=r")
4240         (ANY_EXTEND:GPI
4241          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4242                        (match_operand 2 "const_int_operand" "n"))))]
4243   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4245   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4246   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4248   [(set_attr "type" "bfx")]
4251 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4252   [(set (match_operand:GPI 0 "register_operand" "=r")
4253         (zero_extend:GPI
4254          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4255                          (match_operand 2 "const_int_operand" "n"))))]
4256   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4258   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4259   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4261   [(set_attr "type" "bfx")]
4264 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4265   [(set (match_operand:GPI 0 "register_operand" "=r")
4266         (sign_extend:GPI
4267          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4268                          (match_operand 2 "const_int_operand" "n"))))]
4269   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4271   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4272   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4274   [(set_attr "type" "bfx")]
4277 ;; -------------------------------------------------------------------
4278 ;; Bitfields
4279 ;; -------------------------------------------------------------------
4281 (define_expand "<optab>"
4282   [(set (match_operand:DI 0 "register_operand" "=r")
4283         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4284                         (match_operand 2
4285                           "aarch64_simd_shift_imm_offset_di")
4286                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4287   ""
4288   {
4289     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4290                    1, GET_MODE_BITSIZE (DImode) - 1))
4291      FAIL;
4292   }
4296 (define_insn "*<optab><mode>"
4297   [(set (match_operand:GPI 0 "register_operand" "=r")
4298         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4299                          (match_operand 2
4300                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4301                          (match_operand 3
4302                            "aarch64_simd_shift_imm_<mode>" "n")))]
4303   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4304              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4305   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4306   [(set_attr "type" "bfx")]
4309 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4310 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4311 (define_split
4312   [(set (match_operand:DI 0 "register_operand")
4313         (zero_extract:DI (match_operand:DI 1 "register_operand")
4314                          (match_operand 2
4315                            "aarch64_simd_shift_imm_offset_di")
4316                          (match_operand 3
4317                            "aarch64_simd_shift_imm_di")))]
4318   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4319              GET_MODE_BITSIZE (DImode) - 1)
4320    && (INTVAL (operands[2]) + INTVAL (operands[3]))
4321        == GET_MODE_BITSIZE (SImode)"
4322   [(set (match_dup 0)
4323         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4324   {
4325     operands[4] = gen_lowpart (SImode, operands[1]);
4326   }
4329 ;; Bitfield Insert (insv)
4330 (define_expand "insv<mode>"
4331   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4332                           (match_operand 1 "const_int_operand")
4333                           (match_operand 2 "const_int_operand"))
4334         (match_operand:GPI 3 "general_operand"))]
4335   ""
4337   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4338   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4339   rtx value = operands[3];
4341   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4342     FAIL;
4344   if (CONST_INT_P (value))
4345     {
4346       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4348       /* Prefer AND/OR for inserting all zeros or all ones.  */
4349       if ((UINTVAL (value) & mask) == 0
4350            || (UINTVAL (value) & mask) == mask)
4351         FAIL;
4353       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4354       if (width == 16 && (pos % 16) == 0)
4355         DONE;
4356     }
4357   operands[3] = force_reg (<MODE>mode, value);
4360 (define_insn "*insv_reg<mode>"
4361   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4362                           (match_operand 1 "const_int_operand" "n")
4363                           (match_operand 2 "const_int_operand" "n"))
4364         (match_operand:GPI 3 "register_operand" "r"))]
4365   "!(UINTVAL (operands[1]) == 0
4366      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4367          > GET_MODE_BITSIZE (<MODE>mode)))"
4368   "bfi\\t%<w>0, %<w>3, %2, %1"
4369   [(set_attr "type" "bfm")]
4372 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4373   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4374                           (match_operand 1 "const_int_operand" "n")
4375                           (match_operand 2 "const_int_operand" "n"))
4376         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4377   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4378   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4379   [(set_attr "type" "bfm")]
4382 (define_insn "*extr_insv_lower_reg<mode>"
4383   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4384                           (match_operand 1 "const_int_operand" "n")
4385                           (const_int 0))
4386         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4387                           (match_dup 1)
4388                           (match_operand 3 "const_int_operand" "n")))]
4389   "!(UINTVAL (operands[1]) == 0
4390      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4391          > GET_MODE_BITSIZE (<MODE>mode)))"
4392   "bfxil\\t%<w>0, %<w>2, %3, %1"
4393   [(set_attr "type" "bfm")]
4396 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4397   [(set (match_operand:GPI 0 "register_operand" "=r")
4398         (ashift:GPI (ANY_EXTEND:GPI
4399                      (match_operand:ALLX 1 "register_operand" "r"))
4400                     (match_operand 2 "const_int_operand" "n")))]
4401   "UINTVAL (operands[2]) < <GPI:sizen>"
4403   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4404               ? GEN_INT (<ALLX:sizen>)
4405               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4406   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4408   [(set_attr "type" "bfx")]
4411 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4413 (define_insn "*andim_ashift<mode>_bfiz"
4414   [(set (match_operand:GPI 0 "register_operand" "=r")
4415         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4416                              (match_operand 2 "const_int_operand" "n"))
4417                  (match_operand 3 "const_int_operand" "n")))]
4418   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4419   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4420   [(set_attr "type" "bfx")]
4423 ;; When the bit position and width of the equivalent extraction add up to 32
4424 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4425 ;; zero-extension of the X-reg.
4426 (define_split
4427   [(set (match_operand:DI 0 "register_operand")
4428         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4429                              (match_operand 2 "const_int_operand"))
4430                  (match_operand 3 "const_int_operand")))]
4431  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4432   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4433       == GET_MODE_BITSIZE (SImode)"
4434   [(set (match_dup 0)
4435         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4436   {
4437     operands[4] = gen_lowpart (SImode, operands[1]);
4438   }
4441 (define_insn "bswap<mode>2"
4442   [(set (match_operand:GPI 0 "register_operand" "=r")
4443         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4444   ""
4445   "rev\\t%<w>0, %<w>1"
4446   [(set_attr "type" "rev")]
4449 (define_insn "bswaphi2"
4450   [(set (match_operand:HI 0 "register_operand" "=r")
4451         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4452   ""
4453   "rev16\\t%w0, %w1"
4454   [(set_attr "type" "rev")]
4457 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4458 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4459 ;; each valid permutation.
4461 (define_insn "rev16<mode>2"
4462   [(set (match_operand:GPI 0 "register_operand" "=r")
4463         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4464                                       (const_int 8))
4465                           (match_operand:GPI 3 "const_int_operand" "n"))
4466                  (and:GPI (lshiftrt:GPI (match_dup 1)
4467                                         (const_int 8))
4468                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4469   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4470    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4471   "rev16\\t%<w>0, %<w>1"
4472   [(set_attr "type" "rev")]
4475 (define_insn "rev16<mode>2_alt"
4476   [(set (match_operand:GPI 0 "register_operand" "=r")
4477         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4478                                         (const_int 8))
4479                           (match_operand:GPI 2 "const_int_operand" "n"))
4480                  (and:GPI (ashift:GPI (match_dup 1)
4481                                       (const_int 8))
4482                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4483   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4484    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4485   "rev16\\t%<w>0, %<w>1"
4486   [(set_attr "type" "rev")]
4489 ;; zero_extend version of above
4490 (define_insn "*bswapsi2_uxtw"
4491   [(set (match_operand:DI 0 "register_operand" "=r")
4492         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4493   ""
4494   "rev\\t%w0, %w1"
4495   [(set_attr "type" "rev")]
4498 ;; -------------------------------------------------------------------
4499 ;; Floating-point intrinsics
4500 ;; -------------------------------------------------------------------
4502 ;; frint floating-point round to integral standard patterns.
4503 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4505 (define_insn "<frint_pattern><mode>2"
4506   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4507         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4508          FRINT))]
4509   "TARGET_FLOAT"
4510   "frint<frint_suffix>\\t%<s>0, %<s>1"
4511   [(set_attr "type" "f_rint<stype>")]
4514 ;; frcvt floating-point round to integer and convert standard patterns.
4515 ;; Expands to lbtrunc, lceil, lfloor, lround.
4516 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4517   [(set (match_operand:GPI 0 "register_operand" "=r")
4518         (FIXUORS:GPI
4519           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4520            FCVT)))]
4521   "TARGET_FLOAT"
4522   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4523   [(set_attr "type" "f_cvtf2i")]
4526 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4527   [(set (match_operand:GPI 0 "register_operand" "=r")
4528         (FIXUORS:GPI
4529           (mult:GPF
4530             (match_operand:GPF 1 "register_operand" "w")
4531             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4532   "TARGET_FLOAT
4533    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4534                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4535   {
4536     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4537     char buf[64];
4538     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4539     output_asm_insn (buf, operands);
4540     return "";
4541   }
4542   [(set_attr "type" "f_cvtf2i")]
4545 ;; fma - no throw
4547 (define_insn "fma<mode>4"
4548   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4549         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4550                      (match_operand:GPF_F16 2 "register_operand" "w")
4551                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4552   "TARGET_FLOAT"
4553   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4554   [(set_attr "type" "fmac<stype>")]
4557 (define_insn "fnma<mode>4"
4558   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4559         (fma:GPF_F16
4560           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4561           (match_operand:GPF_F16 2 "register_operand" "w")
4562           (match_operand:GPF_F16 3 "register_operand" "w")))]
4563   "TARGET_FLOAT"
4564   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4565   [(set_attr "type" "fmac<stype>")]
4568 (define_insn "fms<mode>4"
4569   [(set (match_operand:GPF 0 "register_operand" "=w")
4570         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4571                  (match_operand:GPF 2 "register_operand" "w")
4572                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4573   "TARGET_FLOAT"
4574   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4575   [(set_attr "type" "fmac<s>")]
4578 (define_insn "fnms<mode>4"
4579   [(set (match_operand:GPF 0 "register_operand" "=w")
4580         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4581                  (match_operand:GPF 2 "register_operand" "w")
4582                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4583   "TARGET_FLOAT"
4584   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4585   [(set_attr "type" "fmac<s>")]
4588 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4589 (define_insn "*fnmadd<mode>4"
4590   [(set (match_operand:GPF 0 "register_operand" "=w")
4591         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4592                           (match_operand:GPF 2 "register_operand" "w")
4593                           (match_operand:GPF 3 "register_operand" "w"))))]
4594   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4595   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4596   [(set_attr "type" "fmac<s>")]
4599 ;; -------------------------------------------------------------------
4600 ;; Floating-point conversions
4601 ;; -------------------------------------------------------------------
4603 (define_insn "extendsfdf2"
4604   [(set (match_operand:DF 0 "register_operand" "=w")
4605         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4606   "TARGET_FLOAT"
4607   "fcvt\\t%d0, %s1"
4608   [(set_attr "type" "f_cvt")]
4611 (define_insn "extendhfsf2"
4612   [(set (match_operand:SF 0 "register_operand" "=w")
4613         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4614   "TARGET_FLOAT"
4615   "fcvt\\t%s0, %h1"
4616   [(set_attr "type" "f_cvt")]
4619 (define_insn "extendhfdf2"
4620   [(set (match_operand:DF 0 "register_operand" "=w")
4621         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4622   "TARGET_FLOAT"
4623   "fcvt\\t%d0, %h1"
4624   [(set_attr "type" "f_cvt")]
4627 (define_insn "truncdfsf2"
4628   [(set (match_operand:SF 0 "register_operand" "=w")
4629         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4630   "TARGET_FLOAT"
4631   "fcvt\\t%s0, %d1"
4632   [(set_attr "type" "f_cvt")]
4635 (define_insn "truncsfhf2"
4636   [(set (match_operand:HF 0 "register_operand" "=w")
4637         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4638   "TARGET_FLOAT"
4639   "fcvt\\t%h0, %s1"
4640   [(set_attr "type" "f_cvt")]
4643 (define_insn "truncdfhf2"
4644   [(set (match_operand:HF 0 "register_operand" "=w")
4645         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4646   "TARGET_FLOAT"
4647   "fcvt\\t%h0, %d1"
4648   [(set_attr "type" "f_cvt")]
4651 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4652   [(set (match_operand:GPI 0 "register_operand" "=r")
4653         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4654   "TARGET_FLOAT"
4655   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4656   [(set_attr "type" "f_cvtf2i")]
4659 (define_insn "<optab><fcvt_target><GPF:mode>2"
4660   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4661         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4662   "TARGET_FLOAT"
4663   "@
4664    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4665    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4666   [(set_attr "simd" "yes,no")
4667    (set_attr "fp" "no,yes")
4668    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4671 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4672   [(set (match_operand:GPF 0 "register_operand" "=w")
4673         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4674   "TARGET_FLOAT"
4675   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4676   [(set_attr "type" "f_cvti2f")]
4679 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4680 ;; midend will arrange for an SImode conversion to HFmode to first go
4681 ;; through DFmode, then to HFmode.  But first it will try converting
4682 ;; to DImode then down, which would match our DImode pattern below and
4683 ;; give very poor code-generation.  So, we must provide our own emulation
4684 ;; of the mid-end logic.
4686 (define_insn "aarch64_fp16_<optab><mode>hf2"
4687   [(set (match_operand:HF 0 "register_operand" "=w")
4688         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4689   "TARGET_FP_F16INST"
4690   "<su_optab>cvtf\t%h0, %<w>1"
4691   [(set_attr "type" "f_cvti2f")]
4694 (define_expand "<optab>sihf2"
4695   [(set (match_operand:HF 0 "register_operand")
4696         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4697   "TARGET_FLOAT"
4699   if (TARGET_FP_F16INST)
4700     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4701   else
4702     {
4703       rtx convert_target = gen_reg_rtx (DFmode);
4704       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4705       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4706     }
4707   DONE;
4711 ;; For DImode there is no wide enough floating-point mode that we
4712 ;; can convert through natively (TFmode would work, but requires a library
4713 ;; call).  However, we know that any value >= 65504 will be rounded
4714 ;; to infinity on conversion.  This is well within the range of SImode, so
4715 ;; we can:
4716 ;;   Saturate to SImode.
4717 ;;   Convert from that to DFmode
4718 ;;   Convert from that to HFmode (phew!).
4719 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4720 ;; we ever need to provide this pattern where the SIMD extensions are not
4721 ;; available, we would need a different approach.
4723 (define_expand "<optab>dihf2"
4724   [(set (match_operand:HF 0 "register_operand")
4725         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4726   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4728   if (TARGET_FP_F16INST)
4729     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4730   else
4731     {
4732       rtx sat_target = gen_reg_rtx (SImode);
4733       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4734       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4735     }
4737   DONE;
4741 ;; Convert between fixed-point and floating-point (scalar modes)
4743 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4744   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4745         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4746                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4747          FCVT_F2FIXED))]
4748   ""
4749   "@
4750    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4751    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4752   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4753    (set_attr "fp" "yes, *")
4754    (set_attr "simd" "*, yes")]
4757 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4758   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4759         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4760                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4761          FCVT_FIXED2F))]
4762   ""
4763   "@
4764    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4765    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4766   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4767    (set_attr "fp" "yes, *")
4768    (set_attr "simd" "*, yes")]
4771 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4772   [(set (match_operand:GPI 0 "register_operand" "=r")
4773         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4774                      (match_operand:SI 2 "immediate_operand" "i")]
4775          FCVT_F2FIXED))]
4776   "TARGET_FP_F16INST"
4777    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4778   [(set_attr "type" "f_cvtf2i")]
4781 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4782   [(set (match_operand:HF 0 "register_operand" "=w")
4783         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4784                     (match_operand:SI 2 "immediate_operand" "i")]
4785          FCVT_FIXED2F))]
4786   "TARGET_FP_F16INST"
4787   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4788   [(set_attr "type" "f_cvti2f")]
4791 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4792   [(set (match_operand:HI 0 "register_operand" "=w")
4793         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4794                     (match_operand:SI 2 "immediate_operand" "i")]
4795          FCVT_F2FIXED))]
4796   "TARGET_SIMD"
4797   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4798   [(set_attr "type" "neon_fp_to_int_s")]
4801 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4802   [(set (match_operand:HF 0 "register_operand" "=w")
4803         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4804                     (match_operand:SI 2 "immediate_operand" "i")]
4805          FCVT_FIXED2F))]
4806   "TARGET_SIMD"
4807   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4808   [(set_attr "type" "neon_int_to_fp_s")]
4811 ;; -------------------------------------------------------------------
4812 ;; Floating-point arithmetic
4813 ;; -------------------------------------------------------------------
4815 (define_insn "add<mode>3"
4816   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4817         (plus:GPF_F16
4818          (match_operand:GPF_F16 1 "register_operand" "w")
4819          (match_operand:GPF_F16 2 "register_operand" "w")))]
4820   "TARGET_FLOAT"
4821   "fadd\\t%<s>0, %<s>1, %<s>2"
4822   [(set_attr "type" "fadd<stype>")]
4825 (define_insn "sub<mode>3"
4826   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4827         (minus:GPF_F16
4828          (match_operand:GPF_F16 1 "register_operand" "w")
4829          (match_operand:GPF_F16 2 "register_operand" "w")))]
4830   "TARGET_FLOAT"
4831   "fsub\\t%<s>0, %<s>1, %<s>2"
4832   [(set_attr "type" "fadd<stype>")]
4835 (define_insn "mul<mode>3"
4836   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4837         (mult:GPF_F16
4838          (match_operand:GPF_F16 1 "register_operand" "w")
4839          (match_operand:GPF_F16 2 "register_operand" "w")))]
4840   "TARGET_FLOAT"
4841   "fmul\\t%<s>0, %<s>1, %<s>2"
4842   [(set_attr "type" "fmul<stype>")]
4845 (define_insn "*fnmul<mode>3"
4846   [(set (match_operand:GPF 0 "register_operand" "=w")
4847         (mult:GPF
4848                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4849                  (match_operand:GPF 2 "register_operand" "w")))]
4850   "TARGET_FLOAT && !flag_rounding_math"
4851   "fnmul\\t%<s>0, %<s>1, %<s>2"
4852   [(set_attr "type" "fmul<s>")]
4855 (define_insn "*fnmul<mode>3"
4856   [(set (match_operand:GPF 0 "register_operand" "=w")
4857         (neg:GPF (mult:GPF
4858                  (match_operand:GPF 1 "register_operand" "w")
4859                  (match_operand:GPF 2 "register_operand" "w"))))]
4860   "TARGET_FLOAT"
4861   "fnmul\\t%<s>0, %<s>1, %<s>2"
4862   [(set_attr "type" "fmul<s>")]
4865 (define_expand "div<mode>3"
4866  [(set (match_operand:GPF_F16 0 "register_operand")
4867        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4868                     (match_operand:GPF_F16 2 "register_operand")))]
4869  "TARGET_SIMD"
4871   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4872     DONE;
4874   operands[1] = force_reg (<MODE>mode, operands[1]);
4877 (define_insn "*div<mode>3"
4878   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4879         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4880                      (match_operand:GPF_F16 2 "register_operand" "w")))]
4881   "TARGET_FLOAT"
4882   "fdiv\\t%<s>0, %<s>1, %<s>2"
4883   [(set_attr "type" "fdiv<stype>")]
4886 (define_insn "neg<mode>2"
4887   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4888         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4889   "TARGET_FLOAT"
4890   "fneg\\t%<s>0, %<s>1"
4891   [(set_attr "type" "ffarith<stype>")]
4894 (define_expand "sqrt<mode>2"
4895   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4896         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4897   "TARGET_FLOAT"
4899   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4900     DONE;
4903 (define_insn "*sqrt<mode>2"
4904   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4905         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4906   "TARGET_FLOAT"
4907   "fsqrt\\t%<s>0, %<s>1"
4908   [(set_attr "type" "fsqrt<stype>")]
4911 (define_insn "abs<mode>2"
4912   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4913         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4914   "TARGET_FLOAT"
4915   "fabs\\t%<s>0, %<s>1"
4916   [(set_attr "type" "ffarith<stype>")]
4919 ;; Given that smax/smin do not specify the result when either input is NaN,
4920 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4921 ;; for smin.
4923 (define_insn "smax<mode>3"
4924   [(set (match_operand:GPF 0 "register_operand" "=w")
4925         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4926                   (match_operand:GPF 2 "register_operand" "w")))]
4927   "TARGET_FLOAT"
4928   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4929   [(set_attr "type" "f_minmax<s>")]
4932 (define_insn "smin<mode>3"
4933   [(set (match_operand:GPF 0 "register_operand" "=w")
4934         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4935                   (match_operand:GPF 2 "register_operand" "w")))]
4936   "TARGET_FLOAT"
4937   "fminnm\\t%<s>0, %<s>1, %<s>2"
4938   [(set_attr "type" "f_minmax<s>")]
4941 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4942 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4943 ;; which implement the IEEE fmax ()/fmin () functions.
4944 (define_insn "<maxmin_uns><mode>3"
4945   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4946         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4947                      (match_operand:GPF_F16 2 "register_operand" "w")]
4948                      FMAXMIN_UNS))]
4949   "TARGET_FLOAT"
4950   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4951   [(set_attr "type" "f_minmax<stype>")]
4954 ;; For copysign (x, y), we want to generate:
4956 ;;   LDR d2, #(1 << 63)
4957 ;;   BSL v2.8b, [y], [x]
4959 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4960 ;; aarch64_simd_bsldf will select the best suited of these instructions
4961 ;; to generate based on register allocation, and knows how to partially
4962 ;; constant fold based on the values of X and Y, so expand through that.
4964 (define_expand "copysigndf3"
4965   [(match_operand:DF 0 "register_operand")
4966    (match_operand:DF 1 "register_operand")
4967    (match_operand:DF 2 "register_operand")]
4968   "TARGET_FLOAT && TARGET_SIMD"
4970   rtx mask = gen_reg_rtx (DImode);
4971   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4972   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4973                                      operands[2], operands[1]));
4974   DONE;
4978 ;; As above, but we must first get to a 64-bit value if we wish to use
4979 ;; aarch64_simd_bslv2sf.
4981 (define_expand "copysignsf3"
4982   [(match_operand:SF 0 "register_operand")
4983    (match_operand:SF 1 "register_operand")
4984    (match_operand:SF 2 "register_operand")]
4985   "TARGET_FLOAT && TARGET_SIMD"
4987   rtx mask = gen_reg_rtx (DImode);
4989   /* Juggle modes to get us in to a vector mode for BSL.  */
4990   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4991   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4992   rtx tmp = gen_reg_rtx (V2SFmode);
4993   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4994   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4995   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4996   DONE;
5000 ;; -------------------------------------------------------------------
5001 ;; Reload support
5002 ;; -------------------------------------------------------------------
5003 ;; Reload Scalar Floating point modes from constant pool.
5004 ;; The AArch64 port doesn't have __int128 constant move support.
5005 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5006  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5007        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5008   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5009  "TARGET_FLOAT"
5011    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5012    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5013    DONE;
5017 ;; Reload Vector modes from constant pool.
5018 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5019  [(set (match_operand:VALL 0 "register_operand" "=w")
5020        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5021   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5022  "TARGET_FLOAT"
5024    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5025    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5026    DONE;
5030 (define_expand "aarch64_reload_mov<mode>"
5031   [(set (match_operand:TX 0 "register_operand" "=w")
5032         (match_operand:TX 1 "register_operand" "w"))
5033    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5034   ]
5035   "TARGET_FLOAT"
5036   {
5037     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5038     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5039     gen_aarch64_movtilow_tilow (op0, op1);
5040     gen_aarch64_movdi_tihigh (operands[2], op1);
5041     gen_aarch64_movtihigh_di (op0, operands[2]);
5042     DONE;
5043   }
5046 ;; The following secondary reload helpers patterns are invoked
5047 ;; after or during reload as we don't want these patterns to start
5048 ;; kicking in during the combiner.
5050 (define_insn "aarch64_movdi_<mode>low"
5051   [(set (match_operand:DI 0 "register_operand" "=r")
5052         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5053                          (const_int 64) (const_int 0)))]
5054   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5055   "fmov\\t%x0, %d1"
5056   [(set_attr "type" "f_mrc")
5057    (set_attr "length" "4")
5058   ])
5060 (define_insn "aarch64_movdi_<mode>high"
5061   [(set (match_operand:DI 0 "register_operand" "=r")
5062         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5063                          (const_int 64) (const_int 64)))]
5064   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5065   "fmov\\t%x0, %1.d[1]"
5066   [(set_attr "type" "f_mrc")
5067    (set_attr "length" "4")
5068   ])
5070 (define_insn "aarch64_mov<mode>high_di"
5071   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5072                          (const_int 64) (const_int 64))
5073         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5074   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5075   "fmov\\t%0.d[1], %x1"
5076   [(set_attr "type" "f_mcr")
5077    (set_attr "length" "4")
5078   ])
5080 (define_insn "aarch64_mov<mode>low_di"
5081   [(set (match_operand:TX 0 "register_operand" "=w")
5082         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5083   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5084   "fmov\\t%d0, %x1"
5085   [(set_attr "type" "f_mcr")
5086    (set_attr "length" "4")
5087   ])
5089 (define_insn "aarch64_movtilow_tilow"
5090   [(set (match_operand:TI 0 "register_operand" "=w")
5091         (zero_extend:TI
5092           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5093   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5094   "fmov\\t%d0, %d1"
5095   [(set_attr "type" "fmov")
5096    (set_attr "length" "4")
5097   ])
5099 ;; There is a deliberate reason why the parameters of high and lo_sum's
5100 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5101 ;; and lo_sum's to be used with the labels defining the jump tables in
5102 ;; rodata section.
5104 (define_expand "add_losym"
5105   [(set (match_operand 0 "register_operand" "=r")
5106         (lo_sum (match_operand 1 "register_operand" "r")
5107                 (match_operand 2 "aarch64_valid_symref" "S")))]
5108   ""
5110   machine_mode mode = GET_MODE (operands[0]);
5112   emit_insn ((mode == DImode
5113               ? gen_add_losym_di
5114               : gen_add_losym_si) (operands[0],
5115                                    operands[1],
5116                                    operands[2]));
5117   DONE;
5120 (define_insn "add_losym_<mode>"
5121   [(set (match_operand:P 0 "register_operand" "=r")
5122         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5123                   (match_operand 2 "aarch64_valid_symref" "S")))]
5124   ""
5125   "add\\t%<w>0, %<w>1, :lo12:%a2"
5126   [(set_attr "type" "alu_imm")]
5129 (define_insn "ldr_got_small_<mode>"
5130   [(set (match_operand:PTR 0 "register_operand" "=r")
5131         (unspec:PTR [(mem:PTR (lo_sum:PTR
5132                               (match_operand:PTR 1 "register_operand" "r")
5133                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5134                     UNSPEC_GOTSMALLPIC))]
5135   ""
5136   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5137   [(set_attr "type" "load1")]
5140 (define_insn "ldr_got_small_sidi"
5141   [(set (match_operand:DI 0 "register_operand" "=r")
5142         (zero_extend:DI
5143          (unspec:SI [(mem:SI (lo_sum:DI
5144                              (match_operand:DI 1 "register_operand" "r")
5145                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5146                     UNSPEC_GOTSMALLPIC)))]
5147   "TARGET_ILP32"
5148   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5149   [(set_attr "type" "load1")]
5152 (define_insn "ldr_got_small_28k_<mode>"
5153   [(set (match_operand:PTR 0 "register_operand" "=r")
5154         (unspec:PTR [(mem:PTR (lo_sum:PTR
5155                               (match_operand:PTR 1 "register_operand" "r")
5156                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5157                     UNSPEC_GOTSMALLPIC28K))]
5158   ""
5159   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5160   [(set_attr "type" "load1")]
5163 (define_insn "ldr_got_small_28k_sidi"
5164   [(set (match_operand:DI 0 "register_operand" "=r")
5165         (zero_extend:DI
5166          (unspec:SI [(mem:SI (lo_sum:DI
5167                              (match_operand:DI 1 "register_operand" "r")
5168                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5169                     UNSPEC_GOTSMALLPIC28K)))]
5170   "TARGET_ILP32"
5171   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5172   [(set_attr "type" "load1")]
5175 (define_insn "ldr_got_tiny"
5176   [(set (match_operand:DI 0 "register_operand" "=r")
5177         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5178                    UNSPEC_GOTTINYPIC))]
5179   ""
5180   "ldr\\t%0, %L1"
5181   [(set_attr "type" "load1")]
5184 (define_insn "aarch64_load_tp_hard"
5185   [(set (match_operand:DI 0 "register_operand" "=r")
5186         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5187   ""
5188   "mrs\\t%0, tpidr_el0"
5189   [(set_attr "type" "mrs")]
5192 ;; The TLS ABI specifically requires that the compiler does not schedule
5193 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5194 ;; Therefore we treat the stubs as an atomic sequence.
5195 (define_expand "tlsgd_small_<mode>"
5196  [(parallel [(set (match_operand 0 "register_operand" "")
5197                   (call (mem:DI (match_dup 2)) (const_int 1)))
5198              (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5199              (clobber (reg:DI LR_REGNUM))])]
5200  ""
5202   operands[2] = aarch64_tls_get_addr ();
5205 (define_insn "*tlsgd_small_<mode>"
5206   [(set (match_operand 0 "register_operand" "")
5207         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5208    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5209    (clobber (reg:DI LR_REGNUM))
5210   ]
5211   ""
5212   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5213   [(set_attr "type" "call")
5214    (set_attr "length" "16")])
5216 (define_insn "tlsie_small_<mode>"
5217   [(set (match_operand:PTR 0 "register_operand" "=r")
5218         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5219                    UNSPEC_GOTSMALLTLS))]
5220   ""
5221   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5222   [(set_attr "type" "load1")
5223    (set_attr "length" "8")]
5226 (define_insn "tlsie_small_sidi"
5227   [(set (match_operand:DI 0 "register_operand" "=r")
5228         (zero_extend:DI
5229           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5230                       UNSPEC_GOTSMALLTLS)))]
5231   ""
5232   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5233   [(set_attr "type" "load1")
5234    (set_attr "length" "8")]
5237 (define_insn "tlsie_tiny_<mode>"
5238   [(set (match_operand:PTR 0 "register_operand" "=&r")
5239         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5240                      (match_operand:PTR 2 "register_operand" "r")]
5241                    UNSPEC_GOTTINYTLS))]
5242   ""
5243   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5244   [(set_attr "type" "multiple")
5245    (set_attr "length" "8")]
5248 (define_insn "tlsie_tiny_sidi"
5249   [(set (match_operand:DI 0 "register_operand" "=&r")
5250         (zero_extend:DI
5251           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5252                       (match_operand:DI 2 "register_operand" "r")
5253                       ]
5254                       UNSPEC_GOTTINYTLS)))]
5255   ""
5256   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5257   [(set_attr "type" "multiple")
5258    (set_attr "length" "8")]
5261 (define_insn "tlsle12_<mode>"
5262   [(set (match_operand:P 0 "register_operand" "=r")
5263         (unspec:P [(match_operand:P 1 "register_operand" "r")
5264                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5265                    UNSPEC_TLSLE12))]
5266   ""
5267   "add\\t%<w>0, %<w>1, #%L2";
5268   [(set_attr "type" "alu_sreg")
5269    (set_attr "length" "4")]
5272 (define_insn "tlsle24_<mode>"
5273   [(set (match_operand:P 0 "register_operand" "=r")
5274         (unspec:P [(match_operand:P 1 "register_operand" "r")
5275                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5276                    UNSPEC_TLSLE24))]
5277   ""
5278   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5279   [(set_attr "type" "multiple")
5280    (set_attr "length" "8")]
5283 (define_insn "tlsle32_<mode>"
5284   [(set (match_operand:P 0 "register_operand" "=r")
5285         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5286                    UNSPEC_TLSLE32))]
5287   ""
5288   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5289   [(set_attr "type" "multiple")
5290    (set_attr "length" "8")]
5293 (define_insn "tlsle48_<mode>"
5294   [(set (match_operand:P 0 "register_operand" "=r")
5295         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5296                    UNSPEC_TLSLE48))]
5297   ""
5298   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5299   [(set_attr "type" "multiple")
5300    (set_attr "length" "12")]
5303 (define_insn "tlsdesc_small_<mode>"
5304   [(set (reg:PTR R0_REGNUM)
5305         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5306                    UNSPEC_TLSDESC))
5307    (clobber (reg:DI LR_REGNUM))
5308    (clobber (reg:CC CC_REGNUM))
5309    (clobber (match_scratch:DI 1 "=r"))]
5310   "TARGET_TLS_DESC"
5311   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5312   [(set_attr "type" "call")
5313    (set_attr "length" "16")])
5315 (define_insn "stack_tie"
5316   [(set (mem:BLK (scratch))
5317         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5318                      (match_operand:DI 1 "register_operand" "rk")]
5319                     UNSPEC_PRLG_STK))]
5320   ""
5321   ""
5322   [(set_attr "length" "0")]
5325 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5326 ;; all of memory.  This blocks insns from being moved across this point.
5328 (define_insn "blockage"
5329   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5330   ""
5331   ""
5332   [(set_attr "length" "0")
5333    (set_attr "type" "block")]
5336 (define_insn "probe_stack_range_<PTR:mode>"
5337   [(set (match_operand:PTR 0 "register_operand" "=r")
5338         (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5339                               (match_operand:PTR 2 "register_operand" "r")]
5340                                UNSPECV_PROBE_STACK_RANGE))]
5341   ""
5343   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5345   [(set_attr "length" "32")]
5348 ;; Named pattern for expanding thread pointer reference.
5349 (define_expand "get_thread_pointerdi"
5350   [(match_operand:DI 0 "register_operand" "=r")]
5351   ""
5353   rtx tmp = aarch64_load_tp (operands[0]);
5354   if (tmp != operands[0])
5355     emit_move_insn (operands[0], tmp);
5356   DONE;
5359 ;; Named patterns for stack smashing protection.
5360 (define_expand "stack_protect_set"
5361   [(match_operand 0 "memory_operand")
5362    (match_operand 1 "memory_operand")]
5363   ""
5365   machine_mode mode = GET_MODE (operands[0]);
5367   emit_insn ((mode == DImode
5368               ? gen_stack_protect_set_di
5369               : gen_stack_protect_set_si) (operands[0], operands[1]));
5370   DONE;
5373 (define_insn "stack_protect_set_<mode>"
5374   [(set (match_operand:PTR 0 "memory_operand" "=m")
5375         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5376          UNSPEC_SP_SET))
5377    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5378   ""
5379   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5380   [(set_attr "length" "12")
5381    (set_attr "type" "multiple")])
5383 (define_expand "stack_protect_test"
5384   [(match_operand 0 "memory_operand")
5385    (match_operand 1 "memory_operand")
5386    (match_operand 2)]
5387   ""
5389   rtx result;
5390   machine_mode mode = GET_MODE (operands[0]);
5392   result = gen_reg_rtx(mode);
5394   emit_insn ((mode == DImode
5395               ? gen_stack_protect_test_di
5396               : gen_stack_protect_test_si) (result,
5397                                             operands[0],
5398                                             operands[1]));
5400   if (mode == DImode)
5401     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5402                                     result, const0_rtx, operands[2]));
5403   else
5404     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5405                                     result, const0_rtx, operands[2]));
5406   DONE;
5409 (define_insn "stack_protect_test_<mode>"
5410   [(set (match_operand:PTR 0 "register_operand" "=r")
5411         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5412                      (match_operand:PTR 2 "memory_operand" "m")]
5413          UNSPEC_SP_TEST))
5414    (clobber (match_scratch:PTR 3 "=&r"))]
5415   ""
5416   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5417   [(set_attr "length" "12")
5418    (set_attr "type" "multiple")])
5420 ;; Write Floating-point Control Register.
5421 (define_insn "set_fpcr"
5422   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5423   ""
5424   "msr\\tfpcr, %0"
5425   [(set_attr "type" "mrs")])
5427 ;; Read Floating-point Control Register.
5428 (define_insn "get_fpcr"
5429   [(set (match_operand:SI 0 "register_operand" "=r")
5430         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5431   ""
5432   "mrs\\t%0, fpcr"
5433   [(set_attr "type" "mrs")])
5435 ;; Write Floating-point Status Register.
5436 (define_insn "set_fpsr"
5437   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5438   ""
5439   "msr\\tfpsr, %0"
5440   [(set_attr "type" "mrs")])
5442 ;; Read Floating-point Status Register.
5443 (define_insn "get_fpsr"
5444   [(set (match_operand:SI 0 "register_operand" "=r")
5445         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5446   ""
5447   "mrs\\t%0, fpsr"
5448   [(set_attr "type" "mrs")])
5451 ;; Define the subtract-one-and-jump insns so loop.c
5452 ;; knows what to generate.
5453 (define_expand "doloop_end"
5454   [(use (match_operand 0 "" ""))      ; loop pseudo
5455    (use (match_operand 1 "" ""))]     ; label
5456   "optimize > 0 && flag_modulo_sched"
5458   rtx s0;
5459   rtx bcomp;
5460   rtx loc_ref;
5461   rtx cc_reg;
5462   rtx insn;
5463   rtx cmp;
5465   /* Currently SMS relies on the do-loop pattern to recognize loops
5466      where (1) the control part consists of all insns defining and/or
5467      using a certain 'count' register and (2) the loop count can be
5468      adjusted by modifying this register prior to the loop.
5469      ??? The possible introduction of a new block to initialize the
5470      new IV can potentially affect branch optimizations.  */
5472   if (GET_MODE (operands[0]) != DImode)
5473     FAIL;
5475   s0 = operands [0];
5476   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5478   cmp = XVECEXP (PATTERN (insn), 0, 0);
5479   cc_reg = SET_DEST (cmp);
5480   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5481   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5482   emit_jump_insn (gen_rtx_SET (pc_rtx,
5483                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5484                                                      loc_ref, pc_rtx)));
5485   DONE;
5488 ;; AdvSIMD Stuff
5489 (include "aarch64-simd.md")
5491 ;; Atomic Operations
5492 (include "atomics.md")
5494 ;; ldp/stp peephole patterns
5495 (include "aarch64-ldpstp.md")