[AArch64] Use SUBS for parallel subtraction and comparison with immediate
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blobd89df66fecc9873b84b6bf34d01792dd818443e6
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_AUTI1716
71     UNSPEC_AUTISP
72     UNSPEC_CASESI
73     UNSPEC_CRC32B
74     UNSPEC_CRC32CB
75     UNSPEC_CRC32CH
76     UNSPEC_CRC32CW
77     UNSPEC_CRC32CX
78     UNSPEC_CRC32H
79     UNSPEC_CRC32W
80     UNSPEC_CRC32X
81     UNSPEC_FCVTZS
82     UNSPEC_FCVTZU
83     UNSPEC_URECPE
84     UNSPEC_FRECPE
85     UNSPEC_FRECPS
86     UNSPEC_FRECPX
87     UNSPEC_FRINTA
88     UNSPEC_FRINTI
89     UNSPEC_FRINTM
90     UNSPEC_FRINTN
91     UNSPEC_FRINTP
92     UNSPEC_FRINTX
93     UNSPEC_FRINTZ
94     UNSPEC_GOTSMALLPIC
95     UNSPEC_GOTSMALLPIC28K
96     UNSPEC_GOTSMALLTLS
97     UNSPEC_GOTTINYPIC
98     UNSPEC_GOTTINYTLS
99     UNSPEC_LD1
100     UNSPEC_LD2
101     UNSPEC_LD2_DUP
102     UNSPEC_LD3
103     UNSPEC_LD3_DUP
104     UNSPEC_LD4
105     UNSPEC_LD4_DUP
106     UNSPEC_LD2_LANE
107     UNSPEC_LD3_LANE
108     UNSPEC_LD4_LANE
109     UNSPEC_MB
110     UNSPEC_NOP
111     UNSPEC_PACI1716
112     UNSPEC_PACISP
113     UNSPEC_PRLG_STK
114     UNSPEC_RBIT
115     UNSPEC_SCVTF
116     UNSPEC_SISD_NEG
117     UNSPEC_SISD_SSHL
118     UNSPEC_SISD_USHL
119     UNSPEC_SSHL_2S
120     UNSPEC_ST1
121     UNSPEC_ST2
122     UNSPEC_ST3
123     UNSPEC_ST4
124     UNSPEC_ST2_LANE
125     UNSPEC_ST3_LANE
126     UNSPEC_ST4_LANE
127     UNSPEC_TLS
128     UNSPEC_TLSDESC
129     UNSPEC_TLSLE12
130     UNSPEC_TLSLE24
131     UNSPEC_TLSLE32
132     UNSPEC_TLSLE48
133     UNSPEC_UCVTF
134     UNSPEC_USHL_2S
135     UNSPEC_VSTRUCTDUMMY
136     UNSPEC_SP_SET
137     UNSPEC_SP_TEST
138     UNSPEC_RSQRT
139     UNSPEC_RSQRTE
140     UNSPEC_RSQRTS
141     UNSPEC_NZCV
142     UNSPEC_XPACLRI
145 (define_c_enum "unspecv" [
146     UNSPECV_EH_RETURN           ; Represent EH_RETURN
147     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
148     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
149     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
150     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
151     UNSPECV_BLOCKAGE            ; Represent a blockage
152     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
153   ]
156 ;; If further include files are added the defintion of MD_INCLUDES
157 ;; must be updated.
159 (include "constraints.md")
160 (include "predicates.md")
161 (include "iterators.md")
163 ;; -------------------------------------------------------------------
164 ;; Instruction types and attributes
165 ;; -------------------------------------------------------------------
167 ; The "type" attribute is included here from AArch32 backend to be able
168 ; to share pipeline descriptions.
169 (include "../arm/types.md")
171 ;; It is important to set the fp or simd attributes to yes when a pattern
172 ;; alternative uses the FP or SIMD register files, usually signified by use of
173 ;; the 'w' constraint.  This will ensure that the alternative will be
174 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
175 ;; architecture extensions.  If all the alternatives in a pattern use the
176 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
177 ;; or TARGET_SIMD.
179 ;; Attribute that specifies whether or not the instruction touches fp
180 ;; registers.  When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_FLOAT.
182 (define_attr "fp" "no,yes" (const_string "no"))
184 ;; Attribute that specifies whether or not the instruction touches simd
185 ;; registers.  When this is set to yes for an alternative, that alternative
186 ;; will be disabled when !TARGET_SIMD.
187 (define_attr "simd" "no,yes" (const_string "no"))
189 (define_attr "length" ""
190   (const_int 4))
192 ;; Attribute that controls whether an alternative is enabled or not.
193 ;; Currently it is only used to disable alternatives which touch fp or simd
194 ;; registers when -mgeneral-regs-only is specified.
195 (define_attr "enabled" "no,yes"
196   (cond [(ior
197         (and (eq_attr "fp" "yes")
198              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
199         (and (eq_attr "simd" "yes")
200              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
201              (const_string "no")
202         ] (const_string "yes")))
204 ;; Attribute that specifies whether we are dealing with a branch to a
205 ;; label that is far away, i.e. further away than the maximum/minimum
206 ;; representable in a signed 21-bits number.
207 ;; 0 :=: no
208 ;; 1 :=: yes
209 (define_attr "far_branch" "" (const_int 0))
211 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
212 ;; no predicated insns.
213 (define_attr "predicated" "yes,no" (const_string "no"))
215 ;; -------------------------------------------------------------------
216 ;; Pipeline descriptions and scheduling
217 ;; -------------------------------------------------------------------
219 ;; Processor types.
220 (include "aarch64-tune.md")
222 ;; Scheduling
223 (include "../arm/cortex-a53.md")
224 (include "../arm/cortex-a57.md")
225 (include "../arm/exynos-m1.md")
226 (include "thunderx.md")
227 (include "../arm/xgene1.md")
228 (include "thunderx2t99.md")
230 ;; -------------------------------------------------------------------
231 ;; Jumps and other miscellaneous insns
232 ;; -------------------------------------------------------------------
234 (define_insn "indirect_jump"
235   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
236   ""
237   "br\\t%0"
238   [(set_attr "type" "branch")]
241 (define_insn "jump"
242   [(set (pc) (label_ref (match_operand 0 "" "")))]
243   ""
244   "b\\t%l0"
245   [(set_attr "type" "branch")]
248 (define_expand "cbranch<mode>4"
249   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
250                             [(match_operand:GPI 1 "register_operand" "")
251                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
252                            (label_ref (match_operand 3 "" ""))
253                            (pc)))]
254   ""
255   "
256   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
257                                          operands[2]);
258   operands[2] = const0_rtx;
259   "
262 (define_expand "cbranch<mode>4"
263   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
264                             [(match_operand:GPF 1 "register_operand" "")
265                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
266                            (label_ref (match_operand 3 "" ""))
267                            (pc)))]
268   ""
269   "
270   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
271                                          operands[2]);
272   operands[2] = const0_rtx;
273   "
276 (define_expand "cbranchcc4"
277   [(set (pc) (if_then_else
278               (match_operator 0 "aarch64_comparison_operator"
279                [(match_operand 1 "cc_register" "")
280                 (match_operand 2 "const0_operand")])
281               (label_ref (match_operand 3 "" ""))
282               (pc)))]
283   ""
284   "")
286 (define_insn "ccmp<mode>"
287   [(set (match_operand:CC 1 "cc_register" "")
288         (if_then_else:CC
289           (match_operator 4 "aarch64_comparison_operator"
290            [(match_operand 0 "cc_register" "")
291             (const_int 0)])
292           (compare:CC
293             (match_operand:GPI 2 "register_operand" "r,r,r")
294             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
295           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
296   ""
297   "@
298    ccmp\\t%<w>2, %<w>3, %k5, %m4
299    ccmp\\t%<w>2, %3, %k5, %m4
300    ccmn\\t%<w>2, #%n3, %k5, %m4"
301   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
304 (define_insn "fccmp<mode>"
305   [(set (match_operand:CCFP 1 "cc_register" "")
306         (if_then_else:CCFP
307           (match_operator 4 "aarch64_comparison_operator"
308            [(match_operand 0 "cc_register" "")
309             (const_int 0)])
310           (compare:CCFP
311             (match_operand:GPF 2 "register_operand" "w")
312             (match_operand:GPF 3 "register_operand" "w"))
313           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
314   "TARGET_FLOAT"
315   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
316   [(set_attr "type" "fccmp<s>")]
319 (define_insn "fccmpe<mode>"
320   [(set (match_operand:CCFPE 1 "cc_register" "")
321          (if_then_else:CCFPE
322           (match_operator 4 "aarch64_comparison_operator"
323            [(match_operand 0 "cc_register" "")
324           (const_int 0)])
325            (compare:CCFPE
326             (match_operand:GPF 2 "register_operand" "w")
327             (match_operand:GPF 3 "register_operand" "w"))
328           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
329   "TARGET_FLOAT"
330   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
331   [(set_attr "type" "fccmp<s>")]
334 ;; Expansion of signed mod by a power of 2 using CSNEG.
335 ;; For x0 % n where n is a power of 2 produce:
336 ;; negs   x1, x0
337 ;; and    x0, x0, #(n - 1)
338 ;; and    x1, x1, #(n - 1)
339 ;; csneg  x0, x0, x1, mi
341 (define_expand "mod<mode>3"
342   [(match_operand:GPI 0 "register_operand" "")
343    (match_operand:GPI 1 "register_operand" "")
344    (match_operand:GPI 2 "const_int_operand" "")]
345   ""
346   {
347     HOST_WIDE_INT val = INTVAL (operands[2]);
349     if (val <= 0
350        || exact_log2 (val) <= 0
351        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
352       FAIL;
354     rtx mask = GEN_INT (val - 1);
356     /* In the special case of x0 % 2 we can do the even shorter:
357         cmp    x0, xzr
358         and    x0, x0, 1
359         cneg   x0, x0, lt.  */
360     if (val == 2)
361       {
362         rtx masked = gen_reg_rtx (<MODE>mode);
363         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
364         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
365         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
366         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
367         DONE;
368       }
370     rtx neg_op = gen_reg_rtx (<MODE>mode);
371     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
373     /* Extract the condition register and mode.  */
374     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
375     rtx cc_reg = SET_DEST (cmp);
376     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
378     rtx masked_pos = gen_reg_rtx (<MODE>mode);
379     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
381     rtx masked_neg = gen_reg_rtx (<MODE>mode);
382     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
384     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
385                                        masked_neg, masked_pos));
386     DONE;
387   }
390 (define_insn "condjump"
391   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
392                             [(match_operand 1 "cc_register" "") (const_int 0)])
393                            (label_ref (match_operand 2 "" ""))
394                            (pc)))]
395   ""
396   {
397     if (get_attr_length (insn) == 8)
398       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
399     else
400       return  "b%m0\\t%l2";
401   }
402   [(set_attr "type" "branch")
403    (set (attr "length")
404         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
405                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
406                       (const_int 4)
407                       (const_int 8)))
408    (set (attr "far_branch")
409         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
410                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
411                       (const_int 0)
412                       (const_int 1)))]
415 ;; For a 24-bit immediate CST we can optimize the compare for equality
416 ;; and branch sequence from:
417 ;;      mov     x0, #imm1
418 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
419 ;;      cmp     x1, x0
420 ;;      b<ne,eq> .Label
421 ;; into the shorter:
422 ;;      sub     x0, x1, #(CST & 0xfff000)
423 ;;      subs    x0, x0, #(CST & 0x000fff)
424 ;;      b<ne,eq> .Label
425 (define_insn_and_split "*compare_condjump<mode>"
426   [(set (pc) (if_then_else (EQL
427                               (match_operand:GPI 0 "register_operand" "r")
428                               (match_operand:GPI 1 "aarch64_imm24" "n"))
429                            (label_ref:P (match_operand 2 "" ""))
430                            (pc)))]
431   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
432    && !aarch64_plus_operand (operands[1], <MODE>mode)
433    && !reload_completed"
434   "#"
435   "&& true"
436   [(const_int 0)]
437   {
438     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
439     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
440     rtx tmp = gen_reg_rtx (<MODE>mode);
441     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
442     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
443     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
444     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
445     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
446     DONE;
447   }
450 (define_expand "casesi"
451   [(match_operand:SI 0 "register_operand" "")   ; Index
452    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
453    (match_operand:SI 2 "const_int_operand" "")  ; Total range
454    (match_operand:DI 3 "" "")                   ; Table label
455    (match_operand:DI 4 "" "")]                  ; Out of range label
456   ""
457   {
458     if (operands[1] != const0_rtx)
459       {
460         rtx reg = gen_reg_rtx (SImode);
462         /* Canonical RTL says that if you have:
464            (minus (X) (CONST))
466            then this should be emitted as:
468            (plus (X) (-CONST))
470            The use of trunc_int_for_mode ensures that the resulting
471            constant can be represented in SImode, this is important
472            for the corner case where operand[1] is INT_MIN.  */
474         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
476         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
477               (operands[1], SImode))
478           operands[1] = force_reg (SImode, operands[1]);
479         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
480         operands[0] = reg;
481       }
483     if (!aarch64_plus_operand (operands[2], SImode))
484       operands[2] = force_reg (SImode, operands[2]);
485     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
486                                                  const0_rtx),
487                                     operands[0], operands[2], operands[4]));
489     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
490     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
491                                          operands[3]));
492     DONE;
493   }
496 (define_insn "casesi_dispatch"
497   [(parallel
498     [(set (pc)
499           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
500                            (match_operand:SI 1 "register_operand" "r")]
501                         UNSPEC_CASESI)))
502      (clobber (reg:CC CC_REGNUM))
503      (clobber (match_scratch:DI 3 "=r"))
504      (clobber (match_scratch:DI 4 "=r"))
505      (use (label_ref (match_operand 2 "" "")))])]
506   ""
507   "*
508   return aarch64_output_casesi (operands);
509   "
510   [(set_attr "length" "16")
511    (set_attr "type" "branch")]
514 (define_insn "nop"
515   [(unspec[(const_int 0)] UNSPEC_NOP)]
516   ""
517   "nop"
518   [(set_attr "type" "no_insn")]
521 (define_insn "prefetch"
522   [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
523             (match_operand:QI 1 "const_int_operand" "")
524             (match_operand:QI 2 "const_int_operand" ""))]
525   ""
526   {
527     const char * pftype[2][4] =
528     {
529       {"prfm\\tPLDL1STRM, %0",
530        "prfm\\tPLDL3KEEP, %0",
531        "prfm\\tPLDL2KEEP, %0",
532        "prfm\\tPLDL1KEEP, %0"},
533       {"prfm\\tPSTL1STRM, %0",
534        "prfm\\tPSTL3KEEP, %0",
535        "prfm\\tPSTL2KEEP, %0",
536        "prfm\\tPSTL1KEEP, %0"},
537     };
539     int locality = INTVAL (operands[2]);
541     gcc_assert (IN_RANGE (locality, 0, 3));
543     /* PRFM accepts the same addresses as a 64-bit LDR so wrap
544        the address into a DImode MEM so that aarch64_print_operand knows
545        how to print it.  */
546     operands[0] = gen_rtx_MEM (DImode, operands[0]);
547     return pftype[INTVAL(operands[1])][locality];
548   }
549   [(set_attr "type" "load1")]
552 (define_insn "trap"
553   [(trap_if (const_int 1) (const_int 8))]
554   ""
555   "brk #1000"
556   [(set_attr "type" "trap")])
558 (define_expand "prologue"
559   [(clobber (const_int 0))]
560   ""
561   "
562   aarch64_expand_prologue ();
563   DONE;
564   "
567 (define_expand "epilogue"
568   [(clobber (const_int 0))]
569   ""
570   "
571   aarch64_expand_epilogue (false);
572   DONE;
573   "
576 (define_expand "sibcall_epilogue"
577   [(clobber (const_int 0))]
578   ""
579   "
580   aarch64_expand_epilogue (true);
581   DONE;
582   "
585 (define_insn "*do_return"
586   [(return)]
587   ""
588   {
589     if (aarch64_return_address_signing_enabled ()
590         && TARGET_ARMV8_3
591         && !crtl->calls_eh_return)
592       return "retaa";
594     return "ret";
595   }
596   [(set_attr "type" "branch")]
599 (define_expand "return"
600   [(simple_return)]
601   "aarch64_use_return_insn_p ()"
602   ""
605 (define_insn "simple_return"
606   [(simple_return)]
607   ""
608   "ret"
609   [(set_attr "type" "branch")]
612 (define_insn "*cb<optab><mode>1"
613   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
614                                 (const_int 0))
615                            (label_ref (match_operand 1 "" ""))
616                            (pc)))]
617   ""
618   {
619     if (get_attr_length (insn) == 8)
620       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
621     else
622       return "<cbz>\\t%<w>0, %l1";
623   }
624   [(set_attr "type" "branch")
625    (set (attr "length")
626         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
627                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
628                       (const_int 4)
629                       (const_int 8)))
630    (set (attr "far_branch")
631         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
632                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
633                       (const_int 0)
634                       (const_int 1)))]
637 (define_insn "*tb<optab><mode>1"
638   [(set (pc) (if_then_else
639               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
640                                     (const_int 1)
641                                     (match_operand 1
642                                       "aarch64_simd_shift_imm_<mode>" "n"))
643                    (const_int 0))
644              (label_ref (match_operand 2 "" ""))
645              (pc)))
646    (clobber (reg:CC CC_REGNUM))]
647   ""
648   {
649     if (get_attr_length (insn) == 8)
650       {
651         if (get_attr_far_branch (insn) == 1)
652           return aarch64_gen_far_branch (operands, 2, "Ltb",
653                                          "<inv_tb>\\t%<w>0, %1, ");
654         else
655           {
656             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
657             return "tst\t%<w>0, %1\;<bcond>\t%l2";
658           }
659       }
660     else
661       return "<tbz>\t%<w>0, %1, %l2";
662   }
663   [(set_attr "type" "branch")
664    (set (attr "length")
665         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
666                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
667                       (const_int 4)
668                       (const_int 8)))
669    (set (attr "far_branch")
670         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
671                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
672                       (const_int 0)
673                       (const_int 1)))]
677 (define_insn "*cb<optab><mode>1"
678   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
679                                  (const_int 0))
680                            (label_ref (match_operand 1 "" ""))
681                            (pc)))
682    (clobber (reg:CC CC_REGNUM))]
683   ""
684   {
685     if (get_attr_length (insn) == 8)
686       {
687         if (get_attr_far_branch (insn) == 1)
688           return aarch64_gen_far_branch (operands, 1, "Ltb",
689                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
690         else
691           {
692             char buf[64];
693             uint64_t val = ((uint64_t) 1)
694                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
695             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
696             output_asm_insn (buf, operands);
697             return "<bcond>\t%l1";
698           }
699       }
700     else
701       return "<tbz>\t%<w>0, <sizem1>, %l1";
702   }
703   [(set_attr "type" "branch")
704    (set (attr "length")
705         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
706                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
707                       (const_int 4)
708                       (const_int 8)))
709    (set (attr "far_branch")
710         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
711                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
712                       (const_int 0)
713                       (const_int 1)))]
716 ;; -------------------------------------------------------------------
717 ;; Subroutine calls and sibcalls
718 ;; -------------------------------------------------------------------
720 (define_expand "call"
721   [(parallel [(call (match_operand 0 "memory_operand" "")
722                     (match_operand 1 "general_operand" ""))
723               (use (match_operand 2 "" ""))
724               (clobber (reg:DI LR_REGNUM))])]
725   ""
726   "
727   {
728     aarch64_expand_call (NULL_RTX, operands[0], false);
729     DONE;
730   }"
733 (define_insn "*call_insn"
734   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
735          (match_operand 1 "" ""))
736    (clobber (reg:DI LR_REGNUM))]
737   ""
738   "@
739   blr\\t%0
740   bl\\t%a0"
741   [(set_attr "type" "call, call")]
744 (define_expand "call_value"
745   [(parallel [(set (match_operand 0 "" "")
746                    (call (match_operand 1 "memory_operand" "")
747                          (match_operand 2 "general_operand" "")))
748               (use (match_operand 3 "" ""))
749               (clobber (reg:DI LR_REGNUM))])]
750   ""
751   "
752   {
753     aarch64_expand_call (operands[0], operands[1], false);
754     DONE;
755   }"
758 (define_insn "*call_value_insn"
759   [(set (match_operand 0 "" "")
760         (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
761                       (match_operand 2 "" "")))
762    (clobber (reg:DI LR_REGNUM))]
763   ""
764   "@
765   blr\\t%1
766   bl\\t%a1"
767   [(set_attr "type" "call, call")]
770 (define_expand "sibcall"
771   [(parallel [(call (match_operand 0 "memory_operand" "")
772                     (match_operand 1 "general_operand" ""))
773               (return)
774               (use (match_operand 2 "" ""))])]
775   ""
776   {
777     aarch64_expand_call (NULL_RTX, operands[0], true);
778     DONE;
779   }
782 (define_expand "sibcall_value"
783   [(parallel [(set (match_operand 0 "" "")
784                    (call (match_operand 1 "memory_operand" "")
785                          (match_operand 2 "general_operand" "")))
786               (return)
787               (use (match_operand 3 "" ""))])]
788   ""
789   {
790     aarch64_expand_call (operands[0], operands[1], true);
791     DONE;
792   }
795 (define_insn "*sibcall_insn"
796   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
797          (match_operand 1 "" ""))
798    (return)]
799   "SIBLING_CALL_P (insn)"
800   "@
801    br\\t%0
802    b\\t%a0"
803   [(set_attr "type" "branch, branch")]
806 (define_insn "*sibcall_value_insn"
807   [(set (match_operand 0 "" "")
808         (call (mem:DI
809                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
810               (match_operand 2 "" "")))
811    (return)]
812   "SIBLING_CALL_P (insn)"
813   "@
814    br\\t%1
815    b\\t%a1"
816   [(set_attr "type" "branch, branch")]
819 ;; Call subroutine returning any type.
821 (define_expand "untyped_call"
822   [(parallel [(call (match_operand 0 "")
823                     (const_int 0))
824               (match_operand 1 "")
825               (match_operand 2 "")])]
826   ""
828   int i;
830   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
832   for (i = 0; i < XVECLEN (operands[2], 0); i++)
833     {
834       rtx set = XVECEXP (operands[2], 0, i);
835       emit_move_insn (SET_DEST (set), SET_SRC (set));
836     }
838   /* The optimizer does not know that the call sets the function value
839      registers we stored in the result block.  We avoid problems by
840      claiming that all hard registers are used and clobbered at this
841      point.  */
842   emit_insn (gen_blockage ());
843   DONE;
846 ;; -------------------------------------------------------------------
847 ;; Moves
848 ;; -------------------------------------------------------------------
850 (define_expand "mov<mode>"
851   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
852         (match_operand:SHORT 1 "general_operand" ""))]
853   ""
854   "
855     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
856       operands[1] = force_reg (<MODE>mode, operands[1]);
857   "
860 (define_insn "*mov<mode>_aarch64"
861   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
862         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
863   "(register_operand (operands[0], <MODE>mode)
864     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
866    switch (which_alternative)
867      {
868      case 0:
869        return "mov\t%w0, %w1";
870      case 1:
871        return "mov\t%w0, %1";
872      case 2:
873        return aarch64_output_scalar_simd_mov_immediate (operands[1],
874                                                         <MODE>mode);
875      case 3:
876        return "ldr<size>\t%w0, %1";
877      case 4:
878        return "ldr\t%<size>0, %1";
879      case 5:
880        return "str<size>\t%w1, %0";
881      case 6:
882        return "str\t%<size>1, %0";
883      case 7:
884        return "umov\t%w0, %1.<v>[0]";
885      case 8:
886        return "dup\t%0.<Vallxd>, %w1";
887      case 9:
888        return "dup\t%<Vetype>0, %1.<v>[0]";
889      default:
890        gcc_unreachable ();
891      }
893   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
894                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
895    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
898 (define_expand "mov<mode>"
899   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
900         (match_operand:GPI 1 "general_operand" ""))]
901   ""
902   "
903     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
904         && <MODE>mode == DImode
905         && aarch64_split_dimode_const_store (operands[0], operands[1]))
906       DONE;
908     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
909       operands[1] = force_reg (<MODE>mode, operands[1]);
911     /* FIXME: RR we still need to fix up what we are doing with
912        symbol_refs and other types of constants.  */
913     if (CONSTANT_P (operands[1])
914         && !CONST_INT_P (operands[1]))
915      {
916        aarch64_expand_mov_immediate (operands[0], operands[1]);
917        DONE;
918      }
919   "
922 (define_insn_and_split "*movsi_aarch64"
923   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w,r,*w")
924         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w"))]
925   "(register_operand (operands[0], SImode)
926     || aarch64_reg_or_zero (operands[1], SImode))"
927   "@
928    mov\\t%w0, %w1
929    mov\\t%w0, %w1
930    mov\\t%w0, %w1
931    mov\\t%w0, %1
932    #
933    ldr\\t%w0, %1
934    ldr\\t%s0, %1
935    str\\t%w1, %0
936    str\\t%s1, %0
937    adr\\t%x0, %a1
938    adrp\\t%x0, %A1
939    fmov\\t%s0, %w1
940    fmov\\t%w0, %s1
941    fmov\\t%s0, %s1"
942    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
943     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
944    [(const_int 0)]
945    "{
946        aarch64_expand_mov_immediate (operands[0], operands[1]);
947        DONE;
948     }"
949   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
950                      adr,adr,f_mcr,f_mrc,fmov")
951    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
954 (define_insn_and_split "*movdi_aarch64"
955   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w,r,*w,w")
956         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
957   "(register_operand (operands[0], DImode)
958     || aarch64_reg_or_zero (operands[1], DImode))"
959   "@
960    mov\\t%x0, %x1
961    mov\\t%0, %x1
962    mov\\t%x0, %1
963    mov\\t%x0, %1
964    #
965    ldr\\t%x0, %1
966    ldr\\t%d0, %1
967    str\\t%x1, %0
968    str\\t%d1, %0
969    adr\\t%x0, %a1
970    adrp\\t%x0, %A1
971    fmov\\t%d0, %x1
972    fmov\\t%x0, %d1
973    fmov\\t%d0, %d1
974    movi\\t%d0, %1"
975    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
976     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
977    [(const_int 0)]
978    "{
979        aarch64_expand_mov_immediate (operands[0], operands[1]);
980        DONE;
981     }"
982   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
983                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
984    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
985    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
988 (define_insn "insv_imm<mode>"
989   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
990                           (const_int 16)
991                           (match_operand:GPI 1 "const_int_operand" "n"))
992         (match_operand:GPI 2 "const_int_operand" "n"))]
993   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
994    && UINTVAL (operands[1]) % 16 == 0"
995   "movk\\t%<w>0, %X2, lsl %1"
996   [(set_attr "type" "mov_imm")]
999 (define_expand "movti"
1000   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1001         (match_operand:TI 1 "general_operand" ""))]
1002   ""
1003   "
1004     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1005       operands[1] = force_reg (TImode, operands[1]);
1006   "
1009 (define_insn "*movti_aarch64"
1010   [(set (match_operand:TI 0
1011          "nonimmediate_operand"  "=r, *w,r ,*w,r,m,m,*w,m")
1012         (match_operand:TI 1
1013          "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1014   "(register_operand (operands[0], TImode)
1015     || aarch64_reg_or_zero (operands[1], TImode))"
1016   "@
1017    #
1018    #
1019    #
1020    orr\\t%0.16b, %1.16b, %1.16b
1021    ldp\\t%0, %H0, %1
1022    stp\\t%1, %H1, %0
1023    stp\\txzr, xzr, %0
1024    ldr\\t%q0, %1
1025    str\\t%q1, %0"
1026   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1027                              load2,store2,store2,f_loadd,f_stored")
1028    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1029    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1030    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1033 ;; Split a TImode register-register or register-immediate move into
1034 ;; its component DImode pieces, taking care to handle overlapping
1035 ;; source and dest registers.
1036 (define_split
1037    [(set (match_operand:TI 0 "register_operand" "")
1038          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1039   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1040   [(const_int 0)]
1042   aarch64_split_128bit_move (operands[0], operands[1]);
1043   DONE;
1046 (define_expand "mov<mode>"
1047   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1048         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1049   ""
1050   {
1051     if (!TARGET_FLOAT)
1052       {
1053         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1054         FAIL;
1055       }
1057     if (GET_CODE (operands[0]) == MEM
1058         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1059               && aarch64_float_const_zero_rtx_p (operands[1])))
1060       operands[1] = force_reg (<MODE>mode, operands[1]);
1061   }
1064 (define_insn "*movhf_aarch64"
1065   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w,m,r,m ,r")
1066         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,m,w,m,rY,r"))]
1067   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1068     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1069   "@
1070    movi\\t%0.4h, #0
1071    mov\\t%0.h[0], %w1
1072    umov\\t%w0, %1.h[0]
1073    mov\\t%0.h[0], %1.h[0]
1074    ldr\\t%h0, %1
1075    str\\t%h1, %0
1076    ldrh\\t%w0, %1
1077    strh\\t%w1, %0
1078    mov\\t%w0, %w1"
1079   [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1080                      f_loads,f_stores,load1,store1,mov_reg")
1081    (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1084 (define_insn "*movsf_aarch64"
1085   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1086         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1087   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1088     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1089   "@
1090    movi\\t%0.2s, #0
1091    fmov\\t%s0, %w1
1092    fmov\\t%w0, %s1
1093    fmov\\t%s0, %s1
1094    fmov\\t%s0, %1
1095    ldr\\t%s0, %1
1096    str\\t%s1, %0
1097    ldr\\t%w0, %1
1098    str\\t%w1, %0
1099    mov\\t%w0, %w1"
1100   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1101                      f_loads,f_stores,load1,store1,mov_reg")
1102    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1105 (define_insn "*movdf_aarch64"
1106   [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1107         (match_operand:DF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1108   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1109     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1110   "@
1111    movi\\t%d0, #0
1112    fmov\\t%d0, %x1
1113    fmov\\t%x0, %d1
1114    fmov\\t%d0, %d1
1115    fmov\\t%d0, %1
1116    ldr\\t%d0, %1
1117    str\\t%d1, %0
1118    ldr\\t%x0, %1
1119    str\\t%x1, %0
1120    mov\\t%x0, %x1"
1121   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1122                      f_loadd,f_stored,load1,store1,mov_reg")
1123    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1126 (define_insn "*movtf_aarch64"
1127   [(set (match_operand:TF 0
1128          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1129         (match_operand:TF 1
1130          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1131   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1132     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1133   "@
1134    orr\\t%0.16b, %1.16b, %1.16b
1135    #
1136    #
1137    #
1138    movi\\t%0.2d, #0
1139    fmov\\t%s0, wzr
1140    ldr\\t%q0, %1
1141    str\\t%q1, %0
1142    ldp\\t%0, %H0, %1
1143    stp\\t%1, %H1, %0
1144    stp\\txzr, xzr, %0"
1145   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1146                      f_loadd,f_stored,load2,store2,store2")
1147    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1148    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1151 (define_split
1152    [(set (match_operand:TF 0 "register_operand" "")
1153          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1154   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1155   [(const_int 0)]
1156   {
1157     aarch64_split_128bit_move (operands[0], operands[1]);
1158     DONE;
1159   }
1162 ;; 0 is dst
1163 ;; 1 is src
1164 ;; 2 is size of move in bytes
1165 ;; 3 is alignment
1167 (define_expand "movmemdi"
1168   [(match_operand:BLK 0 "memory_operand")
1169    (match_operand:BLK 1 "memory_operand")
1170    (match_operand:DI 2 "immediate_operand")
1171    (match_operand:DI 3 "immediate_operand")]
1172    "!STRICT_ALIGNMENT"
1174   if (aarch64_expand_movmem (operands))
1175     DONE;
1176   FAIL;
1180 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1181 ;; fairly lax checking on the second memory operation.
1182 (define_insn "load_pairsi"
1183   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1184         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1185    (set (match_operand:SI 2 "register_operand" "=r,*w")
1186         (match_operand:SI 3 "memory_operand" "m,m"))]
1187   "rtx_equal_p (XEXP (operands[3], 0),
1188                 plus_constant (Pmode,
1189                                XEXP (operands[1], 0),
1190                                GET_MODE_SIZE (SImode)))"
1191   "@
1192    ldp\\t%w0, %w2, %1
1193    ldp\\t%s0, %s2, %1"
1194   [(set_attr "type" "load2,neon_load1_2reg")
1195    (set_attr "fp" "*,yes")]
1198 (define_insn "load_pairdi"
1199   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1200         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1201    (set (match_operand:DI 2 "register_operand" "=r,*w")
1202         (match_operand:DI 3 "memory_operand" "m,m"))]
1203   "rtx_equal_p (XEXP (operands[3], 0),
1204                 plus_constant (Pmode,
1205                                XEXP (operands[1], 0),
1206                                GET_MODE_SIZE (DImode)))"
1207   "@
1208    ldp\\t%x0, %x2, %1
1209    ldp\\t%d0, %d2, %1"
1210   [(set_attr "type" "load2,neon_load1_2reg")
1211    (set_attr "fp" "*,yes")]
1215 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1216 ;; fairly lax checking on the second memory operation.
1217 (define_insn "store_pairsi"
1218   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1219         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1220    (set (match_operand:SI 2 "memory_operand" "=m,m")
1221         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1222   "rtx_equal_p (XEXP (operands[2], 0),
1223                 plus_constant (Pmode,
1224                                XEXP (operands[0], 0),
1225                                GET_MODE_SIZE (SImode)))"
1226   "@
1227    stp\\t%w1, %w3, %0
1228    stp\\t%s1, %s3, %0"
1229   [(set_attr "type" "store2,neon_store1_2reg")
1230    (set_attr "fp" "*,yes")]
1233 (define_insn "store_pairdi"
1234   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1235         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1236    (set (match_operand:DI 2 "memory_operand" "=m,m")
1237         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1238   "rtx_equal_p (XEXP (operands[2], 0),
1239                 plus_constant (Pmode,
1240                                XEXP (operands[0], 0),
1241                                GET_MODE_SIZE (DImode)))"
1242   "@
1243    stp\\t%x1, %x3, %0
1244    stp\\t%d1, %d3, %0"
1245   [(set_attr "type" "store2,neon_store1_2reg")
1246    (set_attr "fp" "*,yes")]
1249 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1250 ;; fairly lax checking on the second memory operation.
1251 (define_insn "load_pairsf"
1252   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1253         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1254    (set (match_operand:SF 2 "register_operand" "=w,*r")
1255         (match_operand:SF 3 "memory_operand" "m,m"))]
1256   "rtx_equal_p (XEXP (operands[3], 0),
1257                 plus_constant (Pmode,
1258                                XEXP (operands[1], 0),
1259                                GET_MODE_SIZE (SFmode)))"
1260   "@
1261    ldp\\t%s0, %s2, %1
1262    ldp\\t%w0, %w2, %1"
1263   [(set_attr "type" "neon_load1_2reg,load2")
1264    (set_attr "fp" "yes,*")]
1267 (define_insn "load_pairdf"
1268   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1269         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1270    (set (match_operand:DF 2 "register_operand" "=w,*r")
1271         (match_operand:DF 3 "memory_operand" "m,m"))]
1272   "rtx_equal_p (XEXP (operands[3], 0),
1273                 plus_constant (Pmode,
1274                                XEXP (operands[1], 0),
1275                                GET_MODE_SIZE (DFmode)))"
1276   "@
1277    ldp\\t%d0, %d2, %1
1278    ldp\\t%x0, %x2, %1"
1279   [(set_attr "type" "neon_load1_2reg,load2")
1280    (set_attr "fp" "yes,*")]
1283 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1284 ;; fairly lax checking on the second memory operation.
1285 (define_insn "store_pairsf"
1286   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1287         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1288    (set (match_operand:SF 2 "memory_operand" "=m,m")
1289         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1290   "rtx_equal_p (XEXP (operands[2], 0),
1291                 plus_constant (Pmode,
1292                                XEXP (operands[0], 0),
1293                                GET_MODE_SIZE (SFmode)))"
1294   "@
1295    stp\\t%s1, %s3, %0
1296    stp\\t%w1, %w3, %0"
1297   [(set_attr "type" "neon_store1_2reg,store2")
1298    (set_attr "fp" "yes,*")]
1301 (define_insn "store_pairdf"
1302   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1303         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1304    (set (match_operand:DF 2 "memory_operand" "=m,m")
1305         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1306   "rtx_equal_p (XEXP (operands[2], 0),
1307                 plus_constant (Pmode,
1308                                XEXP (operands[0], 0),
1309                                GET_MODE_SIZE (DFmode)))"
1310   "@
1311    stp\\t%d1, %d3, %0
1312    stp\\t%x1, %x3, %0"
1313   [(set_attr "type" "neon_store1_2reg,store2")
1314    (set_attr "fp" "yes,*")]
1317 ;; Load pair with post-index writeback.  This is primarily used in function
1318 ;; epilogues.
1319 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1320   [(parallel
1321     [(set (match_operand:P 0 "register_operand" "=k")
1322           (plus:P (match_operand:P 1 "register_operand" "0")
1323                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1324      (set (match_operand:GPI 2 "register_operand" "=r")
1325           (mem:GPI (match_dup 1)))
1326      (set (match_operand:GPI 3 "register_operand" "=r")
1327           (mem:GPI (plus:P (match_dup 1)
1328                    (match_operand:P 5 "const_int_operand" "n"))))])]
1329   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1330   "ldp\\t%<w>2, %<w>3, [%1], %4"
1331   [(set_attr "type" "load2")]
1334 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1335   [(parallel
1336     [(set (match_operand:P 0 "register_operand" "=k")
1337           (plus:P (match_operand:P 1 "register_operand" "0")
1338                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1339      (set (match_operand:GPF 2 "register_operand" "=w")
1340           (mem:GPF (match_dup 1)))
1341      (set (match_operand:GPF 3 "register_operand" "=w")
1342           (mem:GPF (plus:P (match_dup 1)
1343                    (match_operand:P 5 "const_int_operand" "n"))))])]
1344   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1345   "ldp\\t%<w>2, %<w>3, [%1], %4"
1346   [(set_attr "type" "neon_load1_2reg")]
1349 ;; Store pair with pre-index writeback.  This is primarily used in function
1350 ;; prologues.
1351 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1352   [(parallel
1353     [(set (match_operand:P 0 "register_operand" "=&k")
1354           (plus:P (match_operand:P 1 "register_operand" "0")
1355                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1356      (set (mem:GPI (plus:P (match_dup 0)
1357                    (match_dup 4)))
1358           (match_operand:GPI 2 "register_operand" "r"))
1359      (set (mem:GPI (plus:P (match_dup 0)
1360                    (match_operand:P 5 "const_int_operand" "n")))
1361           (match_operand:GPI 3 "register_operand" "r"))])]
1362   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1363   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1364   [(set_attr "type" "store2")]
1367 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1368   [(parallel
1369     [(set (match_operand:P 0 "register_operand" "=&k")
1370           (plus:P (match_operand:P 1 "register_operand" "0")
1371                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1372      (set (mem:GPF (plus:P (match_dup 0)
1373                    (match_dup 4)))
1374           (match_operand:GPF 2 "register_operand" "w"))
1375      (set (mem:GPF (plus:P (match_dup 0)
1376                    (match_operand:P 5 "const_int_operand" "n")))
1377           (match_operand:GPF 3 "register_operand" "w"))])]
1378   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1379   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1380   [(set_attr "type" "neon_store1_2reg<q>")]
1383 ;; -------------------------------------------------------------------
1384 ;; Sign/Zero extension
1385 ;; -------------------------------------------------------------------
1387 (define_expand "<optab>sidi2"
1388   [(set (match_operand:DI 0 "register_operand")
1389         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1390   ""
1393 (define_insn "*extendsidi2_aarch64"
1394   [(set (match_operand:DI 0 "register_operand" "=r,r")
1395         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1396   ""
1397   "@
1398    sxtw\t%0, %w1
1399    ldrsw\t%0, %1"
1400   [(set_attr "type" "extend,load1")]
1403 (define_insn "*load_pair_extendsidi2_aarch64"
1404   [(set (match_operand:DI 0 "register_operand" "=r")
1405         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1406    (set (match_operand:DI 2 "register_operand" "=r")
1407         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1408   "rtx_equal_p (XEXP (operands[3], 0),
1409                 plus_constant (Pmode,
1410                                XEXP (operands[1], 0),
1411                                GET_MODE_SIZE (SImode)))"
1412   "ldpsw\\t%0, %2, %1"
1413   [(set_attr "type" "load2")]
1416 (define_insn "*zero_extendsidi2_aarch64"
1417   [(set (match_operand:DI 0 "register_operand" "=r,r")
1418         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1419   ""
1420   "@
1421    uxtw\t%0, %w1
1422    ldr\t%w0, %1"
1423   [(set_attr "type" "extend,load1")]
1426 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1427   [(set (match_operand:DI 0 "register_operand" "=r")
1428         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1429    (set (match_operand:DI 2 "register_operand" "=r")
1430         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1431   "rtx_equal_p (XEXP (operands[3], 0),
1432                 plus_constant (Pmode,
1433                                XEXP (operands[1], 0),
1434                                GET_MODE_SIZE (SImode)))"
1435   "ldp\\t%w0, %w2, %1"
1436   [(set_attr "type" "load2")]
1439 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1440   [(set (match_operand:GPI 0 "register_operand")
1441         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1442   ""
1445 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1446   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1447         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1448   ""
1449   "@
1450    sxt<SHORT:size>\t%<GPI:w>0, %w1
1451    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1452   [(set_attr "type" "extend,load1")]
1455 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1456   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1457         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1458   ""
1459   "@
1460    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1461    ldr<SHORT:size>\t%w0, %1
1462    ldr\t%<SHORT:size>0, %1"
1463   [(set_attr "type" "logic_imm,load1,load1")]
1466 (define_expand "<optab>qihi2"
1467   [(set (match_operand:HI 0 "register_operand")
1468         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1469   ""
1472 (define_insn "*extendqihi2_aarch64"
1473   [(set (match_operand:HI 0 "register_operand" "=r,r")
1474         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1475   ""
1476   "@
1477    sxtb\t%w0, %w1
1478    ldrsb\t%w0, %1"
1479   [(set_attr "type" "extend,load1")]
1482 (define_insn "*zero_extendqihi2_aarch64"
1483   [(set (match_operand:HI 0 "register_operand" "=r,r")
1484         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1485   ""
1486   "@
1487    and\t%w0, %w1, 255
1488    ldrb\t%w0, %1"
1489   [(set_attr "type" "logic_imm,load1")]
1492 ;; -------------------------------------------------------------------
1493 ;; Simple arithmetic
1494 ;; -------------------------------------------------------------------
1496 (define_expand "add<mode>3"
1497   [(set
1498     (match_operand:GPI 0 "register_operand" "")
1499     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1500               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1501   ""
1503   /* If operands[1] is a subreg extract the inner RTX.  */
1504   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1506   /* If the constant is too large for a single instruction and isn't frame
1507      based, split off the immediate so it is available for CSE.  */
1508   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1509       && can_create_pseudo_p ()
1510       && (!REG_P (op1)
1511          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1512     operands[2] = force_reg (<MODE>mode, operands[2]);
1515 (define_insn "*add<mode>3_aarch64"
1516   [(set
1517     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1518     (plus:GPI
1519      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1520      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1521   ""
1522   "@
1523   add\\t%<w>0, %<w>1, %2
1524   add\\t%<w>0, %<w>1, %<w>2
1525   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1526   sub\\t%<w>0, %<w>1, #%n2
1527   #"
1528   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1529    (set_attr "simd" "*,*,yes,*,*")]
1532 ;; zero_extend version of above
1533 (define_insn "*addsi3_aarch64_uxtw"
1534   [(set
1535     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1536     (zero_extend:DI
1537      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1538               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1539   ""
1540   "@
1541   add\\t%w0, %w1, %2
1542   add\\t%w0, %w1, %w2
1543   sub\\t%w0, %w1, #%n2
1544   #"
1545   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1548 ;; If there's a free register, and we can load the constant with a
1549 ;; single instruction, do so.  This has a chance to improve scheduling.
1550 (define_peephole2
1551   [(match_scratch:GPI 3 "r")
1552    (set (match_operand:GPI 0 "register_operand")
1553         (plus:GPI
1554           (match_operand:GPI 1 "register_operand")
1555           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1556   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1557   [(set (match_dup 3) (match_dup 2))
1558    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1561 (define_peephole2
1562   [(match_scratch:SI 3 "r")
1563    (set (match_operand:DI 0 "register_operand")
1564         (zero_extend:DI
1565           (plus:SI
1566             (match_operand:SI 1 "register_operand")
1567             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1568   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1569   [(set (match_dup 3) (match_dup 2))
1570    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1573 ;; After peephole2 has had a chance to run, split any remaining long
1574 ;; additions into two add immediates.
1575 (define_split
1576   [(set (match_operand:GPI 0 "register_operand")
1577         (plus:GPI
1578           (match_operand:GPI 1 "register_operand")
1579           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1580   "epilogue_completed"
1581   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1582    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1583   {
1584     HOST_WIDE_INT i = INTVAL (operands[2]);
1585     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1586     operands[3] = GEN_INT (i - s);
1587     operands[4] = GEN_INT (s);
1588   }
1591 (define_split
1592   [(set (match_operand:DI 0 "register_operand")
1593         (zero_extend:DI
1594           (plus:SI
1595             (match_operand:SI 1 "register_operand")
1596             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1597   "epilogue_completed"
1598   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1599    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1600   {
1601     HOST_WIDE_INT i = INTVAL (operands[2]);
1602     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1603     operands[3] = GEN_INT (i - s);
1604     operands[4] = GEN_INT (s);
1605     operands[5] = gen_lowpart (SImode, operands[0]);
1606   }
1609 (define_expand "addti3"
1610   [(set (match_operand:TI 0 "register_operand" "")
1611         (plus:TI (match_operand:TI 1 "register_operand" "")
1612                  (match_operand:TI 2 "register_operand" "")))]
1613   ""
1615   rtx low = gen_reg_rtx (DImode);
1616   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1617                                   gen_lowpart (DImode, operands[2])));
1619   rtx high = gen_reg_rtx (DImode);
1620   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1621                                  gen_highpart (DImode, operands[2])));
1623   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1624   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1625   DONE;
1628 (define_insn "add<mode>3_compare0"
1629   [(set (reg:CC_NZ CC_REGNUM)
1630         (compare:CC_NZ
1631          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1632                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1633          (const_int 0)))
1634    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1635         (plus:GPI (match_dup 1) (match_dup 2)))]
1636   ""
1637   "@
1638   adds\\t%<w>0, %<w>1, %<w>2
1639   adds\\t%<w>0, %<w>1, %2
1640   subs\\t%<w>0, %<w>1, #%n2"
1641   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1644 ;; zero_extend version of above
1645 (define_insn "*addsi3_compare0_uxtw"
1646   [(set (reg:CC_NZ CC_REGNUM)
1647         (compare:CC_NZ
1648          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1649                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1650          (const_int 0)))
1651    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1652         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1653   ""
1654   "@
1655   adds\\t%w0, %w1, %w2
1656   adds\\t%w0, %w1, %2
1657   subs\\t%w0, %w1, #%n2"
1658   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1661 (define_insn "*add<mode>3_compareC_cconly_imm"
1662   [(set (reg:CC_C CC_REGNUM)
1663         (ne:CC_C
1664           (plus:<DWI>
1665             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1666             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1667           (zero_extend:<DWI>
1668             (plus:GPI
1669               (match_dup 0)
1670               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1671   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1672                                  <MODE>mode, operands[1])"
1673   "@
1674   cmn\\t%<w>0, %1
1675   cmp\\t%<w>0, #%n1"
1676   [(set_attr "type" "alus_imm")]
1679 (define_insn "*add<mode>3_compareC_cconly"
1680   [(set (reg:CC_C CC_REGNUM)
1681         (ne:CC_C
1682           (plus:<DWI>
1683             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1684             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1685           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1686   ""
1687   "cmn\\t%<w>0, %<w>1"
1688   [(set_attr "type" "alus_sreg")]
1691 (define_insn "*add<mode>3_compareC_imm"
1692   [(set (reg:CC_C CC_REGNUM)
1693         (ne:CC_C
1694           (plus:<DWI>
1695             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1696             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1697           (zero_extend:<DWI>
1698             (plus:GPI
1699               (match_dup 1)
1700               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1701    (set (match_operand:GPI 0 "register_operand" "=r,r")
1702         (plus:GPI (match_dup 1) (match_dup 2)))]
1703   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1704                                  <MODE>mode, operands[2])"
1705   "@
1706   adds\\t%<w>0, %<w>1, %2
1707   subs\\t%<w>0, %<w>1, #%n2"
1708   [(set_attr "type" "alus_imm")]
1711 (define_insn "add<mode>3_compareC"
1712   [(set (reg:CC_C CC_REGNUM)
1713         (ne:CC_C
1714           (plus:<DWI>
1715             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1716             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1717           (zero_extend:<DWI>
1718             (plus:GPI (match_dup 1) (match_dup 2)))))
1719    (set (match_operand:GPI 0 "register_operand" "=r")
1720         (plus:GPI (match_dup 1) (match_dup 2)))]
1721   ""
1722   "adds\\t%<w>0, %<w>1, %<w>2"
1723   [(set_attr "type" "alus_sreg")]
1726 (define_insn "*adds_shift_imm_<mode>"
1727   [(set (reg:CC_NZ CC_REGNUM)
1728         (compare:CC_NZ
1729          (plus:GPI (ASHIFT:GPI 
1730                     (match_operand:GPI 1 "register_operand" "r")
1731                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1732                    (match_operand:GPI 3 "register_operand" "r"))
1733          (const_int 0)))
1734    (set (match_operand:GPI 0 "register_operand" "=r")
1735         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1736                   (match_dup 3)))]
1737   ""
1738   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1739   [(set_attr "type" "alus_shift_imm")]
1742 (define_insn "*subs_shift_imm_<mode>"
1743   [(set (reg:CC_NZ CC_REGNUM)
1744         (compare:CC_NZ
1745          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1746                     (ASHIFT:GPI
1747                      (match_operand:GPI 2 "register_operand" "r")
1748                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1749          (const_int 0)))
1750    (set (match_operand:GPI 0 "register_operand" "=r")
1751         (minus:GPI (match_dup 1)
1752                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1753   ""
1754   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1755   [(set_attr "type" "alus_shift_imm")]
1758 (define_insn "*adds_mul_imm_<mode>"
1759   [(set (reg:CC_NZ CC_REGNUM)
1760         (compare:CC_NZ
1761          (plus:GPI (mult:GPI
1762                     (match_operand:GPI 1 "register_operand" "r")
1763                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1764                    (match_operand:GPI 3 "register_operand" "r"))
1765          (const_int 0)))
1766    (set (match_operand:GPI 0 "register_operand" "=r")
1767         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1768                   (match_dup 3)))]
1769   ""
1770   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1771   [(set_attr "type" "alus_shift_imm")]
1774 (define_insn "*subs_mul_imm_<mode>"
1775   [(set (reg:CC_NZ CC_REGNUM)
1776         (compare:CC_NZ
1777          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1778                     (mult:GPI
1779                      (match_operand:GPI 2 "register_operand" "r")
1780                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1781          (const_int 0)))
1782    (set (match_operand:GPI 0 "register_operand" "=r")
1783         (minus:GPI (match_dup 1)
1784                    (mult:GPI (match_dup 2) (match_dup 3))))]
1785   ""
1786   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1787   [(set_attr "type" "alus_shift_imm")]
1790 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1791   [(set (reg:CC_NZ CC_REGNUM)
1792         (compare:CC_NZ
1793          (plus:GPI
1794           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1795           (match_operand:GPI 2 "register_operand" "r"))
1796         (const_int 0)))
1797    (set (match_operand:GPI 0 "register_operand" "=r")
1798         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1799   ""
1800   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1801   [(set_attr "type" "alus_ext")]
1804 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1805   [(set (reg:CC_NZ CC_REGNUM)
1806         (compare:CC_NZ
1807          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1808                     (ANY_EXTEND:GPI
1809                      (match_operand:ALLX 2 "register_operand" "r")))
1810         (const_int 0)))
1811    (set (match_operand:GPI 0 "register_operand" "=r")
1812         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1813   ""
1814   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1815   [(set_attr "type" "alus_ext")]
1818 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1819   [(set (reg:CC_NZ CC_REGNUM)
1820         (compare:CC_NZ
1821          (plus:GPI (ashift:GPI 
1822                     (ANY_EXTEND:GPI 
1823                      (match_operand:ALLX 1 "register_operand" "r"))
1824                     (match_operand 2 "aarch64_imm3" "Ui3"))
1825                    (match_operand:GPI 3 "register_operand" "r"))
1826          (const_int 0)))
1827    (set (match_operand:GPI 0 "register_operand" "=rk")
1828         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1829                               (match_dup 2))
1830                   (match_dup 3)))]
1831   ""
1832   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1833   [(set_attr "type" "alus_ext")]
1836 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1837   [(set (reg:CC_NZ CC_REGNUM)
1838         (compare:CC_NZ
1839          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1840                     (ashift:GPI 
1841                      (ANY_EXTEND:GPI
1842                       (match_operand:ALLX 2 "register_operand" "r"))
1843                      (match_operand 3 "aarch64_imm3" "Ui3")))
1844          (const_int 0)))
1845    (set (match_operand:GPI 0 "register_operand" "=rk")
1846         (minus:GPI (match_dup 1)
1847                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1848                                (match_dup 3))))]
1849   ""
1850   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1851   [(set_attr "type" "alus_ext")]
1854 (define_insn "*adds_<optab><mode>_multp2"
1855   [(set (reg:CC_NZ CC_REGNUM)
1856         (compare:CC_NZ
1857          (plus:GPI (ANY_EXTRACT:GPI
1858                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1859                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1860                     (match_operand 3 "const_int_operand" "n")
1861                     (const_int 0))
1862                    (match_operand:GPI 4 "register_operand" "r"))
1863         (const_int 0)))
1864    (set (match_operand:GPI 0 "register_operand" "=r")
1865         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1866                                    (match_dup 3)
1867                                    (const_int 0))
1868                   (match_dup 4)))]
1869   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1870   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1871   [(set_attr "type" "alus_ext")]
1874 (define_insn "*subs_<optab><mode>_multp2"
1875   [(set (reg:CC_NZ CC_REGNUM)
1876         (compare:CC_NZ
1877          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1878                     (ANY_EXTRACT:GPI
1879                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1880                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1881                      (match_operand 3 "const_int_operand" "n")
1882                      (const_int 0)))
1883         (const_int 0)))
1884    (set (match_operand:GPI 0 "register_operand" "=r")
1885         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1886                                   (mult:GPI (match_dup 1) (match_dup 2))
1887                                   (match_dup 3)
1888                                   (const_int 0))))]
1889   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1890   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1891   [(set_attr "type" "alus_ext")]
1894 (define_insn "*add<mode>3nr_compare0"
1895   [(set (reg:CC_NZ CC_REGNUM)
1896         (compare:CC_NZ
1897          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1898                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1899          (const_int 0)))]
1900   ""
1901   "@
1902   cmn\\t%<w>0, %<w>1
1903   cmn\\t%<w>0, %1
1904   cmp\\t%<w>0, #%n1"
1905   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1908 (define_insn "*compare_neg<mode>"
1909   [(set (reg:CC_Z CC_REGNUM)
1910         (compare:CC_Z
1911          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1912          (match_operand:GPI 1 "register_operand" "r")))]
1913   ""
1914   "cmn\\t%<w>1, %<w>0"
1915   [(set_attr "type" "alus_sreg")]
1918 (define_insn "*add_<shift>_<mode>"
1919   [(set (match_operand:GPI 0 "register_operand" "=r")
1920         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1921                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1922                   (match_operand:GPI 3 "register_operand" "r")))]
1923   ""
1924   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1925   [(set_attr "type" "alu_shift_imm")]
1928 ;; zero_extend version of above
1929 (define_insn "*add_<shift>_si_uxtw"
1930   [(set (match_operand:DI 0 "register_operand" "=r")
1931         (zero_extend:DI
1932          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1933                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1934                   (match_operand:SI 3 "register_operand" "r"))))]
1935   ""
1936   "add\\t%w0, %w3, %w1, <shift> %2"
1937   [(set_attr "type" "alu_shift_imm")]
1940 (define_insn "*add_mul_imm_<mode>"
1941   [(set (match_operand:GPI 0 "register_operand" "=r")
1942         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1943                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1944                   (match_operand:GPI 3 "register_operand" "r")))]
1945   ""
1946   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1947   [(set_attr "type" "alu_shift_imm")]
1950 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1951   [(set (match_operand:GPI 0 "register_operand" "=rk")
1952         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1953                   (match_operand:GPI 2 "register_operand" "r")))]
1954   ""
1955   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1956   [(set_attr "type" "alu_ext")]
1959 ;; zero_extend version of above
1960 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
1961   [(set (match_operand:DI 0 "register_operand" "=rk")
1962         (zero_extend:DI
1963          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
1964                   (match_operand:GPI 2 "register_operand" "r"))))]
1965   ""
1966   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
1967   [(set_attr "type" "alu_ext")]
1970 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1971   [(set (match_operand:GPI 0 "register_operand" "=rk")
1972         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1973                                (match_operand:ALLX 1 "register_operand" "r"))
1974                               (match_operand 2 "aarch64_imm3" "Ui3"))
1975                   (match_operand:GPI 3 "register_operand" "r")))]
1976   ""
1977   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1978   [(set_attr "type" "alu_ext")]
1981 ;; zero_extend version of above
1982 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
1983   [(set (match_operand:DI 0 "register_operand" "=rk")
1984         (zero_extend:DI
1985          (plus:SI (ashift:SI (ANY_EXTEND:SI
1986                               (match_operand:SHORT 1 "register_operand" "r"))
1987                              (match_operand 2 "aarch64_imm3" "Ui3"))
1988                   (match_operand:SI 3 "register_operand" "r"))))]
1989   ""
1990   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
1991   [(set_attr "type" "alu_ext")]
1994 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1995   [(set (match_operand:GPI 0 "register_operand" "=rk")
1996         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1997                              (match_operand:ALLX 1 "register_operand" "r"))
1998                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1999                   (match_operand:GPI 3 "register_operand" "r")))]
2000   ""
2001   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2002   [(set_attr "type" "alu_ext")]
2005 ;; zero_extend version of above
2006 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2007   [(set (match_operand:DI 0 "register_operand" "=rk")
2008         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2009                              (match_operand:SHORT 1 "register_operand" "r"))
2010                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2011                   (match_operand:SI 3 "register_operand" "r"))))]
2012   ""
2013   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2014   [(set_attr "type" "alu_ext")]
2017 (define_insn "*add_<optab><mode>_multp2"
2018   [(set (match_operand:GPI 0 "register_operand" "=rk")
2019         (plus:GPI (ANY_EXTRACT:GPI
2020                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2021                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2022                    (match_operand 3 "const_int_operand" "n")
2023                    (const_int 0))
2024                   (match_operand:GPI 4 "register_operand" "r")))]
2025   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2026   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2027   [(set_attr "type" "alu_ext")]
2030 ;; zero_extend version of above
2031 (define_insn "*add_<optab>si_multp2_uxtw"
2032   [(set (match_operand:DI 0 "register_operand" "=rk")
2033         (zero_extend:DI
2034          (plus:SI (ANY_EXTRACT:SI
2035                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2036                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2037                    (match_operand 3 "const_int_operand" "n")
2038                    (const_int 0))
2039                   (match_operand:SI 4 "register_operand" "r"))))]
2040   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2041   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2042   [(set_attr "type" "alu_ext")]
2045 (define_expand "add<mode>3_carryin"
2046   [(set (match_operand:GPI 0 "register_operand")
2047         (plus:GPI
2048           (plus:GPI
2049             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2050             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2051           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2052    ""
2053    ""
2056 ;; Note that add with carry with two zero inputs is matched by cset,
2057 ;; and that add with carry with one zero input is matched by cinc.
2059 (define_insn "*add<mode>3_carryin"
2060   [(set (match_operand:GPI 0 "register_operand" "=r")
2061         (plus:GPI
2062           (plus:GPI
2063             (match_operand:GPI 3 "aarch64_carry_operation" "")
2064             (match_operand:GPI 1 "register_operand" "r"))
2065           (match_operand:GPI 2 "register_operand" "r")))]
2066    ""
2067    "adc\\t%<w>0, %<w>1, %<w>2"
2068   [(set_attr "type" "adc_reg")]
2071 ;; zero_extend version of above
2072 (define_insn "*addsi3_carryin_uxtw"
2073   [(set (match_operand:DI 0 "register_operand" "=r")
2074         (zero_extend:DI
2075           (plus:SI
2076             (plus:SI
2077               (match_operand:SI 3 "aarch64_carry_operation" "")
2078               (match_operand:SI 1 "register_operand" "r"))
2079             (match_operand:SI 2 "register_operand" "r"))))]
2080    ""
2081    "adc\\t%w0, %w1, %w2"
2082   [(set_attr "type" "adc_reg")]
2085 (define_insn "*add_uxt<mode>_shift2"
2086   [(set (match_operand:GPI 0 "register_operand" "=rk")
2087         (plus:GPI (and:GPI
2088                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2089                                (match_operand 2 "aarch64_imm3" "Ui3"))
2090                    (match_operand 3 "const_int_operand" "n"))
2091                   (match_operand:GPI 4 "register_operand" "r")))]
2092   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2093   "*
2094   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2095                                            INTVAL (operands[3])));
2096   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2097   [(set_attr "type" "alu_ext")]
2100 ;; zero_extend version of above
2101 (define_insn "*add_uxtsi_shift2_uxtw"
2102   [(set (match_operand:DI 0 "register_operand" "=rk")
2103         (zero_extend:DI
2104          (plus:SI (and:SI
2105                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2106                               (match_operand 2 "aarch64_imm3" "Ui3"))
2107                    (match_operand 3 "const_int_operand" "n"))
2108                   (match_operand:SI 4 "register_operand" "r"))))]
2109   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2110   "*
2111   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2112                                            INTVAL (operands[3])));
2113   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2114   [(set_attr "type" "alu_ext")]
2117 (define_insn "*add_uxt<mode>_multp2"
2118   [(set (match_operand:GPI 0 "register_operand" "=rk")
2119         (plus:GPI (and:GPI
2120                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2121                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2122                    (match_operand 3 "const_int_operand" "n"))
2123                   (match_operand:GPI 4 "register_operand" "r")))]
2124   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2125   "*
2126   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2127                                            INTVAL (operands[3])));
2128   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2129   [(set_attr "type" "alu_ext")]
2132 ;; zero_extend version of above
2133 (define_insn "*add_uxtsi_multp2_uxtw"
2134   [(set (match_operand:DI 0 "register_operand" "=rk")
2135         (zero_extend:DI
2136          (plus:SI (and:SI
2137                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2138                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2139                    (match_operand 3 "const_int_operand" "n"))
2140                   (match_operand:SI 4 "register_operand" "r"))))]
2141   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2142   "*
2143   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2144                                            INTVAL (operands[3])));
2145   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2146   [(set_attr "type" "alu_ext")]
2149 (define_insn "subsi3"
2150   [(set (match_operand:SI 0 "register_operand" "=rk")
2151         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2152                   (match_operand:SI 2 "register_operand" "r")))]
2153   ""
2154   "sub\\t%w0, %w1, %w2"
2155   [(set_attr "type" "alu_sreg")]
2158 ;; zero_extend version of above
2159 (define_insn "*subsi3_uxtw"
2160   [(set (match_operand:DI 0 "register_operand" "=rk")
2161         (zero_extend:DI
2162          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2163                    (match_operand:SI 2 "register_operand" "r"))))]
2164   ""
2165   "sub\\t%w0, %w1, %w2"
2166   [(set_attr "type" "alu_sreg")]
2169 (define_insn "subdi3"
2170   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2171         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2172                   (match_operand:DI 2 "register_operand" "r,w")))]
2173   ""
2174   "@
2175    sub\\t%x0, %x1, %x2
2176    sub\\t%d0, %d1, %d2"
2177   [(set_attr "type" "alu_sreg, neon_sub")
2178    (set_attr "simd" "*,yes")]
2181 (define_expand "subti3"
2182   [(set (match_operand:TI 0 "register_operand" "")
2183         (minus:TI (match_operand:TI 1 "register_operand" "")
2184                   (match_operand:TI 2 "register_operand" "")))]
2185   ""
2187   rtx low = gen_reg_rtx (DImode);
2188   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2189                                   gen_lowpart (DImode, operands[2])));
2191   rtx high = gen_reg_rtx (DImode);
2192   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2193                                  gen_highpart (DImode, operands[2])));
2195   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2196   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2197   DONE;
2200 (define_insn "*sub<mode>3_compare0"
2201   [(set (reg:CC_NZ CC_REGNUM)
2202         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2203                                   (match_operand:GPI 2 "register_operand" "r"))
2204                        (const_int 0)))
2205    (set (match_operand:GPI 0 "register_operand" "=r")
2206         (minus:GPI (match_dup 1) (match_dup 2)))]
2207   ""
2208   "subs\\t%<w>0, %<w>1, %<w>2"
2209   [(set_attr "type" "alus_sreg")]
2212 ;; zero_extend version of above
2213 (define_insn "*subsi3_compare0_uxtw"
2214   [(set (reg:CC_NZ CC_REGNUM)
2215         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2216                                  (match_operand:SI 2 "register_operand" "r"))
2217                        (const_int 0)))
2218    (set (match_operand:DI 0 "register_operand" "=r")
2219         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2220   ""
2221   "subs\\t%w0, %w1, %w2"
2222   [(set_attr "type" "alus_sreg")]
2225 (define_insn "sub<mode>3_compare1"
2226   [(set (reg:CC CC_REGNUM)
2227         (compare:CC
2228           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2229           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2230    (set (match_operand:GPI 0 "register_operand" "=r")
2231         (minus:GPI (match_dup 1) (match_dup 2)))]
2232   ""
2233   "subs\\t%<w>0, %<w>1, %<w>2"
2234   [(set_attr "type" "alus_sreg")]
2237 (define_insn "sub<mode>3_compare1_imm"
2238   [(set (reg:CC CC_REGNUM)
2239         (compare:CC
2240           (match_operand:GPI 1 "register_operand" "r")
2241           (match_operand:GPI 3 "const_int_operand" "n")))
2242    (set (match_operand:GPI 0 "register_operand" "=r")
2243         (plus:GPI (match_dup 1)
2244                   (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2245   "INTVAL (operands[3]) == -INTVAL (operands[2])"
2246   "subs\\t%<w>0, %<w>1, #%n2"
2247   [(set_attr "type" "alus_sreg")]
2250 (define_peephole2
2251   [(set (match_operand:GPI 0 "register_operand")
2252         (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2253                     (match_operand:GPI 2 "aarch64_reg_or_zero")))
2254    (set (reg:CC CC_REGNUM)
2255         (compare:CC
2256           (match_dup 1)
2257           (match_dup 2)))]
2258   "!reg_overlap_mentioned_p (operands[0], operands[1])
2259    && !reg_overlap_mentioned_p (operands[0], operands[2])"
2260   [(const_int 0)]
2261   {
2262     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2263                                          operands[2]));
2264     DONE;
2265   }
2268 (define_peephole2
2269   [(set (match_operand:GPI 0 "register_operand")
2270         (plus:GPI (match_operand:GPI 1 "register_operand")
2271                   (match_operand:GPI 2 "aarch64_sub_immediate")))
2272    (set (reg:CC CC_REGNUM)
2273         (compare:CC
2274           (match_dup 1)
2275           (match_operand:GPI 3 "const_int_operand")))]
2276   "!reg_overlap_mentioned_p (operands[0], operands[1])
2277    && INTVAL (operands[3]) == -INTVAL (operands[2])"
2278   [(const_int 0)]
2279   {
2280     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2281                                          operands[2], operands[3]));
2282     DONE;
2283   }
2286 (define_insn "*sub_<shift>_<mode>"
2287   [(set (match_operand:GPI 0 "register_operand" "=r")
2288         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2289                    (ASHIFT:GPI
2290                     (match_operand:GPI 1 "register_operand" "r")
2291                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2292   ""
2293   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2294   [(set_attr "type" "alu_shift_imm")]
2297 ;; zero_extend version of above
2298 (define_insn "*sub_<shift>_si_uxtw"
2299   [(set (match_operand:DI 0 "register_operand" "=r")
2300         (zero_extend:DI
2301          (minus:SI (match_operand:SI 3 "register_operand" "r")
2302                    (ASHIFT:SI
2303                     (match_operand:SI 1 "register_operand" "r")
2304                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2305   ""
2306   "sub\\t%w0, %w3, %w1, <shift> %2"
2307   [(set_attr "type" "alu_shift_imm")]
2310 (define_insn "*sub_mul_imm_<mode>"
2311   [(set (match_operand:GPI 0 "register_operand" "=r")
2312         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2313                    (mult:GPI
2314                     (match_operand:GPI 1 "register_operand" "r")
2315                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2316   ""
2317   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2318   [(set_attr "type" "alu_shift_imm")]
2321 ;; zero_extend version of above
2322 (define_insn "*sub_mul_imm_si_uxtw"
2323   [(set (match_operand:DI 0 "register_operand" "=r")
2324         (zero_extend:DI
2325          (minus:SI (match_operand:SI 3 "register_operand" "r")
2326                    (mult:SI
2327                     (match_operand:SI 1 "register_operand" "r")
2328                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2329   ""
2330   "sub\\t%w0, %w3, %w1, lsl %p2"
2331   [(set_attr "type" "alu_shift_imm")]
2334 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2335   [(set (match_operand:GPI 0 "register_operand" "=rk")
2336         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2337                    (ANY_EXTEND:GPI
2338                     (match_operand:ALLX 2 "register_operand" "r"))))]
2339   ""
2340   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2341   [(set_attr "type" "alu_ext")]
2344 ;; zero_extend version of above
2345 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2346   [(set (match_operand:DI 0 "register_operand" "=rk")
2347         (zero_extend:DI
2348          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2349                    (ANY_EXTEND:SI
2350                     (match_operand:SHORT 2 "register_operand" "r")))))]
2351   ""
2352   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2353   [(set_attr "type" "alu_ext")]
2356 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2357   [(set (match_operand:GPI 0 "register_operand" "=rk")
2358         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2359                    (ashift:GPI (ANY_EXTEND:GPI
2360                                 (match_operand:ALLX 2 "register_operand" "r"))
2361                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2362   ""
2363   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2364   [(set_attr "type" "alu_ext")]
2367 ;; zero_extend version of above
2368 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2369   [(set (match_operand:DI 0 "register_operand" "=rk")
2370         (zero_extend:DI
2371          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2372                    (ashift:SI (ANY_EXTEND:SI
2373                                (match_operand:SHORT 2 "register_operand" "r"))
2374                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2375   ""
2376   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2377   [(set_attr "type" "alu_ext")]
2380 (define_insn "*sub_<optab><mode>_multp2"
2381   [(set (match_operand:GPI 0 "register_operand" "=rk")
2382         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2383                    (ANY_EXTRACT:GPI
2384                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2385                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2386                     (match_operand 3 "const_int_operand" "n")
2387                     (const_int 0))))]
2388   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2389   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2390   [(set_attr "type" "alu_ext")]
2393 ;; zero_extend version of above
2394 (define_insn "*sub_<optab>si_multp2_uxtw"
2395   [(set (match_operand:DI 0 "register_operand" "=rk")
2396         (zero_extend:DI
2397          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2398                    (ANY_EXTRACT:SI
2399                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2400                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2401                     (match_operand 3 "const_int_operand" "n")
2402                     (const_int 0)))))]
2403   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2404   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2405   [(set_attr "type" "alu_ext")]
2408 ;; The hardware description is op1 + ~op2 + C.
2409 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2410 ;;                           = op1 - op2 - 1 + 1 - !C
2411 ;;                           = op1 - op2 - !C.
2412 ;; We describe the latter.
2414 (define_insn "*sub<mode>3_carryin0"
2415   [(set (match_operand:GPI 0 "register_operand" "=r")
2416         (minus:GPI
2417           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2418           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2419    ""
2420    "sbc\\t%<w>0, %<w>1, <w>zr"
2421   [(set_attr "type" "adc_reg")]
2424 ;; zero_extend version of the above
2425 (define_insn "*subsi3_carryin_uxtw"
2426   [(set (match_operand:DI 0 "register_operand" "=r")
2427         (zero_extend:DI
2428           (minus:SI
2429             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2430             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2431    ""
2432    "sbc\\t%w0, %w1, wzr"
2433   [(set_attr "type" "adc_reg")]
2436 (define_expand "sub<mode>3_carryin"
2437   [(set (match_operand:GPI 0 "register_operand")
2438         (minus:GPI
2439           (minus:GPI
2440             (match_operand:GPI 1 "aarch64_reg_or_zero")
2441             (match_operand:GPI 2 "register_operand"))
2442           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2443    ""
2444    ""
2447 (define_insn "*sub<mode>3_carryin"
2448   [(set (match_operand:GPI 0 "register_operand" "=r")
2449         (minus:GPI
2450           (minus:GPI
2451             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2452             (match_operand:GPI 2 "register_operand" "r"))
2453           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2455    ""
2456    "sbc\\t%<w>0, %<w>1, %<w>2"
2457   [(set_attr "type" "adc_reg")]
2460 ;; zero_extend version of the above
2461 (define_insn "*subsi3_carryin_uxtw"
2462   [(set (match_operand:DI 0 "register_operand" "=r")
2463         (zero_extend:DI
2464           (minus:SI
2465             (minus:SI
2466               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2467               (match_operand:SI 2 "register_operand" "r"))
2468             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2470    ""
2471    "sbc\\t%w0, %w1, %w2"
2472   [(set_attr "type" "adc_reg")]
2475 (define_insn "*sub<mode>3_carryin_alt"
2476   [(set (match_operand:GPI 0 "register_operand" "=r")
2477         (minus:GPI
2478           (minus:GPI
2479             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2480             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2481           (match_operand:GPI 2 "register_operand" "r")))]
2482    ""
2483    "sbc\\t%<w>0, %<w>1, %<w>2"
2484   [(set_attr "type" "adc_reg")]
2487 ;; zero_extend version of the above
2488 (define_insn "*subsi3_carryin_alt_uxtw"
2489   [(set (match_operand:DI 0 "register_operand" "=r")
2490         (zero_extend:DI
2491           (minus:SI
2492             (minus:SI
2493               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2494               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2495             (match_operand:SI 2 "register_operand" "r"))))]
2496    ""
2497    "sbc\\t%w0, %w1, %w2"
2498   [(set_attr "type" "adc_reg")]
2501 (define_insn "*sub_uxt<mode>_shift2"
2502   [(set (match_operand:GPI 0 "register_operand" "=rk")
2503         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2504                    (and:GPI
2505                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2506                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2507                     (match_operand 3 "const_int_operand" "n"))))]
2508   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2509   "*
2510   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2511                                            INTVAL (operands[3])));
2512   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2513   [(set_attr "type" "alu_ext")]
2516 ;; zero_extend version of above
2517 (define_insn "*sub_uxtsi_shift2_uxtw"
2518   [(set (match_operand:DI 0 "register_operand" "=rk")
2519         (zero_extend:DI
2520          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2521                    (and:SI
2522                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2523                                (match_operand 2 "aarch64_imm3" "Ui3"))
2524                     (match_operand 3 "const_int_operand" "n")))))]
2525   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2526   "*
2527   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2528                                            INTVAL (operands[3])));
2529   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2530   [(set_attr "type" "alu_ext")]
2533 (define_insn "*sub_uxt<mode>_multp2"
2534   [(set (match_operand:GPI 0 "register_operand" "=rk")
2535         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2536                    (and:GPI
2537                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2538                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2539                     (match_operand 3 "const_int_operand" "n"))))]
2540   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2541   "*
2542   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2543                                            INTVAL (operands[3])));
2544   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2545   [(set_attr "type" "alu_ext")]
2548 ;; zero_extend version of above
2549 (define_insn "*sub_uxtsi_multp2_uxtw"
2550   [(set (match_operand:DI 0 "register_operand" "=rk")
2551         (zero_extend:DI
2552          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2553                    (and:SI
2554                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2555                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2556                     (match_operand 3 "const_int_operand" "n")))))]
2557   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2558   "*
2559   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2560                                            INTVAL (operands[3])));
2561   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2562   [(set_attr "type" "alu_ext")]
2565 (define_expand "abs<mode>2"
2566   [(match_operand:GPI 0 "register_operand" "")
2567    (match_operand:GPI 1 "register_operand" "")]
2568   ""
2569   {
2570     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2571     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2572     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2573     DONE;
2574   }
2577 (define_insn "neg<mode>2"
2578   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2579         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2580   ""
2581   "@
2582    neg\\t%<w>0, %<w>1
2583    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2584   [(set_attr "type" "alu_sreg, neon_neg<q>")
2585    (set_attr "simd" "*,yes")]
2588 ;; zero_extend version of above
2589 (define_insn "*negsi2_uxtw"
2590   [(set (match_operand:DI 0 "register_operand" "=r")
2591         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2592   ""
2593   "neg\\t%w0, %w1"
2594   [(set_attr "type" "alu_sreg")]
2597 (define_insn "*ngc<mode>"
2598   [(set (match_operand:GPI 0 "register_operand" "=r")
2599         (minus:GPI
2600           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2601           (match_operand:GPI 1 "register_operand" "r")))]
2602   ""
2603   "ngc\\t%<w>0, %<w>1"
2604   [(set_attr "type" "adc_reg")]
2607 (define_insn "*ngcsi_uxtw"
2608   [(set (match_operand:DI 0 "register_operand" "=r")
2609         (zero_extend:DI
2610           (minus:SI
2611             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2612             (match_operand:SI 1 "register_operand" "r"))))]
2613   ""
2614   "ngc\\t%w0, %w1"
2615   [(set_attr "type" "adc_reg")]
2618 (define_insn "neg<mode>2_compare0"
2619   [(set (reg:CC_NZ CC_REGNUM)
2620         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2621                        (const_int 0)))
2622    (set (match_operand:GPI 0 "register_operand" "=r")
2623         (neg:GPI (match_dup 1)))]
2624   ""
2625   "negs\\t%<w>0, %<w>1"
2626   [(set_attr "type" "alus_sreg")]
2629 ;; zero_extend version of above
2630 (define_insn "*negsi2_compare0_uxtw"
2631   [(set (reg:CC_NZ CC_REGNUM)
2632         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2633                        (const_int 0)))
2634    (set (match_operand:DI 0 "register_operand" "=r")
2635         (zero_extend:DI (neg:SI (match_dup 1))))]
2636   ""
2637   "negs\\t%w0, %w1"
2638   [(set_attr "type" "alus_sreg")]
2641 (define_insn "*neg_<shift><mode>3_compare0"
2642   [(set (reg:CC_NZ CC_REGNUM)
2643         (compare:CC_NZ
2644          (neg:GPI (ASHIFT:GPI
2645                    (match_operand:GPI 1 "register_operand" "r")
2646                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2647          (const_int 0)))
2648    (set (match_operand:GPI 0 "register_operand" "=r")
2649         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2650   ""
2651   "negs\\t%<w>0, %<w>1, <shift> %2"
2652   [(set_attr "type" "alus_shift_imm")]
2655 (define_insn "*neg_<shift>_<mode>2"
2656   [(set (match_operand:GPI 0 "register_operand" "=r")
2657         (neg:GPI (ASHIFT:GPI
2658                   (match_operand:GPI 1 "register_operand" "r")
2659                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2660   ""
2661   "neg\\t%<w>0, %<w>1, <shift> %2"
2662   [(set_attr "type" "alu_shift_imm")]
2665 ;; zero_extend version of above
2666 (define_insn "*neg_<shift>_si2_uxtw"
2667   [(set (match_operand:DI 0 "register_operand" "=r")
2668         (zero_extend:DI
2669          (neg:SI (ASHIFT:SI
2670                   (match_operand:SI 1 "register_operand" "r")
2671                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2672   ""
2673   "neg\\t%w0, %w1, <shift> %2"
2674   [(set_attr "type" "alu_shift_imm")]
2677 (define_insn "*neg_mul_imm_<mode>2"
2678   [(set (match_operand:GPI 0 "register_operand" "=r")
2679         (neg:GPI (mult:GPI
2680                   (match_operand:GPI 1 "register_operand" "r")
2681                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2682   ""
2683   "neg\\t%<w>0, %<w>1, lsl %p2"
2684   [(set_attr "type" "alu_shift_imm")]
2687 ;; zero_extend version of above
2688 (define_insn "*neg_mul_imm_si2_uxtw"
2689   [(set (match_operand:DI 0 "register_operand" "=r")
2690         (zero_extend:DI
2691          (neg:SI (mult:SI
2692                   (match_operand:SI 1 "register_operand" "r")
2693                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2694   ""
2695   "neg\\t%w0, %w1, lsl %p2"
2696   [(set_attr "type" "alu_shift_imm")]
2699 (define_insn "mul<mode>3"
2700   [(set (match_operand:GPI 0 "register_operand" "=r")
2701         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2702                   (match_operand:GPI 2 "register_operand" "r")))]
2703   ""
2704   "mul\\t%<w>0, %<w>1, %<w>2"
2705   [(set_attr "type" "mul")]
2708 ;; zero_extend version of above
2709 (define_insn "*mulsi3_uxtw"
2710   [(set (match_operand:DI 0 "register_operand" "=r")
2711         (zero_extend:DI
2712          (mult:SI (match_operand:SI 1 "register_operand" "r")
2713                   (match_operand:SI 2 "register_operand" "r"))))]
2714   ""
2715   "mul\\t%w0, %w1, %w2"
2716   [(set_attr "type" "mul")]
2719 (define_insn "madd<mode>"
2720   [(set (match_operand:GPI 0 "register_operand" "=r")
2721         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2722                             (match_operand:GPI 2 "register_operand" "r"))
2723                   (match_operand:GPI 3 "register_operand" "r")))]
2724   ""
2725   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2726   [(set_attr "type" "mla")]
2729 ;; zero_extend version of above
2730 (define_insn "*maddsi_uxtw"
2731   [(set (match_operand:DI 0 "register_operand" "=r")
2732         (zero_extend:DI
2733          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2734                            (match_operand:SI 2 "register_operand" "r"))
2735                   (match_operand:SI 3 "register_operand" "r"))))]
2736   ""
2737   "madd\\t%w0, %w1, %w2, %w3"
2738   [(set_attr "type" "mla")]
2741 (define_insn "*msub<mode>"
2742   [(set (match_operand:GPI 0 "register_operand" "=r")
2743         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2744                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2745                              (match_operand:GPI 2 "register_operand" "r"))))]
2747   ""
2748   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2749   [(set_attr "type" "mla")]
2752 ;; zero_extend version of above
2753 (define_insn "*msubsi_uxtw"
2754   [(set (match_operand:DI 0 "register_operand" "=r")
2755         (zero_extend:DI
2756          (minus:SI (match_operand:SI 3 "register_operand" "r")
2757                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2758                             (match_operand:SI 2 "register_operand" "r")))))]
2760   ""
2761   "msub\\t%w0, %w1, %w2, %w3"
2762   [(set_attr "type" "mla")]
2765 (define_insn "*mul<mode>_neg"
2766   [(set (match_operand:GPI 0 "register_operand" "=r")
2767         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2768                   (match_operand:GPI 2 "register_operand" "r")))]
2770   ""
2771   "mneg\\t%<w>0, %<w>1, %<w>2"
2772   [(set_attr "type" "mul")]
2775 ;; zero_extend version of above
2776 (define_insn "*mulsi_neg_uxtw"
2777   [(set (match_operand:DI 0 "register_operand" "=r")
2778         (zero_extend:DI
2779          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2780                   (match_operand:SI 2 "register_operand" "r"))))]
2782   ""
2783   "mneg\\t%w0, %w1, %w2"
2784   [(set_attr "type" "mul")]
2787 (define_insn "<su_optab>mulsidi3"
2788   [(set (match_operand:DI 0 "register_operand" "=r")
2789         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2790                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2791   ""
2792   "<su>mull\\t%0, %w1, %w2"
2793   [(set_attr "type" "<su>mull")]
2796 (define_insn "<su_optab>maddsidi4"
2797   [(set (match_operand:DI 0 "register_operand" "=r")
2798         (plus:DI (mult:DI
2799                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2800                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2801                  (match_operand:DI 3 "register_operand" "r")))]
2802   ""
2803   "<su>maddl\\t%0, %w1, %w2, %3"
2804   [(set_attr "type" "<su>mlal")]
2807 (define_insn "<su_optab>msubsidi4"
2808   [(set (match_operand:DI 0 "register_operand" "=r")
2809         (minus:DI
2810          (match_operand:DI 3 "register_operand" "r")
2811          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2812                   (ANY_EXTEND:DI
2813                    (match_operand:SI 2 "register_operand" "r")))))]
2814   ""
2815   "<su>msubl\\t%0, %w1, %w2, %3"
2816   [(set_attr "type" "<su>mlal")]
2819 (define_insn "*<su_optab>mulsidi_neg"
2820   [(set (match_operand:DI 0 "register_operand" "=r")
2821         (mult:DI (neg:DI
2822                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2823                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2824   ""
2825   "<su>mnegl\\t%0, %w1, %w2"
2826   [(set_attr "type" "<su>mull")]
2829 (define_expand "<su_optab>mulditi3"
2830   [(set (match_operand:TI 0 "register_operand")
2831         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2832                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2833   ""
2835   rtx low = gen_reg_rtx (DImode);
2836   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2838   rtx high = gen_reg_rtx (DImode);
2839   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2841   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2842   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2843   DONE;
2846 ;; The default expansion of multi3 using umuldi3_highpart will perform
2847 ;; the additions in an order that fails to combine into two madd insns.
2848 (define_expand "multi3"
2849   [(set (match_operand:TI 0 "register_operand")
2850         (mult:TI (match_operand:TI 1 "register_operand")
2851                  (match_operand:TI 2 "register_operand")))]
2852   ""
2854   rtx l0 = gen_reg_rtx (DImode);
2855   rtx l1 = gen_lowpart (DImode, operands[1]);
2856   rtx l2 = gen_lowpart (DImode, operands[2]);
2857   rtx h0 = gen_reg_rtx (DImode);
2858   rtx h1 = gen_highpart (DImode, operands[1]);
2859   rtx h2 = gen_highpart (DImode, operands[2]);
2861   emit_insn (gen_muldi3 (l0, l1, l2));
2862   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2863   emit_insn (gen_madddi (h0, h1, l2, h0));
2864   emit_insn (gen_madddi (h0, l1, h2, h0));
2866   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2867   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2868   DONE;
2871 (define_insn "<su>muldi3_highpart"
2872   [(set (match_operand:DI 0 "register_operand" "=r")
2873         (truncate:DI
2874          (lshiftrt:TI
2875           (mult:TI
2876            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2877            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2878           (const_int 64))))]
2879   ""
2880   "<su>mulh\\t%0, %1, %2"
2881   [(set_attr "type" "<su>mull")]
2884 (define_insn "<su_optab>div<mode>3"
2885   [(set (match_operand:GPI 0 "register_operand" "=r")
2886         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2887                      (match_operand:GPI 2 "register_operand" "r")))]
2888   ""
2889   "<su>div\\t%<w>0, %<w>1, %<w>2"
2890   [(set_attr "type" "<su>div")]
2893 ;; zero_extend version of above
2894 (define_insn "*<su_optab>divsi3_uxtw"
2895   [(set (match_operand:DI 0 "register_operand" "=r")
2896         (zero_extend:DI
2897          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2898                      (match_operand:SI 2 "register_operand" "r"))))]
2899   ""
2900   "<su>div\\t%w0, %w1, %w2"
2901   [(set_attr "type" "<su>div")]
2904 ;; -------------------------------------------------------------------
2905 ;; Comparison insns
2906 ;; -------------------------------------------------------------------
2908 (define_insn "cmp<mode>"
2909   [(set (reg:CC CC_REGNUM)
2910         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2911                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2912   ""
2913   "@
2914    cmp\\t%<w>0, %<w>1
2915    cmp\\t%<w>0, %1
2916    cmn\\t%<w>0, #%n1"
2917   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2920 (define_insn "fcmp<mode>"
2921   [(set (reg:CCFP CC_REGNUM)
2922         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2923                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2924    "TARGET_FLOAT"
2925    "@
2926     fcmp\\t%<s>0, #0.0
2927     fcmp\\t%<s>0, %<s>1"
2928   [(set_attr "type" "fcmp<s>")]
2931 (define_insn "fcmpe<mode>"
2932   [(set (reg:CCFPE CC_REGNUM)
2933         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2934                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2935    "TARGET_FLOAT"
2936    "@
2937     fcmpe\\t%<s>0, #0.0
2938     fcmpe\\t%<s>0, %<s>1"
2939   [(set_attr "type" "fcmp<s>")]
2942 (define_insn "*cmp_swp_<shift>_reg<mode>"
2943   [(set (reg:CC_SWP CC_REGNUM)
2944         (compare:CC_SWP (ASHIFT:GPI
2945                          (match_operand:GPI 0 "register_operand" "r")
2946                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2947                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2948   ""
2949   "cmp\\t%<w>2, %<w>0, <shift> %1"
2950   [(set_attr "type" "alus_shift_imm")]
2953 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2954   [(set (reg:CC_SWP CC_REGNUM)
2955         (compare:CC_SWP (ANY_EXTEND:GPI
2956                          (match_operand:ALLX 0 "register_operand" "r"))
2957                         (match_operand:GPI 1 "register_operand" "r")))]
2958   ""
2959   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
2960   [(set_attr "type" "alus_ext")]
2963 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
2964   [(set (reg:CC_SWP CC_REGNUM)
2965         (compare:CC_SWP (ashift:GPI
2966                          (ANY_EXTEND:GPI
2967                           (match_operand:ALLX 0 "register_operand" "r"))
2968                          (match_operand 1 "aarch64_imm3" "Ui3"))
2969         (match_operand:GPI 2 "register_operand" "r")))]
2970   ""
2971   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
2972   [(set_attr "type" "alus_ext")]
2975 ;; -------------------------------------------------------------------
2976 ;; Store-flag and conditional select insns
2977 ;; -------------------------------------------------------------------
2979 (define_expand "cstore<mode>4"
2980   [(set (match_operand:SI 0 "register_operand" "")
2981         (match_operator:SI 1 "aarch64_comparison_operator"
2982          [(match_operand:GPI 2 "register_operand" "")
2983           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
2984   ""
2985   "
2986   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2987                                       operands[3]);
2988   operands[3] = const0_rtx;
2989   "
2992 (define_expand "cstorecc4"
2993   [(set (match_operand:SI 0 "register_operand")
2994        (match_operator 1 "aarch64_comparison_operator_mode"
2995         [(match_operand 2 "cc_register")
2996          (match_operand 3 "const0_operand")]))]
2997   ""
2999   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3000   DONE;
3004 (define_expand "cstore<mode>4"
3005   [(set (match_operand:SI 0 "register_operand" "")
3006         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3007          [(match_operand:GPF 2 "register_operand" "")
3008           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3009   ""
3010   "
3011   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3012                                       operands[3]);
3013   operands[3] = const0_rtx;
3014   "
3017 (define_insn "aarch64_cstore<mode>"
3018   [(set (match_operand:ALLI 0 "register_operand" "=r")
3019         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3020          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3021   ""
3022   "cset\\t%<w>0, %m1"
3023   [(set_attr "type" "csel")]
3026 ;; For a 24-bit immediate CST we can optimize the compare for equality
3027 ;; and branch sequence from:
3028 ;;      mov     x0, #imm1
3029 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3030 ;;      cmp     x1, x0
3031 ;;      cset    x2, <ne,eq>
3032 ;; into the shorter:
3033 ;;      sub     x0, x1, #(CST & 0xfff000)
3034 ;;      subs    x0, x0, #(CST & 0x000fff)
3035 ;;      cset x2, <ne, eq>.
3036 (define_insn_and_split "*compare_cstore<mode>_insn"
3037   [(set (match_operand:GPI 0 "register_operand" "=r")
3038          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3039                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3040   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3041    && !aarch64_plus_operand (operands[2], <MODE>mode)
3042    && !reload_completed"
3043   "#"
3044   "&& true"
3045   [(const_int 0)]
3046   {
3047     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3048     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3049     rtx tmp = gen_reg_rtx (<MODE>mode);
3050     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3051     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3052     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3053     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3054     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3055     DONE;
3056   }
3057   [(set_attr "type" "csel")]
3060 ;; zero_extend version of the above
3061 (define_insn "*cstoresi_insn_uxtw"
3062   [(set (match_operand:DI 0 "register_operand" "=r")
3063         (zero_extend:DI
3064          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3065           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3066   ""
3067   "cset\\t%w0, %m1"
3068   [(set_attr "type" "csel")]
3071 (define_insn "cstore<mode>_neg"
3072   [(set (match_operand:ALLI 0 "register_operand" "=r")
3073         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3074                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3075   ""
3076   "csetm\\t%<w>0, %m1"
3077   [(set_attr "type" "csel")]
3080 ;; zero_extend version of the above
3081 (define_insn "*cstoresi_neg_uxtw"
3082   [(set (match_operand:DI 0 "register_operand" "=r")
3083         (zero_extend:DI
3084          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3085                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3086   ""
3087   "csetm\\t%w0, %m1"
3088   [(set_attr "type" "csel")]
3091 (define_expand "cmov<mode>6"
3092   [(set (match_operand:GPI 0 "register_operand" "")
3093         (if_then_else:GPI
3094          (match_operator 1 "aarch64_comparison_operator"
3095           [(match_operand:GPI 2 "register_operand" "")
3096            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3097          (match_operand:GPI 4 "register_operand" "")
3098          (match_operand:GPI 5 "register_operand" "")))]
3099   ""
3100   "
3101   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3102                                       operands[3]);
3103   operands[3] = const0_rtx;
3104   "
3107 (define_expand "cmov<mode>6"
3108   [(set (match_operand:GPF 0 "register_operand" "")
3109         (if_then_else:GPF
3110          (match_operator 1 "aarch64_comparison_operator"
3111           [(match_operand:GPF 2 "register_operand" "")
3112            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3113          (match_operand:GPF 4 "register_operand" "")
3114          (match_operand:GPF 5 "register_operand" "")))]
3115   ""
3116   "
3117   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3118                                       operands[3]);
3119   operands[3] = const0_rtx;
3120   "
3123 (define_insn "*cmov<mode>_insn"
3124   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3125         (if_then_else:ALLI
3126          (match_operator 1 "aarch64_comparison_operator"
3127           [(match_operand 2 "cc_register" "") (const_int 0)])
3128          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3129          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3130   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3131      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3132   ;; Final two alternatives should be unreachable, but included for completeness
3133   "@
3134    csel\\t%<w>0, %<w>3, %<w>4, %m1
3135    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3136    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3137    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3138    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3139    mov\\t%<w>0, -1
3140    mov\\t%<w>0, 1"
3141   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3144 ;; zero_extend version of above
3145 (define_insn "*cmovsi_insn_uxtw"
3146   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3147         (zero_extend:DI
3148          (if_then_else:SI
3149           (match_operator 1 "aarch64_comparison_operator"
3150            [(match_operand 2 "cc_register" "") (const_int 0)])
3151           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3152           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3153   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3154      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3155   ;; Final two alternatives should be unreachable, but included for completeness
3156   "@
3157    csel\\t%w0, %w3, %w4, %m1
3158    csinv\\t%w0, %w3, wzr, %m1
3159    csinv\\t%w0, %w4, wzr, %M1
3160    csinc\\t%w0, %w3, wzr, %m1
3161    csinc\\t%w0, %w4, wzr, %M1
3162    mov\\t%w0, -1
3163    mov\\t%w0, 1"
3164   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3167 (define_insn "*cmovdi_insn_uxtw"
3168   [(set (match_operand:DI 0 "register_operand" "=r")
3169         (if_then_else:DI
3170          (match_operator 1 "aarch64_comparison_operator"
3171           [(match_operand 2 "cc_register" "") (const_int 0)])
3172          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3173          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3174   ""
3175   "csel\\t%w0, %w3, %w4, %m1"
3176   [(set_attr "type" "csel")]
3179 (define_insn "*cmov<mode>_insn"
3180   [(set (match_operand:GPF 0 "register_operand" "=w")
3181         (if_then_else:GPF
3182          (match_operator 1 "aarch64_comparison_operator"
3183           [(match_operand 2 "cc_register" "") (const_int 0)])
3184          (match_operand:GPF 3 "register_operand" "w")
3185          (match_operand:GPF 4 "register_operand" "w")))]
3186   "TARGET_FLOAT"
3187   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3188   [(set_attr "type" "fcsel")]
3191 (define_expand "mov<mode>cc"
3192   [(set (match_operand:ALLI 0 "register_operand" "")
3193         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3194                            (match_operand:ALLI 2 "register_operand" "")
3195                            (match_operand:ALLI 3 "register_operand" "")))]
3196   ""
3197   {
3198     rtx ccreg;
3199     enum rtx_code code = GET_CODE (operands[1]);
3201     if (code == UNEQ || code == LTGT)
3202       FAIL;
3204     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3205                                      XEXP (operands[1], 1));
3206     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3207   }
3210 (define_expand "mov<GPF:mode><GPI:mode>cc"
3211   [(set (match_operand:GPI 0 "register_operand" "")
3212         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3213                           (match_operand:GPF 2 "register_operand" "")
3214                           (match_operand:GPF 3 "register_operand" "")))]
3215   ""
3216   {
3217     rtx ccreg;
3218     enum rtx_code code = GET_CODE (operands[1]);
3220     if (code == UNEQ || code == LTGT)
3221       FAIL;
3223     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3224                                   XEXP (operands[1], 1));
3225     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3226   }
3229 (define_expand "mov<mode>cc"
3230   [(set (match_operand:GPF 0 "register_operand" "")
3231         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3232                           (match_operand:GPF 2 "register_operand" "")
3233                           (match_operand:GPF 3 "register_operand" "")))]
3234   ""
3235   {
3236     rtx ccreg;
3237     enum rtx_code code = GET_CODE (operands[1]);
3239     if (code == UNEQ || code == LTGT)
3240       FAIL;
3242     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3243                                   XEXP (operands[1], 1));
3244     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3245   }
3248 (define_expand "<neg_not_op><mode>cc"
3249   [(set (match_operand:GPI 0 "register_operand" "")
3250         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3251                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3252                           (match_operand:GPI 3 "register_operand" "")))]
3253   ""
3254   {
3255     rtx ccreg;
3256     enum rtx_code code = GET_CODE (operands[1]);
3258     if (code == UNEQ || code == LTGT)
3259       FAIL;
3261     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3262                                       XEXP (operands[1], 1));
3263     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3264   }
3267 ;; CRC32 instructions.
3268 (define_insn "aarch64_<crc_variant>"
3269   [(set (match_operand:SI 0 "register_operand" "=r")
3270         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3271                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3272          CRC))]
3273   "TARGET_CRC32"
3274   {
3275     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3276       return "<crc_variant>\\t%w0, %w1, %x2";
3277     else
3278       return "<crc_variant>\\t%w0, %w1, %w2";
3279   }
3280   [(set_attr "type" "crc")]
3283 (define_insn "*csinc2<mode>_insn"
3284   [(set (match_operand:GPI 0 "register_operand" "=r")
3285         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3286                   (match_operand:GPI 1 "register_operand" "r")))]
3287   ""
3288   "cinc\\t%<w>0, %<w>1, %m2"
3289   [(set_attr "type" "csel")]
3292 (define_insn "csinc3<mode>_insn"
3293   [(set (match_operand:GPI 0 "register_operand" "=r")
3294         (if_then_else:GPI
3295           (match_operand 1 "aarch64_comparison_operation" "")
3296           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3297                     (const_int 1))
3298           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3299   ""
3300   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3301   [(set_attr "type" "csel")]
3304 (define_insn "*csinv3<mode>_insn"
3305   [(set (match_operand:GPI 0 "register_operand" "=r")
3306         (if_then_else:GPI
3307           (match_operand 1 "aarch64_comparison_operation" "")
3308           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3309           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3310   ""
3311   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3312   [(set_attr "type" "csel")]
3315 (define_insn "csneg3_uxtw_insn"
3316   [(set (match_operand:DI 0 "register_operand" "=r")
3317         (zero_extend:DI
3318           (if_then_else:SI
3319             (match_operand 1 "aarch64_comparison_operation" "")
3320             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3321             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3322   ""
3323   "csneg\\t%w0, %w3, %w2, %M1"
3324   [(set_attr "type" "csel")]
3327 (define_insn "csneg3<mode>_insn"
3328   [(set (match_operand:GPI 0 "register_operand" "=r")
3329         (if_then_else:GPI
3330           (match_operand 1 "aarch64_comparison_operation" "")
3331           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3332           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3333   ""
3334   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3335   [(set_attr "type" "csel")]
3338 ;; -------------------------------------------------------------------
3339 ;; Logical operations
3340 ;; -------------------------------------------------------------------
3343 (define_insn_and_split "*aarch64_and<mode>_imm2"
3344   [(set (match_operand:GPI 0 "register_operand" "=rk")
3345         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3346                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3347   ""
3348   "#"
3349   "true"
3350   [(const_int 0)]
3351   {
3352      HOST_WIDE_INT val = INTVAL (operands[2]);
3353      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3354      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3356      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3357      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3358      DONE;
3359   }
3362 (define_insn "<optab><mode>3"
3363   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3364         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3365                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3366   ""
3367   "@
3368   <logical>\\t%<w>0, %<w>1, %<w>2
3369   <logical>\\t%<w>0, %<w>1, %2
3370   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3371   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3372    (set_attr "simd" "*,*,yes")]
3375 ;; zero_extend version of above
3376 (define_insn "*<optab>si3_uxtw"
3377   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3378         (zero_extend:DI
3379          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3380                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3381   ""
3382   "@
3383    <logical>\\t%w0, %w1, %w2
3384    <logical>\\t%w0, %w1, %2"
3385   [(set_attr "type" "logic_reg,logic_imm")]
3388 (define_insn "*and<mode>3_compare0"
3389   [(set (reg:CC_NZ CC_REGNUM)
3390         (compare:CC_NZ
3391          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3392                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3393          (const_int 0)))
3394    (set (match_operand:GPI 0 "register_operand" "=r,r")
3395         (and:GPI (match_dup 1) (match_dup 2)))]
3396   ""
3397   "@
3398    ands\\t%<w>0, %<w>1, %<w>2
3399    ands\\t%<w>0, %<w>1, %2"
3400   [(set_attr "type" "logics_reg,logics_imm")]
3403 ;; zero_extend version of above
3404 (define_insn "*andsi3_compare0_uxtw"
3405   [(set (reg:CC_NZ CC_REGNUM)
3406         (compare:CC_NZ
3407          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3408                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3409          (const_int 0)))
3410    (set (match_operand:DI 0 "register_operand" "=r,r")
3411         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3412   ""
3413   "@
3414    ands\\t%w0, %w1, %w2
3415    ands\\t%w0, %w1, %2"
3416   [(set_attr "type" "logics_reg,logics_imm")]
3419 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3420   [(set (reg:CC_NZ CC_REGNUM)
3421         (compare:CC_NZ
3422          (and:GPI (SHIFT:GPI
3423                    (match_operand:GPI 1 "register_operand" "r")
3424                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3425                   (match_operand:GPI 3 "register_operand" "r"))
3426          (const_int 0)))
3427    (set (match_operand:GPI 0 "register_operand" "=r")
3428         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3429   ""
3430   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3431   [(set_attr "type" "logics_shift_imm")]
3434 ;; zero_extend version of above
3435 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3436   [(set (reg:CC_NZ CC_REGNUM)
3437         (compare:CC_NZ
3438          (and:SI (SHIFT:SI
3439                   (match_operand:SI 1 "register_operand" "r")
3440                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3441                  (match_operand:SI 3 "register_operand" "r"))
3442          (const_int 0)))
3443    (set (match_operand:DI 0 "register_operand" "=r")
3444         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3445                                 (match_dup 3))))]
3446   ""
3447   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3448   [(set_attr "type" "logics_shift_imm")]
3451 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3452   [(set (match_operand:GPI 0 "register_operand" "=r")
3453         (LOGICAL:GPI (SHIFT:GPI
3454                       (match_operand:GPI 1 "register_operand" "r")
3455                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3456                      (match_operand:GPI 3 "register_operand" "r")))]
3457   ""
3458   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3459   [(set_attr "type" "logic_shift_imm")]
3462 (define_insn "*<optab>_rol<mode>3"
3463   [(set (match_operand:GPI 0 "register_operand" "=r")
3464         (LOGICAL:GPI (rotate:GPI
3465                       (match_operand:GPI 1 "register_operand" "r")
3466                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3467                      (match_operand:GPI 3 "register_operand" "r")))]
3468   ""
3469   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3470   [(set_attr "type" "logic_shift_imm")]
3473 ;; zero_extend versions of above
3474 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3475   [(set (match_operand:DI 0 "register_operand" "=r")
3476         (zero_extend:DI
3477          (LOGICAL:SI (SHIFT:SI
3478                       (match_operand:SI 1 "register_operand" "r")
3479                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3480                      (match_operand:SI 3 "register_operand" "r"))))]
3481   ""
3482   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3483   [(set_attr "type" "logic_shift_imm")]
3486 (define_insn "*<optab>_rolsi3_uxtw"
3487   [(set (match_operand:DI 0 "register_operand" "=r")
3488         (zero_extend:DI
3489          (LOGICAL:SI (rotate:SI
3490                       (match_operand:SI 1 "register_operand" "r")
3491                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3492                      (match_operand:SI 3 "register_operand" "r"))))]
3493   ""
3494   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3495   [(set_attr "type" "logic_shift_imm")]
3498 (define_insn "one_cmpl<mode>2"
3499   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3500         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3501   ""
3502   "@
3503   mvn\\t%<w>0, %<w>1
3504   mvn\\t%0.8b, %1.8b"
3505   [(set_attr "type" "logic_reg,neon_logic")
3506    (set_attr "simd" "*,yes")]
3509 (define_insn "*one_cmpl_<optab><mode>2"
3510   [(set (match_operand:GPI 0 "register_operand" "=r")
3511         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3512                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3513   ""
3514   "mvn\\t%<w>0, %<w>1, <shift> %2"
3515   [(set_attr "type" "logic_shift_imm")]
3518 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3520 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3521   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3522         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3523                      (match_operand:GPI 2 "register_operand" "r,w")))]
3524   ""
3525   "@
3526   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3527   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3528   [(set_attr "type" "logic_reg,neon_logic")
3529    (set_attr "simd" "*,yes")]
3532 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3533   [(set (match_operand:DI 0 "register_operand" "=r")
3534         (zero_extend:DI
3535           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3536                        (match_operand:SI 2 "register_operand" "r"))))]
3537   ""
3538   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3539   [(set_attr "type" "logic_reg")]
3542 (define_insn "*xor_one_cmplsidi3_ze"
3543   [(set (match_operand:DI 0 "register_operand" "=r")
3544         (zero_extend:DI
3545           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3546                           (match_operand:SI 2 "register_operand" "r")))))]
3547   ""
3548   "eon\\t%w0, %w1, %w2"
3549   [(set_attr "type" "logic_reg")]
3552 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3553 ;; eon does not operate on SIMD registers so the vector variant must be split.
3554 (define_insn_and_split "*xor_one_cmpl<mode>3"
3555   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3556         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3557                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3558   ""
3559   "@
3560   eon\\t%<w>0, %<w>1, %<w>2
3561   #"
3562   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3563   [(set (match_operand:GPI 0 "register_operand" "=w")
3564         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3565                  (match_operand:GPI 2 "register_operand" "w")))
3566    (set (match_dup 0) (not:GPI (match_dup 0)))]
3567   ""
3568   [(set_attr "type" "logic_reg,multiple")
3569    (set_attr "simd" "*,yes")]
3572 (define_insn "*and_one_cmpl<mode>3_compare0"
3573   [(set (reg:CC_NZ CC_REGNUM)
3574         (compare:CC_NZ
3575          (and:GPI (not:GPI
3576                    (match_operand:GPI 1 "register_operand" "r"))
3577                   (match_operand:GPI 2 "register_operand" "r"))
3578          (const_int 0)))
3579    (set (match_operand:GPI 0 "register_operand" "=r")
3580         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3581   ""
3582   "bics\\t%<w>0, %<w>2, %<w>1"
3583   [(set_attr "type" "logics_reg")]
3586 ;; zero_extend version of above
3587 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3588   [(set (reg:CC_NZ CC_REGNUM)
3589         (compare:CC_NZ
3590          (and:SI (not:SI
3591                   (match_operand:SI 1 "register_operand" "r"))
3592                  (match_operand:SI 2 "register_operand" "r"))
3593          (const_int 0)))
3594    (set (match_operand:DI 0 "register_operand" "=r")
3595         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3596   ""
3597   "bics\\t%w0, %w2, %w1"
3598   [(set_attr "type" "logics_reg")]
3601 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3602   [(set (reg:CC_NZ CC_REGNUM)
3603     (compare:CC_NZ
3604      (and:GPI (not:GPI
3605            (match_operand:GPI 0 "register_operand" "r"))
3606           (match_operand:GPI 1 "register_operand" "r"))
3607      (const_int 0)))]
3608   ""
3609   "bics\\t<w>zr, %<w>1, %<w>0"
3610   [(set_attr "type" "logics_reg")]
3613 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3614   [(set (match_operand:GPI 0 "register_operand" "=r")
3615         (LOGICAL:GPI (not:GPI
3616                       (SHIFT:GPI
3617                        (match_operand:GPI 1 "register_operand" "r")
3618                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3619                      (match_operand:GPI 3 "register_operand" "r")))]
3620   ""
3621   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3622   [(set_attr "type" "logic_shift_imm")]
3625 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3626   [(set (match_operand:GPI 0 "register_operand" "=r")
3627         (not:GPI (xor:GPI
3628                       (SHIFT:GPI
3629                        (match_operand:GPI 1 "register_operand" "r")
3630                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3631                      (match_operand:GPI 3 "register_operand" "r"))))]
3632   ""
3633   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3634   [(set_attr "type" "logic_shift_imm")]
3637 ;; Zero-extend version of the above.
3638 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3639   [(set (match_operand:DI 0 "register_operand" "=r")
3640         (zero_extend:DI
3641           (not:SI (xor:SI
3642                     (SHIFT:SI
3643                       (match_operand:SI 1 "register_operand" "r")
3644                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3645                     (match_operand:SI 3 "register_operand" "r")))))]
3646   ""
3647   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3648   [(set_attr "type" "logic_shift_imm")]
3651 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3652   [(set (reg:CC_NZ CC_REGNUM)
3653         (compare:CC_NZ
3654          (and:GPI (not:GPI
3655                    (SHIFT:GPI
3656                     (match_operand:GPI 1 "register_operand" "r")
3657                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3658                   (match_operand:GPI 3 "register_operand" "r"))
3659          (const_int 0)))
3660    (set (match_operand:GPI 0 "register_operand" "=r")
3661         (and:GPI (not:GPI
3662                   (SHIFT:GPI
3663                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3664   ""
3665   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3666   [(set_attr "type" "logics_shift_imm")]
3669 ;; zero_extend version of above
3670 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3671   [(set (reg:CC_NZ CC_REGNUM)
3672         (compare:CC_NZ
3673          (and:SI (not:SI
3674                   (SHIFT:SI
3675                    (match_operand:SI 1 "register_operand" "r")
3676                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3677                  (match_operand:SI 3 "register_operand" "r"))
3678          (const_int 0)))
3679    (set (match_operand:DI 0 "register_operand" "=r")
3680         (zero_extend:DI (and:SI
3681                          (not:SI
3682                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3683   ""
3684   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3685   [(set_attr "type" "logics_shift_imm")]
3688 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3689   [(set (reg:CC_NZ CC_REGNUM)
3690     (compare:CC_NZ
3691      (and:GPI (not:GPI
3692            (SHIFT:GPI
3693             (match_operand:GPI 0 "register_operand" "r")
3694             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3695           (match_operand:GPI 2 "register_operand" "r"))
3696      (const_int 0)))]
3697   ""
3698   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3699   [(set_attr "type" "logics_shift_imm")]
3702 (define_insn "clz<mode>2"
3703   [(set (match_operand:GPI 0 "register_operand" "=r")
3704         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3705   ""
3706   "clz\\t%<w>0, %<w>1"
3707   [(set_attr "type" "clz")]
3710 (define_expand "ffs<mode>2"
3711   [(match_operand:GPI 0 "register_operand")
3712    (match_operand:GPI 1 "register_operand")]
3713   ""
3714   {
3715     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3716     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3718     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3719     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3720     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3721     DONE;
3722   }
3725 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3727 ;; MOV  v.1d, x0
3728 ;; CNT  v1.8b, v.8b
3729 ;; ADDV b2, v1.8b
3730 ;; MOV  w0, v2.b[0]
3732 (define_expand "popcount<mode>2"
3733   [(match_operand:GPI 0 "register_operand")
3734    (match_operand:GPI 1 "register_operand")]
3735   "TARGET_SIMD"
3737   rtx v = gen_reg_rtx (V8QImode);
3738   rtx v1 = gen_reg_rtx (V8QImode);
3739   rtx r = gen_reg_rtx (QImode);
3740   rtx in = operands[1];
3741   rtx out = operands[0];
3742   if(<MODE>mode == SImode)
3743     {
3744       rtx tmp;
3745       tmp = gen_reg_rtx (DImode);
3746       /* If we have SImode, zero extend to DImode, pop count does
3747          not change if we have extra zeros. */
3748       emit_insn (gen_zero_extendsidi2 (tmp, in));
3749       in = tmp;
3750     }
3751   emit_move_insn (v, gen_lowpart (V8QImode, in));
3752   emit_insn (gen_popcountv8qi2 (v1, v));
3753   emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3754   emit_insn (gen_zero_extendqi<mode>2 (out, r));
3755   DONE;
3758 (define_insn "clrsb<mode>2"
3759   [(set (match_operand:GPI 0 "register_operand" "=r")
3760         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3761   ""
3762   "cls\\t%<w>0, %<w>1"
3763   [(set_attr "type" "clz")]
3766 (define_insn "rbit<mode>2"
3767   [(set (match_operand:GPI 0 "register_operand" "=r")
3768         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3769   ""
3770   "rbit\\t%<w>0, %<w>1"
3771   [(set_attr "type" "rbit")]
3774 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3775 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3776 ;; expression and split after reload to enable scheduling them apart if
3777 ;; needed.
3779 (define_insn_and_split "ctz<mode>2"
3780  [(set (match_operand:GPI           0 "register_operand" "=r")
3781        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3782   ""
3783   "#"
3784   "reload_completed"
3785   [(const_int 0)]
3786   "
3787   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3788   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3789   DONE;
3792 (define_insn "*and<mode>_compare0"
3793   [(set (reg:CC_NZ CC_REGNUM)
3794         (compare:CC_NZ
3795          (match_operand:SHORT 0 "register_operand" "r")
3796          (const_int 0)))]
3797   ""
3798   "tst\\t%<w>0, <short_mask>"
3799   [(set_attr "type" "alus_imm")]
3802 (define_insn "*ands<mode>_compare0"
3803   [(set (reg:CC_NZ CC_REGNUM)
3804         (compare:CC_NZ
3805          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3806          (const_int 0)))
3807    (set (match_operand:GPI 0 "register_operand" "=r")
3808         (zero_extend:GPI (match_dup 1)))]
3809   ""
3810   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3811   [(set_attr "type" "alus_imm")]
3814 (define_insn "*and<mode>3nr_compare0"
3815   [(set (reg:CC_NZ CC_REGNUM)
3816         (compare:CC_NZ
3817          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3818                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3819          (const_int 0)))]
3820   ""
3821   "@
3822    tst\\t%<w>0, %<w>1
3823    tst\\t%<w>0, %1"
3824   [(set_attr "type" "logics_reg,logics_imm")]
3827 (define_insn "*and<mode>3nr_compare0_zextract"
3828   [(set (reg:CC_NZ CC_REGNUM)
3829         (compare:CC_NZ
3830          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3831                   (match_operand:GPI 1 "const_int_operand" "n")
3832                   (match_operand:GPI 2 "const_int_operand" "n"))
3833          (const_int 0)))]
3834   "INTVAL (operands[1]) > 0
3835    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3836         <= GET_MODE_BITSIZE (<MODE>mode))
3837    && aarch64_bitmask_imm (
3838         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3839                                                  operands[2])),
3840         <MODE>mode)"
3841   {
3842     operands[1]
3843       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3844     return "tst\\t%<w>0, %1";
3845   }
3846   [(set_attr "type" "logics_shift_imm")]
3849 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3850   [(set (reg:CC_NZ CC_REGNUM)
3851         (compare:CC_NZ
3852          (and:GPI (SHIFT:GPI
3853                    (match_operand:GPI 0 "register_operand" "r")
3854                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3855                   (match_operand:GPI 2 "register_operand" "r"))
3856         (const_int 0)))]
3857   ""
3858   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3859   [(set_attr "type" "logics_shift_imm")]
3862 ;; -------------------------------------------------------------------
3863 ;; Shifts
3864 ;; -------------------------------------------------------------------
3866 (define_expand "<optab><mode>3"
3867   [(set (match_operand:GPI 0 "register_operand")
3868         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3869                     (match_operand:QI 2 "nonmemory_operand")))]
3870   ""
3871   {
3872     if (CONST_INT_P (operands[2]))
3873       {
3874         operands[2] = GEN_INT (INTVAL (operands[2])
3875                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3877         if (operands[2] == const0_rtx)
3878           {
3879             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3880             DONE;
3881           }
3882       }
3883   }
3886 (define_expand "ashl<mode>3"
3887   [(set (match_operand:SHORT 0 "register_operand")
3888         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3889                       (match_operand:QI 2 "const_int_operand")))]
3890   ""
3891   {
3892     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3894     if (operands[2] == const0_rtx)
3895       {
3896         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3897         DONE;
3898       }
3899   }
3902 (define_expand "rotr<mode>3"
3903   [(set (match_operand:GPI 0 "register_operand")
3904         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3905                       (match_operand:QI 2 "nonmemory_operand")))]
3906   ""
3907   {
3908     if (CONST_INT_P (operands[2]))
3909       {
3910         operands[2] = GEN_INT (INTVAL (operands[2])
3911                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3913         if (operands[2] == const0_rtx)
3914           {
3915             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3916             DONE;
3917           }
3918       }
3919   }
3922 (define_expand "rotl<mode>3"
3923   [(set (match_operand:GPI 0 "register_operand")
3924         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3925                       (match_operand:QI 2 "nonmemory_operand")))]
3926   ""
3927   {
3928     /* (SZ - cnt) % SZ == -cnt % SZ */
3929     if (CONST_INT_P (operands[2]))
3930       {
3931         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3932                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3933         if (operands[2] == const0_rtx)
3934           {
3935             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3936             DONE;
3937           }
3938       }
3939     else
3940       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3941                                         NULL_RTX, 1);
3942   }
3945 ;; Logical left shift using SISD or Integer instruction
3946 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3947   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3948         (ashift:GPI
3949           (match_operand:GPI 1 "register_operand" "r,r,w,w")
3950           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3951   ""
3952   "@
3953    lsl\t%<w>0, %<w>1, %2
3954    lsl\t%<w>0, %<w>1, %<w>2
3955    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3956    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3957   [(set_attr "simd" "no,no,yes,yes")
3958    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3961 ;; Logical right shift using SISD or Integer instruction
3962 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3963   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3964         (lshiftrt:GPI
3965          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3966          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3967   ""
3968   "@
3969    lsr\t%<w>0, %<w>1, %2
3970    lsr\t%<w>0, %<w>1, %<w>2
3971    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3972    #
3973    #"
3974   [(set_attr "simd" "no,no,yes,yes,yes")
3975    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3978 (define_split
3979   [(set (match_operand:DI 0 "aarch64_simd_register")
3980         (lshiftrt:DI
3981            (match_operand:DI 1 "aarch64_simd_register")
3982            (match_operand:QI 2 "aarch64_simd_register")))]
3983   "TARGET_SIMD && reload_completed"
3984   [(set (match_dup 3)
3985         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3986    (set (match_dup 0)
3987         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3988   {
3989     operands[3] = gen_lowpart (QImode, operands[0]);
3990   }
3993 (define_split
3994   [(set (match_operand:SI 0 "aarch64_simd_register")
3995         (lshiftrt:SI
3996            (match_operand:SI 1 "aarch64_simd_register")
3997            (match_operand:QI 2 "aarch64_simd_register")))]
3998   "TARGET_SIMD && reload_completed"
3999   [(set (match_dup 3)
4000         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4001    (set (match_dup 0)
4002         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4003   {
4004     operands[3] = gen_lowpart (QImode, operands[0]);
4005   }
4008 ;; Arithmetic right shift using SISD or Integer instruction
4009 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4010   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4011         (ashiftrt:GPI
4012           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4013           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4014   ""
4015   "@
4016    asr\t%<w>0, %<w>1, %2
4017    asr\t%<w>0, %<w>1, %<w>2
4018    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4019    #
4020    #"
4021   [(set_attr "simd" "no,no,yes,yes,yes")
4022    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4025 (define_split
4026   [(set (match_operand:DI 0 "aarch64_simd_register")
4027         (ashiftrt:DI
4028            (match_operand:DI 1 "aarch64_simd_register")
4029            (match_operand:QI 2 "aarch64_simd_register")))]
4030   "TARGET_SIMD && reload_completed"
4031   [(set (match_dup 3)
4032         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4033    (set (match_dup 0)
4034         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4036   operands[3] = gen_lowpart (QImode, operands[0]);
4040 (define_split
4041   [(set (match_operand:SI 0 "aarch64_simd_register")
4042         (ashiftrt:SI
4043            (match_operand:SI 1 "aarch64_simd_register")
4044            (match_operand:QI 2 "aarch64_simd_register")))]
4045   "TARGET_SIMD && reload_completed"
4046   [(set (match_dup 3)
4047         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4048    (set (match_dup 0)
4049         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4051   operands[3] = gen_lowpart (QImode, operands[0]);
4055 (define_insn "*aarch64_sisd_ushl"
4056   [(set (match_operand:DI 0 "register_operand" "=w")
4057         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4058                     (match_operand:QI 2 "register_operand" "w")]
4059                    UNSPEC_SISD_USHL))]
4060   "TARGET_SIMD"
4061   "ushl\t%d0, %d1, %d2"
4062   [(set_attr "simd" "yes")
4063    (set_attr "type" "neon_shift_reg")]
4066 (define_insn "*aarch64_ushl_2s"
4067   [(set (match_operand:SI 0 "register_operand" "=w")
4068         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4069                     (match_operand:QI 2 "register_operand" "w")]
4070                    UNSPEC_USHL_2S))]
4071   "TARGET_SIMD"
4072   "ushl\t%0.2s, %1.2s, %2.2s"
4073   [(set_attr "simd" "yes")
4074    (set_attr "type" "neon_shift_reg")]
4077 (define_insn "*aarch64_sisd_sshl"
4078   [(set (match_operand:DI 0 "register_operand" "=w")
4079         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4080                     (match_operand:QI 2 "register_operand" "w")]
4081                    UNSPEC_SISD_SSHL))]
4082   "TARGET_SIMD"
4083   "sshl\t%d0, %d1, %d2"
4084   [(set_attr "simd" "yes")
4085    (set_attr "type" "neon_shift_reg")]
4088 (define_insn "*aarch64_sshl_2s"
4089   [(set (match_operand:SI 0 "register_operand" "=w")
4090         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4091                     (match_operand:QI 2 "register_operand" "w")]
4092                    UNSPEC_SSHL_2S))]
4093   "TARGET_SIMD"
4094   "sshl\t%0.2s, %1.2s, %2.2s"
4095   [(set_attr "simd" "yes")
4096    (set_attr "type" "neon_shift_reg")]
4099 (define_insn "*aarch64_sisd_neg_qi"
4100   [(set (match_operand:QI 0 "register_operand" "=w")
4101         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4102                    UNSPEC_SISD_NEG))]
4103   "TARGET_SIMD"
4104   "neg\t%d0, %d1"
4105   [(set_attr "simd" "yes")
4106    (set_attr "type" "neon_neg")]
4109 ;; Rotate right
4110 (define_insn "*ror<mode>3_insn"
4111   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4112      (rotatert:GPI
4113        (match_operand:GPI 1 "register_operand" "r,r")
4114        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4115   ""
4116   "@
4117    ror\\t%<w>0, %<w>1, %2
4118    ror\\t%<w>0, %<w>1, %<w>2"
4119   [(set_attr "type" "rotate_imm,shift_reg")]
4122 ;; zero_extend version of above
4123 (define_insn "*<optab>si3_insn_uxtw"
4124   [(set (match_operand:DI 0 "register_operand" "=r,r")
4125         (zero_extend:DI (SHIFT:SI
4126          (match_operand:SI 1 "register_operand" "r,r")
4127          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4128   ""
4129   "@
4130    <shift>\\t%w0, %w1, %2
4131    <shift>\\t%w0, %w1, %w2"
4132   [(set_attr "type" "bfx,shift_reg")]
4135 (define_insn "*<optab><mode>3_insn"
4136   [(set (match_operand:SHORT 0 "register_operand" "=r")
4137         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4138                       (match_operand 2 "const_int_operand" "n")))]
4139   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4141   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4142   return "<bfshift>\t%w0, %w1, %2, %3";
4144   [(set_attr "type" "bfx")]
4147 (define_insn "*extr<mode>5_insn"
4148   [(set (match_operand:GPI 0 "register_operand" "=r")
4149         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4150                              (match_operand 3 "const_int_operand" "n"))
4151                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4152                                (match_operand 4 "const_int_operand" "n"))))]
4153   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4154    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4155   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4156   [(set_attr "type" "rotate_imm")]
4159 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4160 ;; so we have to match both orderings.
4161 (define_insn "*extr<mode>5_insn_alt"
4162   [(set (match_operand:GPI 0 "register_operand" "=r")
4163         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4164                                 (match_operand 4 "const_int_operand" "n"))
4165                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4166                               (match_operand 3 "const_int_operand" "n"))))]
4167   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4168    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4169        == GET_MODE_BITSIZE (<MODE>mode))"
4170   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4171   [(set_attr "type" "rotate_imm")]
4174 ;; zero_extend version of the above
4175 (define_insn "*extrsi5_insn_uxtw"
4176   [(set (match_operand:DI 0 "register_operand" "=r")
4177         (zero_extend:DI
4178          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4179                             (match_operand 3 "const_int_operand" "n"))
4180                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4181                               (match_operand 4 "const_int_operand" "n")))))]
4182   "UINTVAL (operands[3]) < 32 &&
4183    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4184   "extr\\t%w0, %w1, %w2, %4"
4185   [(set_attr "type" "rotate_imm")]
4188 (define_insn "*extrsi5_insn_uxtw_alt"
4189   [(set (match_operand:DI 0 "register_operand" "=r")
4190         (zero_extend:DI
4191          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4192                                (match_operand 4 "const_int_operand" "n"))
4193                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4194                             (match_operand 3 "const_int_operand" "n")))))]
4195   "UINTVAL (operands[3]) < 32 &&
4196    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4197   "extr\\t%w0, %w1, %w2, %4"
4198   [(set_attr "type" "rotate_imm")]
4201 (define_insn "*ror<mode>3_insn"
4202   [(set (match_operand:GPI 0 "register_operand" "=r")
4203         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4204                     (match_operand 2 "const_int_operand" "n")))]
4205   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4207   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4208   return "ror\\t%<w>0, %<w>1, %3";
4210   [(set_attr "type" "rotate_imm")]
4213 ;; zero_extend version of the above
4214 (define_insn "*rorsi3_insn_uxtw"
4215   [(set (match_operand:DI 0 "register_operand" "=r")
4216         (zero_extend:DI
4217          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4218                     (match_operand 2 "const_int_operand" "n"))))]
4219   "UINTVAL (operands[2]) < 32"
4221   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4222   return "ror\\t%w0, %w1, %3";
4224   [(set_attr "type" "rotate_imm")]
4227 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4228   [(set (match_operand:GPI 0 "register_operand" "=r")
4229         (ANY_EXTEND:GPI
4230          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4231                        (match_operand 2 "const_int_operand" "n"))))]
4232   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4234   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4235   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4237   [(set_attr "type" "bfx")]
4240 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4241   [(set (match_operand:GPI 0 "register_operand" "=r")
4242         (zero_extend:GPI
4243          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4244                          (match_operand 2 "const_int_operand" "n"))))]
4245   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4247   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4248   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4250   [(set_attr "type" "bfx")]
4253 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4254   [(set (match_operand:GPI 0 "register_operand" "=r")
4255         (sign_extend:GPI
4256          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4257                          (match_operand 2 "const_int_operand" "n"))))]
4258   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4260   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4261   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4263   [(set_attr "type" "bfx")]
4266 ;; -------------------------------------------------------------------
4267 ;; Bitfields
4268 ;; -------------------------------------------------------------------
4270 (define_expand "<optab>"
4271   [(set (match_operand:DI 0 "register_operand" "=r")
4272         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4273                         (match_operand 2
4274                           "aarch64_simd_shift_imm_offset_di")
4275                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4276   ""
4277   {
4278     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4279                    1, GET_MODE_BITSIZE (DImode) - 1))
4280      FAIL;
4281   }
4285 (define_insn "*<optab><mode>"
4286   [(set (match_operand:GPI 0 "register_operand" "=r")
4287         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4288                          (match_operand 2
4289                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4290                          (match_operand 3
4291                            "aarch64_simd_shift_imm_<mode>" "n")))]
4292   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4293              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4294   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4295   [(set_attr "type" "bfx")]
4298 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4299 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4300 (define_split
4301   [(set (match_operand:DI 0 "register_operand")
4302         (zero_extract:DI (match_operand:DI 1 "register_operand")
4303                          (match_operand 2
4304                            "aarch64_simd_shift_imm_offset_di")
4305                          (match_operand 3
4306                            "aarch64_simd_shift_imm_di")))]
4307   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4308              GET_MODE_BITSIZE (DImode) - 1)
4309    && (INTVAL (operands[2]) + INTVAL (operands[3]))
4310        == GET_MODE_BITSIZE (SImode)"
4311   [(set (match_dup 0)
4312         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4313   {
4314     operands[4] = gen_lowpart (SImode, operands[1]);
4315   }
4318 ;; Bitfield Insert (insv)
4319 (define_expand "insv<mode>"
4320   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4321                           (match_operand 1 "const_int_operand")
4322                           (match_operand 2 "const_int_operand"))
4323         (match_operand:GPI 3 "general_operand"))]
4324   ""
4326   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4327   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4328   rtx value = operands[3];
4330   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4331     FAIL;
4333   if (CONST_INT_P (value))
4334     {
4335       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4337       /* Prefer AND/OR for inserting all zeros or all ones.  */
4338       if ((UINTVAL (value) & mask) == 0
4339            || (UINTVAL (value) & mask) == mask)
4340         FAIL;
4342       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4343       if (width == 16 && (pos % 16) == 0)
4344         DONE;
4345     }
4346   operands[3] = force_reg (<MODE>mode, value);
4349 (define_insn "*insv_reg<mode>"
4350   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4351                           (match_operand 1 "const_int_operand" "n")
4352                           (match_operand 2 "const_int_operand" "n"))
4353         (match_operand:GPI 3 "register_operand" "r"))]
4354   "!(UINTVAL (operands[1]) == 0
4355      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4356          > GET_MODE_BITSIZE (<MODE>mode)))"
4357   "bfi\\t%<w>0, %<w>3, %2, %1"
4358   [(set_attr "type" "bfm")]
4361 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4362   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4363                           (match_operand 1 "const_int_operand" "n")
4364                           (match_operand 2 "const_int_operand" "n"))
4365         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4366   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4367   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4368   [(set_attr "type" "bfm")]
4371 (define_insn "*extr_insv_lower_reg<mode>"
4372   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4373                           (match_operand 1 "const_int_operand" "n")
4374                           (const_int 0))
4375         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4376                           (match_dup 1)
4377                           (match_operand 3 "const_int_operand" "n")))]
4378   "!(UINTVAL (operands[1]) == 0
4379      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4380          > GET_MODE_BITSIZE (<MODE>mode)))"
4381   "bfxil\\t%<w>0, %<w>2, %3, %1"
4382   [(set_attr "type" "bfm")]
4385 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4386   [(set (match_operand:GPI 0 "register_operand" "=r")
4387         (ashift:GPI (ANY_EXTEND:GPI
4388                      (match_operand:ALLX 1 "register_operand" "r"))
4389                     (match_operand 2 "const_int_operand" "n")))]
4390   "UINTVAL (operands[2]) < <GPI:sizen>"
4392   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4393               ? GEN_INT (<ALLX:sizen>)
4394               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4395   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4397   [(set_attr "type" "bfx")]
4400 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4402 (define_insn "*andim_ashift<mode>_bfiz"
4403   [(set (match_operand:GPI 0 "register_operand" "=r")
4404         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4405                              (match_operand 2 "const_int_operand" "n"))
4406                  (match_operand 3 "const_int_operand" "n")))]
4407   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4408   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4409   [(set_attr "type" "bfx")]
4412 ;; When the bit position and width of the equivalent extraction add up to 32
4413 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4414 ;; zero-extension of the X-reg.
4415 (define_split
4416   [(set (match_operand:DI 0 "register_operand")
4417         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4418                              (match_operand 2 "const_int_operand"))
4419                  (match_operand 3 "const_int_operand")))]
4420  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4421   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4422       == GET_MODE_BITSIZE (SImode)"
4423   [(set (match_dup 0)
4424         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4425   {
4426     operands[4] = gen_lowpart (SImode, operands[1]);
4427   }
4430 (define_insn "bswap<mode>2"
4431   [(set (match_operand:GPI 0 "register_operand" "=r")
4432         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4433   ""
4434   "rev\\t%<w>0, %<w>1"
4435   [(set_attr "type" "rev")]
4438 (define_insn "bswaphi2"
4439   [(set (match_operand:HI 0 "register_operand" "=r")
4440         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4441   ""
4442   "rev16\\t%w0, %w1"
4443   [(set_attr "type" "rev")]
4446 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4447 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4448 ;; each valid permutation.
4450 (define_insn "rev16<mode>2"
4451   [(set (match_operand:GPI 0 "register_operand" "=r")
4452         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4453                                       (const_int 8))
4454                           (match_operand:GPI 3 "const_int_operand" "n"))
4455                  (and:GPI (lshiftrt:GPI (match_dup 1)
4456                                         (const_int 8))
4457                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4458   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4459    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4460   "rev16\\t%<w>0, %<w>1"
4461   [(set_attr "type" "rev")]
4464 (define_insn "rev16<mode>2_alt"
4465   [(set (match_operand:GPI 0 "register_operand" "=r")
4466         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4467                                         (const_int 8))
4468                           (match_operand:GPI 2 "const_int_operand" "n"))
4469                  (and:GPI (ashift:GPI (match_dup 1)
4470                                       (const_int 8))
4471                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4472   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4473    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4474   "rev16\\t%<w>0, %<w>1"
4475   [(set_attr "type" "rev")]
4478 ;; zero_extend version of above
4479 (define_insn "*bswapsi2_uxtw"
4480   [(set (match_operand:DI 0 "register_operand" "=r")
4481         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4482   ""
4483   "rev\\t%w0, %w1"
4484   [(set_attr "type" "rev")]
4487 ;; -------------------------------------------------------------------
4488 ;; Floating-point intrinsics
4489 ;; -------------------------------------------------------------------
4491 ;; frint floating-point round to integral standard patterns.
4492 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4494 (define_insn "<frint_pattern><mode>2"
4495   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4496         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4497          FRINT))]
4498   "TARGET_FLOAT"
4499   "frint<frint_suffix>\\t%<s>0, %<s>1"
4500   [(set_attr "type" "f_rint<stype>")]
4503 ;; frcvt floating-point round to integer and convert standard patterns.
4504 ;; Expands to lbtrunc, lceil, lfloor, lround.
4505 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4506   [(set (match_operand:GPI 0 "register_operand" "=r")
4507         (FIXUORS:GPI
4508           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4509            FCVT)))]
4510   "TARGET_FLOAT"
4511   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4512   [(set_attr "type" "f_cvtf2i")]
4515 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4516   [(set (match_operand:GPI 0 "register_operand" "=r")
4517         (FIXUORS:GPI
4518           (mult:GPF
4519             (match_operand:GPF 1 "register_operand" "w")
4520             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4521   "TARGET_FLOAT
4522    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4523                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4524   {
4525     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4526     char buf[64];
4527     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4528     output_asm_insn (buf, operands);
4529     return "";
4530   }
4531   [(set_attr "type" "f_cvtf2i")]
4534 ;; fma - no throw
4536 (define_insn "fma<mode>4"
4537   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4538         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4539                      (match_operand:GPF_F16 2 "register_operand" "w")
4540                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4541   "TARGET_FLOAT"
4542   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4543   [(set_attr "type" "fmac<stype>")]
4546 (define_insn "fnma<mode>4"
4547   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4548         (fma:GPF_F16
4549           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4550           (match_operand:GPF_F16 2 "register_operand" "w")
4551           (match_operand:GPF_F16 3 "register_operand" "w")))]
4552   "TARGET_FLOAT"
4553   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4554   [(set_attr "type" "fmac<stype>")]
4557 (define_insn "fms<mode>4"
4558   [(set (match_operand:GPF 0 "register_operand" "=w")
4559         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4560                  (match_operand:GPF 2 "register_operand" "w")
4561                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4562   "TARGET_FLOAT"
4563   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4564   [(set_attr "type" "fmac<s>")]
4567 (define_insn "fnms<mode>4"
4568   [(set (match_operand:GPF 0 "register_operand" "=w")
4569         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4570                  (match_operand:GPF 2 "register_operand" "w")
4571                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4572   "TARGET_FLOAT"
4573   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4574   [(set_attr "type" "fmac<s>")]
4577 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4578 (define_insn "*fnmadd<mode>4"
4579   [(set (match_operand:GPF 0 "register_operand" "=w")
4580         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4581                           (match_operand:GPF 2 "register_operand" "w")
4582                           (match_operand:GPF 3 "register_operand" "w"))))]
4583   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4584   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4585   [(set_attr "type" "fmac<s>")]
4588 ;; -------------------------------------------------------------------
4589 ;; Floating-point conversions
4590 ;; -------------------------------------------------------------------
4592 (define_insn "extendsfdf2"
4593   [(set (match_operand:DF 0 "register_operand" "=w")
4594         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4595   "TARGET_FLOAT"
4596   "fcvt\\t%d0, %s1"
4597   [(set_attr "type" "f_cvt")]
4600 (define_insn "extendhfsf2"
4601   [(set (match_operand:SF 0 "register_operand" "=w")
4602         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4603   "TARGET_FLOAT"
4604   "fcvt\\t%s0, %h1"
4605   [(set_attr "type" "f_cvt")]
4608 (define_insn "extendhfdf2"
4609   [(set (match_operand:DF 0 "register_operand" "=w")
4610         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4611   "TARGET_FLOAT"
4612   "fcvt\\t%d0, %h1"
4613   [(set_attr "type" "f_cvt")]
4616 (define_insn "truncdfsf2"
4617   [(set (match_operand:SF 0 "register_operand" "=w")
4618         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4619   "TARGET_FLOAT"
4620   "fcvt\\t%s0, %d1"
4621   [(set_attr "type" "f_cvt")]
4624 (define_insn "truncsfhf2"
4625   [(set (match_operand:HF 0 "register_operand" "=w")
4626         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4627   "TARGET_FLOAT"
4628   "fcvt\\t%h0, %s1"
4629   [(set_attr "type" "f_cvt")]
4632 (define_insn "truncdfhf2"
4633   [(set (match_operand:HF 0 "register_operand" "=w")
4634         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4635   "TARGET_FLOAT"
4636   "fcvt\\t%h0, %d1"
4637   [(set_attr "type" "f_cvt")]
4640 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4641   [(set (match_operand:GPI 0 "register_operand" "=r")
4642         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4643   "TARGET_FLOAT"
4644   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4645   [(set_attr "type" "f_cvtf2i")]
4648 (define_insn "<optab><fcvt_target><GPF:mode>2"
4649   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4650         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4651   "TARGET_FLOAT"
4652   "@
4653    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4654    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4655   [(set_attr "simd" "yes,no")
4656    (set_attr "fp" "no,yes")
4657    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4660 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4661   [(set (match_operand:GPF 0 "register_operand" "=w")
4662         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4663   "TARGET_FLOAT"
4664   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4665   [(set_attr "type" "f_cvti2f")]
4668 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4669 ;; midend will arrange for an SImode conversion to HFmode to first go
4670 ;; through DFmode, then to HFmode.  But first it will try converting
4671 ;; to DImode then down, which would match our DImode pattern below and
4672 ;; give very poor code-generation.  So, we must provide our own emulation
4673 ;; of the mid-end logic.
4675 (define_insn "aarch64_fp16_<optab><mode>hf2"
4676   [(set (match_operand:HF 0 "register_operand" "=w")
4677         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4678   "TARGET_FP_F16INST"
4679   "<su_optab>cvtf\t%h0, %<w>1"
4680   [(set_attr "type" "f_cvti2f")]
4683 (define_expand "<optab>sihf2"
4684   [(set (match_operand:HF 0 "register_operand")
4685         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4686   "TARGET_FLOAT"
4688   if (TARGET_FP_F16INST)
4689     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4690   else
4691     {
4692       rtx convert_target = gen_reg_rtx (DFmode);
4693       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4694       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4695     }
4696   DONE;
4700 ;; For DImode there is no wide enough floating-point mode that we
4701 ;; can convert through natively (TFmode would work, but requires a library
4702 ;; call).  However, we know that any value >= 65504 will be rounded
4703 ;; to infinity on conversion.  This is well within the range of SImode, so
4704 ;; we can:
4705 ;;   Saturate to SImode.
4706 ;;   Convert from that to DFmode
4707 ;;   Convert from that to HFmode (phew!).
4708 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4709 ;; we ever need to provide this pattern where the SIMD extensions are not
4710 ;; available, we would need a different approach.
4712 (define_expand "<optab>dihf2"
4713   [(set (match_operand:HF 0 "register_operand")
4714         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4715   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4717   if (TARGET_FP_F16INST)
4718     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4719   else
4720     {
4721       rtx sat_target = gen_reg_rtx (SImode);
4722       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4723       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4724     }
4726   DONE;
4730 ;; Convert between fixed-point and floating-point (scalar modes)
4732 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4733   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4734         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4735                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4736          FCVT_F2FIXED))]
4737   ""
4738   "@
4739    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4740    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4741   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4742    (set_attr "fp" "yes, *")
4743    (set_attr "simd" "*, yes")]
4746 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4747   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4748         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4749                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4750          FCVT_FIXED2F))]
4751   ""
4752   "@
4753    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4754    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4755   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4756    (set_attr "fp" "yes, *")
4757    (set_attr "simd" "*, yes")]
4760 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4761   [(set (match_operand:GPI 0 "register_operand" "=r")
4762         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4763                      (match_operand:SI 2 "immediate_operand" "i")]
4764          FCVT_F2FIXED))]
4765   "TARGET_FP_F16INST"
4766    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4767   [(set_attr "type" "f_cvtf2i")]
4770 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4771   [(set (match_operand:HF 0 "register_operand" "=w")
4772         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4773                     (match_operand:SI 2 "immediate_operand" "i")]
4774          FCVT_FIXED2F))]
4775   "TARGET_FP_F16INST"
4776   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4777   [(set_attr "type" "f_cvti2f")]
4780 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4781   [(set (match_operand:HI 0 "register_operand" "=w")
4782         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4783                     (match_operand:SI 2 "immediate_operand" "i")]
4784          FCVT_F2FIXED))]
4785   "TARGET_SIMD"
4786   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4787   [(set_attr "type" "neon_fp_to_int_s")]
4790 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4791   [(set (match_operand:HF 0 "register_operand" "=w")
4792         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4793                     (match_operand:SI 2 "immediate_operand" "i")]
4794          FCVT_FIXED2F))]
4795   "TARGET_SIMD"
4796   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4797   [(set_attr "type" "neon_int_to_fp_s")]
4800 ;; -------------------------------------------------------------------
4801 ;; Floating-point arithmetic
4802 ;; -------------------------------------------------------------------
4804 (define_insn "add<mode>3"
4805   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4806         (plus:GPF_F16
4807          (match_operand:GPF_F16 1 "register_operand" "w")
4808          (match_operand:GPF_F16 2 "register_operand" "w")))]
4809   "TARGET_FLOAT"
4810   "fadd\\t%<s>0, %<s>1, %<s>2"
4811   [(set_attr "type" "fadd<stype>")]
4814 (define_insn "sub<mode>3"
4815   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4816         (minus:GPF_F16
4817          (match_operand:GPF_F16 1 "register_operand" "w")
4818          (match_operand:GPF_F16 2 "register_operand" "w")))]
4819   "TARGET_FLOAT"
4820   "fsub\\t%<s>0, %<s>1, %<s>2"
4821   [(set_attr "type" "fadd<stype>")]
4824 (define_insn "mul<mode>3"
4825   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4826         (mult:GPF_F16
4827          (match_operand:GPF_F16 1 "register_operand" "w")
4828          (match_operand:GPF_F16 2 "register_operand" "w")))]
4829   "TARGET_FLOAT"
4830   "fmul\\t%<s>0, %<s>1, %<s>2"
4831   [(set_attr "type" "fmul<stype>")]
4834 (define_insn "*fnmul<mode>3"
4835   [(set (match_operand:GPF 0 "register_operand" "=w")
4836         (mult:GPF
4837                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4838                  (match_operand:GPF 2 "register_operand" "w")))]
4839   "TARGET_FLOAT && !flag_rounding_math"
4840   "fnmul\\t%<s>0, %<s>1, %<s>2"
4841   [(set_attr "type" "fmul<s>")]
4844 (define_insn "*fnmul<mode>3"
4845   [(set (match_operand:GPF 0 "register_operand" "=w")
4846         (neg:GPF (mult:GPF
4847                  (match_operand:GPF 1 "register_operand" "w")
4848                  (match_operand:GPF 2 "register_operand" "w"))))]
4849   "TARGET_FLOAT"
4850   "fnmul\\t%<s>0, %<s>1, %<s>2"
4851   [(set_attr "type" "fmul<s>")]
4854 (define_expand "div<mode>3"
4855  [(set (match_operand:GPF_F16 0 "register_operand")
4856        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4857                     (match_operand:GPF_F16 2 "register_operand")))]
4858  "TARGET_SIMD"
4860   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4861     DONE;
4863   operands[1] = force_reg (<MODE>mode, operands[1]);
4866 (define_insn "*div<mode>3"
4867   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4868         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4869                      (match_operand:GPF_F16 2 "register_operand" "w")))]
4870   "TARGET_FLOAT"
4871   "fdiv\\t%<s>0, %<s>1, %<s>2"
4872   [(set_attr "type" "fdiv<stype>")]
4875 (define_insn "neg<mode>2"
4876   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4878   "TARGET_FLOAT"
4879   "fneg\\t%<s>0, %<s>1"
4880   [(set_attr "type" "ffarith<stype>")]
4883 (define_expand "sqrt<mode>2"
4884   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4885         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4886   "TARGET_FLOAT"
4888   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4889     DONE;
4892 (define_insn "*sqrt<mode>2"
4893   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4894         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4895   "TARGET_FLOAT"
4896   "fsqrt\\t%<s>0, %<s>1"
4897   [(set_attr "type" "fsqrt<stype>")]
4900 (define_insn "abs<mode>2"
4901   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4902         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4903   "TARGET_FLOAT"
4904   "fabs\\t%<s>0, %<s>1"
4905   [(set_attr "type" "ffarith<stype>")]
4908 ;; Given that smax/smin do not specify the result when either input is NaN,
4909 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4910 ;; for smin.
4912 (define_insn "smax<mode>3"
4913   [(set (match_operand:GPF 0 "register_operand" "=w")
4914         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4915                   (match_operand:GPF 2 "register_operand" "w")))]
4916   "TARGET_FLOAT"
4917   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4918   [(set_attr "type" "f_minmax<s>")]
4921 (define_insn "smin<mode>3"
4922   [(set (match_operand:GPF 0 "register_operand" "=w")
4923         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4924                   (match_operand:GPF 2 "register_operand" "w")))]
4925   "TARGET_FLOAT"
4926   "fminnm\\t%<s>0, %<s>1, %<s>2"
4927   [(set_attr "type" "f_minmax<s>")]
4930 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4931 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4932 ;; which implement the IEEE fmax ()/fmin () functions.
4933 (define_insn "<maxmin_uns><mode>3"
4934   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4935         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4936                      (match_operand:GPF_F16 2 "register_operand" "w")]
4937                      FMAXMIN_UNS))]
4938   "TARGET_FLOAT"
4939   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4940   [(set_attr "type" "f_minmax<stype>")]
4943 ;; For copysign (x, y), we want to generate:
4945 ;;   LDR d2, #(1 << 63)
4946 ;;   BSL v2.8b, [y], [x]
4948 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4949 ;; aarch64_simd_bsldf will select the best suited of these instructions
4950 ;; to generate based on register allocation, and knows how to partially
4951 ;; constant fold based on the values of X and Y, so expand through that.
4953 (define_expand "copysigndf3"
4954   [(match_operand:DF 0 "register_operand")
4955    (match_operand:DF 1 "register_operand")
4956    (match_operand:DF 2 "register_operand")]
4957   "TARGET_FLOAT && TARGET_SIMD"
4959   rtx mask = gen_reg_rtx (DImode);
4960   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4961   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4962                                      operands[2], operands[1]));
4963   DONE;
4967 ;; As above, but we must first get to a 64-bit value if we wish to use
4968 ;; aarch64_simd_bslv2sf.
4970 (define_expand "copysignsf3"
4971   [(match_operand:SF 0 "register_operand")
4972    (match_operand:SF 1 "register_operand")
4973    (match_operand:SF 2 "register_operand")]
4974   "TARGET_FLOAT && TARGET_SIMD"
4976   rtx mask = gen_reg_rtx (DImode);
4978   /* Juggle modes to get us in to a vector mode for BSL.  */
4979   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4980   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4981   rtx tmp = gen_reg_rtx (V2SFmode);
4982   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4983   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4984   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4985   DONE;
4989 ;; -------------------------------------------------------------------
4990 ;; Reload support
4991 ;; -------------------------------------------------------------------
4992 ;; Reload Scalar Floating point modes from constant pool.
4993 ;; The AArch64 port doesn't have __int128 constant move support.
4994 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4995  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4996        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4997   (clobber (match_operand:P 2 "register_operand" "=&r"))]
4998  "TARGET_FLOAT"
5000    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5001    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5002    DONE;
5006 ;; Reload Vector modes from constant pool.
5007 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5008  [(set (match_operand:VALL 0 "register_operand" "=w")
5009        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5010   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5011  "TARGET_FLOAT"
5013    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5014    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5015    DONE;
5019 (define_expand "aarch64_reload_mov<mode>"
5020   [(set (match_operand:TX 0 "register_operand" "=w")
5021         (match_operand:TX 1 "register_operand" "w"))
5022    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5023   ]
5024   "TARGET_FLOAT"
5025   {
5026     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5027     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5028     gen_aarch64_movtilow_tilow (op0, op1);
5029     gen_aarch64_movdi_tihigh (operands[2], op1);
5030     gen_aarch64_movtihigh_di (op0, operands[2]);
5031     DONE;
5032   }
5035 ;; The following secondary reload helpers patterns are invoked
5036 ;; after or during reload as we don't want these patterns to start
5037 ;; kicking in during the combiner.
5039 (define_insn "aarch64_movdi_<mode>low"
5040   [(set (match_operand:DI 0 "register_operand" "=r")
5041         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5042                          (const_int 64) (const_int 0)))]
5043   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5044   "fmov\\t%x0, %d1"
5045   [(set_attr "type" "f_mrc")
5046    (set_attr "length" "4")
5047   ])
5049 (define_insn "aarch64_movdi_<mode>high"
5050   [(set (match_operand:DI 0 "register_operand" "=r")
5051         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5052                          (const_int 64) (const_int 64)))]
5053   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5054   "fmov\\t%x0, %1.d[1]"
5055   [(set_attr "type" "f_mrc")
5056    (set_attr "length" "4")
5057   ])
5059 (define_insn "aarch64_mov<mode>high_di"
5060   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5061                          (const_int 64) (const_int 64))
5062         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5063   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5064   "fmov\\t%0.d[1], %x1"
5065   [(set_attr "type" "f_mcr")
5066    (set_attr "length" "4")
5067   ])
5069 (define_insn "aarch64_mov<mode>low_di"
5070   [(set (match_operand:TX 0 "register_operand" "=w")
5071         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5072   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5073   "fmov\\t%d0, %x1"
5074   [(set_attr "type" "f_mcr")
5075    (set_attr "length" "4")
5076   ])
5078 (define_insn "aarch64_movtilow_tilow"
5079   [(set (match_operand:TI 0 "register_operand" "=w")
5080         (zero_extend:TI
5081           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5082   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5083   "fmov\\t%d0, %d1"
5084   [(set_attr "type" "fmov")
5085    (set_attr "length" "4")
5086   ])
5088 ;; There is a deliberate reason why the parameters of high and lo_sum's
5089 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5090 ;; and lo_sum's to be used with the labels defining the jump tables in
5091 ;; rodata section.
5093 (define_expand "add_losym"
5094   [(set (match_operand 0 "register_operand" "=r")
5095         (lo_sum (match_operand 1 "register_operand" "r")
5096                 (match_operand 2 "aarch64_valid_symref" "S")))]
5097   ""
5099   machine_mode mode = GET_MODE (operands[0]);
5101   emit_insn ((mode == DImode
5102               ? gen_add_losym_di
5103               : gen_add_losym_si) (operands[0],
5104                                    operands[1],
5105                                    operands[2]));
5106   DONE;
5109 (define_insn "add_losym_<mode>"
5110   [(set (match_operand:P 0 "register_operand" "=r")
5111         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5112                   (match_operand 2 "aarch64_valid_symref" "S")))]
5113   ""
5114   "add\\t%<w>0, %<w>1, :lo12:%a2"
5115   [(set_attr "type" "alu_imm")]
5118 (define_insn "ldr_got_small_<mode>"
5119   [(set (match_operand:PTR 0 "register_operand" "=r")
5120         (unspec:PTR [(mem:PTR (lo_sum:PTR
5121                               (match_operand:PTR 1 "register_operand" "r")
5122                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5123                     UNSPEC_GOTSMALLPIC))]
5124   ""
5125   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5126   [(set_attr "type" "load1")]
5129 (define_insn "ldr_got_small_sidi"
5130   [(set (match_operand:DI 0 "register_operand" "=r")
5131         (zero_extend:DI
5132          (unspec:SI [(mem:SI (lo_sum:DI
5133                              (match_operand:DI 1 "register_operand" "r")
5134                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5135                     UNSPEC_GOTSMALLPIC)))]
5136   "TARGET_ILP32"
5137   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5138   [(set_attr "type" "load1")]
5141 (define_insn "ldr_got_small_28k_<mode>"
5142   [(set (match_operand:PTR 0 "register_operand" "=r")
5143         (unspec:PTR [(mem:PTR (lo_sum:PTR
5144                               (match_operand:PTR 1 "register_operand" "r")
5145                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5146                     UNSPEC_GOTSMALLPIC28K))]
5147   ""
5148   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5149   [(set_attr "type" "load1")]
5152 (define_insn "ldr_got_small_28k_sidi"
5153   [(set (match_operand:DI 0 "register_operand" "=r")
5154         (zero_extend:DI
5155          (unspec:SI [(mem:SI (lo_sum:DI
5156                              (match_operand:DI 1 "register_operand" "r")
5157                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5158                     UNSPEC_GOTSMALLPIC28K)))]
5159   "TARGET_ILP32"
5160   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5161   [(set_attr "type" "load1")]
5164 (define_insn "ldr_got_tiny"
5165   [(set (match_operand:DI 0 "register_operand" "=r")
5166         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5167                    UNSPEC_GOTTINYPIC))]
5168   ""
5169   "ldr\\t%0, %L1"
5170   [(set_attr "type" "load1")]
5173 (define_insn "aarch64_load_tp_hard"
5174   [(set (match_operand:DI 0 "register_operand" "=r")
5175         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5176   ""
5177   "mrs\\t%0, tpidr_el0"
5178   [(set_attr "type" "mrs")]
5181 ;; The TLS ABI specifically requires that the compiler does not schedule
5182 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5183 ;; Therefore we treat the stubs as an atomic sequence.
5184 (define_expand "tlsgd_small_<mode>"
5185  [(parallel [(set (match_operand 0 "register_operand" "")
5186                   (call (mem:DI (match_dup 2)) (const_int 1)))
5187              (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5188              (clobber (reg:DI LR_REGNUM))])]
5189  ""
5191   operands[2] = aarch64_tls_get_addr ();
5194 (define_insn "*tlsgd_small_<mode>"
5195   [(set (match_operand 0 "register_operand" "")
5196         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5197    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5198    (clobber (reg:DI LR_REGNUM))
5199   ]
5200   ""
5201   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5202   [(set_attr "type" "call")
5203    (set_attr "length" "16")])
5205 (define_insn "tlsie_small_<mode>"
5206   [(set (match_operand:PTR 0 "register_operand" "=r")
5207         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5208                    UNSPEC_GOTSMALLTLS))]
5209   ""
5210   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5211   [(set_attr "type" "load1")
5212    (set_attr "length" "8")]
5215 (define_insn "tlsie_small_sidi"
5216   [(set (match_operand:DI 0 "register_operand" "=r")
5217         (zero_extend:DI
5218           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5219                       UNSPEC_GOTSMALLTLS)))]
5220   ""
5221   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5222   [(set_attr "type" "load1")
5223    (set_attr "length" "8")]
5226 (define_insn "tlsie_tiny_<mode>"
5227   [(set (match_operand:PTR 0 "register_operand" "=&r")
5228         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5229                      (match_operand:PTR 2 "register_operand" "r")]
5230                    UNSPEC_GOTTINYTLS))]
5231   ""
5232   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5233   [(set_attr "type" "multiple")
5234    (set_attr "length" "8")]
5237 (define_insn "tlsie_tiny_sidi"
5238   [(set (match_operand:DI 0 "register_operand" "=&r")
5239         (zero_extend:DI
5240           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5241                       (match_operand:DI 2 "register_operand" "r")
5242                       ]
5243                       UNSPEC_GOTTINYTLS)))]
5244   ""
5245   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5246   [(set_attr "type" "multiple")
5247    (set_attr "length" "8")]
5250 (define_insn "tlsle12_<mode>"
5251   [(set (match_operand:P 0 "register_operand" "=r")
5252         (unspec:P [(match_operand:P 1 "register_operand" "r")
5253                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5254                    UNSPEC_TLSLE12))]
5255   ""
5256   "add\\t%<w>0, %<w>1, #%L2";
5257   [(set_attr "type" "alu_sreg")
5258    (set_attr "length" "4")]
5261 (define_insn "tlsle24_<mode>"
5262   [(set (match_operand:P 0 "register_operand" "=r")
5263         (unspec:P [(match_operand:P 1 "register_operand" "r")
5264                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5265                    UNSPEC_TLSLE24))]
5266   ""
5267   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5268   [(set_attr "type" "multiple")
5269    (set_attr "length" "8")]
5272 (define_insn "tlsle32_<mode>"
5273   [(set (match_operand:P 0 "register_operand" "=r")
5274         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5275                    UNSPEC_TLSLE32))]
5276   ""
5277   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5278   [(set_attr "type" "multiple")
5279    (set_attr "length" "8")]
5282 (define_insn "tlsle48_<mode>"
5283   [(set (match_operand:P 0 "register_operand" "=r")
5284         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5285                    UNSPEC_TLSLE48))]
5286   ""
5287   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5288   [(set_attr "type" "multiple")
5289    (set_attr "length" "12")]
5292 (define_insn "tlsdesc_small_<mode>"
5293   [(set (reg:PTR R0_REGNUM)
5294         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5295                    UNSPEC_TLSDESC))
5296    (clobber (reg:DI LR_REGNUM))
5297    (clobber (reg:CC CC_REGNUM))
5298    (clobber (match_scratch:DI 1 "=r"))]
5299   "TARGET_TLS_DESC"
5300   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5301   [(set_attr "type" "call")
5302    (set_attr "length" "16")])
5304 (define_insn "stack_tie"
5305   [(set (mem:BLK (scratch))
5306         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5307                      (match_operand:DI 1 "register_operand" "rk")]
5308                     UNSPEC_PRLG_STK))]
5309   ""
5310   ""
5311   [(set_attr "length" "0")]
5314 ;; Pointer authentication patterns are always provided.  In architecture
5315 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5316 ;; This lets the user write portable software which authenticates pointers
5317 ;; when run on something which implements ARMv8.3-A, and which runs
5318 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5319 ;; implemented.
5321 ;; Signing/Authenticating R30 using SP as the salt.
5323 (define_insn "<pauth_mnem_prefix>sp"
5324   [(set (reg:DI R30_REGNUM)
5325         (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5326   ""
5327   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5330 ;; Signing/Authenticating X17 using X16 as the salt.
5332 (define_insn "<pauth_mnem_prefix>1716"
5333   [(set (reg:DI R17_REGNUM)
5334         (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5335   ""
5336   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5339 ;; Stripping the signature in R30.
5341 (define_insn "xpaclri"
5342   [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5343   ""
5344   "hint\t7 // xpaclri"
5347 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5348 ;; all of memory.  This blocks insns from being moved across this point.
5350 (define_insn "blockage"
5351   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5352   ""
5353   ""
5354   [(set_attr "length" "0")
5355    (set_attr "type" "block")]
5358 (define_insn "probe_stack_range"
5359   [(set (match_operand:DI 0 "register_operand" "=r")
5360         (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5361                              (match_operand:DI 2 "register_operand" "r")]
5362                               UNSPECV_PROBE_STACK_RANGE))]
5363   ""
5365   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5367   [(set_attr "length" "32")]
5370 ;; Named pattern for expanding thread pointer reference.
5371 (define_expand "get_thread_pointerdi"
5372   [(match_operand:DI 0 "register_operand" "=r")]
5373   ""
5375   rtx tmp = aarch64_load_tp (operands[0]);
5376   if (tmp != operands[0])
5377     emit_move_insn (operands[0], tmp);
5378   DONE;
5381 ;; Named patterns for stack smashing protection.
5382 (define_expand "stack_protect_set"
5383   [(match_operand 0 "memory_operand")
5384    (match_operand 1 "memory_operand")]
5385   ""
5387   machine_mode mode = GET_MODE (operands[0]);
5389   emit_insn ((mode == DImode
5390               ? gen_stack_protect_set_di
5391               : gen_stack_protect_set_si) (operands[0], operands[1]));
5392   DONE;
5395 (define_insn "stack_protect_set_<mode>"
5396   [(set (match_operand:PTR 0 "memory_operand" "=m")
5397         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5398          UNSPEC_SP_SET))
5399    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5400   ""
5401   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5402   [(set_attr "length" "12")
5403    (set_attr "type" "multiple")])
5405 (define_expand "stack_protect_test"
5406   [(match_operand 0 "memory_operand")
5407    (match_operand 1 "memory_operand")
5408    (match_operand 2)]
5409   ""
5411   rtx result;
5412   machine_mode mode = GET_MODE (operands[0]);
5414   result = gen_reg_rtx(mode);
5416   emit_insn ((mode == DImode
5417               ? gen_stack_protect_test_di
5418               : gen_stack_protect_test_si) (result,
5419                                             operands[0],
5420                                             operands[1]));
5422   if (mode == DImode)
5423     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5424                                     result, const0_rtx, operands[2]));
5425   else
5426     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5427                                     result, const0_rtx, operands[2]));
5428   DONE;
5431 (define_insn "stack_protect_test_<mode>"
5432   [(set (match_operand:PTR 0 "register_operand" "=r")
5433         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5434                      (match_operand:PTR 2 "memory_operand" "m")]
5435          UNSPEC_SP_TEST))
5436    (clobber (match_scratch:PTR 3 "=&r"))]
5437   ""
5438   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5439   [(set_attr "length" "12")
5440    (set_attr "type" "multiple")])
5442 ;; Write Floating-point Control Register.
5443 (define_insn "set_fpcr"
5444   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5445   ""
5446   "msr\\tfpcr, %0"
5447   [(set_attr "type" "mrs")])
5449 ;; Read Floating-point Control Register.
5450 (define_insn "get_fpcr"
5451   [(set (match_operand:SI 0 "register_operand" "=r")
5452         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5453   ""
5454   "mrs\\t%0, fpcr"
5455   [(set_attr "type" "mrs")])
5457 ;; Write Floating-point Status Register.
5458 (define_insn "set_fpsr"
5459   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5460   ""
5461   "msr\\tfpsr, %0"
5462   [(set_attr "type" "mrs")])
5464 ;; Read Floating-point Status Register.
5465 (define_insn "get_fpsr"
5466   [(set (match_operand:SI 0 "register_operand" "=r")
5467         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5468   ""
5469   "mrs\\t%0, fpsr"
5470   [(set_attr "type" "mrs")])
5473 ;; Define the subtract-one-and-jump insns so loop.c
5474 ;; knows what to generate.
5475 (define_expand "doloop_end"
5476   [(use (match_operand 0 "" ""))      ; loop pseudo
5477    (use (match_operand 1 "" ""))]     ; label
5478   "optimize > 0 && flag_modulo_sched"
5480   rtx s0;
5481   rtx bcomp;
5482   rtx loc_ref;
5483   rtx cc_reg;
5484   rtx insn;
5485   rtx cmp;
5487   /* Currently SMS relies on the do-loop pattern to recognize loops
5488      where (1) the control part consists of all insns defining and/or
5489      using a certain 'count' register and (2) the loop count can be
5490      adjusted by modifying this register prior to the loop.
5491      ??? The possible introduction of a new block to initialize the
5492      new IV can potentially affect branch optimizations.  */
5494   if (GET_MODE (operands[0]) != DImode)
5495     FAIL;
5497   s0 = operands [0];
5498   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5500   cmp = XVECEXP (PATTERN (insn), 0, 0);
5501   cc_reg = SET_DEST (cmp);
5502   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5503   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5504   emit_jump_insn (gen_rtx_SET (pc_rtx,
5505                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5506                                                      loc_ref, pc_rtx)));
5507   DONE;
5510 ;; AdvSIMD Stuff
5511 (include "aarch64-simd.md")
5513 ;; Atomic Operations
5514 (include "atomics.md")
5516 ;; ldp/stp peephole patterns
5517 (include "aarch64-ldpstp.md")