2017-07-28 Tamar Christina <tamar.christina@arm.com>
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob33cbf1f7ac64da0ae23f786babe9e93ce0e2b35d
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 half
185 ;; precision fp registers.  When this is set to yes for an alternative,
186 ;; that alternative will be disabled when !TARGET_FP_F16INST.
187 (define_attr "fp16" "no,yes" (const_string "no"))
189 ;; Attribute that specifies whether or not the instruction touches simd
190 ;; registers.  When this is set to yes for an alternative, that alternative
191 ;; will be disabled when !TARGET_SIMD.
192 (define_attr "simd" "no,yes" (const_string "no"))
194 (define_attr "length" ""
195   (const_int 4))
197 ;; Attribute that controls whether an alternative is enabled or not.
198 ;; Currently it is only used to disable alternatives which touch fp or simd
199 ;; registers when -mgeneral-regs-only is specified.
200 (define_attr "enabled" "no,yes"
201   (cond [(ior
202             (ior
203                 (and (eq_attr "fp" "yes")
204                      (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
205                 (and (eq_attr "simd" "yes")
206                      (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
207             (and (eq_attr "fp16" "yes")
208                  (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0))))
209             (const_string "no")
210         ] (const_string "yes")))
212 ;; Attribute that specifies whether we are dealing with a branch to a
213 ;; label that is far away, i.e. further away than the maximum/minimum
214 ;; representable in a signed 21-bits number.
215 ;; 0 :=: no
216 ;; 1 :=: yes
217 (define_attr "far_branch" "" (const_int 0))
219 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
220 ;; no predicated insns.
221 (define_attr "predicated" "yes,no" (const_string "no"))
223 ;; -------------------------------------------------------------------
224 ;; Pipeline descriptions and scheduling
225 ;; -------------------------------------------------------------------
227 ;; Processor types.
228 (include "aarch64-tune.md")
230 ;; Scheduling
231 (include "../arm/cortex-a53.md")
232 (include "../arm/cortex-a57.md")
233 (include "../arm/exynos-m1.md")
234 (include "thunderx.md")
235 (include "../arm/xgene1.md")
236 (include "thunderx2t99.md")
238 ;; -------------------------------------------------------------------
239 ;; Jumps and other miscellaneous insns
240 ;; -------------------------------------------------------------------
242 (define_insn "indirect_jump"
243   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
244   ""
245   "br\\t%0"
246   [(set_attr "type" "branch")]
249 (define_insn "jump"
250   [(set (pc) (label_ref (match_operand 0 "" "")))]
251   ""
252   "b\\t%l0"
253   [(set_attr "type" "branch")]
256 (define_expand "cbranch<mode>4"
257   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
258                             [(match_operand:GPI 1 "register_operand" "")
259                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
260                            (label_ref (match_operand 3 "" ""))
261                            (pc)))]
262   ""
263   "
264   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
265                                          operands[2]);
266   operands[2] = const0_rtx;
267   "
270 (define_expand "cbranch<mode>4"
271   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
272                             [(match_operand:GPF 1 "register_operand" "")
273                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
274                            (label_ref (match_operand 3 "" ""))
275                            (pc)))]
276   ""
277   "
278   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
279                                          operands[2]);
280   operands[2] = const0_rtx;
281   "
284 (define_expand "cbranchcc4"
285   [(set (pc) (if_then_else
286               (match_operator 0 "aarch64_comparison_operator"
287                [(match_operand 1 "cc_register" "")
288                 (match_operand 2 "const0_operand")])
289               (label_ref (match_operand 3 "" ""))
290               (pc)))]
291   ""
292   "")
294 (define_insn "ccmp<mode>"
295   [(set (match_operand:CC 1 "cc_register" "")
296         (if_then_else:CC
297           (match_operator 4 "aarch64_comparison_operator"
298            [(match_operand 0 "cc_register" "")
299             (const_int 0)])
300           (compare:CC
301             (match_operand:GPI 2 "register_operand" "r,r,r")
302             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
303           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
304   ""
305   "@
306    ccmp\\t%<w>2, %<w>3, %k5, %m4
307    ccmp\\t%<w>2, %3, %k5, %m4
308    ccmn\\t%<w>2, #%n3, %k5, %m4"
309   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
312 (define_insn "fccmp<mode>"
313   [(set (match_operand:CCFP 1 "cc_register" "")
314         (if_then_else:CCFP
315           (match_operator 4 "aarch64_comparison_operator"
316            [(match_operand 0 "cc_register" "")
317             (const_int 0)])
318           (compare:CCFP
319             (match_operand:GPF 2 "register_operand" "w")
320             (match_operand:GPF 3 "register_operand" "w"))
321           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
322   "TARGET_FLOAT"
323   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
324   [(set_attr "type" "fccmp<s>")]
327 (define_insn "fccmpe<mode>"
328   [(set (match_operand:CCFPE 1 "cc_register" "")
329          (if_then_else:CCFPE
330           (match_operator 4 "aarch64_comparison_operator"
331            [(match_operand 0 "cc_register" "")
332           (const_int 0)])
333            (compare:CCFPE
334             (match_operand:GPF 2 "register_operand" "w")
335             (match_operand:GPF 3 "register_operand" "w"))
336           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
337   "TARGET_FLOAT"
338   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
339   [(set_attr "type" "fccmp<s>")]
342 ;; Expansion of signed mod by a power of 2 using CSNEG.
343 ;; For x0 % n where n is a power of 2 produce:
344 ;; negs   x1, x0
345 ;; and    x0, x0, #(n - 1)
346 ;; and    x1, x1, #(n - 1)
347 ;; csneg  x0, x0, x1, mi
349 (define_expand "mod<mode>3"
350   [(match_operand:GPI 0 "register_operand" "")
351    (match_operand:GPI 1 "register_operand" "")
352    (match_operand:GPI 2 "const_int_operand" "")]
353   ""
354   {
355     HOST_WIDE_INT val = INTVAL (operands[2]);
357     if (val <= 0
358        || exact_log2 (val) <= 0
359        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
360       FAIL;
362     rtx mask = GEN_INT (val - 1);
364     /* In the special case of x0 % 2 we can do the even shorter:
365         cmp    x0, xzr
366         and    x0, x0, 1
367         cneg   x0, x0, lt.  */
368     if (val == 2)
369       {
370         rtx masked = gen_reg_rtx (<MODE>mode);
371         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
372         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
373         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
374         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
375         DONE;
376       }
378     rtx neg_op = gen_reg_rtx (<MODE>mode);
379     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
381     /* Extract the condition register and mode.  */
382     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
383     rtx cc_reg = SET_DEST (cmp);
384     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
386     rtx masked_pos = gen_reg_rtx (<MODE>mode);
387     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
389     rtx masked_neg = gen_reg_rtx (<MODE>mode);
390     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
392     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
393                                        masked_neg, masked_pos));
394     DONE;
395   }
398 (define_insn "condjump"
399   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
400                             [(match_operand 1 "cc_register" "") (const_int 0)])
401                            (label_ref (match_operand 2 "" ""))
402                            (pc)))]
403   ""
404   {
405     if (get_attr_length (insn) == 8)
406       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
407     else
408       return  "b%m0\\t%l2";
409   }
410   [(set_attr "type" "branch")
411    (set (attr "length")
412         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
413                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
414                       (const_int 4)
415                       (const_int 8)))
416    (set (attr "far_branch")
417         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
418                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
419                       (const_int 0)
420                       (const_int 1)))]
423 ;; For a 24-bit immediate CST we can optimize the compare for equality
424 ;; and branch sequence from:
425 ;;      mov     x0, #imm1
426 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
427 ;;      cmp     x1, x0
428 ;;      b<ne,eq> .Label
429 ;; into the shorter:
430 ;;      sub     x0, x1, #(CST & 0xfff000)
431 ;;      subs    x0, x0, #(CST & 0x000fff)
432 ;;      b<ne,eq> .Label
433 (define_insn_and_split "*compare_condjump<mode>"
434   [(set (pc) (if_then_else (EQL
435                               (match_operand:GPI 0 "register_operand" "r")
436                               (match_operand:GPI 1 "aarch64_imm24" "n"))
437                            (label_ref:P (match_operand 2 "" ""))
438                            (pc)))]
439   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
440    && !aarch64_plus_operand (operands[1], <MODE>mode)
441    && !reload_completed"
442   "#"
443   "&& true"
444   [(const_int 0)]
445   {
446     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
447     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
448     rtx tmp = gen_reg_rtx (<MODE>mode);
449     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
450     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
451     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
452     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
453     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
454     DONE;
455   }
458 (define_expand "casesi"
459   [(match_operand:SI 0 "register_operand" "")   ; Index
460    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
461    (match_operand:SI 2 "const_int_operand" "")  ; Total range
462    (match_operand:DI 3 "" "")                   ; Table label
463    (match_operand:DI 4 "" "")]                  ; Out of range label
464   ""
465   {
466     if (operands[1] != const0_rtx)
467       {
468         rtx reg = gen_reg_rtx (SImode);
470         /* Canonical RTL says that if you have:
472            (minus (X) (CONST))
474            then this should be emitted as:
476            (plus (X) (-CONST))
478            The use of trunc_int_for_mode ensures that the resulting
479            constant can be represented in SImode, this is important
480            for the corner case where operand[1] is INT_MIN.  */
482         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
484         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
485               (operands[1], SImode))
486           operands[1] = force_reg (SImode, operands[1]);
487         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
488         operands[0] = reg;
489       }
491     if (!aarch64_plus_operand (operands[2], SImode))
492       operands[2] = force_reg (SImode, operands[2]);
493     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
494                                                  const0_rtx),
495                                     operands[0], operands[2], operands[4]));
497     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
498     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
499                                          operands[3]));
500     DONE;
501   }
504 (define_insn "casesi_dispatch"
505   [(parallel
506     [(set (pc)
507           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
508                            (match_operand:SI 1 "register_operand" "r")]
509                         UNSPEC_CASESI)))
510      (clobber (reg:CC CC_REGNUM))
511      (clobber (match_scratch:DI 3 "=r"))
512      (clobber (match_scratch:DI 4 "=r"))
513      (use (label_ref (match_operand 2 "" "")))])]
514   ""
515   "*
516   return aarch64_output_casesi (operands);
517   "
518   [(set_attr "length" "16")
519    (set_attr "type" "branch")]
522 (define_insn "nop"
523   [(unspec[(const_int 0)] UNSPEC_NOP)]
524   ""
525   "nop"
526   [(set_attr "type" "no_insn")]
529 (define_insn "prefetch"
530   [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
531             (match_operand:QI 1 "const_int_operand" "")
532             (match_operand:QI 2 "const_int_operand" ""))]
533   ""
534   {
535     const char * pftype[2][4] =
536     {
537       {"prfm\\tPLDL1STRM, %0",
538        "prfm\\tPLDL3KEEP, %0",
539        "prfm\\tPLDL2KEEP, %0",
540        "prfm\\tPLDL1KEEP, %0"},
541       {"prfm\\tPSTL1STRM, %0",
542        "prfm\\tPSTL3KEEP, %0",
543        "prfm\\tPSTL2KEEP, %0",
544        "prfm\\tPSTL1KEEP, %0"},
545     };
547     int locality = INTVAL (operands[2]);
549     gcc_assert (IN_RANGE (locality, 0, 3));
551     /* PRFM accepts the same addresses as a 64-bit LDR so wrap
552        the address into a DImode MEM so that aarch64_print_operand knows
553        how to print it.  */
554     operands[0] = gen_rtx_MEM (DImode, operands[0]);
555     return pftype[INTVAL(operands[1])][locality];
556   }
557   [(set_attr "type" "load1")]
560 (define_insn "trap"
561   [(trap_if (const_int 1) (const_int 8))]
562   ""
563   "brk #1000"
564   [(set_attr "type" "trap")])
566 (define_expand "prologue"
567   [(clobber (const_int 0))]
568   ""
569   "
570   aarch64_expand_prologue ();
571   DONE;
572   "
575 (define_expand "epilogue"
576   [(clobber (const_int 0))]
577   ""
578   "
579   aarch64_expand_epilogue (false);
580   DONE;
581   "
584 (define_expand "sibcall_epilogue"
585   [(clobber (const_int 0))]
586   ""
587   "
588   aarch64_expand_epilogue (true);
589   DONE;
590   "
593 (define_insn "*do_return"
594   [(return)]
595   ""
596   {
597     if (aarch64_return_address_signing_enabled ()
598         && TARGET_ARMV8_3
599         && !crtl->calls_eh_return)
600       return "retaa";
602     return "ret";
603   }
604   [(set_attr "type" "branch")]
607 (define_expand "return"
608   [(simple_return)]
609   "aarch64_use_return_insn_p ()"
610   ""
613 (define_insn "simple_return"
614   [(simple_return)]
615   ""
616   "ret"
617   [(set_attr "type" "branch")]
620 (define_insn "*cb<optab><mode>1"
621   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
622                                 (const_int 0))
623                            (label_ref (match_operand 1 "" ""))
624                            (pc)))]
625   ""
626   {
627     if (get_attr_length (insn) == 8)
628       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
629     else
630       return "<cbz>\\t%<w>0, %l1";
631   }
632   [(set_attr "type" "branch")
633    (set (attr "length")
634         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
635                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
636                       (const_int 4)
637                       (const_int 8)))
638    (set (attr "far_branch")
639         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
640                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
641                       (const_int 0)
642                       (const_int 1)))]
645 (define_insn "*tb<optab><mode>1"
646   [(set (pc) (if_then_else
647               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
648                                     (const_int 1)
649                                     (match_operand 1
650                                       "aarch64_simd_shift_imm_<mode>" "n"))
651                    (const_int 0))
652              (label_ref (match_operand 2 "" ""))
653              (pc)))
654    (clobber (reg:CC CC_REGNUM))]
655   ""
656   {
657     if (get_attr_length (insn) == 8)
658       {
659         if (get_attr_far_branch (insn) == 1)
660           return aarch64_gen_far_branch (operands, 2, "Ltb",
661                                          "<inv_tb>\\t%<w>0, %1, ");
662         else
663           {
664             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
665             return "tst\t%<w>0, %1\;<bcond>\t%l2";
666           }
667       }
668     else
669       return "<tbz>\t%<w>0, %1, %l2";
670   }
671   [(set_attr "type" "branch")
672    (set (attr "length")
673         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
674                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
675                       (const_int 4)
676                       (const_int 8)))
677    (set (attr "far_branch")
678         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
679                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
680                       (const_int 0)
681                       (const_int 1)))]
685 (define_insn "*cb<optab><mode>1"
686   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
687                                  (const_int 0))
688                            (label_ref (match_operand 1 "" ""))
689                            (pc)))
690    (clobber (reg:CC CC_REGNUM))]
691   ""
692   {
693     if (get_attr_length (insn) == 8)
694       {
695         if (get_attr_far_branch (insn) == 1)
696           return aarch64_gen_far_branch (operands, 1, "Ltb",
697                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
698         else
699           {
700             char buf[64];
701             uint64_t val = ((uint64_t) 1)
702                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
703             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
704             output_asm_insn (buf, operands);
705             return "<bcond>\t%l1";
706           }
707       }
708     else
709       return "<tbz>\t%<w>0, <sizem1>, %l1";
710   }
711   [(set_attr "type" "branch")
712    (set (attr "length")
713         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
714                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
715                       (const_int 4)
716                       (const_int 8)))
717    (set (attr "far_branch")
718         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
719                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
720                       (const_int 0)
721                       (const_int 1)))]
724 ;; -------------------------------------------------------------------
725 ;; Subroutine calls and sibcalls
726 ;; -------------------------------------------------------------------
728 (define_expand "call"
729   [(parallel [(call (match_operand 0 "memory_operand" "")
730                     (match_operand 1 "general_operand" ""))
731               (use (match_operand 2 "" ""))
732               (clobber (reg:DI LR_REGNUM))])]
733   ""
734   "
735   {
736     aarch64_expand_call (NULL_RTX, operands[0], false);
737     DONE;
738   }"
741 (define_insn "*call_insn"
742   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
743          (match_operand 1 "" ""))
744    (clobber (reg:DI LR_REGNUM))]
745   ""
746   "@
747   blr\\t%0
748   bl\\t%a0"
749   [(set_attr "type" "call, call")]
752 (define_expand "call_value"
753   [(parallel [(set (match_operand 0 "" "")
754                    (call (match_operand 1 "memory_operand" "")
755                          (match_operand 2 "general_operand" "")))
756               (use (match_operand 3 "" ""))
757               (clobber (reg:DI LR_REGNUM))])]
758   ""
759   "
760   {
761     aarch64_expand_call (operands[0], operands[1], false);
762     DONE;
763   }"
766 (define_insn "*call_value_insn"
767   [(set (match_operand 0 "" "")
768         (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
769                       (match_operand 2 "" "")))
770    (clobber (reg:DI LR_REGNUM))]
771   ""
772   "@
773   blr\\t%1
774   bl\\t%a1"
775   [(set_attr "type" "call, call")]
778 (define_expand "sibcall"
779   [(parallel [(call (match_operand 0 "memory_operand" "")
780                     (match_operand 1 "general_operand" ""))
781               (return)
782               (use (match_operand 2 "" ""))])]
783   ""
784   {
785     aarch64_expand_call (NULL_RTX, operands[0], true);
786     DONE;
787   }
790 (define_expand "sibcall_value"
791   [(parallel [(set (match_operand 0 "" "")
792                    (call (match_operand 1 "memory_operand" "")
793                          (match_operand 2 "general_operand" "")))
794               (return)
795               (use (match_operand 3 "" ""))])]
796   ""
797   {
798     aarch64_expand_call (operands[0], operands[1], true);
799     DONE;
800   }
803 (define_insn "*sibcall_insn"
804   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
805          (match_operand 1 "" ""))
806    (return)]
807   "SIBLING_CALL_P (insn)"
808   "@
809    br\\t%0
810    b\\t%a0"
811   [(set_attr "type" "branch, branch")]
814 (define_insn "*sibcall_value_insn"
815   [(set (match_operand 0 "" "")
816         (call (mem:DI
817                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
818               (match_operand 2 "" "")))
819    (return)]
820   "SIBLING_CALL_P (insn)"
821   "@
822    br\\t%1
823    b\\t%a1"
824   [(set_attr "type" "branch, branch")]
827 ;; Call subroutine returning any type.
829 (define_expand "untyped_call"
830   [(parallel [(call (match_operand 0 "")
831                     (const_int 0))
832               (match_operand 1 "")
833               (match_operand 2 "")])]
834   ""
836   int i;
838   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
840   for (i = 0; i < XVECLEN (operands[2], 0); i++)
841     {
842       rtx set = XVECEXP (operands[2], 0, i);
843       emit_move_insn (SET_DEST (set), SET_SRC (set));
844     }
846   /* The optimizer does not know that the call sets the function value
847      registers we stored in the result block.  We avoid problems by
848      claiming that all hard registers are used and clobbered at this
849      point.  */
850   emit_insn (gen_blockage ());
851   DONE;
854 ;; -------------------------------------------------------------------
855 ;; Moves
856 ;; -------------------------------------------------------------------
858 (define_expand "mov<mode>"
859   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
860         (match_operand:SHORT 1 "general_operand" ""))]
861   ""
862   "
863     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
864       operands[1] = force_reg (<MODE>mode, operands[1]);
865   "
868 (define_insn "*mov<mode>_aarch64"
869   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
870         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
871   "(register_operand (operands[0], <MODE>mode)
872     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
874    switch (which_alternative)
875      {
876      case 0:
877        return "mov\t%w0, %w1";
878      case 1:
879        return "mov\t%w0, %1";
880      case 2:
881        return aarch64_output_scalar_simd_mov_immediate (operands[1],
882                                                         <MODE>mode);
883      case 3:
884        return "ldr<size>\t%w0, %1";
885      case 4:
886        return "ldr\t%<size>0, %1";
887      case 5:
888        return "str<size>\t%w1, %0";
889      case 6:
890        return "str\t%<size>1, %0";
891      case 7:
892        return "umov\t%w0, %1.<v>[0]";
893      case 8:
894        return "dup\t%0.<Vallxd>, %w1";
895      case 9:
896        return "dup\t%<Vetype>0, %1.<v>[0]";
897      default:
898        gcc_unreachable ();
899      }
901   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
902                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
903    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
906 (define_expand "mov<mode>"
907   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
908         (match_operand:GPI 1 "general_operand" ""))]
909   ""
910   "
911     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
912         && <MODE>mode == DImode
913         && aarch64_split_dimode_const_store (operands[0], operands[1]))
914       DONE;
916     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
917       operands[1] = force_reg (<MODE>mode, operands[1]);
919     /* FIXME: RR we still need to fix up what we are doing with
920        symbol_refs and other types of constants.  */
921     if (CONSTANT_P (operands[1])
922         && !CONST_INT_P (operands[1]))
923      {
924        aarch64_expand_mov_immediate (operands[0], operands[1]);
925        DONE;
926      }
927   "
930 (define_insn_and_split "*movsi_aarch64"
931   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w,w")
932         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Ds"))]
933   "(register_operand (operands[0], SImode)
934     || aarch64_reg_or_zero (operands[1], SImode))"
935   "@
936    mov\\t%w0, %w1
937    mov\\t%w0, %w1
938    mov\\t%w0, %w1
939    mov\\t%w0, %1
940    #
941    ldr\\t%w0, %1
942    ldr\\t%s0, %1
943    str\\t%w1, %0
944    str\\t%s1, %0
945    adr\\t%x0, %a1
946    adrp\\t%x0, %A1
947    fmov\\t%s0, %w1
948    fmov\\t%w0, %s1
949    fmov\\t%s0, %s1
950    * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
951   "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
952     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
953    [(const_int 0)]
954    "{
955        aarch64_expand_mov_immediate (operands[0], operands[1]);
956        DONE;
957     }"
958   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
959                     adr,adr,f_mcr,f_mrc,fmov,neon_move")
960    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
961    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
964 (define_insn_and_split "*movdi_aarch64"
965   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w,r,*w,w")
966         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
967   "(register_operand (operands[0], DImode)
968     || aarch64_reg_or_zero (operands[1], DImode))"
969   "@
970    mov\\t%x0, %x1
971    mov\\t%0, %x1
972    mov\\t%x0, %1
973    mov\\t%x0, %1
974    #
975    ldr\\t%x0, %1
976    ldr\\t%d0, %1
977    str\\t%x1, %0
978    str\\t%d1, %0
979    adr\\t%x0, %a1
980    adrp\\t%x0, %A1
981    fmov\\t%d0, %x1
982    fmov\\t%x0, %d1
983    fmov\\t%d0, %d1
984    * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
985    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
986     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
987    [(const_int 0)]
988    "{
989        aarch64_expand_mov_immediate (operands[0], operands[1]);
990        DONE;
991     }"
992   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
993                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
994    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
995    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
998 (define_insn "insv_imm<mode>"
999   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1000                           (const_int 16)
1001                           (match_operand:GPI 1 "const_int_operand" "n"))
1002         (match_operand:GPI 2 "const_int_operand" "n"))]
1003   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1004    && UINTVAL (operands[1]) % 16 == 0"
1005   "movk\\t%<w>0, %X2, lsl %1"
1006   [(set_attr "type" "mov_imm")]
1009 (define_expand "movti"
1010   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1011         (match_operand:TI 1 "general_operand" ""))]
1012   ""
1013   "
1014     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1015       operands[1] = force_reg (TImode, operands[1]);
1016   "
1019 (define_insn "*movti_aarch64"
1020   [(set (match_operand:TI 0
1021          "nonimmediate_operand"  "=r, *w,r ,*w,r,m,m,*w,m")
1022         (match_operand:TI 1
1023          "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1024   "(register_operand (operands[0], TImode)
1025     || aarch64_reg_or_zero (operands[1], TImode))"
1026   "@
1027    #
1028    #
1029    #
1030    mov\\t%0.16b, %1.16b
1031    ldp\\t%0, %H0, %1
1032    stp\\t%1, %H1, %0
1033    stp\\txzr, xzr, %0
1034    ldr\\t%q0, %1
1035    str\\t%q1, %0"
1036   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1037                              load2,store2,store2,f_loadd,f_stored")
1038    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1039    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1040    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1043 ;; Split a TImode register-register or register-immediate move into
1044 ;; its component DImode pieces, taking care to handle overlapping
1045 ;; source and dest registers.
1046 (define_split
1047    [(set (match_operand:TI 0 "register_operand" "")
1048          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1049   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1050   [(const_int 0)]
1052   aarch64_split_128bit_move (operands[0], operands[1]);
1053   DONE;
1056 (define_expand "mov<mode>"
1057   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1058         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1059   ""
1060   {
1061     if (!TARGET_FLOAT)
1062       {
1063         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1064         FAIL;
1065       }
1067     if (GET_CODE (operands[0]) == MEM
1068         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1069               && aarch64_float_const_zero_rtx_p (operands[1])))
1070       operands[1] = force_reg (<MODE>mode, operands[1]);
1071   }
1074 (define_insn "*movhf_aarch64"
1075   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r")
1076         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1077   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1078     || aarch64_reg_or_fp_float (operands[1], HFmode))"
1079   "@
1080    movi\\t%0.4h, #0
1081    fmov\\t%h0, %w1
1082    umov\\t%w0, %1.h[0]
1083    mov\\t%0.h[0], %1.h[0]
1084    fmov\\t%h0, %1
1085    * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1086    ldr\\t%h0, %1
1087    str\\t%h1, %0
1088    ldrh\\t%w0, %1
1089    strh\\t%w1, %0
1090    mov\\t%w0, %w1"
1091   [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
1092                      neon_move,f_loads,f_stores,load1,store1,mov_reg")
1093    (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
1094    (set_attr "fp16"   "*,yes,*,*,yes,*,*,*,*,*,*")]
1097 (define_insn "*movsf_aarch64"
1098   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
1099         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1100   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1101     || aarch64_reg_or_fp_float (operands[1], SFmode))"
1102   "@
1103    movi\\t%0.2s, #0
1104    fmov\\t%s0, %w1
1105    fmov\\t%w0, %s1
1106    fmov\\t%s0, %s1
1107    fmov\\t%s0, %1
1108    * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1109    ldr\\t%s0, %1
1110    str\\t%s1, %0
1111    ldr\\t%w0, %1
1112    str\\t%w1, %0
1113    mov\\t%w0, %w1
1114    mov\\t%w0, %1"
1115   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1116                      f_loads,f_stores,load1,store1,mov_reg,\
1117                      fconsts")
1118    (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1121 (define_insn "*movdf_aarch64"
1122   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
1123         (match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1124   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1125     || aarch64_reg_or_fp_float (operands[1], DFmode))"
1126   "@
1127    movi\\t%d0, #0
1128    fmov\\t%d0, %x1
1129    fmov\\t%x0, %d1
1130    fmov\\t%d0, %d1
1131    fmov\\t%d0, %1
1132    * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1133    ldr\\t%d0, %1
1134    str\\t%d1, %0
1135    ldr\\t%x0, %1
1136    str\\t%x1, %0
1137    mov\\t%x0, %x1
1138    mov\\t%x0, %1"
1139   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1140                      f_loadd,f_stored,load1,store1,mov_reg,\
1141                      fconstd")
1142    (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1145 (define_split
1146   [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1147         (match_operand:GPF_HF 1 "general_operand"))]
1148   "can_create_pseudo_p ()
1149    && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1150    && !aarch64_float_const_representable_p (operands[1])
1151    &&  aarch64_float_const_rtx_p (operands[1])"
1152   [(const_int 0)]
1153   {
1154     unsigned HOST_WIDE_INT ival;
1155     if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1156       FAIL;
1158     rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1159     emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1160     emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1161     DONE;
1162   }
1165 (define_insn "*movtf_aarch64"
1166   [(set (match_operand:TF 0
1167          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1168         (match_operand:TF 1
1169          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1170   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1171     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1172   "@
1173    mov\\t%0.16b, %1.16b
1174    #
1175    #
1176    #
1177    movi\\t%0.2d, #0
1178    fmov\\t%s0, wzr
1179    ldr\\t%q0, %1
1180    str\\t%q1, %0
1181    ldp\\t%0, %H0, %1
1182    stp\\t%1, %H1, %0
1183    stp\\txzr, xzr, %0"
1184   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1185                      f_loadd,f_stored,load2,store2,store2")
1186    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1187    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1190 (define_split
1191    [(set (match_operand:TF 0 "register_operand" "")
1192          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1193   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1194   [(const_int 0)]
1195   {
1196     aarch64_split_128bit_move (operands[0], operands[1]);
1197     DONE;
1198   }
1201 ;; 0 is dst
1202 ;; 1 is src
1203 ;; 2 is size of move in bytes
1204 ;; 3 is alignment
1206 (define_expand "movmemdi"
1207   [(match_operand:BLK 0 "memory_operand")
1208    (match_operand:BLK 1 "memory_operand")
1209    (match_operand:DI 2 "immediate_operand")
1210    (match_operand:DI 3 "immediate_operand")]
1211    "!STRICT_ALIGNMENT"
1213   if (aarch64_expand_movmem (operands))
1214     DONE;
1215   FAIL;
1219 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1220 ;; fairly lax checking on the second memory operation.
1221 (define_insn "load_pairsi"
1222   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1223         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1224    (set (match_operand:SI 2 "register_operand" "=r,*w")
1225         (match_operand:SI 3 "memory_operand" "m,m"))]
1226   "rtx_equal_p (XEXP (operands[3], 0),
1227                 plus_constant (Pmode,
1228                                XEXP (operands[1], 0),
1229                                GET_MODE_SIZE (SImode)))"
1230   "@
1231    ldp\\t%w0, %w2, %1
1232    ldp\\t%s0, %s2, %1"
1233   [(set_attr "type" "load2,neon_load1_2reg")
1234    (set_attr "fp" "*,yes")]
1237 (define_insn "load_pairdi"
1238   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1239         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1240    (set (match_operand:DI 2 "register_operand" "=r,*w")
1241         (match_operand:DI 3 "memory_operand" "m,m"))]
1242   "rtx_equal_p (XEXP (operands[3], 0),
1243                 plus_constant (Pmode,
1244                                XEXP (operands[1], 0),
1245                                GET_MODE_SIZE (DImode)))"
1246   "@
1247    ldp\\t%x0, %x2, %1
1248    ldp\\t%d0, %d2, %1"
1249   [(set_attr "type" "load2,neon_load1_2reg")
1250    (set_attr "fp" "*,yes")]
1254 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1255 ;; fairly lax checking on the second memory operation.
1256 (define_insn "store_pairsi"
1257   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1258         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1259    (set (match_operand:SI 2 "memory_operand" "=m,m")
1260         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1261   "rtx_equal_p (XEXP (operands[2], 0),
1262                 plus_constant (Pmode,
1263                                XEXP (operands[0], 0),
1264                                GET_MODE_SIZE (SImode)))"
1265   "@
1266    stp\\t%w1, %w3, %0
1267    stp\\t%s1, %s3, %0"
1268   [(set_attr "type" "store2,neon_store1_2reg")
1269    (set_attr "fp" "*,yes")]
1272 (define_insn "store_pairdi"
1273   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1274         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1275    (set (match_operand:DI 2 "memory_operand" "=m,m")
1276         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1277   "rtx_equal_p (XEXP (operands[2], 0),
1278                 plus_constant (Pmode,
1279                                XEXP (operands[0], 0),
1280                                GET_MODE_SIZE (DImode)))"
1281   "@
1282    stp\\t%x1, %x3, %0
1283    stp\\t%d1, %d3, %0"
1284   [(set_attr "type" "store2,neon_store1_2reg")
1285    (set_attr "fp" "*,yes")]
1288 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1289 ;; fairly lax checking on the second memory operation.
1290 (define_insn "load_pairsf"
1291   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1292         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1293    (set (match_operand:SF 2 "register_operand" "=w,*r")
1294         (match_operand:SF 3 "memory_operand" "m,m"))]
1295   "rtx_equal_p (XEXP (operands[3], 0),
1296                 plus_constant (Pmode,
1297                                XEXP (operands[1], 0),
1298                                GET_MODE_SIZE (SFmode)))"
1299   "@
1300    ldp\\t%s0, %s2, %1
1301    ldp\\t%w0, %w2, %1"
1302   [(set_attr "type" "neon_load1_2reg,load2")
1303    (set_attr "fp" "yes,*")]
1306 (define_insn "load_pairdf"
1307   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1308         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1309    (set (match_operand:DF 2 "register_operand" "=w,*r")
1310         (match_operand:DF 3 "memory_operand" "m,m"))]
1311   "rtx_equal_p (XEXP (operands[3], 0),
1312                 plus_constant (Pmode,
1313                                XEXP (operands[1], 0),
1314                                GET_MODE_SIZE (DFmode)))"
1315   "@
1316    ldp\\t%d0, %d2, %1
1317    ldp\\t%x0, %x2, %1"
1318   [(set_attr "type" "neon_load1_2reg,load2")
1319    (set_attr "fp" "yes,*")]
1322 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1323 ;; fairly lax checking on the second memory operation.
1324 (define_insn "store_pairsf"
1325   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1326         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1327    (set (match_operand:SF 2 "memory_operand" "=m,m")
1328         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1329   "rtx_equal_p (XEXP (operands[2], 0),
1330                 plus_constant (Pmode,
1331                                XEXP (operands[0], 0),
1332                                GET_MODE_SIZE (SFmode)))"
1333   "@
1334    stp\\t%s1, %s3, %0
1335    stp\\t%w1, %w3, %0"
1336   [(set_attr "type" "neon_store1_2reg,store2")
1337    (set_attr "fp" "yes,*")]
1340 (define_insn "store_pairdf"
1341   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1342         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1343    (set (match_operand:DF 2 "memory_operand" "=m,m")
1344         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1345   "rtx_equal_p (XEXP (operands[2], 0),
1346                 plus_constant (Pmode,
1347                                XEXP (operands[0], 0),
1348                                GET_MODE_SIZE (DFmode)))"
1349   "@
1350    stp\\t%d1, %d3, %0
1351    stp\\t%x1, %x3, %0"
1352   [(set_attr "type" "neon_store1_2reg,store2")
1353    (set_attr "fp" "yes,*")]
1356 ;; Load pair with post-index writeback.  This is primarily used in function
1357 ;; epilogues.
1358 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1359   [(parallel
1360     [(set (match_operand:P 0 "register_operand" "=k")
1361           (plus:P (match_operand:P 1 "register_operand" "0")
1362                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1363      (set (match_operand:GPI 2 "register_operand" "=r")
1364           (mem:GPI (match_dup 1)))
1365      (set (match_operand:GPI 3 "register_operand" "=r")
1366           (mem:GPI (plus:P (match_dup 1)
1367                    (match_operand:P 5 "const_int_operand" "n"))))])]
1368   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1369   "ldp\\t%<w>2, %<w>3, [%1], %4"
1370   [(set_attr "type" "load2")]
1373 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1374   [(parallel
1375     [(set (match_operand:P 0 "register_operand" "=k")
1376           (plus:P (match_operand:P 1 "register_operand" "0")
1377                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1378      (set (match_operand:GPF 2 "register_operand" "=w")
1379           (mem:GPF (match_dup 1)))
1380      (set (match_operand:GPF 3 "register_operand" "=w")
1381           (mem:GPF (plus:P (match_dup 1)
1382                    (match_operand:P 5 "const_int_operand" "n"))))])]
1383   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1384   "ldp\\t%<w>2, %<w>3, [%1], %4"
1385   [(set_attr "type" "neon_load1_2reg")]
1388 ;; Store pair with pre-index writeback.  This is primarily used in function
1389 ;; prologues.
1390 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1391   [(parallel
1392     [(set (match_operand:P 0 "register_operand" "=&k")
1393           (plus:P (match_operand:P 1 "register_operand" "0")
1394                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1395      (set (mem:GPI (plus:P (match_dup 0)
1396                    (match_dup 4)))
1397           (match_operand:GPI 2 "register_operand" "r"))
1398      (set (mem:GPI (plus:P (match_dup 0)
1399                    (match_operand:P 5 "const_int_operand" "n")))
1400           (match_operand:GPI 3 "register_operand" "r"))])]
1401   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1402   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1403   [(set_attr "type" "store2")]
1406 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1407   [(parallel
1408     [(set (match_operand:P 0 "register_operand" "=&k")
1409           (plus:P (match_operand:P 1 "register_operand" "0")
1410                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1411      (set (mem:GPF (plus:P (match_dup 0)
1412                    (match_dup 4)))
1413           (match_operand:GPF 2 "register_operand" "w"))
1414      (set (mem:GPF (plus:P (match_dup 0)
1415                    (match_operand:P 5 "const_int_operand" "n")))
1416           (match_operand:GPF 3 "register_operand" "w"))])]
1417   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1418   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1419   [(set_attr "type" "neon_store1_2reg<q>")]
1422 ;; -------------------------------------------------------------------
1423 ;; Sign/Zero extension
1424 ;; -------------------------------------------------------------------
1426 (define_expand "<optab>sidi2"
1427   [(set (match_operand:DI 0 "register_operand")
1428         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1429   ""
1432 (define_insn "*extendsidi2_aarch64"
1433   [(set (match_operand:DI 0 "register_operand" "=r,r")
1434         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1435   ""
1436   "@
1437    sxtw\t%0, %w1
1438    ldrsw\t%0, %1"
1439   [(set_attr "type" "extend,load1")]
1442 (define_insn "*load_pair_extendsidi2_aarch64"
1443   [(set (match_operand:DI 0 "register_operand" "=r")
1444         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1445    (set (match_operand:DI 2 "register_operand" "=r")
1446         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1447   "rtx_equal_p (XEXP (operands[3], 0),
1448                 plus_constant (Pmode,
1449                                XEXP (operands[1], 0),
1450                                GET_MODE_SIZE (SImode)))"
1451   "ldpsw\\t%0, %2, %1"
1452   [(set_attr "type" "load2")]
1455 (define_insn "*zero_extendsidi2_aarch64"
1456   [(set (match_operand:DI 0 "register_operand" "=r,r")
1457         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1458   ""
1459   "@
1460    uxtw\t%0, %w1
1461    ldr\t%w0, %1"
1462   [(set_attr "type" "extend,load1")]
1465 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1466   [(set (match_operand:DI 0 "register_operand" "=r")
1467         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1468    (set (match_operand:DI 2 "register_operand" "=r")
1469         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1470   "rtx_equal_p (XEXP (operands[3], 0),
1471                 plus_constant (Pmode,
1472                                XEXP (operands[1], 0),
1473                                GET_MODE_SIZE (SImode)))"
1474   "ldp\\t%w0, %w2, %1"
1475   [(set_attr "type" "load2")]
1478 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1479   [(set (match_operand:GPI 0 "register_operand")
1480         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1481   ""
1484 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1485   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1486         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1487   ""
1488   "@
1489    sxt<SHORT:size>\t%<GPI:w>0, %w1
1490    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1491   [(set_attr "type" "extend,load1")]
1494 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1495   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1496         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1497   ""
1498   "@
1499    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1500    ldr<SHORT:size>\t%w0, %1
1501    ldr\t%<SHORT:size>0, %1"
1502   [(set_attr "type" "logic_imm,load1,load1")]
1505 (define_expand "<optab>qihi2"
1506   [(set (match_operand:HI 0 "register_operand")
1507         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1508   ""
1511 (define_insn "*extendqihi2_aarch64"
1512   [(set (match_operand:HI 0 "register_operand" "=r,r")
1513         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1514   ""
1515   "@
1516    sxtb\t%w0, %w1
1517    ldrsb\t%w0, %1"
1518   [(set_attr "type" "extend,load1")]
1521 (define_insn "*zero_extendqihi2_aarch64"
1522   [(set (match_operand:HI 0 "register_operand" "=r,r")
1523         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1524   ""
1525   "@
1526    and\t%w0, %w1, 255
1527    ldrb\t%w0, %1"
1528   [(set_attr "type" "logic_imm,load1")]
1531 ;; -------------------------------------------------------------------
1532 ;; Simple arithmetic
1533 ;; -------------------------------------------------------------------
1535 (define_expand "add<mode>3"
1536   [(set
1537     (match_operand:GPI 0 "register_operand" "")
1538     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1539               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1540   ""
1542   /* If operands[1] is a subreg extract the inner RTX.  */
1543   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1545   /* If the constant is too large for a single instruction and isn't frame
1546      based, split off the immediate so it is available for CSE.  */
1547   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1548       && can_create_pseudo_p ()
1549       && (!REG_P (op1)
1550          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1551     operands[2] = force_reg (<MODE>mode, operands[2]);
1554 (define_insn "*add<mode>3_aarch64"
1555   [(set
1556     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1557     (plus:GPI
1558      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1559      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1560   ""
1561   "@
1562   add\\t%<w>0, %<w>1, %2
1563   add\\t%<w>0, %<w>1, %<w>2
1564   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1565   sub\\t%<w>0, %<w>1, #%n2
1566   #"
1567   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1568    (set_attr "simd" "*,*,yes,*,*")]
1571 ;; zero_extend version of above
1572 (define_insn "*addsi3_aarch64_uxtw"
1573   [(set
1574     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1575     (zero_extend:DI
1576      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1577               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1578   ""
1579   "@
1580   add\\t%w0, %w1, %2
1581   add\\t%w0, %w1, %w2
1582   sub\\t%w0, %w1, #%n2
1583   #"
1584   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1587 ;; If there's a free register, and we can load the constant with a
1588 ;; single instruction, do so.  This has a chance to improve scheduling.
1589 (define_peephole2
1590   [(match_scratch:GPI 3 "r")
1591    (set (match_operand:GPI 0 "register_operand")
1592         (plus:GPI
1593           (match_operand:GPI 1 "register_operand")
1594           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1595   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1596   [(set (match_dup 3) (match_dup 2))
1597    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1600 (define_peephole2
1601   [(match_scratch:SI 3 "r")
1602    (set (match_operand:DI 0 "register_operand")
1603         (zero_extend:DI
1604           (plus:SI
1605             (match_operand:SI 1 "register_operand")
1606             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1607   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1608   [(set (match_dup 3) (match_dup 2))
1609    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1612 ;; After peephole2 has had a chance to run, split any remaining long
1613 ;; additions into two add immediates.
1614 (define_split
1615   [(set (match_operand:GPI 0 "register_operand")
1616         (plus:GPI
1617           (match_operand:GPI 1 "register_operand")
1618           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1619   "epilogue_completed"
1620   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1621    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1622   {
1623     HOST_WIDE_INT i = INTVAL (operands[2]);
1624     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1625     operands[3] = GEN_INT (i - s);
1626     operands[4] = GEN_INT (s);
1627   }
1630 (define_split
1631   [(set (match_operand:DI 0 "register_operand")
1632         (zero_extend:DI
1633           (plus:SI
1634             (match_operand:SI 1 "register_operand")
1635             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1636   "epilogue_completed"
1637   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1638    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1639   {
1640     HOST_WIDE_INT i = INTVAL (operands[2]);
1641     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1642     operands[3] = GEN_INT (i - s);
1643     operands[4] = GEN_INT (s);
1644     operands[5] = gen_lowpart (SImode, operands[0]);
1645   }
1648 (define_expand "addti3"
1649   [(set (match_operand:TI 0 "register_operand" "")
1650         (plus:TI (match_operand:TI 1 "register_operand" "")
1651                  (match_operand:TI 2 "register_operand" "")))]
1652   ""
1654   rtx low = gen_reg_rtx (DImode);
1655   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1656                                   gen_lowpart (DImode, operands[2])));
1658   rtx high = gen_reg_rtx (DImode);
1659   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1660                                  gen_highpart (DImode, operands[2])));
1662   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1663   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1664   DONE;
1667 (define_insn "add<mode>3_compare0"
1668   [(set (reg:CC_NZ CC_REGNUM)
1669         (compare:CC_NZ
1670          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1671                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1672          (const_int 0)))
1673    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1674         (plus:GPI (match_dup 1) (match_dup 2)))]
1675   ""
1676   "@
1677   adds\\t%<w>0, %<w>1, %<w>2
1678   adds\\t%<w>0, %<w>1, %2
1679   subs\\t%<w>0, %<w>1, #%n2"
1680   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1683 ;; zero_extend version of above
1684 (define_insn "*addsi3_compare0_uxtw"
1685   [(set (reg:CC_NZ CC_REGNUM)
1686         (compare:CC_NZ
1687          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1688                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1689          (const_int 0)))
1690    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1691         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1692   ""
1693   "@
1694   adds\\t%w0, %w1, %w2
1695   adds\\t%w0, %w1, %2
1696   subs\\t%w0, %w1, #%n2"
1697   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1700 (define_insn "*add<mode>3_compareC_cconly_imm"
1701   [(set (reg:CC_C CC_REGNUM)
1702         (ne:CC_C
1703           (plus:<DWI>
1704             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1705             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1706           (zero_extend:<DWI>
1707             (plus:GPI
1708               (match_dup 0)
1709               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1710   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1711                                  <MODE>mode, operands[1])"
1712   "@
1713   cmn\\t%<w>0, %1
1714   cmp\\t%<w>0, #%n1"
1715   [(set_attr "type" "alus_imm")]
1718 (define_insn "*add<mode>3_compareC_cconly"
1719   [(set (reg:CC_C CC_REGNUM)
1720         (ne:CC_C
1721           (plus:<DWI>
1722             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1723             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1724           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1725   ""
1726   "cmn\\t%<w>0, %<w>1"
1727   [(set_attr "type" "alus_sreg")]
1730 (define_insn "*add<mode>3_compareC_imm"
1731   [(set (reg:CC_C CC_REGNUM)
1732         (ne:CC_C
1733           (plus:<DWI>
1734             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1735             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1736           (zero_extend:<DWI>
1737             (plus:GPI
1738               (match_dup 1)
1739               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1740    (set (match_operand:GPI 0 "register_operand" "=r,r")
1741         (plus:GPI (match_dup 1) (match_dup 2)))]
1742   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1743                                  <MODE>mode, operands[2])"
1744   "@
1745   adds\\t%<w>0, %<w>1, %2
1746   subs\\t%<w>0, %<w>1, #%n2"
1747   [(set_attr "type" "alus_imm")]
1750 (define_insn "add<mode>3_compareC"
1751   [(set (reg:CC_C CC_REGNUM)
1752         (ne:CC_C
1753           (plus:<DWI>
1754             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1755             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1756           (zero_extend:<DWI>
1757             (plus:GPI (match_dup 1) (match_dup 2)))))
1758    (set (match_operand:GPI 0 "register_operand" "=r")
1759         (plus:GPI (match_dup 1) (match_dup 2)))]
1760   ""
1761   "adds\\t%<w>0, %<w>1, %<w>2"
1762   [(set_attr "type" "alus_sreg")]
1765 (define_insn "*adds_shift_imm_<mode>"
1766   [(set (reg:CC_NZ CC_REGNUM)
1767         (compare:CC_NZ
1768          (plus:GPI (ASHIFT:GPI 
1769                     (match_operand:GPI 1 "register_operand" "r")
1770                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1771                    (match_operand:GPI 3 "register_operand" "r"))
1772          (const_int 0)))
1773    (set (match_operand:GPI 0 "register_operand" "=r")
1774         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1775                   (match_dup 3)))]
1776   ""
1777   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1778   [(set_attr "type" "alus_shift_imm")]
1781 (define_insn "*subs_shift_imm_<mode>"
1782   [(set (reg:CC_NZ CC_REGNUM)
1783         (compare:CC_NZ
1784          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1785                     (ASHIFT:GPI
1786                      (match_operand:GPI 2 "register_operand" "r")
1787                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1788          (const_int 0)))
1789    (set (match_operand:GPI 0 "register_operand" "=r")
1790         (minus:GPI (match_dup 1)
1791                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1792   ""
1793   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1794   [(set_attr "type" "alus_shift_imm")]
1797 (define_insn "*adds_mul_imm_<mode>"
1798   [(set (reg:CC_NZ CC_REGNUM)
1799         (compare:CC_NZ
1800          (plus:GPI (mult:GPI
1801                     (match_operand:GPI 1 "register_operand" "r")
1802                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1803                    (match_operand:GPI 3 "register_operand" "r"))
1804          (const_int 0)))
1805    (set (match_operand:GPI 0 "register_operand" "=r")
1806         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1807                   (match_dup 3)))]
1808   ""
1809   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1810   [(set_attr "type" "alus_shift_imm")]
1813 (define_insn "*subs_mul_imm_<mode>"
1814   [(set (reg:CC_NZ CC_REGNUM)
1815         (compare:CC_NZ
1816          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1817                     (mult:GPI
1818                      (match_operand:GPI 2 "register_operand" "r")
1819                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1820          (const_int 0)))
1821    (set (match_operand:GPI 0 "register_operand" "=r")
1822         (minus:GPI (match_dup 1)
1823                    (mult:GPI (match_dup 2) (match_dup 3))))]
1824   ""
1825   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1826   [(set_attr "type" "alus_shift_imm")]
1829 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1830   [(set (reg:CC_NZ CC_REGNUM)
1831         (compare:CC_NZ
1832          (plus:GPI
1833           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1834           (match_operand:GPI 2 "register_operand" "r"))
1835         (const_int 0)))
1836    (set (match_operand:GPI 0 "register_operand" "=r")
1837         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1838   ""
1839   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1840   [(set_attr "type" "alus_ext")]
1843 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1844   [(set (reg:CC_NZ CC_REGNUM)
1845         (compare:CC_NZ
1846          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1847                     (ANY_EXTEND:GPI
1848                      (match_operand:ALLX 2 "register_operand" "r")))
1849         (const_int 0)))
1850    (set (match_operand:GPI 0 "register_operand" "=r")
1851         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1852   ""
1853   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1854   [(set_attr "type" "alus_ext")]
1857 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1858   [(set (reg:CC_NZ CC_REGNUM)
1859         (compare:CC_NZ
1860          (plus:GPI (ashift:GPI 
1861                     (ANY_EXTEND:GPI 
1862                      (match_operand:ALLX 1 "register_operand" "r"))
1863                     (match_operand 2 "aarch64_imm3" "Ui3"))
1864                    (match_operand:GPI 3 "register_operand" "r"))
1865          (const_int 0)))
1866    (set (match_operand:GPI 0 "register_operand" "=rk")
1867         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1868                               (match_dup 2))
1869                   (match_dup 3)))]
1870   ""
1871   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1872   [(set_attr "type" "alus_ext")]
1875 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1876   [(set (reg:CC_NZ CC_REGNUM)
1877         (compare:CC_NZ
1878          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1879                     (ashift:GPI 
1880                      (ANY_EXTEND:GPI
1881                       (match_operand:ALLX 2 "register_operand" "r"))
1882                      (match_operand 3 "aarch64_imm3" "Ui3")))
1883          (const_int 0)))
1884    (set (match_operand:GPI 0 "register_operand" "=rk")
1885         (minus:GPI (match_dup 1)
1886                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1887                                (match_dup 3))))]
1888   ""
1889   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1890   [(set_attr "type" "alus_ext")]
1893 (define_insn "*adds_<optab><mode>_multp2"
1894   [(set (reg:CC_NZ CC_REGNUM)
1895         (compare:CC_NZ
1896          (plus:GPI (ANY_EXTRACT:GPI
1897                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1898                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1899                     (match_operand 3 "const_int_operand" "n")
1900                     (const_int 0))
1901                    (match_operand:GPI 4 "register_operand" "r"))
1902         (const_int 0)))
1903    (set (match_operand:GPI 0 "register_operand" "=r")
1904         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1905                                    (match_dup 3)
1906                                    (const_int 0))
1907                   (match_dup 4)))]
1908   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1909   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1910   [(set_attr "type" "alus_ext")]
1913 (define_insn "*subs_<optab><mode>_multp2"
1914   [(set (reg:CC_NZ CC_REGNUM)
1915         (compare:CC_NZ
1916          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1917                     (ANY_EXTRACT:GPI
1918                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1919                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1920                      (match_operand 3 "const_int_operand" "n")
1921                      (const_int 0)))
1922         (const_int 0)))
1923    (set (match_operand:GPI 0 "register_operand" "=r")
1924         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1925                                   (mult:GPI (match_dup 1) (match_dup 2))
1926                                   (match_dup 3)
1927                                   (const_int 0))))]
1928   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1929   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1930   [(set_attr "type" "alus_ext")]
1933 (define_insn "*add<mode>3nr_compare0"
1934   [(set (reg:CC_NZ CC_REGNUM)
1935         (compare:CC_NZ
1936          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1937                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1938          (const_int 0)))]
1939   ""
1940   "@
1941   cmn\\t%<w>0, %<w>1
1942   cmn\\t%<w>0, %1
1943   cmp\\t%<w>0, #%n1"
1944   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1947 (define_insn "aarch64_sub<mode>_compare0"
1948   [(set (reg:CC_NZ CC_REGNUM)
1949         (compare:CC_NZ
1950          (minus:GPI (match_operand:GPI 0 "register_operand" "r")
1951                    (match_operand:GPI 1 "aarch64_plus_operand" "r"))
1952          (const_int 0)))]
1953   ""
1954   "cmp\\t%<w>0, %<w>1"
1955   [(set_attr "type" "alus_sreg")]
1958 (define_insn "*compare_neg<mode>"
1959   [(set (reg:CC_Z CC_REGNUM)
1960         (compare:CC_Z
1961          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1962          (match_operand:GPI 1 "register_operand" "r")))]
1963   ""
1964   "cmn\\t%<w>1, %<w>0"
1965   [(set_attr "type" "alus_sreg")]
1968 (define_insn "*add_<shift>_<mode>"
1969   [(set (match_operand:GPI 0 "register_operand" "=r")
1970         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1971                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1972                   (match_operand:GPI 3 "register_operand" "r")))]
1973   ""
1974   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1975   [(set_attr "type" "alu_shift_imm")]
1978 ;; zero_extend version of above
1979 (define_insn "*add_<shift>_si_uxtw"
1980   [(set (match_operand:DI 0 "register_operand" "=r")
1981         (zero_extend:DI
1982          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1983                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1984                   (match_operand:SI 3 "register_operand" "r"))))]
1985   ""
1986   "add\\t%w0, %w3, %w1, <shift> %2"
1987   [(set_attr "type" "alu_shift_imm")]
1990 (define_insn "*add_mul_imm_<mode>"
1991   [(set (match_operand:GPI 0 "register_operand" "=r")
1992         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1993                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1994                   (match_operand:GPI 3 "register_operand" "r")))]
1995   ""
1996   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1997   [(set_attr "type" "alu_shift_imm")]
2000 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2001   [(set (match_operand:GPI 0 "register_operand" "=rk")
2002         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2003                   (match_operand:GPI 2 "register_operand" "r")))]
2004   ""
2005   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2006   [(set_attr "type" "alu_ext")]
2009 ;; zero_extend version of above
2010 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2011   [(set (match_operand:DI 0 "register_operand" "=rk")
2012         (zero_extend:DI
2013          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2014                   (match_operand:GPI 2 "register_operand" "r"))))]
2015   ""
2016   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2017   [(set_attr "type" "alu_ext")]
2020 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2021   [(set (match_operand:GPI 0 "register_operand" "=rk")
2022         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2023                                (match_operand:ALLX 1 "register_operand" "r"))
2024                               (match_operand 2 "aarch64_imm3" "Ui3"))
2025                   (match_operand:GPI 3 "register_operand" "r")))]
2026   ""
2027   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2028   [(set_attr "type" "alu_ext")]
2031 ;; zero_extend version of above
2032 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2033   [(set (match_operand:DI 0 "register_operand" "=rk")
2034         (zero_extend:DI
2035          (plus:SI (ashift:SI (ANY_EXTEND:SI
2036                               (match_operand:SHORT 1 "register_operand" "r"))
2037                              (match_operand 2 "aarch64_imm3" "Ui3"))
2038                   (match_operand:SI 3 "register_operand" "r"))))]
2039   ""
2040   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2041   [(set_attr "type" "alu_ext")]
2044 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2045   [(set (match_operand:GPI 0 "register_operand" "=rk")
2046         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2047                              (match_operand:ALLX 1 "register_operand" "r"))
2048                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2049                   (match_operand:GPI 3 "register_operand" "r")))]
2050   ""
2051   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2052   [(set_attr "type" "alu_ext")]
2055 ;; zero_extend version of above
2056 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2057   [(set (match_operand:DI 0 "register_operand" "=rk")
2058         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2059                              (match_operand:SHORT 1 "register_operand" "r"))
2060                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2061                   (match_operand:SI 3 "register_operand" "r"))))]
2062   ""
2063   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2064   [(set_attr "type" "alu_ext")]
2067 (define_insn "*add_<optab><mode>_multp2"
2068   [(set (match_operand:GPI 0 "register_operand" "=rk")
2069         (plus:GPI (ANY_EXTRACT:GPI
2070                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2071                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2072                    (match_operand 3 "const_int_operand" "n")
2073                    (const_int 0))
2074                   (match_operand:GPI 4 "register_operand" "r")))]
2075   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2076   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2077   [(set_attr "type" "alu_ext")]
2080 ;; zero_extend version of above
2081 (define_insn "*add_<optab>si_multp2_uxtw"
2082   [(set (match_operand:DI 0 "register_operand" "=rk")
2083         (zero_extend:DI
2084          (plus:SI (ANY_EXTRACT:SI
2085                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2086                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2087                    (match_operand 3 "const_int_operand" "n")
2088                    (const_int 0))
2089                   (match_operand:SI 4 "register_operand" "r"))))]
2090   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2091   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2092   [(set_attr "type" "alu_ext")]
2095 (define_expand "add<mode>3_carryin"
2096   [(set (match_operand:GPI 0 "register_operand")
2097         (plus:GPI
2098           (plus:GPI
2099             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2100             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2101           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2102    ""
2103    ""
2106 ;; Note that add with carry with two zero inputs is matched by cset,
2107 ;; and that add with carry with one zero input is matched by cinc.
2109 (define_insn "*add<mode>3_carryin"
2110   [(set (match_operand:GPI 0 "register_operand" "=r")
2111         (plus:GPI
2112           (plus:GPI
2113             (match_operand:GPI 3 "aarch64_carry_operation" "")
2114             (match_operand:GPI 1 "register_operand" "r"))
2115           (match_operand:GPI 2 "register_operand" "r")))]
2116    ""
2117    "adc\\t%<w>0, %<w>1, %<w>2"
2118   [(set_attr "type" "adc_reg")]
2121 ;; zero_extend version of above
2122 (define_insn "*addsi3_carryin_uxtw"
2123   [(set (match_operand:DI 0 "register_operand" "=r")
2124         (zero_extend:DI
2125           (plus:SI
2126             (plus:SI
2127               (match_operand:SI 3 "aarch64_carry_operation" "")
2128               (match_operand:SI 1 "register_operand" "r"))
2129             (match_operand:SI 2 "register_operand" "r"))))]
2130    ""
2131    "adc\\t%w0, %w1, %w2"
2132   [(set_attr "type" "adc_reg")]
2135 (define_insn "*add_uxt<mode>_shift2"
2136   [(set (match_operand:GPI 0 "register_operand" "=rk")
2137         (plus:GPI (and:GPI
2138                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2139                                (match_operand 2 "aarch64_imm3" "Ui3"))
2140                    (match_operand 3 "const_int_operand" "n"))
2141                   (match_operand:GPI 4 "register_operand" "r")))]
2142   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2143   "*
2144   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2145                                            INTVAL (operands[3])));
2146   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2147   [(set_attr "type" "alu_ext")]
2150 ;; zero_extend version of above
2151 (define_insn "*add_uxtsi_shift2_uxtw"
2152   [(set (match_operand:DI 0 "register_operand" "=rk")
2153         (zero_extend:DI
2154          (plus:SI (and:SI
2155                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2156                               (match_operand 2 "aarch64_imm3" "Ui3"))
2157                    (match_operand 3 "const_int_operand" "n"))
2158                   (match_operand:SI 4 "register_operand" "r"))))]
2159   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2160   "*
2161   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2162                                            INTVAL (operands[3])));
2163   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2164   [(set_attr "type" "alu_ext")]
2167 (define_insn "*add_uxt<mode>_multp2"
2168   [(set (match_operand:GPI 0 "register_operand" "=rk")
2169         (plus:GPI (and:GPI
2170                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2171                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2172                    (match_operand 3 "const_int_operand" "n"))
2173                   (match_operand:GPI 4 "register_operand" "r")))]
2174   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2175   "*
2176   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2177                                            INTVAL (operands[3])));
2178   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2179   [(set_attr "type" "alu_ext")]
2182 ;; zero_extend version of above
2183 (define_insn "*add_uxtsi_multp2_uxtw"
2184   [(set (match_operand:DI 0 "register_operand" "=rk")
2185         (zero_extend:DI
2186          (plus:SI (and:SI
2187                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2188                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2189                    (match_operand 3 "const_int_operand" "n"))
2190                   (match_operand:SI 4 "register_operand" "r"))))]
2191   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2192   "*
2193   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2194                                            INTVAL (operands[3])));
2195   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2196   [(set_attr "type" "alu_ext")]
2199 (define_insn "subsi3"
2200   [(set (match_operand:SI 0 "register_operand" "=rk")
2201         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2202                   (match_operand:SI 2 "register_operand" "r")))]
2203   ""
2204   "sub\\t%w0, %w1, %w2"
2205   [(set_attr "type" "alu_sreg")]
2208 ;; zero_extend version of above
2209 (define_insn "*subsi3_uxtw"
2210   [(set (match_operand:DI 0 "register_operand" "=rk")
2211         (zero_extend:DI
2212          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2213                    (match_operand:SI 2 "register_operand" "r"))))]
2214   ""
2215   "sub\\t%w0, %w1, %w2"
2216   [(set_attr "type" "alu_sreg")]
2219 (define_insn "subdi3"
2220   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2221         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2222                   (match_operand:DI 2 "register_operand" "r,w")))]
2223   ""
2224   "@
2225    sub\\t%x0, %x1, %x2
2226    sub\\t%d0, %d1, %d2"
2227   [(set_attr "type" "alu_sreg, neon_sub")
2228    (set_attr "simd" "*,yes")]
2231 (define_expand "subti3"
2232   [(set (match_operand:TI 0 "register_operand" "")
2233         (minus:TI (match_operand:TI 1 "register_operand" "")
2234                   (match_operand:TI 2 "register_operand" "")))]
2235   ""
2237   rtx low = gen_reg_rtx (DImode);
2238   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2239                                   gen_lowpart (DImode, operands[2])));
2241   rtx high = gen_reg_rtx (DImode);
2242   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2243                                  gen_highpart (DImode, operands[2])));
2245   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2246   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2247   DONE;
2250 (define_insn "*sub<mode>3_compare0"
2251   [(set (reg:CC_NZ CC_REGNUM)
2252         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2253                                   (match_operand:GPI 2 "register_operand" "r"))
2254                        (const_int 0)))
2255    (set (match_operand:GPI 0 "register_operand" "=r")
2256         (minus:GPI (match_dup 1) (match_dup 2)))]
2257   ""
2258   "subs\\t%<w>0, %<w>1, %<w>2"
2259   [(set_attr "type" "alus_sreg")]
2262 ;; zero_extend version of above
2263 (define_insn "*subsi3_compare0_uxtw"
2264   [(set (reg:CC_NZ CC_REGNUM)
2265         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2266                                  (match_operand:SI 2 "register_operand" "r"))
2267                        (const_int 0)))
2268    (set (match_operand:DI 0 "register_operand" "=r")
2269         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2270   ""
2271   "subs\\t%w0, %w1, %w2"
2272   [(set_attr "type" "alus_sreg")]
2275 (define_insn "sub<mode>3_compare1"
2276   [(set (reg:CC CC_REGNUM)
2277         (compare:CC
2278           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2279           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2280    (set (match_operand:GPI 0 "register_operand" "=r")
2281         (minus:GPI (match_dup 1) (match_dup 2)))]
2282   ""
2283   "subs\\t%<w>0, %<w>1, %<w>2"
2284   [(set_attr "type" "alus_sreg")]
2287 (define_insn "sub<mode>3_compare1_imm"
2288   [(set (reg:CC CC_REGNUM)
2289         (compare:CC
2290           (match_operand:GPI 1 "register_operand" "r")
2291           (match_operand:GPI 3 "const_int_operand" "n")))
2292    (set (match_operand:GPI 0 "register_operand" "=r")
2293         (plus:GPI (match_dup 1)
2294                   (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2295   "INTVAL (operands[3]) == -INTVAL (operands[2])"
2296   "subs\\t%<w>0, %<w>1, #%n2"
2297   [(set_attr "type" "alus_sreg")]
2300 (define_peephole2
2301   [(set (match_operand:GPI 0 "register_operand")
2302         (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2303                     (match_operand:GPI 2 "aarch64_reg_or_zero")))
2304    (set (reg:CC CC_REGNUM)
2305         (compare:CC
2306           (match_dup 1)
2307           (match_dup 2)))]
2308   "!reg_overlap_mentioned_p (operands[0], operands[1])
2309    && !reg_overlap_mentioned_p (operands[0], operands[2])"
2310   [(const_int 0)]
2311   {
2312     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2313                                          operands[2]));
2314     DONE;
2315   }
2318 (define_peephole2
2319   [(set (match_operand:GPI 0 "register_operand")
2320         (plus:GPI (match_operand:GPI 1 "register_operand")
2321                   (match_operand:GPI 2 "aarch64_sub_immediate")))
2322    (set (reg:CC CC_REGNUM)
2323         (compare:CC
2324           (match_dup 1)
2325           (match_operand:GPI 3 "const_int_operand")))]
2326   "!reg_overlap_mentioned_p (operands[0], operands[1])
2327    && INTVAL (operands[3]) == -INTVAL (operands[2])"
2328   [(const_int 0)]
2329   {
2330     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2331                                          operands[2], operands[3]));
2332     DONE;
2333   }
2336 (define_insn "*sub_<shift>_<mode>"
2337   [(set (match_operand:GPI 0 "register_operand" "=r")
2338         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2339                    (ASHIFT:GPI
2340                     (match_operand:GPI 1 "register_operand" "r")
2341                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2342   ""
2343   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2344   [(set_attr "type" "alu_shift_imm")]
2347 ;; zero_extend version of above
2348 (define_insn "*sub_<shift>_si_uxtw"
2349   [(set (match_operand:DI 0 "register_operand" "=r")
2350         (zero_extend:DI
2351          (minus:SI (match_operand:SI 3 "register_operand" "r")
2352                    (ASHIFT:SI
2353                     (match_operand:SI 1 "register_operand" "r")
2354                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2355   ""
2356   "sub\\t%w0, %w3, %w1, <shift> %2"
2357   [(set_attr "type" "alu_shift_imm")]
2360 (define_insn "*sub_mul_imm_<mode>"
2361   [(set (match_operand:GPI 0 "register_operand" "=r")
2362         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2363                    (mult:GPI
2364                     (match_operand:GPI 1 "register_operand" "r")
2365                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2366   ""
2367   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2368   [(set_attr "type" "alu_shift_imm")]
2371 ;; zero_extend version of above
2372 (define_insn "*sub_mul_imm_si_uxtw"
2373   [(set (match_operand:DI 0 "register_operand" "=r")
2374         (zero_extend:DI
2375          (minus:SI (match_operand:SI 3 "register_operand" "r")
2376                    (mult:SI
2377                     (match_operand:SI 1 "register_operand" "r")
2378                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2379   ""
2380   "sub\\t%w0, %w3, %w1, lsl %p2"
2381   [(set_attr "type" "alu_shift_imm")]
2384 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2385   [(set (match_operand:GPI 0 "register_operand" "=rk")
2386         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2387                    (ANY_EXTEND:GPI
2388                     (match_operand:ALLX 2 "register_operand" "r"))))]
2389   ""
2390   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2391   [(set_attr "type" "alu_ext")]
2394 ;; zero_extend version of above
2395 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2396   [(set (match_operand:DI 0 "register_operand" "=rk")
2397         (zero_extend:DI
2398          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2399                    (ANY_EXTEND:SI
2400                     (match_operand:SHORT 2 "register_operand" "r")))))]
2401   ""
2402   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2403   [(set_attr "type" "alu_ext")]
2406 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2407   [(set (match_operand:GPI 0 "register_operand" "=rk")
2408         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2409                    (ashift:GPI (ANY_EXTEND:GPI
2410                                 (match_operand:ALLX 2 "register_operand" "r"))
2411                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2412   ""
2413   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2414   [(set_attr "type" "alu_ext")]
2417 ;; zero_extend version of above
2418 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2419   [(set (match_operand:DI 0 "register_operand" "=rk")
2420         (zero_extend:DI
2421          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2422                    (ashift:SI (ANY_EXTEND:SI
2423                                (match_operand:SHORT 2 "register_operand" "r"))
2424                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2425   ""
2426   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2427   [(set_attr "type" "alu_ext")]
2430 (define_insn "*sub_<optab><mode>_multp2"
2431   [(set (match_operand:GPI 0 "register_operand" "=rk")
2432         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2433                    (ANY_EXTRACT:GPI
2434                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2435                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2436                     (match_operand 3 "const_int_operand" "n")
2437                     (const_int 0))))]
2438   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2439   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2440   [(set_attr "type" "alu_ext")]
2443 ;; zero_extend version of above
2444 (define_insn "*sub_<optab>si_multp2_uxtw"
2445   [(set (match_operand:DI 0 "register_operand" "=rk")
2446         (zero_extend:DI
2447          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2448                    (ANY_EXTRACT:SI
2449                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2450                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2451                     (match_operand 3 "const_int_operand" "n")
2452                     (const_int 0)))))]
2453   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2454   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2455   [(set_attr "type" "alu_ext")]
2458 ;; The hardware description is op1 + ~op2 + C.
2459 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2460 ;;                           = op1 - op2 - 1 + 1 - !C
2461 ;;                           = op1 - op2 - !C.
2462 ;; We describe the latter.
2464 (define_insn "*sub<mode>3_carryin0"
2465   [(set (match_operand:GPI 0 "register_operand" "=r")
2466         (minus:GPI
2467           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2468           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2469    ""
2470    "sbc\\t%<w>0, %<w>1, <w>zr"
2471   [(set_attr "type" "adc_reg")]
2474 ;; zero_extend version of the above
2475 (define_insn "*subsi3_carryin_uxtw"
2476   [(set (match_operand:DI 0 "register_operand" "=r")
2477         (zero_extend:DI
2478           (minus:SI
2479             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2480             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2481    ""
2482    "sbc\\t%w0, %w1, wzr"
2483   [(set_attr "type" "adc_reg")]
2486 (define_expand "sub<mode>3_carryin"
2487   [(set (match_operand:GPI 0 "register_operand")
2488         (minus:GPI
2489           (minus:GPI
2490             (match_operand:GPI 1 "aarch64_reg_or_zero")
2491             (match_operand:GPI 2 "register_operand"))
2492           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2493    ""
2494    ""
2497 (define_insn "*sub<mode>3_carryin"
2498   [(set (match_operand:GPI 0 "register_operand" "=r")
2499         (minus:GPI
2500           (minus:GPI
2501             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2502             (match_operand:GPI 2 "register_operand" "r"))
2503           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2505    ""
2506    "sbc\\t%<w>0, %<w>1, %<w>2"
2507   [(set_attr "type" "adc_reg")]
2510 ;; zero_extend version of the above
2511 (define_insn "*subsi3_carryin_uxtw"
2512   [(set (match_operand:DI 0 "register_operand" "=r")
2513         (zero_extend:DI
2514           (minus:SI
2515             (minus:SI
2516               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2517               (match_operand:SI 2 "register_operand" "r"))
2518             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2520    ""
2521    "sbc\\t%w0, %w1, %w2"
2522   [(set_attr "type" "adc_reg")]
2525 (define_insn "*sub<mode>3_carryin_alt"
2526   [(set (match_operand:GPI 0 "register_operand" "=r")
2527         (minus:GPI
2528           (minus:GPI
2529             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2530             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2531           (match_operand:GPI 2 "register_operand" "r")))]
2532    ""
2533    "sbc\\t%<w>0, %<w>1, %<w>2"
2534   [(set_attr "type" "adc_reg")]
2537 ;; zero_extend version of the above
2538 (define_insn "*subsi3_carryin_alt_uxtw"
2539   [(set (match_operand:DI 0 "register_operand" "=r")
2540         (zero_extend:DI
2541           (minus:SI
2542             (minus:SI
2543               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2544               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2545             (match_operand:SI 2 "register_operand" "r"))))]
2546    ""
2547    "sbc\\t%w0, %w1, %w2"
2548   [(set_attr "type" "adc_reg")]
2551 (define_insn "*sub_uxt<mode>_shift2"
2552   [(set (match_operand:GPI 0 "register_operand" "=rk")
2553         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2554                    (and:GPI
2555                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2556                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2557                     (match_operand 3 "const_int_operand" "n"))))]
2558   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2559   "*
2560   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2561                                            INTVAL (operands[3])));
2562   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2563   [(set_attr "type" "alu_ext")]
2566 ;; zero_extend version of above
2567 (define_insn "*sub_uxtsi_shift2_uxtw"
2568   [(set (match_operand:DI 0 "register_operand" "=rk")
2569         (zero_extend:DI
2570          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2571                    (and:SI
2572                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2573                                (match_operand 2 "aarch64_imm3" "Ui3"))
2574                     (match_operand 3 "const_int_operand" "n")))))]
2575   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2576   "*
2577   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2578                                            INTVAL (operands[3])));
2579   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2580   [(set_attr "type" "alu_ext")]
2583 (define_insn "*sub_uxt<mode>_multp2"
2584   [(set (match_operand:GPI 0 "register_operand" "=rk")
2585         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2586                    (and:GPI
2587                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2588                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2589                     (match_operand 3 "const_int_operand" "n"))))]
2590   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2591   "*
2592   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2593                                            INTVAL (operands[3])));
2594   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2595   [(set_attr "type" "alu_ext")]
2598 ;; zero_extend version of above
2599 (define_insn "*sub_uxtsi_multp2_uxtw"
2600   [(set (match_operand:DI 0 "register_operand" "=rk")
2601         (zero_extend:DI
2602          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2603                    (and:SI
2604                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2605                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2606                     (match_operand 3 "const_int_operand" "n")))))]
2607   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2608   "*
2609   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2610                                            INTVAL (operands[3])));
2611   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2612   [(set_attr "type" "alu_ext")]
2615 (define_expand "abs<mode>2"
2616   [(match_operand:GPI 0 "register_operand" "")
2617    (match_operand:GPI 1 "register_operand" "")]
2618   ""
2619   {
2620     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2621     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2622     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2623     DONE;
2624   }
2627 (define_insn "neg<mode>2"
2628   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2629         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2630   ""
2631   "@
2632    neg\\t%<w>0, %<w>1
2633    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2634   [(set_attr "type" "alu_sreg, neon_neg<q>")
2635    (set_attr "simd" "*,yes")]
2638 ;; zero_extend version of above
2639 (define_insn "*negsi2_uxtw"
2640   [(set (match_operand:DI 0 "register_operand" "=r")
2641         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2642   ""
2643   "neg\\t%w0, %w1"
2644   [(set_attr "type" "alu_sreg")]
2647 (define_insn "*ngc<mode>"
2648   [(set (match_operand:GPI 0 "register_operand" "=r")
2649         (minus:GPI
2650           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2651           (match_operand:GPI 1 "register_operand" "r")))]
2652   ""
2653   "ngc\\t%<w>0, %<w>1"
2654   [(set_attr "type" "adc_reg")]
2657 (define_insn "*ngcsi_uxtw"
2658   [(set (match_operand:DI 0 "register_operand" "=r")
2659         (zero_extend:DI
2660           (minus:SI
2661             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2662             (match_operand:SI 1 "register_operand" "r"))))]
2663   ""
2664   "ngc\\t%w0, %w1"
2665   [(set_attr "type" "adc_reg")]
2668 (define_insn "neg<mode>2_compare0"
2669   [(set (reg:CC_NZ CC_REGNUM)
2670         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2671                        (const_int 0)))
2672    (set (match_operand:GPI 0 "register_operand" "=r")
2673         (neg:GPI (match_dup 1)))]
2674   ""
2675   "negs\\t%<w>0, %<w>1"
2676   [(set_attr "type" "alus_sreg")]
2679 ;; zero_extend version of above
2680 (define_insn "*negsi2_compare0_uxtw"
2681   [(set (reg:CC_NZ CC_REGNUM)
2682         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2683                        (const_int 0)))
2684    (set (match_operand:DI 0 "register_operand" "=r")
2685         (zero_extend:DI (neg:SI (match_dup 1))))]
2686   ""
2687   "negs\\t%w0, %w1"
2688   [(set_attr "type" "alus_sreg")]
2691 (define_insn "*neg_<shift><mode>3_compare0"
2692   [(set (reg:CC_NZ CC_REGNUM)
2693         (compare:CC_NZ
2694          (neg:GPI (ASHIFT:GPI
2695                    (match_operand:GPI 1 "register_operand" "r")
2696                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2697          (const_int 0)))
2698    (set (match_operand:GPI 0 "register_operand" "=r")
2699         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2700   ""
2701   "negs\\t%<w>0, %<w>1, <shift> %2"
2702   [(set_attr "type" "alus_shift_imm")]
2705 (define_insn "*neg_<shift>_<mode>2"
2706   [(set (match_operand:GPI 0 "register_operand" "=r")
2707         (neg:GPI (ASHIFT:GPI
2708                   (match_operand:GPI 1 "register_operand" "r")
2709                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2710   ""
2711   "neg\\t%<w>0, %<w>1, <shift> %2"
2712   [(set_attr "type" "alu_shift_imm")]
2715 ;; zero_extend version of above
2716 (define_insn "*neg_<shift>_si2_uxtw"
2717   [(set (match_operand:DI 0 "register_operand" "=r")
2718         (zero_extend:DI
2719          (neg:SI (ASHIFT:SI
2720                   (match_operand:SI 1 "register_operand" "r")
2721                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2722   ""
2723   "neg\\t%w0, %w1, <shift> %2"
2724   [(set_attr "type" "alu_shift_imm")]
2727 (define_insn "*neg_mul_imm_<mode>2"
2728   [(set (match_operand:GPI 0 "register_operand" "=r")
2729         (neg:GPI (mult:GPI
2730                   (match_operand:GPI 1 "register_operand" "r")
2731                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2732   ""
2733   "neg\\t%<w>0, %<w>1, lsl %p2"
2734   [(set_attr "type" "alu_shift_imm")]
2737 ;; zero_extend version of above
2738 (define_insn "*neg_mul_imm_si2_uxtw"
2739   [(set (match_operand:DI 0 "register_operand" "=r")
2740         (zero_extend:DI
2741          (neg:SI (mult:SI
2742                   (match_operand:SI 1 "register_operand" "r")
2743                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2744   ""
2745   "neg\\t%w0, %w1, lsl %p2"
2746   [(set_attr "type" "alu_shift_imm")]
2749 (define_insn "mul<mode>3"
2750   [(set (match_operand:GPI 0 "register_operand" "=r")
2751         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2752                   (match_operand:GPI 2 "register_operand" "r")))]
2753   ""
2754   "mul\\t%<w>0, %<w>1, %<w>2"
2755   [(set_attr "type" "mul")]
2758 ;; zero_extend version of above
2759 (define_insn "*mulsi3_uxtw"
2760   [(set (match_operand:DI 0 "register_operand" "=r")
2761         (zero_extend:DI
2762          (mult:SI (match_operand:SI 1 "register_operand" "r")
2763                   (match_operand:SI 2 "register_operand" "r"))))]
2764   ""
2765   "mul\\t%w0, %w1, %w2"
2766   [(set_attr "type" "mul")]
2769 (define_insn "madd<mode>"
2770   [(set (match_operand:GPI 0 "register_operand" "=r")
2771         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2772                             (match_operand:GPI 2 "register_operand" "r"))
2773                   (match_operand:GPI 3 "register_operand" "r")))]
2774   ""
2775   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2776   [(set_attr "type" "mla")]
2779 ;; zero_extend version of above
2780 (define_insn "*maddsi_uxtw"
2781   [(set (match_operand:DI 0 "register_operand" "=r")
2782         (zero_extend:DI
2783          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2784                            (match_operand:SI 2 "register_operand" "r"))
2785                   (match_operand:SI 3 "register_operand" "r"))))]
2786   ""
2787   "madd\\t%w0, %w1, %w2, %w3"
2788   [(set_attr "type" "mla")]
2791 (define_insn "*msub<mode>"
2792   [(set (match_operand:GPI 0 "register_operand" "=r")
2793         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2794                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2795                              (match_operand:GPI 2 "register_operand" "r"))))]
2797   ""
2798   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2799   [(set_attr "type" "mla")]
2802 ;; zero_extend version of above
2803 (define_insn "*msubsi_uxtw"
2804   [(set (match_operand:DI 0 "register_operand" "=r")
2805         (zero_extend:DI
2806          (minus:SI (match_operand:SI 3 "register_operand" "r")
2807                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2808                             (match_operand:SI 2 "register_operand" "r")))))]
2810   ""
2811   "msub\\t%w0, %w1, %w2, %w3"
2812   [(set_attr "type" "mla")]
2815 (define_insn "*mul<mode>_neg"
2816   [(set (match_operand:GPI 0 "register_operand" "=r")
2817         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2818                   (match_operand:GPI 2 "register_operand" "r")))]
2820   ""
2821   "mneg\\t%<w>0, %<w>1, %<w>2"
2822   [(set_attr "type" "mul")]
2825 ;; zero_extend version of above
2826 (define_insn "*mulsi_neg_uxtw"
2827   [(set (match_operand:DI 0 "register_operand" "=r")
2828         (zero_extend:DI
2829          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2830                   (match_operand:SI 2 "register_operand" "r"))))]
2832   ""
2833   "mneg\\t%w0, %w1, %w2"
2834   [(set_attr "type" "mul")]
2837 (define_insn "<su_optab>mulsidi3"
2838   [(set (match_operand:DI 0 "register_operand" "=r")
2839         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2840                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2841   ""
2842   "<su>mull\\t%0, %w1, %w2"
2843   [(set_attr "type" "<su>mull")]
2846 (define_insn "<su_optab>maddsidi4"
2847   [(set (match_operand:DI 0 "register_operand" "=r")
2848         (plus:DI (mult:DI
2849                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2850                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2851                  (match_operand:DI 3 "register_operand" "r")))]
2852   ""
2853   "<su>maddl\\t%0, %w1, %w2, %3"
2854   [(set_attr "type" "<su>mlal")]
2857 (define_insn "<su_optab>msubsidi4"
2858   [(set (match_operand:DI 0 "register_operand" "=r")
2859         (minus:DI
2860          (match_operand:DI 3 "register_operand" "r")
2861          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2862                   (ANY_EXTEND:DI
2863                    (match_operand:SI 2 "register_operand" "r")))))]
2864   ""
2865   "<su>msubl\\t%0, %w1, %w2, %3"
2866   [(set_attr "type" "<su>mlal")]
2869 (define_insn "*<su_optab>mulsidi_neg"
2870   [(set (match_operand:DI 0 "register_operand" "=r")
2871         (mult:DI (neg:DI
2872                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2873                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2874   ""
2875   "<su>mnegl\\t%0, %w1, %w2"
2876   [(set_attr "type" "<su>mull")]
2879 (define_expand "<su_optab>mulditi3"
2880   [(set (match_operand:TI 0 "register_operand")
2881         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2882                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2883   ""
2885   rtx low = gen_reg_rtx (DImode);
2886   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2888   rtx high = gen_reg_rtx (DImode);
2889   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2891   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2892   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2893   DONE;
2896 ;; The default expansion of multi3 using umuldi3_highpart will perform
2897 ;; the additions in an order that fails to combine into two madd insns.
2898 (define_expand "multi3"
2899   [(set (match_operand:TI 0 "register_operand")
2900         (mult:TI (match_operand:TI 1 "register_operand")
2901                  (match_operand:TI 2 "register_operand")))]
2902   ""
2904   rtx l0 = gen_reg_rtx (DImode);
2905   rtx l1 = gen_lowpart (DImode, operands[1]);
2906   rtx l2 = gen_lowpart (DImode, operands[2]);
2907   rtx h0 = gen_reg_rtx (DImode);
2908   rtx h1 = gen_highpart (DImode, operands[1]);
2909   rtx h2 = gen_highpart (DImode, operands[2]);
2911   emit_insn (gen_muldi3 (l0, l1, l2));
2912   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2913   emit_insn (gen_madddi (h0, h1, l2, h0));
2914   emit_insn (gen_madddi (h0, l1, h2, h0));
2916   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2917   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2918   DONE;
2921 (define_insn "<su>muldi3_highpart"
2922   [(set (match_operand:DI 0 "register_operand" "=r")
2923         (truncate:DI
2924          (lshiftrt:TI
2925           (mult:TI
2926            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2927            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2928           (const_int 64))))]
2929   ""
2930   "<su>mulh\\t%0, %1, %2"
2931   [(set_attr "type" "<su>mull")]
2934 (define_insn "<su_optab>div<mode>3"
2935   [(set (match_operand:GPI 0 "register_operand" "=r")
2936         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2937                      (match_operand:GPI 2 "register_operand" "r")))]
2938   ""
2939   "<su>div\\t%<w>0, %<w>1, %<w>2"
2940   [(set_attr "type" "<su>div")]
2943 ;; zero_extend version of above
2944 (define_insn "*<su_optab>divsi3_uxtw"
2945   [(set (match_operand:DI 0 "register_operand" "=r")
2946         (zero_extend:DI
2947          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2948                      (match_operand:SI 2 "register_operand" "r"))))]
2949   ""
2950   "<su>div\\t%w0, %w1, %w2"
2951   [(set_attr "type" "<su>div")]
2954 ;; -------------------------------------------------------------------
2955 ;; Comparison insns
2956 ;; -------------------------------------------------------------------
2958 (define_insn "cmp<mode>"
2959   [(set (reg:CC CC_REGNUM)
2960         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2961                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2962   ""
2963   "@
2964    cmp\\t%<w>0, %<w>1
2965    cmp\\t%<w>0, %1
2966    cmn\\t%<w>0, #%n1"
2967   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2970 (define_insn "fcmp<mode>"
2971   [(set (reg:CCFP CC_REGNUM)
2972         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2973                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2974    "TARGET_FLOAT"
2975    "@
2976     fcmp\\t%<s>0, #0.0
2977     fcmp\\t%<s>0, %<s>1"
2978   [(set_attr "type" "fcmp<s>")]
2981 (define_insn "fcmpe<mode>"
2982   [(set (reg:CCFPE CC_REGNUM)
2983         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2984                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2985    "TARGET_FLOAT"
2986    "@
2987     fcmpe\\t%<s>0, #0.0
2988     fcmpe\\t%<s>0, %<s>1"
2989   [(set_attr "type" "fcmp<s>")]
2992 (define_insn "*cmp_swp_<shift>_reg<mode>"
2993   [(set (reg:CC_SWP CC_REGNUM)
2994         (compare:CC_SWP (ASHIFT:GPI
2995                          (match_operand:GPI 0 "register_operand" "r")
2996                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2997                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2998   ""
2999   "cmp\\t%<w>2, %<w>0, <shift> %1"
3000   [(set_attr "type" "alus_shift_imm")]
3003 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3004   [(set (reg:CC_SWP CC_REGNUM)
3005         (compare:CC_SWP (ANY_EXTEND:GPI
3006                          (match_operand:ALLX 0 "register_operand" "r"))
3007                         (match_operand:GPI 1 "register_operand" "r")))]
3008   ""
3009   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3010   [(set_attr "type" "alus_ext")]
3013 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3014   [(set (reg:CC_SWP CC_REGNUM)
3015         (compare:CC_SWP (ashift:GPI
3016                          (ANY_EXTEND:GPI
3017                           (match_operand:ALLX 0 "register_operand" "r"))
3018                          (match_operand 1 "aarch64_imm3" "Ui3"))
3019         (match_operand:GPI 2 "register_operand" "r")))]
3020   ""
3021   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3022   [(set_attr "type" "alus_ext")]
3025 ;; -------------------------------------------------------------------
3026 ;; Store-flag and conditional select insns
3027 ;; -------------------------------------------------------------------
3029 (define_expand "cstore<mode>4"
3030   [(set (match_operand:SI 0 "register_operand" "")
3031         (match_operator:SI 1 "aarch64_comparison_operator"
3032          [(match_operand:GPI 2 "register_operand" "")
3033           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3034   ""
3035   "
3036   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3037                                       operands[3]);
3038   operands[3] = const0_rtx;
3039   "
3042 (define_expand "cstorecc4"
3043   [(set (match_operand:SI 0 "register_operand")
3044        (match_operator 1 "aarch64_comparison_operator_mode"
3045         [(match_operand 2 "cc_register")
3046          (match_operand 3 "const0_operand")]))]
3047   ""
3049   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3050   DONE;
3054 (define_expand "cstore<mode>4"
3055   [(set (match_operand:SI 0 "register_operand" "")
3056         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3057          [(match_operand:GPF 2 "register_operand" "")
3058           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3059   ""
3060   "
3061   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3062                                       operands[3]);
3063   operands[3] = const0_rtx;
3064   "
3067 (define_insn "aarch64_cstore<mode>"
3068   [(set (match_operand:ALLI 0 "register_operand" "=r")
3069         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3070          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3071   ""
3072   "cset\\t%<w>0, %m1"
3073   [(set_attr "type" "csel")]
3076 ;; For a 24-bit immediate CST we can optimize the compare for equality
3077 ;; and branch sequence from:
3078 ;;      mov     x0, #imm1
3079 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3080 ;;      cmp     x1, x0
3081 ;;      cset    x2, <ne,eq>
3082 ;; into the shorter:
3083 ;;      sub     x0, x1, #(CST & 0xfff000)
3084 ;;      subs    x0, x0, #(CST & 0x000fff)
3085 ;;      cset x2, <ne, eq>.
3086 (define_insn_and_split "*compare_cstore<mode>_insn"
3087   [(set (match_operand:GPI 0 "register_operand" "=r")
3088          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3089                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3090   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3091    && !aarch64_plus_operand (operands[2], <MODE>mode)
3092    && !reload_completed"
3093   "#"
3094   "&& true"
3095   [(const_int 0)]
3096   {
3097     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3098     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3099     rtx tmp = gen_reg_rtx (<MODE>mode);
3100     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3101     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3102     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3103     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3104     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3105     DONE;
3106   }
3107   [(set_attr "type" "csel")]
3110 ;; zero_extend version of the above
3111 (define_insn "*cstoresi_insn_uxtw"
3112   [(set (match_operand:DI 0 "register_operand" "=r")
3113         (zero_extend:DI
3114          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3115           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3116   ""
3117   "cset\\t%w0, %m1"
3118   [(set_attr "type" "csel")]
3121 (define_insn "cstore<mode>_neg"
3122   [(set (match_operand:ALLI 0 "register_operand" "=r")
3123         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3124                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3125   ""
3126   "csetm\\t%<w>0, %m1"
3127   [(set_attr "type" "csel")]
3130 ;; zero_extend version of the above
3131 (define_insn "*cstoresi_neg_uxtw"
3132   [(set (match_operand:DI 0 "register_operand" "=r")
3133         (zero_extend:DI
3134          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3135                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3136   ""
3137   "csetm\\t%w0, %m1"
3138   [(set_attr "type" "csel")]
3141 (define_expand "cmov<mode>6"
3142   [(set (match_operand:GPI 0 "register_operand" "")
3143         (if_then_else:GPI
3144          (match_operator 1 "aarch64_comparison_operator"
3145           [(match_operand:GPI 2 "register_operand" "")
3146            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3147          (match_operand:GPI 4 "register_operand" "")
3148          (match_operand:GPI 5 "register_operand" "")))]
3149   ""
3150   "
3151   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3152                                       operands[3]);
3153   operands[3] = const0_rtx;
3154   "
3157 (define_expand "cmov<mode>6"
3158   [(set (match_operand:GPF 0 "register_operand" "")
3159         (if_then_else:GPF
3160          (match_operator 1 "aarch64_comparison_operator"
3161           [(match_operand:GPF 2 "register_operand" "")
3162            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3163          (match_operand:GPF 4 "register_operand" "")
3164          (match_operand:GPF 5 "register_operand" "")))]
3165   ""
3166   "
3167   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3168                                       operands[3]);
3169   operands[3] = const0_rtx;
3170   "
3173 (define_insn "*cmov<mode>_insn"
3174   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3175         (if_then_else:ALLI
3176          (match_operator 1 "aarch64_comparison_operator"
3177           [(match_operand 2 "cc_register" "") (const_int 0)])
3178          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3179          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3180   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3181      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3182   ;; Final two alternatives should be unreachable, but included for completeness
3183   "@
3184    csel\\t%<w>0, %<w>3, %<w>4, %m1
3185    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3186    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3187    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3188    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3189    mov\\t%<w>0, -1
3190    mov\\t%<w>0, 1"
3191   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3194 ;; zero_extend version of above
3195 (define_insn "*cmovsi_insn_uxtw"
3196   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3197         (zero_extend:DI
3198          (if_then_else:SI
3199           (match_operator 1 "aarch64_comparison_operator"
3200            [(match_operand 2 "cc_register" "") (const_int 0)])
3201           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3202           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3203   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3204      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3205   ;; Final two alternatives should be unreachable, but included for completeness
3206   "@
3207    csel\\t%w0, %w3, %w4, %m1
3208    csinv\\t%w0, %w3, wzr, %m1
3209    csinv\\t%w0, %w4, wzr, %M1
3210    csinc\\t%w0, %w3, wzr, %m1
3211    csinc\\t%w0, %w4, wzr, %M1
3212    mov\\t%w0, -1
3213    mov\\t%w0, 1"
3214   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3217 (define_insn "*cmovdi_insn_uxtw"
3218   [(set (match_operand:DI 0 "register_operand" "=r")
3219         (if_then_else:DI
3220          (match_operator 1 "aarch64_comparison_operator"
3221           [(match_operand 2 "cc_register" "") (const_int 0)])
3222          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3223          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3224   ""
3225   "csel\\t%w0, %w3, %w4, %m1"
3226   [(set_attr "type" "csel")]
3229 (define_insn "*cmov<mode>_insn"
3230   [(set (match_operand:GPF 0 "register_operand" "=w")
3231         (if_then_else:GPF
3232          (match_operator 1 "aarch64_comparison_operator"
3233           [(match_operand 2 "cc_register" "") (const_int 0)])
3234          (match_operand:GPF 3 "register_operand" "w")
3235          (match_operand:GPF 4 "register_operand" "w")))]
3236   "TARGET_FLOAT"
3237   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3238   [(set_attr "type" "fcsel")]
3241 (define_expand "mov<mode>cc"
3242   [(set (match_operand:ALLI 0 "register_operand" "")
3243         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3244                            (match_operand:ALLI 2 "register_operand" "")
3245                            (match_operand:ALLI 3 "register_operand" "")))]
3246   ""
3247   {
3248     rtx ccreg;
3249     enum rtx_code code = GET_CODE (operands[1]);
3251     if (code == UNEQ || code == LTGT)
3252       FAIL;
3254     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3255                                      XEXP (operands[1], 1));
3256     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3257   }
3260 (define_expand "mov<GPF:mode><GPI:mode>cc"
3261   [(set (match_operand:GPI 0 "register_operand" "")
3262         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3263                           (match_operand:GPF 2 "register_operand" "")
3264                           (match_operand:GPF 3 "register_operand" "")))]
3265   ""
3266   {
3267     rtx ccreg;
3268     enum rtx_code code = GET_CODE (operands[1]);
3270     if (code == UNEQ || code == LTGT)
3271       FAIL;
3273     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3274                                   XEXP (operands[1], 1));
3275     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3276   }
3279 (define_expand "mov<mode>cc"
3280   [(set (match_operand:GPF 0 "register_operand" "")
3281         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3282                           (match_operand:GPF 2 "register_operand" "")
3283                           (match_operand:GPF 3 "register_operand" "")))]
3284   ""
3285   {
3286     rtx ccreg;
3287     enum rtx_code code = GET_CODE (operands[1]);
3289     if (code == UNEQ || code == LTGT)
3290       FAIL;
3292     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3293                                   XEXP (operands[1], 1));
3294     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3295   }
3298 (define_expand "<neg_not_op><mode>cc"
3299   [(set (match_operand:GPI 0 "register_operand" "")
3300         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3301                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3302                           (match_operand:GPI 3 "register_operand" "")))]
3303   ""
3304   {
3305     rtx ccreg;
3306     enum rtx_code code = GET_CODE (operands[1]);
3308     if (code == UNEQ || code == LTGT)
3309       FAIL;
3311     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3312                                       XEXP (operands[1], 1));
3313     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3314   }
3317 ;; CRC32 instructions.
3318 (define_insn "aarch64_<crc_variant>"
3319   [(set (match_operand:SI 0 "register_operand" "=r")
3320         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3321                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3322          CRC))]
3323   "TARGET_CRC32"
3324   {
3325     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3326       return "<crc_variant>\\t%w0, %w1, %x2";
3327     else
3328       return "<crc_variant>\\t%w0, %w1, %w2";
3329   }
3330   [(set_attr "type" "crc")]
3333 (define_insn "*csinc2<mode>_insn"
3334   [(set (match_operand:GPI 0 "register_operand" "=r")
3335         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3336                   (match_operand:GPI 1 "register_operand" "r")))]
3337   ""
3338   "cinc\\t%<w>0, %<w>1, %m2"
3339   [(set_attr "type" "csel")]
3342 (define_insn "csinc3<mode>_insn"
3343   [(set (match_operand:GPI 0 "register_operand" "=r")
3344         (if_then_else:GPI
3345           (match_operand 1 "aarch64_comparison_operation" "")
3346           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3347                     (const_int 1))
3348           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3349   ""
3350   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3351   [(set_attr "type" "csel")]
3354 (define_insn "*csinv3<mode>_insn"
3355   [(set (match_operand:GPI 0 "register_operand" "=r")
3356         (if_then_else:GPI
3357           (match_operand 1 "aarch64_comparison_operation" "")
3358           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3359           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3360   ""
3361   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3362   [(set_attr "type" "csel")]
3365 (define_insn "csneg3_uxtw_insn"
3366   [(set (match_operand:DI 0 "register_operand" "=r")
3367         (zero_extend:DI
3368           (if_then_else:SI
3369             (match_operand 1 "aarch64_comparison_operation" "")
3370             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3371             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3372   ""
3373   "csneg\\t%w0, %w3, %w2, %M1"
3374   [(set_attr "type" "csel")]
3377 (define_insn "csneg3<mode>_insn"
3378   [(set (match_operand:GPI 0 "register_operand" "=r")
3379         (if_then_else:GPI
3380           (match_operand 1 "aarch64_comparison_operation" "")
3381           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3382           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3383   ""
3384   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3385   [(set_attr "type" "csel")]
3388 ;; -------------------------------------------------------------------
3389 ;; Logical operations
3390 ;; -------------------------------------------------------------------
3393 (define_insn_and_split "*aarch64_and<mode>_imm2"
3394   [(set (match_operand:GPI 0 "register_operand" "=rk")
3395         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3396                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3397   ""
3398   "#"
3399   "true"
3400   [(const_int 0)]
3401   {
3402      HOST_WIDE_INT val = INTVAL (operands[2]);
3403      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3404      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3406      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3407      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3408      DONE;
3409   }
3412 (define_insn "<optab><mode>3"
3413   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3414         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3415                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3416   ""
3417   "@
3418   <logical>\\t%<w>0, %<w>1, %<w>2
3419   <logical>\\t%<w>0, %<w>1, %2
3420   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3421   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3422    (set_attr "simd" "*,*,yes")]
3425 ;; zero_extend version of above
3426 (define_insn "*<optab>si3_uxtw"
3427   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3428         (zero_extend:DI
3429          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3430                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3431   ""
3432   "@
3433    <logical>\\t%w0, %w1, %w2
3434    <logical>\\t%w0, %w1, %2"
3435   [(set_attr "type" "logic_reg,logic_imm")]
3438 (define_insn "*and<mode>3_compare0"
3439   [(set (reg:CC_NZ CC_REGNUM)
3440         (compare:CC_NZ
3441          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3442                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3443          (const_int 0)))
3444    (set (match_operand:GPI 0 "register_operand" "=r,r")
3445         (and:GPI (match_dup 1) (match_dup 2)))]
3446   ""
3447   "@
3448    ands\\t%<w>0, %<w>1, %<w>2
3449    ands\\t%<w>0, %<w>1, %2"
3450   [(set_attr "type" "logics_reg,logics_imm")]
3453 ;; zero_extend version of above
3454 (define_insn "*andsi3_compare0_uxtw"
3455   [(set (reg:CC_NZ CC_REGNUM)
3456         (compare:CC_NZ
3457          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3458                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3459          (const_int 0)))
3460    (set (match_operand:DI 0 "register_operand" "=r,r")
3461         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3462   ""
3463   "@
3464    ands\\t%w0, %w1, %w2
3465    ands\\t%w0, %w1, %2"
3466   [(set_attr "type" "logics_reg,logics_imm")]
3469 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3470   [(set (reg:CC_NZ CC_REGNUM)
3471         (compare:CC_NZ
3472          (and:GPI (SHIFT:GPI
3473                    (match_operand:GPI 1 "register_operand" "r")
3474                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3475                   (match_operand:GPI 3 "register_operand" "r"))
3476          (const_int 0)))
3477    (set (match_operand:GPI 0 "register_operand" "=r")
3478         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3479   ""
3480   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3481   [(set_attr "type" "logics_shift_imm")]
3484 ;; zero_extend version of above
3485 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3486   [(set (reg:CC_NZ CC_REGNUM)
3487         (compare:CC_NZ
3488          (and:SI (SHIFT:SI
3489                   (match_operand:SI 1 "register_operand" "r")
3490                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3491                  (match_operand:SI 3 "register_operand" "r"))
3492          (const_int 0)))
3493    (set (match_operand:DI 0 "register_operand" "=r")
3494         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3495                                 (match_dup 3))))]
3496   ""
3497   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3498   [(set_attr "type" "logics_shift_imm")]
3501 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3502   [(set (match_operand:GPI 0 "register_operand" "=r")
3503         (LOGICAL:GPI (SHIFT:GPI
3504                       (match_operand:GPI 1 "register_operand" "r")
3505                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3506                      (match_operand:GPI 3 "register_operand" "r")))]
3507   ""
3508   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3509   [(set_attr "type" "logic_shift_imm")]
3512 (define_insn "*<optab>_rol<mode>3"
3513   [(set (match_operand:GPI 0 "register_operand" "=r")
3514         (LOGICAL:GPI (rotate:GPI
3515                       (match_operand:GPI 1 "register_operand" "r")
3516                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3517                      (match_operand:GPI 3 "register_operand" "r")))]
3518   ""
3519   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3520   [(set_attr "type" "logic_shift_imm")]
3523 ;; zero_extend versions of above
3524 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3525   [(set (match_operand:DI 0 "register_operand" "=r")
3526         (zero_extend:DI
3527          (LOGICAL:SI (SHIFT:SI
3528                       (match_operand:SI 1 "register_operand" "r")
3529                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3530                      (match_operand:SI 3 "register_operand" "r"))))]
3531   ""
3532   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3533   [(set_attr "type" "logic_shift_imm")]
3536 (define_insn "*<optab>_rolsi3_uxtw"
3537   [(set (match_operand:DI 0 "register_operand" "=r")
3538         (zero_extend:DI
3539          (LOGICAL:SI (rotate:SI
3540                       (match_operand:SI 1 "register_operand" "r")
3541                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3542                      (match_operand:SI 3 "register_operand" "r"))))]
3543   ""
3544   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3545   [(set_attr "type" "logic_shift_imm")]
3548 (define_insn "one_cmpl<mode>2"
3549   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3550         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3551   ""
3552   "@
3553   mvn\\t%<w>0, %<w>1
3554   mvn\\t%0.8b, %1.8b"
3555   [(set_attr "type" "logic_reg,neon_logic")
3556    (set_attr "simd" "*,yes")]
3559 (define_insn "*one_cmpl_<optab><mode>2"
3560   [(set (match_operand:GPI 0 "register_operand" "=r")
3561         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3562                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3563   ""
3564   "mvn\\t%<w>0, %<w>1, <shift> %2"
3565   [(set_attr "type" "logic_shift_imm")]
3568 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3570 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3571   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3572         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3573                      (match_operand:GPI 2 "register_operand" "r,w")))]
3574   ""
3575   "@
3576   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3577   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3578   [(set_attr "type" "logic_reg,neon_logic")
3579    (set_attr "simd" "*,yes")]
3582 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3583   [(set (match_operand:DI 0 "register_operand" "=r")
3584         (zero_extend:DI
3585           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3586                        (match_operand:SI 2 "register_operand" "r"))))]
3587   ""
3588   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3589   [(set_attr "type" "logic_reg")]
3592 (define_insn "*xor_one_cmplsidi3_ze"
3593   [(set (match_operand:DI 0 "register_operand" "=r")
3594         (zero_extend:DI
3595           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3596                           (match_operand:SI 2 "register_operand" "r")))))]
3597   ""
3598   "eon\\t%w0, %w1, %w2"
3599   [(set_attr "type" "logic_reg")]
3602 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3603 ;; eon does not operate on SIMD registers so the vector variant must be split.
3604 (define_insn_and_split "*xor_one_cmpl<mode>3"
3605   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3606         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3607                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3608   ""
3609   "@
3610   eon\\t%<w>0, %<w>1, %<w>2
3611   #"
3612   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3613   [(set (match_operand:GPI 0 "register_operand" "=w")
3614         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3615                  (match_operand:GPI 2 "register_operand" "w")))
3616    (set (match_dup 0) (not:GPI (match_dup 0)))]
3617   ""
3618   [(set_attr "type" "logic_reg,multiple")
3619    (set_attr "simd" "*,yes")]
3622 (define_insn "*and_one_cmpl<mode>3_compare0"
3623   [(set (reg:CC_NZ CC_REGNUM)
3624         (compare:CC_NZ
3625          (and:GPI (not:GPI
3626                    (match_operand:GPI 1 "register_operand" "r"))
3627                   (match_operand:GPI 2 "register_operand" "r"))
3628          (const_int 0)))
3629    (set (match_operand:GPI 0 "register_operand" "=r")
3630         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3631   ""
3632   "bics\\t%<w>0, %<w>2, %<w>1"
3633   [(set_attr "type" "logics_reg")]
3636 ;; zero_extend version of above
3637 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3638   [(set (reg:CC_NZ CC_REGNUM)
3639         (compare:CC_NZ
3640          (and:SI (not:SI
3641                   (match_operand:SI 1 "register_operand" "r"))
3642                  (match_operand:SI 2 "register_operand" "r"))
3643          (const_int 0)))
3644    (set (match_operand:DI 0 "register_operand" "=r")
3645         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3646   ""
3647   "bics\\t%w0, %w2, %w1"
3648   [(set_attr "type" "logics_reg")]
3651 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3652   [(set (reg:CC_NZ CC_REGNUM)
3653     (compare:CC_NZ
3654      (and:GPI (not:GPI
3655            (match_operand:GPI 0 "register_operand" "r"))
3656           (match_operand:GPI 1 "register_operand" "r"))
3657      (const_int 0)))]
3658   ""
3659   "bics\\t<w>zr, %<w>1, %<w>0"
3660   [(set_attr "type" "logics_reg")]
3663 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3664   [(set (match_operand:GPI 0 "register_operand" "=r")
3665         (LOGICAL:GPI (not:GPI
3666                       (SHIFT:GPI
3667                        (match_operand:GPI 1 "register_operand" "r")
3668                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3669                      (match_operand:GPI 3 "register_operand" "r")))]
3670   ""
3671   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3672   [(set_attr "type" "logic_shift_imm")]
3675 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3676   [(set (match_operand:GPI 0 "register_operand" "=r")
3677         (not:GPI (xor:GPI
3678                       (SHIFT:GPI
3679                        (match_operand:GPI 1 "register_operand" "r")
3680                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3681                      (match_operand:GPI 3 "register_operand" "r"))))]
3682   ""
3683   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3684   [(set_attr "type" "logic_shift_imm")]
3687 ;; Zero-extend version of the above.
3688 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3689   [(set (match_operand:DI 0 "register_operand" "=r")
3690         (zero_extend:DI
3691           (not:SI (xor:SI
3692                     (SHIFT:SI
3693                       (match_operand:SI 1 "register_operand" "r")
3694                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3695                     (match_operand:SI 3 "register_operand" "r")))))]
3696   ""
3697   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3698   [(set_attr "type" "logic_shift_imm")]
3701 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3702   [(set (reg:CC_NZ CC_REGNUM)
3703         (compare:CC_NZ
3704          (and:GPI (not:GPI
3705                    (SHIFT:GPI
3706                     (match_operand:GPI 1 "register_operand" "r")
3707                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3708                   (match_operand:GPI 3 "register_operand" "r"))
3709          (const_int 0)))
3710    (set (match_operand:GPI 0 "register_operand" "=r")
3711         (and:GPI (not:GPI
3712                   (SHIFT:GPI
3713                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3714   ""
3715   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3716   [(set_attr "type" "logics_shift_imm")]
3719 ;; zero_extend version of above
3720 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3721   [(set (reg:CC_NZ CC_REGNUM)
3722         (compare:CC_NZ
3723          (and:SI (not:SI
3724                   (SHIFT:SI
3725                    (match_operand:SI 1 "register_operand" "r")
3726                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3727                  (match_operand:SI 3 "register_operand" "r"))
3728          (const_int 0)))
3729    (set (match_operand:DI 0 "register_operand" "=r")
3730         (zero_extend:DI (and:SI
3731                          (not:SI
3732                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3733   ""
3734   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3735   [(set_attr "type" "logics_shift_imm")]
3738 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3739   [(set (reg:CC_NZ CC_REGNUM)
3740     (compare:CC_NZ
3741      (and:GPI (not:GPI
3742            (SHIFT:GPI
3743             (match_operand:GPI 0 "register_operand" "r")
3744             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3745           (match_operand:GPI 2 "register_operand" "r"))
3746      (const_int 0)))]
3747   ""
3748   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3749   [(set_attr "type" "logics_shift_imm")]
3752 (define_insn "clz<mode>2"
3753   [(set (match_operand:GPI 0 "register_operand" "=r")
3754         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3755   ""
3756   "clz\\t%<w>0, %<w>1"
3757   [(set_attr "type" "clz")]
3760 (define_expand "ffs<mode>2"
3761   [(match_operand:GPI 0 "register_operand")
3762    (match_operand:GPI 1 "register_operand")]
3763   ""
3764   {
3765     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3766     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3768     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3769     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3770     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3771     DONE;
3772   }
3775 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3777 ;; MOV  v.1d, x0
3778 ;; CNT  v1.8b, v.8b
3779 ;; ADDV b2, v1.8b
3780 ;; MOV  w0, v2.b[0]
3782 (define_expand "popcount<mode>2"
3783   [(match_operand:GPI 0 "register_operand")
3784    (match_operand:GPI 1 "register_operand")]
3785   "TARGET_SIMD"
3787   rtx v = gen_reg_rtx (V8QImode);
3788   rtx v1 = gen_reg_rtx (V8QImode);
3789   rtx r = gen_reg_rtx (QImode);
3790   rtx in = operands[1];
3791   rtx out = operands[0];
3792   if(<MODE>mode == SImode)
3793     {
3794       rtx tmp;
3795       tmp = gen_reg_rtx (DImode);
3796       /* If we have SImode, zero extend to DImode, pop count does
3797          not change if we have extra zeros. */
3798       emit_insn (gen_zero_extendsidi2 (tmp, in));
3799       in = tmp;
3800     }
3801   emit_move_insn (v, gen_lowpart (V8QImode, in));
3802   emit_insn (gen_popcountv8qi2 (v1, v));
3803   emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3804   emit_insn (gen_zero_extendqi<mode>2 (out, r));
3805   DONE;
3808 (define_insn "clrsb<mode>2"
3809   [(set (match_operand:GPI 0 "register_operand" "=r")
3810         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3811   ""
3812   "cls\\t%<w>0, %<w>1"
3813   [(set_attr "type" "clz")]
3816 (define_insn "rbit<mode>2"
3817   [(set (match_operand:GPI 0 "register_operand" "=r")
3818         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3819   ""
3820   "rbit\\t%<w>0, %<w>1"
3821   [(set_attr "type" "rbit")]
3824 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3825 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3826 ;; expression and split after reload to enable scheduling them apart if
3827 ;; needed.
3829 (define_insn_and_split "ctz<mode>2"
3830  [(set (match_operand:GPI           0 "register_operand" "=r")
3831        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3832   ""
3833   "#"
3834   "reload_completed"
3835   [(const_int 0)]
3836   "
3837   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3838   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3839   DONE;
3842 (define_insn "*and<mode>_compare0"
3843   [(set (reg:CC_NZ CC_REGNUM)
3844         (compare:CC_NZ
3845          (match_operand:SHORT 0 "register_operand" "r")
3846          (const_int 0)))]
3847   ""
3848   "tst\\t%<w>0, <short_mask>"
3849   [(set_attr "type" "alus_imm")]
3852 (define_insn "*ands<mode>_compare0"
3853   [(set (reg:CC_NZ CC_REGNUM)
3854         (compare:CC_NZ
3855          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3856          (const_int 0)))
3857    (set (match_operand:GPI 0 "register_operand" "=r")
3858         (zero_extend:GPI (match_dup 1)))]
3859   ""
3860   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3861   [(set_attr "type" "alus_imm")]
3864 (define_insn "*and<mode>3nr_compare0"
3865   [(set (reg:CC_NZ CC_REGNUM)
3866         (compare:CC_NZ
3867          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3868                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3869          (const_int 0)))]
3870   ""
3871   "@
3872    tst\\t%<w>0, %<w>1
3873    tst\\t%<w>0, %1"
3874   [(set_attr "type" "logics_reg,logics_imm")]
3877 (define_split
3878   [(set (reg:CC_NZ CC_REGNUM)
3879         (compare:CC_NZ
3880          (and:GPI (match_operand:GPI 0 "register_operand")
3881                   (match_operand:GPI 1 "aarch64_mov_imm_operand"))
3882          (const_int 0)))
3883    (clobber (match_operand:SI 2 "register_operand"))]
3884   ""
3885   [(set (match_dup 2) (match_dup 1))
3886    (set (reg:CC_NZ CC_REGNUM)
3887         (compare:CC_NZ
3888          (and:GPI (match_dup 0)
3889                   (match_dup 2))
3890          (const_int 0)))]
3893 (define_insn "*and<mode>3nr_compare0_zextract"
3894   [(set (reg:CC_NZ CC_REGNUM)
3895         (compare:CC_NZ
3896          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3897                   (match_operand:GPI 1 "const_int_operand" "n")
3898                   (match_operand:GPI 2 "const_int_operand" "n"))
3899          (const_int 0)))]
3900   "INTVAL (operands[1]) > 0
3901    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3902         <= GET_MODE_BITSIZE (<MODE>mode))
3903    && aarch64_bitmask_imm (
3904         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3905                                                  operands[2])),
3906         <MODE>mode)"
3907   {
3908     operands[1]
3909       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3910     return "tst\\t%<w>0, %1";
3911   }
3912   [(set_attr "type" "logics_shift_imm")]
3915 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3916   [(set (reg:CC_NZ CC_REGNUM)
3917         (compare:CC_NZ
3918          (and:GPI (SHIFT:GPI
3919                    (match_operand:GPI 0 "register_operand" "r")
3920                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3921                   (match_operand:GPI 2 "register_operand" "r"))
3922         (const_int 0)))]
3923   ""
3924   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3925   [(set_attr "type" "logics_shift_imm")]
3928 (define_split
3929   [(set (reg:CC_NZ CC_REGNUM)
3930         (compare:CC_NZ
3931          (and:GPI (SHIFT:GPI
3932                    (match_operand:GPI 0 "register_operand")
3933                    (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
3934                   (match_operand:GPI 2 "aarch64_mov_imm_operand"))
3935         (const_int 0)))
3936     (clobber (match_operand:SI 3 "register_operand"))]
3937   ""
3938   [(set (match_dup 3) (match_dup 2))
3939    (set (reg:CC_NZ CC_REGNUM)
3940         (compare:CC_NZ
3941          (and:GPI (SHIFT:GPI
3942                    (match_dup 0)
3943                    (match_dup 1))
3944                   (match_dup 3))
3945          (const_int 0)))]
3948 ;; -------------------------------------------------------------------
3949 ;; Shifts
3950 ;; -------------------------------------------------------------------
3952 (define_expand "<optab><mode>3"
3953   [(set (match_operand:GPI 0 "register_operand")
3954         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3955                     (match_operand:QI 2 "nonmemory_operand")))]
3956   ""
3957   {
3958     if (CONST_INT_P (operands[2]))
3959       {
3960         operands[2] = GEN_INT (INTVAL (operands[2])
3961                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3963         if (operands[2] == const0_rtx)
3964           {
3965             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3966             DONE;
3967           }
3968       }
3969   }
3972 (define_expand "ashl<mode>3"
3973   [(set (match_operand:SHORT 0 "register_operand")
3974         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3975                       (match_operand:QI 2 "const_int_operand")))]
3976   ""
3977   {
3978     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3980     if (operands[2] == const0_rtx)
3981       {
3982         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3983         DONE;
3984       }
3985   }
3988 (define_expand "rotr<mode>3"
3989   [(set (match_operand:GPI 0 "register_operand")
3990         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3991                       (match_operand:QI 2 "nonmemory_operand")))]
3992   ""
3993   {
3994     if (CONST_INT_P (operands[2]))
3995       {
3996         operands[2] = GEN_INT (INTVAL (operands[2])
3997                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3999         if (operands[2] == const0_rtx)
4000           {
4001             emit_insn (gen_mov<mode> (operands[0], operands[1]));
4002             DONE;
4003           }
4004       }
4005   }
4008 (define_expand "rotl<mode>3"
4009   [(set (match_operand:GPI 0 "register_operand")
4010         (rotatert:GPI (match_operand:GPI 1 "register_operand")
4011                       (match_operand:QI 2 "nonmemory_operand")))]
4012   ""
4013   {
4014     /* (SZ - cnt) % SZ == -cnt % SZ */
4015     if (CONST_INT_P (operands[2]))
4016       {
4017         operands[2] = GEN_INT ((-INTVAL (operands[2]))
4018                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4019         if (operands[2] == const0_rtx)
4020           {
4021             emit_insn (gen_mov<mode> (operands[0], operands[1]));
4022             DONE;
4023           }
4024       }
4025     else
4026       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4027                                         NULL_RTX, 1);
4028   }
4031 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4032 ;; they truncate the shift/rotate amount by the size of the registers they
4033 ;; operate on: 32 for W-regs, 64 for X-regs.  This allows us to optimise away
4034 ;; such redundant masking instructions.  GCC can do that automatically when
4035 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4036 ;; because some of the SISD shift alternatives don't perform this truncations.
4037 ;; So this pattern exists to catch such cases.
4039 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4040   [(set (match_operand:GPI 0 "register_operand" "=r")
4041         (SHIFT:GPI
4042           (match_operand:GPI 1 "register_operand" "r")
4043           (match_operator 4 "subreg_lowpart_operator"
4044            [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4045                      (match_operand 3 "const_int_operand" "n"))])))]
4046   "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4047   "<shift>\t%<w>0, %<w>1, %<w>2"
4048   [(set_attr "type" "shift_reg")]
4051 (define_insn_and_split "*aarch64_reg_<mode>3_neg_mask2"
4052   [(set (match_operand:GPI 0 "register_operand" "=&r")
4053         (SHIFT:GPI
4054           (match_operand:GPI 1 "register_operand" "r")
4055           (match_operator 4 "subreg_lowpart_operator"
4056           [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4057                            (match_operand 3 "const_int_operand" "n")))])))]
4058   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4059   "#"
4060   "&& true"
4061   [(const_int 0)]
4062   {
4063     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4064                : operands[0]);
4065     emit_insn (gen_negsi2 (tmp, operands[2]));
4067     rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4068     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4069                                      SUBREG_BYTE (operands[4]));
4070     emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4071     DONE;
4072   }
4075 (define_insn_and_split "*aarch64_reg_<mode>3_minus_mask"
4076   [(set (match_operand:GPI 0 "register_operand" "=&r")
4077         (ashift:GPI
4078           (match_operand:GPI 1 "register_operand" "r")
4079           (minus:QI (match_operand 2 "const_int_operand" "n")
4080                     (match_operator 5 "subreg_lowpart_operator"
4081                     [(and:SI (match_operand:SI 3 "register_operand" "r")
4082                              (match_operand 4 "const_int_operand" "n"))]))))]
4083   "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4084    && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4085   "#"
4086   "&& true"
4087   [(const_int 0)]
4088   {
4089     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4090                : operands[0]);
4092     emit_insn (gen_negsi2 (tmp, operands[3]));
4094     rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
4095     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
4096                                      SUBREG_BYTE (operands[5]));
4098     emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
4099     DONE;
4100   }
4103 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4104   [(set (match_operand:DI 0 "register_operand" "=r")
4105         (SHIFT:DI
4106           (match_operand:DI 1 "register_operand" "r")
4107           (match_operator 4 "subreg_lowpart_operator"
4108            [(and:SI (match_operand:SI 2 "register_operand" "r")
4109                      (match_operand 3 "aarch64_shift_imm_di" "Usd"))])))]
4110   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1)) == 0)"
4112   rtx xop[3];
4113   xop[0] = operands[0];
4114   xop[1] = operands[1];
4115   xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
4116   output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
4117   return "";
4119   [(set_attr "type" "shift_reg")]
4122 ;; Logical left shift using SISD or Integer instruction
4123 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4124   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4125         (ashift:GPI
4126           (match_operand:GPI 1 "register_operand" "r,r,w,w")
4127           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4128   ""
4129   "@
4130    lsl\t%<w>0, %<w>1, %2
4131    lsl\t%<w>0, %<w>1, %<w>2
4132    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4133    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4134   [(set_attr "simd" "no,no,yes,yes")
4135    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4138 ;; Logical right shift using SISD or Integer instruction
4139 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4140   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4141         (lshiftrt:GPI
4142          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4143          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
4144   ""
4145   "@
4146    lsr\t%<w>0, %<w>1, %2
4147    lsr\t%<w>0, %<w>1, %<w>2
4148    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4149    #
4150    #"
4151   [(set_attr "simd" "no,no,yes,yes,yes")
4152    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4155 (define_split
4156   [(set (match_operand:DI 0 "aarch64_simd_register")
4157         (lshiftrt:DI
4158            (match_operand:DI 1 "aarch64_simd_register")
4159            (match_operand:QI 2 "aarch64_simd_register")))]
4160   "TARGET_SIMD && reload_completed"
4161   [(set (match_dup 3)
4162         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4163    (set (match_dup 0)
4164         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4165   {
4166     operands[3] = gen_lowpart (QImode, operands[0]);
4167   }
4170 (define_split
4171   [(set (match_operand:SI 0 "aarch64_simd_register")
4172         (lshiftrt:SI
4173            (match_operand:SI 1 "aarch64_simd_register")
4174            (match_operand:QI 2 "aarch64_simd_register")))]
4175   "TARGET_SIMD && reload_completed"
4176   [(set (match_dup 3)
4177         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4178    (set (match_dup 0)
4179         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4180   {
4181     operands[3] = gen_lowpart (QImode, operands[0]);
4182   }
4185 ;; Arithmetic right shift using SISD or Integer instruction
4186 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4187   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4188         (ashiftrt:GPI
4189           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4190           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4191   ""
4192   "@
4193    asr\t%<w>0, %<w>1, %2
4194    asr\t%<w>0, %<w>1, %<w>2
4195    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4196    #
4197    #"
4198   [(set_attr "simd" "no,no,yes,yes,yes")
4199    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4202 (define_split
4203   [(set (match_operand:DI 0 "aarch64_simd_register")
4204         (ashiftrt:DI
4205            (match_operand:DI 1 "aarch64_simd_register")
4206            (match_operand:QI 2 "aarch64_simd_register")))]
4207   "TARGET_SIMD && reload_completed"
4208   [(set (match_dup 3)
4209         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4210    (set (match_dup 0)
4211         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4213   operands[3] = gen_lowpart (QImode, operands[0]);
4217 (define_split
4218   [(set (match_operand:SI 0 "aarch64_simd_register")
4219         (ashiftrt:SI
4220            (match_operand:SI 1 "aarch64_simd_register")
4221            (match_operand:QI 2 "aarch64_simd_register")))]
4222   "TARGET_SIMD && reload_completed"
4223   [(set (match_dup 3)
4224         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4225    (set (match_dup 0)
4226         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4228   operands[3] = gen_lowpart (QImode, operands[0]);
4232 (define_insn "*aarch64_sisd_ushl"
4233   [(set (match_operand:DI 0 "register_operand" "=w")
4234         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4235                     (match_operand:QI 2 "register_operand" "w")]
4236                    UNSPEC_SISD_USHL))]
4237   "TARGET_SIMD"
4238   "ushl\t%d0, %d1, %d2"
4239   [(set_attr "simd" "yes")
4240    (set_attr "type" "neon_shift_reg")]
4243 (define_insn "*aarch64_ushl_2s"
4244   [(set (match_operand:SI 0 "register_operand" "=w")
4245         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4246                     (match_operand:QI 2 "register_operand" "w")]
4247                    UNSPEC_USHL_2S))]
4248   "TARGET_SIMD"
4249   "ushl\t%0.2s, %1.2s, %2.2s"
4250   [(set_attr "simd" "yes")
4251    (set_attr "type" "neon_shift_reg")]
4254 (define_insn "*aarch64_sisd_sshl"
4255   [(set (match_operand:DI 0 "register_operand" "=w")
4256         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4257                     (match_operand:QI 2 "register_operand" "w")]
4258                    UNSPEC_SISD_SSHL))]
4259   "TARGET_SIMD"
4260   "sshl\t%d0, %d1, %d2"
4261   [(set_attr "simd" "yes")
4262    (set_attr "type" "neon_shift_reg")]
4265 (define_insn "*aarch64_sshl_2s"
4266   [(set (match_operand:SI 0 "register_operand" "=w")
4267         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4268                     (match_operand:QI 2 "register_operand" "w")]
4269                    UNSPEC_SSHL_2S))]
4270   "TARGET_SIMD"
4271   "sshl\t%0.2s, %1.2s, %2.2s"
4272   [(set_attr "simd" "yes")
4273    (set_attr "type" "neon_shift_reg")]
4276 (define_insn "*aarch64_sisd_neg_qi"
4277   [(set (match_operand:QI 0 "register_operand" "=w")
4278         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4279                    UNSPEC_SISD_NEG))]
4280   "TARGET_SIMD"
4281   "neg\t%d0, %d1"
4282   [(set_attr "simd" "yes")
4283    (set_attr "type" "neon_neg")]
4286 ;; Rotate right
4287 (define_insn "*ror<mode>3_insn"
4288   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4289      (rotatert:GPI
4290        (match_operand:GPI 1 "register_operand" "r,r")
4291        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4292   ""
4293   "@
4294    ror\\t%<w>0, %<w>1, %2
4295    ror\\t%<w>0, %<w>1, %<w>2"
4296   [(set_attr "type" "rotate_imm,shift_reg")]
4299 ;; zero_extend version of above
4300 (define_insn "*<optab>si3_insn_uxtw"
4301   [(set (match_operand:DI 0 "register_operand" "=r,r")
4302         (zero_extend:DI (SHIFT:SI
4303          (match_operand:SI 1 "register_operand" "r,r")
4304          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4305   ""
4306   "@
4307    <shift>\\t%w0, %w1, %2
4308    <shift>\\t%w0, %w1, %w2"
4309   [(set_attr "type" "bfx,shift_reg")]
4312 (define_insn "*<optab><mode>3_insn"
4313   [(set (match_operand:SHORT 0 "register_operand" "=r")
4314         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4315                       (match_operand 2 "const_int_operand" "n")))]
4316   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4318   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4319   return "<bfshift>\t%w0, %w1, %2, %3";
4321   [(set_attr "type" "bfx")]
4324 (define_insn "*extr<mode>5_insn"
4325   [(set (match_operand:GPI 0 "register_operand" "=r")
4326         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4327                              (match_operand 3 "const_int_operand" "n"))
4328                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4329                                (match_operand 4 "const_int_operand" "n"))))]
4330   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4331    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4332   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4333   [(set_attr "type" "rotate_imm")]
4336 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4337 ;; so we have to match both orderings.
4338 (define_insn "*extr<mode>5_insn_alt"
4339   [(set (match_operand:GPI 0 "register_operand" "=r")
4340         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4341                                 (match_operand 4 "const_int_operand" "n"))
4342                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4343                               (match_operand 3 "const_int_operand" "n"))))]
4344   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4345    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4346        == GET_MODE_BITSIZE (<MODE>mode))"
4347   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4348   [(set_attr "type" "rotate_imm")]
4351 ;; zero_extend version of the above
4352 (define_insn "*extrsi5_insn_uxtw"
4353   [(set (match_operand:DI 0 "register_operand" "=r")
4354         (zero_extend:DI
4355          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4356                             (match_operand 3 "const_int_operand" "n"))
4357                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4358                               (match_operand 4 "const_int_operand" "n")))))]
4359   "UINTVAL (operands[3]) < 32 &&
4360    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4361   "extr\\t%w0, %w1, %w2, %4"
4362   [(set_attr "type" "rotate_imm")]
4365 (define_insn "*extrsi5_insn_uxtw_alt"
4366   [(set (match_operand:DI 0 "register_operand" "=r")
4367         (zero_extend:DI
4368          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4369                                (match_operand 4 "const_int_operand" "n"))
4370                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4371                             (match_operand 3 "const_int_operand" "n")))))]
4372   "UINTVAL (operands[3]) < 32 &&
4373    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4374   "extr\\t%w0, %w1, %w2, %4"
4375   [(set_attr "type" "rotate_imm")]
4378 (define_insn "*ror<mode>3_insn"
4379   [(set (match_operand:GPI 0 "register_operand" "=r")
4380         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4381                     (match_operand 2 "const_int_operand" "n")))]
4382   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4384   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4385   return "ror\\t%<w>0, %<w>1, %3";
4387   [(set_attr "type" "rotate_imm")]
4390 ;; zero_extend version of the above
4391 (define_insn "*rorsi3_insn_uxtw"
4392   [(set (match_operand:DI 0 "register_operand" "=r")
4393         (zero_extend:DI
4394          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4395                     (match_operand 2 "const_int_operand" "n"))))]
4396   "UINTVAL (operands[2]) < 32"
4398   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4399   return "ror\\t%w0, %w1, %3";
4401   [(set_attr "type" "rotate_imm")]
4404 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4405   [(set (match_operand:GPI 0 "register_operand" "=r")
4406         (ANY_EXTEND:GPI
4407          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4408                        (match_operand 2 "const_int_operand" "n"))))]
4409   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4411   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4412   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4414   [(set_attr "type" "bfx")]
4417 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4418   [(set (match_operand:GPI 0 "register_operand" "=r")
4419         (zero_extend:GPI
4420          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4421                          (match_operand 2 "const_int_operand" "n"))))]
4422   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4424   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4425   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4427   [(set_attr "type" "bfx")]
4430 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4431   [(set (match_operand:GPI 0 "register_operand" "=r")
4432         (sign_extend:GPI
4433          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4434                          (match_operand 2 "const_int_operand" "n"))))]
4435   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4437   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4438   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4440   [(set_attr "type" "bfx")]
4443 ;; -------------------------------------------------------------------
4444 ;; Bitfields
4445 ;; -------------------------------------------------------------------
4447 (define_expand "<optab>"
4448   [(set (match_operand:DI 0 "register_operand" "=r")
4449         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4450                         (match_operand 2
4451                           "aarch64_simd_shift_imm_offset_di")
4452                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4453   ""
4454   {
4455     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4456                    1, GET_MODE_BITSIZE (DImode) - 1))
4457      FAIL;
4458   }
4462 (define_insn "*<optab><mode>"
4463   [(set (match_operand:GPI 0 "register_operand" "=r")
4464         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4465                          (match_operand 2
4466                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4467                          (match_operand 3
4468                            "aarch64_simd_shift_imm_<mode>" "n")))]
4469   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4470              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4471   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4472   [(set_attr "type" "bfx")]
4475 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4476 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4477 (define_split
4478   [(set (match_operand:DI 0 "register_operand")
4479         (zero_extract:DI (match_operand:DI 1 "register_operand")
4480                          (match_operand 2
4481                            "aarch64_simd_shift_imm_offset_di")
4482                          (match_operand 3
4483                            "aarch64_simd_shift_imm_di")))]
4484   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4485              GET_MODE_BITSIZE (DImode) - 1)
4486    && (INTVAL (operands[2]) + INTVAL (operands[3]))
4487        == GET_MODE_BITSIZE (SImode)"
4488   [(set (match_dup 0)
4489         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4490   {
4491     operands[4] = gen_lowpart (SImode, operands[1]);
4492   }
4495 ;; Bitfield Insert (insv)
4496 (define_expand "insv<mode>"
4497   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4498                           (match_operand 1 "const_int_operand")
4499                           (match_operand 2 "const_int_operand"))
4500         (match_operand:GPI 3 "general_operand"))]
4501   ""
4503   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4504   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4505   rtx value = operands[3];
4507   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4508     FAIL;
4510   if (CONST_INT_P (value))
4511     {
4512       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4514       /* Prefer AND/OR for inserting all zeros or all ones.  */
4515       if ((UINTVAL (value) & mask) == 0
4516            || (UINTVAL (value) & mask) == mask)
4517         FAIL;
4519       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4520       if (width == 16 && (pos % 16) == 0)
4521         DONE;
4522     }
4523   operands[3] = force_reg (<MODE>mode, value);
4526 (define_insn "*insv_reg<mode>"
4527   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4528                           (match_operand 1 "const_int_operand" "n")
4529                           (match_operand 2 "const_int_operand" "n"))
4530         (match_operand:GPI 3 "register_operand" "r"))]
4531   "!(UINTVAL (operands[1]) == 0
4532      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4533          > GET_MODE_BITSIZE (<MODE>mode)))"
4534   "bfi\\t%<w>0, %<w>3, %2, %1"
4535   [(set_attr "type" "bfm")]
4538 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4539   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4540                           (match_operand 1 "const_int_operand" "n")
4541                           (match_operand 2 "const_int_operand" "n"))
4542         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4543   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4544   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4545   [(set_attr "type" "bfm")]
4548 (define_insn "*extr_insv_lower_reg<mode>"
4549   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4550                           (match_operand 1 "const_int_operand" "n")
4551                           (const_int 0))
4552         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4553                           (match_dup 1)
4554                           (match_operand 3 "const_int_operand" "n")))]
4555   "!(UINTVAL (operands[1]) == 0
4556      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4557          > GET_MODE_BITSIZE (<MODE>mode)))"
4558   "bfxil\\t%<w>0, %<w>2, %3, %1"
4559   [(set_attr "type" "bfm")]
4562 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4563   [(set (match_operand:GPI 0 "register_operand" "=r")
4564         (ashift:GPI (ANY_EXTEND:GPI
4565                      (match_operand:ALLX 1 "register_operand" "r"))
4566                     (match_operand 2 "const_int_operand" "n")))]
4567   "UINTVAL (operands[2]) < <GPI:sizen>"
4569   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4570               ? GEN_INT (<ALLX:sizen>)
4571               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4572   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4574   [(set_attr "type" "bfx")]
4577 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4579 (define_insn "*andim_ashift<mode>_bfiz"
4580   [(set (match_operand:GPI 0 "register_operand" "=r")
4581         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4582                              (match_operand 2 "const_int_operand" "n"))
4583                  (match_operand 3 "const_int_operand" "n")))]
4584   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4585   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4586   [(set_attr "type" "bfx")]
4589 ;; When the bit position and width of the equivalent extraction add up to 32
4590 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4591 ;; zero-extension of the X-reg.
4592 (define_split
4593   [(set (match_operand:DI 0 "register_operand")
4594         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4595                              (match_operand 2 "const_int_operand"))
4596                  (match_operand 3 "const_int_operand")))]
4597  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4598   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4599       == GET_MODE_BITSIZE (SImode)"
4600   [(set (match_dup 0)
4601         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4602   {
4603     operands[4] = gen_lowpart (SImode, operands[1]);
4604   }
4607 (define_insn "bswap<mode>2"
4608   [(set (match_operand:GPI 0 "register_operand" "=r")
4609         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4610   ""
4611   "rev\\t%<w>0, %<w>1"
4612   [(set_attr "type" "rev")]
4615 (define_insn "bswaphi2"
4616   [(set (match_operand:HI 0 "register_operand" "=r")
4617         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4618   ""
4619   "rev16\\t%w0, %w1"
4620   [(set_attr "type" "rev")]
4623 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4624 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4625 ;; each valid permutation.
4627 (define_insn "rev16<mode>2"
4628   [(set (match_operand:GPI 0 "register_operand" "=r")
4629         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4630                                       (const_int 8))
4631                           (match_operand:GPI 3 "const_int_operand" "n"))
4632                  (and:GPI (lshiftrt:GPI (match_dup 1)
4633                                         (const_int 8))
4634                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4635   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4636    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4637   "rev16\\t%<w>0, %<w>1"
4638   [(set_attr "type" "rev")]
4641 (define_insn "rev16<mode>2_alt"
4642   [(set (match_operand:GPI 0 "register_operand" "=r")
4643         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4644                                         (const_int 8))
4645                           (match_operand:GPI 2 "const_int_operand" "n"))
4646                  (and:GPI (ashift:GPI (match_dup 1)
4647                                       (const_int 8))
4648                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4649   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4650    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4651   "rev16\\t%<w>0, %<w>1"
4652   [(set_attr "type" "rev")]
4655 ;; zero_extend version of above
4656 (define_insn "*bswapsi2_uxtw"
4657   [(set (match_operand:DI 0 "register_operand" "=r")
4658         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4659   ""
4660   "rev\\t%w0, %w1"
4661   [(set_attr "type" "rev")]
4664 ;; -------------------------------------------------------------------
4665 ;; Floating-point intrinsics
4666 ;; -------------------------------------------------------------------
4668 ;; frint floating-point round to integral standard patterns.
4669 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4671 (define_insn "<frint_pattern><mode>2"
4672   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4673         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4674          FRINT))]
4675   "TARGET_FLOAT"
4676   "frint<frint_suffix>\\t%<s>0, %<s>1"
4677   [(set_attr "type" "f_rint<stype>")]
4680 ;; frcvt floating-point round to integer and convert standard patterns.
4681 ;; Expands to lbtrunc, lceil, lfloor, lround.
4682 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4683   [(set (match_operand:GPI 0 "register_operand" "=r")
4684         (FIXUORS:GPI
4685           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4686            FCVT)))]
4687   "TARGET_FLOAT"
4688   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4689   [(set_attr "type" "f_cvtf2i")]
4692 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4693   [(set (match_operand:GPI 0 "register_operand" "=r")
4694         (FIXUORS:GPI
4695           (mult:GPF
4696             (match_operand:GPF 1 "register_operand" "w")
4697             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4698   "TARGET_FLOAT
4699    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4700                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4701   {
4702     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4703     char buf[64];
4704     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4705     output_asm_insn (buf, operands);
4706     return "";
4707   }
4708   [(set_attr "type" "f_cvtf2i")]
4711 ;; fma - no throw
4713 (define_insn "fma<mode>4"
4714   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4715         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4716                      (match_operand:GPF_F16 2 "register_operand" "w")
4717                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4718   "TARGET_FLOAT"
4719   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4720   [(set_attr "type" "fmac<stype>")]
4723 (define_insn "fnma<mode>4"
4724   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4725         (fma:GPF_F16
4726           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4727           (match_operand:GPF_F16 2 "register_operand" "w")
4728           (match_operand:GPF_F16 3 "register_operand" "w")))]
4729   "TARGET_FLOAT"
4730   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4731   [(set_attr "type" "fmac<stype>")]
4734 (define_insn "fms<mode>4"
4735   [(set (match_operand:GPF 0 "register_operand" "=w")
4736         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4737                  (match_operand:GPF 2 "register_operand" "w")
4738                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4739   "TARGET_FLOAT"
4740   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4741   [(set_attr "type" "fmac<s>")]
4744 (define_insn "fnms<mode>4"
4745   [(set (match_operand:GPF 0 "register_operand" "=w")
4746         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4747                  (match_operand:GPF 2 "register_operand" "w")
4748                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4749   "TARGET_FLOAT"
4750   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4751   [(set_attr "type" "fmac<s>")]
4754 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4755 (define_insn "*fnmadd<mode>4"
4756   [(set (match_operand:GPF 0 "register_operand" "=w")
4757         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4758                           (match_operand:GPF 2 "register_operand" "w")
4759                           (match_operand:GPF 3 "register_operand" "w"))))]
4760   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4761   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4762   [(set_attr "type" "fmac<s>")]
4765 ;; -------------------------------------------------------------------
4766 ;; Floating-point conversions
4767 ;; -------------------------------------------------------------------
4769 (define_insn "extendsfdf2"
4770   [(set (match_operand:DF 0 "register_operand" "=w")
4771         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4772   "TARGET_FLOAT"
4773   "fcvt\\t%d0, %s1"
4774   [(set_attr "type" "f_cvt")]
4777 (define_insn "extendhfsf2"
4778   [(set (match_operand:SF 0 "register_operand" "=w")
4779         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4780   "TARGET_FLOAT"
4781   "fcvt\\t%s0, %h1"
4782   [(set_attr "type" "f_cvt")]
4785 (define_insn "extendhfdf2"
4786   [(set (match_operand:DF 0 "register_operand" "=w")
4787         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4788   "TARGET_FLOAT"
4789   "fcvt\\t%d0, %h1"
4790   [(set_attr "type" "f_cvt")]
4793 (define_insn "truncdfsf2"
4794   [(set (match_operand:SF 0 "register_operand" "=w")
4795         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4796   "TARGET_FLOAT"
4797   "fcvt\\t%s0, %d1"
4798   [(set_attr "type" "f_cvt")]
4801 (define_insn "truncsfhf2"
4802   [(set (match_operand:HF 0 "register_operand" "=w")
4803         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4804   "TARGET_FLOAT"
4805   "fcvt\\t%h0, %s1"
4806   [(set_attr "type" "f_cvt")]
4809 (define_insn "truncdfhf2"
4810   [(set (match_operand:HF 0 "register_operand" "=w")
4811         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4812   "TARGET_FLOAT"
4813   "fcvt\\t%h0, %d1"
4814   [(set_attr "type" "f_cvt")]
4817 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4818   [(set (match_operand:GPI 0 "register_operand" "=r")
4819         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4820   "TARGET_FLOAT"
4821   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4822   [(set_attr "type" "f_cvtf2i")]
4825 (define_insn "<optab><fcvt_target><GPF:mode>2"
4826   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4827         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4828   "TARGET_FLOAT"
4829   "@
4830    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4831    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4832   [(set_attr "simd" "yes,no")
4833    (set_attr "fp" "no,yes")
4834    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4837 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4838   [(set (match_operand:GPF 0 "register_operand" "=w")
4839         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4840   "TARGET_FLOAT"
4841   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4842   [(set_attr "type" "f_cvti2f")]
4845 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4846 ;; midend will arrange for an SImode conversion to HFmode to first go
4847 ;; through DFmode, then to HFmode.  But first it will try converting
4848 ;; to DImode then down, which would match our DImode pattern below and
4849 ;; give very poor code-generation.  So, we must provide our own emulation
4850 ;; of the mid-end logic.
4852 (define_insn "aarch64_fp16_<optab><mode>hf2"
4853   [(set (match_operand:HF 0 "register_operand" "=w")
4854         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4855   "TARGET_FP_F16INST"
4856   "<su_optab>cvtf\t%h0, %<w>1"
4857   [(set_attr "type" "f_cvti2f")]
4860 (define_expand "<optab>sihf2"
4861   [(set (match_operand:HF 0 "register_operand")
4862         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4863   "TARGET_FLOAT"
4865   if (TARGET_FP_F16INST)
4866     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4867   else
4868     {
4869       rtx convert_target = gen_reg_rtx (DFmode);
4870       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4871       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4872     }
4873   DONE;
4877 ;; For DImode there is no wide enough floating-point mode that we
4878 ;; can convert through natively (TFmode would work, but requires a library
4879 ;; call).  However, we know that any value >= 65504 will be rounded
4880 ;; to infinity on conversion.  This is well within the range of SImode, so
4881 ;; we can:
4882 ;;   Saturate to SImode.
4883 ;;   Convert from that to DFmode
4884 ;;   Convert from that to HFmode (phew!).
4885 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4886 ;; we ever need to provide this pattern where the SIMD extensions are not
4887 ;; available, we would need a different approach.
4889 (define_expand "<optab>dihf2"
4890   [(set (match_operand:HF 0 "register_operand")
4891         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4892   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4894   if (TARGET_FP_F16INST)
4895     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4896   else
4897     {
4898       rtx sat_target = gen_reg_rtx (SImode);
4899       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4900       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4901     }
4903   DONE;
4907 ;; Convert between fixed-point and floating-point (scalar modes)
4909 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4910   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4911         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4912                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4913          FCVT_F2FIXED))]
4914   ""
4915   "@
4916    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4917    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4918   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4919    (set_attr "fp" "yes, *")
4920    (set_attr "simd" "*, yes")]
4923 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4924   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4925         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4926                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4927          FCVT_FIXED2F))]
4928   ""
4929   "@
4930    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4931    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4932   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4933    (set_attr "fp" "yes, *")
4934    (set_attr "simd" "*, yes")]
4937 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4938   [(set (match_operand:GPI 0 "register_operand" "=r")
4939         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4940                      (match_operand:SI 2 "immediate_operand" "i")]
4941          FCVT_F2FIXED))]
4942   "TARGET_FP_F16INST"
4943    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4944   [(set_attr "type" "f_cvtf2i")]
4947 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4948   [(set (match_operand:HF 0 "register_operand" "=w")
4949         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4950                     (match_operand:SI 2 "immediate_operand" "i")]
4951          FCVT_FIXED2F))]
4952   "TARGET_FP_F16INST"
4953   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4954   [(set_attr "type" "f_cvti2f")]
4957 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4958   [(set (match_operand:HI 0 "register_operand" "=w")
4959         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4960                     (match_operand:SI 2 "immediate_operand" "i")]
4961          FCVT_F2FIXED))]
4962   "TARGET_SIMD"
4963   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4964   [(set_attr "type" "neon_fp_to_int_s")]
4967 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4968   [(set (match_operand:HF 0 "register_operand" "=w")
4969         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4970                     (match_operand:SI 2 "immediate_operand" "i")]
4971          FCVT_FIXED2F))]
4972   "TARGET_SIMD"
4973   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4974   [(set_attr "type" "neon_int_to_fp_s")]
4977 ;; -------------------------------------------------------------------
4978 ;; Floating-point arithmetic
4979 ;; -------------------------------------------------------------------
4981 (define_insn "add<mode>3"
4982   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4983         (plus:GPF_F16
4984          (match_operand:GPF_F16 1 "register_operand" "w")
4985          (match_operand:GPF_F16 2 "register_operand" "w")))]
4986   "TARGET_FLOAT"
4987   "fadd\\t%<s>0, %<s>1, %<s>2"
4988   [(set_attr "type" "fadd<stype>")]
4991 (define_insn "sub<mode>3"
4992   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4993         (minus:GPF_F16
4994          (match_operand:GPF_F16 1 "register_operand" "w")
4995          (match_operand:GPF_F16 2 "register_operand" "w")))]
4996   "TARGET_FLOAT"
4997   "fsub\\t%<s>0, %<s>1, %<s>2"
4998   [(set_attr "type" "fadd<stype>")]
5001 (define_insn "mul<mode>3"
5002   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5003         (mult:GPF_F16
5004          (match_operand:GPF_F16 1 "register_operand" "w")
5005          (match_operand:GPF_F16 2 "register_operand" "w")))]
5006   "TARGET_FLOAT"
5007   "fmul\\t%<s>0, %<s>1, %<s>2"
5008   [(set_attr "type" "fmul<stype>")]
5011 (define_insn "*fnmul<mode>3"
5012   [(set (match_operand:GPF 0 "register_operand" "=w")
5013         (mult:GPF
5014                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
5015                  (match_operand:GPF 2 "register_operand" "w")))]
5016   "TARGET_FLOAT && !flag_rounding_math"
5017   "fnmul\\t%<s>0, %<s>1, %<s>2"
5018   [(set_attr "type" "fmul<s>")]
5021 (define_insn "*fnmul<mode>3"
5022   [(set (match_operand:GPF 0 "register_operand" "=w")
5023         (neg:GPF (mult:GPF
5024                  (match_operand:GPF 1 "register_operand" "w")
5025                  (match_operand:GPF 2 "register_operand" "w"))))]
5026   "TARGET_FLOAT"
5027   "fnmul\\t%<s>0, %<s>1, %<s>2"
5028   [(set_attr "type" "fmul<s>")]
5031 (define_expand "div<mode>3"
5032  [(set (match_operand:GPF_F16 0 "register_operand")
5033        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
5034                     (match_operand:GPF_F16 2 "register_operand")))]
5035  "TARGET_SIMD"
5037   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
5038     DONE;
5040   operands[1] = force_reg (<MODE>mode, operands[1]);
5043 (define_insn "*div<mode>3"
5044   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5045         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
5046                      (match_operand:GPF_F16 2 "register_operand" "w")))]
5047   "TARGET_FLOAT"
5048   "fdiv\\t%<s>0, %<s>1, %<s>2"
5049   [(set_attr "type" "fdiv<stype>")]
5052 (define_insn "neg<mode>2"
5053   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5054         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5055   "TARGET_FLOAT"
5056   "fneg\\t%<s>0, %<s>1"
5057   [(set_attr "type" "ffarith<stype>")]
5060 (define_expand "sqrt<mode>2"
5061   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5062         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5063   "TARGET_FLOAT"
5065   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
5066     DONE;
5069 (define_insn "*sqrt<mode>2"
5070   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5071         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5072   "TARGET_FLOAT"
5073   "fsqrt\\t%<s>0, %<s>1"
5074   [(set_attr "type" "fsqrt<stype>")]
5077 (define_insn "abs<mode>2"
5078   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5079         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5080   "TARGET_FLOAT"
5081   "fabs\\t%<s>0, %<s>1"
5082   [(set_attr "type" "ffarith<stype>")]
5085 ;; Given that smax/smin do not specify the result when either input is NaN,
5086 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5087 ;; for smin.
5089 (define_insn "smax<mode>3"
5090   [(set (match_operand:GPF 0 "register_operand" "=w")
5091         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
5092                   (match_operand:GPF 2 "register_operand" "w")))]
5093   "TARGET_FLOAT"
5094   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
5095   [(set_attr "type" "f_minmax<s>")]
5098 (define_insn "smin<mode>3"
5099   [(set (match_operand:GPF 0 "register_operand" "=w")
5100         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
5101                   (match_operand:GPF 2 "register_operand" "w")))]
5102   "TARGET_FLOAT"
5103   "fminnm\\t%<s>0, %<s>1, %<s>2"
5104   [(set_attr "type" "f_minmax<s>")]
5107 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5108 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
5109 ;; which implement the IEEE fmax ()/fmin () functions.
5110 (define_insn "<maxmin_uns><mode>3"
5111   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5112         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
5113                      (match_operand:GPF_F16 2 "register_operand" "w")]
5114                      FMAXMIN_UNS))]
5115   "TARGET_FLOAT"
5116   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5117   [(set_attr "type" "f_minmax<stype>")]
5120 (define_expand "lrint<GPF:mode><GPI:mode>2"
5121   [(match_operand:GPI 0 "register_operand")
5122    (match_operand:GPF 1 "register_operand")]
5123   "TARGET_FLOAT"
5125   rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5126   emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
5127   emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
5128   DONE;
5132 ;; For copysign (x, y), we want to generate:
5134 ;;   LDR d2, #(1 << 63)
5135 ;;   BSL v2.8b, [y], [x]
5137 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5138 ;; aarch64_simd_bsldf will select the best suited of these instructions
5139 ;; to generate based on register allocation, and knows how to partially
5140 ;; constant fold based on the values of X and Y, so expand through that.
5142 (define_expand "copysigndf3"
5143   [(match_operand:DF 0 "register_operand")
5144    (match_operand:DF 1 "register_operand")
5145    (match_operand:DF 2 "register_operand")]
5146   "TARGET_FLOAT && TARGET_SIMD"
5148   rtx mask = gen_reg_rtx (DImode);
5149   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5150   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5151                                      operands[2], operands[1]));
5152   DONE;
5156 ;; As above, but we must first get to a 64-bit value if we wish to use
5157 ;; aarch64_simd_bslv2sf.
5159 (define_expand "copysignsf3"
5160   [(match_operand:SF 0 "register_operand")
5161    (match_operand:SF 1 "register_operand")
5162    (match_operand:SF 2 "register_operand")]
5163   "TARGET_FLOAT && TARGET_SIMD"
5165   rtx v_bitmask = gen_reg_rtx (V2SImode);
5167   /* Juggle modes to get us in to a vector mode for BSL.  */
5168   rtx op1 = lowpart_subreg (DImode, operands[1], SFmode);
5169   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5170   rtx tmp = gen_reg_rtx (V2SFmode);
5171   emit_move_insn (v_bitmask,
5172                   aarch64_simd_gen_const_vector_dup (V2SImode,
5173                                                      HOST_WIDE_INT_M1U << 31));
5174   emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5175   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5176   DONE;
5180 ;; -------------------------------------------------------------------
5181 ;; Reload support
5182 ;; -------------------------------------------------------------------
5183 ;; Reload Scalar Floating point modes from constant pool.
5184 ;; The AArch64 port doesn't have __int128 constant move support.
5185 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5186  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5187        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5188   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5189  "TARGET_FLOAT"
5191    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5192    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5193    DONE;
5197 ;; Reload Vector modes from constant pool.
5198 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5199  [(set (match_operand:VALL 0 "register_operand" "=w")
5200        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5201   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5202  "TARGET_FLOAT"
5204    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5205    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5206    DONE;
5210 (define_expand "aarch64_reload_mov<mode>"
5211   [(set (match_operand:TX 0 "register_operand" "=w")
5212         (match_operand:TX 1 "register_operand" "w"))
5213    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5214   ]
5215   "TARGET_FLOAT"
5216   {
5217     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5218     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5219     gen_aarch64_movtilow_tilow (op0, op1);
5220     gen_aarch64_movdi_tihigh (operands[2], op1);
5221     gen_aarch64_movtihigh_di (op0, operands[2]);
5222     DONE;
5223   }
5226 ;; The following secondary reload helpers patterns are invoked
5227 ;; after or during reload as we don't want these patterns to start
5228 ;; kicking in during the combiner.
5230 (define_insn "aarch64_movdi_<mode>low"
5231   [(set (match_operand:DI 0 "register_operand" "=r")
5232         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5233                          (const_int 64) (const_int 0)))]
5234   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5235   "fmov\\t%x0, %d1"
5236   [(set_attr "type" "f_mrc")
5237    (set_attr "length" "4")
5238   ])
5240 (define_insn "aarch64_movdi_<mode>high"
5241   [(set (match_operand:DI 0 "register_operand" "=r")
5242         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5243                          (const_int 64) (const_int 64)))]
5244   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5245   "fmov\\t%x0, %1.d[1]"
5246   [(set_attr "type" "f_mrc")
5247    (set_attr "length" "4")
5248   ])
5250 (define_insn "aarch64_mov<mode>high_di"
5251   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5252                          (const_int 64) (const_int 64))
5253         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5254   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5255   "fmov\\t%0.d[1], %x1"
5256   [(set_attr "type" "f_mcr")
5257    (set_attr "length" "4")
5258   ])
5260 (define_insn "aarch64_mov<mode>low_di"
5261   [(set (match_operand:TX 0 "register_operand" "=w")
5262         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5263   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5264   "fmov\\t%d0, %x1"
5265   [(set_attr "type" "f_mcr")
5266    (set_attr "length" "4")
5267   ])
5269 (define_insn "aarch64_movtilow_tilow"
5270   [(set (match_operand:TI 0 "register_operand" "=w")
5271         (zero_extend:TI
5272           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5273   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5274   "fmov\\t%d0, %d1"
5275   [(set_attr "type" "fmov")
5276    (set_attr "length" "4")
5277   ])
5279 ;; There is a deliberate reason why the parameters of high and lo_sum's
5280 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5281 ;; and lo_sum's to be used with the labels defining the jump tables in
5282 ;; rodata section.
5284 (define_expand "add_losym"
5285   [(set (match_operand 0 "register_operand" "=r")
5286         (lo_sum (match_operand 1 "register_operand" "r")
5287                 (match_operand 2 "aarch64_valid_symref" "S")))]
5288   ""
5290   machine_mode mode = GET_MODE (operands[0]);
5292   emit_insn ((mode == DImode
5293               ? gen_add_losym_di
5294               : gen_add_losym_si) (operands[0],
5295                                    operands[1],
5296                                    operands[2]));
5297   DONE;
5300 (define_insn "add_losym_<mode>"
5301   [(set (match_operand:P 0 "register_operand" "=r")
5302         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5303                   (match_operand 2 "aarch64_valid_symref" "S")))]
5304   ""
5305   "add\\t%<w>0, %<w>1, :lo12:%a2"
5306   [(set_attr "type" "alu_imm")]
5309 (define_insn "ldr_got_small_<mode>"
5310   [(set (match_operand:PTR 0 "register_operand" "=r")
5311         (unspec:PTR [(mem:PTR (lo_sum:PTR
5312                               (match_operand:PTR 1 "register_operand" "r")
5313                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5314                     UNSPEC_GOTSMALLPIC))]
5315   ""
5316   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5317   [(set_attr "type" "load1")]
5320 (define_insn "ldr_got_small_sidi"
5321   [(set (match_operand:DI 0 "register_operand" "=r")
5322         (zero_extend:DI
5323          (unspec:SI [(mem:SI (lo_sum:DI
5324                              (match_operand:DI 1 "register_operand" "r")
5325                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5326                     UNSPEC_GOTSMALLPIC)))]
5327   "TARGET_ILP32"
5328   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5329   [(set_attr "type" "load1")]
5332 (define_insn "ldr_got_small_28k_<mode>"
5333   [(set (match_operand:PTR 0 "register_operand" "=r")
5334         (unspec:PTR [(mem:PTR (lo_sum:PTR
5335                               (match_operand:PTR 1 "register_operand" "r")
5336                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5337                     UNSPEC_GOTSMALLPIC28K))]
5338   ""
5339   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5340   [(set_attr "type" "load1")]
5343 (define_insn "ldr_got_small_28k_sidi"
5344   [(set (match_operand:DI 0 "register_operand" "=r")
5345         (zero_extend:DI
5346          (unspec:SI [(mem:SI (lo_sum:DI
5347                              (match_operand:DI 1 "register_operand" "r")
5348                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5349                     UNSPEC_GOTSMALLPIC28K)))]
5350   "TARGET_ILP32"
5351   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5352   [(set_attr "type" "load1")]
5355 (define_insn "ldr_got_tiny"
5356   [(set (match_operand:DI 0 "register_operand" "=r")
5357         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5358                    UNSPEC_GOTTINYPIC))]
5359   ""
5360   "ldr\\t%0, %L1"
5361   [(set_attr "type" "load1")]
5364 (define_insn "aarch64_load_tp_hard"
5365   [(set (match_operand:DI 0 "register_operand" "=r")
5366         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5367   ""
5368   "mrs\\t%0, tpidr_el0"
5369   [(set_attr "type" "mrs")]
5372 ;; The TLS ABI specifically requires that the compiler does not schedule
5373 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5374 ;; Therefore we treat the stubs as an atomic sequence.
5375 (define_expand "tlsgd_small_<mode>"
5376  [(parallel [(set (match_operand 0 "register_operand" "")
5377                   (call (mem:DI (match_dup 2)) (const_int 1)))
5378              (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5379              (clobber (reg:DI LR_REGNUM))])]
5380  ""
5382   operands[2] = aarch64_tls_get_addr ();
5385 (define_insn "*tlsgd_small_<mode>"
5386   [(set (match_operand 0 "register_operand" "")
5387         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5388    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5389    (clobber (reg:DI LR_REGNUM))
5390   ]
5391   ""
5392   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5393   [(set_attr "type" "call")
5394    (set_attr "length" "16")])
5396 (define_insn "tlsie_small_<mode>"
5397   [(set (match_operand:PTR 0 "register_operand" "=r")
5398         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5399                    UNSPEC_GOTSMALLTLS))]
5400   ""
5401   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5402   [(set_attr "type" "load1")
5403    (set_attr "length" "8")]
5406 (define_insn "tlsie_small_sidi"
5407   [(set (match_operand:DI 0 "register_operand" "=r")
5408         (zero_extend:DI
5409           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5410                       UNSPEC_GOTSMALLTLS)))]
5411   ""
5412   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5413   [(set_attr "type" "load1")
5414    (set_attr "length" "8")]
5417 (define_insn "tlsie_tiny_<mode>"
5418   [(set (match_operand:PTR 0 "register_operand" "=&r")
5419         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5420                      (match_operand:PTR 2 "register_operand" "r")]
5421                    UNSPEC_GOTTINYTLS))]
5422   ""
5423   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5424   [(set_attr "type" "multiple")
5425    (set_attr "length" "8")]
5428 (define_insn "tlsie_tiny_sidi"
5429   [(set (match_operand:DI 0 "register_operand" "=&r")
5430         (zero_extend:DI
5431           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5432                       (match_operand:DI 2 "register_operand" "r")
5433                       ]
5434                       UNSPEC_GOTTINYTLS)))]
5435   ""
5436   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5437   [(set_attr "type" "multiple")
5438    (set_attr "length" "8")]
5441 (define_insn "tlsle12_<mode>"
5442   [(set (match_operand:P 0 "register_operand" "=r")
5443         (unspec:P [(match_operand:P 1 "register_operand" "r")
5444                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5445                    UNSPEC_TLSLE12))]
5446   ""
5447   "add\\t%<w>0, %<w>1, #%L2";
5448   [(set_attr "type" "alu_sreg")
5449    (set_attr "length" "4")]
5452 (define_insn "tlsle24_<mode>"
5453   [(set (match_operand:P 0 "register_operand" "=r")
5454         (unspec:P [(match_operand:P 1 "register_operand" "r")
5455                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5456                    UNSPEC_TLSLE24))]
5457   ""
5458   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5459   [(set_attr "type" "multiple")
5460    (set_attr "length" "8")]
5463 (define_insn "tlsle32_<mode>"
5464   [(set (match_operand:P 0 "register_operand" "=r")
5465         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5466                    UNSPEC_TLSLE32))]
5467   ""
5468   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5469   [(set_attr "type" "multiple")
5470    (set_attr "length" "8")]
5473 (define_insn "tlsle48_<mode>"
5474   [(set (match_operand:P 0 "register_operand" "=r")
5475         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5476                    UNSPEC_TLSLE48))]
5477   ""
5478   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5479   [(set_attr "type" "multiple")
5480    (set_attr "length" "12")]
5483 (define_insn "tlsdesc_small_<mode>"
5484   [(set (reg:PTR R0_REGNUM)
5485         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5486                    UNSPEC_TLSDESC))
5487    (clobber (reg:DI LR_REGNUM))
5488    (clobber (reg:CC CC_REGNUM))
5489    (clobber (match_scratch:DI 1 "=r"))]
5490   "TARGET_TLS_DESC"
5491   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5492   [(set_attr "type" "call")
5493    (set_attr "length" "16")])
5495 (define_insn "stack_tie"
5496   [(set (mem:BLK (scratch))
5497         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5498                      (match_operand:DI 1 "register_operand" "rk")]
5499                     UNSPEC_PRLG_STK))]
5500   ""
5501   ""
5502   [(set_attr "length" "0")]
5505 ;; Pointer authentication patterns are always provided.  In architecture
5506 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5507 ;; This lets the user write portable software which authenticates pointers
5508 ;; when run on something which implements ARMv8.3-A, and which runs
5509 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5510 ;; implemented.
5512 ;; Signing/Authenticating R30 using SP as the salt.
5514 (define_insn "<pauth_mnem_prefix>sp"
5515   [(set (reg:DI R30_REGNUM)
5516         (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5517   ""
5518   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5521 ;; Signing/Authenticating X17 using X16 as the salt.
5523 (define_insn "<pauth_mnem_prefix>1716"
5524   [(set (reg:DI R17_REGNUM)
5525         (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5526   ""
5527   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5530 ;; Stripping the signature in R30.
5532 (define_insn "xpaclri"
5533   [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5534   ""
5535   "hint\t7 // xpaclri"
5538 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5539 ;; all of memory.  This blocks insns from being moved across this point.
5541 (define_insn "blockage"
5542   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5543   ""
5544   ""
5545   [(set_attr "length" "0")
5546    (set_attr "type" "block")]
5549 (define_insn "probe_stack_range"
5550   [(set (match_operand:DI 0 "register_operand" "=r")
5551         (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5552                              (match_operand:DI 2 "register_operand" "r")]
5553                               UNSPECV_PROBE_STACK_RANGE))]
5554   ""
5556   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5558   [(set_attr "length" "32")]
5561 ;; Named pattern for expanding thread pointer reference.
5562 (define_expand "get_thread_pointerdi"
5563   [(match_operand:DI 0 "register_operand" "=r")]
5564   ""
5566   rtx tmp = aarch64_load_tp (operands[0]);
5567   if (tmp != operands[0])
5568     emit_move_insn (operands[0], tmp);
5569   DONE;
5572 ;; Named patterns for stack smashing protection.
5573 (define_expand "stack_protect_set"
5574   [(match_operand 0 "memory_operand")
5575    (match_operand 1 "memory_operand")]
5576   ""
5578   machine_mode mode = GET_MODE (operands[0]);
5580   emit_insn ((mode == DImode
5581               ? gen_stack_protect_set_di
5582               : gen_stack_protect_set_si) (operands[0], operands[1]));
5583   DONE;
5586 (define_insn "stack_protect_set_<mode>"
5587   [(set (match_operand:PTR 0 "memory_operand" "=m")
5588         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5589          UNSPEC_SP_SET))
5590    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5591   ""
5592   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5593   [(set_attr "length" "12")
5594    (set_attr "type" "multiple")])
5596 (define_expand "stack_protect_test"
5597   [(match_operand 0 "memory_operand")
5598    (match_operand 1 "memory_operand")
5599    (match_operand 2)]
5600   ""
5602   rtx result;
5603   machine_mode mode = GET_MODE (operands[0]);
5605   result = gen_reg_rtx(mode);
5607   emit_insn ((mode == DImode
5608               ? gen_stack_protect_test_di
5609               : gen_stack_protect_test_si) (result,
5610                                             operands[0],
5611                                             operands[1]));
5613   if (mode == DImode)
5614     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5615                                     result, const0_rtx, operands[2]));
5616   else
5617     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5618                                     result, const0_rtx, operands[2]));
5619   DONE;
5622 (define_insn "stack_protect_test_<mode>"
5623   [(set (match_operand:PTR 0 "register_operand" "=r")
5624         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5625                      (match_operand:PTR 2 "memory_operand" "m")]
5626          UNSPEC_SP_TEST))
5627    (clobber (match_scratch:PTR 3 "=&r"))]
5628   ""
5629   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5630   [(set_attr "length" "12")
5631    (set_attr "type" "multiple")])
5633 ;; Write Floating-point Control Register.
5634 (define_insn "set_fpcr"
5635   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5636   ""
5637   "msr\\tfpcr, %0"
5638   [(set_attr "type" "mrs")])
5640 ;; Read Floating-point Control Register.
5641 (define_insn "get_fpcr"
5642   [(set (match_operand:SI 0 "register_operand" "=r")
5643         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5644   ""
5645   "mrs\\t%0, fpcr"
5646   [(set_attr "type" "mrs")])
5648 ;; Write Floating-point Status Register.
5649 (define_insn "set_fpsr"
5650   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5651   ""
5652   "msr\\tfpsr, %0"
5653   [(set_attr "type" "mrs")])
5655 ;; Read Floating-point Status Register.
5656 (define_insn "get_fpsr"
5657   [(set (match_operand:SI 0 "register_operand" "=r")
5658         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5659   ""
5660   "mrs\\t%0, fpsr"
5661   [(set_attr "type" "mrs")])
5664 ;; Define the subtract-one-and-jump insns so loop.c
5665 ;; knows what to generate.
5666 (define_expand "doloop_end"
5667   [(use (match_operand 0 "" ""))      ; loop pseudo
5668    (use (match_operand 1 "" ""))]     ; label
5669   "optimize > 0 && flag_modulo_sched"
5671   rtx s0;
5672   rtx bcomp;
5673   rtx loc_ref;
5674   rtx cc_reg;
5675   rtx insn;
5676   rtx cmp;
5678   /* Currently SMS relies on the do-loop pattern to recognize loops
5679      where (1) the control part consists of all insns defining and/or
5680      using a certain 'count' register and (2) the loop count can be
5681      adjusted by modifying this register prior to the loop.
5682      ??? The possible introduction of a new block to initialize the
5683      new IV can potentially affect branch optimizations.  */
5685   if (GET_MODE (operands[0]) != DImode)
5686     FAIL;
5688   s0 = operands [0];
5689   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5691   cmp = XVECEXP (PATTERN (insn), 0, 0);
5692   cc_reg = SET_DEST (cmp);
5693   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5694   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5695   emit_jump_insn (gen_rtx_SET (pc_rtx,
5696                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5697                                                      loc_ref, pc_rtx)));
5698   DONE;
5701 ;; AdvSIMD Stuff
5702 (include "aarch64-simd.md")
5704 ;; Atomic Operations
5705 (include "atomics.md")
5707 ;; ldp/stp peephole patterns
5708 (include "aarch64-ldpstp.md")